mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
HDC9234: Added HD track reading; several bug fixes.
This commit is contained in:
parent
571a4e88d9
commit
445fa7422d
@ -16,7 +16,7 @@
|
||||
The HDC9234 controller is also referred to as the "Universal Disk Controller" (UDC)
|
||||
by the data book
|
||||
|
||||
Michael Zapf, September 2014
|
||||
Michael Zapf, July 2015
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
@ -54,8 +54,10 @@
|
||||
#define TRACE_INDEX 0
|
||||
#define TRACE_DMA 0
|
||||
#define TRACE_DONE 0
|
||||
#define TRACE_FAIL 0
|
||||
#define TRACE_FAIL 1
|
||||
#define TRACE_AUXBUS 0
|
||||
#define TRACE_HEADER 0
|
||||
#define TRACE_GAPS 0
|
||||
|
||||
#define TRACE_DETAIL 0
|
||||
|
||||
@ -66,14 +68,17 @@
|
||||
ECC
|
||||
Write long (see MODE register; only useful with ECC)
|
||||
Tape operations
|
||||
Read track (HD)
|
||||
AT mode (HD)
|
||||
FM-encoded HD
|
||||
|
||||
=== Implemented but untested ===
|
||||
Burst mode
|
||||
Restore
|
||||
Poll drives
|
||||
Seek/Read ID
|
||||
Read track (floppy)
|
||||
Read track
|
||||
|
||||
=== TODO ===
|
||||
Create a common state machine for HD and floppy
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -488,9 +493,24 @@ bool hdc9234_device::drive_ready()
|
||||
return (m_register_r[DRIVE_STATUS] & HDC_DS_READY)!=0;
|
||||
}
|
||||
|
||||
/*
|
||||
Doing a track read?
|
||||
*/
|
||||
bool hdc9234_device::reading_track()
|
||||
{
|
||||
return (current_command() & 0xfe) == 0x5a;
|
||||
}
|
||||
|
||||
/*
|
||||
Accessor functions for specific parameters.
|
||||
*/
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
int hdc9234_device::desired_head()
|
||||
{
|
||||
return m_register_w[DESIRED_HEAD] & 0x0f;
|
||||
@ -688,9 +708,9 @@ void hdc9234_device::read_id(int& cont, bool implied_seek, bool wait_seek_comple
|
||||
break;
|
||||
}
|
||||
|
||||
if (TRACE_READID && TRACE_SUBSTATES)
|
||||
if (TRACE_READID)
|
||||
{
|
||||
logerror("%s: substate READ_ID1\n", tag());
|
||||
if (TRACE_SUBSTATES) logerror("%s: substate READ_ID1\n", tag());
|
||||
logerror("%s: DESIRED_CYL = %d; CURRENT_CYL = %d\n", tag(), desired_cylinder(), current_cylinder());
|
||||
}
|
||||
|
||||
@ -775,7 +795,7 @@ void hdc9234_device::read_id(int& cont, bool implied_seek, bool wait_seek_comple
|
||||
contents of the DESIRED_HEAD/CYLINDER/SECTOR registers
|
||||
- checks the CRC
|
||||
*/
|
||||
void hdc9234_device::verify(int& cont, bool verify_all)
|
||||
void hdc9234_device::verify(int& cont)
|
||||
{
|
||||
cont = CONTINUE;
|
||||
|
||||
@ -842,7 +862,7 @@ void hdc9234_device::verify(int& cont, bool verify_all)
|
||||
break;
|
||||
|
||||
case VERIFY3:
|
||||
if (TRACE_VERIFY) logerror("%s: Total bytes read: %d\n", tag(), m_live_state.bit_count_total / 16);
|
||||
if (TRACE_VERIFY) logerror("%s: Next IDAM found; total bytes read: %d\n", tag(), m_live_state.bit_count_total / 16);
|
||||
if ((m_register_r[CHIP_STATUS] & CS_COMPERR) != 0)
|
||||
{
|
||||
if (TRACE_FAIL) logerror("%s: VERIFY failed to find sector CHS=(%d,%d,%d)\n", tag(), desired_cylinder(), desired_head(), desired_sector());
|
||||
@ -851,7 +871,7 @@ void hdc9234_device::verify(int& cont, bool verify_all)
|
||||
}
|
||||
|
||||
// Continue with the loop
|
||||
if (verify_all || !m_first_sector_found)
|
||||
if (m_logical || !m_first_sector_found)
|
||||
{
|
||||
// this is for the logical sector reading/writing
|
||||
m_substate = VERIFY1;
|
||||
@ -905,10 +925,16 @@ void hdc9234_device::data_transfer(int& cont)
|
||||
|
||||
if (m_transfer_enabled) dma_address_out(m_register_w[DMA23_16], m_register_w[DMA15_8], m_register_w[DMA7_0]);
|
||||
|
||||
if (TRACE_TRANSFER && TRACE_DETAIL) logerror("%s: %s sector CHS=(%d,%d,%d)\n", tag(), m_write? "write" : "read",
|
||||
desired_cylinder(),
|
||||
desired_head(),
|
||||
desired_sector());
|
||||
if (TRACE_TRANSFER && TRACE_DETAIL)
|
||||
{
|
||||
if (m_logical)
|
||||
logerror("%s: %s sector CHS=(%d,%d,%d)\n", tag(), m_write? "Write" : "Read",
|
||||
desired_cylinder(),
|
||||
desired_head(),
|
||||
desired_sector());
|
||||
else
|
||||
logerror("%s: %s next sector on track\n", tag(), m_write? "Write" : "Read");
|
||||
}
|
||||
|
||||
if (m_write)
|
||||
{
|
||||
@ -970,8 +996,9 @@ void hdc9234_device::data_transfer(int& cont)
|
||||
dma_address = (dma_address + calc_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) >> 16;
|
||||
m_register_w[DMA7_0] = m_register_r[DMA7_0] = (dma_address & 0x0000ff) >> 16;
|
||||
m_register_w[DMA15_8] = m_register_r[DMA15_8] = (dma_address & 0x00ff00) >> 8;
|
||||
m_register_w[DMA7_0] = m_register_r[DMA7_0] = (dma_address & 0x0000ff);
|
||||
if (TRACE_TRANSFER) logerror("%s: New DMA address = %06x\n", tag(), dma_address);
|
||||
}
|
||||
|
||||
// Decrement the count
|
||||
@ -989,8 +1016,8 @@ void hdc9234_device::data_transfer(int& cont)
|
||||
// What happens when we exceed the highest sector number
|
||||
// in the track? We have to assume that this is possible
|
||||
// and that in this case the VERIFY routine fails.
|
||||
m_register_w[DESIRED_SECTOR] = (desired_sector() + 1) & 0xff;
|
||||
m_substate = VERIFY1;
|
||||
if (m_logical) m_register_w[DESIRED_SECTOR] = (desired_sector() + 1) & 0xff;
|
||||
m_substate = VERIFY2;
|
||||
cont = NEXT;
|
||||
m_live_state.bit_count_total = 0;
|
||||
}
|
||||
@ -1012,16 +1039,17 @@ void hdc9234_device::data_transfer(int& cont)
|
||||
dma_address = (dma_address + calc_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) >> 16;
|
||||
m_register_w[DMA7_0] = m_register_r[DMA7_0] = (dma_address & 0x0000ff) >> 16;
|
||||
m_register_w[DMA15_8] = m_register_r[DMA15_8] = (dma_address & 0x00ff00) >> 8;
|
||||
m_register_w[DMA7_0] = m_register_r[DMA7_0] = (dma_address & 0x0000ff);
|
||||
if (TRACE_TRANSFER) logerror("%s: New DMA address = %06x\n", tag(), dma_address);
|
||||
}
|
||||
|
||||
// Decrement the count
|
||||
m_register_w[SECTOR_COUNT] = (m_register_w[SECTOR_COUNT]-1) & 0xff;
|
||||
if (m_register_w[SECTOR_COUNT] != 0 && !m_stop_after_index)
|
||||
{
|
||||
m_register_w[DESIRED_SECTOR] = (desired_sector() + 1) & 0xff;
|
||||
m_substate = VERIFY1;
|
||||
if (m_logical) m_register_w[DESIRED_SECTOR] = (desired_sector() + 1) & 0xff;
|
||||
m_substate = VERIFY2;
|
||||
cont = NEXT;
|
||||
m_live_state.bit_count_total = 0;
|
||||
}
|
||||
@ -1462,6 +1490,7 @@ void hdc9234_device::seek_read_id()
|
||||
bool step_enable = (current_command() & 0x04)==1;
|
||||
bool wait_seek_comp = (current_command() & 0x02)==1;
|
||||
bool do_verify = (current_command() & 0x01)==1;
|
||||
m_logical = true;
|
||||
|
||||
while (cont == NEXT)
|
||||
{
|
||||
@ -1474,7 +1503,7 @@ void hdc9234_device::seek_read_id()
|
||||
if (!do_verify)
|
||||
cont = SUCCESS;
|
||||
else
|
||||
verify(cont, true);
|
||||
verify(cont);
|
||||
break;
|
||||
case DATA_TRANSFER:
|
||||
// No data transfer here. Just exit.
|
||||
@ -1512,12 +1541,12 @@ void hdc9234_device::seek_read_id()
|
||||
*/
|
||||
void hdc9234_device::read_sectors()
|
||||
{
|
||||
bool logical = (current_command() & 0x04)!=0;
|
||||
m_logical = (current_command() & 0x04)!=0;
|
||||
|
||||
if (m_substate == UNDEF)
|
||||
{
|
||||
// Command init
|
||||
if (TRACE_READ) logerror("%s: READ SECTORS %s command %02x, CHS=(%d,%d,%d)\n", tag(), logical? "LOGICAL": "PHYSICAL", current_command(), desired_cylinder(), desired_head(), desired_sector());
|
||||
if (TRACE_READ) logerror("%s: READ SECTORS %s command %02x, CHS=(%d,%d,%d)\n", tag(), m_logical? "LOGICAL": "PHYSICAL", current_command(), desired_cylinder(), desired_head(), desired_sector());
|
||||
m_retry_save = m_register_w[RETRY_COUNT];
|
||||
m_multi_sector = (m_register_w[SECTOR_COUNT] != 1);
|
||||
m_write = false;
|
||||
@ -1537,7 +1566,7 @@ void hdc9234_device::read_sectors()
|
||||
read_id(cont, implied_seek, true); // Always check SEEK COMPLETE
|
||||
break;
|
||||
case VERIFY:
|
||||
verify(cont, logical); // for physical, only verify the first sector
|
||||
verify(cont); // for physical, only verify the first sector
|
||||
break;
|
||||
case DATA_TRANSFER:
|
||||
data_transfer(cont);
|
||||
@ -1579,13 +1608,16 @@ void hdc9234_device::read_track()
|
||||
switch (m_substate)
|
||||
{
|
||||
case WAITINDEX0:
|
||||
if (TRACE_READTRACK && TRACE_DETAIL) logerror("%s: Read track - waiting for index hole\n", tag());
|
||||
if (!index_hole())
|
||||
{
|
||||
m_substate = WAITINDEX1;
|
||||
cont = NEXT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're above the index hole; wait for the index line going down
|
||||
if (TRACE_READTRACK && TRACE_DETAIL) logerror("%s: Index hole just passing by ... waiting for next\n", tag());
|
||||
wait_line(INDEX_LINE, ASSERT_LINE, WAITINDEX1, false);
|
||||
cont = WAIT;
|
||||
}
|
||||
@ -1596,13 +1628,15 @@ void hdc9234_device::read_track()
|
||||
cont = WAIT;
|
||||
break;
|
||||
case TRACKSTART:
|
||||
if (TRACE_READTRACK && TRACE_DETAIL) logerror("%s: Read track - index hole arrived\n", tag());
|
||||
live_start(READ_TRACK);
|
||||
wait_line(INDEX_LINE, ASSERT_LINE, TRACKDONE, true);
|
||||
cont = WAIT;
|
||||
break;
|
||||
case TRACKDONE:
|
||||
if (TRACE_READTRACK && TRACE_SUBSTATES) logerror("%s: Track reading done\n", tag());
|
||||
cont = SUCCESS;
|
||||
m_out_dmarq(CLEAR_LINE);
|
||||
m_out_dip(CLEAR_LINE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1706,7 +1740,7 @@ void hdc9234_device::format_track()
|
||||
switch (m_substate)
|
||||
{
|
||||
case WAITINDEX0:
|
||||
if (TRACE_FORMAT && TRACE_DETAIL) logerror("%s: Formatting - wait for index hole\n", tag());
|
||||
if (TRACE_FORMAT && TRACE_DETAIL) logerror("%s: Format track - waiting for index hole\n", tag());
|
||||
if (!index_hole())
|
||||
{
|
||||
m_substate = WAITINDEX1;
|
||||
@ -1726,7 +1760,7 @@ void hdc9234_device::format_track()
|
||||
cont = WAIT;
|
||||
break;
|
||||
case TRACKSTART:
|
||||
if (TRACE_FORMAT && TRACE_DETAIL) logerror("%s: Formatting - index hole arrived\n", tag());
|
||||
if (TRACE_FORMAT && TRACE_DETAIL) logerror("%s: Format track - index hole arrived\n", tag());
|
||||
live_start(FORMAT_TRACK);
|
||||
cont = WAIT;
|
||||
break;
|
||||
@ -1766,11 +1800,11 @@ void hdc9234_device::format_track()
|
||||
*/
|
||||
void hdc9234_device::write_sectors()
|
||||
{
|
||||
bool logical = (current_command() & 0x20)!=0;
|
||||
m_logical = (current_command() & 0x20)!=0;
|
||||
|
||||
if (m_substate == UNDEF)
|
||||
{
|
||||
if (TRACE_WRITE) logerror("%s: WRITE SECTORS %s command %02x, CHS=(%d,%d,%d)\n", tag(), logical? "LOGICAL" : "PHYSICAL", current_command(), desired_cylinder(), desired_head(), desired_sector());
|
||||
if (TRACE_WRITE) logerror("%s: WRITE SECTORS %s command %02x, CHS=(%d,%d,%d)\n", tag(), m_logical? "LOGICAL" : "PHYSICAL", current_command(), desired_cylinder(), desired_head(), desired_sector());
|
||||
m_multi_sector = (m_register_w[SECTOR_COUNT] != 1);
|
||||
m_substate = READ_ID;
|
||||
|
||||
@ -1815,7 +1849,7 @@ void hdc9234_device::write_sectors()
|
||||
read_id(cont, implied_seek, true); // Always check SEEK COMPLETE
|
||||
break;
|
||||
case VERIFY:
|
||||
verify(cont, logical);
|
||||
verify(cont);
|
||||
break;
|
||||
case DATA_TRANSFER:
|
||||
m_write = true;
|
||||
@ -2130,7 +2164,7 @@ void hdc9234_device::live_run_until(attotime limit)
|
||||
if(slot > 4)
|
||||
{
|
||||
// We successfully read the ID fields; let's wait for the machine time to catch up.
|
||||
if ((current_command() & 0xfe) == 0x5a)
|
||||
if (reading_track())
|
||||
// Continue if we're reading a complete track
|
||||
wait_for_realtime(READ_TRACK_ID_DONE);
|
||||
else
|
||||
@ -2302,7 +2336,7 @@ void hdc9234_device::live_run_until(attotime limit)
|
||||
// CRC
|
||||
if (slot == calc_sector_size()+1)
|
||||
{
|
||||
if ((current_command() & 0xfe)==0x5a)
|
||||
if (reading_track())
|
||||
{
|
||||
// Reading a track? Continue with next ID.
|
||||
wait_for_realtime(READ_TRACK_ID);
|
||||
@ -2870,7 +2904,6 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
||||
break;
|
||||
|
||||
case READ_ID_FIELDS_INTO_REGS:
|
||||
|
||||
if (TRACE_LIVE && m_last_live_state != READ_ID_FIELDS_INTO_REGS)
|
||||
{
|
||||
logerror("%s: [%s live] READ_ID_FIELDS_INTO_REGS\n", tag(),tts(m_live_state.time).c_str());
|
||||
@ -2888,7 +2921,7 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
||||
if(slot > 5)
|
||||
{
|
||||
// We successfully read the ID fields; let's wait for the machine time to catch up.
|
||||
if ((current_command() & 0xfe) == 0x5a)
|
||||
if (reading_track())
|
||||
// Continue if we're reading a complete track
|
||||
wait_for_realtime(READ_TRACK_ID_DONE);
|
||||
else
|
||||
@ -2968,7 +3001,8 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
||||
// Request bus release
|
||||
// For hard disk, get it only for the first byte and then keep the bus until the last byte.
|
||||
// HD: bit_counter increases by 16 for MFM_BYTE, SEPARATED(_SIMPLE) and by 1 for MFM_BIT
|
||||
if (m_transfer_enabled && (m_live_state.bit_counter == 1 || m_live_state.bit_counter == 16))
|
||||
// If we are reading a track, the DMA must have already been granted
|
||||
if (!reading_track() && m_transfer_enabled && (m_live_state.bit_counter == 1 || m_live_state.bit_counter == 16))
|
||||
{
|
||||
set_bits(m_register_r[INT_STATUS], ST_OVRUN, true);
|
||||
m_out_dmarq(ASSERT_LINE);
|
||||
@ -2999,7 +3033,7 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
||||
m_out_dmarq(CLEAR_LINE);
|
||||
checkpoint();
|
||||
|
||||
if ((current_command() & 0xfe)==0x5a)
|
||||
if (reading_track())
|
||||
{
|
||||
// Reading a track? Continue with next ID.
|
||||
wait_for_realtime(READ_TRACK_ID);
|
||||
@ -3071,7 +3105,7 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
||||
case WRITE_TRACK_BYTE:
|
||||
if (write_to_mfmhd(limit))
|
||||
{
|
||||
logerror("%s: [%s live] write limit reached\n", tag(), tts(m_live_state.time).c_str());
|
||||
if (TRACE_LIVE) logerror("%s: [%s live] write limit reached\n", tag(), tts(m_live_state.time).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3213,6 +3247,46 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
||||
}
|
||||
break;
|
||||
|
||||
// ==================================================
|
||||
// Track reading (HD)
|
||||
// ==================================================
|
||||
//
|
||||
// Read the next ID fields, then the sector contents.
|
||||
// Continue until the next index hole shows up (live_abort).
|
||||
case READ_TRACK:
|
||||
if (TRACE_LIVE) logerror("%s: READ_TRACK\n", tag());
|
||||
m_live_state.state = READ_TRACK_ID;
|
||||
break;
|
||||
|
||||
case READ_TRACK_ID:
|
||||
m_live_state.state = SEARCH_IDAM;
|
||||
// Ask for access to bus
|
||||
set_bits(m_register_r[INT_STATUS], ST_OVRUN, true);
|
||||
m_out_dmarq(ASSERT_LINE);
|
||||
break;
|
||||
|
||||
case READ_TRACK_ID_DONE:
|
||||
if ((m_register_r[INT_STATUS] & ST_OVRUN)!=0)
|
||||
{
|
||||
// We need an ACK right now, or the header bytes will be lost
|
||||
if (TRACE_FAIL) logerror("%s: No DMA ACK - buffer overrun\n", tag());
|
||||
set_bits(m_register_r[INT_STATUS], TC_DATAERR, true);
|
||||
m_live_state.state = IDLE;
|
||||
return;
|
||||
}
|
||||
if (TRACE_LIVE) logerror("%s: READ_TRACK_ID_DONE\n", tag());
|
||||
m_out_dip(ASSERT_LINE);
|
||||
|
||||
// Write the header via DMA
|
||||
for (int slot = 0; slot < 6; slot++)
|
||||
m_out_dma(0, m_register_r[id_field[slot]], 0xff);
|
||||
|
||||
// Continue with reading the sector data
|
||||
m_live_state.state = SEARCH_DAM;
|
||||
wait_line(INDEX_LINE, ASSERT_LINE, TRACKDONE, true);
|
||||
break;
|
||||
|
||||
|
||||
// =========== HD formatting =============
|
||||
// Live states for track formatting
|
||||
// Write GAP 1
|
||||
@ -3233,12 +3307,12 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
||||
|
||||
case WRITE_GAP1:
|
||||
// GAP1 length is in DMA15_8
|
||||
if (TRACE_WRITE && TRACE_DETAIL) logerror("%s: Writing GAP1; size=%d\n", tag(), m_gap1_size);
|
||||
if (TRACE_GAPS) logerror("%s: Writing GAP1; size=%d\n", tag(), m_gap1_size);
|
||||
write_on_track(encode_hd(0x4e), m_gap1_size, WRITE_IDAM_SYNC);
|
||||
break;
|
||||
|
||||
case WRITE_IDAM_SYNC:
|
||||
if (TRACE_WRITE && TRACE_DETAIL) logerror("%s: Writing IDAM sync, size=%d\n", tag(), m_sync_size);
|
||||
if (TRACE_GAPS) logerror("%s: Writing IDAM sync, size=%d\n", tag(), m_sync_size);
|
||||
write_on_track(encode_hd(0x00), m_sync_size, WRITE_IDAM);
|
||||
break;
|
||||
|
||||
@ -3246,7 +3320,7 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
||||
// Set the over/underrun flag and hope that it will be cleared before we enter the next state (after writing)
|
||||
set_bits(m_register_r[INT_STATUS], ST_OVRUN, true);
|
||||
m_out_dmarq(ASSERT_LINE);
|
||||
if (TRACE_WRITE && TRACE_DETAIL) logerror("%s: Writing IDAM and header\n", tag());
|
||||
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;
|
||||
@ -3261,6 +3335,7 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
||||
m_out_dip(ASSERT_LINE);
|
||||
m_live_state.byte_counter--;
|
||||
UINT8 headbyte = m_in_dma(0, 0xff);
|
||||
if (TRACE_HEADER) logerror("%02x ", headbyte);
|
||||
write_on_track(encode_hd(headbyte), 1, (m_live_state.byte_counter>0)? WRITE_HEADER : WRITE_HEADER_CRC);
|
||||
|
||||
if (m_live_state.byte_counter==0)
|
||||
@ -3277,29 +3352,32 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
||||
if (m_live_state.byte_counter > 0)
|
||||
{
|
||||
UINT8 crct = (m_live_state.crc >> 8) & 0xff;
|
||||
if (TRACE_WRITE && TRACE_DETAIL) logerror("%s: Write CRC byte %02x\n", tag(), crct);
|
||||
if (TRACE_HEADER) logerror("%02x ", crct);
|
||||
m_live_state.byte_counter--;
|
||||
write_on_track(encode_hd(crct), 1, WRITE_HEADER_CRC);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TRACE_HEADER) logerror("\n");
|
||||
m_live_state.state = WRITE_GAP2;
|
||||
}
|
||||
break;
|
||||
|
||||
case WRITE_GAP2:
|
||||
if (TRACE_WRITE && TRACE_DETAIL) logerror("%s: Writing GAP2, size=%d\n", tag(), m_gap2_size);
|
||||
if (TRACE_GAPS) logerror("%s: Writing GAP2, size=%d\n", tag(), m_gap2_size);
|
||||
write_on_track(encode_hd(0x4e), m_gap2_size, WRITE_DAM_SYNC);
|
||||
break;
|
||||
|
||||
case WRITE_GAP3:
|
||||
m_sector_count--;
|
||||
if (TRACE_WRITE && TRACE_DETAIL) logerror("%s: Writing GAP3, size=%d\n", tag(), m_gap3_size);
|
||||
if (TRACE_GAPS) logerror("%s: Writing GAP3, size=%d\n", tag(), m_gap3_size);
|
||||
write_on_track(encode_hd(0x4e), m_gap3_size, (m_sector_count>0)? WRITE_IDAM_SYNC : WRITE_GAP4);
|
||||
break;
|
||||
|
||||
case WRITE_GAP4:
|
||||
// Write bytes up to the end of the track
|
||||
wait_line(INDEX_LINE, ASSERT_LINE, TRACKDONE, true);
|
||||
if (TRACE_WRITE && TRACE_DETAIL && m_last_live_state != WRITE_GAP4)
|
||||
if (TRACE_GAPS && m_last_live_state != WRITE_GAP4)
|
||||
{
|
||||
logerror("%s: Writing GAP4\n", tag());
|
||||
m_last_live_state = WRITE_GAP4;
|
||||
@ -3309,13 +3387,6 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
||||
break;
|
||||
// --------------------------------------------------------
|
||||
|
||||
// ==================================================
|
||||
// Live states for track reading
|
||||
// ==================================================
|
||||
|
||||
// Quite simple. Read the next ID fields, then the sector contents.
|
||||
// Continue until the next index hole shows up (live_abort).
|
||||
|
||||
default:
|
||||
if (TRACE_LIVE) logerror("%s: Unknown state: %02x\n", tag(), m_live_state.state);
|
||||
break;
|
||||
@ -3425,14 +3496,17 @@ void hdc9234_device::skip_on_track(int repeat, int next_state)
|
||||
|
||||
UINT8 hdc9234_device::get_data_from_encoding(UINT16 raw)
|
||||
{
|
||||
return (raw & 0x4000 ? 0x80 : 0x00) |
|
||||
(raw & 0x1000 ? 0x40 : 0x00) |
|
||||
(raw & 0x0400 ? 0x20 : 0x00) |
|
||||
(raw & 0x0100 ? 0x10 : 0x00) |
|
||||
(raw & 0x0040 ? 0x08 : 0x00) |
|
||||
(raw & 0x0010 ? 0x04 : 0x00) |
|
||||
(raw & 0x0004 ? 0x02 : 0x00) |
|
||||
(raw & 0x0001 ? 0x01 : 0x00);
|
||||
unsigned int value = 0;
|
||||
|
||||
if (!using_floppy() && (m_hd_encoding == SEPARATED || m_hd_encoding == SEPARATED_SIMPLE)) return raw & 0xff;
|
||||
|
||||
for (int i=0; i < 8; i++)
|
||||
{
|
||||
value <<= 1;
|
||||
value |= (raw & 0x4000);
|
||||
raw <<= 2;
|
||||
}
|
||||
return (value >> 14) & 0xff;
|
||||
}
|
||||
|
||||
void hdc9234_device::rollback()
|
||||
@ -4257,7 +4331,7 @@ void hdc9234_device::connect_hard_drive(mfm_harddisk_device* harddisk)
|
||||
{
|
||||
m_harddisk = harddisk;
|
||||
m_hd_encoding = m_harddisk->get_encoding();
|
||||
if (TRACE_DETAIL) logerror("%s: HD encoding = %d\n", tag(), m_hd_encoding);
|
||||
if (TRACE_SELECT && TRACE_DETAIL) logerror("%s: HD encoding = %d\n", tag(), m_hd_encoding);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4332,6 +4406,7 @@ void hdc9234_device::device_reset()
|
||||
m_line_level = CLEAR_LINE;
|
||||
m_live_state.state = IDLE;
|
||||
m_live_state.time = attotime::never;
|
||||
m_logical = true;
|
||||
m_multi_sector = false;
|
||||
m_output1 = 0;
|
||||
m_output2 = 0x80;
|
||||
|
@ -372,6 +372,9 @@ private:
|
||||
// Used in RESTORE to find out when to give up
|
||||
int m_seek_count;
|
||||
|
||||
// Read/write logical or physical?
|
||||
bool m_logical;
|
||||
|
||||
// Signals to abort writing
|
||||
bool m_stopwrite;
|
||||
|
||||
@ -402,6 +405,9 @@ private:
|
||||
// Is the attached drive ready?
|
||||
bool drive_ready();
|
||||
|
||||
// Are we reading a track?
|
||||
bool reading_track();
|
||||
|
||||
// Delivers the desired head
|
||||
int desired_head();
|
||||
|
||||
@ -437,7 +443,7 @@ private:
|
||||
|
||||
// Common subprograms READ ID, VERIFY, and DATA TRANSFER
|
||||
void read_id(int& cont, bool implied_seek, bool wait_seek_complete);
|
||||
void verify(int& cont, bool verify_all);
|
||||
void verify(int& cont);
|
||||
void data_transfer(int& cont);
|
||||
|
||||
// ===================================================
|
||||
|
@ -23,14 +23,17 @@
|
||||
|
||||
#include "ti99_hd.h"
|
||||
|
||||
#define TRACE_STEPS 1
|
||||
#define TRACE_SIGNALS 1
|
||||
#define TRACE_STEPS 0
|
||||
#define TRACE_SIGNALS 0
|
||||
#define TRACE_READ 0
|
||||
#define TRACE_WRITE 0
|
||||
#define TRACE_CACHE 1
|
||||
#define TRACE_CACHE 0
|
||||
#define TRACE_RWTRACK 0
|
||||
#define TRACE_BITS 0
|
||||
#define TRACE_DETAIL 0
|
||||
#define TRACE_TIMING 0
|
||||
#define TRACE_IMAGE 0
|
||||
#define TRACE_STATE 1
|
||||
|
||||
enum
|
||||
{
|
||||
@ -163,7 +166,7 @@ attotime mfm_harddisk_device::track_end_time()
|
||||
if (!m_revolution_start_time.is_never())
|
||||
{
|
||||
endtime = m_revolution_start_time + nexttime;
|
||||
if (TRACE_DETAIL) logerror("%s: Track start time = %s, end time = %s\n", tag(), tts(m_revolution_start_time).c_str(), tts(endtime).c_str());
|
||||
if (TRACE_TIMING) logerror("%s: Track start time = %s, end time = %s\n", tag(), tts(m_revolution_start_time).c_str(), tts(endtime).c_str());
|
||||
}
|
||||
return endtime;
|
||||
}
|
||||
@ -218,7 +221,7 @@ void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int
|
||||
{
|
||||
m_ready = true;
|
||||
m_recalibrated = true;
|
||||
if (TRACE_SIGNALS) logerror("%s: Spinup complete, drive recalibrated and positioned at cylinder %d; drive is READY\n", tag(), m_current_cylinder);
|
||||
if (TRACE_STATE) logerror("%s: Spinup complete, drive recalibrated and positioned at cylinder %d; drive is READY\n", tag(), m_current_cylinder);
|
||||
if (!m_ready_cb.isnull()) m_ready_cb(this, ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
@ -358,7 +361,7 @@ bool mfm_harddisk_device::find_position(attotime &from_when, const attotime &lim
|
||||
// Reached the end
|
||||
if (bytepos >= 10416)
|
||||
{
|
||||
if (TRACE_DETAIL) logerror("%s: Reached end: rev_start = %s, live = %s\n", tag(), tts(m_revolution_start_time).c_str(), tts(from_when).c_str());
|
||||
if (TRACE_TIMING) logerror("%s: Reached end: rev_start = %s, live = %s\n", tag(), tts(m_revolution_start_time).c_str(), tts(from_when).c_str());
|
||||
m_revolution_start_time += m_rev_time;
|
||||
cell = (from_when - m_revolution_start_time).as_ticks(10000000);
|
||||
bytepos = cell / 16;
|
||||
@ -366,7 +369,7 @@ bool mfm_harddisk_device::find_position(attotime &from_when, const attotime &lim
|
||||
|
||||
if (bytepos < 0)
|
||||
{
|
||||
if (TRACE_DETAIL) logerror("%s: Negative cell number: rev_start = %s, live = %s\n", tag(), tts(m_revolution_start_time).c_str(), tts(from_when).c_str());
|
||||
if (TRACE_TIMING) logerror("%s: Negative cell number: rev_start = %s, live = %s\n", tag(), tts(m_revolution_start_time).c_str(), tts(from_when).c_str());
|
||||
bytepos = 0;
|
||||
}
|
||||
bit = cell % 16;
|
||||
@ -450,7 +453,7 @@ bool mfm_harddisk_device::write(attotime &from_when, const attotime &limit, UINT
|
||||
track[bytepos] = cdata;
|
||||
}
|
||||
|
||||
if (TRACE_WRITE) if ((bitpos&0x0f)==0) logerror("%s: Writing data=%04x (c=%d,h=%d) at position %d\n", tag(), track[bytepos], m_current_cylinder, m_current_head, bytepos);
|
||||
if (TRACE_WRITE) if ((bitpos&0x0f)==0) logerror("%s: Wrote data=%04x (c=%d,h=%d) at position %04x\n", tag(), track[bytepos], m_current_cylinder, m_current_head, bytepos);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -809,11 +812,15 @@ chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinde
|
||||
|
||||
int sec_il_start = 0;
|
||||
int sec_number = 0;
|
||||
int identfield = 0;
|
||||
int cylfield = 0;
|
||||
int headfield = 0;
|
||||
int sizefield = (size >> 7)-1;
|
||||
|
||||
// Round up
|
||||
int delta = (sectorcount + interleave-1) / interleave;
|
||||
|
||||
if (TRACE_DETAIL) logerror("%s: cyl=%02x head=%02x: sector sequence = ", tag(), cylinder&0xff, head&0xff);
|
||||
if (TRACE_DETAIL) logerror("%s: cyl=%d head=%d: sector sequence = ", tag(), cylinder, head);
|
||||
for (int sector = 0; sector < sectorcount; sector++)
|
||||
{
|
||||
if (TRACE_DETAIL) logerror("%02d ", sec_number);
|
||||
@ -823,13 +830,18 @@ chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinde
|
||||
|
||||
// Write IDAM
|
||||
mfm_encode_a1(slot, position);
|
||||
mfm_encode(slot, position, cylinder_to_ident(cylinder));
|
||||
|
||||
// Write header (according to MDM5: CHSL)
|
||||
mfm_encode(slot, position, cylinder & 0xff);
|
||||
mfm_encode(slot, position, head & 0xff);
|
||||
// Write header
|
||||
identfield = cylinder_to_ident(cylinder);
|
||||
cylfield = cylinder & 0xff;
|
||||
headfield = ((cylinder & 0x700)>>4) | (head&0x0f);
|
||||
|
||||
mfm_encode(slot, position, identfield);
|
||||
mfm_encode(slot, position, cylfield);
|
||||
mfm_encode(slot, position, headfield);
|
||||
mfm_encode(slot, position, sec_number);
|
||||
mfm_encode(slot, position, (size >> 7)-1);
|
||||
mfm_encode(slot, position, sizefield);
|
||||
// logerror("%s: Created header (%02x,%02x,%02x,%02x)\n", tag(), identfield, cylfield, headfield, sector);
|
||||
|
||||
// Write CRC for header.
|
||||
int crc = m_current_crc;
|
||||
@ -847,9 +859,16 @@ chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinde
|
||||
mfm_encode(slot, position, 0xfb);
|
||||
|
||||
// Get sector content from CHD
|
||||
chd_error state = m_chd->read_units(chs_to_lba(cylinder, head, sec_number), sector_content);
|
||||
if (state != CHDERR_NONE)
|
||||
break;
|
||||
int lbaposition = chs_to_lba(cylinder, head, sec_number);
|
||||
if (lbaposition>=0)
|
||||
{
|
||||
chd_error state = m_chd->read_units(lbaposition, sector_content);
|
||||
if (state != CHDERR_NONE) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("%s: Invalid CHS data (%d,%d,%d); not loading from CHD\n", tag(), cylinder, head, sector);
|
||||
}
|
||||
|
||||
for (int i=0; i < size; i++)
|
||||
mfm_encode(slot, position, sector_content[i]);
|
||||
@ -874,7 +893,7 @@ chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinde
|
||||
{
|
||||
// Fill the rest with 0x4e
|
||||
mfm_encode(slot, position, 0x4e, TRACKIMAGE_SIZE-position);
|
||||
if (TRACE_DETAIL)
|
||||
if (TRACE_IMAGE)
|
||||
{
|
||||
showtrack(slot->encdata, TRACKIMAGE_SIZE);
|
||||
}
|
||||
@ -929,6 +948,7 @@ void mfmhd_trackimage_cache::write_back(mfmhd_trackimage* slot)
|
||||
UINT8 byte;
|
||||
bool search_header = true;
|
||||
|
||||
int ident = 0;
|
||||
int cylinder = 0;
|
||||
int head = 0;
|
||||
int sector = 0;
|
||||
@ -939,6 +959,16 @@ void mfmhd_trackimage_cache::write_back(mfmhd_trackimage* slot)
|
||||
int interleave_prec = -1;
|
||||
bool check_interleave = true;
|
||||
|
||||
if (TRACE_IMAGE)
|
||||
{
|
||||
for (int i=0; i < TRACKIMAGE_SIZE; i++)
|
||||
{
|
||||
if ((i % 16)==0) logerror("\n%04x: ", i);
|
||||
logerror("%02x ", (m_encoding==MFM_BITS || m_encoding==MFM_BYTE)? mfm_decode(track[i]) : (track[i]&0xff));
|
||||
}
|
||||
logerror("\n");
|
||||
}
|
||||
|
||||
// We have to go through the bytes of the track and save a sector as soon as one shows up
|
||||
while (bytepos < TRACKIMAGE_SIZE)
|
||||
{
|
||||
@ -979,10 +1009,17 @@ void mfmhd_trackimage_cache::write_back(mfmhd_trackimage* slot)
|
||||
if (search_header)
|
||||
{
|
||||
// Found a header
|
||||
// ident = buffer[0]; // check?
|
||||
cylinder = buffer[1];
|
||||
head = buffer[2];
|
||||
ident = buffer[0];
|
||||
// Highest three bits are in the head field
|
||||
cylinder = buffer[1] | ((buffer[2]&0x70)<<4);
|
||||
head = buffer[2] & 0x0f;
|
||||
sector = buffer[3];
|
||||
int identexp = cylinder_to_ident(cylinder);
|
||||
|
||||
if (identexp != ident)
|
||||
{
|
||||
logerror("%s: MFM HD: Field error; ident = %02x (expected %02x) for sector chs=(%d,%d,%d)\n", tag(), ident, identexp, cylinder, head, sector);
|
||||
}
|
||||
|
||||
// Count the sectors for the interleave
|
||||
if (check_interleave)
|
||||
@ -1005,19 +1042,28 @@ void mfmhd_trackimage_cache::write_back(mfmhd_trackimage* slot)
|
||||
{
|
||||
// Sector contents
|
||||
// Write the sectors to the CHD
|
||||
if (TRACE_DETAIL) logerror("%s: MFM HD: Writing sector chs=(%d,%d,%d) to CHD\n", tag(), cylinder, head, sector);
|
||||
chd_error state = m_chd->write_units(chs_to_lba(cylinder, head, sector), buffer);
|
||||
|
||||
if (state != CHDERR_NONE)
|
||||
int lbaposition = chs_to_lba(cylinder, head, sector);
|
||||
if (lbaposition>=0)
|
||||
{
|
||||
logerror("%s: MFM HD: Write error while writing sector chs=(%d,%d,%d)\n", tag(), cylinder, head, sector);
|
||||
if (TRACE_DETAIL) logerror("%s: MFM HD: Writing sector chs=(%d,%d,%d) to CHD\n", tag(), cylinder, head, sector);
|
||||
chd_error state = m_chd->write_units(chs_to_lba(cylinder, head, sector), buffer);
|
||||
|
||||
if (state != CHDERR_NONE)
|
||||
{
|
||||
logerror("%s: MFM HD: Write error while writing sector chs=(%d,%d,%d)\n", tag(), cylinder, head, sector);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("%s: Invalid CHS data in track image: (%d,%d,%d); not saving to CHD\n", tag(), cylinder, head, sector);
|
||||
}
|
||||
|
||||
search_header = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("%s: MFM HD: CRC error\n", tag());
|
||||
logerror("%s: MFM HD: CRC error in %s of (%d,%d,%d)\n", tag(), search_header? "header" : "data", cylinder, head, sector);
|
||||
search_header = true;
|
||||
}
|
||||
// search next A1
|
||||
|
Loading…
Reference in New Issue
Block a user