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_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
|
||||
|
||||
#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) :
|
||||
device_t(mconfig, WD1010, tag, owner, clock),
|
||||
m_out_intrq_cb(*this),
|
||||
m_out_bdrq_cb(*this),
|
||||
m_out_bcs_cb(*this),
|
||||
m_out_bcr_cb(*this),
|
||||
m_out_dirin_cb(*this),
|
||||
m_out_wg_cb(*this),
|
||||
m_in_data_cb(*this),
|
||||
m_out_data_cb(*this),
|
||||
m_intrq(0),
|
||||
@ -83,13 +87,18 @@ void wd1010_device::device_start()
|
||||
|
||||
// resolve callbacks
|
||||
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_dirin_cb.resolve_safe();
|
||||
m_out_wg_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);
|
||||
m_read_timer = timer_alloc(TIMER_READ);
|
||||
m_write_timer = timer_alloc(TIMER_WRITE);
|
||||
|
||||
// register for save states
|
||||
save_item(NAME(m_intrq));
|
||||
@ -156,14 +165,12 @@ void wd1010_device::device_timer(emu_timer &timer, device_timer_id tid, int para
|
||||
|
||||
break;
|
||||
|
||||
case TIMER_DATA:
|
||||
case TIMER_READ:
|
||||
cmd_read_sector();
|
||||
break;
|
||||
|
||||
// check if data is ready or continue waiting
|
||||
if (m_brdy)
|
||||
case TIMER_WRITE:
|
||||
cmd_write_sector();
|
||||
else
|
||||
m_data_timer->adjust(attotime::from_usec(35));
|
||||
|
||||
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
|
||||
//-------------------------------------------------
|
||||
@ -305,6 +332,16 @@ void wd1010_device::brdy_w(int 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)
|
||||
{
|
||||
// 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)
|
||||
m_status &= ~STATUS_SC;
|
||||
|
||||
int amount = 0;
|
||||
int seek = 0;
|
||||
int target = 0;
|
||||
|
||||
switch (m_command >> 4)
|
||||
{
|
||||
case CMD_RESTORE:
|
||||
amount = m_drives[drive()].cylinder;
|
||||
seek = m_drives[drive()].cylinder;
|
||||
target = 0;
|
||||
break;
|
||||
|
||||
@ -437,15 +474,17 @@ void wd1010_device::write(offs_t offset, uint8_t data)
|
||||
case CMD_READ_SECTOR:
|
||||
case CMD_WRITE_SECTOR:
|
||||
case CMD_WRITE_FORMAT:
|
||||
amount = abs(m_drives[drive()].cylinder - m_cylinder);
|
||||
seek = 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_out_dirin_cb(seek > 0 ? 1 : 0);
|
||||
|
||||
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;
|
||||
@ -465,12 +504,30 @@ void wd1010_device::cmd_restore()
|
||||
|
||||
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_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)
|
||||
{
|
||||
@ -479,13 +536,16 @@ void wd1010_device::cmd_read_sector()
|
||||
|
||||
set_error(ERR_AC);
|
||||
end_command();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
uint8_t buffer[512];
|
||||
|
||||
while (m_sector_count > 0)
|
||||
{
|
||||
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);
|
||||
@ -493,50 +553,58 @@ void wd1010_device::cmd_read_sector()
|
||||
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;
|
||||
|
||||
// multi-sector read
|
||||
if (BIT(m_command, 2))
|
||||
{
|
||||
m_sector_number++;
|
||||
m_sector_count--;
|
||||
}
|
||||
else
|
||||
break;
|
||||
{
|
||||
m_sector_count = 0;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
if (!(m_status & STATUS_DRQ))
|
||||
{
|
||||
LOGDATA("Setting DATA REQUEST\n");
|
||||
m_status |= STATUS_DRQ;
|
||||
m_data_timer->adjust(attotime::from_usec(35));
|
||||
return;
|
||||
}
|
||||
set_bdrq(1);
|
||||
|
||||
// wait if the buffer isn't ready
|
||||
if (m_brdy == 0)
|
||||
{
|
||||
m_data_timer->adjust(attotime::from_usec(35));
|
||||
m_write_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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// we ignore the format specification and fill everything with 0xe5
|
||||
@ -555,15 +623,25 @@ void wd1010_device::cmd_write_sector()
|
||||
m_drives[drive()].head = head();
|
||||
m_drives[drive()].sector = m_sector_number;
|
||||
|
||||
if (BIT(m_command, 2))
|
||||
// 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;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
m_out_bcs_cb(0);
|
||||
m_out_wg_cb(0);
|
||||
|
||||
end_command();
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,11 @@ public:
|
||||
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_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_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 out_data_callback() { return m_out_data_cb.bind(); }
|
||||
|
||||
@ -37,6 +41,10 @@ public:
|
||||
void drdy_w(int state);
|
||||
void brdy_w(int state);
|
||||
|
||||
// actually inputs to the controller from the drive
|
||||
int sc_r();
|
||||
int tk000_r();
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
@ -81,11 +89,13 @@ private:
|
||||
enum
|
||||
{
|
||||
TIMER_SEEK,
|
||||
TIMER_DATA
|
||||
TIMER_READ,
|
||||
TIMER_WRITE
|
||||
};
|
||||
|
||||
void set_error(int error);
|
||||
void set_intrq(int state);
|
||||
void set_bdrq(int state);
|
||||
attotime get_stepping_rate();
|
||||
void start_command();
|
||||
void end_command();
|
||||
@ -107,7 +117,11 @@ private:
|
||||
void cmd_seek();
|
||||
|
||||
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_dirin_cb;
|
||||
devcb_write_line m_out_wg_cb;
|
||||
devcb_read8 m_in_data_cb;
|
||||
devcb_write8 m_out_data_cb;
|
||||
|
||||
@ -120,9 +134,11 @@ private:
|
||||
} m_drives[4];
|
||||
|
||||
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_bdrq;
|
||||
int m_brdy;
|
||||
uint8_t m_stepping_rate;
|
||||
uint8_t m_command;
|
||||
|
Loading…
Reference in New Issue
Block a user