From 7c27ec1308628b3f8037a7d7e1bc388c0c9dd2da Mon Sep 17 00:00:00 2001 From: smf- Date: Mon, 24 Jun 2013 10:24:14 +0000 Subject: [PATCH] Uses one timer instead of anonymous timers, so that resetting the device will stop any outstanding work. BSY is always set when waiting for the busy timer to fire. Implemented DASP & PDIAG functionality, device 1 is detected during reset & if device 1 fails diagnostic then device 0 sets bit 7 of it's diagnostic result. Ide cards now default to 1 hard disk, otherwise device 1 without a chd will cause device 0 to report a controller error (AMIBIOS for example doesn't allow booting from device 0 if device 1 fails). Timing of DASP & PDIAG is set very short because of lack of wait states when accessing ATA bus. Improved SRST functionality, which has meant viper needed to be changed to trigger a hard reset instead of a soft reset. Writes to the command register are now ignored with BSY or DRQ is set (packet devices can accept the DEVICE RESET command but they are not supported yet). [smf] --- src/emu/machine/atadev.c | 4 +- src/emu/machine/atadev.h | 3 + src/emu/machine/ataintf.c | 87 ++++++---- src/emu/machine/ataintf.h | 14 +- src/emu/machine/idehd.c | 319 +++++++++++++++++++++++++--------- src/emu/machine/idehd.h | 20 ++- src/mame/drivers/viper.c | 3 +- src/mess/machine/a2cffa.c | 2 +- src/mess/machine/a2vulcan.c | 2 +- src/mess/machine/a2zipdrive.c | 2 +- src/mess/machine/c64_ide64.c | 2 +- src/mess/machine/isa_ide.c | 2 +- src/mess/machine/isa_ide8.c | 2 +- src/mess/machine/kc_d004.c | 2 +- 14 files changed, 337 insertions(+), 127 deletions(-) diff --git a/src/emu/machine/atadev.c b/src/emu/machine/atadev.c index 73e2a63f61e..caad25745f4 100644 --- a/src/emu/machine/atadev.c +++ b/src/emu/machine/atadev.c @@ -12,6 +12,8 @@ ata_device_interface::ata_device_interface(const machine_config &mconfig, device_t &device) : m_irq_handler(device), - m_dmarq_handler(device) + m_dmarq_handler(device), + m_dasp_handler(device), + m_pdiag_handler(device) { } diff --git a/src/emu/machine/atadev.h b/src/emu/machine/atadev.h index bf5a7c92423..dd24b8239aa 100644 --- a/src/emu/machine/atadev.h +++ b/src/emu/machine/atadev.h @@ -34,9 +34,12 @@ public: virtual DECLARE_WRITE_LINE_MEMBER(write_dmack) = 0; virtual DECLARE_WRITE_LINE_MEMBER(write_csel) = 0; virtual DECLARE_WRITE_LINE_MEMBER(write_dasp) = 0; + virtual DECLARE_WRITE_LINE_MEMBER(write_pdiag) = 0; devcb2_write_line m_irq_handler; devcb2_write_line m_dmarq_handler; + devcb2_write_line m_dasp_handler; + devcb2_write_line m_pdiag_handler; }; #endif diff --git a/src/emu/machine/ataintf.c b/src/emu/machine/ataintf.c index 81b06ceece2..027a8ded646 100644 --- a/src/emu/machine/ataintf.c +++ b/src/emu/machine/ataintf.c @@ -14,24 +14,10 @@ #include "debugger.h" #include "idehd.h" -/*************************************************************************** - DEBUGGING -***************************************************************************/ - -#define VERBOSE 0 - -#define LOG(x) do { if (VERBOSE) logerror x; } while (0) - void ata_interface_device::set_irq(int state) { // printf( "irq %d\n", state ); - if (state == ASSERT_LINE) - LOG(("ATA interrupt assert\n")); - else - LOG(("ATA interrupt clear\n")); - - /* signal an interrupt */ m_irq_handler(state); } @@ -42,6 +28,13 @@ void ata_interface_device::set_dmarq(int state) m_dmarq_handler(state); } +void ata_interface_device::set_dasp(int state) +{ +// printf( "dasp %d\n", state ); + + m_dasp_handler(state); +} + WRITE_LINE_MEMBER( ata_interface_device::irq0_write_line ) { if (m_irq[0] != state) @@ -62,6 +55,30 @@ WRITE_LINE_MEMBER( ata_interface_device::irq1_write_line ) } } +WRITE_LINE_MEMBER( ata_interface_device::dasp0_write_line ) +{ + if (m_dasp[0] != state) + { + m_dasp[0] = state; + + set_dasp(m_dasp[0] == ASSERT_LINE || m_dasp[1] == ASSERT_LINE); + } +} + +WRITE_LINE_MEMBER( ata_interface_device::dasp1_write_line ) +{ + if (m_dasp[1] != state) + { + m_dasp[1] = state; + + ata_device_interface *dev = m_slot[0]->dev(); + if (dev != NULL) + dev->write_dasp(state); + + set_dasp(m_dasp[0] == ASSERT_LINE || m_dasp[1] == ASSERT_LINE); + } +} + WRITE_LINE_MEMBER( ata_interface_device::dmarq0_write_line ) { if (m_dmarq[0] != state) @@ -82,6 +99,22 @@ WRITE_LINE_MEMBER( ata_interface_device::dmarq1_write_line ) } } +WRITE_LINE_MEMBER( ata_interface_device::pdiag0_write_line ) +{ + m_pdiag[0] = state; +} + +WRITE_LINE_MEMBER( ata_interface_device::pdiag1_write_line ) +{ + if (m_pdiag[1] != state) + { + m_pdiag[1] = state; + + ata_device_interface *dev = m_slot[0]->dev(); + if (dev != NULL) + dev->write_pdiag(state); + } +} /************************************* * @@ -174,8 +207,8 @@ SLOT_INTERFACE_END 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) : device_t(mconfig, type, name, tag, owner, clock, shortname, source), m_irq_handler(*this), - m_dmarq_handler(*this) -{ + m_dmarq_handler(*this), + m_dasp_handler(*this){ } @@ -184,7 +217,8 @@ const device_type ATA_INTERFACE = &device_creator; ata_interface_device::ata_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, ATA_INTERFACE, "ATA Interface", tag, owner, clock, "ata_interface", __FILE__), m_irq_handler(*this), - m_dmarq_handler(*this) + m_dmarq_handler(*this), + m_dasp_handler(*this) { } @@ -196,6 +230,7 @@ void ata_interface_device::device_start() { m_irq_handler.resolve_safe(); m_dmarq_handler.resolve_safe(); + m_dasp_handler.resolve_safe(); /* set MAME harddisk handle */ m_slot[0] = subdevice("0"); @@ -205,6 +240,8 @@ void ata_interface_device::device_start() { m_irq[i] = 0; m_dmarq[i] = 0; + m_dasp[i] = 0; + m_pdiag[i] = 0; ata_device_interface *dev = m_slot[i]->dev(); if (dev != NULL) @@ -213,30 +250,22 @@ void ata_interface_device::device_start() { dev->m_irq_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, irq0_write_line)); dev->m_dmarq_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, dmarq0_write_line)); + dev->m_dasp_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, dasp0_write_line)); + dev->m_pdiag_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, pdiag0_write_line)); } else { dev->m_irq_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, irq1_write_line)); dev->m_dmarq_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, dmarq1_write_line)); + dev->m_dasp_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, dasp1_write_line)); + dev->m_pdiag_handler.set_callback(DEVCB2_DEVWRITELINE("^", ata_interface_device, pdiag1_write_line)); } dev->write_csel(i); - dev->write_dasp(m_slot[1]->dev() != NULL); } } } -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void ata_interface_device::device_reset() -{ - LOG(("ATA interface reset\n")); -} - - - //************************************************************************** // ATA SLOT DEVICE //************************************************************************** diff --git a/src/emu/machine/ataintf.h b/src/emu/machine/ataintf.h index 369933e0029..be63a9e644e 100644 --- a/src/emu/machine/ataintf.h +++ b/src/emu/machine/ataintf.h @@ -51,6 +51,9 @@ extern const device_type ATA_SLOT; #define MCFG_ATA_INTERFACE_DMARQ_HANDLER(_devcb) \ devcb = &ata_interface_device::set_dmarq_handler(*device, DEVCB2_##_devcb); +#define MCFG_ATA_INTERFACE_DASP_HANDLER(_devcb) \ + devcb = &ata_interface_device::set_dasp_handler(*device, DEVCB2_##_devcb); + SLOT_INTERFACE_EXTERN(ata_devices); /*************************************************************************** @@ -82,7 +85,7 @@ public: // static configuration helpers template static devcb2_base &set_irq_handler(device_t &device, _Object object) { return downcast(device).m_irq_handler.set_callback(object); } template static devcb2_base &set_dmarq_handler(device_t &device, _Object object) { return downcast(device).m_dmarq_handler.set_callback(object); } - + template static devcb2_base &set_dasp_handler(device_t &device, _Object object) { return downcast(device).m_dasp_handler.set_callback(object); } UINT16 read_dma(); virtual DECLARE_READ16_MEMBER(read_cs0); virtual DECLARE_READ16_MEMBER(read_cs1); @@ -95,24 +98,31 @@ public: protected: // device-level overrides virtual void device_start(); - virtual void device_reset(); virtual void set_irq(int state); virtual void set_dmarq(int state); + virtual void set_dasp(int state); private: DECLARE_WRITE_LINE_MEMBER(irq0_write_line); DECLARE_WRITE_LINE_MEMBER(dmarq0_write_line); + DECLARE_WRITE_LINE_MEMBER(dasp0_write_line); + DECLARE_WRITE_LINE_MEMBER(pdiag0_write_line); DECLARE_WRITE_LINE_MEMBER(irq1_write_line); DECLARE_WRITE_LINE_MEMBER(dmarq1_write_line); + DECLARE_WRITE_LINE_MEMBER(dasp1_write_line); + DECLARE_WRITE_LINE_MEMBER(pdiag1_write_line); ata_slot_device *m_slot[2]; int m_irq[2]; int m_dmarq[2]; + int m_dasp[2]; + int m_pdiag[2]; devcb2_write_line m_irq_handler; devcb2_write_line m_dmarq_handler; + devcb2_write_line m_dasp_handler; }; extern const device_type ATA_INTERFACE; diff --git a/src/emu/machine/idehd.c b/src/emu/machine/idehd.c index afab428d90a..616f845fc6a 100644 --- a/src/emu/machine/idehd.c +++ b/src/emu/machine/idehd.c @@ -16,10 +16,15 @@ #define TIME_PER_SECTOR (attotime::from_usec(100)) #define TIME_PER_ROTATION (attotime::from_hz(5400/60)) +#define TIME_MULTIPLE_SECTORS (attotime::from_usec(1)) #define TIME_SEEK_MULTISECTOR (attotime::from_msec(13)) #define TIME_NO_SEEK_MULTISECTOR (attotime::from_nsec(16300)) +#define DIAGNOSTIC_TIME (attotime::from_msec(2)) +#define DETECT_DEVICE1_TIME (attotime::from_msec(2)) +#define DEVICE1_PDIAG_TIME (attotime::from_msec(2)) + #define IDE_CS0_DATA_RW 0 #define IDE_CS0_ERROR_R 1 #define IDE_CS0_FEATURE_W 1 @@ -63,11 +68,16 @@ enum { TID_NULL, - TID_DELAYED_INTERRUPT, - TID_DELAYED_INTERRUPT_BUFFER_READY, - TID_RESET_CALLBACK, - TID_READ_SECTOR_DONE_CALLBACK, - TID_WRITE_SECTOR_DONE_CALLBACK + TID_BUSY, +}; + +enum +{ + PARAM_RESET, + PARAM_DETECT_DEVICE1, + PARAM_DIAGNOSTIC, + PARAM_WAIT_FOR_PDIAG, + PARAM_COMMAND }; 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) @@ -76,10 +86,13 @@ ata_mass_storage_device::ata_mass_storage_device(const machine_config &mconfig, device_slot_card_interface(mconfig, *this), m_can_identify_device(0), m_csel(0), - m_dasp(0), + m_daspin(0), + m_daspout(0), m_dmack(0), m_dmarq(0), m_irq(0), + m_pdiagin(0), + m_pdiagout(0), m_master_password(NULL), m_user_password(NULL) { @@ -118,6 +131,26 @@ void ata_mass_storage_device::set_dmarq(int state) } } +void ata_mass_storage_device::set_dasp(int state) +{ + if (m_daspout != state) + { + m_daspout = state; + + m_dasp_handler(state); + } +} + +void ata_mass_storage_device::set_pdiag(int state) +{ + if (m_pdiagout != state) + { + m_pdiagout = state; + + m_pdiag_handler(state); + } +} + WRITE_LINE_MEMBER( ata_mass_storage_device::write_csel ) { m_csel = state; @@ -125,7 +158,7 @@ WRITE_LINE_MEMBER( ata_mass_storage_device::write_csel ) WRITE_LINE_MEMBER( ata_mass_storage_device::write_dasp ) { - m_dasp = state; + m_daspin = state; } WRITE_LINE_MEMBER( ata_mass_storage_device::write_dmack ) @@ -133,6 +166,17 @@ WRITE_LINE_MEMBER( ata_mass_storage_device::write_dmack ) m_dmack = state; } +WRITE_LINE_MEMBER( ata_mass_storage_device::write_pdiag ) +{ + m_pdiagin = state; + + if (m_pdiagin == ASSERT_LINE && m_busy_timer->param() == PARAM_WAIT_FOR_PDIAG) + { + stop_busy(); + finished_diagnostic(); + } +} + /************************************* * * Compute the LBA address @@ -334,6 +378,8 @@ void ata_mass_storage_device::device_start() { m_irq_handler.resolve_safe(); m_dmarq_handler.resolve_safe(); + m_dasp_handler.resolve_safe(); + m_pdiag_handler.resolve_safe(); save_item(NAME(m_buffer)); save_item(NAME(m_buffer_offset)); @@ -360,10 +406,33 @@ void ata_mass_storage_device::device_start() /* create a timer for timing status */ m_last_status_timer = timer_alloc(TID_NULL); - m_reset_timer = timer_alloc(TID_RESET_CALLBACK); + m_busy_timer = timer_alloc(TID_BUSY); } void ata_mass_storage_device::device_reset() +{ + /* reset the drive state */ + set_dasp(CLEAR_LINE); + set_dmarq(CLEAR_LINE); + set_irq(CLEAR_LINE); + set_pdiag(CLEAR_LINE); + + m_status = 0; + m_device_control = 0; + m_resetting = true; + + if (m_csel == 0) + { + start_busy(DETECT_DEVICE1_TIME, PARAM_DETECT_DEVICE1); + } + else + { + set_dasp(ASSERT_LINE); + soft_reset(); + } +} + +void ata_mass_storage_device::soft_reset() { m_buffer_offset = 0; m_master_password_enable = (m_master_password != NULL); @@ -376,50 +445,139 @@ void ata_mass_storage_device::device_reset() m_status |= IDE_STATUS_DRDY; } + start_busy(DIAGNOSTIC_TIME, PARAM_DIAGNOSTIC); +} + +void ata_mass_storage_device::perform_diagnostic() +{ if (m_can_identify_device) + { m_error = IDE_ERROR_DIAGNOSTIC_PASSED; + + if (m_csel == 1) + set_pdiag(ASSERT_LINE); + } else m_error = IDE_ERROR_DIAGNOSTIC_FAILED; + if (m_csel == 0 && !m_single_device && m_pdiagin == CLEAR_LINE) + start_busy(DEVICE1_PDIAG_TIME, PARAM_WAIT_FOR_PDIAG); + else + finished_diagnostic(); +} + +void ata_mass_storage_device::finished_diagnostic() +{ m_sector_count = 1; m_sector_number = 1; m_cylinder_low = 0; m_cylinder_high = 0; m_device_head = 0; - /* reset the drive state */ - set_irq(CLEAR_LINE); - set_dmarq(CLEAR_LINE); + m_resetting = false; +} + + +void ata_mass_storage_device::start_busy(attotime time, int param) +{ + m_status |= IDE_STATUS_BSY; + m_busy_timer->adjust(time, param); +} + +void ata_mass_storage_device::stop_busy() +{ + m_status &= ~IDE_STATUS_BSY; + m_busy_timer->adjust(attotime::never); } void ata_mass_storage_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { switch(id) { - case TID_DELAYED_INTERRUPT: + case TID_BUSY: m_status &= ~IDE_STATUS_BSY; - set_irq(ASSERT_LINE); + finished_busy(param); + break; + } +} + +void ata_mass_storage_device::finished_busy(int param) +{ + switch (param) + { + case PARAM_DETECT_DEVICE1: + m_single_device = (m_daspin == CLEAR_LINE); + soft_reset(); break; - case TID_DELAYED_INTERRUPT_BUFFER_READY: - m_status &= ~IDE_STATUS_BSY; - m_status |= IDE_STATUS_DRQ; - - set_irq(ASSERT_LINE); + case PARAM_DIAGNOSTIC: + perform_diagnostic(); break; - case TID_RESET_CALLBACK: - reset(); + case PARAM_WAIT_FOR_PDIAG: + m_error |= 0x80; + finished_diagnostic(); break; - case TID_READ_SECTOR_DONE_CALLBACK: - read_sector_done(); - break; + case PARAM_COMMAND: + switch (m_command) + { + case IDE_COMMAND_DIAGNOSTIC: + perform_diagnostic(); - case TID_WRITE_SECTOR_DONE_CALLBACK: - write_sector_done(); - break; + if (m_csel == 0) + set_irq(ASSERT_LINE); + break; + + case IDE_COMMAND_IDENTIFY_DEVICE: + if (m_can_identify_device) + { + memcpy(m_buffer, m_identify_device, sizeof(m_buffer)); + m_status |= IDE_STATUS_DRQ; + } + else + { + m_status |= IDE_STATUS_ERR; + m_error = IDE_ERROR_NONE; + } + + set_irq(ASSERT_LINE); + break; + + case IDE_COMMAND_SET_CONFIG: + set_geometry(m_sector_count,(m_device_head & IDE_DEVICE_HEAD_HS) + 1); + set_irq(ASSERT_LINE); + break; + + case IDE_COMMAND_READ_SECTORS: + case IDE_COMMAND_READ_SECTORS_NORETRY: + case IDE_COMMAND_READ_MULTIPLE: + case IDE_COMMAND_VERIFY_SECTORS: + case IDE_COMMAND_VERIFY_SECTORS_NORETRY: + case IDE_COMMAND_READ_DMA: + read_sector_done(); + break; + + case IDE_COMMAND_WRITE_SECTORS: + case IDE_COMMAND_WRITE_SECTORS_NORETRY: + case IDE_COMMAND_WRITE_MULTIPLE: + case IDE_COMMAND_WRITE_DMA: + write_sector_done(); + break; + + case IDE_COMMAND_RECALIBRATE: + set_irq(ASSERT_LINE); + break; + + case IDE_COMMAND_SET_FEATURES: + set_irq(ASSERT_LINE); + break; + + default: + logerror( "finished_busy(%d) unhandled command %02x\n", param, m_command ); + break; + } } } @@ -539,7 +697,7 @@ void ata_mass_storage_device::read_sector_done() { int lba = lba_address(), count = 0; - m_status &= ~IDE_STATUS_BSY; + set_dasp(CLEAR_LINE); /* now do the read */ count = read_sector(lba, m_buffer); @@ -589,8 +747,7 @@ void ata_mass_storage_device::read_sector_done() void ata_mass_storage_device::read_first_sector() { - /* mark ourselves busy */ - m_status |= IDE_STATUS_BSY; + set_dasp(ASSERT_LINE); /* just set a timer */ if (m_command == IDE_COMMAND_READ_MULTIPLE) @@ -599,22 +756,20 @@ void ata_mass_storage_device::read_first_sector() attotime seek_time; if (new_lba == m_cur_lba || new_lba == m_cur_lba + 1) - seek_time = TIME_NO_SEEK_MULTISECTOR; + start_busy(TIME_NO_SEEK_MULTISECTOR, PARAM_COMMAND); else - seek_time = TIME_SEEK_MULTISECTOR; + start_busy(TIME_SEEK_MULTISECTOR, PARAM_COMMAND); m_cur_lba = new_lba; - timer_set(seek_time, TID_READ_SECTOR_DONE_CALLBACK); } else - timer_set(TIME_PER_SECTOR, TID_READ_SECTOR_DONE_CALLBACK); + start_busy(TIME_PER_SECTOR, PARAM_COMMAND); } void ata_mass_storage_device::read_next_sector() { - /* mark ourselves busy */ - m_status |= IDE_STATUS_BSY; + set_dasp(ASSERT_LINE); if (m_command == IDE_COMMAND_READ_MULTIPLE) { @@ -622,12 +777,10 @@ void ata_mass_storage_device::read_next_sector() /* make ready now */ read_sector_done(); else - /* just set a timer */ - timer_set(attotime::from_usec(1), TID_READ_SECTOR_DONE_CALLBACK); + start_busy(TIME_MULTIPLE_SECTORS, PARAM_COMMAND); } else - /* just set a timer */ - timer_set(TIME_PER_SECTOR, TID_READ_SECTOR_DONE_CALLBACK); + start_busy(TIME_PER_SECTOR, PARAM_COMMAND); } @@ -643,8 +796,7 @@ void ata_mass_storage_device::continue_write() /* reset the totals */ m_buffer_offset = 0; - /* clear the buffer ready flag */ - m_status |= IDE_STATUS_BSY; + set_dasp(ASSERT_LINE); if (m_command == IDE_COMMAND_WRITE_MULTIPLE) { @@ -656,13 +808,13 @@ void ata_mass_storage_device::continue_write() else { /* set a timer to do the write */ - timer_set(TIME_PER_SECTOR, TID_WRITE_SECTOR_DONE_CALLBACK); + start_busy(TIME_PER_SECTOR, PARAM_COMMAND); } } else { /* set a timer to do the write */ - timer_set(TIME_PER_SECTOR, TID_WRITE_SECTOR_DONE_CALLBACK); + start_busy(TIME_PER_SECTOR, PARAM_COMMAND); } } @@ -718,7 +870,7 @@ void ata_mass_storage_device::write_sector_done() { int lba = lba_address(), count = 0; - m_status &= ~IDE_STATUS_BSY; + set_dasp(CLEAR_LINE); /* now do the write */ count = write_sector(lba, m_buffer); @@ -867,34 +1019,15 @@ bool ata_mass_storage_device::process_command() case IDE_COMMAND_IDENTIFY_DEVICE: LOGPRINT(("IDE Identify device\n")); - m_status |= IDE_STATUS_BSY; - if (m_can_identify_device) - { - memcpy(m_buffer, m_identify_device, sizeof(m_buffer)); - - timer_set(MINIMUM_COMMAND_TIME, TID_DELAYED_INTERRUPT_BUFFER_READY); - } - else - { - m_status |= IDE_STATUS_ERR; - m_error = IDE_ERROR_NONE; - timer_set(MINIMUM_COMMAND_TIME, TID_DELAYED_INTERRUPT); - } + start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); return true; case IDE_COMMAND_DIAGNOSTIC: - if (m_can_identify_device) - m_error = IDE_ERROR_DIAGNOSTIC_PASSED; - else - m_error = IDE_ERROR_DIAGNOSTIC_FAILED; - - m_status |= IDE_STATUS_BSY; - timer_set(MINIMUM_COMMAND_TIME, TID_DELAYED_INTERRUPT); + start_busy(DIAGNOSTIC_TIME, PARAM_COMMAND); return true; case IDE_COMMAND_RECALIBRATE: - m_status |= IDE_STATUS_BSY; - timer_set(MINIMUM_COMMAND_TIME, TID_DELAYED_INTERRUPT); + start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); return true; case IDE_COMMAND_IDLE: @@ -904,10 +1037,8 @@ bool ata_mass_storage_device::process_command() case IDE_COMMAND_SET_CONFIG: LOGPRINT(("IDE Set configuration (%d heads, %d sectors)\n", (m_device_head & IDE_DEVICE_HEAD_HS) + 1, m_sector_count)); - set_geometry(m_sector_count,(m_device_head & IDE_DEVICE_HEAD_HS) + 1); - m_status |= IDE_STATUS_BSY; - timer_set(MINIMUM_COMMAND_TIME, TID_DELAYED_INTERRUPT); + start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); return true; case IDE_COMMAND_SET_MAX: @@ -920,8 +1051,7 @@ bool ata_mass_storage_device::process_command() case IDE_COMMAND_SET_FEATURES: 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)); - m_status |= IDE_STATUS_BSY; - timer_set(MINIMUM_COMMAND_TIME, TID_DELAYED_INTERRUPT); + start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); return true; case IDE_COMMAND_SET_BLOCK_COUNT: @@ -989,7 +1119,7 @@ READ16_MEMBER( ata_mass_storage_device::read_cs0 ) UINT16 result = 0xffff; - if (device_selected() || single_device()) + if (device_selected() || m_single_device) { if (m_dmack) { @@ -997,6 +1127,8 @@ READ16_MEMBER( ata_mass_storage_device::read_cs0 ) } else if ((m_status & IDE_STATUS_BSY) && offset != IDE_CS0_STATUS_R) { + // ATA5 spec says status reads should also go through here, but this breaks Primal Rage 2. + // Real hardware might work due to read ahead in the vt83c461. if (device_selected()) { switch (offset) @@ -1093,9 +1225,7 @@ READ16_MEMBER( ata_mass_storage_device::read_cs0 ) } if (!(m_status & IDE_STATUS_DRDY) && is_ready()) - { m_status |= IDE_STATUS_DRDY; - } set_irq(CLEAR_LINE); } @@ -1125,7 +1255,7 @@ READ16_MEMBER( ata_mass_storage_device::read_cs1 ) UINT16 result = 0xffff; - if (device_selected() || single_device()) + if (device_selected() || m_single_device) { if (m_dmack) { @@ -1212,7 +1342,7 @@ WRITE16_MEMBER( ata_mass_storage_device::write_cs0 ) } else if ((m_status & IDE_STATUS_BSY) && offset != IDE_CS0_COMMAND_W) { - logerror( "%s: dev %d write_cs0 %04x %04x %04x ignored (BSY)\n", machine().describe_context(), dev(), offset, data, mem_mask ); + logerror( "%s: dev %d write_cs0 %04x %04x %04x ignored (BSY) command %02x\n", machine().describe_context(), dev(), offset, data, mem_mask, m_command ); } else if ((m_status & IDE_STATUS_DRQ) && offset != IDE_CS0_DATA_RW && offset != IDE_CS0_COMMAND_W) { @@ -1284,10 +1414,19 @@ WRITE16_MEMBER( ata_mass_storage_device::write_cs0 ) /* command */ case IDE_CS0_COMMAND_W: - m_command = data; - - if (device_selected() || m_command == IDE_COMMAND_DIAGNOSTIC) + // Packet devices can accept DEVICE RESET when BSY or DRQ is set. + if (m_status & IDE_STATUS_BSY) { + logerror( "%s: dev %d write_cs0 %04x %04x %04x ignored (BSY) command %02x\n", machine().describe_context(), dev(), offset, data, mem_mask, m_command ); + } + else if (m_status & IDE_STATUS_DRQ) + { + logerror( "%s: dev %d write_cs0 %04x %04x %04x ignored (DRQ) command %02x\n", machine().describe_context(), dev(), offset, data, mem_mask, m_command ); + } + else if (device_selected() || m_command == IDE_COMMAND_DIAGNOSTIC) + { + m_command = data; + /* implicitly clear interrupts & dmarq here */ set_irq(CLEAR_LINE); set_dmarq(CLEAR_LINE); @@ -1295,7 +1434,7 @@ WRITE16_MEMBER( ata_mass_storage_device::write_cs0 ) m_buffer_offset = 0; m_sectors_until_int = 0; - m_status &= ~IDE_STATUS_BSY; + set_dasp(CLEAR_LINE); m_status &= ~IDE_STATUS_DRQ; m_status &= ~IDE_STATUS_ERR; @@ -1344,9 +1483,23 @@ WRITE16_MEMBER( ata_mass_storage_device::write_cs1 ) { if (m_device_control & IDE_DEVICE_CONTROL_SRST) { - m_status |= IDE_STATUS_BSY; - set_irq(CLEAR_LINE); - m_reset_timer->adjust(attotime::from_msec(5)); + if (m_resetting) + { + logerror( "%s: dev %d write_cs1 %04x %04x %04x ignored (RESET)\n", machine().describe_context(), dev(), offset, data, mem_mask ); + } + else + { + set_dasp(CLEAR_LINE); + set_dmarq(CLEAR_LINE); + set_irq(CLEAR_LINE); + set_pdiag(CLEAR_LINE); + + start_busy(attotime::never, PARAM_RESET); + } + } + else if (m_busy_timer->param() == PARAM_RESET) + { + soft_reset(); } } break; diff --git a/src/emu/machine/idehd.h b/src/emu/machine/idehd.h index e59c43e416f..3ca8285a16b 100644 --- a/src/emu/machine/idehd.h +++ b/src/emu/machine/idehd.h @@ -61,6 +61,7 @@ public: virtual DECLARE_WRITE_LINE_MEMBER(write_csel); virtual DECLARE_WRITE_LINE_MEMBER(write_dasp); virtual DECLARE_WRITE_LINE_MEMBER(write_dmack); + virtual DECLARE_WRITE_LINE_MEMBER(write_pdiag); UINT8 *identify_device_buffer() { return m_identify_device; } @@ -88,15 +89,17 @@ protected: int dev() { return (m_device_head & IDE_DEVICE_HEAD_DRV) >> 4; } bool device_selected() { return m_csel == dev(); } - bool single_device() { return m_csel == 0 && m_dasp == 0; } void set_irq(int state); void set_dmarq(int state); + void set_dasp(int state); + void set_pdiag(int state); void ide_build_identify_device(); virtual bool process_command(); virtual void process_buffer(); virtual void fill_buffer(); + virtual void finished_busy(int param); UINT8 m_buffer[IDE_DISK_SECTOR_SIZE]; UINT16 m_buffer_offset; @@ -131,12 +134,23 @@ private: void read_buffer_empty(); void write_buffer_full(); void update_irq(); + void start_busy(attotime time, int param); + void stop_busy(); + void soft_reset(); + void perform_diagnostic(); + void finished_diagnostic(); int m_csel; - int m_dasp; + int m_daspin; + int m_daspout; int m_dmack; int m_dmarq; int m_irq; + int m_pdiagin; + int m_pdiagout; + + bool m_resetting; + bool m_single_device; UINT32 m_cur_lba; UINT16 m_block_count; @@ -148,7 +162,7 @@ private: const UINT8 * m_user_password; emu_timer * m_last_status_timer; - emu_timer * m_reset_timer; + emu_timer * m_busy_timer; }; // ======================> ide_hdd_device diff --git a/src/mame/drivers/viper.c b/src/mame/drivers/viper.c index e24ee5ed0b9..8322639daa2 100644 --- a/src/mame/drivers/viper.c +++ b/src/mame/drivers/viper.c @@ -1419,8 +1419,7 @@ WRITE64_MEMBER(viper_state::cf_card_w) { m_cf_card_ide = 1; - // soft reset - m_ata->write_cs1(space, 6, 0x04, 0xff); + m_ata->reset(); } break; } diff --git a/src/mess/machine/a2cffa.c b/src/mess/machine/a2cffa.c index 6bfda7e6f93..b6db86a79eb 100644 --- a/src/mess/machine/a2cffa.c +++ b/src/mess/machine/a2cffa.c @@ -32,7 +32,7 @@ const device_type A2BUS_CFFA2_6502 = &device_creator; #define CFFA2_ATA_TAG "cffa2_ata" MACHINE_CONFIG_FRAGMENT( cffa2 ) - MCFG_ATA_INTERFACE_ADD(CFFA2_ATA_TAG, ata_devices, "hdd", "hdd", false) + MCFG_ATA_INTERFACE_ADD(CFFA2_ATA_TAG, ata_devices, "hdd", NULL, false) MACHINE_CONFIG_END ROM_START( cffa2 ) diff --git a/src/mess/machine/a2vulcan.c b/src/mess/machine/a2vulcan.c index 662b48c8e25..94d51c2fcc7 100644 --- a/src/mess/machine/a2vulcan.c +++ b/src/mess/machine/a2vulcan.c @@ -66,7 +66,7 @@ const device_type A2BUS_VULCAN = &device_creator; #define VULCAN_ATA_TAG "vulcan_ata" static MACHINE_CONFIG_FRAGMENT( vulcan ) - MCFG_ATA_INTERFACE_ADD(VULCAN_ATA_TAG, ata_devices, "hdd", "hdd", false) + MCFG_ATA_INTERFACE_ADD(VULCAN_ATA_TAG, ata_devices, "hdd", NULL, false) MACHINE_CONFIG_END ROM_START( vulcan ) diff --git a/src/mess/machine/a2zipdrive.c b/src/mess/machine/a2zipdrive.c index 48c8ca9f243..2441856c2ab 100644 --- a/src/mess/machine/a2zipdrive.c +++ b/src/mess/machine/a2zipdrive.c @@ -32,7 +32,7 @@ const device_type A2BUS_ZIPDRIVE = &device_creator; #define ZIPDRIVE_ATA_TAG "zipdrive_ata" static MACHINE_CONFIG_FRAGMENT( zipdrive ) - MCFG_ATA_INTERFACE_ADD(ZIPDRIVE_ATA_TAG, ata_devices, "hdd", "hdd", false) + MCFG_ATA_INTERFACE_ADD(ZIPDRIVE_ATA_TAG, ata_devices, "hdd", NULL, false) MACHINE_CONFIG_END ROM_START( zipdrive ) diff --git a/src/mess/machine/c64_ide64.c b/src/mess/machine/c64_ide64.c index 82806f1829c..060ad4de8f1 100644 --- a/src/mess/machine/c64_ide64.c +++ b/src/mess/machine/c64_ide64.c @@ -49,7 +49,7 @@ static MACHINE_CONFIG_FRAGMENT( c64_ide64 ) MCFG_ATMEL_29C010_ADD(AT29C010A_TAG) MCFG_DS1302_ADD(DS1302_TAG, XTAL_32_768kHz) - MCFG_ATA_INTERFACE_ADD(ATA_TAG, ata_devices, "hdd", "hdd", false) + MCFG_ATA_INTERFACE_ADD(ATA_TAG, ata_devices, "hdd", NULL, false) MACHINE_CONFIG_END diff --git a/src/mess/machine/isa_ide.c b/src/mess/machine/isa_ide.c index c2fd92e2db0..0e29f43c0b8 100644 --- a/src/mess/machine/isa_ide.c +++ b/src/mess/machine/isa_ide.c @@ -40,7 +40,7 @@ WRITE_LINE_MEMBER(isa16_ide_device::ide_interrupt) } static MACHINE_CONFIG_FRAGMENT( ide ) - MCFG_IDE_CONTROLLER_ADD("ide", ata_devices, "hdd", "hdd", false) + MCFG_IDE_CONTROLLER_ADD("ide", ata_devices, "hdd", NULL, false) MCFG_ATA_INTERFACE_IRQ_HANDLER(WRITELINE(isa16_ide_device, ide_interrupt)) MACHINE_CONFIG_END diff --git a/src/mess/machine/isa_ide8.c b/src/mess/machine/isa_ide8.c index fc73c5bfc95..48230a78022 100644 --- a/src/mess/machine/isa_ide8.c +++ b/src/mess/machine/isa_ide8.c @@ -114,7 +114,7 @@ WRITE_LINE_MEMBER(isa8_ide_device::ide_interrupt) } static MACHINE_CONFIG_FRAGMENT( ide8_config ) - MCFG_IDE_CONTROLLER_ADD("ide", ata_devices, "hdd", "hdd", false) + MCFG_IDE_CONTROLLER_ADD("ide", ata_devices, "hdd", NULL, false) MCFG_ATA_INTERFACE_IRQ_HANDLER(WRITELINE(isa8_ide_device, ide_interrupt)) MACHINE_CONFIG_END diff --git a/src/mess/machine/kc_d004.c b/src/mess/machine/kc_d004.c index 4ac2acbb243..9359d7fabf9 100644 --- a/src/mess/machine/kc_d004.c +++ b/src/mess/machine/kc_d004.c @@ -90,7 +90,7 @@ static MACHINE_CONFIG_FRAGMENT(kc_d004_gide) MCFG_CPU_MODIFY(Z80_TAG) MCFG_CPU_IO_MAP(kc_d004_gide_io) - MCFG_ATA_INTERFACE_ADD(ATA_TAG, ata_devices, "hdd", "hdd", false) + MCFG_ATA_INTERFACE_ADD(ATA_TAG, ata_devices, "hdd", NULL, false) MACHINE_CONFIG_END