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