trunk/src/emu/machine/idehd.c
| r23717 | r23718 | |
| 16 | 16 | |
| 17 | 17 | #define TIME_PER_SECTOR (attotime::from_usec(100)) |
| 18 | 18 | #define TIME_PER_ROTATION (attotime::from_hz(5400/60)) |
| 19 | | #define TIME_SECURITY_ERROR (attotime::from_msec(1000)) |
| 20 | 19 | |
| 21 | 20 | #define TIME_SEEK_MULTISECTOR (attotime::from_msec(13)) |
| 22 | 21 | #define TIME_NO_SEEK_MULTISECTOR (attotime::from_nsec(16300)) |
| r23717 | r23718 | |
| 67 | 66 | TID_DELAYED_INTERRUPT, |
| 68 | 67 | TID_DELAYED_INTERRUPT_BUFFER_READY, |
| 69 | 68 | TID_RESET_CALLBACK, |
| 70 | | TID_SECURITY_ERROR_DONE, |
| 71 | 69 | TID_READ_SECTOR_DONE_CALLBACK, |
| 72 | 70 | TID_WRITE_SECTOR_DONE_CALLBACK |
| 73 | 71 | }; |
| r23717 | r23718 | |
| 387 | 385 | m_gnetreadlock = 0; |
| 388 | 386 | m_master_password_enable = (m_master_password != NULL); |
| 389 | 387 | m_user_password_enable = (m_user_password != NULL); |
| 390 | | m_error = IDE_ERROR_DEFAULT; |
| 388 | m_error = IDE_ERROR_DIAGNOSTIC_PASSED; |
| 391 | 389 | |
| 392 | 390 | m_status = IDE_STATUS_DSC; |
| 393 | | if (is_ready()) |
| 394 | | { |
| 391 | |
| 392 | if (!m_gnetreadlock) |
| 395 | 393 | m_status |= IDE_STATUS_DRDY; |
| 396 | | } |
| 397 | 394 | |
| 398 | 395 | m_cur_drive = 0; |
| 399 | 396 | |
| r23717 | r23718 | |
| 422 | 419 | reset(); |
| 423 | 420 | break; |
| 424 | 421 | |
| 425 | | case TID_SECURITY_ERROR_DONE: |
| 426 | | /* clear error state */ |
| 427 | | m_status &= ~IDE_STATUS_ERR; |
| 428 | | m_status |= IDE_STATUS_DRDY; |
| 429 | | break; |
| 430 | | |
| 431 | 422 | case TID_READ_SECTOR_DONE_CALLBACK: |
| 432 | 423 | read_sector_done(); |
| 433 | 424 | break; |
| r23717 | r23718 | |
| 504 | 495 | { |
| 505 | 496 | /* set error state */ |
| 506 | 497 | m_status |= IDE_STATUS_ERR; |
| 498 | m_error = IDE_ERROR_NONE; |
| 507 | 499 | m_status &= ~IDE_STATUS_DRDY; |
| 508 | | |
| 509 | | /* just set a timer and mark ourselves error */ |
| 510 | | timer_set(TIME_SECURITY_ERROR, TID_SECURITY_ERROR_DONE); |
| 511 | 500 | } |
| 512 | 501 | |
| 513 | 502 | |
| r23717 | r23718 | |
| 523 | 512 | /* reset the totals */ |
| 524 | 513 | m_buffer_offset = 0; |
| 525 | 514 | |
| 526 | | /* clear the buffer ready and busy flag */ |
| 527 | 515 | m_status &= ~IDE_STATUS_DRQ; |
| 528 | | m_status &= ~IDE_STATUS_BSY; |
| 529 | | m_error = IDE_ERROR_DEFAULT; |
| 530 | 516 | set_dmarq(CLEAR_LINE); |
| 531 | 517 | |
| 532 | 518 | if (m_master_password_enable || m_user_password_enable) |
| 533 | 519 | { |
| 534 | 520 | security_error(); |
| 535 | | |
| 536 | 521 | m_sector_count = 0; |
| 537 | | |
| 538 | 522 | return; |
| 539 | 523 | } |
| 540 | 524 | |
| 541 | 525 | /* if there is more data to read, keep going */ |
| 542 | 526 | if (m_sector_count > 0) |
| 543 | 527 | m_sector_count--; |
| 528 | |
| 544 | 529 | if (m_sector_count > 0) |
| 545 | 530 | read_next_sector(); |
| 546 | 531 | } |
| r23717 | r23718 | |
| 550 | 535 | { |
| 551 | 536 | int lba = lba_address(), count = 0; |
| 552 | 537 | |
| 538 | m_status &= ~IDE_STATUS_BSY; |
| 539 | |
| 553 | 540 | /* GNET readlock check */ |
| 554 | | if (m_gnetreadlock) { |
| 555 | | m_status &= ~IDE_STATUS_ERR; |
| 556 | | m_status &= ~IDE_STATUS_BSY; |
| 541 | if (m_gnetreadlock) |
| 542 | { |
| 557 | 543 | return; |
| 558 | 544 | } |
| 559 | 545 | |
| 560 | 546 | /* now do the read */ |
| 561 | 547 | count = read_sector(lba, m_buffer); |
| 562 | 548 | |
| 563 | | /* by default, mark the buffer ready and the seek complete */ |
| 564 | | if (!m_verify_only) |
| 565 | | m_status |= IDE_STATUS_DRQ; |
| 566 | | |
| 567 | | m_status |= IDE_STATUS_DSC; |
| 568 | | |
| 569 | | /* and clear the busy and error flags */ |
| 570 | | m_status &= ~IDE_STATUS_ERR; |
| 571 | | m_status &= ~IDE_STATUS_BSY; |
| 572 | | |
| 573 | 549 | /* if we succeeded, advance to the next sector and set the nice bits */ |
| 574 | 550 | if (count == 1) |
| 575 | 551 | { |
| r23717 | r23718 | |
| 578 | 554 | if (m_sector_count != 1) |
| 579 | 555 | next_sector(); |
| 580 | 556 | |
| 581 | | /* clear the error value */ |
| 582 | | m_error = IDE_ERROR_NONE; |
| 583 | | |
| 584 | 557 | /* signal an interrupt */ |
| 585 | 558 | if (!m_verify_only) |
| 586 | 559 | m_sectors_until_int--; |
| r23717 | r23718 | |
| 590 | 563 | set_irq(ASSERT_LINE); |
| 591 | 564 | } |
| 592 | 565 | |
| 593 | | /* handle DMA */ |
| 594 | | if (m_dma_active) |
| 595 | | set_dmarq(ASSERT_LINE); |
| 596 | | |
| 597 | 566 | /* if we're just verifying we can read the next sector */ |
| 598 | 567 | if (m_verify_only) |
| 568 | { |
| 599 | 569 | read_buffer_empty(); |
| 570 | } |
| 571 | else |
| 572 | { |
| 573 | m_status |= IDE_STATUS_DRQ; |
| 574 | |
| 575 | if (m_dma_active) |
| 576 | set_dmarq(ASSERT_LINE); |
| 577 | } |
| 600 | 578 | } |
| 601 | 579 | |
| 602 | 580 | /* if we got an error, we need to report it */ |
| r23717 | r23718 | |
| 669 | 647 | m_buffer_offset = 0; |
| 670 | 648 | |
| 671 | 649 | /* clear the buffer ready flag */ |
| 672 | | m_status &= ~IDE_STATUS_DRQ; |
| 673 | 650 | m_status |= IDE_STATUS_BSY; |
| 674 | 651 | |
| 675 | 652 | if (m_command == IDE_COMMAND_WRITE_MULTIPLE) |
| r23717 | r23718 | |
| 695 | 672 | |
| 696 | 673 | void ide_mass_storage_device::write_buffer_full() |
| 697 | 674 | { |
| 675 | m_status &= ~IDE_STATUS_DRQ; |
| 698 | 676 | set_dmarq(CLEAR_LINE); |
| 699 | 677 | |
| 700 | 678 | if (m_command == IDE_COMMAND_SECURITY_UNLOCK) |
| r23717 | r23718 | |
| 724 | 702 | mame_printf_debug("\n"); |
| 725 | 703 | } |
| 726 | 704 | |
| 727 | | /* clear the busy and error flags */ |
| 728 | | m_status &= ~IDE_STATUS_ERR; |
| 729 | | m_status &= ~IDE_STATUS_BSY; |
| 730 | | m_status &= ~IDE_STATUS_DRQ; |
| 731 | | |
| 732 | 705 | if (m_master_password_enable || m_user_password_enable) |
| 733 | 706 | security_error(); |
| 734 | | else |
| 735 | | m_status |= IDE_STATUS_DRDY; |
| 736 | 707 | } |
| 737 | 708 | else if (m_command == IDE_COMMAND_TAITO_GNET_UNLOCK_2) |
| 738 | 709 | { |
| r23717 | r23718 | |
| 743 | 714 | for (i=0; !bad && i<512; i++) |
| 744 | 715 | bad = ((i < 2 || i >= 7) && m_buffer[i]) || ((i >= 2 && i < 7) && m_buffer[i] != key[i-2]); |
| 745 | 716 | |
| 746 | | m_status &= ~IDE_STATUS_BSY; |
| 747 | | m_status &= ~IDE_STATUS_DRQ; |
| 748 | 717 | if (bad) |
| 718 | { |
| 749 | 719 | m_status |= IDE_STATUS_ERR; |
| 750 | | else { |
| 751 | | m_status &= ~IDE_STATUS_ERR; |
| 720 | m_error = IDE_ERROR_NONE; |
| 721 | } |
| 722 | else |
| 723 | { |
| 752 | 724 | m_gnetreadlock= 0; |
| 753 | 725 | } |
| 754 | 726 | } |
| r23717 | r23718 | |
| 763 | 735 | { |
| 764 | 736 | int lba = lba_address(), count = 0; |
| 765 | 737 | |
| 738 | m_status &= ~IDE_STATUS_BSY; |
| 739 | |
| 766 | 740 | /* now do the write */ |
| 767 | 741 | count = write_sector(lba, m_buffer); |
| 768 | 742 | |
| 769 | | /* by default, mark the buffer ready and the seek complete */ |
| 770 | | m_status |= IDE_STATUS_DRQ; |
| 771 | | m_status |= IDE_STATUS_DSC; |
| 772 | | |
| 773 | | /* and clear the busy adn error flags */ |
| 774 | | m_status &= ~IDE_STATUS_ERR; |
| 775 | | m_status &= ~IDE_STATUS_BSY; |
| 776 | | |
| 777 | 743 | /* if we succeeded, advance to the next sector and set the nice bits */ |
| 778 | 744 | if (count == 1) |
| 779 | 745 | { |
| r23717 | r23718 | |
| 782 | 748 | if (m_sector_count != 1) |
| 783 | 749 | next_sector(); |
| 784 | 750 | |
| 785 | | /* clear the error value */ |
| 786 | | m_error = IDE_ERROR_NONE; |
| 787 | | |
| 788 | 751 | /* signal an interrupt */ |
| 789 | 752 | if (--m_sectors_until_int == 0 || m_sector_count == 1) |
| 790 | 753 | { |
| r23717 | r23718 | |
| 795 | 758 | /* signal an interrupt if there's more data needed */ |
| 796 | 759 | if (m_sector_count > 0) |
| 797 | 760 | m_sector_count--; |
| 798 | | if (m_sector_count == 0) |
| 799 | | m_status &= ~IDE_STATUS_DRQ; |
| 800 | 761 | |
| 801 | | /* keep going for DMA */ |
| 802 | | if (m_dma_active && m_sector_count != 0) |
| 762 | if (m_sector_count > 0) |
| 803 | 763 | { |
| 804 | | set_dmarq(ASSERT_LINE); |
| 764 | m_status |= IDE_STATUS_DRQ; |
| 765 | |
| 766 | if (m_dma_active) |
| 767 | { |
| 768 | set_dmarq(ASSERT_LINE); |
| 769 | } |
| 805 | 770 | } |
| 806 | 771 | } |
| 807 | 772 | |
| r23717 | r23718 | |
| 833 | 798 | set_irq(CLEAR_LINE); |
| 834 | 799 | set_dmarq(CLEAR_LINE); |
| 835 | 800 | |
| 801 | m_status &= ~IDE_STATUS_ERR; |
| 802 | |
| 836 | 803 | switch (m_command) |
| 837 | 804 | { |
| 838 | 805 | case IDE_COMMAND_READ_SECTORS: |
| r23717 | r23718 | |
| 962 | 929 | |
| 963 | 930 | /* indicate everything is ready */ |
| 964 | 931 | m_status |= IDE_STATUS_DRQ; |
| 965 | | m_status |= IDE_STATUS_DSC; |
| 966 | | m_status |= IDE_STATUS_DRDY; |
| 967 | | |
| 968 | | /* and clear the busy adn error flags */ |
| 969 | | m_status &= ~IDE_STATUS_ERR; |
| 970 | 932 | m_status &= ~IDE_STATUS_BSY; |
| 971 | 933 | |
| 972 | | /* clear the error too */ |
| 973 | | m_error = IDE_ERROR_NONE; |
| 974 | | |
| 975 | 934 | /* signal an interrupt */ |
| 976 | 935 | signal_delayed_interrupt(MINIMUM_COMMAND_TIME, 1); |
| 977 | 936 | break; |
| 978 | 937 | |
| 979 | 938 | case IDE_COMMAND_DIAGNOSTIC: |
| 980 | | m_error = IDE_ERROR_DEFAULT; |
| 939 | m_error = IDE_ERROR_DIAGNOSTIC_PASSED; |
| 981 | 940 | |
| 982 | 941 | /* signal an interrupt */ |
| 983 | 942 | signal_delayed_interrupt(MINIMUM_COMMAND_TIME, 0); |
| 984 | 943 | break; |
| 985 | 944 | |
| 986 | 945 | case IDE_COMMAND_RECALIBRATE: |
| 987 | | /* clear the error too */ |
| 988 | | m_error = IDE_ERROR_NONE; |
| 989 | 946 | /* signal an interrupt */ |
| 990 | 947 | signal_delayed_interrupt(MINIMUM_COMMAND_TIME, 0); |
| 991 | 948 | break; |
| 992 | 949 | |
| 993 | 950 | case IDE_COMMAND_IDLE: |
| 994 | | /* clear the error too */ |
| 995 | | m_error = IDE_ERROR_NONE; |
| 996 | | |
| 997 | 951 | /* for timeout disabled value is 0 */ |
| 998 | 952 | m_sector_count = 0; |
| 999 | 953 | /* signal an interrupt */ |
| r23717 | r23718 | |
| 1002 | 956 | |
| 1003 | 957 | case IDE_COMMAND_SET_CONFIG: |
| 1004 | 958 | LOGPRINT(("IDE Set configuration (%d heads, %d sectors)\n", m_cur_head + 1, m_sector_count)); |
| 1005 | | m_status &= ~IDE_STATUS_ERR; |
| 1006 | | m_error = IDE_ERROR_NONE; |
| 1007 | 959 | set_geometry(m_sector_count,m_cur_head + 1); |
| 1008 | 960 | |
| 1009 | 961 | /* signal an interrupt */ |
| r23717 | r23718 | |
| 1029 | 981 | LOGPRINT(("IDE Set block count (%02X)\n", m_sector_count)); |
| 1030 | 982 | |
| 1031 | 983 | m_block_count = m_sector_count; |
| 1032 | | // judge dredd wants 'drive ready' on this command |
| 1033 | | m_status |= IDE_STATUS_DRDY; |
| 1034 | 984 | |
| 1035 | 985 | /* signal an interrupt */ |
| 1036 | 986 | set_irq(ASSERT_LINE); |
| r23717 | r23718 | |
| 1041 | 991 | |
| 1042 | 992 | m_sector_count = 1; |
| 1043 | 993 | m_status |= IDE_STATUS_DRDY; |
| 1044 | | m_status &= ~IDE_STATUS_ERR; |
| 994 | |
| 1045 | 995 | set_irq(ASSERT_LINE); |
| 1046 | 996 | break; |
| 1047 | 997 | |
| r23717 | r23718 | |
| 1068 | 1018 | { |
| 1069 | 1019 | m_gnetreadlock= 0; |
| 1070 | 1020 | } |
| 1021 | else |
| 1022 | { |
| 1023 | m_status &= ~IDE_STATUS_DRDY; |
| 1024 | } |
| 1071 | 1025 | |
| 1072 | | /* update flags */ |
| 1073 | | m_status |= IDE_STATUS_DRDY; |
| 1074 | | m_status &= ~IDE_STATUS_ERR; |
| 1075 | 1026 | set_irq(ASSERT_LINE); |
| 1076 | 1027 | break; |
| 1077 | 1028 | |
| r23717 | r23718 | |
| 1081 | 1032 | are all already set in this case so no need |
| 1082 | 1033 | so that implements actual seek |
| 1083 | 1034 | */ |
| 1084 | | /* clear the error too */ |
| 1085 | | m_error = IDE_ERROR_NONE; |
| 1086 | 1035 | |
| 1087 | 1036 | /* for timeout disabled value is 0 */ |
| 1088 | 1037 | m_sector_count = 0; |
| r23717 | r23718 | |
| 1250 | 1199 | m_last_status_timer->adjust(attotime::never); |
| 1251 | 1200 | } |
| 1252 | 1201 | |
| 1202 | if (!(m_status & IDE_STATUS_DRDY) && !m_gnetreadlock) |
| 1203 | { |
| 1204 | m_status |= IDE_STATUS_DRDY; |
| 1205 | } |
| 1206 | |
| 1253 | 1207 | set_irq(CLEAR_LINE); |
| 1254 | 1208 | } |
| 1255 | 1209 | else |
| 1256 | 1210 | { |
| 1257 | 1211 | result = 0; |
| 1258 | 1212 | } |
| 1213 | |
| 1259 | 1214 | break; |
| 1260 | 1215 | |
| 1261 | 1216 | /* log anything else */ |
| r23717 | r23718 | |
| 1354 | 1309 | |
| 1355 | 1310 | WRITE16_MEMBER( ide_mass_storage_device::write_cs0 ) |
| 1356 | 1311 | { |
| 1312 | if (!device_present()) |
| 1313 | return; |
| 1314 | |
| 1357 | 1315 | /* logit */ |
| 1358 | 1316 | if (offset != IDE_CS0_DATA_RW) |
| 1359 | 1317 | LOG(("%s:IDE cs0 write to %X = %08X, mem_mask=%d\n", machine().describe_context(), offset, data, mem_mask)); |
| r23717 | r23718 | |
| 1445 | 1403 | |
| 1446 | 1404 | WRITE16_MEMBER( ide_mass_storage_device::write_cs1 ) |
| 1447 | 1405 | { |
| 1406 | if (!device_present()) |
| 1407 | return; |
| 1408 | |
| 1448 | 1409 | /* logit */ |
| 1449 | 1410 | LOG(("%s:IDE cs1 write to %X = %08X, mem_mask=%d\n", machine().describe_context(), offset, data, mem_mask)); |
| 1450 | 1411 | |
trunk/src/emu/machine/idehd.h
| r23717 | r23718 | |
| 28 | 28 | #define IDE_STATUS_BSY (0x80) |
| 29 | 29 | |
| 30 | 30 | #define IDE_ERROR_NONE 0x00 |
| 31 | | #define IDE_ERROR_DEFAULT 0x01 |
| 31 | #define IDE_ERROR_DIAGNOSTIC_OK 0x01 |
| 32 | 32 | #define IDE_ERROR_TRACK0_NOT_FOUND 0x02 |
| 33 | 33 | #define IDE_ERROR_UNKNOWN_COMMAND 0x04 |
| 34 | 34 | #define IDE_ERROR_BAD_LOCATION 0x10 |
| 35 | 35 | #define IDE_ERROR_BAD_SECTOR 0x80 |
| 36 | 36 | |
| 37 | #define IDE_ERROR_DIAGNOSTIC_FAILED 0x00 |
| 38 | #define IDE_ERROR_DIAGNOSTIC_PASSED 0x01 |
| 39 | #define IDE_ERROR_DIAGNOSTIC_DEVICE1_FAILED 0x81 |
| 40 | |
| 37 | 41 | // ======================> ide_device_interface |
| 38 | 42 | |
| 39 | 43 | class ide_device_interface |
| r23717 | r23718 | |
| 53 | 57 | virtual DECLARE_WRITE_LINE_MEMBER(write_csel) = 0; |
| 54 | 58 | virtual DECLARE_WRITE_LINE_MEMBER(write_dasp) = 0; |
| 55 | 59 | |
| 60 | virtual bool device_present() = 0; |
| 56 | 61 | virtual UINT8 *get_features() = 0; |
| 57 | 62 | |
| 58 | 63 | UINT8 m_master_password_enable; |
| r23717 | r23718 | |
| 91 | 96 | |
| 92 | 97 | virtual int read_sector(UINT32 lba, void *buffer) = 0; |
| 93 | 98 | virtual int write_sector(UINT32 lba, const void *buffer) = 0; |
| 94 | | virtual bool is_ready() = 0; |
| 95 | 99 | virtual void read_key(UINT8 key[]) = 0; |
| 96 | 100 | |
| 97 | | bool device_selected() { return m_cur_drive == m_csel; } |
| 98 | | bool single_device() { return m_csel == 0 && m_dasp == 0; } |
| 101 | bool device_selected() { return m_csel == m_cur_drive && device_present(); } |
| 102 | bool single_device() { return m_csel == 0 && m_dasp == 0 && device_present(); } |
| 99 | 103 | |
| 100 | 104 | void set_irq(int state); |
| 101 | 105 | void set_dmarq(int state); |
| r23717 | r23718 | |
| 177 | 181 | // optional information overrides |
| 178 | 182 | virtual machine_config_constructor device_mconfig_additions() const; |
| 179 | 183 | |
| 180 | | virtual bool is_ready() { return (m_disk != NULL); } |
| 184 | virtual bool device_present() { return (m_disk != NULL); } |
| 181 | 185 | virtual void read_key(UINT8 key[]); |
| 182 | 186 | |
| 183 | 187 | chd_file *m_handle; |