Added PC-AT mode (still untested), some preparations for 9224 emulation

This commit is contained in:
Michael Zapf 2016-08-11 01:16:17 +02:00
parent 2676e800e6
commit 2976243da1
2 changed files with 284 additions and 71 deletions

View File

@ -16,6 +16,56 @@
Michael Zapf, August 2015
==================================
Specifics of both controller types
** 9224 **
- Defines a special "ST506" type for hard disks with a fixed 512 byte sector length
- No specific IDENT; uses HEAD field for cylinder MSBs (both ST and user-defined types);
- Different buffered step rate for SEEK and RESTORE
- POLL_DRIVES
- must be preceded by DESELECT
- DRIVE_SELECT
- 00 = ST506
- READ_SECTORS_LOGICAL
- Bit 1 = Bad sector bypass/terminate
- Multi-sector read requires ECC correction disable
- WRITE_SECTOR_*
- Bit 6 = Bad sector bypass/terminate
- FORMAT_TRACK
- 3-byte header for ST506, 4-byte otherwise
- No IDENT byte in the format parameters; the IDENT field (after the IDAM) is locked to FE
** 9234 **
- Defines a special "PC-AT" type for hard disks with a selectable sector length (128, 256, 512, 1024)
- IDENT field in the sector header encodes cylinder MSBs (HD and MFM floppy)
- Defines R6 as CURRENT IDENT byte register
- Uses HEAD field for cylinder MSBs (only user-defined type)
- Faster step rates, no different rates for SEEK/RESTORE
- PC-AT mode:
- R/W reg A contains specs for sector length and zone
- HEAD register contains sector size code provided by system (W4)
or read from disk (R4)
- POLL_DRIVES
- must be preceded by SEEK or DESELECT
- DRIVE_SELECT
- 00 = PC-AT
- READ_SECTORS_PHYSICAL
- PC-AT: Requires W10 to be set appropriately
- READ_SECTORS_LOGICAL
- Bit 1 = Implied seek enabled/disabled
- PC-AT: Requires W10 to be set appropriately
- WRITE_SECTOR_*
- Bit 6 = Implied seek enable/disable
- PC-AT: Requires W10 to be set appropriately
- WRITE LONG mode for extended ECC code
- MODE register (8) allows for setting WRITE LONG mode
- FORMAT_TRACK
- 4-byte header for PC-AT, 5-byte otherwise
- IDENT byte must be set for MFM floppy and MFM/PC-AT HD
- No Bad Sector Flag for PC-AT
- HEAD field contains sector size for PC-AT
***************************************************************************/
#include "emu.h"
@ -67,7 +117,6 @@
ECC
Write long (see MODE register; only useful with ECC)
Tape operations
AT mode (HD)
FM-encoded HD
=== Implemented but untested ===
@ -75,6 +124,7 @@
Poll drives
Seek/Read ID
Read track
AT mode (HD)
=== TODO ===
Create a common state machine for HD and floppy
@ -232,7 +282,8 @@ enum
TYPE_AT = 0x00,
TYPE_HD = 0x01,
TYPE_FLOPPY8 = 0x02,
TYPE_FLOPPY5 = 0x03
TYPE_FLOPPY5 = 0x03,
TYPE_ST = 0x04
};
/*
@ -241,8 +292,7 @@ enum
enum
{
GEN_TIMER = 1,
COM_TIMER /*,
LIVE_TIMER */
COM_TIMER
};
/*
@ -256,14 +306,6 @@ enum {
MO_STEPRATE = 0x07 // Step rates
};
/*
Step rates in microseconds for MFM. This is set in the mode register,
bits 0-2. FM mode doubles all values.
*/
static const int step_hd[] = { 22, 50, 100, 200, 400, 800, 1600, 3200 };
static const int step_flop8[] = { 218, 500, 1000, 2000, 4000, 8000, 16000, 32000 };
static const int step_flop5[] = { 436, 1000, 2000, 4000, 8000, 16000, 32000, 64000 };
/*
Head load timer increments in usec. Delay value is calculated from this value
multiplied by the factor in the DATA/DELAY register. For FM mode all
@ -271,11 +313,6 @@ static const int step_flop5[] = { 436, 1000, 2000, 4000, 8000, 16000, 32000, 6
*/
static const int head_load_timer_increment[] = { 200, 200, 2000, 4000 };
/*
ID fields association to registers
*/
static const int id_field[] = { CURRENT_CYLINDER, CURRENT_HEAD, CURRENT_SECTOR, CURRENT_SIZE, CURRENT_CRC1, CURRENT_CRC2 };
/*
Pulse widths for stepping in usec
*/
@ -518,19 +555,32 @@ bool hdc92x4_device::reading_track()
*/
/*
In SMC mode, the cylinder number is stored in bit positions 4,5,6 of the
head register and in the 8 bits of the cylinder register.
This is true for the desired cyl/head, current cyl/head, and the header
fields on the track.
The desired head is specified by the last 4 bits of the desired head
register in all modes.
*/
int hdc92x4_device::desired_head()
{
return m_register_w[DESIRED_HEAD] & 0x0f;
}
/*
PC-AT mode: Cylinder number is specified by the least significant two
bits of the R/W register A (DATA) and the 8 bits of the desired cylinder
register.
SMC mode: Cylinder number is stored in bit positions 4,5,6 of the
head register and in the 8 bits of the desired cylinder register.
*/
int hdc92x4_device::desired_cylinder()
{
return (m_register_w[DESIRED_CYLINDER] & 0xff) | ((m_register_w[DESIRED_HEAD] & 0x70) << 4);
if (m_selected_drive_type == TYPE_AT)
{
return (m_register_w[DESIRED_CYLINDER] & 0xff) | ((m_register_w[DATA] & 0x03) << 8);
}
else
{
return (m_register_w[DESIRED_CYLINDER] & 0xff) | ((m_register_w[DESIRED_HEAD] & 0x70) << 4);
}
}
int hdc92x4_device::desired_sector()
@ -538,14 +588,34 @@ int hdc92x4_device::desired_sector()
return m_register_w[DESIRED_SECTOR] & 0xff;
}
/*
The current head is specified by the last 4 bits of the current head
register in all modes.
*/
int hdc92x4_device::current_head()
{
return m_register_r[CURRENT_HEAD] & 0x0f;
}
/*
PC-AT mode: The current cylinder number is specified by the IDENT field
as read from the sector header and the 8 bits of the desired cylinder
register.
IDENT: FE->0, FF->1, FC->2, FD->3
SMC mode: The current cylinder number is stored in bit positions 4,5,6 of
the head register and in the 8 bits of the desired cylinder register.
*/
int hdc92x4_device::current_cylinder()
{
return (m_register_r[CURRENT_CYLINDER] & 0xff) | ((m_register_r[CURRENT_HEAD] & 0x70) << 4);
if (m_selected_drive_type == TYPE_AT)
{
return (m_register_r[CURRENT_CYLINDER] & 0xff) | (((m_register_r[CURRENT_IDENT] + 2) & 0x03) << 8);
}
else
{
return (m_register_r[CURRENT_CYLINDER] & 0xff) | ((m_register_r[CURRENT_HEAD] & 0x70) << 4);
}
}
int hdc92x4_device::current_sector()
@ -563,12 +633,77 @@ bool hdc92x4_device::using_floppy()
return (m_selected_drive_type == TYPE_FLOPPY5 || m_selected_drive_type == TYPE_FLOPPY8);
}
int hdc92x4_device::header_length()
{
return (m_selected_drive_type == TYPE_AT)? 4 : 5;
}
/*
Delivers the step time (in microseconds) minus the pulse width
Returns the index of the register where the sector header field shall be stored
*/
int hdc92x4_device::step_time()
int hdc92x4_device::register_number(int slot)
{
// The id_field is an array of indexes into the chip registers.
// Thus we get the values properly assigned to the registers.
// The PC-AT mode does not use a size field.
const int id_field[] = { CURRENT_CYLINDER, CURRENT_HEAD, CURRENT_SECTOR, CURRENT_SIZE, CURRENT_CRC1, CURRENT_CRC2 };
int index = slot;
// Skip size for PC-AT
if (m_selected_drive_type == TYPE_AT && slot > 2) index++;
if (index > 5)
{
logerror("BUG: Invalid index for header field: %d", index);
index = 5;
}
return id_field[index];
}
/*
Delivers the step time (in microseconds) minus the pulse width (9224).
The first two values in the list apply for index==0 (buffered step),
but the first one is used for the RESTORE command, the second one is used
for SEEK. [2]
*/
int hdc9224_device::step_time()
{
int time;
// Step rates in microseconds for MFM. This is set in the mode register,
// bits 0-2. FM mode doubles all values.
const int step_hd[] = { 22, 18, 200, 400, 800, 1600, 3200, 6400, 12800 };
const int step_flop8[] = { 218, 176, 2000, 4000, 8000, 16000, 32000, 64000, 128000 };
const int step_flop5[] = { 436, 352, 4000, 8000, 16000, 32000, 64000, 128000, 256000 };
int index = m_register_w[MODE] & MO_STEPRATE;
// First value is used only for RESTORE (02, 03)
if ((index > 0) || ((current_command() & 0xfe)!=0x02)) index++;
// Get seek time.
if (m_selected_drive_type == TYPE_FLOPPY8)
time = step_flop8[index] - pulse_flop8;
else if (m_selected_drive_type == TYPE_FLOPPY5)
time = step_flop5[index] - pulse_flop5;
else
time = step_hd[index] - pulse_hd;
if (fm_mode()) time = time * 2;
return time;
}
/*
Delivers the step time (in microseconds) minus the pulse width (9234).
The 9234 does not use different values for buffered steps.
*/
int hdc9234_device::step_time()
{
int time;
// Step rates in microseconds for MFM. This is set in the mode register,
// bits 0-2. FM mode doubles all values.
const int step_hd[] = { 22, 50, 100, 200, 400, 800, 1600, 3200 };
const int step_flop8[] = { 218, 500, 1000, 2000, 4000, 8000, 16000, 32000 };
const int step_flop5[] = { 436, 1000, 2000, 4000, 8000, 16000, 32000, 64000 };
int index = m_register_w[MODE] & MO_STEPRATE;
// Get seek time.
if (m_selected_drive_type == TYPE_FLOPPY8)
@ -603,11 +738,24 @@ int hdc92x4_device::pulse_width()
}
/*
Delivers the sector size
Delivers the sector size. The register has been either loaded from the
sector header (floppy / generic HD) or from register A (PC-AT mode). For
the 9224, 512 bytes is returned when TYPE_ST was selected.
*/
int hdc92x4_device::calc_sector_size()
int hdc92x4_device::sector_size()
{
return 128 << (m_register_r[CURRENT_SIZE] & 3);
// TYPE_AT:
// CURRENT_HEAD
// x S S x x x x x, where SS =0 (256), =1 (512), =2(1024), =3 (128)
if (m_selected_drive_type==TYPE_AT)
return 128 << (((m_register_r[CURRENT_HEAD] >> 5) + 1) & 0x03);
else
{
if (m_selected_drive_type==TYPE_ST)
return 512;
else
return 128 << (m_register_r[CURRENT_SIZE] & 7);
}
}
// ===========================================================================
@ -1006,7 +1154,7 @@ void hdc92x4_device::data_transfer(int& cont)
(m_register_w[DMA15_8] & 0xff) << 8 |
(m_register_w[DMA7_0] & 0xff);
dma_address = (dma_address + calc_sector_size()) & 0xffffff;
dma_address = (dma_address + sector_size()) & 0xffffff;
m_register_w[DMA23_16] = m_register_r[DMA23_16] = (dma_address & 0xff0000) >> 16;
m_register_w[DMA15_8] = m_register_r[DMA15_8] = (dma_address & 0x00ff00) >> 8;
@ -1049,7 +1197,7 @@ void hdc92x4_device::data_transfer(int& cont)
(m_register_w[DMA15_8] & 0xff) << 8 |
(m_register_w[DMA7_0] & 0xff);
dma_address = (dma_address + calc_sector_size()) & 0xffffff;
dma_address = (dma_address + sector_size()) & 0xffffff;
m_register_w[DMA23_16] = m_register_r[DMA23_16] = (dma_address & 0xff0000) >> 16;
m_register_w[DMA15_8] = m_register_r[DMA15_8] = (dma_address & 0x00ff00) >> 8;
@ -1087,6 +1235,56 @@ void hdc92x4_device::data_transfer(int& cont)
}
}
/*
Presets the CRC register, depending on the flag in the Interrupt/Command
Termination Register.
If this flag is set to 0, the CRC calculation is preset with 0, which
means that only media with the same setting will be readable (all others
will yield CRC errors).
This method simply provides preset values for some particular situations.
When value=0, the CRC is preset to 0 or FFFF. Other defined values are:
a1 = data value of MFM IDAM
a1a1a1 = all three a1s
fe = data value of FM IDAM
f56a = cell pattern of f8 (DAM, FM)
f56b = cell pattern of f9 (DAM, FM)
f56e = cell pattern of fa (DAM, FM)
f56f = cell pattern of fb (DAM, FM)
*/
void hdc92x4_device::preset_crc(live_info& live, int value)
{
if ((m_register_w[INT_COMM_TERM] & 0x80)!=0)
{
// Preset -1
switch (value)
{
case 0xa1: live.crc = 0x443b; break;
case 0xfe: live.crc = 0xef21; break;
case 0xf56a: live.crc = 0x8fe7; break; // F8
case 0xf56b: live.crc = 0x9fc6; break; // F9
case 0xf56e: live.crc = 0xafa5; break; // FA
case 0xf56f: live.crc = 0xbf84; break; // FB
case 0xa1a1a1: live.crc = 0xcdb4; break; // A1A1A1
default: live.crc = 0xffff; break;
}
}
else
{
// Preset 0
switch (value)
{
case 0xa1: live.crc = 0xc1a9; break;
case 0xfe: live.crc = 0x736d; break;
case 0xf56a: live.crc = 0x6e17; break; // F8
case 0xf56b: live.crc = 0x7e36; break; // F9
case 0xf56e: live.crc = 0x4e55; break; // FA
case 0xf56f: live.crc = 0x5e74; break; // FB
case 0xa1a1a1: live.crc = 0x0128; break; // A1A1A1
default: live.crc = 0x0000; break;
}
}
};
// ===========================================================================
// Commands
// ===========================================================================
@ -1954,7 +2152,7 @@ void hdc92x4_device::live_start(int state)
m_live_state.next_state = -1;
m_live_state.shift_reg = 0;
m_live_state.crc = 0xffff;
preset_crc(m_live_state, 0);
m_live_state.bit_counter = 0;
m_live_state.byte_counter = 0;
m_live_state.data_separator_phase = false;
@ -2063,7 +2261,7 @@ void hdc92x4_device::live_run_until(attotime limit)
if (m_live_state.shift_reg == 0x4489)
{
if (TRACE_LIVE) logerror("%s: [%s live] Found an A1 mark\n", tag(),tts(m_live_state.time).c_str());
m_live_state.crc = 0x443b;
preset_crc(m_live_state, 0xa1);
m_live_state.data_separator_phase = false;
m_live_state.bit_counter = 0;
// Next task: find the next two A1 marks
@ -2076,7 +2274,7 @@ void hdc92x4_device::live_run_until(attotime limit)
if (m_live_state.shift_reg == 0xf57e)
{
if (TRACE_LIVE) logerror("%s: SEARCH_IDAM: IDAM found\n", tag());
m_live_state.crc = 0xef21;
preset_crc(m_live_state, 0xfe);
m_live_state.data_separator_phase = false;
m_live_state.bit_counter = 0;
m_live_state.state = READ_ID_FIELDS_INTO_REGS;
@ -2174,11 +2372,9 @@ void hdc92x4_device::live_run_until(attotime limit)
if (TRACE_LIVE) logerror("%s: slot %d = %02x, crc=%04x\n", tag(), slot, m_live_state.data_reg, m_live_state.crc);
// The id_field is an array of indexes into the chip registers.
// Thus we get the values properly assigned to the registers.
m_register_r[id_field[slot]] = m_live_state.data_reg;
m_register_r[register_number(slot)] = m_live_state.data_reg;
if(slot > 4)
if (slot > 4) // this includes both CRC bytes. There are no different lengths for the floppy headers (excluding the ident byte)
{
// We successfully read the ID fields; let's wait for the machine time to catch up.
if (reading_track())
@ -2222,7 +2418,7 @@ void hdc92x4_device::live_run_until(attotime limit)
if (m_live_state.bit_counter >= 28*16 && m_live_state.shift_reg == 0x4489)
{
if (TRACE_LIVE) logerror("%s: [%s live] Found an A1 mark\n", tag(),tts(m_live_state.time).c_str());
m_live_state.crc = 0x443b;
preset_crc(m_live_state, 0xa1);
m_live_state.data_separator_phase = false;
m_live_state.bit_counter = 0;
m_live_state.state = READ_TWO_MORE_A1_DAM;
@ -2240,11 +2436,7 @@ void hdc92x4_device::live_run_until(attotime limit)
if (m_live_state.bit_counter >= 11*16 && (m_live_state.shift_reg == 0xf56a || m_live_state.shift_reg == 0xf56b ||
m_live_state.shift_reg == 0xf56e || m_live_state.shift_reg == 0xf56f)) {
if (TRACE_LIVE) logerror("%s: SEARCH_DAM: found DAM = %04x\n", tag(), m_live_state.shift_reg);
m_live_state.crc =
m_live_state.shift_reg == 0xf56a ? 0x8fe7 :
m_live_state.shift_reg == 0xf56b ? 0x9fc6 :
m_live_state.shift_reg == 0xf56e ? 0xafa5 :
0xbf84;
preset_crc(m_live_state, m_live_state.shift_reg);
m_live_state.data_separator_phase = false;
m_live_state.bit_counter = 0;
m_live_state.state = READ_SECTOR_DATA;
@ -2342,16 +2534,16 @@ void hdc92x4_device::live_run_until(attotime limit)
if (TRACE_LIVE) logerror("%s: [%s live] Found data value %02X, CRC=%04x\n", tag(),tts(m_live_state.time).c_str(), m_live_state.data_reg, m_live_state.crc);
int slot = (m_live_state.bit_counter >> 4)-1;
if (slot < calc_sector_size())
if (slot < sector_size())
{
// Sector data
wait_for_realtime(READ_SECTOR_DATA_CONT);
return;
}
else if (slot < calc_sector_size()+2)
else if (slot < sector_size()+2)
{
// CRC
if (slot == calc_sector_size()+1)
if (slot == sector_size()+1)
{
if (reading_track())
{
@ -2395,7 +2587,7 @@ void hdc92x4_device::live_run_until(attotime limit)
m_out_dma(0, m_register_r[DATA], 0xff);
// And again, for floppies, clear line after writing each byte, for hard disk, only after the last byte
if (using_floppy() || (m_live_state.bit_counter >> 4)==calc_sector_size()-1)
if (using_floppy() || (m_live_state.bit_counter >> 4)==sector_size()-1)
{
m_out_dip(CLEAR_LINE);
m_out_dmarq(CLEAR_LINE);
@ -2441,7 +2633,7 @@ void hdc92x4_device::live_run_until(attotime limit)
if (fm_mode())
{
// Init the CRC for the DAM and sector
m_live_state.crc = 0xffff;
preset_crc(m_live_state, 0);
// 1111 0101 0110 1010 = F8 deleted
// 1111 0101 0110 1111 = FB normal
@ -2450,10 +2642,10 @@ void hdc92x4_device::live_run_until(attotime limit)
else
{
// Init the CRC for the ident byte and sector
m_live_state.crc = 0xcdb4; // value for 3*A1
preset_crc(m_live_state, 0xa1a1a1);
write_on_track(encode(m_deleted? 0xf8 : 0xfb), 1, WRITE_SECDATA);
}
m_live_state.byte_counter = calc_sector_size();
m_live_state.byte_counter = sector_size();
// Set the over/underrun flag and hope that it will be cleared before we start writing
// (only for sector writing)
@ -2476,7 +2668,7 @@ void hdc92x4_device::live_run_until(attotime limit)
else
{
// For floppies, set this for each byte; for hard disk, set it only at the beginning
if (using_floppy() || m_live_state.byte_counter == calc_sector_size())
if (using_floppy() || m_live_state.byte_counter == sector_size())
m_out_dip(ASSERT_LINE);
m_register_r[DATA] = m_register_w[DATA] = m_in_dma(0, 0xff);
@ -2624,7 +2816,7 @@ void hdc92x4_device::live_run_until(attotime limit)
write_on_track(0x4489, 3, WRITE_HEADER);
m_live_state.byte_counter = 5;
}
m_live_state.crc = 0xffff;
preset_crc(m_live_state, 0);
break;
case WRITE_HEADER:
@ -2721,8 +2913,8 @@ void hdc92x4_device::live_run_until(attotime limit)
m_out_dip(ASSERT_LINE);
// Write the header via DMA
for (auto & elem : id_field)
m_out_dma(0, m_register_r[elem], 0xff);
for (int i=0; i < header_length(); i++)
m_out_dma(0, m_register_r[register_number(i)], 0xff);
m_out_dip(CLEAR_LINE);
m_out_dmarq(CLEAR_LINE);
@ -2877,7 +3069,7 @@ void hdc92x4_device::live_run_hd_until(attotime limit)
if (found_mark(SEARCH_IDAM))
{
if (TRACE_LIVE) logerror("%s: [%s live] Found an A1 mark\n", tag(), tts(m_live_state.time).c_str());
m_live_state.crc = 0x443b;
preset_crc(m_live_state, 0xa1);
m_live_state.data_separator_phase = false;
m_live_state.bit_counter = 0;
@ -2934,7 +3126,7 @@ void hdc92x4_device::live_run_hd_until(attotime limit)
if (m_live_state.bit_counter & 15) break;
if (TRACE_LIVE) logerror("%s: slot %d = %02x, crc=%04x\n", tag(), slot, m_live_state.data_reg, m_live_state.crc);
m_register_r[id_field[slot++]] = m_live_state.data_reg;
m_register_r[register_number(slot++)] = m_live_state.data_reg;
if(slot > 5)
{
@ -2972,7 +3164,7 @@ void hdc92x4_device::live_run_hd_until(attotime limit)
if (found_mark(SEARCH_DAM))
{
if (TRACE_LIVE) logerror("%s: [%s live] Found an A1 mark\n", tag(),tts(m_live_state.time).c_str());
m_live_state.crc = 0x443b;
preset_crc(m_live_state, 0xa1);
m_live_state.data_separator_phase = false;
m_live_state.bit_counter = 0;
m_live_state.state = READ_DATADEL_FLAG;
@ -3030,9 +3222,9 @@ void hdc92x4_device::live_run_hd_until(attotime limit)
if (m_live_state.bit_counter & 15) break;
slot = (m_live_state.bit_counter >> 4)-1;
if (TRACE_LIVE) logerror("%s: [%s live] Found data value [%d/%d] = %02X, CRC=%04x\n", tag(),tts(m_live_state.time).c_str(), slot, calc_sector_size(), m_live_state.data_reg, m_live_state.crc);
if (TRACE_LIVE) logerror("%s: [%s live] Found data value [%d/%d] = %02X, CRC=%04x\n", tag(),tts(m_live_state.time).c_str(), slot, sector_size(), m_live_state.data_reg, m_live_state.crc);
if (slot < calc_sector_size())
if (slot < sector_size())
{
// For the first byte, allow for the DMA acknowledge to be set.
if (slot == 0)
@ -3042,10 +3234,10 @@ void hdc92x4_device::live_run_hd_until(attotime limit)
}
else m_live_state.state = READ_SECTOR_DATA_CONT;
}
else if (slot < calc_sector_size()+2)
else if (slot < sector_size()+2)
{
// CRC
if (slot == calc_sector_size()+1)
if (slot == sector_size()+1)
{
m_out_dip(CLEAR_LINE);
m_out_dmarq(CLEAR_LINE);
@ -3176,11 +3368,11 @@ void hdc92x4_device::live_run_hd_until(attotime limit)
if (TRACE_WRITE && TRACE_DETAIL) logerror("%s: Write data mark\n", tag());
// Init the CRC for the ident byte and sector
m_live_state.crc = 0x443b; // value for 1*A1
preset_crc(m_live_state, 0xa1); // only one A1
write_on_track(encode_hd(m_deleted? 0xf8 : 0xfb), 1, WRITE_SECDATA);
m_live_state.byte_counter = calc_sector_size();
m_live_state.byte_counter = sector_size();
// Set the over/underrun flag and hope that it will be cleared before we start writing
// (only for sector writing)
@ -3204,8 +3396,8 @@ void hdc92x4_device::live_run_hd_until(attotime limit)
{
if (TRACE_WRITE && TRACE_DETAIL) logerror("%s: Write sector byte, %d to go\n", tag(), m_live_state.byte_counter);
// For floppies, set this for each byte; for hard disk, set it only at the beginning
if (m_live_state.byte_counter == calc_sector_size())
// This is hard disk, so set DIP only at the beginning
if (m_live_state.byte_counter == sector_size())
m_out_dip(ASSERT_LINE);
m_register_r[DATA] = m_register_w[DATA] = m_in_dma(0, 0xff);
@ -3296,8 +3488,8 @@ void hdc92x4_device::live_run_hd_until(attotime limit)
m_out_dip(ASSERT_LINE);
// Write the header via DMA
for (auto & elem : id_field)
m_out_dma(0, m_register_r[elem], 0xff);
for (int i=0; i < header_length(); i++)
m_out_dma(0, m_register_r[register_number(i)], 0xff);
// Continue with reading the sector data
m_live_state.state = SEARCH_DAM;
@ -3341,7 +3533,7 @@ void hdc92x4_device::live_run_hd_until(attotime limit)
if (TRACE_HEADER) logerror("%s: Writing IDAM and header: ", tag());
write_on_track(encode_a1_hd(), 1, WRITE_HEADER);
m_live_state.byte_counter = 5; // TODO: Check this for AT mode
m_live_state.crc = 0xffff;
preset_crc(m_live_state, 0);
break;
case WRITE_HEADER:
@ -3997,6 +4189,12 @@ void hdc92x4_device::process_command()
// write are identical, so in that case we copy the contents
if (m_register_pointer < DESIRED_HEAD) m_register_r[m_register_pointer] = m_regvalue;
// Note for the PC-AT mode: The DATA register contains two bits (5,4)
// that are defined as "Actual sector size" ([1] p. 7). The
// specification does not say anything about the meaning of these
// bits. The desired sector size is already specified by bits 6 and 5
// of the DESIRED_HEAD register, so we ignore these bits for now.
// Autoincrement until DATA is reached.
if (m_register_pointer < DATA) m_register_pointer++;
}

View File

@ -232,6 +232,9 @@ protected:
live_info m_live_state, m_checkpoint_state;
int m_last_live_state;
// Presets CRC.
void preset_crc(live_info& live, int value);
// Starts the live run
void live_start(int state);
@ -433,13 +436,19 @@ protected:
UINT8 current_command();
// Step time (minus pulse width)
int step_time();
virtual int step_time() =0;
// Step pulse width
int pulse_width();
// Sector size as read from the track
int calc_sector_size();
// Sector size as read from the track or given by register A (PC-AT mode)
int sector_size();
// Returns the sector header length
int header_length();
// Returns the index of the register for the header field
int register_number(int slot);
// Is the currently selected drive a floppy drive?
bool using_floppy();
@ -476,12 +485,18 @@ class hdc9224_device : public hdc92x4_device
{
public:
hdc9224_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
protected:
int step_time();
};
class hdc9234_device : public hdc92x4_device
{
public:
hdc9234_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
protected:
int step_time();
};
#endif