summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/wd1010.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/wd1010.cpp')
-rw-r--r--src/devices/machine/wd1010.cpp583
1 files changed, 0 insertions, 583 deletions
diff --git a/src/devices/machine/wd1010.cpp b/src/devices/machine/wd1010.cpp
deleted file mode 100644
index 16442934352..00000000000
--- a/src/devices/machine/wd1010.cpp
+++ /dev/null
@@ -1,583 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Dirk Best
-/***************************************************************************
-
- Western Digital WD1010-05 Winchester Disk Controller
-
-***************************************************************************/
-
-#include "emu.h"
-#include "wd1010.h"
-
-//#define LOG_GENERAL (1U << 0)
-#define LOG_CMD (1U << 1)
-#define LOG_INT (1U << 2)
-#define LOG_SEEK (1U << 3)
-#define LOG_REGS (1U << 4)
-#define LOG_DATA (1U << 5)
-
-//#define VERBOSE (LOG_CMD | LOG_INT | LOG_SEEK | LOG_REGS | LOG_DATA)
-//#define LOG_OUTPUT_STREAM std::cout
-
-#include "logmacro.h"
-
-#define LOGCMD(...) LOGMASKED(LOG_CMD, __VA_ARGS__)
-#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
-#define LOGSEEK(...) LOGMASKED(LOG_SEEK, __VA_ARGS__)
-#define LOGREGS(...) LOGMASKED(LOG_REGS, __VA_ARGS__)
-#define LOGDATA(...) LOGMASKED(LOG_DATA, __VA_ARGS__)
-
-
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(WD1010, wd1010_device, "wd1010", "Western Digital WD1010-05")
-
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// wd1010_device - constructor
-//-------------------------------------------------
-
-wd1010_device::wd1010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, WD1010, tag, owner, clock),
- m_out_intrq_cb(*this),
- m_out_bcr_cb(*this),
- m_in_data_cb(*this),
- m_out_data_cb(*this),
- m_intrq(0),
- m_brdy(0),
- m_stepping_rate(0x00),
- m_command(0x00),
- m_error(0x00),
- m_precomp(0x00),
- m_sector_count(0x00),
- m_sector_number(0x00),
- m_cylinder(0x0000),
- m_sdh(0x00),
- m_status(0x00)
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void wd1010_device::device_start()
-{
- // get connected drives
- 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].head = 0;
- m_drives[i].cylinder = 0;
- m_drives[i].sector = 0;
- }
-
- // resolve callbacks
- m_out_intrq_cb.resolve_safe();
- m_out_bcr_cb.resolve_safe();
- m_in_data_cb.resolve_safe(0);
- m_out_data_cb.resolve_safe();
-
- // allocate timer
- m_seek_timer = timer_alloc(TIMER_SEEK);
- m_data_timer = timer_alloc(TIMER_DATA);
-
- // register for save states
- save_item(NAME(m_intrq));
- save_item(NAME(m_brdy));
- 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));
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void wd1010_device::device_reset()
-{
-}
-
-//-------------------------------------------------
-// device_timer - device-specific timer
-//-------------------------------------------------
-
-void wd1010_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
-{
- switch (tid)
- {
- case TIMER_SEEK:
-
- if ((m_command >> 4) != CMD_SCAN_ID)
- {
- LOGSEEK("Seek complete\n");
- m_drives[drive()].cylinder = param;
- m_status |= STATUS_SC;
- }
-
- switch (m_command >> 4)
- {
- case CMD_RESTORE:
- cmd_restore();
- break;
-
- case CMD_SEEK:
- cmd_seek();
- break;
-
- case CMD_READ_SECTOR:
- cmd_read_sector();
- break;
-
- case CMD_WRITE_SECTOR:
- case CMD_WRITE_FORMAT:
- cmd_write_sector();
- break;
-
- case CMD_SCAN_ID:
- cmd_scan_id();
- break;
- }
-
- break;
-
- case TIMER_DATA:
-
- // check if data is ready or continue waiting
- if (m_brdy)
- cmd_write_sector();
- else
- m_data_timer->adjust(attotime::from_usec(35));
-
- break;
- }
-}
-
-//-------------------------------------------------
-// set_error - set error and adjust status
-//-------------------------------------------------
-
-void wd1010_device::set_error(int error)
-{
- if (error)
- {
- m_error |= error;
- m_status |= STATUS_ERR;
- }
- else
- {
- m_error = 0;
- m_status &= ~STATUS_ERR;
- }
-}
-
-//-------------------------------------------------
-// set_intrq - set interrupt status
-//-------------------------------------------------
-
-void wd1010_device::set_intrq(int state)
-{
- if (m_intrq == 0 && state == 1)
- {
- LOGINT("INT 1\n");
- m_intrq = 1;
- m_out_intrq_cb(1);
- }
- else if (m_intrq == 1 && state == 0)
- {
- LOGINT("INT 0\n");
- m_intrq = 0;
- m_out_intrq_cb(0);
- }
-}
-
-//-------------------------------------------------
-// get_stepping_rate - calculate stepping rate
-//-------------------------------------------------
-
-attotime wd1010_device::get_stepping_rate()
-{
- if (m_stepping_rate)
- return attotime::from_usec(500 * m_stepping_rate);
- else
- return attotime::from_usec(35);
-}
-
-//-------------------------------------------------
-// start_command - executed at the start of every command
-//-------------------------------------------------
-
-void wd1010_device::start_command()
-{
- // now busy and command in progress, clear error
- m_status |= STATUS_BSY;
- m_status |= STATUS_CIP;
- set_error(0);
-
- switch (m_command >> 4)
- {
- case CMD_RESTORE:
- m_stepping_rate = m_command & 0x0f;
- LOGCMD("RESTORE\n");
- break;
- case CMD_READ_SECTOR:
- LOGCMD("READ SECTOR\n");
- break;
- case CMD_WRITE_SECTOR:
- LOGCMD("WRITE SECTOR\n");
- break;
- case CMD_SCAN_ID:
- LOGCMD("SCAN ID\n");
- break;
- case CMD_WRITE_FORMAT:
- LOGCMD("WRITE FORMAT ID\n");
- break;
- case CMD_SEEK:
- m_stepping_rate = m_command & 0x0f;
- LOGCMD("SEEK\n");
- break;
- }
-}
-
-//-------------------------------------------------
-// end_command - executed at end of every command
-//-------------------------------------------------
-
-void wd1010_device::end_command()
-{
- m_out_bcr_cb(1);
- m_out_bcr_cb(0);
-
- m_status &= ~(STATUS_BSY | STATUS_CIP);
-
- set_intrq(1);
-}
-
-//-------------------------------------------------
-// get_lbasector - translate to lba
-//-------------------------------------------------
-
-int wd1010_device::get_lbasector()
-{
- hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file();
- hard_disk_info *info = hard_disk_get_info(file);
- int lbasector;
-
- lbasector = m_cylinder;
- lbasector *= info->heads;
- lbasector += head();
- lbasector *= info->sectors;
- lbasector += m_sector_number;
-
- return lbasector;
-}
-
-
-//**************************************************************************
-// INTERFACE
-//**************************************************************************
-
-WRITE_LINE_MEMBER( wd1010_device::drdy_w )
-{
- if (state)
- m_status |= STATUS_RDY;
- else
- m_status &= ~STATUS_RDY;
-}
-
-WRITE_LINE_MEMBER( wd1010_device::brdy_w )
-{
- m_brdy = state;
-}
-
-READ8_MEMBER( wd1010_device::read )
-{
- // if the controller is busy all reads return the status register
- if (m_status & STATUS_BSY)
- {
- LOG("Read while busy, return STATUS: %02x\n", m_status);
- return m_status;
- }
-
- switch (offset & 0x07)
- {
- case 0:
- LOGREGS("RD INVALID\n");
- return 0;
-
- case 1:
- LOGREGS("RD ERROR: %02x\n", m_error);
- return m_error;
-
- case 2:
- LOGREGS("RD SECTOR COUNT: %02x\n", m_sector_count);
- return m_sector_count;
-
- case 3:
- LOGREGS("RD SECTOR NUMBER: %02x\n", m_sector_number);
- return m_sector_number;
-
- case 4:
- LOGREGS("RD CYLINDER L: %02x\n", m_cylinder & 0xff);
- return m_cylinder & 0xff;
-
- case 5:
- LOGREGS("RD CYLINDER H: %02x\n", m_cylinder >> 8);
- return m_cylinder >> 8;
-
- case 6:
- LOGREGS("RD SDH: %02x\n", m_sdh);
- return m_sdh;
-
- case 7:
- LOGREGS("RD STATUS: %02x\n", m_status);
-
- // reading the status register clears the interrupt
- set_intrq(0);
-
- return m_status;
- }
-
- // should never get here
- return 0xff;
-}
-
-WRITE8_MEMBER( wd1010_device::write )
-{
- switch (offset & 0x07)
- {
- case 0:
- LOGREGS("WR INVALID: %02x\n", data);
- break;
-
- case 1:
- LOGREGS("WR PRECOMP: %02x\n", data);
- m_precomp = data;
- break;
-
- case 2:
- LOGREGS("WR SECTOR COUNT: %02x\n", data);
- m_sector_count = data;
- break;
-
- case 3:
- LOGREGS("WR SECTOR NUMBER: %02x\n", data);
- m_sector_number = data;
- break;
-
- case 4:
- LOGREGS("WR CYLINDER L: %02x\n", data);
- m_cylinder = (m_cylinder & 0xff00) | (data << 0);
- break;
-
- case 5:
- LOGREGS("WR CYLINDER H: %02x\n", data);
- m_cylinder = (m_cylinder & 0x00ff) | (data << 8);
- break;
-
- case 6:
- LOGREGS("WR SDH: %02x\n", data);
- m_sdh = data;
- break;
-
- case 7:
- // writes to the command register are ignored when a command is in progress
- if (m_status & STATUS_CIP)
- return;
-
- // writing the command register clears the interrupt
- set_intrq(0);
-
- // check drive status
- if (!(m_status & STATUS_RDY))
- {
- // selected drive not ready
- LOG("--> Drive not ready, aborting\n");
-
- set_error(ERR_AC);
- end_command();
- }
- else
- {
- m_command = data;
-
- start_command();
-
- // all other command imply a seek
- if ((m_command >> 4) != CMD_SCAN_ID)
- m_status &= ~STATUS_SC;
-
- int amount = 0;
- int target = 0;
-
- switch (m_command >> 4)
- {
- case CMD_RESTORE:
- amount = m_drives[drive()].cylinder;
- target = 0;
- break;
-
- case CMD_SEEK:
- case CMD_READ_SECTOR:
- case CMD_WRITE_SECTOR:
- case CMD_WRITE_FORMAT:
- amount = abs(m_drives[drive()].cylinder - m_cylinder);
- target = m_cylinder;
- break;
- }
-
- if ((m_command >> 4) != CMD_SCAN_ID)
- LOGSEEK("Seeking %d cylinders to %d\n", amount, target);
-
- m_seek_timer->adjust(get_stepping_rate() * amount, target);
- }
-
- break;
- }
-}
-
-
-//**************************************************************************
-// IMPLEMENTATION
-//**************************************************************************
-
-void wd1010_device::cmd_restore()
-{
- LOGCMD("--> RESTORE done\n");
- end_command();
-}
-
-void wd1010_device::cmd_read_sector()
-{
- hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file();
- hard_disk_info *info = hard_disk_get_info(file);
-
- m_out_bcr_cb(1);
- m_out_bcr_cb(0);
-
- // verify that we can read
- if (head() > info->heads)
- {
- // out of range
- LOG("--> Head out of range, aborting\n");
-
- set_error(ERR_AC);
- end_command();
- }
- else
- {
- uint8_t buffer[512];
-
- while (m_sector_count > 0)
- {
- LOGDATA("--> Transferring sector to buffer (lba = %08x)\n", get_lbasector());
-
- hard_disk_read(file, get_lbasector(), buffer);
-
- for (int i = 0; i < 512; i++)
- m_out_data_cb(buffer[i]);
-
- m_out_bcr_cb(1);
- m_out_bcr_cb(0);
-
- // save last read head and sector number
- m_drives[drive()].head = head();
- m_drives[drive()].sector = m_sector_number;
-
- if (BIT(m_command, 2))
- {
- m_sector_number++;
- m_sector_count--;
- }
- else
- break;
- }
-
- end_command();
- }
-}
-
-void wd1010_device::cmd_write_sector()
-{
- if (!(m_status & STATUS_DRQ))
- {
- LOGDATA("Setting DATA REQUEST\n");
- m_status |= STATUS_DRQ;
- m_data_timer->adjust(attotime::from_usec(35));
- return;
- }
-
- if (m_brdy == 0)
- {
- m_data_timer->adjust(attotime::from_usec(35));
- return;
- }
-
- LOGDATA("Clearing DATA REQUEST\n");
- m_status &= ~STATUS_DRQ;
-
- hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file();
- uint8_t buffer[512];
-
- while (m_sector_count > 0)
- {
- if ((m_command >> 4) == CMD_WRITE_FORMAT)
- {
- // we ignore the format specification and fill everything with 0xe5
- std::fill(std::begin(buffer), std::end(buffer), 0xe5);
- }
- else
- {
- // get data for sector from buffer chip
- for (int i = 0; i < 512; i++)
- buffer[i] = m_in_data_cb();
- }
-
- hard_disk_write(file, get_lbasector(), buffer);
-
- // save last read head and sector number
- m_drives[drive()].head = head();
- m_drives[drive()].sector = m_sector_number;
-
- if (BIT(m_command, 2))
- {
- m_sector_number++;
- m_sector_count--;
- }
- else
- break;
- }
-
- end_command();
-}
-
-void wd1010_device::cmd_scan_id()
-{
- // update head, sector size, sector number and cylinder
- m_sdh = (m_sdh & 0xf8) | (m_drives[drive()].head & 0x07);
- m_sector_number = m_drives[drive()].sector;
- m_cylinder = m_drives[drive()].cylinder;
-
- end_command();
-}
-
-void wd1010_device::cmd_seek()
-{
- LOGCMD("--> SEEK done\n");
- end_command();
-}