trunk/src/emu/machine/idehd.c
| r23903 | r23904 | |
| 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_MULTIPLE_SECTORS (attotime::from_usec(1)) |
| 19 | 20 | |
| 20 | 21 | #define TIME_SEEK_MULTISECTOR (attotime::from_msec(13)) |
| 21 | 22 | #define TIME_NO_SEEK_MULTISECTOR (attotime::from_nsec(16300)) |
| 22 | 23 | |
| 24 | #define DIAGNOSTIC_TIME (attotime::from_msec(2)) |
| 25 | #define DETECT_DEVICE1_TIME (attotime::from_msec(2)) |
| 26 | #define DEVICE1_PDIAG_TIME (attotime::from_msec(2)) |
| 27 | |
| 23 | 28 | #define IDE_CS0_DATA_RW 0 |
| 24 | 29 | #define IDE_CS0_ERROR_R 1 |
| 25 | 30 | #define IDE_CS0_FEATURE_W 1 |
| r23903 | r23904 | |
| 63 | 68 | enum |
| 64 | 69 | { |
| 65 | 70 | TID_NULL, |
| 66 | | TID_DELAYED_INTERRUPT, |
| 67 | | TID_DELAYED_INTERRUPT_BUFFER_READY, |
| 68 | | TID_RESET_CALLBACK, |
| 69 | | TID_READ_SECTOR_DONE_CALLBACK, |
| 70 | | TID_WRITE_SECTOR_DONE_CALLBACK |
| 71 | TID_BUSY, |
| 71 | 72 | }; |
| 72 | 73 | |
| 74 | enum |
| 75 | { |
| 76 | PARAM_RESET, |
| 77 | PARAM_DETECT_DEVICE1, |
| 78 | PARAM_DIAGNOSTIC, |
| 79 | PARAM_WAIT_FOR_PDIAG, |
| 80 | PARAM_COMMAND |
| 81 | }; |
| 82 | |
| 73 | 83 | ata_mass_storage_device::ata_mass_storage_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock,const char *shortname, const char *source) |
| 74 | 84 | : device_t(mconfig, type, name, tag, owner, clock, shortname, source), |
| 75 | 85 | ata_device_interface(mconfig, *this), |
| 76 | 86 | device_slot_card_interface(mconfig, *this), |
| 77 | 87 | m_can_identify_device(0), |
| 78 | 88 | m_csel(0), |
| 79 | | m_dasp(0), |
| 89 | m_daspin(0), |
| 90 | m_daspout(0), |
| 80 | 91 | m_dmack(0), |
| 81 | 92 | m_dmarq(0), |
| 82 | 93 | m_irq(0), |
| 94 | m_pdiagin(0), |
| 95 | m_pdiagout(0), |
| 83 | 96 | m_master_password(NULL), |
| 84 | 97 | m_user_password(NULL) |
| 85 | 98 | { |
| r23903 | r23904 | |
| 118 | 131 | } |
| 119 | 132 | } |
| 120 | 133 | |
| 134 | void ata_mass_storage_device::set_dasp(int state) |
| 135 | { |
| 136 | if (m_daspout != state) |
| 137 | { |
| 138 | m_daspout = state; |
| 139 | |
| 140 | m_dasp_handler(state); |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | void ata_mass_storage_device::set_pdiag(int state) |
| 145 | { |
| 146 | if (m_pdiagout != state) |
| 147 | { |
| 148 | m_pdiagout = state; |
| 149 | |
| 150 | m_pdiag_handler(state); |
| 151 | } |
| 152 | } |
| 153 | |
| 121 | 154 | WRITE_LINE_MEMBER( ata_mass_storage_device::write_csel ) |
| 122 | 155 | { |
| 123 | 156 | m_csel = state; |
| r23903 | r23904 | |
| 125 | 158 | |
| 126 | 159 | WRITE_LINE_MEMBER( ata_mass_storage_device::write_dasp ) |
| 127 | 160 | { |
| 128 | | m_dasp = state; |
| 161 | m_daspin = state; |
| 129 | 162 | } |
| 130 | 163 | |
| 131 | 164 | WRITE_LINE_MEMBER( ata_mass_storage_device::write_dmack ) |
| r23903 | r23904 | |
| 133 | 166 | m_dmack = state; |
| 134 | 167 | } |
| 135 | 168 | |
| 169 | WRITE_LINE_MEMBER( ata_mass_storage_device::write_pdiag ) |
| 170 | { |
| 171 | m_pdiagin = state; |
| 172 | |
| 173 | if (m_pdiagin == ASSERT_LINE && m_busy_timer->param() == PARAM_WAIT_FOR_PDIAG) |
| 174 | { |
| 175 | stop_busy(); |
| 176 | finished_diagnostic(); |
| 177 | } |
| 178 | } |
| 179 | |
| 136 | 180 | /************************************* |
| 137 | 181 | * |
| 138 | 182 | * Compute the LBA address |
| r23903 | r23904 | |
| 334 | 378 | { |
| 335 | 379 | m_irq_handler.resolve_safe(); |
| 336 | 380 | m_dmarq_handler.resolve_safe(); |
| 381 | m_dasp_handler.resolve_safe(); |
| 382 | m_pdiag_handler.resolve_safe(); |
| 337 | 383 | |
| 338 | 384 | save_item(NAME(m_buffer)); |
| 339 | 385 | save_item(NAME(m_buffer_offset)); |
| r23903 | r23904 | |
| 360 | 406 | |
| 361 | 407 | /* create a timer for timing status */ |
| 362 | 408 | m_last_status_timer = timer_alloc(TID_NULL); |
| 363 | | m_reset_timer = timer_alloc(TID_RESET_CALLBACK); |
| 409 | m_busy_timer = timer_alloc(TID_BUSY); |
| 364 | 410 | } |
| 365 | 411 | |
| 366 | 412 | void ata_mass_storage_device::device_reset() |
| 367 | 413 | { |
| 414 | /* reset the drive state */ |
| 415 | set_dasp(CLEAR_LINE); |
| 416 | set_dmarq(CLEAR_LINE); |
| 417 | set_irq(CLEAR_LINE); |
| 418 | set_pdiag(CLEAR_LINE); |
| 419 | |
| 420 | m_status = 0; |
| 421 | m_device_control = 0; |
| 422 | m_resetting = true; |
| 423 | |
| 424 | if (m_csel == 0) |
| 425 | { |
| 426 | start_busy(DETECT_DEVICE1_TIME, PARAM_DETECT_DEVICE1); |
| 427 | } |
| 428 | else |
| 429 | { |
| 430 | set_dasp(ASSERT_LINE); |
| 431 | soft_reset(); |
| 432 | } |
| 433 | } |
| 434 | |
| 435 | void ata_mass_storage_device::soft_reset() |
| 436 | { |
| 368 | 437 | m_buffer_offset = 0; |
| 369 | 438 | m_master_password_enable = (m_master_password != NULL); |
| 370 | 439 | m_user_password_enable = (m_user_password != NULL); |
| r23903 | r23904 | |
| 376 | 445 | m_status |= IDE_STATUS_DRDY; |
| 377 | 446 | } |
| 378 | 447 | |
| 448 | start_busy(DIAGNOSTIC_TIME, PARAM_DIAGNOSTIC); |
| 449 | } |
| 450 | |
| 451 | void ata_mass_storage_device::perform_diagnostic() |
| 452 | { |
| 379 | 453 | if (m_can_identify_device) |
| 454 | { |
| 380 | 455 | m_error = IDE_ERROR_DIAGNOSTIC_PASSED; |
| 456 | |
| 457 | if (m_csel == 1) |
| 458 | set_pdiag(ASSERT_LINE); |
| 459 | } |
| 381 | 460 | else |
| 382 | 461 | m_error = IDE_ERROR_DIAGNOSTIC_FAILED; |
| 383 | 462 | |
| 463 | if (m_csel == 0 && !m_single_device && m_pdiagin == CLEAR_LINE) |
| 464 | start_busy(DEVICE1_PDIAG_TIME, PARAM_WAIT_FOR_PDIAG); |
| 465 | else |
| 466 | finished_diagnostic(); |
| 467 | } |
| 468 | |
| 469 | void ata_mass_storage_device::finished_diagnostic() |
| 470 | { |
| 384 | 471 | m_sector_count = 1; |
| 385 | 472 | m_sector_number = 1; |
| 386 | 473 | m_cylinder_low = 0; |
| 387 | 474 | m_cylinder_high = 0; |
| 388 | 475 | m_device_head = 0; |
| 389 | 476 | |
| 390 | | /* reset the drive state */ |
| 391 | | set_irq(CLEAR_LINE); |
| 392 | | set_dmarq(CLEAR_LINE); |
| 477 | m_resetting = false; |
| 393 | 478 | } |
| 394 | 479 | |
| 480 | |
| 481 | void ata_mass_storage_device::start_busy(attotime time, int param) |
| 482 | { |
| 483 | m_status |= IDE_STATUS_BSY; |
| 484 | m_busy_timer->adjust(time, param); |
| 485 | } |
| 486 | |
| 487 | void ata_mass_storage_device::stop_busy() |
| 488 | { |
| 489 | m_status &= ~IDE_STATUS_BSY; |
| 490 | m_busy_timer->adjust(attotime::never); |
| 491 | } |
| 492 | |
| 395 | 493 | void ata_mass_storage_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| 396 | 494 | { |
| 397 | 495 | switch(id) |
| 398 | 496 | { |
| 399 | | case TID_DELAYED_INTERRUPT: |
| 497 | case TID_BUSY: |
| 400 | 498 | m_status &= ~IDE_STATUS_BSY; |
| 401 | 499 | |
| 402 | | set_irq(ASSERT_LINE); |
| 500 | finished_busy(param); |
| 403 | 501 | break; |
| 502 | } |
| 503 | } |
| 404 | 504 | |
| 405 | | case TID_DELAYED_INTERRUPT_BUFFER_READY: |
| 406 | | m_status &= ~IDE_STATUS_BSY; |
| 407 | | m_status |= IDE_STATUS_DRQ; |
| 408 | | |
| 409 | | set_irq(ASSERT_LINE); |
| 505 | void ata_mass_storage_device::finished_busy(int param) |
| 506 | { |
| 507 | switch (param) |
| 508 | { |
| 509 | case PARAM_DETECT_DEVICE1: |
| 510 | m_single_device = (m_daspin == CLEAR_LINE); |
| 511 | soft_reset(); |
| 410 | 512 | break; |
| 411 | 513 | |
| 412 | | case TID_RESET_CALLBACK: |
| 413 | | reset(); |
| 514 | case PARAM_DIAGNOSTIC: |
| 515 | perform_diagnostic(); |
| 414 | 516 | break; |
| 415 | 517 | |
| 416 | | case TID_READ_SECTOR_DONE_CALLBACK: |
| 417 | | read_sector_done(); |
| 518 | case PARAM_WAIT_FOR_PDIAG: |
| 519 | m_error |= 0x80; |
| 520 | finished_diagnostic(); |
| 418 | 521 | break; |
| 419 | 522 | |
| 420 | | case TID_WRITE_SECTOR_DONE_CALLBACK: |
| 421 | | write_sector_done(); |
| 422 | | break; |
| 523 | case PARAM_COMMAND: |
| 524 | switch (m_command) |
| 525 | { |
| 526 | case IDE_COMMAND_DIAGNOSTIC: |
| 527 | perform_diagnostic(); |
| 528 | |
| 529 | if (m_csel == 0) |
| 530 | set_irq(ASSERT_LINE); |
| 531 | break; |
| 532 | |
| 533 | case IDE_COMMAND_IDENTIFY_DEVICE: |
| 534 | if (m_can_identify_device) |
| 535 | { |
| 536 | memcpy(m_buffer, m_identify_device, sizeof(m_buffer)); |
| 537 | m_status |= IDE_STATUS_DRQ; |
| 538 | } |
| 539 | else |
| 540 | { |
| 541 | m_status |= IDE_STATUS_ERR; |
| 542 | m_error = IDE_ERROR_NONE; |
| 543 | } |
| 544 | |
| 545 | set_irq(ASSERT_LINE); |
| 546 | break; |
| 547 | |
| 548 | case IDE_COMMAND_SET_CONFIG: |
| 549 | set_geometry(m_sector_count,(m_device_head & IDE_DEVICE_HEAD_HS) + 1); |
| 550 | set_irq(ASSERT_LINE); |
| 551 | break; |
| 552 | |
| 553 | case IDE_COMMAND_READ_SECTORS: |
| 554 | case IDE_COMMAND_READ_SECTORS_NORETRY: |
| 555 | case IDE_COMMAND_READ_MULTIPLE: |
| 556 | case IDE_COMMAND_VERIFY_SECTORS: |
| 557 | case IDE_COMMAND_VERIFY_SECTORS_NORETRY: |
| 558 | case IDE_COMMAND_READ_DMA: |
| 559 | read_sector_done(); |
| 560 | break; |
| 561 | |
| 562 | case IDE_COMMAND_WRITE_SECTORS: |
| 563 | case IDE_COMMAND_WRITE_SECTORS_NORETRY: |
| 564 | case IDE_COMMAND_WRITE_MULTIPLE: |
| 565 | case IDE_COMMAND_WRITE_DMA: |
| 566 | write_sector_done(); |
| 567 | break; |
| 568 | |
| 569 | case IDE_COMMAND_RECALIBRATE: |
| 570 | set_irq(ASSERT_LINE); |
| 571 | break; |
| 572 | |
| 573 | case IDE_COMMAND_SET_FEATURES: |
| 574 | set_irq(ASSERT_LINE); |
| 575 | break; |
| 576 | |
| 577 | default: |
| 578 | logerror( "finished_busy(%d) unhandled command %02x\n", param, m_command ); |
| 579 | break; |
| 580 | } |
| 423 | 581 | } |
| 424 | 582 | } |
| 425 | 583 | |
| r23903 | r23904 | |
| 539 | 697 | { |
| 540 | 698 | int lba = lba_address(), count = 0; |
| 541 | 699 | |
| 542 | | m_status &= ~IDE_STATUS_BSY; |
| 700 | set_dasp(CLEAR_LINE); |
| 543 | 701 | |
| 544 | 702 | /* now do the read */ |
| 545 | 703 | count = read_sector(lba, m_buffer); |
| r23903 | r23904 | |
| 589 | 747 | |
| 590 | 748 | void ata_mass_storage_device::read_first_sector() |
| 591 | 749 | { |
| 592 | | /* mark ourselves busy */ |
| 593 | | m_status |= IDE_STATUS_BSY; |
| 750 | set_dasp(ASSERT_LINE); |
| 594 | 751 | |
| 595 | 752 | /* just set a timer */ |
| 596 | 753 | if (m_command == IDE_COMMAND_READ_MULTIPLE) |
| r23903 | r23904 | |
| 599 | 756 | attotime seek_time; |
| 600 | 757 | |
| 601 | 758 | if (new_lba == m_cur_lba || new_lba == m_cur_lba + 1) |
| 602 | | seek_time = TIME_NO_SEEK_MULTISECTOR; |
| 759 | start_busy(TIME_NO_SEEK_MULTISECTOR, PARAM_COMMAND); |
| 603 | 760 | else |
| 604 | | seek_time = TIME_SEEK_MULTISECTOR; |
| 761 | start_busy(TIME_SEEK_MULTISECTOR, PARAM_COMMAND); |
| 605 | 762 | |
| 606 | 763 | m_cur_lba = new_lba; |
| 607 | | timer_set(seek_time, TID_READ_SECTOR_DONE_CALLBACK); |
| 608 | 764 | } |
| 609 | 765 | else |
| 610 | | timer_set(TIME_PER_SECTOR, TID_READ_SECTOR_DONE_CALLBACK); |
| 766 | start_busy(TIME_PER_SECTOR, PARAM_COMMAND); |
| 611 | 767 | } |
| 612 | 768 | |
| 613 | 769 | |
| 614 | 770 | void ata_mass_storage_device::read_next_sector() |
| 615 | 771 | { |
| 616 | | /* mark ourselves busy */ |
| 617 | | m_status |= IDE_STATUS_BSY; |
| 772 | set_dasp(ASSERT_LINE); |
| 618 | 773 | |
| 619 | 774 | if (m_command == IDE_COMMAND_READ_MULTIPLE) |
| 620 | 775 | { |
| r23903 | r23904 | |
| 622 | 777 | /* make ready now */ |
| 623 | 778 | read_sector_done(); |
| 624 | 779 | else |
| 625 | | /* just set a timer */ |
| 626 | | timer_set(attotime::from_usec(1), TID_READ_SECTOR_DONE_CALLBACK); |
| 780 | start_busy(TIME_MULTIPLE_SECTORS, PARAM_COMMAND); |
| 627 | 781 | } |
| 628 | 782 | else |
| 629 | | /* just set a timer */ |
| 630 | | timer_set(TIME_PER_SECTOR, TID_READ_SECTOR_DONE_CALLBACK); |
| 783 | start_busy(TIME_PER_SECTOR, PARAM_COMMAND); |
| 631 | 784 | } |
| 632 | 785 | |
| 633 | 786 | |
| r23903 | r23904 | |
| 643 | 796 | /* reset the totals */ |
| 644 | 797 | m_buffer_offset = 0; |
| 645 | 798 | |
| 646 | | /* clear the buffer ready flag */ |
| 647 | | m_status |= IDE_STATUS_BSY; |
| 799 | set_dasp(ASSERT_LINE); |
| 648 | 800 | |
| 649 | 801 | if (m_command == IDE_COMMAND_WRITE_MULTIPLE) |
| 650 | 802 | { |
| r23903 | r23904 | |
| 656 | 808 | else |
| 657 | 809 | { |
| 658 | 810 | /* set a timer to do the write */ |
| 659 | | timer_set(TIME_PER_SECTOR, TID_WRITE_SECTOR_DONE_CALLBACK); |
| 811 | start_busy(TIME_PER_SECTOR, PARAM_COMMAND); |
| 660 | 812 | } |
| 661 | 813 | } |
| 662 | 814 | else |
| 663 | 815 | { |
| 664 | 816 | /* set a timer to do the write */ |
| 665 | | timer_set(TIME_PER_SECTOR, TID_WRITE_SECTOR_DONE_CALLBACK); |
| 817 | start_busy(TIME_PER_SECTOR, PARAM_COMMAND); |
| 666 | 818 | } |
| 667 | 819 | } |
| 668 | 820 | |
| r23903 | r23904 | |
| 718 | 870 | { |
| 719 | 871 | int lba = lba_address(), count = 0; |
| 720 | 872 | |
| 721 | | m_status &= ~IDE_STATUS_BSY; |
| 873 | set_dasp(CLEAR_LINE); |
| 722 | 874 | |
| 723 | 875 | /* now do the write */ |
| 724 | 876 | count = write_sector(lba, m_buffer); |
| r23903 | r23904 | |
| 867 | 1019 | case IDE_COMMAND_IDENTIFY_DEVICE: |
| 868 | 1020 | LOGPRINT(("IDE Identify device\n")); |
| 869 | 1021 | |
| 870 | | m_status |= IDE_STATUS_BSY; |
| 871 | | if (m_can_identify_device) |
| 872 | | { |
| 873 | | memcpy(m_buffer, m_identify_device, sizeof(m_buffer)); |
| 874 | | |
| 875 | | timer_set(MINIMUM_COMMAND_TIME, TID_DELAYED_INTERRUPT_BUFFER_READY); |
| 876 | | } |
| 877 | | else |
| 878 | | { |
| 879 | | m_status |= IDE_STATUS_ERR; |
| 880 | | m_error = IDE_ERROR_NONE; |
| 881 | | timer_set(MINIMUM_COMMAND_TIME, TID_DELAYED_INTERRUPT); |
| 882 | | } |
| 1022 | start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); |
| 883 | 1023 | return true; |
| 884 | 1024 | |
| 885 | 1025 | case IDE_COMMAND_DIAGNOSTIC: |
| 886 | | if (m_can_identify_device) |
| 887 | | m_error = IDE_ERROR_DIAGNOSTIC_PASSED; |
| 888 | | else |
| 889 | | m_error = IDE_ERROR_DIAGNOSTIC_FAILED; |
| 890 | | |
| 891 | | m_status |= IDE_STATUS_BSY; |
| 892 | | timer_set(MINIMUM_COMMAND_TIME, TID_DELAYED_INTERRUPT); |
| 1026 | start_busy(DIAGNOSTIC_TIME, PARAM_COMMAND); |
| 893 | 1027 | return true; |
| 894 | 1028 | |
| 895 | 1029 | case IDE_COMMAND_RECALIBRATE: |
| 896 | | m_status |= IDE_STATUS_BSY; |
| 897 | | timer_set(MINIMUM_COMMAND_TIME, TID_DELAYED_INTERRUPT); |
| 1030 | start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); |
| 898 | 1031 | return true; |
| 899 | 1032 | |
| 900 | 1033 | case IDE_COMMAND_IDLE: |
| r23903 | r23904 | |
| 904 | 1037 | |
| 905 | 1038 | case IDE_COMMAND_SET_CONFIG: |
| 906 | 1039 | LOGPRINT(("IDE Set configuration (%d heads, %d sectors)\n", (m_device_head & IDE_DEVICE_HEAD_HS) + 1, m_sector_count)); |
| 907 | | set_geometry(m_sector_count,(m_device_head & IDE_DEVICE_HEAD_HS) + 1); |
| 908 | 1040 | |
| 909 | | m_status |= IDE_STATUS_BSY; |
| 910 | | timer_set(MINIMUM_COMMAND_TIME, TID_DELAYED_INTERRUPT); |
| 1041 | start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); |
| 911 | 1042 | return true; |
| 912 | 1043 | |
| 913 | 1044 | case IDE_COMMAND_SET_MAX: |
| r23903 | r23904 | |
| 920 | 1051 | case IDE_COMMAND_SET_FEATURES: |
| 921 | 1052 | LOGPRINT(("IDE Set features (%02X %02X %02X %02X %02X)\n", m_feature, m_sector_count & 0xff, m_sector_number, m_cylinder_low, m_cylinder_high)); |
| 922 | 1053 | |
| 923 | | m_status |= IDE_STATUS_BSY; |
| 924 | | timer_set(MINIMUM_COMMAND_TIME, TID_DELAYED_INTERRUPT); |
| 1054 | start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); |
| 925 | 1055 | return true; |
| 926 | 1056 | |
| 927 | 1057 | case IDE_COMMAND_SET_BLOCK_COUNT: |
| r23903 | r23904 | |
| 989 | 1119 | |
| 990 | 1120 | UINT16 result = 0xffff; |
| 991 | 1121 | |
| 992 | | if (device_selected() || single_device()) |
| 1122 | if (device_selected() || m_single_device) |
| 993 | 1123 | { |
| 994 | 1124 | if (m_dmack) |
| 995 | 1125 | { |
| r23903 | r23904 | |
| 997 | 1127 | } |
| 998 | 1128 | else if ((m_status & IDE_STATUS_BSY) && offset != IDE_CS0_STATUS_R) |
| 999 | 1129 | { |
| 1130 | // ATA5 spec says status reads should also go through here, but this breaks Primal Rage 2. |
| 1131 | // Real hardware might work due to read ahead in the vt83c461. |
| 1000 | 1132 | if (device_selected()) |
| 1001 | 1133 | { |
| 1002 | 1134 | switch (offset) |
| r23903 | r23904 | |
| 1093 | 1225 | } |
| 1094 | 1226 | |
| 1095 | 1227 | if (!(m_status & IDE_STATUS_DRDY) && is_ready()) |
| 1096 | | { |
| 1097 | 1228 | m_status |= IDE_STATUS_DRDY; |
| 1098 | | } |
| 1099 | 1229 | |
| 1100 | 1230 | set_irq(CLEAR_LINE); |
| 1101 | 1231 | } |
| r23903 | r23904 | |
| 1125 | 1255 | |
| 1126 | 1256 | UINT16 result = 0xffff; |
| 1127 | 1257 | |
| 1128 | | if (device_selected() || single_device()) |
| 1258 | if (device_selected() || m_single_device) |
| 1129 | 1259 | { |
| 1130 | 1260 | if (m_dmack) |
| 1131 | 1261 | { |
| r23903 | r23904 | |
| 1212 | 1342 | } |
| 1213 | 1343 | else if ((m_status & IDE_STATUS_BSY) && offset != IDE_CS0_COMMAND_W) |
| 1214 | 1344 | { |
| 1215 | | logerror( "%s: dev %d write_cs0 %04x %04x %04x ignored (BSY)\n", machine().describe_context(), dev(), offset, data, mem_mask ); |
| 1345 | logerror( "%s: dev %d write_cs0 %04x %04x %04x ignored (BSY) command %02x\n", machine().describe_context(), dev(), offset, data, mem_mask, m_command ); |
| 1216 | 1346 | } |
| 1217 | 1347 | else if ((m_status & IDE_STATUS_DRQ) && offset != IDE_CS0_DATA_RW && offset != IDE_CS0_COMMAND_W) |
| 1218 | 1348 | { |
| r23903 | r23904 | |
| 1284 | 1414 | |
| 1285 | 1415 | /* command */ |
| 1286 | 1416 | case IDE_CS0_COMMAND_W: |
| 1287 | | m_command = data; |
| 1417 | // Packet devices can accept DEVICE RESET when BSY or DRQ is set. |
| 1418 | if (m_status & IDE_STATUS_BSY) |
| 1419 | { |
| 1420 | logerror( "%s: dev %d write_cs0 %04x %04x %04x ignored (BSY) command %02x\n", machine().describe_context(), dev(), offset, data, mem_mask, m_command ); |
| 1421 | } |
| 1422 | else if (m_status & IDE_STATUS_DRQ) |
| 1423 | { |
| 1424 | logerror( "%s: dev %d write_cs0 %04x %04x %04x ignored (DRQ) command %02x\n", machine().describe_context(), dev(), offset, data, mem_mask, m_command ); |
| 1425 | } |
| 1426 | else if (device_selected() || m_command == IDE_COMMAND_DIAGNOSTIC) |
| 1427 | { |
| 1428 | m_command = data; |
| 1288 | 1429 | |
| 1289 | | if (device_selected() || m_command == IDE_COMMAND_DIAGNOSTIC) |
| 1290 | | { |
| 1291 | 1430 | /* implicitly clear interrupts & dmarq here */ |
| 1292 | 1431 | set_irq(CLEAR_LINE); |
| 1293 | 1432 | set_dmarq(CLEAR_LINE); |
| r23903 | r23904 | |
| 1295 | 1434 | m_buffer_offset = 0; |
| 1296 | 1435 | m_sectors_until_int = 0; |
| 1297 | 1436 | |
| 1298 | | m_status &= ~IDE_STATUS_BSY; |
| 1437 | set_dasp(CLEAR_LINE); |
| 1299 | 1438 | m_status &= ~IDE_STATUS_DRQ; |
| 1300 | 1439 | m_status &= ~IDE_STATUS_ERR; |
| 1301 | 1440 | |
| r23903 | r23904 | |
| 1344 | 1483 | { |
| 1345 | 1484 | if (m_device_control & IDE_DEVICE_CONTROL_SRST) |
| 1346 | 1485 | { |
| 1347 | | m_status |= IDE_STATUS_BSY; |
| 1348 | | set_irq(CLEAR_LINE); |
| 1349 | | m_reset_timer->adjust(attotime::from_msec(5)); |
| 1486 | if (m_resetting) |
| 1487 | { |
| 1488 | logerror( "%s: dev %d write_cs1 %04x %04x %04x ignored (RESET)\n", machine().describe_context(), dev(), offset, data, mem_mask ); |
| 1489 | } |
| 1490 | else |
| 1491 | { |
| 1492 | set_dasp(CLEAR_LINE); |
| 1493 | set_dmarq(CLEAR_LINE); |
| 1494 | set_irq(CLEAR_LINE); |
| 1495 | set_pdiag(CLEAR_LINE); |
| 1496 | |
| 1497 | start_busy(attotime::never, PARAM_RESET); |
| 1498 | } |
| 1350 | 1499 | } |
| 1500 | else if (m_busy_timer->param() == PARAM_RESET) |
| 1501 | { |
| 1502 | soft_reset(); |
| 1503 | } |
| 1351 | 1504 | } |
| 1352 | 1505 | break; |
| 1353 | 1506 | |
trunk/src/emu/machine/ataintf.c
| r23903 | r23904 | |
| 14 | 14 | #include "debugger.h" |
| 15 | 15 | #include "idehd.h" |
| 16 | 16 | |
| 17 | | /*************************************************************************** |
| 18 | | DEBUGGING |
| 19 | | ***************************************************************************/ |
| 20 | | |
| 21 | | #define VERBOSE 0 |
| 22 | | |
| 23 | | #define LOG(x) do { if (VERBOSE) logerror x; } while (0) |
| 24 | | |
| 25 | 17 | void ata_interface_device::set_irq(int state) |
| 26 | 18 | { |
| 27 | 19 | // printf( "irq %d\n", state ); |
| 28 | 20 | |
| 29 | | if (state == ASSERT_LINE) |
| 30 | | LOG(("ATA interrupt assert\n")); |
| 31 | | else |
| 32 | | LOG(("ATA interrupt clear\n")); |
| 33 | | |
| 34 | | /* signal an interrupt */ |
| 35 | 21 | m_irq_handler(state); |
| 36 | 22 | } |
| 37 | 23 | |
| r23903 | r23904 | |
| 42 | 28 | m_dmarq_handler(state); |
| 43 | 29 | } |
| 44 | 30 | |
| 31 | void ata_interface_device::set_dasp(int state) |
| 32 | { |
| 33 | // printf( "dasp %d\n", state ); |
| 34 | |
| 35 | m_dasp_handler(state); |
| 36 | } |
| 37 | |
| 45 | 38 | WRITE_LINE_MEMBER( ata_interface_device::irq0_write_line ) |
| 46 | 39 | { |
| 47 | 40 | if (m_irq[0] != state) |
| r23903 | r23904 | |
| 62 | 55 | } |
| 63 | 56 | } |
| 64 | 57 | |
| 58 | WRITE_LINE_MEMBER( ata_interface_device::dasp0_write_line ) |
| 59 | { |
| 60 | if (m_dasp[0] != state) |
| 61 | { |
| 62 | m_dasp[0] = state; |
| 63 | |
| 64 | set_dasp(m_dasp[0] == ASSERT_LINE || m_dasp[1] == ASSERT_LINE); |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | WRITE_LINE_MEMBER( ata_interface_device::dasp1_write_line ) |
| 69 | { |
| 70 | if (m_dasp[1] != state) |
| 71 | { |
| 72 | m_dasp[1] = state; |
| 73 | |
| 74 | ata_device_interface *dev = m_slot[0]->dev(); |
| 75 | if (dev != NULL) |
| 76 | dev->write_dasp(state); |
| 77 | |
| 78 | set_dasp(m_dasp[0] == ASSERT_LINE || m_dasp[1] == ASSERT_LINE); |
| 79 | } |
| 80 | } |
| 81 | |
| 65 | 82 | WRITE_LINE_MEMBER( ata_interface_device::dmarq0_write_line ) |
| 66 | 83 | { |
| 67 | 84 | if (m_dmarq[0] != state) |
| r23903 | r23904 | |
| 82 | 99 | } |
| 83 | 100 | } |
| 84 | 101 | |
| 102 | WRITE_LINE_MEMBER( ata_interface_device::pdiag0_write_line ) |
| 103 | { |
| 104 | m_pdiag[0] = state; |
| 105 | } |
| 85 | 106 | |
| 107 | WRITE_LINE_MEMBER( ata_interface_device::pdiag1_write_line ) |
| 108 | { |
| 109 | if (m_pdiag[1] != state) |
| 110 | { |
| 111 | m_pdiag[1] = state; |
| 112 | |
| 113 | ata_device_interface *dev = m_slot[0]->dev(); |
| 114 | if (dev != NULL) |
| 115 | dev->write_pdiag(state); |
| 116 | } |
| 117 | } |
| 118 | |
| 86 | 119 | /************************************* |
| 87 | 120 | * |
| 88 | 121 | * ATA interface read |
| r23903 | r23904 | |
| 174 | 207 | ata_interface_device::ata_interface_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : |
| 175 | 208 | device_t(mconfig, type, name, tag, owner, clock, shortname, source), |
| 176 | 209 | m_irq_handler(*this), |
| 177 | | m_dmarq_handler(*this) |
| 178 | | { |
| 210 | m_dmarq_handler(*this), |
| 211 | m_dasp_handler(*this){ |
| 179 | 212 | } |
| 180 | 213 | |
| 181 | 214 | |
| r23903 | r23904 | |
| 184 | 217 | ata_interface_device::ata_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 185 | 218 | device_t(mconfig, ATA_INTERFACE, "ATA Interface", tag, owner, clock, "ata_interface", __FILE__), |
| 186 | 219 | m_irq_handler(*this), |
| 187 | | m_dmarq_handler(*this) |
| 220 | m_dmarq_handler(*this), |
| 221 | m_dasp_handler(*this) |
| 188 | 222 | { |
| 189 | 223 | } |
| 190 | 224 | |
| r23903 | r23904 | |
| 196 | 230 | { |
| 197 | 231 | m_irq_handler.resolve_safe(); |
| 198 | 232 | m_dmarq_handler.resolve_safe(); |
| 233 | m_dasp_handler.resolve_safe(); |
| 199 | 234 | |
| 200 | 235 | /* set MAME harddisk handle */ |
| 201 | 236 | m_slot[0] = subdevice<ata_slot_device>("0"); |
| r23903 | r23904 | |
| 205 | 240 | { |
| 206 | 241 | m_irq[i] = 0; |
| 207 | 242 | m_dmarq[i] = 0; |
| 243 | m_dasp[i] = 0; |
| 244 | m_pdiag[i] = 0; |
| 208 | 245 | |
| 209 | 246 | ata_device_interface *dev = m_slot[i]->dev(); |
| 210 | 247 | if (dev != NULL) |
| r23903 | r23904 | |
| 213 | 250 | { |
| 214 | 251 | dev->m_irq_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, irq0_write_line)); |
| 215 | 252 | dev->m_dmarq_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, dmarq0_write_line)); |
| 253 | dev->m_dasp_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, dasp0_write_line)); |
| 254 | dev->m_pdiag_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, pdiag0_write_line)); |
| 216 | 255 | } |
| 217 | 256 | else |
| 218 | 257 | { |
| 219 | 258 | dev->m_irq_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, irq1_write_line)); |
| 220 | 259 | dev->m_dmarq_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, dmarq1_write_line)); |
| 260 | dev->m_dasp_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, dasp1_write_line)); |
| 261 | dev->m_pdiag_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, pdiag1_write_line)); |
| 221 | 262 | } |
| 222 | 263 | |
| 223 | 264 | dev->write_csel(i); |
| 224 | | dev->write_dasp(m_slot[1]->dev() != NULL); |
| 225 | 265 | } |
| 226 | 266 | } |
| 227 | 267 | } |
| 228 | 268 | |
| 229 | | //------------------------------------------------- |
| 230 | | // device_reset - device-specific reset |
| 231 | | //------------------------------------------------- |
| 232 | | |
| 233 | | void ata_interface_device::device_reset() |
| 234 | | { |
| 235 | | LOG(("ATA interface reset\n")); |
| 236 | | } |
| 237 | | |
| 238 | | |
| 239 | | |
| 240 | 269 | //************************************************************************** |
| 241 | 270 | // ATA SLOT DEVICE |
| 242 | 271 | //************************************************************************** |