mirror of
https://github.com/holub/mame
synced 2025-04-26 18:23:08 +03:00
Update wd2010.cpp
Use calculated access times - typical for MFM drives of that age - instead of hard coded values.
This commit is contained in:
parent
6c7e77189e
commit
1f6c45b092
@ -17,7 +17,7 @@ Implements WD2010 / WD1010 controller basics for a single hard disk.
|
|||||||
|
|
||||||
UNIMPLEMENTED FEATURES :
|
UNIMPLEMENTED FEATURES :
|
||||||
- more than 1 drive (untested)
|
- more than 1 drive (untested)
|
||||||
- multi sector transfers (M = 1)
|
- multi sector transfers (M = 1)
|
||||||
- seek and index timers / ID not found.
|
- seek and index timers / ID not found.
|
||||||
- implied seeks / implied writes / retries
|
- implied seeks / implied writes / retries
|
||||||
- edge or level triggered seek complete (SC)
|
- edge or level triggered seek complete (SC)
|
||||||
@ -41,7 +41,7 @@ UNIMPLEMENTED FEATURES :
|
|||||||
#define VERBOSE 1
|
#define VERBOSE 1
|
||||||
#include "logmacro.h"
|
#include "logmacro.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
// MACROS / CONSTANTS
|
// MACROS / CONSTANTS
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
@ -60,6 +60,14 @@ UNIMPLEMENTED FEATURES :
|
|||||||
#define MAX_MFM_SECTORS 17 // STANDARD MFM SECTORS/TRACK
|
#define MAX_MFM_SECTORS 17 // STANDARD MFM SECTORS/TRACK
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
|
||||||
|
// Typical access times for MFM drives (as listed in ST412_OEM Manual_Apr82)
|
||||||
|
#define SETTLING_MS 15.0
|
||||||
|
#define LATENCY_MS 8.33
|
||||||
|
|
||||||
|
// Step rates in ms for 5 Mhz WCLK (35 uS when zero)
|
||||||
|
#define STEP_RATE_MS \
|
||||||
|
(float) ( (data & 0x0f) ? ((data & 0x0f) * 0.5) : 0.035 )
|
||||||
|
|
||||||
|
|
||||||
// task file
|
// task file
|
||||||
enum
|
enum
|
||||||
@ -93,11 +101,11 @@ enum
|
|||||||
#define DRIVE \
|
#define DRIVE \
|
||||||
((m_task_file[TASK_FILE_SDH_REGISTER] >> 3) & 0x03)
|
((m_task_file[TASK_FILE_SDH_REGISTER] >> 3) & 0x03)
|
||||||
|
|
||||||
static constexpr int SECTOR_SIZES[4] = { 256, 512, 1024, 128 };
|
|
||||||
|
|
||||||
#define SECTOR_SIZE \
|
#define SECTOR_SIZE \
|
||||||
SECTOR_SIZES[(m_task_file[TASK_FILE_SDH_REGISTER] >> 5) & 0x03]
|
SECTOR_SIZES[(m_task_file[TASK_FILE_SDH_REGISTER] >> 5) & 0x03]
|
||||||
|
|
||||||
|
static constexpr int SECTOR_SIZES[4] = { 256, 512, 1024, 128 };
|
||||||
|
|
||||||
// status register
|
// status register
|
||||||
#define STATUS_BSY 0x80
|
#define STATUS_BSY 0x80
|
||||||
#define STATUS_RDY 0x40
|
#define STATUS_RDY 0x40
|
||||||
@ -130,8 +138,6 @@ static constexpr int SECTOR_SIZES[4] = { 256, 512, 1024, 128 };
|
|||||||
#define COMMAND_SET_PARAMETER_MASK 0xfe
|
#define COMMAND_SET_PARAMETER_MASK 0xfe
|
||||||
#define COMMAND_SET_PARAMETER 0x00
|
#define COMMAND_SET_PARAMETER 0x00
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
// DEVICE DEFINITIONS
|
// DEVICE DEFINITIONS
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
@ -390,17 +396,13 @@ void wd2010_device::restore(uint8_t data)
|
|||||||
|
|
||||||
m_out_rwc_cb(0); // reset RWC, set direction = OUT
|
m_out_rwc_cb(0); // reset RWC, set direction = OUT
|
||||||
|
|
||||||
// datasheet: DIRIN HIGH = in ; LOW = out
|
// Datasheet: DIRIN HIGH = in ; LOW = out
|
||||||
m_out_dirin_cb(0); // 0 = heads move away from the spindle, towards track O.
|
m_out_dirin_cb(0); // 0 = heads move away from the spindle, towards track O.
|
||||||
|
|
||||||
// TODO: store step rate
|
// Omitted: store step rate for later (implied seeks).
|
||||||
|
|
||||||
m_present_cylinder = 0; // (sse WD2010-05 datasheet)
|
|
||||||
m_task_file[TASK_FILE_CYLINDER_HIGH] = 0;
|
|
||||||
m_task_file[TASK_FILE_CYLINDER_LOW] = 0;
|
|
||||||
|
|
||||||
int step_pulses = 0;
|
int step_pulses = 0;
|
||||||
while (step_pulses < STEP_LIMIT)
|
while (step_pulses <= STEP_LIMIT)
|
||||||
{
|
{
|
||||||
while (!m_in_sc_cb())
|
while (!m_in_sc_cb())
|
||||||
{
|
{
|
||||||
@ -415,25 +417,20 @@ void wd2010_device::restore(uint8_t data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (m_in_tk000_cb())
|
if ( m_in_tk000_cb() || (step_pulses == STEP_LIMIT) ) // Simulate TRACK 00 signal (normally from DRIVE)
|
||||||
if (step_pulses == STEP_LIMIT - 2) // Simulate TRACK 00 signal (normally from DRIVE)
|
|
||||||
{
|
{
|
||||||
m_out_bcr_cb(0); // pulse BCR
|
m_present_cylinder = 0;
|
||||||
m_out_bcr_cb(1);
|
m_task_file[TASK_FILE_CYLINDER_HIGH] = 0;
|
||||||
newstatus &= ~(STATUS_BSY | STATUS_CIP); // prepare new status; (INTRQ later) reset BSY, CIP
|
m_task_file[TASK_FILE_CYLINDER_LOW] = 0;
|
||||||
complete_cmd(newstatus);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (step_pulses == STEP_LIMIT - 1) // NOTE: STEP_LIMIT - differs - between WD2010 and WD1010
|
|
||||||
{
|
|
||||||
m_error = ERROR_TK; // ERROR: track 0 not reached within limit
|
|
||||||
newstatus = newstatus | STATUS_ERR;
|
|
||||||
|
|
||||||
m_out_bcr_cb(0); // pulse BCR
|
m_out_bcr_cb(0); // pulse BCR
|
||||||
m_out_bcr_cb(1);
|
m_out_bcr_cb(1);
|
||||||
newstatus &= ~(STATUS_BSY | STATUS_CIP); // prepare new status; (INTRQ later) reset BSY, CIP
|
newstatus &= ~(STATUS_BSY | STATUS_CIP); // prepare new status; (INTRQ later) reset BSY, CIP
|
||||||
complete_cmd(newstatus);
|
|
||||||
|
// NOTE: calculation needs 'data' (extracted from command register)
|
||||||
|
float step_ms = SETTLING_MS + LATENCY_MS + ( (float)sqrt(1.0 * step_pulses) * STEP_RATE_MS );
|
||||||
|
|
||||||
|
cmd_timer->adjust(attotime::from_usec(1000 * step_ms), newstatus);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,9 +446,11 @@ void wd2010_device::restore(uint8_t data)
|
|||||||
// seek -
|
// seek -
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
// FIXME : step rate, drive change (untested)
|
// FIXME : drive change (untested)
|
||||||
|
|
||||||
|
// Not implemented: IMPLIED SEEK ("wait until rising edge of SC signal")
|
||||||
|
// Also, step rate for implied seeks _should be_ taken from previous restore.
|
||||||
|
|
||||||
// NOT IMPLEMENTED: IMPLIED SEEK ("wait until rising edge of SC signal")
|
|
||||||
void wd2010_device::seek(uint8_t data)
|
void wd2010_device::seek(uint8_t data)
|
||||||
{
|
{
|
||||||
uint8_t newstatus = STATUS_RDY | STATUS_SC;
|
uint8_t newstatus = STATUS_RDY | STATUS_SC;
|
||||||
@ -460,12 +459,11 @@ void wd2010_device::seek(uint8_t data)
|
|||||||
m_error = 0;
|
m_error = 0;
|
||||||
m_status = STATUS_BSY | STATUS_CIP;
|
m_status = STATUS_BSY | STATUS_CIP;
|
||||||
|
|
||||||
// TODO : store STEP RATE.
|
|
||||||
auto_scan_id(data); // has drive number changed?
|
auto_scan_id(data); // has drive number changed?
|
||||||
|
|
||||||
int direction; // 0 = towards 0
|
int direction; // 0 = towards 0
|
||||||
int step_pulses;
|
int step_pulses;
|
||||||
|
|
||||||
// Calculate number of steps by comparing the cylinder registers
|
// Calculate number of steps by comparing the cylinder registers
|
||||||
// HI/LO with the internally stored position.
|
// HI/LO with the internally stored position.
|
||||||
uint32_t cylinder_registers = CYLINDER;
|
uint32_t cylinder_registers = CYLINDER;
|
||||||
@ -479,7 +477,10 @@ void wd2010_device::seek(uint8_t data)
|
|||||||
step_pulses = cylinder_registers - m_present_cylinder;
|
step_pulses = cylinder_registers - m_present_cylinder;
|
||||||
direction = 1;
|
direction = 1;
|
||||||
}
|
}
|
||||||
logerror("SEEK - direction = %u, step_pulses = %u\n", direction, step_pulses);
|
|
||||||
|
// NOTE: calculation needs 'step_pulses' and 'data' (taken from command register)
|
||||||
|
float step_ms = SETTLING_MS + LATENCY_MS + ( (float)sqrt(1.0 * step_pulses) * STEP_RATE_MS );
|
||||||
|
|
||||||
m_out_dirin_cb(direction);
|
m_out_dirin_cb(direction);
|
||||||
|
|
||||||
if (!m_in_drdy_cb() || m_in_wf_cb()) // DRDY de-asserted or WF asserted?
|
if (!m_in_drdy_cb() || m_in_wf_cb()) // DRDY de-asserted or WF asserted?
|
||||||
@ -530,9 +531,8 @@ void wd2010_device::seek(uint8_t data)
|
|||||||
m_task_file[TASK_FILE_CYLINDER_HIGH] = (m_present_cylinder >> 8) & 0xff;
|
m_task_file[TASK_FILE_CYLINDER_HIGH] = (m_present_cylinder >> 8) & 0xff;
|
||||||
m_task_file[TASK_FILE_CYLINDER_LOW] = (m_present_cylinder - ((m_task_file[TASK_FILE_CYLINDER_HIGH] << 8) )) & 0xff;
|
m_task_file[TASK_FILE_CYLINDER_LOW] = (m_present_cylinder - ((m_task_file[TASK_FILE_CYLINDER_HIGH] << 8) )) & 0xff;
|
||||||
|
|
||||||
logerror("SEEK (END) - m_present_cylinder = %u SDH CYL L/H %02x / %02x\n", m_present_cylinder,m_task_file[TASK_FILE_CYLINDER_LOW],m_task_file[TASK_FILE_CYLINDER_HIGH]);
|
//LOGERROR("SEEK (END) - m_present_cylinder = %u SDH CYL L/H %02x / %02x\n", m_present_cylinder,m_task_file[TASK_FILE_CYLINDER_LOW],m_task_file[TASK_FILE_CYLINDER_HIGH]);
|
||||||
|
cmd_timer->adjust(attotime::from_usec(1000 * step_ms), newstatus);
|
||||||
cmd_timer->adjust(attotime::from_msec(35), newstatus); // 35 msecs makes "SEEK_TIMING" test happy.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user