diff options
Diffstat (limited to 'src/devices/machine/wd1000.cpp')
-rw-r--r-- | src/devices/machine/wd1000.cpp | 157 |
1 files changed, 82 insertions, 75 deletions
diff --git a/src/devices/machine/wd1000.cpp b/src/devices/machine/wd1000.cpp index e9ac75bad49..109a3776df4 100644 --- a/src/devices/machine/wd1000.cpp +++ b/src/devices/machine/wd1000.cpp @@ -7,7 +7,7 @@ ***************************************************************************/ #include "emu.h" -#include "machine/wd1000.h" +#include "wd1000.h" //************************************************************************** // DEVICE DEFINITIONS @@ -28,6 +28,7 @@ wd1000_device::wd1000_device(const machine_config &mconfig, const char *tag, dev : device_t(mconfig, WD1000, tag, owner, clock) , m_intrq_cb(*this) , m_drq_cb(*this) + , m_drives(*this, "%u", 0) , m_sector_base(0) , m_buffer_index(0) , m_buffer_end(0) @@ -56,30 +57,37 @@ void wd1000_device::set_sector_base(uint32_t base) void wd1000_device::device_start() { - // Resolve callbacks - m_intrq_cb.resolve(); - m_drq_cb.resolve(); - // Allocate timers - m_seek_timer = timer_alloc(TIMER_SEEK); - m_drq_timer = timer_alloc(TIMER_DRQ); + m_seek_timer = timer_alloc(FUNC(wd1000_device::update_seek), this); + m_drq_timer = timer_alloc(FUNC(wd1000_device::delayed_drq), this); // Empty buffer. m_buffer_index = 0; for (int i = 0; i < 4; i++) - { - char name[2]; - name[0] = '0' + i; - name[1] = 0; - m_drives[i].drive = subdevice<harddisk_image_device>(name); - m_drives[i].cylinder = 0; - } + m_drive_cylinder[i] = 0; // Initialize the status as ready if the initial drive exists, // and assume it has been restored so seek is complete. - if (m_drives[drive()].drive->exists()) + if (m_drives[drive()] && m_drives[drive()]->exists()) m_status |= S_RDY | S_SC; + + save_item(NAME(m_drive_cylinder)); + save_item(NAME(m_sector_base)); + save_item(NAME(m_buffer)); + save_item(NAME(m_buffer_index)); + save_item(NAME(m_buffer_end)); + save_item(NAME(m_intrq)); + save_item(NAME(m_drq)); + save_item(NAME(m_stepping_rate)); + save_item(NAME(m_command)); + save_item(NAME(m_error)); + save_item(NAME(m_precomp)); + save_item(NAME(m_sector_count)); + save_item(NAME(m_sector_number)); + save_item(NAME(m_cylinder)); + save_item(NAME(m_sdh)); + save_item(NAME(m_status)); } //------------------------------------------------- @@ -92,56 +100,54 @@ void wd1000_device::device_reset() m_sdh = 0x20; for (int i = 0; i < 4; i++) - m_drives[i].cylinder = 0; + m_drive_cylinder[i] = 0; - if (m_drives[drive()].drive->exists()) + if (m_drives[drive()] && m_drives[drive()]->exists()) m_status |= S_RDY | S_SC; } //------------------------------------------------- -// device_timer - device-specific timer +// update_seek - //------------------------------------------------- -void wd1000_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr) +TIMER_CALLBACK_MEMBER(wd1000_device::update_seek) { - switch (tid) - { - case TIMER_SEEK: - - m_drives[drive()].cylinder = param; - m_status |= S_SC; - - switch (m_command >> 4) - { - case CMD_RESTORE: - cmd_restore(); - break; - - case CMD_SEEK: - cmd_seek(); - break; + m_drive_cylinder[drive()] = param; + m_status |= S_SC; - case CMD_READ_SECTOR: - cmd_read_sector(); - break; + switch (m_command >> 4) + { + case CMD_RESTORE: + cmd_restore(); + break; - case CMD_WRITE_SECTOR: - cmd_write_sector(); - break; + case CMD_SEEK: + cmd_seek(); + break; - case CMD_WRITE_FORMAT: - cmd_format_sector(); - break; - } + case CMD_READ_SECTOR: + cmd_read_sector(); + break; + case CMD_WRITE_SECTOR: + cmd_write_sector(); break; - case TIMER_DRQ: - set_drq(); + case CMD_WRITE_FORMAT: + cmd_format_sector(); break; } } +//------------------------------------------------- +// delayed_drq - set DRQ after a necessary delay +//------------------------------------------------- + +TIMER_CALLBACK_MEMBER(wd1000_device::delayed_drq) +{ + set_drq(); +} + void wd1000_device::set_error(int error) { if (error) @@ -175,8 +181,7 @@ void wd1000_device::set_drq() if ((m_status & S_DRQ) == 0) { m_status |= S_DRQ; - if (!m_drq_cb.isnull()) - m_drq_cb(true); + m_drq_cb(true); } } @@ -185,8 +190,7 @@ void wd1000_device::drop_drq() if (m_status & S_DRQ) { m_status &= ~S_DRQ; - if (!m_drq_cb.isnull()) - m_drq_cb(false); + m_drq_cb(false); } } @@ -228,36 +232,36 @@ void wd1000_device::end_command() int wd1000_device::get_lbasector() { - hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file(); - hard_disk_info *info = hard_disk_get_info(file); + harddisk_image_device *file = m_drives[drive()]; + const auto &info = file->get_info(); int lbasector; - if (m_cylinder > info->cylinders) + if (m_cylinder > info.cylinders) { - logerror("%s: Unexpected cylinder %d for range 0 to %d\n", machine().describe_context(), m_cylinder, info->cylinders - 1); + logerror("%s: Unexpected cylinder %d for range 0 to %d\n", machine().describe_context(), m_cylinder, info.cylinders - 1); } - if (head() >= info->heads) + if (head() >= info.heads) { - logerror("%s: Unexpected head %d for range 0 to %d\n", machine().describe_context(), head(), info->heads - 1); + logerror("%s: Unexpected head %d for range 0 to %d\n", machine().describe_context(), head(), info.heads - 1); } int16_t sector = m_sector_number - m_sector_base; - if (sector < 0 || sector >= info->sectors) + if (sector < 0 || sector >= info.sectors) { - logerror("%s: Unexpected sector number %d for range %d to %d\n", machine().describe_context(), m_sector_number, m_sector_base, info->sectors + m_sector_base); + logerror("%s: Unexpected sector number %d for range %d to %d\n", machine().describe_context(), m_sector_number, m_sector_base, info.sectors + m_sector_base); } - if (sector_bytes() != info->sectorbytes) + if (sector_bytes() != info.sectorbytes) { - logerror("%s: Unexpected sector bytes %d, expected %d\n", machine().describe_context(), sector_bytes(), info->sectorbytes); + logerror("%s: Unexpected sector bytes %d, expected %d\n", machine().describe_context(), sector_bytes(), info.sectorbytes); } lbasector = m_cylinder; - lbasector *= info->heads; + lbasector *= info.heads; lbasector += head(); - lbasector *= info->sectors; + lbasector *= info.sectors; lbasector += sector; return lbasector; @@ -308,7 +312,7 @@ uint8_t wd1000_device::data_r() return data; } -READ8_MEMBER( wd1000_device::read ) +uint8_t wd1000_device::read(offs_t offset) { if ((m_status & S_BSY) && offset != 7) { @@ -413,7 +417,7 @@ void wd1000_device::data_w(uint8_t data) set_error(0); // Implied seek m_status &= ~S_SC; - int amount = abs(m_drives[drive()].cylinder - m_cylinder); + int amount = abs(m_drive_cylinder[drive()] - m_cylinder); int target = m_cylinder; m_seek_timer->adjust(get_stepping_rate() * amount, target); } @@ -429,7 +433,7 @@ void wd1000_device::data_w(uint8_t data) } } -WRITE8_MEMBER( wd1000_device::write ) +void wd1000_device::write(offs_t offset, uint8_t data) { switch (offset & 0x07) { @@ -476,7 +480,7 @@ WRITE8_MEMBER( wd1000_device::write ) // Update the drive ready flag in the status register which // indicates the ready state for the selected drive. // TODO should this also set the SC flag? - if (m_drives[drive].drive->exists()) + if (m_drives[drive] && m_drives[drive]->exists()) m_status |= S_RDY; else m_status &= ~S_RDY; @@ -519,7 +523,7 @@ WRITE8_MEMBER( wd1000_device::write ) start_command(); // Schedule an implied seek. m_status &= ~S_SC; - int amount = m_drives[drive()].cylinder; + int amount = m_drive_cylinder[drive()]; int target = 0; m_seek_timer->adjust(get_stepping_rate() * amount, target); break; @@ -529,7 +533,7 @@ WRITE8_MEMBER( wd1000_device::write ) case CMD_READ_SECTOR: { start_command(); - int amount = abs(m_drives[drive()].cylinder - m_cylinder); + int amount = abs(m_drive_cylinder[drive()] - m_cylinder); int target = m_cylinder; m_seek_timer->adjust(get_stepping_rate() * amount, target); break; @@ -558,12 +562,15 @@ void wd1000_device::cmd_restore() end_command(); } +// These commands should only be reachable if the status flag S_RDY is +// true, and that should only occur if the m_drives element is there, +// so it is not necessary to guard that case in these functions. void wd1000_device::cmd_read_sector() { - hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file(); + harddisk_image_device *file = m_drives[drive()]; uint8_t dma = BIT(m_command, 3); - hard_disk_read(file, get_lbasector(), m_buffer); + file->read(get_lbasector(), m_buffer); m_buffer_index = 0; m_buffer_end = 512; @@ -581,21 +588,21 @@ void wd1000_device::cmd_read_sector() void wd1000_device::cmd_write_sector() { - hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file(); + harddisk_image_device *file = m_drives[drive()]; if (m_buffer_index != sector_bytes()) { logerror("%s: Unexpected unfilled buffer on write, only %d or %d bytes filled\n", machine().describe_context(), m_buffer_index, sector_bytes()); } - hard_disk_write(file, get_lbasector(), m_buffer); + file->write(get_lbasector(), m_buffer); end_command(); } void wd1000_device::cmd_format_sector() { - hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file(); + harddisk_image_device *file = m_drives[drive()]; uint8_t buffer[512]; // The m_buffer appears to be loaded with an interleave table which is @@ -604,7 +611,7 @@ void wd1000_device::cmd_format_sector() for (int i = 0; i < m_sector_count; i++) { std::fill(std::begin(buffer), std::end(buffer), 0); - hard_disk_write(file, get_lbasector(), buffer); + file->write(get_lbasector(), buffer); } m_sector_count = 0; |