From f197f35c25770a6b439601cc8fcafee34ca556c0 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Thu, 29 Jun 2023 05:31:33 +1000 Subject: machine/ataflash.cpp: Untangle from the parallel ATA interface. This isolates the ATA disk drive interface implementation from the physical parallel ATA device interface. The ATA Flash PC Card is no longer a kind of parallel ATA device. --- scripts/src/bus.lua | 6 +- scripts/src/machine.lua | 24 + src/devices/bus/ata/atadev.cpp | 2 +- src/devices/bus/ata/atahle.cpp | 966 ------------------------------------- src/devices/bus/ata/atahle.h | 223 --------- src/devices/bus/ata/atapicdr.cpp | 1 + src/devices/bus/ata/atapicdr.h | 26 +- src/devices/bus/ata/atapihle.cpp | 12 +- src/devices/bus/ata/atapihle.h | 4 +- src/devices/bus/ata/hdd.cpp | 45 ++ src/devices/bus/ata/hdd.h | 92 ++++ src/devices/bus/ata/idehd.cpp | 953 ------------------------------------ src/devices/bus/ata/idehd.h | 139 ------ src/devices/bus/epson_qx/ide.cpp | 23 +- src/devices/bus/epson_qx/ide.h | 17 +- src/devices/machine/ataflash.cpp | 12 +- src/devices/machine/ataflash.h | 14 +- src/devices/machine/atahle.cpp | 915 +++++++++++++++++++++++++++++++++++ src/devices/machine/atahle.h | 256 ++++++++++ src/devices/machine/atastorage.cpp | 942 ++++++++++++++++++++++++++++++++++++ src/devices/machine/atastorage.h | 136 ++++++ src/mame/atari/jaguar.cpp | 10 +- src/mame/konami/cobra.cpp | 2 +- src/mame/konami/djmain.cpp | 2 +- src/mame/konami/firebeat.cpp | 7 +- src/mame/konami/viper.cpp | 4 +- src/mame/merit/mtouchxl.cpp | 2 +- src/mame/microsoft/xbox.cpp | 10 +- src/mame/midway/seattle.cpp | 2 +- src/mame/midway/vegas.cpp | 2 +- src/mame/namco/turrett.cpp | 4 +- src/mame/rare/kinst.cpp | 2 +- src/mame/sega/chihiro.cpp | 39 +- src/mame/sinclair/atm.cpp | 2 +- src/mame/sinclair/sprinter.cpp | 2 +- src/mame/sony/taitogn.cpp | 58 +-- src/mame/taito/taitotz.cpp | 2 +- 37 files changed, 2572 insertions(+), 2386 deletions(-) delete mode 100644 src/devices/bus/ata/atahle.cpp delete mode 100644 src/devices/bus/ata/atahle.h create mode 100644 src/devices/bus/ata/hdd.cpp create mode 100644 src/devices/bus/ata/hdd.h delete mode 100644 src/devices/bus/ata/idehd.cpp delete mode 100644 src/devices/bus/ata/idehd.h create mode 100644 src/devices/machine/atahle.cpp create mode 100644 src/devices/machine/atahle.h create mode 100644 src/devices/machine/atastorage.cpp create mode 100644 src/devices/machine/atastorage.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 6a8a3735a29..df37b27033e 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -496,8 +496,6 @@ if (BUSES["ATA"]~=null) then files { MAME_DIR .. "src/devices/bus/ata/atadev.cpp", MAME_DIR .. "src/devices/bus/ata/atadev.h", - MAME_DIR .. "src/devices/bus/ata/atahle.cpp", - MAME_DIR .. "src/devices/bus/ata/atahle.h", MAME_DIR .. "src/devices/bus/ata/ataintf.cpp", MAME_DIR .. "src/devices/bus/ata/ataintf.h", MAME_DIR .. "src/devices/bus/ata/atapicdr.cpp", @@ -508,10 +506,10 @@ if (BUSES["ATA"]~=null) then MAME_DIR .. "src/devices/bus/ata/cp2024.h", MAME_DIR .. "src/devices/bus/ata/cr589.cpp", MAME_DIR .. "src/devices/bus/ata/cr589.h", + MAME_DIR .. "src/devices/bus/ata/hdd.cpp", + MAME_DIR .. "src/devices/bus/ata/hdd.h", MAME_DIR .. "src/devices/bus/ata/gdrom.cpp", MAME_DIR .. "src/devices/bus/ata/gdrom.h", - MAME_DIR .. "src/devices/bus/ata/idehd.cpp", - MAME_DIR .. "src/devices/bus/ata/idehd.h", MAME_DIR .. "src/devices/bus/ata/px320a.cpp", MAME_DIR .. "src/devices/bus/ata/px320a.h", } diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 2fcc8ea9a69..59dfd6dbdea 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -928,6 +928,18 @@ if (MACHINES["AT45DBXX"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/atahle.h,MACHINES["ATAHLE"] = true +--------------------------------------------------- + +if (MACHINES["ATAHLE"]~=null) then + files { + MAME_DIR .. "src/devices/machine/atahle.cpp", + MAME_DIR .. "src/devices/machine/atahle.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/ataflash.h,MACHINES["ATAFLASH"] = true @@ -941,6 +953,18 @@ if (MACHINES["ATAFLASH"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/atastorage.h,MACHINES["ATASTORAGE"] = true +--------------------------------------------------- + +if (MACHINES["ATASTORAGE"]~=null) then + files { + MAME_DIR .. "src/devices/machine/atastorage.cpp", + MAME_DIR .. "src/devices/machine/atastorage.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/atmel_arm_aic.h,MACHINES["ARM_AIC"] = true diff --git a/src/devices/bus/ata/atadev.cpp b/src/devices/bus/ata/atadev.cpp index a3cec8b2238..5f2b317bddb 100644 --- a/src/devices/bus/ata/atadev.cpp +++ b/src/devices/bus/ata/atadev.cpp @@ -11,7 +11,7 @@ #include "atapicdr.h" #include "cp2024.h" -#include "idehd.h" +#include "hdd.h" #include "px320a.h" //------------------------------------------------- diff --git a/src/devices/bus/ata/atahle.cpp b/src/devices/bus/ata/atahle.cpp deleted file mode 100644 index 3e5ab4838ef..00000000000 --- a/src/devices/bus/ata/atahle.cpp +++ /dev/null @@ -1,966 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:smf -#include "emu.h" -#include "atahle.h" - -#define VERBOSE 0 -#define PRINTF_IDE_COMMANDS 0 - -#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) - -enum -{ - IDE_CS0_DATA_RW = 0, - IDE_CS0_ERROR_R = 1, - IDE_CS0_FEATURE_W = 1, - IDE_CS0_SECTOR_COUNT_RW = 2, - IDE_CS0_SECTOR_NUMBER_RW = 3, - IDE_CS0_CYLINDER_LOW_RW = 4, - IDE_CS0_CYLINDER_HIGH_RW = 5, - IDE_CS0_DEVICE_HEAD_RW = 6, - IDE_CS0_STATUS_R = 7, - IDE_CS0_COMMAND_W = 7 -}; - -enum -{ - IDE_CS1_ALTERNATE_STATUS_R = 6, - IDE_CS1_DEVICE_CONTROL_W = 6, - IDE_CS1_ACTIVE_STATUS = 7 -}; - -enum -{ - IDE_DEVICE_CONTROL_NIEN = 0x02, - IDE_DEVICE_CONTROL_SRST = 0x04 -}; - -#define DETECT_DEVICE1_TIME (attotime::from_msec(2)) -#define DEVICE1_PDIAG_TIME (attotime::from_msec(2)) -#define DIAGNOSTIC_TIME (attotime::from_msec(2)) - -ata_hle_device::ata_hle_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, type, tag, owner, clock), - device_ata_interface(mconfig, *this), - m_buffer_offset(0), - m_buffer_size(0), - m_error(0), - m_feature(0), - m_sector_count(0), - m_sector_number(0), - m_cylinder_low(0), - m_cylinder_high(0), - m_device_head(0), - m_status(0), - m_command(0), - m_device_control(0), - m_revert_to_defaults(true), - m_8bit_data_transfers(false), - m_csel(0), - m_daspin(0), - m_daspout(0), - m_dmack(0), - m_dmarq(0), - m_irq(0), - m_pdiagin(0), - m_pdiagout(0), - m_single_device(0), - m_resetting(0), m_busy_timer(nullptr), m_buffer_empty_timer(nullptr) -{ -} - -void ata_hle_device::device_start() -{ - MINIMUM_COMMAND_TIME = attotime::from_usec(10); - - m_buffer.resize(sector_length()); - save_item(NAME(m_buffer)); - save_item(NAME(m_buffer_offset)); - save_item(NAME(m_buffer_size)); - save_item(NAME(m_error)); - save_item(NAME(m_feature)); - save_item(NAME(m_sector_count)); - save_item(NAME(m_sector_number)); - save_item(NAME(m_cylinder_low)); - save_item(NAME(m_cylinder_high)); - save_item(NAME(m_device_head)); - save_item(NAME(m_status)); - save_item(NAME(m_command)); - save_item(NAME(m_device_control)); - save_item(NAME(m_revert_to_defaults)); - save_item(NAME(m_8bit_data_transfers)); - - save_item(NAME(m_single_device)); - save_item(NAME(m_resetting)); - - save_item(NAME(m_csel)); - save_item(NAME(m_daspin)); - save_item(NAME(m_daspout)); - save_item(NAME(m_dmack)); - save_item(NAME(m_dmarq)); - save_item(NAME(m_irq)); - save_item(NAME(m_pdiagin)); - save_item(NAME(m_pdiagout)); - - save_item(NAME(m_identify_buffer)); - - m_busy_timer = timer_alloc(FUNC(ata_hle_device::busy_tick), this); - m_buffer_empty_timer = timer_alloc(FUNC(ata_hle_device::empty_tick), this); -} - -void ata_hle_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_hle_device::soft_reset() -{ - m_buffer_offset = 0; - m_buffer_size = 0; - m_status = 0; - - if (is_ready()) - { - m_status |= IDE_STATUS_DRDY; - } - - start_busy(DIAGNOSTIC_TIME, PARAM_DIAGNOSTIC); -} - -TIMER_CALLBACK_MEMBER(ata_hle_device::busy_tick) -{ - m_status &= ~IDE_STATUS_BSY; - finished_busy(param); -} - -TIMER_CALLBACK_MEMBER(ata_hle_device::empty_tick) -{ - m_buffer_empty_timer->enable(false); - fill_buffer(); -} - -void ata_hle_device::finished_busy(int param) -{ - switch (param) - { - case PARAM_DETECT_DEVICE1: - m_single_device = (m_daspin == CLEAR_LINE); - soft_reset(); - break; - - case PARAM_DIAGNOSTIC: - start_diagnostic(); - break; - - case PARAM_WAIT_FOR_PDIAG: - m_error |= IDE_ERROR_DIAGNOSTIC_DEVICE1_FAILED; - finished_diagnostic(); - break; - - case PARAM_COMMAND: - finished_command(); - break; - } -} - -void ata_hle_device::process_command() -{ - switch (m_command) - { - case IDE_COMMAND_DIAGNOSTIC: - start_busy(DIAGNOSTIC_TIME, PARAM_COMMAND); - break; - - case IDE_COMMAND_SET_FEATURES: - start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); - break; - - case IDE_COMMAND_CACHE_FLUSH: - start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); - break; - - default: - LOGPRINT(("IDE unknown command (%02X)\n", m_command)); - m_status |= IDE_STATUS_ERR; - m_error = IDE_ERROR_ABRT; - set_irq(ASSERT_LINE); - //machine().debug_break(); - break; - } -} - -void ata_hle_device::finished_command() -{ - switch (m_command) - { - case IDE_COMMAND_DIAGNOSTIC: - start_diagnostic(); - - if (m_csel == 0) - set_irq(ASSERT_LINE); - break; - - 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)); - - m_status |= IDE_STATUS_ERR; - m_error = IDE_ERROR_ABRT; - } - set_irq(ASSERT_LINE); - break; - - case IDE_COMMAND_CACHE_FLUSH: - m_status |= IDE_STATUS_DRDY; - break; - - default: - logerror( "finished_command() unhandled command %02x\n", m_command ); - break; - } -} - -bool ata_hle_device::set_dma_mode(int word) -{ - if ((m_identify_buffer[word] >> (m_sector_count & 7)) & 1) - { - m_identify_buffer[62] &= 0xff; - m_identify_buffer[63] &= 0xff; - m_identify_buffer[88] &= 0xff; - - m_identify_buffer[word] |= 0x100 << (m_sector_count & 7); - return true; - } - - return false; -} - -bool ata_hle_device::set_features() -{ - switch (m_feature) - { - case IDE_SET_FEATURES_ENABLE_8BIT_DATA_TRANSFERS: - m_8bit_data_transfers = true; - return true; - - case IDE_SET_FEATURES_TRANSFER_MODE: - switch (m_sector_count & IDE_TRANSFER_TYPE_MASK) - { - case IDE_TRANSFER_TYPE_PIO_DEFAULT: - switch (m_sector_count & 7) - { - case 0: - case 1: - return true; - } - break; - - case IDE_TRANSFER_TYPE_PIO_FLOW_CONTROL: - switch (m_sector_count & 7) - { - case 0: - case 1: - case 2: - return true; - - default: - if ((m_identify_buffer[64] >> ((m_sector_count & 7) - 3)) & 1) - { - return true; - } - } - break; - - case IDE_TRANSFER_TYPE_SINGLE_WORD_DMA: - return set_dma_mode(62); - - case IDE_TRANSFER_TYPE_MULTI_WORD_DMA: - return set_dma_mode(63); - - case IDE_TRANSFER_TYPE_ULTRA_DMA: - return set_dma_mode(88); - } - break; - - case IDE_SET_FEATURES_DISABLE_REVERTING_TO_POWER_ON_DEFAULTS: - m_revert_to_defaults = false; - return true; - - case IDE_SET_FEATURES_DISABLE_8BIT_DATA_TRANSFERS: - m_8bit_data_transfers = false; - return true; - - case IDE_SET_FEATURES_ENABLE_REVERTING_TO_POWER_ON_DEFAULTS: - m_revert_to_defaults = true; - return true; - } - - return false; -} - -int ata_hle_device::bit_to_mode(uint16_t word) -{ - switch (word>>8) - { - case 0x01: - return 0; - case 0x02: - return 1; - case 0x04: - return 2; - case 0x08: - return 3; - case 0x10: - return 4; - case 0x20: - return 5; - case 0x40: - return 6; - case 0x080: - return 7; - } - - return -1; -} - -// Return the currently selected single word dma mode, -1 if none selected -int ata_hle_device::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::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::ultra_dma_mode() -{ - return bit_to_mode(m_identify_buffer[88]); -} - -uint16_t ata_hle_device::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())); - read_buffer_empty(); - } - - return result; -} - -void ata_hle_device::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())); - write_buffer_full(); - } -} - -void ata_hle_device::update_irq() -{ - if (device_selected() && (m_device_control & IDE_DEVICE_CONTROL_NIEN) == 0) - device_ata_interface::set_irq(m_irq); - else - device_ata_interface::set_irq(CLEAR_LINE); -} - -void ata_hle_device::set_irq(int state) -{ - if (m_irq != state) - { - m_irq = state; - - update_irq(); - } -} - -void ata_hle_device::set_dmarq(int state) -{ - if (m_dmarq != state) - { - m_dmarq = state; - - device_ata_interface::set_dmarq(state); - } -} - -void ata_hle_device::set_dasp(int state) -{ - if (m_daspout != state) - { - m_daspout = state; - - device_ata_interface::set_dasp(state); - } -} - -void ata_hle_device::set_pdiag(int state) -{ - if (m_pdiagout != state) - { - m_pdiagout = state; - - device_ata_interface::set_pdiag(state); - } -} - -void ata_hle_device::start_busy(const attotime &time, int param) -{ - m_status |= IDE_STATUS_BSY; - m_busy_timer->adjust(time, param); -} - -void ata_hle_device::stop_busy() -{ - m_status &= ~IDE_STATUS_BSY; - m_busy_timer->adjust(attotime::never); -} - -void ata_hle_device::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) { - m_buffer_empty_timer->enable(true); - m_buffer_empty_timer->adjust(attotime::zero); - } - else - fill_buffer(); -} - -void ata_hle_device::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(); -} - -void ata_hle_device::start_diagnostic() -{ - m_error = IDE_ERROR_DIAGNOSTIC_FAILED; - - perform_diagnostic(); - - if (m_csel == 1 && m_error == IDE_ERROR_DIAGNOSTIC_PASSED) - set_pdiag(ASSERT_LINE); - - 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_hle_device::finished_diagnostic() -{ - m_resetting = false; - - signature(); -} - - -void ata_hle_device::write_csel(int state) -{ - m_csel = state; -} - -void ata_hle_device::write_dasp(int state) -{ - m_daspin = state; -} - -void ata_hle_device::write_dmack(int state) -{ - if (state && !m_dmack && single_word_dma_mode() >= 0) - set_dmarq(CLEAR_LINE); - - m_dmack = state; -} - -void ata_hle_device::write_pdiag(int state) -{ - m_pdiagin = state; - - if (m_pdiagin == ASSERT_LINE && m_busy_timer->param() == PARAM_WAIT_FOR_PDIAG) - { - stop_busy(); - finished_diagnostic(); - } -} - -uint16_t ata_hle_device::read_dma() -{ - 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() ); - } - else if (m_dmarq && single_word_dma_mode() >= 0) - { - logerror( "%s: %s dev %d read_dma ignored (DMARQ)\n", machine().describe_context(), tag(), dev() ); - } - else if (!m_dmarq && multi_word_dma_mode() >= 0) - { - logerror( "%s: %s dev %d read_dma ignored (!DMARQ)\n", machine().describe_context(), tag(), dev() ); - } - else if (!m_dmarq && ultra_dma_mode() >= 0) - { - logerror("%s: %s dev %d read_dma ignored (!DMARQ)\n", machine().describe_context(), tag(), dev()); - } - else if (m_status & IDE_STATUS_BSY) - { - logerror( "%s: %s dev %d read_dma ignored (BSY)\n", machine().describe_context(), tag(), dev() ); - } - else if (!(m_status & IDE_STATUS_DRQ)) - { - logerror( "%s: %s dev %d read_dma ignored (!DRQ)\n", machine().describe_context(), tag(), dev() ); - } - else - { - result = read_data(); - - if ((m_status & IDE_STATUS_DRQ) && single_word_dma_mode() >= 0) - set_dmarq(ASSERT_LINE); - } - } - - return result; -} - -uint16_t ata_hle_device::read_cs0(offs_t offset, uint16_t mem_mask) -{ - uint16_t result = 0xffff; - - if (device_selected() || m_single_device) - { - if (m_dmack) - { - logerror( "%s: %s dev %d read_cs0 %04x %04x ignored (DMACK)\n", machine().describe_context(), tag(), dev(), offset, mem_mask ); - } - 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: - logerror( "%s: %s dev %d read_cs0 %04x %04x ignored (BSY)\n", machine().describe_context(), tag(), dev(), offset, mem_mask ); - break; - - default: - result = calculate_status(); - break; - } - } - else - { - result = 0; - } - } - 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)) - { - logerror( "%s: %s dev %d read_cs0 ignored (!DRQ)\n", machine().describe_context(), tag(), dev() ); - } - else - { - result = read_data(); - } - } - 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: - logerror("%s:unknown IDE cs0 read at %03X, mem_mask=%X\n", machine().describe_context(), offset, mem_mask); - break; - } - } - } - - /* logit */ -// if (offset != IDE_CS0_DATA_RW && offset != IDE_CS0_STATUS_R) - LOG(("%s:IDE cs0 read %X at %X (err: %X), mem_mask=%X\n", machine().describe_context(), result, offset, m_error, mem_mask)); - - /* return the result */ - return result; -} - - -uint16_t ata_hle_device::read_cs1(offs_t offset, uint16_t mem_mask) -{ - /* logit */ -// if (offset != IDE_CS1_ALTERNATE_STATUS_R) - LOG(("%s:IDE cs1 read at %X, mem_mask=%d\n", machine().describe_context(), offset, mem_mask)); - - uint16_t result = 0xffff; - - if (device_selected() || m_single_device) - { - if (m_dmack) - { - logerror( "%s: %s dev %d read_cs1 %04x %04x ignored (DMACK)\n", machine().describe_context(), tag(), dev(), offset, mem_mask ); - } - else - { - switch (offset) - { - case IDE_CS1_ALTERNATE_STATUS_R: - if (device_selected()) - { - result = calculate_status(); - } - else - { - result = 0; - } - break; - - case IDE_CS1_ACTIVE_STATUS: - /* - - bit description - - 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; - - /* log anything else */ - default: - logerror("%s:unknown IDE cs1 read at %03X, mem_mask=%d\n", machine().describe_context(), offset, mem_mask); - break; - } - } - } - - /* return the result */ - return result; -} - -void ata_hle_device::write_dma( 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 ); - } - 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 ); - } - 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 ); - } - 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); - } - else if (m_status & IDE_STATUS_BSY) - { - logerror( "%s: %s dev %d write_dma %04x ignored (BSY)\n", machine().describe_context(), tag(), 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 ); - } - else - { - write_data(data); - - if ((m_status & IDE_STATUS_DRQ) && single_word_dma_mode() >= 0) - set_dmarq(ASSERT_LINE); - } - } -} - -void ata_hle_device::write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - /* logit */ - if (offset != IDE_CS0_DATA_RW) - LOG(("%s:IDE cs0 write to %X = %08X, mem_mask=%d\n", machine().describe_context(), offset, data, mem_mask)); - - if (m_dmack) - { - logerror( "%s: %s dev %d write_cs0 %04x %04x %04x ignored (DMACK)\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask ); - } - else if ((m_status & IDE_STATUS_BSY) && offset != IDE_CS0_COMMAND_W) - { - logerror( "%s: %s dev %d write_cs0 %04x %04x %04x ignored (BSY) command %02x\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask, 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 %04x ignored (DRQ) command %02x\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask, 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 %04x ignored (!DRQ)\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask ); - } - else - { - write_data(data); - } - } - break; - - case IDE_CS0_FEATURE_W: - m_feature = data; - break; - - /* sector count */ - case IDE_CS0_SECTOR_COUNT_RW: - m_sector_count = (data & 0xff) ? (data & 0xff) : 0x100; - break; - - /* current sector */ - case IDE_CS0_SECTOR_NUMBER_RW: - m_sector_number = data; - break; - - /* current cylinder LSB */ - case IDE_CS0_CYLINDER_LOW_RW: - m_cylinder_low = data; - break; - - /* current cylinder MSB */ - case IDE_CS0_CYLINDER_HIGH_RW: - m_cylinder_high = data; - break; - - /* current head */ - case IDE_CS0_DEVICE_HEAD_RW: - old = m_device_head; - m_device_head = data; - - if ((m_device_head ^ old) & IDE_DEVICE_HEAD_DRV) - update_irq(); - break; - - /* 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 %04x ignored (BSY) command %02x\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask, m_command ); - } - else if (m_status & IDE_STATUS_DRQ) - { - logerror( "%s: %s dev %d write_cs0 %04x %04x %04x ignored (DRQ) command %02x\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask, m_command ); - } - else if (device_selected() || m_command == IDE_COMMAND_DIAGNOSTIC) - { - m_command = data; - m_error = IDE_ERROR_NONE; - - /* implicitly clear interrupts & dmarq here */ - set_irq(CLEAR_LINE); - set_dmarq(CLEAR_LINE); - - m_buffer_offset = 0; - - set_dasp(CLEAR_LINE); - m_status &= ~IDE_STATUS_DRQ; - m_status &= ~IDE_STATUS_ERR; - - process_command(); - } - break; - - default: - logerror("%s:unknown IDE cs0 write at %03X = %04x, mem_mask=%d\n", machine().describe_context(), offset, data, mem_mask); - break; - } - } -} - -void ata_hle_device::write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask) -{ - /* logit */ - LOG(("%s:IDE cs1 write to %X = %08X, mem_mask=%d\n", machine().describe_context(), offset, data, mem_mask)); - - if (m_dmack) - { - logerror( "%s: %s dev %d write_cs1 %04x %04x %04x ignored (DMACK)\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask ); - } - else - { - uint8_t old; - - switch (offset) - { - /* adapter control */ - case IDE_CS1_DEVICE_CONTROL_W: - old = m_device_control; - m_device_control = data; - - 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_resetting) - { - logerror( "%s: %s dev %d write_cs1 %04x %04x %04x ignored (RESET)\n", machine().describe_context(), tag(), 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; - - default: - logerror("%s:unknown IDE cs1 write at %03X = %04x, mem_mask=%d\n", machine().describe_context(), offset, data, mem_mask); - break; - } - } -} diff --git a/src/devices/bus/ata/atahle.h b/src/devices/bus/ata/atahle.h deleted file mode 100644 index fa85cae7213..00000000000 --- a/src/devices/bus/ata/atahle.h +++ /dev/null @@ -1,223 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:smf -/*************************************************************************** - - atahle.h - - ATA Device HLE - -***************************************************************************/ - -#ifndef MAME_BUS_ATA_ATAHLE_H -#define MAME_BUS_ATA_ATAHLE_H - -#pragma once - -#include "atadev.h" - -class ata_hle_device : public device_t, public device_ata_interface -{ -public: - virtual uint16_t read_dma() override; - virtual uint16_t read_cs0(offs_t offset, uint16_t mem_mask = 0xffff) override; - virtual uint16_t read_cs1(offs_t offset, uint16_t mem_mask = 0xffff) override; - - virtual void write_dma(uint16_t data) override; - virtual void write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) override; - virtual void write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) override; - virtual void write_csel(int state) override; - virtual void write_dasp(int state) override; - virtual void write_dmack(int state) override; - virtual void write_pdiag(int state) override; - -protected: - ata_hle_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - virtual void device_reset() override; - - TIMER_CALLBACK_MEMBER(busy_tick); - TIMER_CALLBACK_MEMBER(empty_tick); - - void set_irq(int state); - void set_dmarq(int state); - void set_dasp(int state); - void set_pdiag(int state); - - void start_busy(const attotime &time, int param); - void stop_busy(); - - int dev() { return (m_device_head & IDE_DEVICE_HEAD_DRV) >> 4; } - bool device_selected() { return m_csel == dev(); } - - virtual uint8_t calculate_status() { return m_status; } - virtual void soft_reset(); - virtual void process_command(); - virtual void finished_command(); - virtual bool set_features(); - virtual int sector_length() = 0; - virtual void process_buffer() = 0; - virtual void fill_buffer() = 0; - virtual bool is_ready() = 0; - virtual void perform_diagnostic() = 0; - virtual void signature() = 0; - virtual uint16_t read_data(); - virtual void write_data(uint16_t data); - - int bit_to_mode(uint16_t word); - int single_word_dma_mode(); - int multi_word_dma_mode(); - int ultra_dma_mode(); - - /// TODO: not sure this should be protected. - void read_buffer_empty(); - - enum - { - IDE_STATUS_ERR = 0x01, // Error - IDE_STATUS_IDX = 0x02, // Index - IDE_STATUS_CORR = 0x04, // Corrected Data - IDE_STATUS_DRQ = 0x08, // Data Request - IDE_STATUS_DSC = 0x10, // ATA Drive Seek Complete - IDE_STATUS_SERV = 0x10, // ATAPI Service - IDE_STATUS_DWF = 0x20, // ATA Drive Write Fault - IDE_STATUS_DMRD = 0x20, // ATAPI DMA Ready - IDE_STATUS_DRDY = 0x40, // Drive Ready - IDE_STATUS_BSY = 0x80 // Busy - }; - - enum - { - IDE_ERROR_NONE = 0x00, - IDE_ERROR_DIAGNOSTIC_OK = 0x01, - IDE_ERROR_TRACK0_NOT_FOUND = 0x02, - IDE_ERROR_ABRT = 0x04, - IDE_ERROR_BAD_LOCATION = 0x10, - IDE_ERROR_BAD_SECTOR = 0x80, - IDE_ERROR_DIAGNOSTIC_FAILED = 0x00, - IDE_ERROR_DIAGNOSTIC_PASSED = 0x01, - IDE_ERROR_DIAGNOSTIC_DEVICE1_FAILED = 0x80 - }; - - enum - { - IDE_COMMAND_NOP = 0x00, - IDE_COMMAND_DEVICE_RESET = 0x08, - IDE_COMMAND_RECALIBRATE = 0x10, - IDE_COMMAND_READ_SECTORS = 0x20, - IDE_COMMAND_READ_SECTORS_NORETRY = 0x21, - IDE_COMMAND_WRITE_SECTORS = 0x30, - IDE_COMMAND_WRITE_SECTORS_NORETRY = 0x31, - IDE_COMMAND_VERIFY_SECTORS = 0x40, - IDE_COMMAND_VERIFY_SECTORS_NORETRY = 0x41, - IDE_COMMAND_SEEK = 0x70, - IDE_COMMAND_DIAGNOSTIC = 0x90, - IDE_COMMAND_SET_CONFIG = 0x91, - IDE_COMMAND_PACKET = 0xa0, - IDE_COMMAND_IDENTIFY_PACKET_DEVICE = 0xa1, - IDE_COMMAND_READ_MULTIPLE = 0xc4, - IDE_COMMAND_WRITE_MULTIPLE = 0xc5, - IDE_COMMAND_SET_BLOCK_COUNT = 0xc6, - IDE_COMMAND_READ_DMA = 0xc8, - IDE_COMMAND_WRITE_DMA = 0xca, - IDE_COMMAND_STANDBY_IMMEDIATE = 0xe0, - IDE_COMMAND_IDLE_IMMEDIATE = 0xe1, - IDE_COMMAND_STANDBY = 0xe2, - IDE_COMMAND_IDLE = 0xe3, - IDE_COMMAND_CHECK_POWER_MODE = 0xe5, - IDE_COMMAND_CACHE_FLUSH = 0xe7, - IDE_COMMAND_IDENTIFY_DEVICE = 0xec, - IDE_COMMAND_SET_FEATURES = 0xef, - IDE_COMMAND_SECURITY_UNLOCK = 0xf2, - IDE_COMMAND_SECURITY_DISABLE_PASSWORD = 0xf6, - IDE_COMMAND_READ_NATIVE_MAX_ADDRESS = 0xf8, - IDE_COMMAND_SET_MAX = 0xf9 - }; - - enum - { - IDE_SET_FEATURES_ENABLE_8BIT_DATA_TRANSFERS = 0x01, - IDE_SET_FEATURES_TRANSFER_MODE = 0x03, - IDE_SET_FEATURES_DISABLE_REVERTING_TO_POWER_ON_DEFAULTS = 0x66, - IDE_SET_FEATURES_DISABLE_8BIT_DATA_TRANSFERS = 0x81, - IDE_SET_FEATURES_ENABLE_REVERTING_TO_POWER_ON_DEFAULTS = 0xcc - }; - - enum ide_transfer_type_t - { - IDE_TRANSFER_TYPE_PIO_DEFAULT = 0x00, - IDE_TRANSFER_TYPE_PIO_FLOW_CONTROL = 0x08, - IDE_TRANSFER_TYPE_SINGLE_WORD_DMA = 0x10, - IDE_TRANSFER_TYPE_MULTI_WORD_DMA = 0x20, - IDE_TRANSFER_TYPE_ULTRA_DMA = 0x40, - IDE_TRANSFER_TYPE_MASK = 0xf8 - }; - - enum - { - IDE_DEVICE_HEAD_HS = 0x0f, - IDE_DEVICE_HEAD_DRV = 0x10, - IDE_DEVICE_HEAD_L = 0x40, - IDE_DEVICE_HEAD_OBSOLETE = 0x80 | 0x20 - }; - - enum - { - TID_BUSY, - TID_BUFFER_EMPTY - }; - - enum - { - PARAM_RESET, - PARAM_DETECT_DEVICE1, - PARAM_DIAGNOSTIC, - PARAM_WAIT_FOR_PDIAG, - PARAM_COMMAND - }; - - attotime MINIMUM_COMMAND_TIME; - - std::vector m_buffer; - uint16_t m_buffer_offset; - uint16_t m_buffer_size; - uint8_t m_error; - uint8_t m_feature; - uint16_t m_sector_count; - uint8_t m_sector_number; - uint8_t m_cylinder_low; - uint8_t m_cylinder_high; - uint8_t m_device_head; - uint8_t m_status; - uint8_t m_command; - uint8_t m_device_control; - - uint16_t m_identify_buffer[256]; - bool m_revert_to_defaults; - bool m_8bit_data_transfers; - -private: - void update_irq(); - void write_buffer_full(); - void start_diagnostic(); - void finished_diagnostic(); - void finished_busy(int param); - bool set_dma_mode(int word); - - int m_csel; - int m_daspin; - int m_daspout; - int m_dmack; - int m_dmarq; - int m_irq; - int m_pdiagin; - int m_pdiagout; - - bool m_single_device; - bool m_resetting; - - emu_timer *m_busy_timer; - emu_timer *m_buffer_empty_timer; -}; - -#endif // MAME_BUS_ATA_ATAHLE_H diff --git a/src/devices/bus/ata/atapicdr.cpp b/src/devices/bus/ata/atapicdr.cpp index 17f26855090..ecf4abd8af8 100644 --- a/src/devices/bus/ata/atapicdr.cpp +++ b/src/devices/bus/ata/atapicdr.cpp @@ -21,6 +21,7 @@ atapi_cdrom_device::atapi_cdrom_device(const machine_config &mconfig, const char atapi_cdrom_device::atapi_cdrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : atapi_hle_device(mconfig, type, tag, owner, clock), + device_ata_interface(mconfig, *this), ultra_dma_mode(0) { } diff --git a/src/devices/bus/ata/atapicdr.h b/src/devices/bus/ata/atapicdr.h index 24e94ea4d8e..459058596e0 100644 --- a/src/devices/bus/ata/atapicdr.h +++ b/src/devices/bus/ata/atapicdr.h @@ -13,10 +13,13 @@ #pragma once +#include "atadev.h" #include "atapihle.h" + #include "machine/t10mmc.h" -class atapi_cdrom_device : public atapi_hle_device, public t10mmc + +class atapi_cdrom_device : public atapi_hle_device, public device_ata_interface, public t10mmc { public: atapi_cdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); @@ -25,6 +28,20 @@ public: uint16_t *identify_device_buffer() { return m_identify_buffer; } + // device_ata_interface implementation + virtual uint16_t read_dma() override { return dma_r(); } + virtual uint16_t read_cs0(offs_t offset, uint16_t mem_mask) override { return command_r(offset); } + virtual uint16_t read_cs1(offs_t offset, uint16_t mem_mask) override { return control_r(offset); } + + virtual void write_dma(uint16_t data) override { dma_w(data); } + virtual void write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask) override { command_w(offset, data); } + virtual void write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask) override { control_w(offset, data); } + + virtual void write_dmack(int state) override { set_dmack_in(state); } + virtual void write_csel(int state) override { set_csel_in(state); } + virtual void write_dasp(int state) override { set_dasp_in(state); } + virtual void write_pdiag(int state) override { set_pdiag_in(state); } + protected: atapi_cdrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); @@ -40,6 +57,13 @@ protected: u32 m_sequence_counter; bool m_media_change; uint16_t ultra_dma_mode; + +private: + // ata_hle_device_base implementation + virtual void set_irq_out(int state) override { device_ata_interface::set_irq(state); } + virtual void set_dmarq_out(int state) override { device_ata_interface::set_dmarq(state); } + virtual void set_dasp_out(int state) override { device_ata_interface::set_dasp(state); } + virtual void set_pdiag_out(int state) override { device_ata_interface::set_pdiag(state); } }; class atapi_fixed_cdrom_device : public atapi_cdrom_device diff --git a/src/devices/bus/ata/atapihle.cpp b/src/devices/bus/ata/atapihle.cpp index b416cdf1e94..8b2f3fd0548 100644 --- a/src/devices/bus/ata/atapihle.cpp +++ b/src/devices/bus/ata/atapihle.cpp @@ -3,8 +3,8 @@ #include "emu.h" #include "atapihle.h" -atapi_hle_device::atapi_hle_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : ata_hle_device(mconfig, type, tag, owner, clock), +atapi_hle_device::atapi_hle_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + ata_hle_device_base(mconfig, type, tag, owner, clock), m_packet(0), m_data_size(0) { @@ -13,13 +13,13 @@ atapi_hle_device::atapi_hle_device(const machine_config &mconfig, device_type ty void atapi_hle_device::device_start() { t10_start(*this); - ata_hle_device::device_start(); + ata_hle_device_base::device_start(); } void atapi_hle_device::device_reset() { t10_reset(); - ata_hle_device::device_reset(); + ata_hle_device_base::device_reset(); } void atapi_hle_device::process_buffer() @@ -257,7 +257,7 @@ void atapi_hle_device::process_command() break; default: - ata_hle_device::process_command(); + ata_hle_device_base::process_command(); break; } } @@ -267,7 +267,7 @@ void atapi_hle_device::finished_command() switch (m_command) { default: - ata_hle_device::finished_command(); + ata_hle_device_base::finished_command(); break; } } diff --git a/src/devices/bus/ata/atapihle.h b/src/devices/bus/ata/atapihle.h index 8d1bb95eec4..80a194afa62 100644 --- a/src/devices/bus/ata/atapihle.h +++ b/src/devices/bus/ata/atapihle.h @@ -13,10 +13,10 @@ #pragma once -#include "atahle.h" +#include "machine/atahle.h" #include "machine/t10spc.h" -class atapi_hle_device : public ata_hle_device, public virtual t10spc +class atapi_hle_device : public ata_hle_device_base, public virtual t10spc { public: enum atapi_features_flag_t diff --git a/src/devices/bus/ata/hdd.cpp b/src/devices/bus/ata/hdd.cpp new file mode 100644 index 00000000000..8eac9aa9163 --- /dev/null +++ b/src/devices/bus/ata/hdd.cpp @@ -0,0 +1,45 @@ +// license:BSD-3-Clause +// copyright-holders:smf +#include "emu.h" +#include "hdd.h" + + +//************************************************************************** +// IDE HARD DISK DEVICE +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(IDE_HARDDISK, ide_hdd_device, "idehd", "IDE Hard Disk") + +//------------------------------------------------- +// ide_hdd_device - constructor +//------------------------------------------------- + +ide_hdd_device::ide_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + ide_hdd_device(mconfig, IDE_HARDDISK, tag, owner, clock) +{ +} + +ide_hdd_device::ide_hdd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + ide_hdd_device_base(mconfig, type, tag, owner, clock), + device_ata_interface(mconfig, *this) +{ +} + + +//************************************************************************** +// ATA COMPACTFLASH CARD DEVICE +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(ATA_CF, ata_cf_device, "atacf", "ATA CompactFlash Card") + +//------------------------------------------------- +// ata_cf_device - constructor +//------------------------------------------------- + +ata_cf_device::ata_cf_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + cf_device_base(mconfig, ATA_CF, tag, owner, clock), + device_ata_interface(mconfig, *this) +{ +} diff --git a/src/devices/bus/ata/hdd.h b/src/devices/bus/ata/hdd.h new file mode 100644 index 00000000000..345b6c77115 --- /dev/null +++ b/src/devices/bus/ata/hdd.h @@ -0,0 +1,92 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + hdd.h + + IDE hard disk on ATA bus + +***************************************************************************/ + +#ifndef MAME_BUS_ATA_IDEHD_H +#define MAME_BUS_ATA_IDEHD_H + +#pragma once + +#include "atadev.h" + +#include "machine/atastorage.h" +#include "imagedev/harddriv.h" + +#include "harddisk.h" + + +// ======================> ide_hdd_device + +class ide_hdd_device : public ide_hdd_device_base, public device_ata_interface +{ +public: + // construction/destruction + ide_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // device_ata_interface implementation + virtual uint16_t read_dma() override { return dma_r(); } + virtual uint16_t read_cs0(offs_t offset, uint16_t mem_mask) override { return command_r(offset); } + virtual uint16_t read_cs1(offs_t offset, uint16_t mem_mask) override { return control_r(offset); } + + virtual void write_dma(uint16_t data) override { dma_w(data); } + virtual void write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask) override { command_w(offset, data); } + virtual void write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask) override { control_w(offset, data); } + + virtual void write_dmack(int state) override { set_dmack_in(state); } + virtual void write_csel(int state) override { set_csel_in(state); } + virtual void write_dasp(int state) override { set_dasp_in(state); } + virtual void write_pdiag(int state) override { set_pdiag_in(state); } + +protected: + ide_hdd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + +private: + // ata_hle_device_base implementation + virtual void set_irq_out(int state) override { device_ata_interface::set_irq(state); } + virtual void set_dmarq_out(int state) override { device_ata_interface::set_dmarq(state); } + virtual void set_dasp_out(int state) override { device_ata_interface::set_dasp(state); } + virtual void set_pdiag_out(int state) override { device_ata_interface::set_pdiag(state); } +}; + + +// ======================> ata_cf_device + +class ata_cf_device : public cf_device_base, public device_ata_interface +{ +public: + // construction/destruction + ata_cf_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // device_ata_interface implementation + virtual uint16_t read_dma() override { return dma_r(); } + virtual uint16_t read_cs0(offs_t offset, uint16_t mem_mask) override { return command_r(offset); } + virtual uint16_t read_cs1(offs_t offset, uint16_t mem_mask) override { return control_r(offset); } + + virtual void write_dma(uint16_t data) override { dma_w(data); } + virtual void write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask) override { command_w(offset, data); } + virtual void write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask) override { control_w(offset, data); } + + virtual void write_dmack(int state) override { set_dmack_in(state); } + virtual void write_csel(int state) override { set_csel_in(state); } + virtual void write_dasp(int state) override { set_dasp_in(state); } + virtual void write_pdiag(int state) override { set_pdiag_in(state); } + +private: + // ata_hle_device_base implementation + virtual void set_irq_out(int state) override { device_ata_interface::set_irq(state); } + virtual void set_dmarq_out(int state) override { device_ata_interface::set_dmarq(state); } + virtual void set_dasp_out(int state) override { device_ata_interface::set_dasp(state); } + virtual void set_pdiag_out(int state) override { device_ata_interface::set_pdiag(state); } +}; + +// device type declaration +DECLARE_DEVICE_TYPE(IDE_HARDDISK, ide_hdd_device) +DECLARE_DEVICE_TYPE(ATA_CF, ata_cf_device) + +#endif // MAME_BUS_ATA_IDEHD_H diff --git a/src/devices/bus/ata/idehd.cpp b/src/devices/bus/ata/idehd.cpp deleted file mode 100644 index 6734bfa82c4..00000000000 --- a/src/devices/bus/ata/idehd.cpp +++ /dev/null @@ -1,953 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:smf -#include "emu.h" -#include "idehd.h" - -/*************************************************************************** - DEBUGGING -***************************************************************************/ - -#define VERBOSE 0 -#define PRINTF_IDE_COMMANDS 0 -#define PRINTF_IDE_PASSWORD 0 - -#define LOGPRINT(x) do { if (VERBOSE) logerror x; if (PRINTF_IDE_COMMANDS) osd_printf_debug x; } while (0) - -#define TIME_PER_SECTOR_WRITE (attotime::from_usec(100)) -#define TIME_PER_ROTATION (attotime::from_hz(5400/60)) -#define TIME_BETWEEN_SECTORS (attotime::from_nsec(400)) - -#define TIME_FULL_STROKE_SEEK (attotime::from_usec(13000)) -#define TIME_AVERAGE_ROTATIONAL_LATENCY (attotime::from_usec(1300)) - -ata_mass_storage_device::ata_mass_storage_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : ata_hle_device(mconfig, type, tag, owner, clock), - m_can_identify_device(0), - m_num_cylinders(0), - m_num_sectors(0), - m_num_heads(0), m_cur_lba(0), m_block_count(0), m_sectors_until_int(0), m_master_password_enable(0), m_user_password_enable(0), - m_master_password(nullptr), - m_user_password(nullptr), - m_dma_transfer_time(attotime::zero) -{ -} - -/************************************* - * - * Compute the LBA address - * - *************************************/ - -uint32_t ata_mass_storage_device::lba_address() -{ - /* LBA direct? */ - if (m_device_head & IDE_DEVICE_HEAD_L) - return ((m_device_head & IDE_DEVICE_HEAD_HS) << 24) | (m_cylinder_high << 16) | (m_cylinder_low << 8) | m_sector_number; - - /* standard CHS */ - else - return (((((m_cylinder_high << 8) | m_cylinder_low) * m_num_heads) + (m_device_head & IDE_DEVICE_HEAD_HS)) * m_num_sectors) + m_sector_number - 1; -} - - -/************************************* - * - * Build a features page - * - *************************************/ - -static void swap_strncpy(uint16_t *dst, const char *src, int field_size_in_words) -{ - for (int i = 0; i < field_size_in_words; i++) - { - uint16_t d; - - if (*src) - { - d = *(src++) << 8; - } - else - { - d = ' ' << 8; - } - - if (*src) - { - d |= *(src++); - } - else - { - d |= ' '; - } - - dst[i] = d; - } - - assert(*(src) == 0); -} - - -void ata_mass_storage_device::ide_build_identify_device() -{ - memset(m_identify_buffer, 0, sizeof(m_identify_buffer)); - int total_sectors = m_num_cylinders * m_num_heads * m_num_sectors; - - /* basic geometry */ - m_identify_buffer[0] = 0x045a; /* 0: configuration bits */ - m_identify_buffer[1] = m_num_cylinders; /* 1: logical cylinders */ - m_identify_buffer[2] = 0; /* 2: reserved */ - m_identify_buffer[3] = m_num_heads; /* 3: logical heads */ - m_identify_buffer[4] = 0; /* 4: vendor specific (obsolete) */ - m_identify_buffer[5] = 0; /* 5: vendor specific (obsolete) */ - m_identify_buffer[6] = m_num_sectors; /* 6: logical sectors per logical track */ - m_identify_buffer[7] = 0; /* 7: vendor-specific */ - m_identify_buffer[8] = 0; /* 8: vendor-specific */ - m_identify_buffer[9] = 0; /* 9: vendor-specific */ - swap_strncpy(&m_identify_buffer[10], /* 10-19: serial number */ - "00000000000000000000", 10); - m_identify_buffer[20] = 0; /* 20: vendor-specific */ - m_identify_buffer[21] = 0; /* 21: vendor-specific */ - m_identify_buffer[22] = 4; /* 22: # of vendor-specific bytes on read/write long commands */ - swap_strncpy(&m_identify_buffer[23], /* 23-26: firmware revision */ - "1.0", 4); - swap_strncpy(&m_identify_buffer[27], /* 27-46: model number */ - "MAME Compressed Hard Disk", 20); - m_identify_buffer[47] = 0x8010; /* 47: read/write multiple support, value from Seagate Quantum Fireball */ - m_identify_buffer[48] = 0; /* 48: reserved */ - m_identify_buffer[49] = 0x0f03; /* 49: capabilities */ - m_identify_buffer[50] = 0; /* 50: reserved */ - m_identify_buffer[51] = 2; /* 51: PIO data transfer cycle timing mode */ - m_identify_buffer[52] = 2; /* 52: single word DMA transfer cycle timing mode */ - m_identify_buffer[53] = 3; /* 53: field validity */ - m_identify_buffer[54] = m_num_cylinders; /* 54: number of current logical cylinders */ - m_identify_buffer[55] = m_num_heads; /* 55: number of current logical heads */ - m_identify_buffer[56] = m_num_sectors; /* 56: number of current logical sectors per track */ - m_identify_buffer[57] = total_sectors & 0xffff; /* 57-58: current capacity in sectors (ATA-1 through ATA-5; obsoleted in ATA-6) */ - m_identify_buffer[58] = total_sectors >> 16; - m_identify_buffer[59] = 0; /* 59: multiple sector timing */ - m_identify_buffer[60] = total_sectors & 0xffff; /* 60-61: total user addressable sectors for LBA mode (ATA-1 through ATA-7) */ - m_identify_buffer[61] = total_sectors >> 16; - m_identify_buffer[62] = 0x0007; /* 62: single word dma transfer */ - m_identify_buffer[63] = 0x0407; /* 63: multiword DMA transfer */ - m_identify_buffer[64] = 0x0003; /* 64: flow control PIO transfer modes supported */ - m_identify_buffer[65] = 0x78; /* 65: minimum multiword DMA transfer cycle time per word */ - m_identify_buffer[66] = 0x78; /* 66: mfr's recommended multiword DMA transfer cycle time */ - m_identify_buffer[67] = 0x014d; /* 67: minimum PIO transfer cycle time without flow control */ - m_identify_buffer[68] = 0x78; /* 68: minimum PIO transfer cycle time with IORDY */ - m_identify_buffer[69] = 0x00; /* 69-70: reserved */ - m_identify_buffer[71] = 0x00; /* 71: reserved for IDENTIFY PACKET command */ - m_identify_buffer[72] = 0x00; /* 72: reserved for IDENTIFY PACKET command */ - m_identify_buffer[73] = 0x00; /* 73: reserved for IDENTIFY PACKET command */ - m_identify_buffer[74] = 0x00; /* 74: reserved for IDENTIFY PACKET command */ - m_identify_buffer[75] = 0x00; /* 75: queue depth */ - m_identify_buffer[76] = 0x00; /* 76-79: reserved */ - m_identify_buffer[80] = 0x00; /* 80: major version number */ - m_identify_buffer[81] = 0x00; /* 81: minor version number */ - m_identify_buffer[82] = 0x00; /* 82: command set supported */ - m_identify_buffer[83] = 0x00; /* 83: command sets supported */ - m_identify_buffer[84] = 0x00; /* 84: command set/feature supported extension */ - m_identify_buffer[85] = 0x00; /* 85: command set/feature enabled */ - m_identify_buffer[86] = 0x00; /* 86: command set/feature enabled */ - m_identify_buffer[87] = 0x00; /* 87: command set/feature default */ - m_identify_buffer[88] = 0x00; /* 88: additional DMA modes (ultra dma) */ - m_identify_buffer[89] = 0x00; /* 89: time required for security erase unit completion */ - m_identify_buffer[90] = 0x00; /* 90: time required for enhanced security erase unit completion */ - m_identify_buffer[91] = 0x00; /* 91: current advanced power management value */ - m_identify_buffer[92] = 0x00; /* 92: master password revision code */ - m_identify_buffer[93] = 0x00; /* 93: hardware reset result */ - m_identify_buffer[94] = 0x00; /* 94: acoustic management values */ - m_identify_buffer[95] = 0x00; /* 95-99: reserved */ - m_identify_buffer[100] = total_sectors & 0xffff; /* 100-103: maximum 48-bit LBA */ - m_identify_buffer[101] = total_sectors >> 16; - m_identify_buffer[102] = 0x00; - m_identify_buffer[103] = 0x00; - m_identify_buffer[104] = 0x00; /* 104-126: reserved */ - m_identify_buffer[127] = 0x00; /* 127: removable media status notification */ - m_identify_buffer[128] = 0x00; /* 128: security status */ - m_identify_buffer[129] = 0x00; /* 129-159: vendor specific */ - m_identify_buffer[160] = 0x00; /* 160: CFA power mode 1 */ - m_identify_buffer[161] = 0x00; /* 161-175: reserved for CompactFlash */ - m_identify_buffer[176] = 0x00; /* 176-205: current media serial number */ - m_identify_buffer[206] = 0x00; /* 206-254: reserved */ - m_identify_buffer[255] = 0x00; /* 255: integrity word */ - - if (total_sectors >= 16514064) - { - /// CHS limit - m_identify_buffer[1] = 16383; /* 1: logical cylinders */ - m_identify_buffer[3] = 16; /* 3: logical heads */ - m_identify_buffer[6] = 63; /* 6: logical sectors per logical track */ - m_identify_buffer[54] = 16383; /* 54: number of current logical cylinders */ - m_identify_buffer[55] = 16; /* 55: number of current logical heads */ - m_identify_buffer[56] = 63; /* 56: number of current logical sectors per track */ - m_identify_buffer[57] = 16514064 & 0xffff; /* 57-58: current capacity in sectors (ATA-1 through ATA-5; obsoleted in ATA-6) */ - m_identify_buffer[58] = 16514064 >> 16; - } - - if (total_sectors > 268435455) - { - /// LBA limit - m_identify_buffer[60] = 268435455 & 0xffff; /* 60-61: total user addressable sectors for LBA mode (ATA-1 through ATA-7) */ - m_identify_buffer[61] = 268435455 >> 16; - } -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void ata_mass_storage_device::device_start() -{ - ata_hle_device::device_start(); - - save_item(NAME(m_can_identify_device)); - save_item(NAME(m_num_cylinders)); - save_item(NAME(m_num_sectors)); - save_item(NAME(m_num_heads)); - - save_item(NAME(m_cur_lba)); - save_item(NAME(m_sectors_until_int)); - save_item(NAME(m_master_password_enable)); - save_item(NAME(m_user_password_enable)); - save_item(NAME(m_block_count)); -} - -void ata_mass_storage_device::soft_reset() -{ - ata_hle_device::soft_reset(); - - m_cur_lba = 0; - m_status |= IDE_STATUS_DSC; - - m_master_password_enable = (m_master_password != nullptr); - m_user_password_enable = (m_user_password != nullptr); -} - -void ata_mass_storage_device::perform_diagnostic() -{ - if (m_can_identify_device) - m_error = IDE_ERROR_DIAGNOSTIC_PASSED; -} - -void ata_mass_storage_device::signature() -{ - m_sector_count = 1; - m_sector_number = 1; - m_cylinder_low = 0; - m_cylinder_high = 0; - m_device_head = 0; -} - -void ata_mass_storage_device::finished_command() -{ - int total_sectors = m_num_cylinders * m_num_heads * m_num_sectors; - - switch (m_command) - { - case IDE_COMMAND_IDENTIFY_DEVICE: - if (m_can_identify_device) - { - for( int w = 0; w < 256; w++ ) - { - m_buffer[w * 2] = m_identify_buffer[ w ] & 0xff; - m_buffer[(w * 2) + 1] = m_identify_buffer[ w ] >> 8; - } - - 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: - finished_read(); - break; - - case IDE_COMMAND_WRITE_SECTORS: - case IDE_COMMAND_WRITE_SECTORS_NORETRY: - case IDE_COMMAND_WRITE_MULTIPLE: - case IDE_COMMAND_WRITE_DMA: - finished_write(); - break; - - case IDE_COMMAND_RECALIBRATE: - set_irq(ASSERT_LINE); - break; - - case IDE_COMMAND_READ_NATIVE_MAX_ADDRESS: - m_buffer[0] = (total_sectors & 0xff000000) >> 24; - m_buffer[1] = (total_sectors & 0x00ff0000) >> 16; - m_buffer[2] = (total_sectors & 0x0000ff00) >> 8; - m_buffer[3] = (total_sectors & 0x000000ff); - set_irq(ASSERT_LINE); - break; - - default: - ata_hle_device::finished_command(); - break; - } -} - -/************************************* - * - * Advance to the next sector - * - *************************************/ - -void ata_mass_storage_device::next_sector() -{ - uint8_t cur_head = m_device_head & IDE_DEVICE_HEAD_HS; - - /* LBA direct? */ - if (m_device_head & IDE_DEVICE_HEAD_L) - { - m_sector_number++; - if (m_sector_number == 0) - { - m_cylinder_low++; - if (m_cylinder_low == 0) - { - m_cylinder_high++; - if (m_cylinder_high == 0) - cur_head++; - } - } - } - - /* standard CHS */ - else - { - /* sectors are 1-based */ - m_sector_number++; - if (m_sector_number > m_num_sectors) - { - /* heads are 0 based */ - m_sector_number = 1; - cur_head++; - if (cur_head >= m_num_heads) - { - cur_head = 0; - m_cylinder_low++; - if (m_cylinder_low == 0) - m_cylinder_high++; - } - } - } - - m_device_head = (m_device_head & ~IDE_DEVICE_HEAD_HS) | cur_head; - - m_cur_lba = lba_address(); -} - - - -/************************************* - * - * security error handling - * - *************************************/ - -void ata_mass_storage_device::security_error() -{ - /* set error state */ - m_status |= IDE_STATUS_ERR; - m_error = IDE_ERROR_NONE; - m_status &= ~IDE_STATUS_DRDY; -} - - - -/************************************* - * - * Sector reading - * - *************************************/ - -attotime ata_mass_storage_device::seek_time() -{ - int sectors_per_cylinder = m_num_heads * m_num_sectors; - - if (sectors_per_cylinder == 0 || m_num_cylinders == 0) - return attotime::zero; - - int new_lba = lba_address(); - int old_cylinder = m_cur_lba / sectors_per_cylinder; - int new_cylinder = new_lba / sectors_per_cylinder; - int diff = abs(old_cylinder - new_cylinder); - - m_cur_lba = new_lba; - - if (diff == 0) - return TIME_BETWEEN_SECTORS; - - attotime seek_time = (TIME_FULL_STROKE_SEEK * diff) / m_num_cylinders; - - return seek_time + TIME_AVERAGE_ROTATIONAL_LATENCY; -} - -void ata_mass_storage_device::fill_buffer() -{ - switch (m_command) - { - case IDE_COMMAND_IDENTIFY_DEVICE: - break; - - case IDE_COMMAND_READ_MULTIPLE: - /* if there is more data to read, keep going */ - if (m_sector_count > 0) - m_sector_count--; - - if (m_sector_count > 0) - { - // Read the next sector with no delay - finished_read(); - } - break; - - default: - /* if there is more data to read, keep going */ - if (m_sector_count > 0) - m_sector_count--; - - if (m_sector_count > 0) - { - set_dasp(ASSERT_LINE); - if (m_command == IDE_COMMAND_READ_DMA) - start_busy(TIME_BETWEEN_SECTORS + m_dma_transfer_time, PARAM_COMMAND); - else - start_busy(TIME_BETWEEN_SECTORS, PARAM_COMMAND); - } - break; - } -} - - -void ata_mass_storage_device::finished_read() -{ - int lba = lba_address(), read_status; - - set_dasp(CLEAR_LINE); - - /* now do the read */ - read_status = read_sector(lba, &m_buffer[0]); - - /* if we succeeded, advance to the next sector and set the nice bits */ - if (read_status) - { - /* advance the pointers, unless this is the last sector */ - /* Gauntlet: Dark Legacy checks to make sure we stop on the last sector */ - if (m_sector_count != 1) - next_sector(); - - /* signal an interrupt, IDE_COMMAND_READ_MULTIPLE sets the interrupt at the start the block */ - if (--m_sectors_until_int == 0 || (m_sector_count == 1 && m_command != IDE_COMMAND_READ_MULTIPLE)) - { - m_sectors_until_int = ((m_command == IDE_COMMAND_READ_MULTIPLE) ? m_block_count : 1); - set_irq(ASSERT_LINE); - } - - /* if we're just verifying we can read the next sector */ - if (m_command == IDE_COMMAND_VERIFY_SECTORS || - m_command == IDE_COMMAND_VERIFY_SECTORS_NORETRY ) - { - read_buffer_empty(); - } - else - { - m_status |= IDE_STATUS_DRQ; - - if (m_command == IDE_COMMAND_READ_DMA) - set_dmarq(ASSERT_LINE); - } - } - - /* if we got an error, we need to report it */ - else - { - /* set the error flag and the error */ - m_status |= IDE_STATUS_ERR; - m_error = IDE_ERROR_BAD_SECTOR; - - /* signal an interrupt */ - set_irq(ASSERT_LINE); - } -} - - -void ata_mass_storage_device::read_first_sector() -{ - if (m_master_password_enable || m_user_password_enable) - { - security_error(); - } - else - { - set_dasp(ASSERT_LINE); - - start_busy(seek_time(), PARAM_COMMAND); - } -} - -/************************************* - * - * Sector writing - * - *************************************/ - -void ata_mass_storage_device::process_buffer() -{ - if (m_command == IDE_COMMAND_SECURITY_UNLOCK) - { - if (m_user_password_enable && memcmp(&m_buffer[0], m_user_password, 2 + 32) == 0) - { - LOGPRINT(("IDE Unlocked user password\n")); - m_user_password_enable = 0; - } - if (m_master_password_enable && memcmp(&m_buffer[0], m_master_password, 2 + 32) == 0) - { - LOGPRINT(("IDE Unlocked master password\n")); - m_master_password_enable = 0; - } - if (PRINTF_IDE_PASSWORD) - { - int i; - - for (i = 0; i < 34; i += 2) - { - if (i % 8 == 2) - osd_printf_debug("\n"); - - osd_printf_debug("0x%02x, 0x%02x, ", m_buffer[i], m_buffer[i + 1]); - //osd_printf_debug("0x%02x%02x, ", m_buffer[i], m_buffer[i + 1]); - } - osd_printf_debug("\n"); - } - - if (m_master_password_enable || m_user_password_enable) - security_error(); - } - else if (m_command == IDE_COMMAND_SECURITY_DISABLE_PASSWORD) - { - LOGPRINT(("IDE Done unimplemented SECURITY_DISABLE_PASSWORD command\n")); - } - else - { - set_dasp(ASSERT_LINE); - - if (m_command == IDE_COMMAND_WRITE_MULTIPLE) - { - if (m_sectors_until_int != 1) - { - /* ready to write now */ - finished_write(); - } - else - { - /* set a timer to do the write */ - start_busy(TIME_PER_SECTOR_WRITE, PARAM_COMMAND); - } - } - else - { - /* set a timer to do the write */ - start_busy(TIME_PER_SECTOR_WRITE, PARAM_COMMAND); - } - } -} - - -void ata_mass_storage_device::finished_write() -{ - int lba = lba_address(), count; - - set_dasp(CLEAR_LINE); - - /* now do the write */ - count = write_sector(lba, &m_buffer[0]); - - /* if we succeeded, advance to the next sector and set the nice bits */ - if (count == 1) - { - /* advance the pointers, unless this is the last sector */ - /* Gauntlet: Dark Legacy checks to make sure we stop on the last sector */ - if (m_sector_count != 1) - next_sector(); - - /* signal an interrupt */ - if (--m_sectors_until_int == 0 || m_sector_count == 1) - { - m_sectors_until_int = ((m_command == IDE_COMMAND_WRITE_MULTIPLE) ? m_block_count : 1); - set_irq(ASSERT_LINE); - } - - /* signal an interrupt if there's more data needed */ - if (m_sector_count > 0) - m_sector_count--; - - if (m_sector_count > 0) - { - m_status |= IDE_STATUS_DRQ; - - if (m_command == IDE_COMMAND_WRITE_DMA) - set_dmarq(ASSERT_LINE); - } - } - - /* if we got an error, we need to report it */ - else - { - /* set the error flag and the error */ - m_status |= IDE_STATUS_ERR; - m_error = IDE_ERROR_BAD_SECTOR; - - /* signal an interrupt */ - set_irq(ASSERT_LINE); - } -} - - -/************************************* - * - * Handle IDE commands - * - *************************************/ - -void ata_mass_storage_device::process_command() -{ - m_sectors_until_int = 0; - m_buffer_size = IDE_DISK_SECTOR_SIZE; - - switch (m_command) - { - case IDE_COMMAND_READ_SECTORS: - case IDE_COMMAND_READ_SECTORS_NORETRY: - LOGPRINT(("IDE Read multiple: C=%u H=%d S=%u LBA=%u count=%u\n", - (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count)); - - m_sectors_until_int = 1; - - /* start the read going */ - read_first_sector(); - break; - - case IDE_COMMAND_READ_MULTIPLE: - LOGPRINT(("IDE Read multiple block: C=%u H=%u S=%u LBA=%u count=%u\n", - (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count)); - - m_sectors_until_int = 1; - - /* start the read going */ - read_first_sector(); - break; - - case IDE_COMMAND_VERIFY_SECTORS: - case IDE_COMMAND_VERIFY_SECTORS_NORETRY: - LOGPRINT(("IDE Read verify multiple with/without retries: C=%u H=%u S=%u LBA=%u count=%u\n", - (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count)); - - /* reset the buffer */ - m_sectors_until_int = m_sector_count; - - /* start the read going */ - read_first_sector(); - break; - - case IDE_COMMAND_READ_DMA: - LOGPRINT(("IDE Read multiple DMA: C=%u H=%u S=%u LBA=%u count=%u\n", - (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count)); - - /* reset the buffer */ - m_sectors_until_int = m_sector_count; - - /* start the read going */ - read_first_sector(); - break; - - case IDE_COMMAND_WRITE_SECTORS: - case IDE_COMMAND_WRITE_SECTORS_NORETRY: - LOGPRINT(("IDE Write multiple: C=%u H=%u S=%u LBA=%u count=%u\n", - (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count)); - - /* reset the buffer */ - m_sectors_until_int = 1; - - /* mark the buffer ready */ - m_status |= IDE_STATUS_DRQ; - break; - - case IDE_COMMAND_WRITE_MULTIPLE: - LOGPRINT(("IDE Write multiple block: C=%u H=%u S=%u LBA=%u count=%u\n", - (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count)); - - /* reset the buffer */ - m_sectors_until_int = m_block_count; - - /* mark the buffer ready */ - m_status |= IDE_STATUS_DRQ; - break; - - case IDE_COMMAND_WRITE_DMA: - LOGPRINT(("IDE Write multiple DMA: C=%u H=%u S=%u LBA=%u count=%u\n", - (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count)); - - /* reset the buffer */ - m_sectors_until_int = m_sector_count; - - /* mark the buffer ready */ - m_status |= IDE_STATUS_DRQ; - - /* start the read going */ - set_dmarq(ASSERT_LINE); - break; - - case IDE_COMMAND_SECURITY_UNLOCK: - LOGPRINT(("IDE Security Unlock\n")); - - /* mark the buffer ready */ - m_status |= IDE_STATUS_DRQ; - - set_irq(ASSERT_LINE); - break; - - case IDE_COMMAND_SECURITY_DISABLE_PASSWORD: - LOGPRINT(("IDE Unimplemented SECURITY DISABLE PASSWORD command\n")); - - /* mark the buffer ready */ - m_status |= IDE_STATUS_DRQ; - - set_irq(ASSERT_LINE); - break; - - case IDE_COMMAND_IDENTIFY_DEVICE: - LOGPRINT(("IDE Identify device\n")); - - start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); - break; - - case IDE_COMMAND_RECALIBRATE: - start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); - break; - - case IDE_COMMAND_IDLE: - /* signal an interrupt */ - set_irq(ASSERT_LINE); - break; - - case IDE_COMMAND_SET_CONFIG: - LOGPRINT(("IDE Set configuration (%u heads, %u sectors)\n", (m_device_head & IDE_DEVICE_HEAD_HS) + 1, m_sector_count)); - - start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); - break; - - case IDE_COMMAND_SET_MAX: - LOGPRINT(("IDE Set max (%02X %02X %02X %02X %02X)\n", m_feature, m_sector_count & 0xff, m_sector_number, m_cylinder_low, m_cylinder_high)); - - /* signal an interrupt */ - set_irq(ASSERT_LINE); - break; - - case IDE_COMMAND_SET_BLOCK_COUNT: - LOGPRINT(("IDE Set block count (%u)\n", m_sector_count)); - - m_block_count = m_sector_count; - - /* signal an interrupt */ - set_irq(ASSERT_LINE); - break; - - case IDE_COMMAND_SEEK: - /* signal an interrupt */ - set_irq(ASSERT_LINE); - break; - - case IDE_COMMAND_READ_NATIVE_MAX_ADDRESS: - start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); - break; - - default: - ata_hle_device::process_command(); - break; - } -} - -//************************************************************************** -// IDE HARD DISK DEVICE -//************************************************************************** - -// device type definition -DEFINE_DEVICE_TYPE(IDE_HARDDISK, ide_hdd_device, "idehd", "IDE Hard Disk") - -//------------------------------------------------- -// ide_hdd_device - constructor -//------------------------------------------------- - -ide_hdd_device::ide_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ide_hdd_device(mconfig, IDE_HARDDISK, tag, owner, clock) -{ -} - -ide_hdd_device::ide_hdd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : ata_mass_storage_device(mconfig, type, tag, owner, clock), - m_image(*this, "image") -{ -} - -void ide_hdd_device::device_start() -{ - ata_mass_storage_device::device_start(); - - /* create a timer for timing status */ - m_last_status_timer = machine().scheduler().timer_alloc(timer_expired_delegate()); -} - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void ide_hdd_device::device_reset() -{ - if (m_image->exists() && !m_can_identify_device) - { - const auto &hdinfo = m_image->get_info(); - if (hdinfo.sectorbytes == IDE_DISK_SECTOR_SIZE) - { - m_num_cylinders = hdinfo.cylinders; - m_num_sectors = hdinfo.sectors; - m_num_heads = hdinfo.heads; - if (PRINTF_IDE_COMMANDS) osd_printf_debug("CHS: %u %u %u\n", m_num_cylinders, m_num_heads, m_num_sectors); - osd_printf_debug("CHS: %u %u %u\n", m_num_cylinders, m_num_heads, m_num_sectors); - } - - // build the features page - std::vector ident; - m_image->get_inquiry_data(ident); - if (ident.size() == 512) - { - for( int w = 0; w < 256; w++ ) - { - m_identify_buffer[w] = (ident[(w * 2) + 1] << 8) | ident[w * 2]; - } - } - else - { - ide_build_identify_device(); - } - - m_can_identify_device = 1; - } - - ata_mass_storage_device::device_reset(); -} - -uint8_t ide_hdd_device::calculate_status() -{ - uint8_t result = ata_hle_device::calculate_status(); - - if (m_last_status_timer->elapsed() > TIME_PER_ROTATION) - { - result |= IDE_STATUS_IDX; - m_last_status_timer->adjust(attotime::never); - } - - return result; -} - -//------------------------------------------------- -// device_add_mconfig - add device configuration -//------------------------------------------------- - -void ide_hdd_device::device_add_mconfig(machine_config &config) -{ - HARDDISK(config, "image", "ide_hdd"); -} - -//************************************************************************** -// ATA COMPACTFLASH CARD DEVICE -//************************************************************************** - -// device type definition -DEFINE_DEVICE_TYPE(ATA_CF, ide_cf_device, "atacf", "ATA CompactFlash Card") - -//------------------------------------------------- -// ide_cf_device - constructor -//------------------------------------------------- - -ide_cf_device::ide_cf_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ide_hdd_device(mconfig, ATA_CF, tag, owner, clock) -{ -} - -//------------------------------------------------- -// device_add_mconfig - add device configuration -//------------------------------------------------- - -void ide_cf_device::device_add_mconfig(machine_config &config) -{ - HARDDISK(config, "image", "ata_cf"); -} - -//------------------------------------------------- -// ide_build_identify_device -//------------------------------------------------- - -void ide_cf_device::ide_build_identify_device() -{ - memset(m_identify_buffer, 0, sizeof(m_identify_buffer)); - int total_sectors = m_num_cylinders * m_num_heads * m_num_sectors; - - /* basic geometry */ - m_identify_buffer[0] = 0x848a; /* 0: configuration bits */ - m_identify_buffer[1] = m_num_cylinders; /* 1: logical cylinders */ - m_identify_buffer[2] = 0; /* 2: reserved */ - m_identify_buffer[3] = m_num_heads; /* 3: logical heads */ - m_identify_buffer[4] = 0; /* 4: number of unformatted bytes per track */ - m_identify_buffer[5] = 0; /* 5: number of unformatted bytes per sector */ - m_identify_buffer[6] = m_num_sectors; /* 6: logical sectors per logical track */ - m_identify_buffer[7] = total_sectors >> 16; /* 7: number of sectors per card MSW */ - m_identify_buffer[8] = total_sectors & 0xffff; /* 8: number of sectors per card LSW */ - m_identify_buffer[9] = 0; /* 9: vendor-specific */ - swap_strncpy(&m_identify_buffer[10], /* 10-19: serial number */ - "00000000000000000000", 10); - m_identify_buffer[20] = 0; /* 20: buffer type */ - m_identify_buffer[21] = 0; /* 21: buffer size in 512 byte increments */ - m_identify_buffer[22] = 4; /* 22: # of vendor-specific bytes on read/write long commands */ - swap_strncpy(&m_identify_buffer[23], /* 23-26: firmware revision */ - "1.0", 4); - swap_strncpy(&m_identify_buffer[27], /* 27-46: model number */ - "MAME Compressed CompactFlash", 20); - m_identify_buffer[47] = 0x0001; /* 47: read/write multiple support */ - m_identify_buffer[48] = 0; /* 48: double word not supported */ - m_identify_buffer[49] = 0x0200; /* 49: capabilities */ - m_identify_buffer[50] = 0; /* 50: reserved */ - m_identify_buffer[51] = 0x0200; /* 51: PIO data transfer cycle timing mode */ - m_identify_buffer[52] = 0x0000; /* 52: single word DMA transfer cycle timing mode */ - m_identify_buffer[53] = 0x0003; /* 53: translation parameters are valid */ - m_identify_buffer[54] = m_num_cylinders; /* 54: number of current logical cylinders */ - m_identify_buffer[55] = m_num_heads; /* 55: number of current logical heads */ - m_identify_buffer[56] = m_num_sectors; /* 56: number of current logical sectors per track */ - m_identify_buffer[57] = total_sectors & 0xffff; /* 57-58: current capacity in sectors */ - m_identify_buffer[58] = total_sectors >> 16; - m_identify_buffer[59] = 0; /* 59: multiple sector timing */ - m_identify_buffer[60] = total_sectors & 0xffff; /* 60-61: total user addressable sectors for LBA mode */ - m_identify_buffer[61] = total_sectors >> 16; - m_identify_buffer[62] = 0x00; /* 62-127: reserved */ - m_identify_buffer[128] = 0x00; /* 128: security status */ - m_identify_buffer[129] = 0x00; /* 129-159: vendor specific */ - m_identify_buffer[160] = 0x00; /* 160: Power requirement description*/ - m_identify_buffer[161] = 0x00; /* 161-255: reserved */ -} diff --git a/src/devices/bus/ata/idehd.h b/src/devices/bus/ata/idehd.h deleted file mode 100644 index 1a6342ea6d9..00000000000 --- a/src/devices/bus/ata/idehd.h +++ /dev/null @@ -1,139 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:smf -/*************************************************************************** - - idehd.h - - IDE Harddisk - -***************************************************************************/ - -#ifndef MAME_BUS_ATA_IDEHD_H -#define MAME_BUS_ATA_IDEHD_H - -#pragma once - -#include "atahle.h" -#include "harddisk.h" -#include "imagedev/harddriv.h" - -class ata_mass_storage_device : public ata_hle_device -{ -public: - uint16_t *identify_device_buffer() { return m_identify_buffer; } - - void set_master_password(const uint8_t *password) - { - m_master_password = password; - m_master_password_enable = (password != nullptr); - } - - void set_user_password(const uint8_t *password) - { - m_user_password = password; - m_user_password_enable = (password != nullptr); - } - - void set_dma_transfer_time(const attotime time) { m_dma_transfer_time = time; } -protected: - ata_mass_storage_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - - virtual int read_sector(uint32_t lba, void *buffer) = 0; - virtual int write_sector(uint32_t lba, const void *buffer) = 0; - virtual attotime seek_time(); - - virtual void ide_build_identify_device(); - - static const int IDE_DISK_SECTOR_SIZE = 512; - virtual int sector_length() override { return IDE_DISK_SECTOR_SIZE; } - virtual void process_buffer() override; - virtual void fill_buffer() override; - virtual bool is_ready() override { return true; } - virtual void process_command() override; - virtual void finished_command() override; - virtual void perform_diagnostic() override; - virtual void signature() override; - - int m_can_identify_device; - uint16_t m_num_cylinders; - uint8_t m_num_sectors; - uint8_t m_num_heads; - - virtual uint32_t lba_address(); - -private: - void set_geometry(uint8_t sectors, uint8_t heads) { m_num_sectors = sectors; m_num_heads = heads; } - void finished_read(); - void finished_write(); - void next_sector(); - void security_error(); - void read_first_sector(); - void soft_reset() override; - - uint32_t m_cur_lba; - uint16_t m_block_count; - uint16_t m_sectors_until_int; - - uint8_t m_master_password_enable; - uint8_t m_user_password_enable; - const uint8_t * m_master_password; - const uint8_t * m_user_password; - // DMA data transfer time for 1 sector - attotime m_dma_transfer_time; -}; - -// ======================> ide_hdd_device - -class ide_hdd_device : public ata_mass_storage_device -{ -public: - // construction/destruction - ide_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -protected: - ide_hdd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - - // optional information overrides - virtual void device_add_mconfig(machine_config &config) override; - - virtual int read_sector(uint32_t lba, void *buffer) override { return !m_image->exists() ? 0 : m_image->read(lba, buffer); } - virtual int write_sector(uint32_t lba, const void *buffer) override { return !m_image->exists() ? 0 : m_image->write(lba, buffer); } - virtual uint8_t calculate_status() override; - - enum - { - TID_NULL = TID_BUSY + 1 - }; - - required_device m_image; - -private: - emu_timer * m_last_status_timer; -}; - -// ======================> ide_cf_device - -class ide_cf_device : public ide_hdd_device -{ -public: - // construction/destruction - ide_cf_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -protected: - // optional information overrides - virtual void device_add_mconfig(machine_config &config) override; - - void ide_build_identify_device() override; -}; - -// device type definition -DECLARE_DEVICE_TYPE(IDE_HARDDISK, ide_hdd_device) -DECLARE_DEVICE_TYPE(ATA_CF, ide_cf_device) - -#endif // MAME_BUS_ATA_IDEHD_H diff --git a/src/devices/bus/epson_qx/ide.cpp b/src/devices/bus/epson_qx/ide.cpp index 80c613bf87d..7d709f442dc 100644 --- a/src/devices/bus/epson_qx/ide.cpp +++ b/src/devices/bus/epson_qx/ide.cpp @@ -41,9 +41,8 @@ INPUT_PORTS_END // ide_device - constructor //------------------------------------------------- ide_device::ide_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, EPSON_QX_OPTION_IDE, tag, owner, clock), + ide_hdd_device_base(mconfig, EPSON_QX_OPTION_IDE, tag, owner, clock), device_option_expansion_interface(mconfig, *this), - m_hdd(*this, "hdd"), m_iobase(*this, "IOBASE"), m_installed(false) { @@ -57,19 +56,13 @@ ioport_constructor ide_device::device_input_ports() const return INPUT_PORTS_NAME( ide ); } -//------------------------------------------------- -// device_add_mconfig - device-specific config -//------------------------------------------------- -void ide_device::device_add_mconfig(machine_config &config) -{ - IDE_HARDDISK(config, m_hdd, 0); -} - //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void ide_device::device_start() { + ide_hdd_device_base::device_start(); + m_installed = false; save_item(NAME(m_installed)); @@ -80,6 +73,8 @@ void ide_device::device_start() //------------------------------------------------- void ide_device::device_reset() { + ide_hdd_device_base::device_reset(); + if (!m_installed) { address_space &space = m_bus->iospace(); offs_t iobase = m_iobase->read() & 0xf0; @@ -91,9 +86,9 @@ void ide_device::device_reset() uint8_t ide_device::read(offs_t offset) { if (offset < 8) { - return m_hdd->read_cs0(offset); + return command_r(offset); } else if (offset == 14 || offset == 15) { - return m_hdd->read_cs1(offset & 7); + return control_r(offset & 7); } return 0xff; } @@ -101,9 +96,9 @@ uint8_t ide_device::read(offs_t offset) void ide_device::write(offs_t offset, uint8_t data) { if (offset < 8) { - m_hdd->write_cs0(offset, data); + command_w(offset, data); } else if (offset == 14) { - m_hdd->write_cs1(offset & 7, data); + control_w(offset & 7, data); } } diff --git a/src/devices/bus/epson_qx/ide.h b/src/devices/bus/epson_qx/ide.h index 3bc61b333ca..19c8f2a3a5d 100644 --- a/src/devices/bus/epson_qx/ide.h +++ b/src/devices/bus/epson_qx/ide.h @@ -13,7 +13,7 @@ #include "option.h" -#include "bus/ata/idehd.h" +#include "machine/atastorage.h" namespace bus::epson_qx { @@ -23,19 +23,17 @@ namespace bus::epson_qx { /* Epson IDE Device */ -class ide_device : public device_t, public bus::epson_qx::device_option_expansion_interface +// TODO: this thing should probably implement the ATA controller interface rather than having an IDE hard disk with no slot +class ide_device : public ide_hdd_device_base, public device_option_expansion_interface { public: // construction/destruction ide_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); protected: - // device-level overrides + // device_t implementation virtual void device_start() override; virtual void device_reset() override; - - // optional information overrides - virtual void device_add_mconfig(machine_config &config) override; virtual ioport_constructor device_input_ports() const override; uint8_t read(offs_t offset); @@ -44,7 +42,12 @@ protected: void map(address_map &map); private: - required_device m_hdd; + // ata_hle_device_base implementation + virtual void set_irq_out(int state) override { } + virtual void set_dmarq_out(int state) override { } + virtual void set_dasp_out(int state) override { } + virtual void set_pdiag_out(int state) override { } + required_ioport m_iobase; bool m_installed; diff --git a/src/devices/machine/ataflash.cpp b/src/devices/machine/ataflash.cpp index 2cf2428db31..7846ce9a888 100644 --- a/src/devices/machine/ataflash.cpp +++ b/src/devices/machine/ataflash.cpp @@ -11,14 +11,14 @@ ata_flash_pccard_device::ata_flash_pccard_device(const machine_config &mconfig, } ata_flash_pccard_device::ata_flash_pccard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : ide_hdd_device(mconfig, type, tag, owner, clock) + : ide_hdd_device_base(mconfig, type, tag, owner, clock) , device_pccard_interface(mconfig, *this) { } void ata_flash_pccard_device::device_reset() { - ide_hdd_device::device_reset(); + ide_hdd_device_base::device_reset(); if (m_image->exists()) { @@ -36,11 +36,11 @@ uint16_t ata_flash_pccard_device::read_memory(offs_t offset, uint16_t mem_mask) if(offset <= 7) { m_8bit_data_transfers = !ACCESSING_BITS_8_15; // HACK - return read_cs0(offset, mem_mask); + return command_r(offset); } else if(offset <= 15) { - return read_cs1(offset & 7, mem_mask); + return control_r(offset & 7); } else { @@ -53,11 +53,11 @@ void ata_flash_pccard_device::write_memory(offs_t offset, uint16_t data, uint16_ if(offset <= 7) { m_8bit_data_transfers = !ACCESSING_BITS_8_15; // HACK - write_cs0(offset, data, mem_mask); + command_w(offset, data); } else if( offset <= 15) { - write_cs1(offset & 7, data, mem_mask); + control_w(offset & 7, data); } } diff --git a/src/devices/machine/ataflash.h b/src/devices/machine/ataflash.h index c9e3cbbf991..acf37a283d5 100644 --- a/src/devices/machine/ataflash.h +++ b/src/devices/machine/ataflash.h @@ -6,11 +6,11 @@ #pragma once #include "pccard.h" -#include "bus/ata/idehd.h" +#include "atastorage.h" DECLARE_DEVICE_TYPE(ATA_FLASH_PCCARD, ata_flash_pccard_device) -class ata_flash_pccard_device : public ide_hdd_device, public device_pccard_interface +class ata_flash_pccard_device : public ide_hdd_device_base, public device_pccard_interface { public: ata_flash_pccard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); @@ -23,13 +23,19 @@ public: protected: ata_flash_pccard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - // device-level overrides + // device_t implementation virtual void device_reset() override; virtual attotime seek_time() override; - uint8_t calculate_status() override { return ata_hle_device::calculate_status(); } + uint8_t calculate_status() override { return ata_hle_device_base::calculate_status(); } private: + // ata_hle_device_base implementation + virtual void set_irq_out(int state) override { } + virtual void set_dmarq_out(int state) override { } + virtual void set_dasp_out(int state) override { } + virtual void set_pdiag_out(int state) override { } + std::vector m_cis; uint8_t m_configuration_option; uint8_t m_configuration_and_status; diff --git a/src/devices/machine/atahle.cpp b/src/devices/machine/atahle.cpp new file mode 100644 index 00000000000..85b9ad958fe --- /dev/null +++ b/src/devices/machine/atahle.cpp @@ -0,0 +1,915 @@ +// license:BSD-3-Clause +// copyright-holders:smf +#include "emu.h" +#include "atahle.h" + +#define VERBOSE 0 +#define PRINTF_IDE_COMMANDS 0 + +#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) + +enum +{ + IDE_CS0_DATA_RW = 0, + IDE_CS0_ERROR_R = 1, + IDE_CS0_FEATURE_W = 1, + IDE_CS0_SECTOR_COUNT_RW = 2, + IDE_CS0_SECTOR_NUMBER_RW = 3, + IDE_CS0_CYLINDER_LOW_RW = 4, + IDE_CS0_CYLINDER_HIGH_RW = 5, + IDE_CS0_DEVICE_HEAD_RW = 6, + IDE_CS0_STATUS_R = 7, + IDE_CS0_COMMAND_W = 7 +}; + +enum +{ + IDE_CS1_ALTERNATE_STATUS_R = 6, + IDE_CS1_DEVICE_CONTROL_W = 6, + IDE_CS1_ACTIVE_STATUS = 7 +}; + +enum +{ + IDE_DEVICE_CONTROL_NIEN = 0x02, + IDE_DEVICE_CONTROL_SRST = 0x04 +}; + +#define DETECT_DEVICE1_TIME (attotime::from_msec(2)) +#define DEVICE1_PDIAG_TIME (attotime::from_msec(2)) +#define DIAGNOSTIC_TIME (attotime::from_msec(2)) + +ata_hle_device_base::ata_hle_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + m_buffer_offset(0), + m_buffer_size(0), + m_error(0), + m_feature(0), + m_sector_count(0), + m_sector_number(0), + m_cylinder_low(0), + m_cylinder_high(0), + m_device_head(0), + m_status(0), + m_command(0), + m_device_control(0), + m_revert_to_defaults(true), + m_8bit_data_transfers(false), + m_csel(0), + m_daspin(0), + m_daspout(0), + m_dmack(0), + m_dmarq(0), + m_irq(0), + m_pdiagin(0), + m_pdiagout(0), + m_single_device(0), + m_resetting(0), m_busy_timer(nullptr), m_buffer_empty_timer(nullptr) +{ +} + +void ata_hle_device_base::device_start() +{ + MINIMUM_COMMAND_TIME = attotime::from_usec(10); + + m_buffer.resize(sector_length()); + save_item(NAME(m_buffer)); + save_item(NAME(m_buffer_offset)); + save_item(NAME(m_buffer_size)); + save_item(NAME(m_error)); + save_item(NAME(m_feature)); + save_item(NAME(m_sector_count)); + save_item(NAME(m_sector_number)); + save_item(NAME(m_cylinder_low)); + save_item(NAME(m_cylinder_high)); + save_item(NAME(m_device_head)); + save_item(NAME(m_status)); + save_item(NAME(m_command)); + save_item(NAME(m_device_control)); + save_item(NAME(m_revert_to_defaults)); + save_item(NAME(m_8bit_data_transfers)); + + save_item(NAME(m_single_device)); + save_item(NAME(m_resetting)); + + save_item(NAME(m_csel)); + save_item(NAME(m_daspin)); + save_item(NAME(m_daspout)); + save_item(NAME(m_dmack)); + save_item(NAME(m_dmarq)); + save_item(NAME(m_irq)); + save_item(NAME(m_pdiagin)); + save_item(NAME(m_pdiagout)); + + save_item(NAME(m_identify_buffer)); + + m_busy_timer = timer_alloc(FUNC(ata_hle_device_base::busy_tick), this); + m_buffer_empty_timer = timer_alloc(FUNC(ata_hle_device_base::empty_tick), this); +} + +void ata_hle_device_base::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_hle_device_base::soft_reset() +{ + m_buffer_offset = 0; + m_buffer_size = 0; + m_status = 0; + + if (is_ready()) + { + m_status |= IDE_STATUS_DRDY; + } + + start_busy(DIAGNOSTIC_TIME, PARAM_DIAGNOSTIC); +} + +TIMER_CALLBACK_MEMBER(ata_hle_device_base::busy_tick) +{ + m_status &= ~IDE_STATUS_BSY; + finished_busy(param); +} + +TIMER_CALLBACK_MEMBER(ata_hle_device_base::empty_tick) +{ + m_buffer_empty_timer->enable(false); + fill_buffer(); +} + +void ata_hle_device_base::finished_busy(int param) +{ + switch (param) + { + case PARAM_DETECT_DEVICE1: + m_single_device = (m_daspin == CLEAR_LINE); + soft_reset(); + break; + + case PARAM_DIAGNOSTIC: + start_diagnostic(); + break; + + case PARAM_WAIT_FOR_PDIAG: + m_error |= IDE_ERROR_DIAGNOSTIC_DEVICE1_FAILED; + finished_diagnostic(); + break; + + case PARAM_COMMAND: + finished_command(); + break; + } +} + +void ata_hle_device_base::process_command() +{ + switch (m_command) + { + case IDE_COMMAND_DIAGNOSTIC: + start_busy(DIAGNOSTIC_TIME, PARAM_COMMAND); + break; + + case IDE_COMMAND_SET_FEATURES: + start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); + break; + + case IDE_COMMAND_CACHE_FLUSH: + start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); + break; + + default: + LOGPRINT(("IDE unknown command (%02X)\n", m_command)); + m_status |= IDE_STATUS_ERR; + m_error = IDE_ERROR_ABRT; + set_irq(ASSERT_LINE); + //machine().debug_break(); + break; + } +} + +void ata_hle_device_base::finished_command() +{ + switch (m_command) + { + case IDE_COMMAND_DIAGNOSTIC: + start_diagnostic(); + + if (m_csel == 0) + set_irq(ASSERT_LINE); + break; + + 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)); + + m_status |= IDE_STATUS_ERR; + m_error = IDE_ERROR_ABRT; + } + set_irq(ASSERT_LINE); + break; + + case IDE_COMMAND_CACHE_FLUSH: + m_status |= IDE_STATUS_DRDY; + break; + + default: + logerror( "finished_command() unhandled command %02x\n", m_command ); + break; + } +} + +bool ata_hle_device_base::set_dma_mode(int word) +{ + if ((m_identify_buffer[word] >> (m_sector_count & 7)) & 1) + { + m_identify_buffer[62] &= 0xff; + m_identify_buffer[63] &= 0xff; + m_identify_buffer[88] &= 0xff; + + m_identify_buffer[word] |= 0x100 << (m_sector_count & 7); + return true; + } + + return false; +} + +bool ata_hle_device_base::set_features() +{ + switch (m_feature) + { + case IDE_SET_FEATURES_ENABLE_8BIT_DATA_TRANSFERS: + m_8bit_data_transfers = true; + return true; + + case IDE_SET_FEATURES_TRANSFER_MODE: + switch (m_sector_count & IDE_TRANSFER_TYPE_MASK) + { + case IDE_TRANSFER_TYPE_PIO_DEFAULT: + switch (m_sector_count & 7) + { + case 0: + case 1: + return true; + } + break; + + case IDE_TRANSFER_TYPE_PIO_FLOW_CONTROL: + switch (m_sector_count & 7) + { + case 0: + case 1: + case 2: + return true; + + default: + if ((m_identify_buffer[64] >> ((m_sector_count & 7) - 3)) & 1) + { + return true; + } + } + break; + + case IDE_TRANSFER_TYPE_SINGLE_WORD_DMA: + return set_dma_mode(62); + + case IDE_TRANSFER_TYPE_MULTI_WORD_DMA: + return set_dma_mode(63); + + case IDE_TRANSFER_TYPE_ULTRA_DMA: + return set_dma_mode(88); + } + break; + + case IDE_SET_FEATURES_DISABLE_REVERTING_TO_POWER_ON_DEFAULTS: + m_revert_to_defaults = false; + return true; + + case IDE_SET_FEATURES_DISABLE_8BIT_DATA_TRANSFERS: + m_8bit_data_transfers = false; + return true; + + case IDE_SET_FEATURES_ENABLE_REVERTING_TO_POWER_ON_DEFAULTS: + m_revert_to_defaults = true; + return true; + } + + return false; +} + +int ata_hle_device_base::bit_to_mode(uint16_t word) +{ + switch (word>>8) + { + case 0x01: + return 0; + case 0x02: + return 1; + case 0x04: + return 2; + case 0x08: + return 3; + case 0x10: + return 4; + case 0x20: + return 5; + case 0x40: + return 6; + case 0x080: + 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]); +} + +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())); + read_buffer_empty(); + } + + return result; +} + +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())); + write_buffer_full(); + } +} + +void ata_hle_device_base::update_irq() +{ + if (device_selected() && (m_device_control & IDE_DEVICE_CONTROL_NIEN) == 0) + set_irq_out(m_irq); + else + set_irq_out(CLEAR_LINE); +} + +void ata_hle_device_base::start_busy(const attotime &time, int param) +{ + m_status |= IDE_STATUS_BSY; + m_busy_timer->adjust(time, param); +} + +void ata_hle_device_base::stop_busy() +{ + m_status &= ~IDE_STATUS_BSY; + m_busy_timer->adjust(attotime::never); +} + +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) { + m_buffer_empty_timer->enable(true); + m_buffer_empty_timer->adjust(attotime::zero); + } + else + fill_buffer(); +} + +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(); +} + +void ata_hle_device_base::start_diagnostic() +{ + m_error = IDE_ERROR_DIAGNOSTIC_FAILED; + + perform_diagnostic(); + + if (m_csel == 1 && m_error == IDE_ERROR_DIAGNOSTIC_PASSED) + set_pdiag(ASSERT_LINE); + + 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_hle_device_base::finished_diagnostic() +{ + m_resetting = false; + + signature(); +} + + +void ata_hle_device_base::set_dmack_in(int state) +{ + if (state && !m_dmack && single_word_dma_mode() >= 0) + set_dmarq(CLEAR_LINE); + + m_dmack = state; +} + +void ata_hle_device_base::set_pdiag_in(int state) +{ + m_pdiagin = state; + + if (m_pdiagin == ASSERT_LINE && m_busy_timer->param() == PARAM_WAIT_FOR_PDIAG) + { + stop_busy(); + finished_diagnostic(); + } +} + +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() ); + } + else if (m_dmarq && single_word_dma_mode() >= 0) + { + logerror( "%s: %s dev %d read_dma ignored (DMARQ)\n", machine().describe_context(), tag(), dev() ); + } + else if (!m_dmarq && multi_word_dma_mode() >= 0) + { + logerror( "%s: %s dev %d read_dma ignored (!DMARQ)\n", machine().describe_context(), tag(), dev() ); + } + else if (!m_dmarq && ultra_dma_mode() >= 0) + { + logerror("%s: %s dev %d read_dma ignored (!DMARQ)\n", machine().describe_context(), tag(), dev()); + } + else if (m_status & IDE_STATUS_BSY) + { + logerror( "%s: %s dev %d read_dma ignored (BSY)\n", machine().describe_context(), tag(), dev() ); + } + else if (!(m_status & IDE_STATUS_DRQ)) + { + logerror( "%s: %s dev %d read_dma ignored (!DRQ)\n", machine().describe_context(), tag(), dev() ); + } + else + { + result = read_data(); + + if ((m_status & IDE_STATUS_DRQ) && single_word_dma_mode() >= 0) + set_dmarq(ASSERT_LINE); + } + } + + return result; +} + +uint16_t ata_hle_device_base::command_r(offs_t offset) +{ + uint16_t result = 0xffff; + + if (device_selected() || m_single_device) + { + if (m_dmack) + { + logerror( "%s: %s dev %d read_cs0 %04x ignored (DMACK)\n", machine().describe_context(), tag(), dev(), offset ); + } + 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: + logerror( "%s: %s dev %d read_cs0 %04x ignored (BSY)\n", machine().describe_context(), tag(), dev(), offset ); + break; + + default: + result = calculate_status(); + break; + } + } + else + { + result = 0; + } + } + 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)) + { + logerror( "%s: %s dev %d read_cs0 ignored (!DRQ)\n", machine().describe_context(), tag(), dev() ); + } + else + { + result = read_data(); + } + } + 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: + logerror("%s:unknown IDE cs0 read at %03X\n", machine().describe_context(), offset); + break; + } + } + } + + /* logit */ +// if (offset != IDE_CS0_DATA_RW && offset != IDE_CS0_STATUS_R) + LOG(("%s:IDE cs0 read %X at %X (err: %X)\n", machine().describe_context(), result, offset, m_error)); + + /* return the result */ + return result; +} + + +uint16_t ata_hle_device_base::control_r(offs_t offset) +{ + /* logit */ +// if (offset != IDE_CS1_ALTERNATE_STATUS_R) + 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) + { + logerror( "%s: %s dev %d read_cs1 %04x ignored (DMACK)\n", machine().describe_context(), tag(), dev(), offset ); + } + else + { + switch (offset) + { + case IDE_CS1_ALTERNATE_STATUS_R: + if (device_selected()) + { + result = calculate_status(); + } + else + { + result = 0; + } + break; + + case IDE_CS1_ACTIVE_STATUS: + /* + + bit description + + 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; + + /* log anything else */ + default: + logerror("%s:unknown IDE cs1 read at %03X\n", machine().describe_context(), offset); + break; + } + } + } + + /* return the result */ + return result; +} + +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 ); + } + 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 ); + } + 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 ); + } + 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); + } + else if (m_status & IDE_STATUS_BSY) + { + logerror( "%s: %s dev %d write_dma %04x ignored (BSY)\n", machine().describe_context(), tag(), 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 ); + } + else + { + write_data(data); + + if ((m_status & IDE_STATUS_DRQ) && single_word_dma_mode() >= 0) + set_dmarq(ASSERT_LINE); + } + } +} + +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_dmack) + { + 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_FEATURE_W: + m_feature = data; + break; + + /* sector count */ + case IDE_CS0_SECTOR_COUNT_RW: + m_sector_count = (data & 0xff) ? (data & 0xff) : 0x100; + break; + + /* current sector */ + case IDE_CS0_SECTOR_NUMBER_RW: + m_sector_number = data; + break; + + /* current cylinder LSB */ + case IDE_CS0_CYLINDER_LOW_RW: + m_cylinder_low = data; + break; + + /* current cylinder MSB */ + case IDE_CS0_CYLINDER_HIGH_RW: + m_cylinder_high = data; + break; + + /* current head */ + case IDE_CS0_DEVICE_HEAD_RW: + old = m_device_head; + m_device_head = data; + + if ((m_device_head ^ old) & IDE_DEVICE_HEAD_DRV) + update_irq(); + break; + + /* 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; + + /* implicitly clear interrupts & dmarq here */ + set_irq(CLEAR_LINE); + set_dmarq(CLEAR_LINE); + + m_buffer_offset = 0; + + set_dasp(CLEAR_LINE); + m_status &= ~IDE_STATUS_DRQ; + m_status &= ~IDE_STATUS_ERR; + + process_command(); + } + break; + + default: + logerror("%s:unknown IDE cs0 write at %03X = %04x\n", machine().describe_context(), 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); + } + else + { + uint8_t old; + + switch (offset) + { + /* adapter control */ + case IDE_CS1_DEVICE_CONTROL_W: + old = m_device_control; + m_device_control = data; + + 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_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); + + start_busy(attotime::never, PARAM_RESET); + } + } + 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; + } + } +} diff --git a/src/devices/machine/atahle.h b/src/devices/machine/atahle.h new file mode 100644 index 00000000000..03c367e4784 --- /dev/null +++ b/src/devices/machine/atahle.h @@ -0,0 +1,256 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + atahle.h + + ATA Device HLE + +***************************************************************************/ +#ifndef MAME_MACHINE_ATAHLE_H +#define MAME_MACHINE_ATAHLE_H + +#pragma once + +class ata_hle_device_base : public device_t +{ +protected: + ata_hle_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; + + TIMER_CALLBACK_MEMBER(busy_tick); + TIMER_CALLBACK_MEMBER(empty_tick); + + uint16_t dma_r(); + uint16_t command_r(offs_t offset); + uint16_t control_r(offs_t offset); + + void dma_w(uint16_t data); + void command_w(offs_t offset, uint16_t data); + void control_w(offs_t offset, uint16_t data); + + void set_csel_in(int state) { m_csel = state; } + void set_dasp_in(int state) { m_daspin = state; } + void set_dmack_in(int state); + void set_pdiag_in(int state); + + void set_irq(int state) + { + if (m_irq != state) + { + m_irq = state; + update_irq(); + } + } + + void set_dmarq(int state) + { + if (m_dmarq != state) + { + m_dmarq = state; + set_dmarq_out(state); + } + } + + void set_dasp(int state) + { + if (m_daspout != state) + { + m_daspout = state; + set_dasp_out(state); + } + } + + void set_pdiag(int state) + { + if (m_pdiagout != state) + { + m_pdiagout = state; + set_pdiag_out(state); + } + } + + void start_busy(const attotime &time, int param); + void stop_busy(); + + int dev() { return (m_device_head & IDE_DEVICE_HEAD_DRV) >> 4; } + bool device_selected() { return m_csel == dev(); } + + virtual uint8_t calculate_status() { return m_status; } + virtual void soft_reset(); + virtual void process_command(); + virtual void finished_command(); + virtual bool set_features(); + virtual int sector_length() = 0; + virtual void process_buffer() = 0; + virtual void fill_buffer() = 0; + virtual bool is_ready() = 0; + virtual void perform_diagnostic() = 0; + virtual void signature() = 0; + virtual uint16_t read_data(); + virtual void write_data(uint16_t data); + + int bit_to_mode(uint16_t word); + int single_word_dma_mode(); + int multi_word_dma_mode(); + int ultra_dma_mode(); + + /// TODO: not sure this should be protected. + void read_buffer_empty(); + + enum + { + IDE_STATUS_ERR = 0x01, // Error + IDE_STATUS_IDX = 0x02, // Index + IDE_STATUS_CORR = 0x04, // Corrected Data + IDE_STATUS_DRQ = 0x08, // Data Request + IDE_STATUS_DSC = 0x10, // ATA Drive Seek Complete + IDE_STATUS_SERV = 0x10, // ATAPI Service + IDE_STATUS_DWF = 0x20, // ATA Drive Write Fault + IDE_STATUS_DMRD = 0x20, // ATAPI DMA Ready + IDE_STATUS_DRDY = 0x40, // Drive Ready + IDE_STATUS_BSY = 0x80 // Busy + }; + + enum + { + IDE_ERROR_NONE = 0x00, + IDE_ERROR_DIAGNOSTIC_OK = 0x01, + IDE_ERROR_TRACK0_NOT_FOUND = 0x02, + IDE_ERROR_ABRT = 0x04, + IDE_ERROR_BAD_LOCATION = 0x10, + IDE_ERROR_BAD_SECTOR = 0x80, + IDE_ERROR_DIAGNOSTIC_FAILED = 0x00, + IDE_ERROR_DIAGNOSTIC_PASSED = 0x01, + IDE_ERROR_DIAGNOSTIC_DEVICE1_FAILED = 0x80 + }; + + enum + { + IDE_COMMAND_NOP = 0x00, + IDE_COMMAND_DEVICE_RESET = 0x08, + IDE_COMMAND_RECALIBRATE = 0x10, + IDE_COMMAND_READ_SECTORS = 0x20, + IDE_COMMAND_READ_SECTORS_NORETRY = 0x21, + IDE_COMMAND_WRITE_SECTORS = 0x30, + IDE_COMMAND_WRITE_SECTORS_NORETRY = 0x31, + IDE_COMMAND_VERIFY_SECTORS = 0x40, + IDE_COMMAND_VERIFY_SECTORS_NORETRY = 0x41, + IDE_COMMAND_SEEK = 0x70, + IDE_COMMAND_DIAGNOSTIC = 0x90, + IDE_COMMAND_SET_CONFIG = 0x91, + IDE_COMMAND_PACKET = 0xa0, + IDE_COMMAND_IDENTIFY_PACKET_DEVICE = 0xa1, + IDE_COMMAND_READ_MULTIPLE = 0xc4, + IDE_COMMAND_WRITE_MULTIPLE = 0xc5, + IDE_COMMAND_SET_BLOCK_COUNT = 0xc6, + IDE_COMMAND_READ_DMA = 0xc8, + IDE_COMMAND_WRITE_DMA = 0xca, + IDE_COMMAND_STANDBY_IMMEDIATE = 0xe0, + IDE_COMMAND_IDLE_IMMEDIATE = 0xe1, + IDE_COMMAND_STANDBY = 0xe2, + IDE_COMMAND_IDLE = 0xe3, + IDE_COMMAND_CHECK_POWER_MODE = 0xe5, + IDE_COMMAND_CACHE_FLUSH = 0xe7, + IDE_COMMAND_IDENTIFY_DEVICE = 0xec, + IDE_COMMAND_SET_FEATURES = 0xef, + IDE_COMMAND_SECURITY_UNLOCK = 0xf2, + IDE_COMMAND_SECURITY_DISABLE_PASSWORD = 0xf6, + IDE_COMMAND_READ_NATIVE_MAX_ADDRESS = 0xf8, + IDE_COMMAND_SET_MAX = 0xf9 + }; + + enum + { + IDE_SET_FEATURES_ENABLE_8BIT_DATA_TRANSFERS = 0x01, + IDE_SET_FEATURES_TRANSFER_MODE = 0x03, + IDE_SET_FEATURES_DISABLE_REVERTING_TO_POWER_ON_DEFAULTS = 0x66, + IDE_SET_FEATURES_DISABLE_8BIT_DATA_TRANSFERS = 0x81, + IDE_SET_FEATURES_ENABLE_REVERTING_TO_POWER_ON_DEFAULTS = 0xcc + }; + + enum ide_transfer_type_t + { + IDE_TRANSFER_TYPE_PIO_DEFAULT = 0x00, + IDE_TRANSFER_TYPE_PIO_FLOW_CONTROL = 0x08, + IDE_TRANSFER_TYPE_SINGLE_WORD_DMA = 0x10, + IDE_TRANSFER_TYPE_MULTI_WORD_DMA = 0x20, + IDE_TRANSFER_TYPE_ULTRA_DMA = 0x40, + IDE_TRANSFER_TYPE_MASK = 0xf8 + }; + + enum + { + IDE_DEVICE_HEAD_HS = 0x0f, + IDE_DEVICE_HEAD_DRV = 0x10, + IDE_DEVICE_HEAD_L = 0x40, + IDE_DEVICE_HEAD_OBSOLETE = 0x80 | 0x20 + }; + + enum + { + TID_BUSY, + TID_BUFFER_EMPTY + }; + + enum + { + PARAM_RESET, + PARAM_DETECT_DEVICE1, + PARAM_DIAGNOSTIC, + PARAM_WAIT_FOR_PDIAG, + PARAM_COMMAND + }; + + attotime MINIMUM_COMMAND_TIME; + + std::vector m_buffer; + uint16_t m_buffer_offset; + uint16_t m_buffer_size; + uint8_t m_error; + uint8_t m_feature; + uint16_t m_sector_count; + uint8_t m_sector_number; + uint8_t m_cylinder_low; + uint8_t m_cylinder_high; + uint8_t m_device_head; + uint8_t m_status; + uint8_t m_command; + uint8_t m_device_control; + + uint16_t m_identify_buffer[256]; + bool m_revert_to_defaults; + bool m_8bit_data_transfers; + +private: + virtual void set_irq_out(int state) = 0; + virtual void set_dmarq_out(int state) = 0; + virtual void set_dasp_out(int state) = 0; + virtual void set_pdiag_out(int state) = 0; + + void update_irq(); + void write_buffer_full(); + void start_diagnostic(); + void finished_diagnostic(); + void finished_busy(int param); + bool set_dma_mode(int word); + + int m_csel; + int m_daspin; + int m_daspout; + int m_dmack; + int m_dmarq; + int m_irq; + int m_pdiagin; + int m_pdiagout; + + bool m_single_device; + bool m_resetting; + + emu_timer *m_busy_timer; + emu_timer *m_buffer_empty_timer; +}; + +#endif // MAME_MACHINE_ATAHLE_H diff --git a/src/devices/machine/atastorage.cpp b/src/devices/machine/atastorage.cpp new file mode 100644 index 00000000000..b869f50ceea --- /dev/null +++ b/src/devices/machine/atastorage.cpp @@ -0,0 +1,942 @@ +// license:BSD-3-Clause +// copyright-holders:smf +#include "emu.h" +#include "atastorage.h" + +/*************************************************************************** + DEBUGGING +***************************************************************************/ + +#define VERBOSE 0 +#define PRINTF_IDE_COMMANDS 0 +#define PRINTF_IDE_PASSWORD 0 + +#define LOGPRINT(x) do { if (VERBOSE) logerror x; if (PRINTF_IDE_COMMANDS) osd_printf_debug x; } while (0) + +#define TIME_PER_SECTOR_WRITE (attotime::from_usec(100)) +#define TIME_PER_ROTATION (attotime::from_hz(5400/60)) +#define TIME_BETWEEN_SECTORS (attotime::from_nsec(400)) + +#define TIME_FULL_STROKE_SEEK (attotime::from_usec(13000)) +#define TIME_AVERAGE_ROTATIONAL_LATENCY (attotime::from_usec(1300)) + +ata_mass_storage_device_base::ata_mass_storage_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + ata_hle_device_base(mconfig, type, tag, owner, clock), + m_can_identify_device(0), + m_num_cylinders(0), + m_num_sectors(0), + m_num_heads(0), m_cur_lba(0), m_block_count(0), m_sectors_until_int(0), m_master_password_enable(0), m_user_password_enable(0), + m_master_password(nullptr), + m_user_password(nullptr), + m_dma_transfer_time(attotime::zero) +{ +} + +/************************************* + * + * Compute the LBA address + * + *************************************/ + +uint32_t ata_mass_storage_device_base::lba_address() +{ + /* LBA direct? */ + if (m_device_head & IDE_DEVICE_HEAD_L) + return ((m_device_head & IDE_DEVICE_HEAD_HS) << 24) | (m_cylinder_high << 16) | (m_cylinder_low << 8) | m_sector_number; + + /* standard CHS */ + else + return (((((m_cylinder_high << 8) | m_cylinder_low) * m_num_heads) + (m_device_head & IDE_DEVICE_HEAD_HS)) * m_num_sectors) + m_sector_number - 1; +} + + +/************************************* + * + * Build a features page + * + *************************************/ + +static void swap_strncpy(uint16_t *dst, const char *src, int field_size_in_words) +{ + for (int i = 0; i < field_size_in_words; i++) + { + uint16_t d; + + if (*src) + { + d = *(src++) << 8; + } + else + { + d = ' ' << 8; + } + + if (*src) + { + d |= *(src++); + } + else + { + d |= ' '; + } + + dst[i] = d; + } + + assert(*(src) == 0); +} + + +void ata_mass_storage_device_base::ide_build_identify_device() +{ + memset(m_identify_buffer, 0, sizeof(m_identify_buffer)); + int total_sectors = m_num_cylinders * m_num_heads * m_num_sectors; + + /* basic geometry */ + m_identify_buffer[0] = 0x045a; /* 0: configuration bits */ + m_identify_buffer[1] = m_num_cylinders; /* 1: logical cylinders */ + m_identify_buffer[2] = 0; /* 2: reserved */ + m_identify_buffer[3] = m_num_heads; /* 3: logical heads */ + m_identify_buffer[4] = 0; /* 4: vendor specific (obsolete) */ + m_identify_buffer[5] = 0; /* 5: vendor specific (obsolete) */ + m_identify_buffer[6] = m_num_sectors; /* 6: logical sectors per logical track */ + m_identify_buffer[7] = 0; /* 7: vendor-specific */ + m_identify_buffer[8] = 0; /* 8: vendor-specific */ + m_identify_buffer[9] = 0; /* 9: vendor-specific */ + swap_strncpy(&m_identify_buffer[10], /* 10-19: serial number */ + "00000000000000000000", 10); + m_identify_buffer[20] = 0; /* 20: vendor-specific */ + m_identify_buffer[21] = 0; /* 21: vendor-specific */ + m_identify_buffer[22] = 4; /* 22: # of vendor-specific bytes on read/write long commands */ + swap_strncpy(&m_identify_buffer[23], /* 23-26: firmware revision */ + "1.0", 4); + swap_strncpy(&m_identify_buffer[27], /* 27-46: model number */ + "MAME Compressed Hard Disk", 20); + m_identify_buffer[47] = 0x8010; /* 47: read/write multiple support, value from Seagate Quantum Fireball */ + m_identify_buffer[48] = 0; /* 48: reserved */ + m_identify_buffer[49] = 0x0f03; /* 49: capabilities */ + m_identify_buffer[50] = 0; /* 50: reserved */ + m_identify_buffer[51] = 2; /* 51: PIO data transfer cycle timing mode */ + m_identify_buffer[52] = 2; /* 52: single word DMA transfer cycle timing mode */ + m_identify_buffer[53] = 3; /* 53: field validity */ + m_identify_buffer[54] = m_num_cylinders; /* 54: number of current logical cylinders */ + m_identify_buffer[55] = m_num_heads; /* 55: number of current logical heads */ + m_identify_buffer[56] = m_num_sectors; /* 56: number of current logical sectors per track */ + m_identify_buffer[57] = total_sectors & 0xffff; /* 57-58: current capacity in sectors (ATA-1 through ATA-5; obsoleted in ATA-6) */ + m_identify_buffer[58] = total_sectors >> 16; + m_identify_buffer[59] = 0; /* 59: multiple sector timing */ + m_identify_buffer[60] = total_sectors & 0xffff; /* 60-61: total user addressable sectors for LBA mode (ATA-1 through ATA-7) */ + m_identify_buffer[61] = total_sectors >> 16; + m_identify_buffer[62] = 0x0007; /* 62: single word dma transfer */ + m_identify_buffer[63] = 0x0407; /* 63: multiword DMA transfer */ + m_identify_buffer[64] = 0x0003; /* 64: flow control PIO transfer modes supported */ + m_identify_buffer[65] = 0x78; /* 65: minimum multiword DMA transfer cycle time per word */ + m_identify_buffer[66] = 0x78; /* 66: mfr's recommended multiword DMA transfer cycle time */ + m_identify_buffer[67] = 0x014d; /* 67: minimum PIO transfer cycle time without flow control */ + m_identify_buffer[68] = 0x78; /* 68: minimum PIO transfer cycle time with IORDY */ + m_identify_buffer[69] = 0x00; /* 69-70: reserved */ + m_identify_buffer[71] = 0x00; /* 71: reserved for IDENTIFY PACKET command */ + m_identify_buffer[72] = 0x00; /* 72: reserved for IDENTIFY PACKET command */ + m_identify_buffer[73] = 0x00; /* 73: reserved for IDENTIFY PACKET command */ + m_identify_buffer[74] = 0x00; /* 74: reserved for IDENTIFY PACKET command */ + m_identify_buffer[75] = 0x00; /* 75: queue depth */ + m_identify_buffer[76] = 0x00; /* 76-79: reserved */ + m_identify_buffer[80] = 0x00; /* 80: major version number */ + m_identify_buffer[81] = 0x00; /* 81: minor version number */ + m_identify_buffer[82] = 0x00; /* 82: command set supported */ + m_identify_buffer[83] = 0x00; /* 83: command sets supported */ + m_identify_buffer[84] = 0x00; /* 84: command set/feature supported extension */ + m_identify_buffer[85] = 0x00; /* 85: command set/feature enabled */ + m_identify_buffer[86] = 0x00; /* 86: command set/feature enabled */ + m_identify_buffer[87] = 0x00; /* 87: command set/feature default */ + m_identify_buffer[88] = 0x00; /* 88: additional DMA modes (ultra dma) */ + m_identify_buffer[89] = 0x00; /* 89: time required for security erase unit completion */ + m_identify_buffer[90] = 0x00; /* 90: time required for enhanced security erase unit completion */ + m_identify_buffer[91] = 0x00; /* 91: current advanced power management value */ + m_identify_buffer[92] = 0x00; /* 92: master password revision code */ + m_identify_buffer[93] = 0x00; /* 93: hardware reset result */ + m_identify_buffer[94] = 0x00; /* 94: acoustic management values */ + m_identify_buffer[95] = 0x00; /* 95-99: reserved */ + m_identify_buffer[100] = total_sectors & 0xffff; /* 100-103: maximum 48-bit LBA */ + m_identify_buffer[101] = total_sectors >> 16; + m_identify_buffer[102] = 0x00; + m_identify_buffer[103] = 0x00; + m_identify_buffer[104] = 0x00; /* 104-126: reserved */ + m_identify_buffer[127] = 0x00; /* 127: removable media status notification */ + m_identify_buffer[128] = 0x00; /* 128: security status */ + m_identify_buffer[129] = 0x00; /* 129-159: vendor specific */ + m_identify_buffer[160] = 0x00; /* 160: CFA power mode 1 */ + m_identify_buffer[161] = 0x00; /* 161-175: reserved for CompactFlash */ + m_identify_buffer[176] = 0x00; /* 176-205: current media serial number */ + m_identify_buffer[206] = 0x00; /* 206-254: reserved */ + m_identify_buffer[255] = 0x00; /* 255: integrity word */ + + if (total_sectors >= 16514064) + { + /// CHS limit + m_identify_buffer[1] = 16383; /* 1: logical cylinders */ + m_identify_buffer[3] = 16; /* 3: logical heads */ + m_identify_buffer[6] = 63; /* 6: logical sectors per logical track */ + m_identify_buffer[54] = 16383; /* 54: number of current logical cylinders */ + m_identify_buffer[55] = 16; /* 55: number of current logical heads */ + m_identify_buffer[56] = 63; /* 56: number of current logical sectors per track */ + m_identify_buffer[57] = 16514064 & 0xffff; /* 57-58: current capacity in sectors (ATA-1 through ATA-5; obsoleted in ATA-6) */ + m_identify_buffer[58] = 16514064 >> 16; + } + + if (total_sectors > 268435455) + { + /// LBA limit + m_identify_buffer[60] = 268435455 & 0xffff; /* 60-61: total user addressable sectors for LBA mode (ATA-1 through ATA-7) */ + m_identify_buffer[61] = 268435455 >> 16; + } +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void ata_mass_storage_device_base::device_start() +{ + ata_hle_device_base::device_start(); + + save_item(NAME(m_can_identify_device)); + save_item(NAME(m_num_cylinders)); + save_item(NAME(m_num_sectors)); + save_item(NAME(m_num_heads)); + + save_item(NAME(m_cur_lba)); + save_item(NAME(m_sectors_until_int)); + save_item(NAME(m_master_password_enable)); + save_item(NAME(m_user_password_enable)); + save_item(NAME(m_block_count)); +} + +void ata_mass_storage_device_base::soft_reset() +{ + ata_hle_device_base::soft_reset(); + + m_cur_lba = 0; + m_status |= IDE_STATUS_DSC; + + m_master_password_enable = (m_master_password != nullptr); + m_user_password_enable = (m_user_password != nullptr); +} + +void ata_mass_storage_device_base::perform_diagnostic() +{ + if (m_can_identify_device) + m_error = IDE_ERROR_DIAGNOSTIC_PASSED; +} + +void ata_mass_storage_device_base::signature() +{ + m_sector_count = 1; + m_sector_number = 1; + m_cylinder_low = 0; + m_cylinder_high = 0; + m_device_head = 0; +} + +void ata_mass_storage_device_base::finished_command() +{ + int total_sectors = m_num_cylinders * m_num_heads * m_num_sectors; + + switch (m_command) + { + case IDE_COMMAND_IDENTIFY_DEVICE: + if (m_can_identify_device) + { + for( int w = 0; w < 256; w++ ) + { + m_buffer[w * 2] = m_identify_buffer[ w ] & 0xff; + m_buffer[(w * 2) + 1] = m_identify_buffer[ w ] >> 8; + } + + 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: + finished_read(); + break; + + case IDE_COMMAND_WRITE_SECTORS: + case IDE_COMMAND_WRITE_SECTORS_NORETRY: + case IDE_COMMAND_WRITE_MULTIPLE: + case IDE_COMMAND_WRITE_DMA: + finished_write(); + break; + + case IDE_COMMAND_RECALIBRATE: + set_irq(ASSERT_LINE); + break; + + case IDE_COMMAND_READ_NATIVE_MAX_ADDRESS: + m_buffer[0] = (total_sectors & 0xff000000) >> 24; + m_buffer[1] = (total_sectors & 0x00ff0000) >> 16; + m_buffer[2] = (total_sectors & 0x0000ff00) >> 8; + m_buffer[3] = (total_sectors & 0x000000ff); + set_irq(ASSERT_LINE); + break; + + default: + ata_hle_device_base::finished_command(); + break; + } +} + +/************************************* + * + * Advance to the next sector + * + *************************************/ + +void ata_mass_storage_device_base::next_sector() +{ + uint8_t cur_head = m_device_head & IDE_DEVICE_HEAD_HS; + + /* LBA direct? */ + if (m_device_head & IDE_DEVICE_HEAD_L) + { + m_sector_number++; + if (m_sector_number == 0) + { + m_cylinder_low++; + if (m_cylinder_low == 0) + { + m_cylinder_high++; + if (m_cylinder_high == 0) + cur_head++; + } + } + } + + /* standard CHS */ + else + { + /* sectors are 1-based */ + m_sector_number++; + if (m_sector_number > m_num_sectors) + { + /* heads are 0 based */ + m_sector_number = 1; + cur_head++; + if (cur_head >= m_num_heads) + { + cur_head = 0; + m_cylinder_low++; + if (m_cylinder_low == 0) + m_cylinder_high++; + } + } + } + + m_device_head = (m_device_head & ~IDE_DEVICE_HEAD_HS) | cur_head; + + m_cur_lba = lba_address(); +} + + + +/************************************* + * + * security error handling + * + *************************************/ + +void ata_mass_storage_device_base::security_error() +{ + /* set error state */ + m_status |= IDE_STATUS_ERR; + m_error = IDE_ERROR_NONE; + m_status &= ~IDE_STATUS_DRDY; +} + + + +/************************************* + * + * Sector reading + * + *************************************/ + +attotime ata_mass_storage_device_base::seek_time() +{ + int sectors_per_cylinder = m_num_heads * m_num_sectors; + + if (sectors_per_cylinder == 0 || m_num_cylinders == 0) + return attotime::zero; + + int new_lba = lba_address(); + int old_cylinder = m_cur_lba / sectors_per_cylinder; + int new_cylinder = new_lba / sectors_per_cylinder; + int diff = abs(old_cylinder - new_cylinder); + + m_cur_lba = new_lba; + + if (diff == 0) + return TIME_BETWEEN_SECTORS; + + attotime seek_time = (TIME_FULL_STROKE_SEEK * diff) / m_num_cylinders; + + return seek_time + TIME_AVERAGE_ROTATIONAL_LATENCY; +} + +void ata_mass_storage_device_base::fill_buffer() +{ + switch (m_command) + { + case IDE_COMMAND_IDENTIFY_DEVICE: + break; + + case IDE_COMMAND_READ_MULTIPLE: + /* if there is more data to read, keep going */ + if (m_sector_count > 0) + m_sector_count--; + + if (m_sector_count > 0) + { + // Read the next sector with no delay + finished_read(); + } + break; + + default: + /* if there is more data to read, keep going */ + if (m_sector_count > 0) + m_sector_count--; + + if (m_sector_count > 0) + { + set_dasp(ASSERT_LINE); + if (m_command == IDE_COMMAND_READ_DMA) + start_busy(TIME_BETWEEN_SECTORS + m_dma_transfer_time, PARAM_COMMAND); + else + start_busy(TIME_BETWEEN_SECTORS, PARAM_COMMAND); + } + break; + } +} + + +void ata_mass_storage_device_base::finished_read() +{ + int lba = lba_address(), read_status; + + set_dasp(CLEAR_LINE); + + /* now do the read */ + read_status = read_sector(lba, &m_buffer[0]); + + /* if we succeeded, advance to the next sector and set the nice bits */ + if (read_status) + { + /* advance the pointers, unless this is the last sector */ + /* Gauntlet: Dark Legacy checks to make sure we stop on the last sector */ + if (m_sector_count != 1) + next_sector(); + + /* signal an interrupt, IDE_COMMAND_READ_MULTIPLE sets the interrupt at the start the block */ + if (--m_sectors_until_int == 0 || (m_sector_count == 1 && m_command != IDE_COMMAND_READ_MULTIPLE)) + { + m_sectors_until_int = ((m_command == IDE_COMMAND_READ_MULTIPLE) ? m_block_count : 1); + set_irq(ASSERT_LINE); + } + + /* if we're just verifying we can read the next sector */ + if (m_command == IDE_COMMAND_VERIFY_SECTORS || + m_command == IDE_COMMAND_VERIFY_SECTORS_NORETRY ) + { + read_buffer_empty(); + } + else + { + m_status |= IDE_STATUS_DRQ; + + if (m_command == IDE_COMMAND_READ_DMA) + set_dmarq(ASSERT_LINE); + } + } + + /* if we got an error, we need to report it */ + else + { + /* set the error flag and the error */ + m_status |= IDE_STATUS_ERR; + m_error = IDE_ERROR_BAD_SECTOR; + + /* signal an interrupt */ + set_irq(ASSERT_LINE); + } +} + + +void ata_mass_storage_device_base::read_first_sector() +{ + if (m_master_password_enable || m_user_password_enable) + { + security_error(); + } + else + { + set_dasp(ASSERT_LINE); + + start_busy(seek_time(), PARAM_COMMAND); + } +} + +/************************************* + * + * Sector writing + * + *************************************/ + +void ata_mass_storage_device_base::process_buffer() +{ + if (m_command == IDE_COMMAND_SECURITY_UNLOCK) + { + if (m_user_password_enable && memcmp(&m_buffer[0], m_user_password, 2 + 32) == 0) + { + LOGPRINT(("IDE Unlocked user password\n")); + m_user_password_enable = 0; + } + if (m_master_password_enable && memcmp(&m_buffer[0], m_master_password, 2 + 32) == 0) + { + LOGPRINT(("IDE Unlocked master password\n")); + m_master_password_enable = 0; + } + if (PRINTF_IDE_PASSWORD) + { + int i; + + for (i = 0; i < 34; i += 2) + { + if (i % 8 == 2) + osd_printf_debug("\n"); + + osd_printf_debug("0x%02x, 0x%02x, ", m_buffer[i], m_buffer[i + 1]); + //osd_printf_debug("0x%02x%02x, ", m_buffer[i], m_buffer[i + 1]); + } + osd_printf_debug("\n"); + } + + if (m_master_password_enable || m_user_password_enable) + security_error(); + } + else if (m_command == IDE_COMMAND_SECURITY_DISABLE_PASSWORD) + { + LOGPRINT(("IDE Done unimplemented SECURITY_DISABLE_PASSWORD command\n")); + } + else + { + set_dasp(ASSERT_LINE); + + if (m_command == IDE_COMMAND_WRITE_MULTIPLE) + { + if (m_sectors_until_int != 1) + { + /* ready to write now */ + finished_write(); + } + else + { + /* set a timer to do the write */ + start_busy(TIME_PER_SECTOR_WRITE, PARAM_COMMAND); + } + } + else + { + /* set a timer to do the write */ + start_busy(TIME_PER_SECTOR_WRITE, PARAM_COMMAND); + } + } +} + + +void ata_mass_storage_device_base::finished_write() +{ + int lba = lba_address(), count; + + set_dasp(CLEAR_LINE); + + /* now do the write */ + count = write_sector(lba, &m_buffer[0]); + + /* if we succeeded, advance to the next sector and set the nice bits */ + if (count == 1) + { + /* advance the pointers, unless this is the last sector */ + /* Gauntlet: Dark Legacy checks to make sure we stop on the last sector */ + if (m_sector_count != 1) + next_sector(); + + /* signal an interrupt */ + if (--m_sectors_until_int == 0 || m_sector_count == 1) + { + m_sectors_until_int = ((m_command == IDE_COMMAND_WRITE_MULTIPLE) ? m_block_count : 1); + set_irq(ASSERT_LINE); + } + + /* signal an interrupt if there's more data needed */ + if (m_sector_count > 0) + m_sector_count--; + + if (m_sector_count > 0) + { + m_status |= IDE_STATUS_DRQ; + + if (m_command == IDE_COMMAND_WRITE_DMA) + set_dmarq(ASSERT_LINE); + } + } + + /* if we got an error, we need to report it */ + else + { + /* set the error flag and the error */ + m_status |= IDE_STATUS_ERR; + m_error = IDE_ERROR_BAD_SECTOR; + + /* signal an interrupt */ + set_irq(ASSERT_LINE); + } +} + + +/************************************* + * + * Handle IDE commands + * + *************************************/ + +void ata_mass_storage_device_base::process_command() +{ + m_sectors_until_int = 0; + m_buffer_size = IDE_DISK_SECTOR_SIZE; + + switch (m_command) + { + case IDE_COMMAND_READ_SECTORS: + case IDE_COMMAND_READ_SECTORS_NORETRY: + LOGPRINT(("IDE Read multiple: C=%u H=%d S=%u LBA=%u count=%u\n", + (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count)); + + m_sectors_until_int = 1; + + /* start the read going */ + read_first_sector(); + break; + + case IDE_COMMAND_READ_MULTIPLE: + LOGPRINT(("IDE Read multiple block: C=%u H=%u S=%u LBA=%u count=%u\n", + (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count)); + + m_sectors_until_int = 1; + + /* start the read going */ + read_first_sector(); + break; + + case IDE_COMMAND_VERIFY_SECTORS: + case IDE_COMMAND_VERIFY_SECTORS_NORETRY: + LOGPRINT(("IDE Read verify multiple with/without retries: C=%u H=%u S=%u LBA=%u count=%u\n", + (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count)); + + /* reset the buffer */ + m_sectors_until_int = m_sector_count; + + /* start the read going */ + read_first_sector(); + break; + + case IDE_COMMAND_READ_DMA: + LOGPRINT(("IDE Read multiple DMA: C=%u H=%u S=%u LBA=%u count=%u\n", + (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count)); + + /* reset the buffer */ + m_sectors_until_int = m_sector_count; + + /* start the read going */ + read_first_sector(); + break; + + case IDE_COMMAND_WRITE_SECTORS: + case IDE_COMMAND_WRITE_SECTORS_NORETRY: + LOGPRINT(("IDE Write multiple: C=%u H=%u S=%u LBA=%u count=%u\n", + (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count)); + + /* reset the buffer */ + m_sectors_until_int = 1; + + /* mark the buffer ready */ + m_status |= IDE_STATUS_DRQ; + break; + + case IDE_COMMAND_WRITE_MULTIPLE: + LOGPRINT(("IDE Write multiple block: C=%u H=%u S=%u LBA=%u count=%u\n", + (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count)); + + /* reset the buffer */ + m_sectors_until_int = m_block_count; + + /* mark the buffer ready */ + m_status |= IDE_STATUS_DRQ; + break; + + case IDE_COMMAND_WRITE_DMA: + LOGPRINT(("IDE Write multiple DMA: C=%u H=%u S=%u LBA=%u count=%u\n", + (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count)); + + /* reset the buffer */ + m_sectors_until_int = m_sector_count; + + /* mark the buffer ready */ + m_status |= IDE_STATUS_DRQ; + + /* start the read going */ + set_dmarq(ASSERT_LINE); + break; + + case IDE_COMMAND_SECURITY_UNLOCK: + LOGPRINT(("IDE Security Unlock\n")); + + /* mark the buffer ready */ + m_status |= IDE_STATUS_DRQ; + + set_irq(ASSERT_LINE); + break; + + case IDE_COMMAND_SECURITY_DISABLE_PASSWORD: + LOGPRINT(("IDE Unimplemented SECURITY DISABLE PASSWORD command\n")); + + /* mark the buffer ready */ + m_status |= IDE_STATUS_DRQ; + + set_irq(ASSERT_LINE); + break; + + case IDE_COMMAND_IDENTIFY_DEVICE: + LOGPRINT(("IDE Identify device\n")); + + start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); + break; + + case IDE_COMMAND_RECALIBRATE: + start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); + break; + + case IDE_COMMAND_IDLE: + /* signal an interrupt */ + set_irq(ASSERT_LINE); + break; + + case IDE_COMMAND_SET_CONFIG: + LOGPRINT(("IDE Set configuration (%u heads, %u sectors)\n", (m_device_head & IDE_DEVICE_HEAD_HS) + 1, m_sector_count)); + + start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); + break; + + case IDE_COMMAND_SET_MAX: + LOGPRINT(("IDE Set max (%02X %02X %02X %02X %02X)\n", m_feature, m_sector_count & 0xff, m_sector_number, m_cylinder_low, m_cylinder_high)); + + /* signal an interrupt */ + set_irq(ASSERT_LINE); + break; + + case IDE_COMMAND_SET_BLOCK_COUNT: + LOGPRINT(("IDE Set block count (%u)\n", m_sector_count)); + + m_block_count = m_sector_count; + + /* signal an interrupt */ + set_irq(ASSERT_LINE); + break; + + case IDE_COMMAND_SEEK: + /* signal an interrupt */ + set_irq(ASSERT_LINE); + break; + + case IDE_COMMAND_READ_NATIVE_MAX_ADDRESS: + start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND); + break; + + default: + ata_hle_device_base::process_command(); + break; + } +} + +//************************************************************************** +// IDE HARD DISK DEVICE +//************************************************************************** + +//------------------------------------------------- +// ide_hdd_device_base - constructor +//------------------------------------------------- + +ide_hdd_device_base::ide_hdd_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + ata_mass_storage_device_base(mconfig, type, tag, owner, clock), + m_image(*this, "image") +{ +} + +void ide_hdd_device_base::device_start() +{ + ata_mass_storage_device_base::device_start(); + + /* create a timer for timing status */ + m_last_status_timer = machine().scheduler().timer_alloc(timer_expired_delegate()); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void ide_hdd_device_base::device_reset() +{ + if (m_image->exists() && !m_can_identify_device) + { + const auto &hdinfo = m_image->get_info(); + if (hdinfo.sectorbytes == IDE_DISK_SECTOR_SIZE) + { + m_num_cylinders = hdinfo.cylinders; + m_num_sectors = hdinfo.sectors; + m_num_heads = hdinfo.heads; + if (PRINTF_IDE_COMMANDS) osd_printf_debug("CHS: %u %u %u\n", m_num_cylinders, m_num_heads, m_num_sectors); + osd_printf_debug("CHS: %u %u %u\n", m_num_cylinders, m_num_heads, m_num_sectors); + } + + // build the features page + std::vector ident; + m_image->get_inquiry_data(ident); + if (ident.size() == 512) + { + for( int w = 0; w < 256; w++ ) + { + m_identify_buffer[w] = (ident[(w * 2) + 1] << 8) | ident[w * 2]; + } + } + else + { + ide_build_identify_device(); + } + + m_can_identify_device = 1; + } + + ata_mass_storage_device_base::device_reset(); +} + +uint8_t ide_hdd_device_base::calculate_status() +{ + uint8_t result = ata_hle_device_base::calculate_status(); + + if (m_last_status_timer->elapsed() > TIME_PER_ROTATION) + { + result |= IDE_STATUS_IDX; + m_last_status_timer->adjust(attotime::never); + } + + return result; +} + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +void ide_hdd_device_base::device_add_mconfig(machine_config &config) +{ + HARDDISK(config, "image", "ide_hdd"); +} + +//************************************************************************** +// ATA COMPACTFLASH CARD DEVICE +//************************************************************************** + +//------------------------------------------------- +// cf_device_base - constructor +//------------------------------------------------- + +cf_device_base::cf_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + ide_hdd_device_base(mconfig, type, tag, owner, clock) +{ +} + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +void cf_device_base::device_add_mconfig(machine_config &config) +{ + HARDDISK(config, "image", "ata_cf"); +} + +//------------------------------------------------- +// ide_build_identify_device +//------------------------------------------------- + +void cf_device_base::ide_build_identify_device() +{ + memset(m_identify_buffer, 0, sizeof(m_identify_buffer)); + int total_sectors = m_num_cylinders * m_num_heads * m_num_sectors; + + /* basic geometry */ + m_identify_buffer[0] = 0x848a; /* 0: configuration bits */ + m_identify_buffer[1] = m_num_cylinders; /* 1: logical cylinders */ + m_identify_buffer[2] = 0; /* 2: reserved */ + m_identify_buffer[3] = m_num_heads; /* 3: logical heads */ + m_identify_buffer[4] = 0; /* 4: number of unformatted bytes per track */ + m_identify_buffer[5] = 0; /* 5: number of unformatted bytes per sector */ + m_identify_buffer[6] = m_num_sectors; /* 6: logical sectors per logical track */ + m_identify_buffer[7] = total_sectors >> 16; /* 7: number of sectors per card MSW */ + m_identify_buffer[8] = total_sectors & 0xffff; /* 8: number of sectors per card LSW */ + m_identify_buffer[9] = 0; /* 9: vendor-specific */ + swap_strncpy(&m_identify_buffer[10], /* 10-19: serial number */ + "00000000000000000000", 10); + m_identify_buffer[20] = 0; /* 20: buffer type */ + m_identify_buffer[21] = 0; /* 21: buffer size in 512 byte increments */ + m_identify_buffer[22] = 4; /* 22: # of vendor-specific bytes on read/write long commands */ + swap_strncpy(&m_identify_buffer[23], /* 23-26: firmware revision */ + "1.0", 4); + swap_strncpy(&m_identify_buffer[27], /* 27-46: model number */ + "MAME Compressed CompactFlash", 20); + m_identify_buffer[47] = 0x0001; /* 47: read/write multiple support */ + m_identify_buffer[48] = 0; /* 48: double word not supported */ + m_identify_buffer[49] = 0x0200; /* 49: capabilities */ + m_identify_buffer[50] = 0; /* 50: reserved */ + m_identify_buffer[51] = 0x0200; /* 51: PIO data transfer cycle timing mode */ + m_identify_buffer[52] = 0x0000; /* 52: single word DMA transfer cycle timing mode */ + m_identify_buffer[53] = 0x0003; /* 53: translation parameters are valid */ + m_identify_buffer[54] = m_num_cylinders; /* 54: number of current logical cylinders */ + m_identify_buffer[55] = m_num_heads; /* 55: number of current logical heads */ + m_identify_buffer[56] = m_num_sectors; /* 56: number of current logical sectors per track */ + m_identify_buffer[57] = total_sectors & 0xffff; /* 57-58: current capacity in sectors */ + m_identify_buffer[58] = total_sectors >> 16; + m_identify_buffer[59] = 0; /* 59: multiple sector timing */ + m_identify_buffer[60] = total_sectors & 0xffff; /* 60-61: total user addressable sectors for LBA mode */ + m_identify_buffer[61] = total_sectors >> 16; + m_identify_buffer[62] = 0x00; /* 62-127: reserved */ + m_identify_buffer[128] = 0x00; /* 128: security status */ + m_identify_buffer[129] = 0x00; /* 129-159: vendor specific */ + m_identify_buffer[160] = 0x00; /* 160: Power requirement description*/ + m_identify_buffer[161] = 0x00; /* 161-255: reserved */ +} diff --git a/src/devices/machine/atastorage.h b/src/devices/machine/atastorage.h new file mode 100644 index 00000000000..cb1212ccece --- /dev/null +++ b/src/devices/machine/atastorage.h @@ -0,0 +1,136 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + idehd.h + + IDE hard disk + +***************************************************************************/ + +#ifndef MAME_MACHINE_ATASTORAGE_H +#define MAME_MACHINE_ATASTORAGE_H + +#pragma once + +#include "atahle.h" + +#include "imagedev/harddriv.h" + +#include "harddisk.h" + + +class ata_mass_storage_device_base : public ata_hle_device_base +{ +public: + uint16_t *identify_device_buffer() { return m_identify_buffer; } + + void set_master_password(const uint8_t *password) + { + m_master_password = password; + m_master_password_enable = (password != nullptr); + } + + void set_user_password(const uint8_t *password) + { + m_user_password = password; + m_user_password_enable = (password != nullptr); + } + + void set_dma_transfer_time(const attotime time) { m_dma_transfer_time = time; } + +protected: + ata_mass_storage_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + + virtual int read_sector(uint32_t lba, void *buffer) = 0; + virtual int write_sector(uint32_t lba, const void *buffer) = 0; + virtual attotime seek_time(); + + virtual void ide_build_identify_device(); + + static const int IDE_DISK_SECTOR_SIZE = 512; + virtual int sector_length() override { return IDE_DISK_SECTOR_SIZE; } + virtual void process_buffer() override; + virtual void fill_buffer() override; + virtual bool is_ready() override { return true; } + virtual void process_command() override; + virtual void finished_command() override; + virtual void perform_diagnostic() override; + virtual void signature() override; + + int m_can_identify_device; + uint16_t m_num_cylinders; + uint8_t m_num_sectors; + uint8_t m_num_heads; + + virtual uint32_t lba_address(); + +private: + void set_geometry(uint8_t sectors, uint8_t heads) { m_num_sectors = sectors; m_num_heads = heads; } + void finished_read(); + void finished_write(); + void next_sector(); + void security_error(); + void read_first_sector(); + void soft_reset() override; + + uint32_t m_cur_lba; + uint16_t m_block_count; + uint16_t m_sectors_until_int; + + uint8_t m_master_password_enable; + uint8_t m_user_password_enable; + const uint8_t * m_master_password; + const uint8_t * m_user_password; + // DMA data transfer time for 1 sector + attotime m_dma_transfer_time; +}; + +// ======================> ide_hdd_device_base + +class ide_hdd_device_base : public ata_mass_storage_device_base +{ +protected: + // construction/destruction + ide_hdd_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // optional information overrides + virtual void device_add_mconfig(machine_config &config) override; + + virtual int read_sector(uint32_t lba, void *buffer) override { return !m_image->exists() ? 0 : m_image->read(lba, buffer); } + virtual int write_sector(uint32_t lba, const void *buffer) override { return !m_image->exists() ? 0 : m_image->write(lba, buffer); } + virtual uint8_t calculate_status() override; + + enum + { + TID_NULL = TID_BUSY + 1 + }; + + required_device m_image; + +private: + emu_timer * m_last_status_timer; +}; + + +// ======================> cf_device_base + +class cf_device_base : public ide_hdd_device_base +{ +protected: + // construction/destruction + cf_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + // optional information overrides + virtual void device_add_mconfig(machine_config &config) override; + + virtual void ide_build_identify_device() override; +}; + +#endif // MAME_MACHINE_ATASTORAGE_H diff --git a/src/mame/atari/jaguar.cpp b/src/mame/atari/jaguar.cpp index 506408c0f6a..45cccf07e27 100644 --- a/src/mame/atari/jaguar.cpp +++ b/src/mame/atari/jaguar.cpp @@ -337,22 +337,24 @@ Notes: #include "emu.h" #include "jaguar.h" +#include "bus/ata/hdd.h" #include "bus/generic/carts.h" -#include "bus/ata/idehd.h" +#include "cpu/jaguar/jaguar.h" #include "cpu/m68000/m68000.h" #include "cpu/m68000/m68020.h" #include "cpu/mips/mips1.h" -#include "cpu/jaguar/jaguar.h" #include "imagedev/cdromimg.h" #include "imagedev/snapquik.h" #include "machine/eepromser.h" -#include "machine/watchdog.h" #include "machine/vt83c461.h" +#include "machine/watchdog.h" #include "sound/cdda.h" -#include "cdrom.h" + #include "softlist_dev.h" #include "speaker.h" +#include "cdrom.h" + #define COJAG_CLOCK XTAL(52'000'000) #define R3000_CLOCK XTAL(40'000'000) #define M68K_CLOCK XTAL(50'000'000) diff --git a/src/mame/konami/cobra.cpp b/src/mame/konami/cobra.cpp index 032a9861aa9..d9f57bdf322 100644 --- a/src/mame/konami/cobra.cpp +++ b/src/mame/konami/cobra.cpp @@ -321,7 +321,7 @@ #include "windy2.h" #include "bus/ata/ataintf.h" -#include "bus/ata/idehd.h" +#include "bus/ata/hdd.h" #include "cpu/powerpc/ppc.h" #include "machine/lpci.h" #include "machine/timekpr.h" diff --git a/src/mame/konami/djmain.cpp b/src/mame/konami/djmain.cpp index baee3bbc92e..b0fb9c0e66d 100644 --- a/src/mame/konami/djmain.cpp +++ b/src/mame/konami/djmain.cpp @@ -72,7 +72,7 @@ hard drive 3.5 adapter long 3.5 IDE cable 3.5 adapter PCB #include "konami_helper.h" #include "bus/ata/ataintf.h" -#include "bus/ata/idehd.h" +#include "bus/ata/hdd.h" #include "cpu/m68000/m68020.h" #include "sound/k054539.h" diff --git a/src/mame/konami/firebeat.cpp b/src/mame/konami/firebeat.cpp index da72fcef089..40b7deb3861 100644 --- a/src/mame/konami/firebeat.cpp +++ b/src/mame/konami/firebeat.cpp @@ -139,30 +139,31 @@ */ #include "emu.h" +#include "k057714.h" +#include "midikbd.h" #include "bus/ata/ataintf.h" #include "bus/ata/atapicdr.h" -#include "bus/ata/idehd.h" +#include "bus/ata/hdd.h" #include "cpu/m68000/m68000.h" #include "cpu/powerpc/ppc.h" #include "machine/fdc37c665gt.h" #include "machine/ins8250.h" #include "machine/intelfsh.h" #include "machine/mb8421.h" -#include "midikbd.h" #include "machine/rtc65271.h" #include "machine/timer.h" #include "sound/cdda.h" #include "sound/xt446.h" #include "sound/rf5c400.h" #include "sound/ymz280b.h" -#include "k057714.h" #include "imagedev/floppy.h" #include "emupal.h" #include "screen.h" #include "speaker.h" + #include "osdcomm.h" #include "wdlfft/fft.h" diff --git a/src/mame/konami/viper.cpp b/src/mame/konami/viper.cpp index ba1bd5e6da7..5b29e8d67be 100644 --- a/src/mame/konami/viper.cpp +++ b/src/mame/konami/viper.cpp @@ -403,15 +403,17 @@ The golf club acts like a LED gun. PCB power input is 12V. */ #include "emu.h" + #include "cpu/powerpc/ppc.h" #include "cpu/upd78k/upd78k4.h" #include "bus/ata/ataintf.h" -#include "bus/ata/idehd.h" +#include "bus/ata/hdd.h" #include "machine/lpci.h" #include "machine/timekpr.h" #include "machine/timer.h" #include "sound/dmadac.h" #include "video/voodoo_banshee.h" + #include "emupal.h" #include "screen.h" #include "speaker.h" diff --git a/src/mame/merit/mtouchxl.cpp b/src/mame/merit/mtouchxl.cpp index 07388dda653..d82c9b17ed5 100644 --- a/src/mame/merit/mtouchxl.cpp +++ b/src/mame/merit/mtouchxl.cpp @@ -31,7 +31,7 @@ #include "emu.h" #include "bus/ata/atapicdr.h" -#include "bus/ata/idehd.h" +#include "bus/ata/hdd.h" #include "bus/isa/isa_cards.h" #include "cpu/i386/i386.h" #include "machine/at.h" diff --git a/src/mame/microsoft/xbox.cpp b/src/mame/microsoft/xbox.cpp index 43b27d58172..f59a3acc799 100644 --- a/src/mame/microsoft/xbox.cpp +++ b/src/mame/microsoft/xbox.cpp @@ -8,14 +8,14 @@ #include "emu.h" -#include "machine/pci.h" -#include "machine/idectrl.h" #include "xbox_pci.h" #include "xbox.h" -#include "cpu/i386/i386.h" #include "bus/ata/atapicdr.h" -#include "bus/ata/idehd.h" +#include "bus/ata/hdd.h" +#include "cpu/i386/i386.h" +#include "machine/idectrl.h" +#include "machine/pci.h" #include "speaker.h" @@ -49,7 +49,7 @@ protected: // devices optional_device m_ide; - required_device m_devh; + required_device m_devh; required_device m_devc; }; diff --git a/src/mame/midway/seattle.cpp b/src/mame/midway/seattle.cpp index c02d4e9ef09..7955fabb0a5 100644 --- a/src/mame/midway/seattle.cpp +++ b/src/mame/midway/seattle.cpp @@ -191,7 +191,7 @@ #include "cage.h" #include "dcs.h" -#include "bus/ata/idehd.h" +#include "bus/ata/hdd.h" #include "cpu/adsp2100/adsp2100.h" #include "cpu/mips/mips3.h" #include "machine/gt64xxx.h" diff --git a/src/mame/midway/vegas.cpp b/src/mame/midway/vegas.cpp index 3f09e7fbdcb..0a0e7269198 100644 --- a/src/mame/midway/vegas.cpp +++ b/src/mame/midway/vegas.cpp @@ -277,7 +277,7 @@ #include "dcs.h" -#include "bus/ata/idehd.h" +#include "bus/ata/hdd.h" #include "bus/rs232/rs232.h" #include "cpu/adsp2100/adsp2100.h" #include "cpu/mips/mips3.h" diff --git a/src/mame/namco/turrett.cpp b/src/mame/namco/turrett.cpp index 229db6c8b7a..a43f47c76ca 100644 --- a/src/mame/namco/turrett.cpp +++ b/src/mame/namco/turrett.cpp @@ -11,7 +11,7 @@ #include "emu.h" #include "turrett.h" -#include "bus/ata/idehd.h" +#include "bus/ata/hdd.h" /************************************* @@ -331,7 +331,7 @@ public: if (m_device_head & IDE_DEVICE_HEAD_L) return (((m_device_head & IDE_DEVICE_HEAD_HS) << 24) | (m_cylinder_high << 16) | (m_cylinder_low << 8) | m_sector_number) - 63; - return ata_mass_storage_device::lba_address(); + return ide_hdd_device::lba_address(); } }; diff --git a/src/mame/rare/kinst.cpp b/src/mame/rare/kinst.cpp index d789a5c9491..be7eed48e31 100644 --- a/src/mame/rare/kinst.cpp +++ b/src/mame/rare/kinst.cpp @@ -187,7 +187,7 @@ Notes: #include "dcs.h" #include "bus/ata/ataintf.h" -#include "bus/ata/idehd.h" +#include "bus/ata/hdd.h" #include "cpu/adsp2100/adsp2100.h" #include "cpu/mips/mips3.h" diff --git a/src/mame/sega/chihiro.cpp b/src/mame/sega/chihiro.cpp index 7388632baad..1567f32671a 100644 --- a/src/mame/sega/chihiro.cpp +++ b/src/mame/sega/chihiro.cpp @@ -430,15 +430,15 @@ Thanks to Alex, Mr Mudkips, and Philip Burke for this info. #include "emu.h" +#include "jvs13551.h" #include "xbox_pci.h" #include "xbox.h" #include "machine/pci.h" #include "machine/idectrl.h" -#include "bus/ata/idehd.h" +#include "bus/ata/hdd.h" #include "cpu/i386/i386.h" -#include "jvs13551.h" #include "machine/jvshost.h" #include "naomigd.h" @@ -1506,22 +1506,46 @@ void ohci_hlean2131sc_device::device_start() // ======================> ide_baseboard_device -class ide_baseboard_device : public ata_mass_storage_device +class ide_baseboard_device : public ata_mass_storage_device_base, public device_ata_interface { public: // construction/destruction ide_baseboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + // device_ata_interface implementation + virtual uint16_t read_dma() override { return dma_r(); } + virtual uint16_t read_cs0(offs_t offset, uint16_t mem_mask) override { return command_r(offset); } + virtual uint16_t read_cs1(offs_t offset, uint16_t mem_mask) override { return control_r(offset); } + + virtual void write_dma(uint16_t data) override { dma_w(data); } + virtual void write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask) override { command_w(offset, data); } + virtual void write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask) override { control_w(offset, data); } + + virtual void write_dmack(int state) override { set_dmack_in(state); } + virtual void write_csel(int state) override { set_csel_in(state); } + virtual void write_dasp(int state) override { set_dasp_in(state); } + virtual void write_pdiag(int state) override { set_pdiag_in(state); } + + // ata_mass_storage_device_base implementation virtual int read_sector(uint32_t lba, void *buffer) override; virtual int write_sector(uint32_t lba, const void *buffer) override; + protected: - // device-level overrides + // device_t implementation virtual void device_start() override; virtual void device_reset() override; + uint8_t read_buffer[0x20]{}; uint8_t write_buffer[0x20]{}; chihiro_state *chihirosystem{}; static const int size_factor = 2; + +private: + // ata_hle_device_base implementation + virtual void set_irq_out(int state) override { device_ata_interface::set_irq(state); } + virtual void set_dmarq_out(int state) override { device_ata_interface::set_dmarq(state); } + virtual void set_dasp_out(int state) override { device_ata_interface::set_dasp(state); } + virtual void set_pdiag_out(int state) override { device_ata_interface::set_pdiag(state); } }; //************************************************************************** @@ -1536,7 +1560,8 @@ DEFINE_DEVICE_TYPE(IDE_BASEBOARD, ide_baseboard_device, "ide_baseboard", "IDE Ba //------------------------------------------------- ide_baseboard_device::ide_baseboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ata_mass_storage_device(mconfig, IDE_BASEBOARD, tag, owner, clock) + : ata_mass_storage_device_base(mconfig, IDE_BASEBOARD, tag, owner, clock) + , device_ata_interface(mconfig, *this) { } @@ -1546,7 +1571,7 @@ ide_baseboard_device::ide_baseboard_device(const machine_config &mconfig, const void ide_baseboard_device::device_start() { - ata_mass_storage_device::device_start(); + ata_mass_storage_device_base::device_start(); chihirosystem = machine().driver_data(); // savestates save_item(NAME(read_buffer)); @@ -1568,7 +1593,7 @@ void ide_baseboard_device::device_reset() m_can_identify_device = 1; } - ata_mass_storage_device::device_reset(); + ata_mass_storage_device_base::device_reset(); } int ide_baseboard_device::read_sector(uint32_t lba, void *buffer) diff --git a/src/mame/sinclair/atm.cpp b/src/mame/sinclair/atm.cpp index a4fcb355eda..ea2e3ce5307 100644 --- a/src/mame/sinclair/atm.cpp +++ b/src/mame/sinclair/atm.cpp @@ -14,7 +14,7 @@ NOTES: #include "atm.h" #include "bus/ata/atapicdr.h" -#include "bus/ata/idehd.h" +#include "bus/ata/hdd.h" #include "sound/ay8910.h" #define LOG_MEM (1U << 1) diff --git a/src/mame/sinclair/sprinter.cpp b/src/mame/sinclair/sprinter.cpp index e33a3197ba9..d5371c299da 100644 --- a/src/mame/sinclair/sprinter.cpp +++ b/src/mame/sinclair/sprinter.cpp @@ -40,7 +40,7 @@ TODO: #include "bus/ata/atapicdr.h" #include "bus/ata/ataintf.h" -#include "bus/ata/idehd.h" +#include "bus/ata/hdd.h" #include "bus/isa/isa.h" #include "bus/isa/isa_cards.h" #include "bus/pc_kbd/keyboards.h" diff --git a/src/mame/sony/taitogn.cpp b/src/mame/sony/taitogn.cpp index 28b49681bc6..0b069a33be9 100644 --- a/src/mame/sony/taitogn.cpp +++ b/src/mame/sony/taitogn.cpp @@ -873,91 +873,91 @@ ROM_END ROM_START(raycris) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "raycris", 0, SHA1(9d255710c87c3286542d357820d828807cc6ca07)) ROM_END ROM_START(raycrisj) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "raycrisj", 0, SHA1(015cb0e6c4421cc38809de28c4793b4491386aee)) ROM_END ROM_START(gobyrc) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard2:image" ) + DISK_REGION( "ata:pccard:taitopccard2" ) DISK_IMAGE( "gobyrc", 0, SHA1(0bee1f495fc8b033fd56aad9260ae94abb35eb58)) ROM_END ROM_START(rcdego) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "rcdego", 0, SHA1(9e177f2a3954cfea0c8c5a288e116324d10f5dd1)) ROM_END ROM_START(chaoshea) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "chaosheat", 0, SHA1(c13b7d7025eee05f1f696d108801c7bafb3f1356)) ROM_END ROM_START(chaosheaj) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "chaosheatj", 0, SHA1(2f211ac08675ea8ec33c7659a13951db94eaa627)) ROM_END ROM_START(flipmaze) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "flipmaze", 0, SHA1(423b6c06f4f2d9a608ce20b61a3ac11687d22c40) ) ROM_END ROM_START(spuzbobl) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard2:image" ) + DISK_REGION( "ata:pccard:taitopccard2" ) DISK_IMAGE( "spuzbobl", 0, SHA1(1b1c72fb7e5656021485fefaef8f2ba48e2b4ea8)) ROM_END ROM_START(spuzboblj) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard2:image" ) + DISK_REGION( "ata:pccard:taitopccard2" ) DISK_IMAGE( "spuzbobj", 0, SHA1(dac433cf88543d2499bf797d7406b82ae4338726)) ROM_END ROM_START(soutenry) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "soutenry", 0, SHA1(9204d0be833d29f37b8cd3fbdf09da69b622254b)) ROM_END ROM_START(shanghss) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "shanghss", 0, SHA1(7964f71ec5c81d2120d83b63a82f97fbad5a8e6d)) ROM_END ROM_START(sianniv) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "sianniv", 0, SHA1(1e08b813190a9e1baf29bc16884172d6c8da7ae3)) ROM_END ROM_START(kollon) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "kollon", 0, SHA1(d8ea5b5b0ee99004b16ef89883e23de6c7ddd7ce)) ROM_END @@ -965,21 +965,21 @@ ROM_START(kollonc) TAITOGNET_BIOS ROM_DEFAULT_BIOS( "v2" ) - DISK_REGION( "pccard:taitocf:image" ) + DISK_REGION( "ata:pccard:taitocf" ) DISK_IMAGE( "kollonc", 0, SHA1(ce62181659701cfb8f7c564870ab902be4d8e060)) /* Original Taito Compact Flash version */ ROM_END ROM_START(shikigam) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "shikigam", 0, SHA1(fa49a0bc47f5cb7c30d7e49e2c3696b21bafb840)) ROM_END ROM_START(shikigama) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "shikigama", 0, SHA1(a6fe194c86730963301be9710782ca4ac1bf3e8d)) ROM_END @@ -989,42 +989,42 @@ ROM_END ROM_START(otenamih) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "otenamih", 0, SHA1(b3babe3a1876c43745616ee1e7d87276ce7dad0b) ) ROM_END ROM_START(psyvaria) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "psyvaria", 0, SHA1(3c7fca5180356190a8bf94b22a847fdd2e6a4e13)) ROM_END ROM_START(psyvarij) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "psyvarij", 0, SHA1(b981a42a10069322b77f7a268beae1d409b4156d)) ROM_END ROM_START(psyvarrv) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "psyvarrv", 0, SHA1(277c4f52502bcd7acc1889840962ec80d56465f3)) ROM_END ROM_START(zooo) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "zooo", 0, SHA1(e275b3141b2bc49142990e6b497a5394a314a30b)) ROM_END ROM_START(zokuoten) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "zokuoten", 0, SHA1(5ce13db00518f96af64935176c71ec68d2a51938)) ROM_END @@ -1032,7 +1032,7 @@ ROM_START(otenamhf) TAITOGNET_BIOS ROM_DEFAULT_BIOS( "v2" ) - DISK_REGION( "pccard:taitocf:image" ) + DISK_REGION( "ata:pccard:taitocf" ) DISK_IMAGE( "otenamhf", 0, SHA1(5b15c33bf401e5546d78e905f538513d6ffcf562)) /* Original Taito Compact Flash version */ ROM_END @@ -1042,14 +1042,14 @@ ROM_END ROM_START(nightrai) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "nightrai", 0, SHA1(74d0458f851cbcf10453c5cc4c47bb4388244cdf)) ROM_END ROM_START(otenki) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "otenki", 0, SHA1(7e745ca4c4570215f452fd09cdd56a42c39caeba)) ROM_END @@ -1059,21 +1059,21 @@ ROM_END ROM_START(usagi) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard2:image" ) + DISK_REGION( "ata:pccard:taitopccard2" ) DISK_IMAGE( "usagi", 0, SHA1(edf9dd271957f6cb06feed238ae21100514bef8e)) ROM_END ROM_START(mahjngoh) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "mahjngoh", 0, SHA1(3ef1110d15582d7c0187438d7ad61765dd121cff)) ROM_END ROM_START(shangtou) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "shanghaito", 0, SHA1(9901db5a9aae77e3af4157aa2c601eaab5b7ca85) ) ROM_END @@ -1083,7 +1083,7 @@ ROM_END ROM_START(xiistag) TAITOGNET_BIOS - DISK_REGION( "pccard:taitopccard1:image" ) + DISK_REGION( "ata:pccard:taitopccard1" ) DISK_IMAGE( "xiistag", 0, SHA1(586e37c8d926293b2bd928e5f0d693910cfb05a2)) ROM_END diff --git a/src/mame/taito/taitotz.cpp b/src/mame/taito/taitotz.cpp index c9ea63ce3e8..89eaa68337f 100644 --- a/src/mame/taito/taitotz.cpp +++ b/src/mame/taito/taitotz.cpp @@ -173,7 +173,7 @@ Notes: #include "emu.h" #include "bus/ata/ataintf.h" -#include "bus/ata/idehd.h" +#include "bus/ata/hdd.h" #include "cpu/powerpc/ppc.h" #include "cpu/tlcs900/tmp95c063.h" #include "machine/nvram.h" -- cgit v1.2.3