Abort ATA commands when writing to command block registers and DRQ or BSY is set, which is mentioned in the ATA3 specification as a possible outcome. Removed the equivalent hack used by the cojag games. Improved the logging in the ATA code. [smf]

This commit is contained in:
smf- 2025-02-07 12:53:38 +00:00
parent d246968ffc
commit 5fcf2f031c
2 changed files with 264 additions and 370 deletions

View File

@ -3,11 +3,27 @@
#include "emu.h"
#include "atahle.h"
#define VERBOSE 0
#define PRINTF_IDE_COMMANDS 0
#define LOG_COMMAND (1U << 1)
#define LOG_READ (1U << 2)
#define LOG_READDATA (1U << 3)
#define LOG_READSTATUS (1U << 4)
#define LOG_READCOMPLETED (1U << 5)
#define LOG_WRITE (1U << 6)
#define LOG_WRITEDATA (1U << 7)
#define LOG_WRITECOMPLETED (1U << 8)
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
#define LOGPRINT(x) do { if (VERBOSE) logerror x; if (PRINTF_IDE_COMMANDS) osd_printf_debug x; } while (0)
//#define VERBOSE (LOG_GENERAL | LOG_COMMAND | LOG_READ | LOG_WRITE | LOG_READCOMPLETED | LOG_WRITECOMPLETED)
//#define LOG_OUTPUT_FUNC osd_printf_info
#include "logmacro.h"
#define LOGCOMMAND(...) LOGMASKED(LOG_COMMAND, __VA_ARGS__)
#define LOGREAD(...) LOGMASKED(LOG_READ, __VA_ARGS__)
#define LOGREADDATA(...) LOGMASKED(LOG_READDATA, __VA_ARGS__)
#define LOGREADSTATUS(...) LOGMASKED(LOG_READSTATUS, __VA_ARGS__)
#define LOGREADCOMPLETED(...) LOGMASKED(LOG_READCOMPLETED, __VA_ARGS__)
#define LOGWRITE(...) LOGMASKED(LOG_WRITE, __VA_ARGS__)
#define LOGWRITEDATA(...) LOGMASKED(LOG_WRITEDATA, __VA_ARGS__)
#define LOGWRITECOMPLETED(...) LOGMASKED(LOG_WRITECOMPLETED, __VA_ARGS__)
enum
{
@ -110,7 +126,6 @@ void ata_hle_device_base::device_start()
void ata_hle_device_base::device_reset()
{
/* reset the drive state */
set_dasp(CLEAR_LINE);
set_dmarq(CLEAR_LINE);
set_irq(CLEAR_LINE);
@ -121,9 +136,7 @@ void ata_hle_device_base::device_reset()
m_resetting = true;
if (m_csel == 0)
{
start_busy(DETECT_DEVICE1_TIME, PARAM_DETECT_DEVICE1);
}
else
{
set_dasp(ASSERT_LINE);
@ -138,9 +151,7 @@ void ata_hle_device_base::soft_reset()
m_status = 0;
if (is_ready())
{
m_status |= IDE_STATUS_DRDY;
}
start_busy(DIAGNOSTIC_TIME, PARAM_DIAGNOSTIC);
}
@ -198,7 +209,7 @@ void ata_hle_device_base::process_command()
break;
default:
LOGPRINT(("IDE unknown command (%02X)\n", m_command));
LOG("%s device %d process_command() unknown command (0x%02x)\n", machine().describe_context(), dev(), m_command);
m_status |= IDE_STATUS_ERR;
m_error = IDE_ERROR_ABRT;
set_irq(ASSERT_LINE);
@ -221,7 +232,7 @@ void ata_hle_device_base::finished_command()
case IDE_COMMAND_SET_FEATURES:
if (!set_features())
{
LOGPRINT(("IDE Set features failed (%02X %02X %02X %02X %02X)\n", m_feature, m_sector_count & 0xff, m_sector_number, m_cylinder_low, m_cylinder_high));
LOGCOMMAND("IDE Set features failed (%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_ERR;
m_error = IDE_ERROR_ABRT;
@ -234,7 +245,7 @@ void ata_hle_device_base::finished_command()
break;
default:
logerror( "finished_command() unhandled command %02x\n", m_command );
LOG("device %d finished_command() unhandled command 0x%02x\n", dev(), m_command);
break;
}
}
@ -319,10 +330,10 @@ bool ata_hle_device_base::set_features()
m_revert_to_defaults = true;
return true;
// not actually handled, but reply as if we did
case IDE_SET_FEATURES_ENABLE_ECC:
case IDE_SET_FEATURES_ENABLE_RETRIES:
case IDE_SET_FEATURES_ENABLE_READ_LOOK_AHEAD:
// not actually handled, but reply as if we did
return true;
}
@ -331,7 +342,7 @@ bool ata_hle_device_base::set_features()
int ata_hle_device_base::bit_to_mode(uint16_t word)
{
switch (word>>8)
switch (word >> 8)
{
case 0x01:
return 0;
@ -347,26 +358,23 @@ int ata_hle_device_base::bit_to_mode(uint16_t word)
return 5;
case 0x40:
return 6;
case 0x080:
case 0x80:
return 7;
}
return -1;
}
// Return the currently selected single word dma mode, -1 if none selected
int ata_hle_device_base::single_word_dma_mode()
{
return bit_to_mode(m_identify_buffer[62]);
}
// Return the currently selected multi word dma mode, -1 if none selected
int ata_hle_device_base::multi_word_dma_mode()
{
return bit_to_mode(m_identify_buffer[63]);
}
// Return the currently selected ultra dma mode, -1 if none selected
int ata_hle_device_base::ultra_dma_mode()
{
return bit_to_mode(m_identify_buffer[88]);
@ -374,15 +382,13 @@ int ata_hle_device_base::ultra_dma_mode()
uint16_t ata_hle_device_base::read_data()
{
/* fetch the correct amount of data */
uint16_t result = m_buffer[m_buffer_offset++];
if (!m_8bit_data_transfers)
result |= m_buffer[m_buffer_offset++] << 8;
/* if we're at the end of the buffer, handle it */
if (m_buffer_offset >= m_buffer_size)
{
LOG(("%s:IDE completed PIO read\n", machine().describe_context()));
LOGREADCOMPLETED("%s device %d read_data() completed\n", machine().describe_context(), dev());
read_buffer_empty();
}
@ -391,15 +397,13 @@ uint16_t ata_hle_device_base::read_data()
void ata_hle_device_base::write_data(uint16_t data)
{
/* store the correct amount of data */
m_buffer[m_buffer_offset++] = data;
if (!m_8bit_data_transfers)
m_buffer[m_buffer_offset++] = data >> 8;
/* if we're at the end of the buffer, handle it */
if (m_buffer_offset >= m_buffer_size)
{
LOG(("%s:IDE completed PIO write\n", machine().describe_context()));
LOGWRITECOMPLETED("%s device %d write_data() completed\n", machine().describe_context(), dev());
write_buffer_full();
}
}
@ -429,12 +433,10 @@ void ata_hle_device_base::read_buffer_empty()
m_buffer_offset = 0;
m_status &= ~IDE_STATUS_DRQ;
// Doesn't matter if we're in dma or not, when the buffer is empty
// there's no more request to be had
set_dmarq(CLEAR_LINE);
if (ultra_dma_mode() >= 0) {
if (ultra_dma_mode() >= 0)
{
m_buffer_empty_timer->enable(true);
m_buffer_empty_timer->adjust(attotime::zero);
}
@ -447,9 +449,6 @@ void ata_hle_device_base::write_buffer_full()
m_buffer_offset = 0;
m_status &= ~IDE_STATUS_DRQ;
// Doesn't matter if we're in dma or not, when the buffer is full
// there's no more request to be had
set_dmarq(CLEAR_LINE);
process_buffer();
@ -499,240 +498,198 @@ void ata_hle_device_base::set_pdiag_in(int state)
uint16_t ata_hle_device_base::dma_r()
{
uint16_t result = 0xffff;
if (device_selected())
{
if (!m_dmack)
{
logerror( "%s: %s dev %d read_dma ignored (!DMACK)\n", machine().describe_context(), tag(), dev() );
}
LOG("%s device %d dma_r 0x%04x (ignored DMACK)\n", machine().describe_context(), dev(), 0xffff);
else if (m_dmarq && single_word_dma_mode() >= 0)
{
logerror( "%s: %s dev %d read_dma ignored (DMARQ)\n", machine().describe_context(), tag(), dev() );
}
LOG("%s device %d dma_r 0x%04x (ignored DMARQ)\n", machine().describe_context(), dev(), 0xffff);
else if (!m_dmarq && multi_word_dma_mode() >= 0)
{
logerror( "%s: %s dev %d read_dma ignored (!DMARQ)\n", machine().describe_context(), tag(), dev() );
}
LOG("%s device %d dma_r 0x%04x (ignored !DMARQ)\n", machine().describe_context(), dev(), 0xffff);
else if (!m_dmarq && ultra_dma_mode() >= 0)
{
logerror("%s: %s dev %d read_dma ignored (!DMARQ)\n", machine().describe_context(), tag(), dev());
}
LOG("%s device %d dma_r 0x%04x (ignored !DMARQ)\n", machine().describe_context(), dev(), 0xffff);
else if (m_status & IDE_STATUS_BSY)
{
logerror( "%s: %s dev %d read_dma ignored (BSY)\n", machine().describe_context(), tag(), dev() );
}
LOG("%s device %d dma_r 0x%04x (ignored BSY)\n", machine().describe_context(), dev(), 0xffff);
else if (!(m_status & IDE_STATUS_DRQ))
{
logerror( "%s: %s dev %d read_dma ignored (!DRQ)\n", machine().describe_context(), tag(), dev() );
}
LOG("%s device %d dma_r 0x%04x (ignored !DRQ)\n", machine().describe_context(), dev(), 0xffff);
else
{
result = read_data();
uint16_t data = read_data();
if ((m_status & IDE_STATUS_DRQ) && single_word_dma_mode() >= 0)
set_dmarq(ASSERT_LINE);
LOGREADDATA("%s device %d dma_r 0x%04x\n", data);
return data;
}
}
return result;
return 0xffff;
}
uint16_t ata_hle_device_base::command_r(offs_t offset)
{
uint16_t result = 0xffff;
if (device_selected() || m_single_device)
{
if (m_dmack)
{
if (!machine().side_effects_disabled())
logerror( "%s: %s dev %d read_cs0 %04x ignored (DMACK)\n", machine().describe_context(), tag(), dev(), offset );
LOG("%s device %d cs0_r (0x%x) 0x%04x (ignored DMACK)\n", machine().describe_context(), dev(), offset, 0xffff);
}
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)
{
case IDE_CS0_DATA_RW:
if (!machine().side_effects_disabled())
logerror( "%s: %s dev %d read_cs0 %04x ignored (BSY)\n", machine().describe_context(), tag(), dev(), offset );
break;
unsigned short busy = !device_selected() ? 0 : (offset == IDE_CS0_DATA_RW) ? 0xffff : calculate_status();
default:
result = calculate_status();
break;
}
}
else
{
result = 0;
}
if (!machine().side_effects_disabled())
LOG("%s device %d cs0_r (0x%x) 0x%04x (ignored BSY)\n", machine().describe_context(), dev(), offset, busy);
return busy;
}
else
{
switch (offset)
{
/* read data if there's data to be read */
case IDE_CS0_DATA_RW:
if (device_selected())
{
if (!(m_status & IDE_STATUS_DRQ))
{
if (!machine().side_effects_disabled())
logerror( "%s: %s dev %d read_cs0 ignored (!DRQ)\n", machine().describe_context(), tag(), dev() );
}
else
{
if (!machine().side_effects_disabled())
result = read_data();
else
result = 0;
}
}
else
{
result = 0;
}
break;
/* return the current error */
case IDE_CS0_ERROR_R:
result = m_error;
break;
/* return the current sector count */
case IDE_CS0_SECTOR_COUNT_RW:
result = m_sector_count;
break;
/* return the current sector */
case IDE_CS0_SECTOR_NUMBER_RW:
result = m_sector_number;
break;
/* return the current cylinder LSB */
case IDE_CS0_CYLINDER_LOW_RW:
result = m_cylinder_low;
break;
/* return the current cylinder MSB */
case IDE_CS0_CYLINDER_HIGH_RW:
result = m_cylinder_high;
break;
/* return the current head */
case IDE_CS0_DEVICE_HEAD_RW:
result = m_device_head;
break;
/* return the current status and clear any pending interrupts */
case IDE_CS0_STATUS_R:
if (device_selected())
{
result = calculate_status();
if (!(m_status & IDE_STATUS_DRDY) && is_ready())
m_status |= IDE_STATUS_DRDY;
set_irq(CLEAR_LINE);
}
else
{
result = 0;
}
break;
/* log anything else */
default:
case IDE_CS0_DATA_RW:
if (device_selected() && !(m_status & IDE_STATUS_DRQ))
{
if (!machine().side_effects_disabled())
logerror("%s:unknown IDE cs0 read at %03X\n", machine().describe_context(), offset);
break;
LOG("%s device %d cs0_r data !DRQ 0x%04x\n", machine().describe_context(), dev(), 0xffff);
}
else
{
uint16_t data = device_selected() ? read_data() : 0xffff;
LOGREADDATA("%s device %d cs0_r data 0x%04x\n", data);
return data;
}
break;
case IDE_CS0_ERROR_R:
if (!machine().side_effects_disabled())
LOGREAD("%s device %d cs0_r error register 0x%02x\n", machine().describe_context(), dev(), m_error);
return m_error;
case IDE_CS0_SECTOR_COUNT_RW:
if (!machine().side_effects_disabled())
LOGREAD("%s device %d cs0_r sector count 0x%02x\n", machine().describe_context(), dev(), m_sector_count);
return m_sector_count;
case IDE_CS0_SECTOR_NUMBER_RW:
if (!machine().side_effects_disabled())
LOGREAD("%s device %d cs0_r sector number 0x%02x\n", machine().describe_context(), dev(), m_sector_number);
return m_sector_number;
case IDE_CS0_CYLINDER_LOW_RW:
if (!machine().side_effects_disabled())
LOGREAD("%s device %d cs0_r cylinder low 0x%02x\n", machine().describe_context(), dev(), m_cylinder_low);
return m_cylinder_low;
case IDE_CS0_CYLINDER_HIGH_RW:
if (!machine().side_effects_disabled())
LOGREAD("%s device %d cs0_r cylinder high 0x%02x\n", machine().describe_context(), dev(), m_cylinder_high);
return m_cylinder_high;
case IDE_CS0_DEVICE_HEAD_RW:
if (!machine().side_effects_disabled())
LOGREAD("%s device %d cs0_r device/head 0x%02x\n", machine().describe_context(), dev(), m_device_head);
return m_device_head;
case IDE_CS0_STATUS_R:
{
uint8_t status;
if (device_selected())
{
status = calculate_status();
if (!(m_status & IDE_STATUS_DRDY) && is_ready())
m_status |= IDE_STATUS_DRDY;
set_irq(CLEAR_LINE);
}
else
status = 0;
if (!machine().side_effects_disabled())
LOGREADSTATUS("%s device %d cs0_r status 0x%04x\n", machine().describe_context(), dev(), status);
return status;
}
default:
if (!machine().side_effects_disabled())
LOG("%s device %d cs0_r unknown (0x%x) 0x%04x\n", machine().describe_context(), dev(), offset, 0xffff);
}
}
}
/* logit */
// if (offset != IDE_CS0_DATA_RW && offset != IDE_CS0_STATUS_R)
if (!machine().side_effects_disabled())
LOG(("%s:IDE cs0 read %X at %X (err: %X)\n", machine().describe_context(), result, offset, m_error));
/* return the result */
return result;
return 0xffff;
}
uint16_t ata_hle_device_base::control_r(offs_t offset)
{
/* logit */
// if (offset != IDE_CS1_ALTERNATE_STATUS_R)
if (!machine().side_effects_disabled())
LOG(("%s:IDE cs1 read at %X\n", machine().describe_context(), offset));
uint16_t result = 0xffff;
if (device_selected() || m_single_device)
{
if (m_dmack)
{
if (!machine().side_effects_disabled())
logerror( "%s: %s dev %d read_cs1 %04x ignored (DMACK)\n", machine().describe_context(), tag(), dev(), offset );
LOG("%s device %d cs1_r (0x%x) 0x%0x (ignored DMACK)\n", machine().describe_context(), dev(), offset, 0xffff);
return 0xffff;
}
else
{
switch (offset)
{
case IDE_CS1_ALTERNATE_STATUS_R:
if (device_selected())
{
result = calculate_status();
}
else
{
result = 0;
}
break;
case IDE_CS1_ALTERNATE_STATUS_R:
{
uint8_t status = device_selected() ? calculate_status() : 0;
case IDE_CS1_ACTIVE_STATUS:
/*
if (!machine().side_effects_disabled())
LOGREADSTATUS("%s device %d cs1_r status 0x%04x\n", machine().describe_context(), dev(), status);
return status;
}
bit description
case IDE_CS1_ACTIVE_STATUS:
{
uint8_t active_status = device_selected() ? 1 : 0;
0 master active
1 slave active
2 complement of active disk head bit 0
3 complement of active disk head bit 1
4 complement of active disk head bit 2
5 complement of active disk head bit 3
6 write in progress
7 floppy present (unused)
/*
*/
if (device_selected())
{
result = 0x01;
}
else
{
result = 0;
}
break;
bit description
/* log anything else */
default:
if (!machine().side_effects_disabled())
logerror("%s:unknown IDE cs1 read at %03X\n", machine().describe_context(), offset);
break;
0 master active
1 slave active
2 complement of active disk head bit 0
3 complement of active disk head bit 1
4 complement of active disk head bit 2
5 complement of active disk head bit 3
6 write in progress
7 floppy present (unused)
*/
if (!machine().side_effects_disabled())
LOGREAD("%s device %d cs1_r active status 0x%04x\n", machine().describe_context(), dev(), active_status);
return active_status;
}
default:
if (!machine().side_effects_disabled())
LOG("%s device %d cs1_r unknown (0x%x) 0x%04x\n", machine().describe_context(), dev(), offset, 0xffff);
return 0xffff;
}
}
}
/* return the result */
return result;
return 0xffff;
}
void ata_hle_device_base::dma_w(uint16_t data)
@ -740,29 +697,17 @@ void ata_hle_device_base::dma_w(uint16_t data)
if (device_selected())
{
if (!m_dmack)
{
logerror( "%s: %s dev %d write_dma %04x ignored (!DMACK)\n", machine().describe_context(), tag(), dev(), data );
}
LOG("%s device %d dma_w 0x%04x (ignored !DMACK)\n", machine().describe_context(), dev(), data);
else if (m_dmarq && single_word_dma_mode() >= 0)
{
logerror( "%s: %s dev %d write_dma %04x ignored (DMARQ)\n", machine().describe_context(), tag(), dev(), data );
}
LOG("%s device %d dma_w 0x%04x (ignored DMARQ)\n", machine().describe_context(), dev(), data);
else if (!m_dmarq && multi_word_dma_mode() >= 0)
{
logerror( "%s: %s dev %d write_dma %04x ignored (!DMARQ)\n", machine().describe_context(), tag(), dev(), data );
}
LOG("%s device %d dma_w 0x%04x (ignored !DMARQ)\n", machine().describe_context(), dev(), data);
else if (!m_dmarq && ultra_dma_mode() >= 0)
{
logerror("%s: %s dev %d write_dma %04x ignored (!DMARQ)\n", machine().describe_context(), tag(), dev(), data);
}
LOG("%s device %d dma_w 0x%04x (ignored !DMARQ)\n", machine().describe_context(), dev(), data);
else if (m_status & IDE_STATUS_BSY)
{
logerror( "%s: %s dev %d write_dma %04x ignored (BSY)\n", machine().describe_context(), tag(), dev(), data );
}
LOG("%s device %d dma_w 0x%04x (ignored BSY)\n", machine().describe_context(), dev(), data);
else if (!(m_status & IDE_STATUS_DRQ))
{
logerror( "%s: %s dev %d write_dma %04x ignored (!DRQ)\n", machine().describe_context(), tag(), dev(), data );
}
LOG("%s device %d dma_w 0x%04x (ignored !DRQ)\n", machine().describe_context(), dev(), data);
else
{
write_data(data);
@ -775,164 +720,140 @@ void ata_hle_device_base::dma_w(uint16_t data)
void ata_hle_device_base::command_w(offs_t offset, uint16_t data)
{
/* logit */
if (offset != IDE_CS0_DATA_RW)
LOG(("%s:IDE cs0 write to %X = %04X\n", machine().describe_context(), offset, data));
if ((m_status & (IDE_STATUS_DRQ | IDE_STATUS_BSY)) && offset != IDE_CS0_DATA_RW)
{
LOGREADCOMPLETED("%s device %d cs0_w (0x%x) aborted after %d bytes\n", machine().describe_context(), dev(), offset, m_buffer_offset);
stop_busy();
m_status &= ~IDE_STATUS_DRQ;
set_dmarq(CLEAR_LINE);
m_status |= IDE_STATUS_ERR;
m_error = IDE_ERROR_ABRT;
}
if (m_dmack)
LOG("%s device %d cs0_w (0x%x) 0x%04x (ignored DMACK)\n", machine().describe_context(), dev(), offset, data);
else if (device_selected() || m_single_device)
{
logerror( "%s: %s dev %d write_cs0 %04x %04x ignored (DMACK)\n", machine().describe_context(), tag(), dev(), offset, data );
}
else if ((m_status & IDE_STATUS_BSY) && offset != IDE_CS0_COMMAND_W)
{
logerror( "%s: %s dev %d write_cs0 %04x %04x ignored (BSY) command %02x\n", machine().describe_context(), tag(), dev(), offset, data, m_command );
}
else if ((m_status & IDE_STATUS_DRQ) && offset != IDE_CS0_DATA_RW && offset != IDE_CS0_COMMAND_W)
{
logerror( "%s: %s dev %d write_cs0 %04x %04x ignored (DRQ) command %02x\n", machine().describe_context(), tag(), dev(), offset, data, m_command );
}
else
{
uint8_t old;
switch (offset)
{
/* write data */
case IDE_CS0_DATA_RW:
if (device_selected())
{
if (!(m_status & IDE_STATUS_DRQ))
{
logerror( "%s: %s dev %d write_cs0 %04x %04x ignored (!DRQ)\n", machine().describe_context(), tag(), dev(), offset, data );
}
else
{
write_data(data);
}
}
break;
case IDE_CS0_DATA_RW:
if (m_status & IDE_STATUS_BSY)
LOG("%s device %d cs0_w data 0x%04x (ignored BSY)\n", machine().describe_context(), dev(), data);
if (!(m_status & IDE_STATUS_DRQ))
LOG("%s device %d cs0_w data 0x%04x (ignored !DRQ)\n", machine().describe_context(), dev(), data);
else if (!device_selected())
LOG("%s device %d cs0_w data 0x%04x (ignored !selected)\n", machine().describe_context(), dev(), data);
else
{
LOGWRITEDATA("%s device %d cs0_w data 0x%04x\n", machine().describe_context(), dev(), data);
write_data(data);
}
break;
case IDE_CS0_FEATURE_W:
m_feature = data;
break;
case IDE_CS0_FEATURE_W:
LOGWRITE("%s device %d cs0_w feature 0x%02x\n", machine().describe_context(), dev(), data);
m_feature = data;
break;
/* sector count */
case IDE_CS0_SECTOR_COUNT_RW:
m_sector_count = (data & 0xff) ? (data & 0xff) : 0x100;
break;
case IDE_CS0_SECTOR_COUNT_RW:
LOGWRITE("%s device %d cs0_w sector count 0x%02x\n", machine().describe_context(), dev(), data);
m_sector_count = (data & 0xff) ? (data & 0xff) : 0x100;
break;
/* current sector */
case IDE_CS0_SECTOR_NUMBER_RW:
m_sector_number = data;
break;
case IDE_CS0_SECTOR_NUMBER_RW:
LOGWRITE("%s device %d cs0_w sector number 0x%02x\n", machine().describe_context(), dev(), data);
m_sector_number = data;
break;
/* current cylinder LSB */
case IDE_CS0_CYLINDER_LOW_RW:
m_cylinder_low = data;
break;
case IDE_CS0_CYLINDER_LOW_RW:
LOGWRITE("%s device %d cs0_w cylinder low 0x%02x\n", machine().describe_context(), dev(), data);
m_cylinder_low = data;
break;
/* current cylinder MSB */
case IDE_CS0_CYLINDER_HIGH_RW:
m_cylinder_high = data;
break;
case IDE_CS0_CYLINDER_HIGH_RW:
LOGWRITE("%s device %d cs0_w cylinder high 0x%02x\n", machine().describe_context(), dev(), data);
m_cylinder_high = data;
break;
/* current head */
case IDE_CS0_DEVICE_HEAD_RW:
old = m_device_head;
m_device_head = data;
case IDE_CS0_DEVICE_HEAD_RW:
{
LOGWRITE("%s device %d cs0_w device/head 0x%02x\n", machine().describe_context(), dev(), data);
if ((m_device_head ^ old) & IDE_DEVICE_HEAD_DRV)
update_irq();
break;
bool drv_changed = ((m_device_head ^ data) & IDE_DEVICE_HEAD_DRV) != 0;
m_device_head = data;
/* command */
case IDE_CS0_COMMAND_W:
// Packet devices can accept DEVICE RESET when BSY or DRQ is set.
if (m_status & IDE_STATUS_BSY)
{
logerror( "%s: %s dev %d write_cs0 %04x %04x ignored (BSY) command %02x\n", machine().describe_context(), tag(), dev(), offset, data, m_command );
}
else if (m_status & IDE_STATUS_DRQ)
{
logerror( "%s: %s dev %d write_cs0 %04x %04x ignored (DRQ) command %02x\n", machine().describe_context(), tag(), dev(), offset, data, m_command );
}
else if (device_selected() || m_command == IDE_COMMAND_DIAGNOSTIC)
{
m_command = data;
m_error = IDE_ERROR_NONE;
if (drv_changed)
update_irq();
break;
}
/* implicitly clear interrupts & dmarq here */
set_irq(CLEAR_LINE);
set_dmarq(CLEAR_LINE);
case IDE_CS0_COMMAND_W:
LOGWRITE("%s device %d cs0_w command 0x%02x\n", machine().describe_context(), dev(), data);
m_buffer_offset = 0;
m_command = data;
m_buffer_offset = 0;
m_status &= ~IDE_STATUS_ERR;
m_error = IDE_ERROR_NONE;
set_dasp(CLEAR_LINE);
m_status &= ~IDE_STATUS_DRQ;
m_status &= ~IDE_STATUS_ERR;
set_irq(CLEAR_LINE);
set_dasp(CLEAR_LINE);
process_command();
}
break;
if (!device_selected() && m_command != IDE_COMMAND_DIAGNOSTIC)
LOG("%s device %d cs0_w command 0x%04x (ignored !selected)\n", machine().describe_context(), dev(), offset, data);
else
process_command();
break;
default:
logerror("%s:unknown IDE cs0 write at %03X = %04x\n", machine().describe_context(), offset, data);
break;
default:
LOG("%s device %d cs0_w unknown (0x%x) 0x%02x\n", machine().describe_context(), dev(), offset, data);
break;
}
}
}
void ata_hle_device_base::control_w(offs_t offset, uint16_t data)
{
/* logit */
LOG(("%s:IDE cs1 write to %X = %08X\n", machine().describe_context(), offset, data));
if (m_dmack)
{
logerror( "%s: %s dev %d write_cs1 %04x %04x ignored (DMACK)\n", machine().describe_context(), tag(), dev(), offset, data);
}
LOG("%s device %d cs1_w (0x%x) 0x%04x (ignored DMACK)\n", machine().describe_context(), dev(), offset, data);
else
{
uint8_t old;
switch (offset)
{
/* adapter control */
case IDE_CS1_DEVICE_CONTROL_W:
old = m_device_control;
m_device_control = data;
case IDE_CS1_DEVICE_CONTROL_W:
{
LOGWRITE("%s device %d cs1_w device control 0x%02x\n", machine().describe_context(), dev(), data);
if ((m_device_control ^ old) & IDE_DEVICE_CONTROL_NIEN)
update_irq();
uint8_t old = m_device_control;
m_device_control = data;
if ((m_device_control ^ old) & IDE_DEVICE_CONTROL_SRST)
if ((m_device_control ^ old) & IDE_DEVICE_CONTROL_NIEN)
update_irq();
if ((m_device_control ^ old) & IDE_DEVICE_CONTROL_SRST)
{
if (m_device_control & IDE_DEVICE_CONTROL_SRST)
{
if (m_device_control & IDE_DEVICE_CONTROL_SRST)
if (m_resetting)
LOG("%s device %d cs1_w (0x%x) %04x (ignored RESET)\n", machine().describe_context(), dev(), offset, data);
else
{
if (m_resetting)
{
logerror( "%s: %s dev %d write_cs1 %04x %04x ignored (RESET)\n", machine().describe_context(), tag(), dev(), offset, data );
}
else
{
set_dasp(CLEAR_LINE);
set_dmarq(CLEAR_LINE);
set_irq(CLEAR_LINE);
set_pdiag(CLEAR_LINE);
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();
start_busy(attotime::never, PARAM_RESET);
}
}
break;
else if (m_busy_timer->param() == PARAM_RESET)
soft_reset();
}
break;
}
default:
logerror("%s:unknown IDE cs1 write at %03X = %04x\n", machine().describe_context(), offset, data);
break;
default:
LOG("%s device %d cs1_w unknown (0x%x) 0x%02x\n", machine().describe_context(), dev(), offset, data);
break;
}
}
}

View File

@ -366,36 +366,9 @@ Notes:
*
*************************************/
/// HACK: Maximum force requests data but doesn't transfer it all before issuing another command.
/// According to the ATA specification this is not allowed, more investigation is required.
DECLARE_DEVICE_TYPE(COJAG_HARDDISK, cojag_hdd)
class cojag_hdd : public ide_hdd_device
{
public:
cojag_hdd(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: ide_hdd_device(mconfig, COJAG_HARDDISK, tag, owner, clock)
{
}
virtual void write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask) override
{
// the first write is to the device head register
if( offset == 6 && (m_status & IDE_STATUS_DRQ))
{
m_status &= ~IDE_STATUS_DRQ;
}
ide_hdd_device::write_cs0(offset, data, mem_mask);
}
};
DEFINE_DEVICE_TYPE(COJAG_HARDDISK, cojag_hdd, "cojag_hdd", "HDD CoJag")
void cojag_devices(device_slot_interface &device)
{
device.option_add("hdd", COJAG_HARDDISK);
device.option_add("hdd", IDE_HARDDISK);
}