mirror of
https://github.com/holub/mame
synced 2025-07-01 08:18:59 +03:00
wd1010: Improve implementation
This commit is contained in:
parent
7099d9f326
commit
ecf98318b4
@ -16,7 +16,7 @@
|
|||||||
#define LOG_REGS (1U << 4)
|
#define LOG_REGS (1U << 4)
|
||||||
#define LOG_DATA (1U << 5)
|
#define LOG_DATA (1U << 5)
|
||||||
|
|
||||||
//#define VERBOSE (LOG_CMD | LOG_INT | LOG_SEEK | LOG_REGS | LOG_DATA)
|
#define VERBOSE (LOG_CMD | LOG_INT | LOG_SEEK | LOG_REGS | LOG_DATA)
|
||||||
//#define LOG_OUTPUT_STREAM std::cout
|
//#define LOG_OUTPUT_STREAM std::cout
|
||||||
|
|
||||||
#include "logmacro.h"
|
#include "logmacro.h"
|
||||||
@ -46,7 +46,11 @@ DEFINE_DEVICE_TYPE(WD1010, wd1010_device, "wd1010", "Western Digital WD1010-05")
|
|||||||
wd1010_device::wd1010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
wd1010_device::wd1010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||||
device_t(mconfig, WD1010, tag, owner, clock),
|
device_t(mconfig, WD1010, tag, owner, clock),
|
||||||
m_out_intrq_cb(*this),
|
m_out_intrq_cb(*this),
|
||||||
|
m_out_bdrq_cb(*this),
|
||||||
|
m_out_bcs_cb(*this),
|
||||||
m_out_bcr_cb(*this),
|
m_out_bcr_cb(*this),
|
||||||
|
m_out_dirin_cb(*this),
|
||||||
|
m_out_wg_cb(*this),
|
||||||
m_in_data_cb(*this),
|
m_in_data_cb(*this),
|
||||||
m_out_data_cb(*this),
|
m_out_data_cb(*this),
|
||||||
m_intrq(0),
|
m_intrq(0),
|
||||||
@ -83,13 +87,18 @@ void wd1010_device::device_start()
|
|||||||
|
|
||||||
// resolve callbacks
|
// resolve callbacks
|
||||||
m_out_intrq_cb.resolve_safe();
|
m_out_intrq_cb.resolve_safe();
|
||||||
|
m_out_bdrq_cb.resolve_safe();
|
||||||
|
m_out_bcs_cb.resolve_safe();
|
||||||
m_out_bcr_cb.resolve_safe();
|
m_out_bcr_cb.resolve_safe();
|
||||||
|
m_out_dirin_cb.resolve_safe();
|
||||||
|
m_out_wg_cb.resolve_safe();
|
||||||
m_in_data_cb.resolve_safe(0);
|
m_in_data_cb.resolve_safe(0);
|
||||||
m_out_data_cb.resolve_safe();
|
m_out_data_cb.resolve_safe();
|
||||||
|
|
||||||
// allocate timer
|
// allocate timer
|
||||||
m_seek_timer = timer_alloc(TIMER_SEEK);
|
m_seek_timer = timer_alloc(TIMER_SEEK);
|
||||||
m_data_timer = timer_alloc(TIMER_DATA);
|
m_read_timer = timer_alloc(TIMER_READ);
|
||||||
|
m_write_timer = timer_alloc(TIMER_WRITE);
|
||||||
|
|
||||||
// register for save states
|
// register for save states
|
||||||
save_item(NAME(m_intrq));
|
save_item(NAME(m_intrq));
|
||||||
@ -156,14 +165,12 @@ void wd1010_device::device_timer(emu_timer &timer, device_timer_id tid, int para
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIMER_DATA:
|
case TIMER_READ:
|
||||||
|
cmd_read_sector();
|
||||||
// check if data is ready or continue waiting
|
break;
|
||||||
if (m_brdy)
|
|
||||||
cmd_write_sector();
|
|
||||||
else
|
|
||||||
m_data_timer->adjust(attotime::from_usec(35));
|
|
||||||
|
|
||||||
|
case TIMER_WRITE:
|
||||||
|
cmd_write_sector();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,6 +213,26 @@ void wd1010_device::set_intrq(int state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// set_bdrq - set drq status
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void wd1010_device::set_bdrq(int state)
|
||||||
|
{
|
||||||
|
if ((!(m_status & STATUS_DRQ)) && state == 1)
|
||||||
|
{
|
||||||
|
LOGINT("DRQ 1\n");
|
||||||
|
m_status |= STATUS_DRQ;
|
||||||
|
m_out_bdrq_cb(1);
|
||||||
|
}
|
||||||
|
else if ((m_status & STATUS_DRQ) && state == 0)
|
||||||
|
{
|
||||||
|
LOGINT("DRQ 0\n");
|
||||||
|
m_status &= ~STATUS_DRQ;
|
||||||
|
m_out_bdrq_cb(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// get_stepping_rate - calculate stepping rate
|
// get_stepping_rate - calculate stepping rate
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
@ -305,6 +332,16 @@ void wd1010_device::brdy_w(int state)
|
|||||||
m_brdy = state;
|
m_brdy = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int wd1010_device::sc_r()
|
||||||
|
{
|
||||||
|
return m_status & STATUS_SC ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wd1010_device::tk000_r()
|
||||||
|
{
|
||||||
|
return m_drives[drive()].cylinder == 0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t wd1010_device::read(offs_t offset)
|
uint8_t wd1010_device::read(offs_t offset)
|
||||||
{
|
{
|
||||||
// if the controller is busy all reads return the status register
|
// if the controller is busy all reads return the status register
|
||||||
@ -423,13 +460,13 @@ void wd1010_device::write(offs_t offset, uint8_t data)
|
|||||||
if ((m_command >> 4) != CMD_SCAN_ID)
|
if ((m_command >> 4) != CMD_SCAN_ID)
|
||||||
m_status &= ~STATUS_SC;
|
m_status &= ~STATUS_SC;
|
||||||
|
|
||||||
int amount = 0;
|
int seek = 0;
|
||||||
int target = 0;
|
int target = 0;
|
||||||
|
|
||||||
switch (m_command >> 4)
|
switch (m_command >> 4)
|
||||||
{
|
{
|
||||||
case CMD_RESTORE:
|
case CMD_RESTORE:
|
||||||
amount = m_drives[drive()].cylinder;
|
seek = m_drives[drive()].cylinder;
|
||||||
target = 0;
|
target = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -437,15 +474,17 @@ void wd1010_device::write(offs_t offset, uint8_t data)
|
|||||||
case CMD_READ_SECTOR:
|
case CMD_READ_SECTOR:
|
||||||
case CMD_WRITE_SECTOR:
|
case CMD_WRITE_SECTOR:
|
||||||
case CMD_WRITE_FORMAT:
|
case CMD_WRITE_FORMAT:
|
||||||
amount = abs(m_drives[drive()].cylinder - m_cylinder);
|
seek = m_drives[drive()].cylinder - m_cylinder;
|
||||||
target = m_cylinder;
|
target = m_cylinder;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_command >> 4) != CMD_SCAN_ID)
|
m_out_dirin_cb(seek > 0 ? 1 : 0);
|
||||||
LOGSEEK("Seeking %d cylinders to %d\n", amount, target);
|
|
||||||
|
|
||||||
m_seek_timer->adjust(get_stepping_rate() * amount, target);
|
if ((m_command >> 4) != CMD_SCAN_ID)
|
||||||
|
LOGSEEK("Seeking %d cylinders to %d\n", seek, target);
|
||||||
|
|
||||||
|
m_seek_timer->adjust(get_stepping_rate() * abs(seek), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -465,12 +504,30 @@ void wd1010_device::cmd_restore()
|
|||||||
|
|
||||||
void wd1010_device::cmd_read_sector()
|
void wd1010_device::cmd_read_sector()
|
||||||
{
|
{
|
||||||
|
if (m_status & STATUS_DRQ)
|
||||||
|
{
|
||||||
|
if (m_brdy)
|
||||||
|
{
|
||||||
|
set_bdrq(0);
|
||||||
|
|
||||||
|
// if there's nothing left we're done
|
||||||
|
if (m_sector_count == 0)
|
||||||
|
{
|
||||||
|
end_command();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// continue waiting for the buffer to be ready
|
||||||
|
m_read_timer->adjust(attotime::from_usec(35));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file();
|
hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file();
|
||||||
hard_disk_info *info = hard_disk_get_info(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
|
// verify that we can read
|
||||||
if (head() > info->heads)
|
if (head() > info->heads)
|
||||||
{
|
{
|
||||||
@ -479,90 +536,111 @@ void wd1010_device::cmd_read_sector()
|
|||||||
|
|
||||||
set_error(ERR_AC);
|
set_error(ERR_AC);
|
||||||
end_command();
|
end_command();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t buffer[512];
|
||||||
|
|
||||||
|
m_out_bcr_cb(1);
|
||||||
|
m_out_bcr_cb(0);
|
||||||
|
|
||||||
|
m_out_bcs_cb(1);
|
||||||
|
|
||||||
|
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]);
|
||||||
|
|
||||||
|
// multi-sector read
|
||||||
|
if (BIT(m_command, 2))
|
||||||
|
{
|
||||||
|
m_sector_number++;
|
||||||
|
m_sector_count--;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint8_t buffer[512];
|
m_sector_count = 0;
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_sector_count == 0)
|
||||||
|
{
|
||||||
|
m_out_bcr_cb(1);
|
||||||
|
m_out_bcr_cb(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_out_bcs_cb(0);
|
||||||
|
|
||||||
|
set_bdrq(1);
|
||||||
|
|
||||||
|
// interrupt at bdrq time?
|
||||||
|
if (BIT(m_command, 3) == 0)
|
||||||
|
set_intrq(1);
|
||||||
|
|
||||||
|
// now wait for brdy
|
||||||
|
m_read_timer->adjust(attotime::from_usec(35));
|
||||||
}
|
}
|
||||||
|
|
||||||
void wd1010_device::cmd_write_sector()
|
void wd1010_device::cmd_write_sector()
|
||||||
{
|
{
|
||||||
if (!(m_status & STATUS_DRQ))
|
set_bdrq(1);
|
||||||
{
|
|
||||||
LOGDATA("Setting DATA REQUEST\n");
|
|
||||||
m_status |= STATUS_DRQ;
|
|
||||||
m_data_timer->adjust(attotime::from_usec(35));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// wait if the buffer isn't ready
|
||||||
if (m_brdy == 0)
|
if (m_brdy == 0)
|
||||||
{
|
{
|
||||||
m_data_timer->adjust(attotime::from_usec(35));
|
m_write_timer->adjust(attotime::from_usec(35));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGDATA("Clearing DATA REQUEST\n");
|
|
||||||
m_status &= ~STATUS_DRQ;
|
|
||||||
|
|
||||||
hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file();
|
hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file();
|
||||||
uint8_t buffer[512];
|
uint8_t buffer[512];
|
||||||
|
|
||||||
while (m_sector_count > 0)
|
set_bdrq(0);
|
||||||
|
|
||||||
|
m_out_bcr_cb(1);
|
||||||
|
m_out_bcr_cb(0);
|
||||||
|
|
||||||
|
m_out_bcs_cb(1);
|
||||||
|
|
||||||
|
m_out_wg_cb(1);
|
||||||
|
|
||||||
|
if ((m_command >> 4) == CMD_WRITE_FORMAT)
|
||||||
{
|
{
|
||||||
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);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
|
||||||
|
// multi-sector write
|
||||||
|
if (BIT(m_command, 2) && m_sector_count > 0)
|
||||||
|
{
|
||||||
|
m_sector_number++;
|
||||||
|
m_sector_count--;
|
||||||
|
|
||||||
|
// schedule another run if we aren't finished yet
|
||||||
|
if (m_sector_count > 0)
|
||||||
|
{
|
||||||
|
m_out_bcs_cb(0);
|
||||||
|
m_out_wg_cb(0);
|
||||||
|
m_write_timer->adjust(attotime::from_usec(35));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_out_bcs_cb(0);
|
||||||
|
m_out_wg_cb(0);
|
||||||
|
|
||||||
end_command();
|
end_command();
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,11 @@ public:
|
|||||||
wd1010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
wd1010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||||
|
|
||||||
auto out_intrq_callback() { return m_out_intrq_cb.bind(); }
|
auto out_intrq_callback() { return m_out_intrq_cb.bind(); }
|
||||||
|
auto out_bdrq_callback() { return m_out_bdrq_cb.bind(); }
|
||||||
|
auto out_bcs_callback() { return m_out_bcs_cb.bind(); }
|
||||||
auto out_bcr_callback() { return m_out_bcr_cb.bind(); }
|
auto out_bcr_callback() { return m_out_bcr_cb.bind(); }
|
||||||
|
auto out_dirin_callback() { return m_out_dirin_cb.bind(); }
|
||||||
|
auto out_wg_callback() { return m_out_wg_cb.bind(); }
|
||||||
auto in_data_callback() { return m_in_data_cb.bind(); }
|
auto in_data_callback() { return m_in_data_cb.bind(); }
|
||||||
auto out_data_callback() { return m_out_data_cb.bind(); }
|
auto out_data_callback() { return m_out_data_cb.bind(); }
|
||||||
|
|
||||||
@ -37,6 +41,10 @@ public:
|
|||||||
void drdy_w(int state);
|
void drdy_w(int state);
|
||||||
void brdy_w(int state);
|
void brdy_w(int state);
|
||||||
|
|
||||||
|
// actually inputs to the controller from the drive
|
||||||
|
int sc_r();
|
||||||
|
int tk000_r();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// device-level overrides
|
// device-level overrides
|
||||||
virtual void device_start() override;
|
virtual void device_start() override;
|
||||||
@ -81,11 +89,13 @@ private:
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
TIMER_SEEK,
|
TIMER_SEEK,
|
||||||
TIMER_DATA
|
TIMER_READ,
|
||||||
|
TIMER_WRITE
|
||||||
};
|
};
|
||||||
|
|
||||||
void set_error(int error);
|
void set_error(int error);
|
||||||
void set_intrq(int state);
|
void set_intrq(int state);
|
||||||
|
void set_bdrq(int state);
|
||||||
attotime get_stepping_rate();
|
attotime get_stepping_rate();
|
||||||
void start_command();
|
void start_command();
|
||||||
void end_command();
|
void end_command();
|
||||||
@ -107,7 +117,11 @@ private:
|
|||||||
void cmd_seek();
|
void cmd_seek();
|
||||||
|
|
||||||
devcb_write_line m_out_intrq_cb;
|
devcb_write_line m_out_intrq_cb;
|
||||||
|
devcb_write_line m_out_bdrq_cb;
|
||||||
|
devcb_write_line m_out_bcs_cb;
|
||||||
devcb_write_line m_out_bcr_cb;
|
devcb_write_line m_out_bcr_cb;
|
||||||
|
devcb_write_line m_out_dirin_cb;
|
||||||
|
devcb_write_line m_out_wg_cb;
|
||||||
devcb_read8 m_in_data_cb;
|
devcb_read8 m_in_data_cb;
|
||||||
devcb_write8 m_out_data_cb;
|
devcb_write8 m_out_data_cb;
|
||||||
|
|
||||||
@ -120,9 +134,11 @@ private:
|
|||||||
} m_drives[4];
|
} m_drives[4];
|
||||||
|
|
||||||
emu_timer *m_seek_timer;
|
emu_timer *m_seek_timer;
|
||||||
emu_timer *m_data_timer;
|
emu_timer *m_read_timer;
|
||||||
|
emu_timer *m_write_timer;
|
||||||
|
|
||||||
int m_intrq;
|
int m_intrq;
|
||||||
|
int m_bdrq;
|
||||||
int m_brdy;
|
int m_brdy;
|
||||||
uint8_t m_stepping_rate;
|
uint8_t m_stepping_rate;
|
||||||
uint8_t m_command;
|
uint8_t m_command;
|
||||||
|
Loading…
Reference in New Issue
Block a user