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]

This commit is contained in:
smf- 2013-06-24 10:24:14 +00:00
parent f07afceb6b
commit 7c27ec1308
14 changed files with 337 additions and 127 deletions

View File

@ -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)
{
}

View File

@ -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

View File

@ -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::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<ata_slot_device>("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
//**************************************************************************

View File

@ -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<class _Object> static devcb2_base &set_irq_handler(device_t &device, _Object object) { return downcast<ata_interface_device &>(device).m_irq_handler.set_callback(object); }
template<class _Object> static devcb2_base &set_dmarq_handler(device_t &device, _Object object) { return downcast<ata_interface_device &>(device).m_dmarq_handler.set_callback(object); }
template<class _Object> static devcb2_base &set_dasp_handler(device_t &device, _Object object) { return downcast<ata_interface_device &>(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;

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -32,7 +32,7 @@ const device_type A2BUS_CFFA2_6502 = &device_creator<a2bus_cffa2_6502_device>;
#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 )

View File

@ -66,7 +66,7 @@ const device_type A2BUS_VULCAN = &device_creator<a2bus_vulcan_device>;
#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 )

View File

@ -32,7 +32,7 @@ const device_type A2BUS_ZIPDRIVE = &device_creator<a2bus_zipdrive_device>;
#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 )

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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