mirror of
https://github.com/holub/mame
synced 2025-04-19 07:00:31 +03:00
geneve/ti99: Fixed HFDC hangs on not connected drives; allows timed steps for sector i/o instead of buffered steps only
This commit is contained in:
parent
a9170dccb8
commit
3c775ba8e5
@ -71,7 +71,7 @@
|
||||
#define LOG_CRU (1U<<10)
|
||||
#define LOG_CONFIG (1U<<15) // Configuration
|
||||
|
||||
#define VERBOSE ( LOG_CONFIG | LOG_WARN )
|
||||
#define VERBOSE ( LOG_GENERAL | LOG_CONFIG | LOG_WARN )
|
||||
#include "logmacro.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE_NS(TI99_HFDC, bus::ti99::peb, myarc_hfdc_device, "ti99_hfdc", "Myarc Hard and Floppy Disk Controller")
|
||||
@ -82,6 +82,8 @@ namespace bus::ti99::peb {
|
||||
#define FDC_TAG "hdc9234"
|
||||
#define CLOCK_TAG "mm58274c"
|
||||
|
||||
#define NONE -1
|
||||
|
||||
#define MOTOR_TIMER 1
|
||||
|
||||
#define TAPE_ADDR 0x0fc0
|
||||
@ -100,8 +102,12 @@ myarc_hfdc_device::myarc_hfdc_device(const machine_config &mconfig, const char *
|
||||
device_ti99_peribox_card_interface(mconfig, *this),
|
||||
m_motor_on_timer(nullptr),
|
||||
m_hdc9234(*this, FDC_TAG),
|
||||
m_clock(*this, CLOCK_TAG), m_current_floppy(nullptr),
|
||||
m_current_harddisk(nullptr), m_see_switches(false),
|
||||
m_clock(*this, CLOCK_TAG),
|
||||
m_current_floppy(nullptr),
|
||||
m_current_harddisk(nullptr),
|
||||
m_current_floppy_index(NONE),
|
||||
m_current_hd_index(NONE),
|
||||
m_see_switches(false),
|
||||
m_irq(), m_dip(), m_motor_running(false),
|
||||
m_inDsrArea(false), m_HDCsel(false), m_RTCsel(false),
|
||||
m_tapesel(false), m_RAMsel(false), m_ROMsel(false), m_address(0),
|
||||
@ -714,7 +720,7 @@ enum
|
||||
void myarc_hfdc_device::connect_floppy_unit(int index)
|
||||
{
|
||||
// Check if we have a new floppy
|
||||
if (m_floppy_unit[index] != m_current_floppy)
|
||||
if (index != m_current_floppy_index)
|
||||
{
|
||||
// Clear all latched flags from other drives
|
||||
m_status_latch = 0;
|
||||
@ -723,6 +729,7 @@ void myarc_hfdc_device::connect_floppy_unit(int index)
|
||||
|
||||
// Connect new drive
|
||||
m_current_floppy = m_floppy_unit[index];
|
||||
m_current_floppy_index = index;
|
||||
|
||||
// We don't use the READY line of floppy drives.
|
||||
// READY is asserted when DSKx = 1
|
||||
@ -732,7 +739,9 @@ void myarc_hfdc_device::connect_floppy_unit(int index)
|
||||
m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&myarc_hfdc_device::floppy_index_callback, this));
|
||||
else
|
||||
LOGMASKED(LOG_WARN, "Connection to DSK%d failed because no drive is connected\n", index+1);
|
||||
m_hdc9234->connect_floppy_drive(m_floppy_unit[index]);
|
||||
|
||||
// Connect to HDC (or disconnect)
|
||||
m_hdc9234->connect_floppy_drive(m_current_floppy);
|
||||
}
|
||||
|
||||
// We can only run a floppy or a harddisk at a time, not both
|
||||
@ -741,15 +750,16 @@ void myarc_hfdc_device::connect_floppy_unit(int index)
|
||||
|
||||
void myarc_hfdc_device::connect_harddisk_unit(int index)
|
||||
{
|
||||
if (m_harddisk_unit[index] != m_current_harddisk)
|
||||
if (index != m_current_hd_index)
|
||||
{
|
||||
// Clear all latched flags form other drives
|
||||
// Clear all latched flags from other drives
|
||||
m_status_latch = 0;
|
||||
disconnect_hard_drives();
|
||||
LOGMASKED(LOG_LINES, "Select hard disk WDS%d\n", index+1);
|
||||
|
||||
// Connect new drive
|
||||
m_current_harddisk = m_harddisk_unit[index];
|
||||
m_current_hd_index = index;
|
||||
|
||||
LOGMASKED(LOG_LINES, "Connect index callback WDS%d\n", index+1);
|
||||
if (m_current_harddisk != nullptr)
|
||||
@ -760,6 +770,8 @@ void myarc_hfdc_device::connect_harddisk_unit(int index)
|
||||
}
|
||||
else
|
||||
LOGMASKED(LOG_WARN, "Connection to WDS%d failed because no drive is connected\n", index+1);
|
||||
|
||||
// Connect to HDC (or disconnect)
|
||||
m_hdc9234->connect_hard_drive(m_current_harddisk);
|
||||
}
|
||||
|
||||
@ -776,6 +788,7 @@ void myarc_hfdc_device::disconnect_floppy_drives()
|
||||
m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
|
||||
m_current_floppy = nullptr;
|
||||
}
|
||||
m_current_floppy_index = NONE;
|
||||
}
|
||||
|
||||
void myarc_hfdc_device::disconnect_hard_drives()
|
||||
@ -787,6 +800,7 @@ void myarc_hfdc_device::disconnect_hard_drives()
|
||||
m_current_harddisk->setup_seek_complete_cb(mfm_harddisk_device::seek_complete_cb());
|
||||
m_current_harddisk = nullptr;
|
||||
}
|
||||
m_current_hd_index = NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -875,6 +889,8 @@ void myarc_hfdc_device::device_start()
|
||||
// The HFDC does not use READY; it has on-board RAM for DMA
|
||||
m_current_floppy = nullptr;
|
||||
m_current_harddisk = nullptr;
|
||||
m_current_floppy_index = NONE;
|
||||
m_current_hd_index = NONE;
|
||||
|
||||
// Parent class members
|
||||
save_item(NAME(m_senila));
|
||||
|
@ -111,6 +111,12 @@ private:
|
||||
// Currently selected hard drive
|
||||
mfm_harddisk_device* m_current_harddisk;
|
||||
|
||||
// Currently selected floppy disk index
|
||||
int m_current_floppy_index;
|
||||
|
||||
// Currently selected hard disk index
|
||||
int m_current_hd_index;
|
||||
|
||||
// True: Access to DIP switch settings, false: access to line states
|
||||
bool m_see_switches;
|
||||
|
||||
|
@ -516,6 +516,14 @@ bool hdc92x4_device::fm_mode()
|
||||
return ((m_register_w[MODE]&MO_DENSITY)!=0);
|
||||
}
|
||||
|
||||
/*
|
||||
Tell whether we have timed steps or buffered steps.
|
||||
*/
|
||||
bool hdc92x4_device::timed_steps()
|
||||
{
|
||||
return ((m_register_w[MODE]&MO_STEPRATE)!=0);
|
||||
}
|
||||
|
||||
/*
|
||||
Are we back on track 0?
|
||||
*/
|
||||
@ -913,7 +921,14 @@ void hdc92x4_device::read_id(int& cont, bool implied_seek, bool wait_seek_comple
|
||||
// zero -> we're already there
|
||||
|
||||
if (m_substate == VERIFY) cont = NEXT;
|
||||
else m_track_delta = desired_cylinder() - current_cylinder();
|
||||
else
|
||||
{
|
||||
m_track_delta = desired_cylinder() - current_cylinder();
|
||||
if (m_track_delta > 0)
|
||||
LOGMASKED(LOG_STEP, "Implied seek %d tracks inwards\n", m_track_delta);
|
||||
if (m_track_delta < 0)
|
||||
LOGMASKED(LOG_STEP, "Implied seek %d tracks outwards\n", -m_track_delta);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@ -1162,6 +1177,7 @@ void hdc92x4_device::data_transfer(int& cont)
|
||||
case DATA_TRANSFER_READ:
|
||||
// OK, sector has been read.
|
||||
// Check CRC
|
||||
LOGMASKED(LOG_SUBSTATES, "substate DATA_TRANSFER_READ\n");
|
||||
if (m_live_state.crc != 0)
|
||||
{
|
||||
// Set Retry Required flag
|
||||
@ -1368,7 +1384,7 @@ void hdc92x4_device::reset_controller()
|
||||
*/
|
||||
void hdc92x4_device::drive_deselect()
|
||||
{
|
||||
LOGMASKED(LOG_SELECT, "DESELECT command\n");
|
||||
LOGMASKED(LOG_COMMAND, "DESELECT command\n");
|
||||
m_selected_drive_number = NODRIVE;
|
||||
m_output1 = 0x00;
|
||||
set_command_done(TC_SUCCESS);
|
||||
@ -1397,7 +1413,7 @@ void hdc92x4_device::restore_drive()
|
||||
|
||||
if (m_substate == UNDEF)
|
||||
{
|
||||
LOGMASKED(LOG_RESTORE, "RESTORE command %02x\n", current_command());
|
||||
LOGMASKED(LOG_COMMAND, "RESTORE command %02x\n", current_command());
|
||||
m_seek_count = 0;
|
||||
m_substate = RESTORE_CHECK;
|
||||
}
|
||||
@ -1496,7 +1512,7 @@ void hdc92x4_device::step_drive()
|
||||
|
||||
if (m_substate == UNDEF)
|
||||
{
|
||||
LOGMASKED(LOG_STEP, "STEP IN/OUT command %02x\n", current_command());
|
||||
LOGMASKED(LOG_COMMAND, "STEP IN/OUT command %02x\n", current_command());
|
||||
m_substate = STEP_ON;
|
||||
}
|
||||
|
||||
@ -1671,7 +1687,7 @@ void hdc92x4_device::drive_select()
|
||||
// Calculate the head load delays
|
||||
head_load_delay = head_load_delay_enable? m_register_w[DATA] * head_load_timer_increment[m_selected_drive_type] : 0;
|
||||
|
||||
LOGMASKED(LOG_SELECT, "DRIVE SELECT command (%02x): head load delay=%d, type=%d, drive=%d, pout=%02x, step_rate=%d\n", current_command(), head_load_delay, m_selected_drive_type, driveparm&3, m_register_w[RETRY_COUNT]&0x0f, pulse_width() + step_time());
|
||||
LOGMASKED(LOG_COMMAND, "DRIVE SELECT command (%02x): head load delay=%d, type=%d, drive=%d, pout=%02x, step_rate=%d\n", current_command(), head_load_delay, m_selected_drive_type, driveparm&3, m_register_w[RETRY_COUNT]&0x0f, pulse_width() + step_time());
|
||||
|
||||
// Copy the DMA registers to registers CURRENT_HEAD, CURRENT_CYLINDER,
|
||||
// and CURRENT_IDENT. This is required during formatting [1,2]
|
||||
@ -1722,7 +1738,7 @@ void hdc92x4_device::drive_select()
|
||||
void hdc92x4_device::set_register_pointer()
|
||||
{
|
||||
m_register_pointer = current_command() & 0xf;
|
||||
LOGMASKED(LOG_SETPTR, "SET REGISTER POINTER command; start reg=%d\n", m_register_pointer);
|
||||
LOGMASKED(LOG_COMMAND, "SET REGISTER POINTER command; start reg=%d\n", m_register_pointer);
|
||||
// The specification does not say anything about the effect of setting an
|
||||
// invalid value (only "care should be taken")
|
||||
if (m_register_pointer > 10)
|
||||
@ -1753,7 +1769,7 @@ void hdc92x4_device::seek_read_id()
|
||||
if (m_substate == UNDEF)
|
||||
{
|
||||
// Command init
|
||||
LOGMASKED(LOG_READ, "SEEK / READ ID command %02x, CHS=(%d,%d,%d)\n", current_command(), desired_cylinder(), desired_head(), desired_sector());
|
||||
LOGMASKED(LOG_COMMAND, "SEEK / READ ID command %02x, CHS=(%d,%d,%d)\n", current_command(), desired_cylinder(), desired_head(), desired_sector());
|
||||
m_substate = READ_ID;
|
||||
}
|
||||
|
||||
@ -1827,7 +1843,7 @@ void hdc92x4_device::read_sectors()
|
||||
{
|
||||
// Command init
|
||||
m_logical = (current_command() & 0x04)!=0; // used in VERIFY and DATA TRANSFER substate
|
||||
LOGMASKED(LOG_READ, "READ SECTORS %s command %02x, CHS=(%d,%d,%d)\n", m_logical? "LOGICAL": "PHYSICAL", current_command(), desired_cylinder(), desired_head(), desired_sector());
|
||||
LOGMASKED(LOG_COMMAND, "READ SECTORS %s command %02x, CHS=(%d,%d,%d)\n", m_logical? "LOGICAL": "PHYSICAL", current_command(), desired_cylinder(), desired_head(), desired_sector());
|
||||
|
||||
m_bypass = !m_is_hdc9234 && (current_command() & 0x02)!=0;
|
||||
m_transfer_enabled = (current_command() & 0x01)!=0;
|
||||
@ -1843,7 +1859,7 @@ void hdc92x4_device::read_sectors()
|
||||
switch (m_substate & 0xf0)
|
||||
{
|
||||
case READ_ID:
|
||||
read_id(cont, implied_seek, true); // Always check SEEK COMPLETE
|
||||
read_id(cont, implied_seek, !timed_steps()); // Check SEEK COMPLETE when time bits are 000
|
||||
break;
|
||||
case VERIFY:
|
||||
verify(cont); // for physical, only verify the first sector
|
||||
@ -1879,7 +1895,7 @@ void hdc92x4_device::read_track()
|
||||
{
|
||||
if (m_substate == UNDEF)
|
||||
{
|
||||
LOGMASKED(LOG_READTRACK, "READ TRACK command %02x, head = %d\n", current_command(), desired_head());
|
||||
LOGMASKED(LOG_COMMAND, "READ TRACK command %02x, head = %d\n", current_command(), desired_head());
|
||||
dma_address_out(m_register_w[DMA23_16], m_register_w[DMA15_8], m_register_w[DMA7_0]);
|
||||
m_transfer_enabled = (current_command() & 1)!=0;
|
||||
}
|
||||
@ -2003,7 +2019,7 @@ void hdc92x4_device::format_track()
|
||||
{
|
||||
if (m_substate == UNDEF)
|
||||
{
|
||||
LOGMASKED(LOG_FORMAT, "FORMAT TRACK command %02x, head = %d\n", current_command(), desired_head());
|
||||
LOGMASKED(LOG_COMMAND, "FORMAT TRACK command %02x, head = %d\n", current_command(), desired_head());
|
||||
m_substate = WAITINDEX0;
|
||||
m_deleted = (current_command() & 0x10)!=0;
|
||||
m_reduced_write_current = (current_command() & 0x08)!=0;
|
||||
@ -2118,7 +2134,7 @@ void hdc92x4_device::write_sectors()
|
||||
{
|
||||
// Command init
|
||||
m_logical = (current_command() & 0x20)!=0;
|
||||
LOGMASKED(LOG_WRITE, "WRITE SECTORS %s command %02x, CHS=(%d,%d,%d)\n", m_logical? "LOGICAL" : "PHYSICAL", current_command(), desired_cylinder(), desired_head(), desired_sector());
|
||||
LOGMASKED(LOG_COMMAND, "WRITE SECTORS %s command %02x, CHS=(%d,%d,%d)\n", 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;
|
||||
@ -2156,7 +2172,7 @@ void hdc92x4_device::write_sectors()
|
||||
switch (m_substate & 0xf0)
|
||||
{
|
||||
case READ_ID:
|
||||
read_id(cont, implied_seek, true); // Always check SEEK COMPLETE
|
||||
read_id(cont, implied_seek, !timed_steps()); // Check SEEK COMPLETE when time bits are 000
|
||||
break;
|
||||
case VERIFY:
|
||||
verify(cont);
|
||||
@ -3195,6 +3211,7 @@ void hdc92x4_device::live_run_hd_until(attotime limit)
|
||||
wait_for_realtime(VERIFY_FAILED);
|
||||
else
|
||||
wait_for_realtime(SEARCH_IDAM_FAILED);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3874,6 +3891,11 @@ uint8_t hdc92x4_device::get_data_from_encoding(uint16_t raw)
|
||||
return (value >> 14) & 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: Check whether the whole rollback concept makes sense in this
|
||||
controller. Unlike the wd17xx, this controller contains a lot more state,
|
||||
including the external RAM connected via DMA.
|
||||
*/
|
||||
void hdc92x4_device::rollback()
|
||||
{
|
||||
m_live_state = m_checkpoint_state;
|
||||
@ -4302,7 +4324,7 @@ void hdc92x4_device::write(offs_t offset, uint8_t data)
|
||||
{
|
||||
if ((offset & 1) == 0)
|
||||
{
|
||||
LOGMASKED(LOG_COMMAND, "New register write access %02x\n", data & 0xff);
|
||||
LOGMASKED(LOG_DETAIL, "New register write access %02x\n", data & 0xff);
|
||||
if (m_executing) LOGMASKED(LOG_WARN, "Error - previous command %02x not completed; register access ignored\n", current_command());
|
||||
else
|
||||
{
|
||||
@ -4312,7 +4334,7 @@ void hdc92x4_device::write(offs_t offset, uint8_t data)
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGMASKED(LOG_COMMAND, "New incoming command %02x\n", data);
|
||||
LOGMASKED(LOG_DETAIL, "New incoming command %02x\n", data);
|
||||
if (m_executing) LOGMASKED(LOG_WARN, "Error - previous command %02x not completed; new command %02x ignored\n", current_command(), data);
|
||||
else
|
||||
{
|
||||
@ -4599,15 +4621,20 @@ void hdc92x4_device::seek_complete_handler()
|
||||
int level = seek_complete()? ASSERT_LINE : CLEAR_LINE;
|
||||
LOGMASKED(LOG_LINES, "[%s] Seek complete handler; level=%d\n", ttsn(), level);
|
||||
|
||||
// Synchronize our position on the track
|
||||
live_sync();
|
||||
|
||||
// Some commands may wait for SEEK_COMPLETE regardless of the step rate
|
||||
if (waiting_for_line(SEEKCOMP_LINE, level))
|
||||
{
|
||||
// Synchronize our position on the track
|
||||
live_sync();
|
||||
|
||||
m_substate = m_state_after_line;
|
||||
m_state_after_line = UNDEF;
|
||||
reenter_command_processing();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (level==ASSERT_LINE) LOGMASKED(LOG_LINES, "[%s] Ignoring seek complete signal\n", ttsn());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4718,8 +4745,11 @@ void hdc92x4_device::connect_floppy_drive(floppy_image_device* floppy)
|
||||
void hdc92x4_device::connect_hard_drive(mfm_harddisk_device* harddisk)
|
||||
{
|
||||
m_harddisk = harddisk;
|
||||
m_hd_encoding = m_harddisk->get_encoding();
|
||||
LOGMASKED(LOG_DETAIL, "HD encoding = %d\n", m_hd_encoding);
|
||||
if (harddisk != nullptr)
|
||||
{
|
||||
m_hd_encoding = m_harddisk->get_encoding();
|
||||
LOGMASKED(LOG_DETAIL, "HD encoding = %d\n", m_hd_encoding);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -364,6 +364,9 @@ protected:
|
||||
// Are we in FM mode?
|
||||
bool fm_mode();
|
||||
|
||||
// Do we have timed steps?
|
||||
bool timed_steps();
|
||||
|
||||
// Seek completed?
|
||||
bool seek_complete();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user