summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/wd1000.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/wd1000.cpp')
-rw-r--r--src/devices/machine/wd1000.cpp157
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;