mirror of
https://github.com/holub/mame
synced 2025-06-07 21:33:45 +03:00
MFM hard disk WIP; adding config options
This commit is contained in:
parent
b6ce8ee991
commit
05a79d2e20
@ -510,7 +510,7 @@ void myarc_hfdc_device::floppy_index_callback(floppy_image_device *floppy, int s
|
|||||||
*/
|
*/
|
||||||
void myarc_hfdc_device::harddisk_index_callback(mfm_harddisk_device *harddisk, int state)
|
void myarc_hfdc_device::harddisk_index_callback(mfm_harddisk_device *harddisk, int state)
|
||||||
{
|
{
|
||||||
/* if (TRACE_LINES) */ if (state==1) logerror("%s: HD index pulse\n", tag());
|
if (TRACE_LINES) if (state==1) logerror("%s: HD index pulse\n", tag());
|
||||||
set_bits(m_status_latch, HDC_DS_INDEX, (state==ASSERT_LINE));
|
set_bits(m_status_latch, HDC_DS_INDEX, (state==ASSERT_LINE));
|
||||||
signal_drive_status();
|
signal_drive_status();
|
||||||
}
|
}
|
||||||
@ -520,7 +520,7 @@ void myarc_hfdc_device::harddisk_index_callback(mfm_harddisk_device *harddisk, i
|
|||||||
*/
|
*/
|
||||||
void myarc_hfdc_device::harddisk_ready_callback(mfm_harddisk_device *harddisk, int state)
|
void myarc_hfdc_device::harddisk_ready_callback(mfm_harddisk_device *harddisk, int state)
|
||||||
{
|
{
|
||||||
/* if (TRACE_LINES) */ logerror("%s: HD READY = %d\n", tag(), state);
|
if (TRACE_LINES) logerror("%s: HD READY = %d\n", tag(), state);
|
||||||
set_bits(m_status_latch, HDC_DS_READY, (state==ASSERT_LINE));
|
set_bits(m_status_latch, HDC_DS_READY, (state==ASSERT_LINE));
|
||||||
signal_drive_status();
|
signal_drive_status();
|
||||||
}
|
}
|
||||||
@ -530,7 +530,7 @@ void myarc_hfdc_device::harddisk_ready_callback(mfm_harddisk_device *harddisk, i
|
|||||||
*/
|
*/
|
||||||
void myarc_hfdc_device::harddisk_skcom_callback(mfm_harddisk_device *harddisk, int state)
|
void myarc_hfdc_device::harddisk_skcom_callback(mfm_harddisk_device *harddisk, int state)
|
||||||
{
|
{
|
||||||
/* if (TRACE_LINES) */ logerror("%s: HD seek complete = %d\n", tag(), state);
|
if (TRACE_LINES) logerror("%s: HD seek complete = %d\n", tag(), state);
|
||||||
set_bits(m_status_latch, HDC_DS_SKCOM, (state==ASSERT_LINE));
|
set_bits(m_status_latch, HDC_DS_SKCOM, (state==ASSERT_LINE));
|
||||||
signal_drive_status();
|
signal_drive_status();
|
||||||
}
|
}
|
||||||
@ -1005,8 +1005,8 @@ static SLOT_INTERFACE_START( hfdc_floppies )
|
|||||||
SLOT_INTERFACE_END
|
SLOT_INTERFACE_END
|
||||||
|
|
||||||
static SLOT_INTERFACE_START( hfdc_harddisks )
|
static SLOT_INTERFACE_START( hfdc_harddisks )
|
||||||
SLOT_INTERFACE( "generic", MFM_HD_GENERIC ) // Generic high-level emulation
|
SLOT_INTERFACE( "generic", MFMHD_GENERIC ) // Generic high-level emulation
|
||||||
// SLOT_INTERFACE( "seagatemfm", MFM_HD_SEAGATE ) // Seagate ST-225 and others
|
SLOT_INTERFACE( "st225", MFMHD_ST225 ) // Seagate ST-225 and others
|
||||||
SLOT_INTERFACE_END
|
SLOT_INTERFACE_END
|
||||||
|
|
||||||
MACHINE_CONFIG_FRAGMENT( ti99_hfdc )
|
MACHINE_CONFIG_FRAGMENT( ti99_hfdc )
|
||||||
@ -1024,9 +1024,9 @@ MACHINE_CONFIG_FRAGMENT( ti99_hfdc )
|
|||||||
MCFG_FLOPPY_DRIVE_ADD("f4", hfdc_floppies, NULL, myarc_hfdc_device::floppy_formats)
|
MCFG_FLOPPY_DRIVE_ADD("f4", hfdc_floppies, NULL, myarc_hfdc_device::floppy_formats)
|
||||||
|
|
||||||
// NB: Hard disks don't go without image (other than floppy drives)
|
// NB: Hard disks don't go without image (other than floppy drives)
|
||||||
MCFG_MFM_HARDDISK_ADD("h1", hfdc_harddisks, NULL, MFM_BYTE)
|
MCFG_MFM_HARDDISK_CONN_ADD("h1", hfdc_harddisks, NULL, MFM_BYTE, 3000, 20)
|
||||||
MCFG_MFM_HARDDISK_ADD("h2", hfdc_harddisks, NULL, MFM_BYTE)
|
MCFG_MFM_HARDDISK_CONN_ADD("h2", hfdc_harddisks, NULL, MFM_BYTE, 2000, 20)
|
||||||
MCFG_MFM_HARDDISK_ADD("h3", hfdc_harddisks, NULL, MFM_BYTE)
|
MCFG_MFM_HARDDISK_CONN_ADD("h3", hfdc_harddisks, NULL, MFM_BYTE, 2000, 20)
|
||||||
|
|
||||||
MCFG_DEVICE_ADD(CLOCK_TAG, MM58274C, 0)
|
MCFG_DEVICE_ADD(CLOCK_TAG, MM58274C, 0)
|
||||||
MCFG_MM58274C_MODE24(1) // 24 hour
|
MCFG_MM58274C_MODE24(1) // 24 hour
|
||||||
|
@ -607,19 +607,19 @@ void hdc9234_device::wait_line(int line, line_state level, int substate, bool st
|
|||||||
bool line_at_level = true;
|
bool line_at_level = true;
|
||||||
if (line == SEEKCOMP_LINE && (seek_complete() == (level==ASSERT_LINE)))
|
if (line == SEEKCOMP_LINE && (seek_complete() == (level==ASSERT_LINE)))
|
||||||
{
|
{
|
||||||
logerror("%s: SEEK_COMPLETE line is already %d\n", tag(), level);
|
if (TRACE_LINES) logerror("%s: SEEK_COMPLETE line is already %d\n", tag(), level);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (line == INDEX_LINE && (index_hole() == (level==ASSERT_LINE)))
|
if (line == INDEX_LINE && (index_hole() == (level==ASSERT_LINE)))
|
||||||
{
|
{
|
||||||
logerror("%s: INDEX line is already %d\n", tag(), level);
|
if (TRACE_LINES) logerror("%s: INDEX line is already %d\n", tag(), level);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (line == READY_LINE && (drive_ready() == (level==ASSERT_LINE)))
|
if (line == READY_LINE && (drive_ready() == (level==ASSERT_LINE)))
|
||||||
{
|
{
|
||||||
logerror("%s: READY line is already %d\n", tag(), level);
|
if (TRACE_LINES) logerror("%s: READY line is already %d\n", tag(), level);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2724,7 +2724,7 @@ void hdc9234_device::live_run_until(attotime limit)
|
|||||||
void hdc9234_device::live_run_hd_until(attotime limit)
|
void hdc9234_device::live_run_hd_until(attotime limit)
|
||||||
{
|
{
|
||||||
int slot = 0;
|
int slot = 0;
|
||||||
logerror("%s: live_run_hd\n", tag());
|
if (TRACE_LIVE) logerror("%s: live_run_hd\n", tag());
|
||||||
|
|
||||||
if (m_live_state.state == IDLE || m_live_state.next_state != -1)
|
if (m_live_state.state == IDLE || m_live_state.next_state != -1)
|
||||||
return;
|
return;
|
||||||
@ -2745,6 +2745,12 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
|||||||
switch (m_live_state.state)
|
switch (m_live_state.state)
|
||||||
{
|
{
|
||||||
case SEARCH_IDAM:
|
case SEARCH_IDAM:
|
||||||
|
if (TRACE_LIVE && m_last_live_state != SEARCH_IDAM)
|
||||||
|
{
|
||||||
|
logerror("%s: [%s live] SEARCH_IDAM [limit %s]\n", tag(),tts(m_live_state.time).c_str(), tts(limit).c_str());
|
||||||
|
m_last_live_state = m_live_state.state;
|
||||||
|
}
|
||||||
|
|
||||||
// This bit will be set when the IDAM cannot be found
|
// This bit will be set when the IDAM cannot be found
|
||||||
set_bits(m_register_r[CHIP_STATUS], CS_SYNCERR, false);
|
set_bits(m_register_r[CHIP_STATUS], CS_SYNCERR, false);
|
||||||
|
|
||||||
@ -2753,7 +2759,9 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
|||||||
if (TRACE_LIVE) logerror("%s: [%s live] SEARCH_IDAM limit reached\n", tag(), tts(m_live_state.time).c_str());
|
if (TRACE_LIVE) logerror("%s: [%s live] SEARCH_IDAM limit reached\n", tag(), tts(m_live_state.time).c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logerror("%s: [%s live] Read %04x\n", tag(), tts(m_live_state.time).c_str(), m_live_state.shift_reg);
|
|
||||||
|
if (TRACE_LIVE)
|
||||||
|
if ((m_live_state.bit_counter & 0x000f)==0) logerror("%s: [%s live] Read %04x\n", tag(), tts(m_live_state.time).c_str(), m_live_state.shift_reg);
|
||||||
|
|
||||||
// [1] p. 9: The ID field sync mark must be found within 33,792 byte times
|
// [1] p. 9: The ID field sync mark must be found within 33,792 byte times
|
||||||
if (m_live_state.bit_count_total > 33792*16)
|
if (m_live_state.bit_count_total > 33792*16)
|
||||||
@ -2781,6 +2789,9 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
|||||||
case READ_IDENT:
|
case READ_IDENT:
|
||||||
if (read_from_mfmhd(limit)) return;
|
if (read_from_mfmhd(limit)) return;
|
||||||
|
|
||||||
|
// Repeat until we have collected 16 bits (MFM_BITS; in the other modes this is always false)
|
||||||
|
if (m_live_state.bit_counter & 15) break;
|
||||||
|
|
||||||
// Ident bytes are 111111xx
|
// Ident bytes are 111111xx
|
||||||
if ((m_live_state.data_reg & 0xfc) != 0xfc)
|
if ((m_live_state.data_reg & 0xfc) != 0xfc)
|
||||||
{
|
{
|
||||||
@ -2806,6 +2817,9 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
|||||||
|
|
||||||
if (read_from_mfmhd(limit)) return;
|
if (read_from_mfmhd(limit)) return;
|
||||||
|
|
||||||
|
// Repeat until we have collected 16 bits
|
||||||
|
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);
|
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[id_field[slot++]] = m_live_state.data_reg;
|
||||||
|
|
||||||
@ -2834,7 +2848,8 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
|||||||
|
|
||||||
if (read_from_mfmhd(limit)) return;
|
if (read_from_mfmhd(limit)) return;
|
||||||
|
|
||||||
logerror("%s: [%s live] Read %04x\n", tag(), tts(m_live_state.time).c_str(), m_live_state.shift_reg);
|
if (TRACE_LIVE)
|
||||||
|
if ((m_live_state.bit_counter & 15)==0) logerror("%s: [%s live] Read %04x\n", tag(), tts(m_live_state.time).c_str(), m_live_state.shift_reg);
|
||||||
|
|
||||||
if (m_live_state.bit_counter > 30*16)
|
if (m_live_state.bit_counter > 30*16)
|
||||||
{
|
{
|
||||||
@ -2856,6 +2871,8 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
|||||||
case READ_DATADEL_FLAG:
|
case READ_DATADEL_FLAG:
|
||||||
if (read_from_mfmhd(limit)) return;
|
if (read_from_mfmhd(limit)) return;
|
||||||
|
|
||||||
|
if (m_live_state.bit_counter & 15) break;
|
||||||
|
|
||||||
if ((m_live_state.data_reg & 0xff) == 0xf8)
|
if ((m_live_state.data_reg & 0xff) == 0xf8)
|
||||||
{
|
{
|
||||||
if (TRACE_LIVE) logerror("%s: [%s live] Found deleted data mark F8 after DAM sync\n", tag(), tts(m_live_state.time).c_str());
|
if (TRACE_LIVE) logerror("%s: [%s live] Found deleted data mark F8 after DAM sync\n", tag(), tts(m_live_state.time).c_str());
|
||||||
@ -2897,6 +2914,9 @@ void hdc9234_device::live_run_hd_until(attotime limit)
|
|||||||
m_out_dmarq(ASSERT_LINE);
|
m_out_dmarq(ASSERT_LINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Repeat until we have collected 16 bits
|
||||||
|
if (m_live_state.bit_counter & 15) break;
|
||||||
|
|
||||||
slot = (m_live_state.bit_counter >> 4)-1;
|
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, calc_sector_size(), m_live_state.data_reg, m_live_state.crc);
|
||||||
|
|
||||||
@ -3018,6 +3038,7 @@ void hdc9234_device::live_sync()
|
|||||||
m_live_state.time = attotime::never;
|
m_live_state.time = attotime::never;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_live_state.next_state = -1;
|
m_live_state.next_state = -1;
|
||||||
checkpoint();
|
checkpoint();
|
||||||
}
|
}
|
||||||
@ -3790,7 +3811,7 @@ void hdc9234_device::connect_hard_drive(mfm_harddisk_device* harddisk)
|
|||||||
{
|
{
|
||||||
m_harddisk = harddisk;
|
m_harddisk = harddisk;
|
||||||
m_hd_encoding = m_harddisk->get_encoding();
|
m_hd_encoding = m_harddisk->get_encoding();
|
||||||
logerror("%s: HD encoding = %d\n", tag(), m_hd_encoding);
|
if (TRACE_DETAIL) logerror("%s: HD encoding = %d\n", tag(), m_hd_encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -14,22 +14,21 @@
|
|||||||
|
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
// TODO: Format
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "formats/imageutl.h"
|
#include "formats/imageutl.h"
|
||||||
#include "harddisk.h"
|
#include "harddisk.h"
|
||||||
|
|
||||||
#include "ti99_hd.h"
|
#include "ti99_hd.h"
|
||||||
|
|
||||||
#define TI99HD_BLOCKNOTFOUND -1
|
#define TRACE_STEPS 0
|
||||||
|
#define TRACE_SIGNALS 0
|
||||||
#define LOG logerror
|
#define TRACE_READ 0
|
||||||
#define VERBOSE 0
|
#define TRACE_CACHE 0
|
||||||
|
#define TRACE_RWTRACK 0
|
||||||
#define GAP1 16
|
#define TRACE_BITS 0
|
||||||
#define GAP2 8
|
#define TRACE_DETAIL 0
|
||||||
#define GAP3 15
|
|
||||||
#define GAP4 340
|
|
||||||
#define SYNC 13
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -48,10 +47,20 @@ enum
|
|||||||
#define TRACKSLOTS 5
|
#define TRACKSLOTS 5
|
||||||
#define TRACKIMAGE_SIZE 10416 // Provide the buffer for a complete track, including preambles and gaps
|
#define TRACKIMAGE_SIZE 10416 // Provide the buffer for a complete track, including preambles and gaps
|
||||||
|
|
||||||
|
std::string mfm_harddisk_device::tts(const attotime &t)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
int nsec = t.attoseconds / ATTOSECONDS_PER_NANOSECOND;
|
||||||
|
sprintf(buf, "%4d.%03d,%03d,%03d", int(t.seconds), nsec/1000000, (nsec/1000)%1000, nsec % 1000);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
mfm_harddisk_device::mfm_harddisk_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
|
mfm_harddisk_device::mfm_harddisk_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
|
||||||
: harddisk_image_device(mconfig, type, name, tag, owner, clock, shortname, source),
|
: harddisk_image_device(mconfig, type, name, tag, owner, clock, shortname, source),
|
||||||
device_slot_card_interface(mconfig, *this)
|
device_slot_card_interface(mconfig, *this)
|
||||||
{
|
{
|
||||||
|
m_spinupms = 10000;
|
||||||
|
m_cachelines = TRACKSLOTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
mfm_harddisk_device::~mfm_harddisk_device()
|
mfm_harddisk_device::~mfm_harddisk_device()
|
||||||
@ -63,16 +72,13 @@ void mfm_harddisk_device::device_start()
|
|||||||
m_index_timer = timer_alloc(INDEX_TM);
|
m_index_timer = timer_alloc(INDEX_TM);
|
||||||
m_spinup_timer = timer_alloc(SPINUP_TM);
|
m_spinup_timer = timer_alloc(SPINUP_TM);
|
||||||
m_seek_timer = timer_alloc(SEEK_TM);
|
m_seek_timer = timer_alloc(SEEK_TM);
|
||||||
m_spinup_time = attotime::from_msec(8000);
|
|
||||||
m_rev_time = attotime::from_hz(60);
|
m_rev_time = attotime::from_hz(60);
|
||||||
|
|
||||||
// MFM drives have a revolution rate of 3600 rpm (i.e. 60/sec)
|
// MFM drives have a revolution rate of 3600 rpm (i.e. 60/sec)
|
||||||
m_index_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60));
|
m_index_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60));
|
||||||
|
|
||||||
// Spinup may take up to 24 seconds
|
m_current_cylinder = 615; // Park position
|
||||||
m_spinup_timer->adjust(m_spinup_time);
|
m_spinup_timer->adjust(attotime::from_msec(m_spinupms));
|
||||||
|
|
||||||
m_current_cylinder = 10; // for test purpose
|
|
||||||
|
|
||||||
m_cache = global_alloc(mfmhd_trackimage_cache);
|
m_cache = global_alloc(mfmhd_trackimage_cache);
|
||||||
}
|
}
|
||||||
@ -85,6 +91,7 @@ void mfm_harddisk_device::device_reset()
|
|||||||
m_seek_inward = false;
|
m_seek_inward = false;
|
||||||
m_track_delta = 0;
|
m_track_delta = 0;
|
||||||
m_step_line = CLEAR_LINE;
|
m_step_line = CLEAR_LINE;
|
||||||
|
m_recalibrated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mfm_harddisk_device::device_stop()
|
void mfm_harddisk_device::device_stop()
|
||||||
@ -94,15 +101,15 @@ void mfm_harddisk_device::device_stop()
|
|||||||
|
|
||||||
bool mfm_harddisk_device::call_load()
|
bool mfm_harddisk_device::call_load()
|
||||||
{
|
{
|
||||||
logerror("call_load\n");
|
setup_characteristics();
|
||||||
bool loaded = harddisk_image_device::call_load();
|
bool loaded = harddisk_image_device::call_load();
|
||||||
if (loaded==IMAGE_INIT_PASS)
|
if (loaded==IMAGE_INIT_PASS)
|
||||||
{
|
{
|
||||||
m_cache->init(get_chd_file(), tag(), TRACKSLOTS, m_encoding);
|
m_cache->init(get_chd_file(), tag(), m_max_cylinder, m_max_heads, m_cachelines, m_encoding);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logerror("Could not load CHD\n");
|
logerror("%s: Could not load CHD\n", tag());
|
||||||
}
|
}
|
||||||
return loaded;
|
return loaded;
|
||||||
}
|
}
|
||||||
@ -127,13 +134,21 @@ attotime mfm_harddisk_device::track_end_time()
|
|||||||
// We back up two microseconds before the track end to avoid the
|
// We back up two microseconds before the track end to avoid the
|
||||||
// index pulse to appear earlier (because of rounding effects)
|
// index pulse to appear earlier (because of rounding effects)
|
||||||
attotime nexttime = m_rev_time - attotime::from_nsec(2000);
|
attotime nexttime = m_rev_time - attotime::from_nsec(2000);
|
||||||
|
attotime endtime = attotime::never;
|
||||||
|
|
||||||
if (!m_ready)
|
if (!m_ready)
|
||||||
{
|
{
|
||||||
// estimate the next index time; during power-up we assume half the rotational speed
|
// estimate the next index time; during power-up we assume half the rotational speed
|
||||||
// Should never be relevant, though, because READY is false.
|
// Should never be relevant, though, because READY is false.
|
||||||
nexttime = nexttime * 2;
|
nexttime = nexttime * 2;
|
||||||
}
|
}
|
||||||
return (m_revolution_start_time.is_never())? attotime::never : (m_revolution_start_time + nexttime);
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
return endtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||||
@ -142,18 +157,18 @@ void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int
|
|||||||
{
|
{
|
||||||
case INDEX_TM:
|
case INDEX_TM:
|
||||||
/* Simple index hole handling. We assume that there is only a short pulse. */
|
/* Simple index hole handling. We assume that there is only a short pulse. */
|
||||||
|
m_revolution_start_time = machine().time();
|
||||||
if (!m_index_pulse_cb.isnull())
|
if (!m_index_pulse_cb.isnull())
|
||||||
{
|
{
|
||||||
m_revolution_start_time = machine().time();
|
|
||||||
m_index_pulse_cb(this, ASSERT_LINE);
|
m_index_pulse_cb(this, ASSERT_LINE);
|
||||||
m_index_pulse_cb(this, CLEAR_LINE);
|
m_index_pulse_cb(this, CLEAR_LINE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPINUP_TM:
|
case SPINUP_TM:
|
||||||
m_ready = true;
|
recalibrate();
|
||||||
logerror("%s: Spinup complete, drive is ready\n", tag());
|
|
||||||
if (!m_ready_cb.isnull()) m_ready_cb(this, ASSERT_LINE);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SEEK_TM:
|
case SEEK_TM:
|
||||||
switch (m_step_phase)
|
switch (m_step_phase)
|
||||||
{
|
{
|
||||||
@ -169,7 +184,7 @@ void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int
|
|||||||
// Start the settle timer
|
// Start the settle timer
|
||||||
m_step_phase = STEP_SETTLE;
|
m_step_phase = STEP_SETTLE;
|
||||||
m_seek_timer->adjust(attotime::from_usec(16800));
|
m_seek_timer->adjust(attotime::from_usec(16800));
|
||||||
logerror("%s: Arrived at target track %d, settling ...\n", tag(), m_current_cylinder);
|
if (TRACE_STEPS && TRACE_DETAIL) logerror("%s: Arrived at target cylinder %d, settling ...\n", tag(), m_current_cylinder);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case STEP_SETTLE:
|
case STEP_SETTLE:
|
||||||
@ -178,7 +193,17 @@ void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Seek completed
|
// Seek completed
|
||||||
logerror("%s: Settling done at cylinder %d, seek complete\n", tag(), m_current_cylinder);
|
if (!m_recalibrated)
|
||||||
|
{
|
||||||
|
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 (!m_ready_cb.isnull()) m_ready_cb(this, ASSERT_LINE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (TRACE_SIGNALS) logerror("%s: Settling done at cylinder %d, seek complete\n", tag(), m_current_cylinder);
|
||||||
|
}
|
||||||
m_seek_complete = true;
|
m_seek_complete = true;
|
||||||
if (!m_seek_complete_cb.isnull()) m_seek_complete_cb(this, ASSERT_LINE);
|
if (!m_seek_complete_cb.isnull()) m_seek_complete_cb(this, ASSERT_LINE);
|
||||||
m_step_phase = STEP_COLLECT;
|
m_step_phase = STEP_COLLECT;
|
||||||
@ -188,11 +213,22 @@ void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mfm_harddisk_device::recalibrate()
|
||||||
|
{
|
||||||
|
if (TRACE_STEPS) logerror("%s: Recalibrate to track 0\n", tag());
|
||||||
|
direction_in_w(CLEAR_LINE);
|
||||||
|
while (-m_track_delta < 620)
|
||||||
|
{
|
||||||
|
step_w(ASSERT_LINE);
|
||||||
|
step_w(CLEAR_LINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void mfm_harddisk_device::head_move()
|
void mfm_harddisk_device::head_move()
|
||||||
{
|
{
|
||||||
int steps = m_track_delta;
|
int steps = m_track_delta;
|
||||||
if (steps < 0) steps = -steps;
|
if (steps < 0) steps = -steps;
|
||||||
logerror("%s: Moving head by %d step(s) %s\n", tag(), steps, (m_track_delta<0)? "outward" : "inward");
|
if (TRACE_STEPS) logerror("%s: Moving head by %d step(s) %s\n", tag(), steps, (m_track_delta<0)? "outward" : "inward");
|
||||||
|
|
||||||
int disttime = steps*200;
|
int disttime = steps*200;
|
||||||
m_step_phase = STEP_MOVING;
|
m_step_phase = STEP_MOVING;
|
||||||
@ -208,7 +244,7 @@ void mfm_harddisk_device::head_move()
|
|||||||
void mfm_harddisk_device::direction_in_w(line_state line)
|
void mfm_harddisk_device::direction_in_w(line_state line)
|
||||||
{
|
{
|
||||||
m_seek_inward = (line == ASSERT_LINE);
|
m_seek_inward = (line == ASSERT_LINE);
|
||||||
logerror("%s: Setting seek direction %s\n", tag(), m_seek_inward? "inward" : "outward");
|
if (TRACE_STEPS && TRACE_DETAIL) logerror("%s: Setting seek direction %s\n", tag(), m_seek_inward? "inward" : "outward");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -267,10 +303,10 @@ void mfm_harddisk_device::step_w(line_state line)
|
|||||||
|
|
||||||
// Counter will be adjusted according to the direction (+-1)
|
// Counter will be adjusted according to the direction (+-1)
|
||||||
m_track_delta += (m_seek_inward)? +1 : -1;
|
m_track_delta += (m_seek_inward)? +1 : -1;
|
||||||
logerror("%s: Got seek pulse; track delta %d\n", tag(), m_track_delta);
|
if (TRACE_STEPS && TRACE_DETAIL) logerror("%s: Got seek pulse; track delta %d\n", tag(), m_track_delta);
|
||||||
if (m_track_delta < -670 || m_track_delta > 670)
|
if (m_track_delta < -670 || m_track_delta > 670)
|
||||||
{
|
{
|
||||||
logerror("%s: Excessive step pulses - doing auto-truncation\n", tag());
|
if (TRACE_STEPS) logerror("%s: Excessive step pulses - doing auto-truncation\n", tag());
|
||||||
m_autotruncation = true;
|
m_autotruncation = true;
|
||||||
}
|
}
|
||||||
m_seek_timer->adjust(attotime::from_usec(250));
|
m_seek_timer->adjust(attotime::from_usec(250));
|
||||||
@ -296,39 +332,79 @@ bool mfm_harddisk_device::read(attotime &from_when, const attotime &limit, UINT1
|
|||||||
throw emu_fatalerror("Cannot read CHD image");
|
throw emu_fatalerror("Cannot read CHD image");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We stop some few cells early each track, so lift the from_when time over
|
||||||
|
// the 2 microseconds.
|
||||||
|
if (from_when < m_revolution_start_time) from_when = m_revolution_start_time;
|
||||||
|
|
||||||
// Calculate the position in the track, given the from_when time and the revolution_start_time.
|
// Calculate the position in the track, given the from_when time and the revolution_start_time.
|
||||||
// Each cell takes 100 ns (10 MHz)
|
// Each cell takes 100 ns (10 MHz)
|
||||||
|
|
||||||
int cell = (from_when - m_revolution_start_time).as_ticks(10000000);
|
int cell = (from_when - m_revolution_start_time).as_ticks(10000000);
|
||||||
|
|
||||||
from_when += attotime::from_nsec(1600);
|
attotime fw = from_when;
|
||||||
|
|
||||||
|
from_when += attotime::from_nsec((m_encoding==MFM_BITS)? 100 : 1600);
|
||||||
if (from_when > limit) return true;
|
if (from_when > limit) return true;
|
||||||
|
|
||||||
int position = cell / 16;
|
|
||||||
|
int bytepos = cell / 16;
|
||||||
|
|
||||||
// Reached the end
|
// Reached the end
|
||||||
if (position >= 10416)
|
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(fw).c_str());
|
||||||
m_revolution_start_time += m_rev_time;
|
m_revolution_start_time += m_rev_time;
|
||||||
cell = (from_when - m_revolution_start_time).as_ticks(10000000);
|
cell = (from_when - m_revolution_start_time).as_ticks(10000000);
|
||||||
position = cell / 16;
|
bytepos = cell / 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: fix the actual issue
|
if (bytepos < 0)
|
||||||
if (position < 0) position = 0;
|
{
|
||||||
|
if (TRACE_DETAIL) logerror("%s: Negative cell number: rev_start = %s, live = %s\n", tag(), tts(m_revolution_start_time).c_str(), tts(fw).c_str());
|
||||||
logerror("%s: Reading track %d head %d at position %d\n", tag(), m_current_cylinder, m_current_head, position);
|
bytepos = 0;
|
||||||
cdata = track[position];
|
}
|
||||||
|
|
||||||
|
if (m_encoding == MFM_BITS)
|
||||||
|
{
|
||||||
|
// We will deliver a single bit
|
||||||
|
int cellno = cell % 16;
|
||||||
|
cdata = ((track[bytepos] << cellno) & 0x8000) >> 15;
|
||||||
|
if (TRACE_BITS) logerror("%s: Reading (c=%d,h=%d,bit=%d) at cell %d [%s] = %d\n", tag(), m_current_cylinder, m_current_head, cellno, cell, tts(fw).c_str(), cdata);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We will deliver a whole byte
|
||||||
|
if (TRACE_READ) logerror("%s: Reading (c=%d,h=%d) at position %d\n", tag(), m_current_cylinder, m_current_head, bytepos);
|
||||||
|
cdata = track[bytepos];
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mfm_hd_generic_device::mfm_hd_generic_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
mfm_hd_generic_device::mfm_hd_generic_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||||
: mfm_harddisk_device(mconfig, MFM_HD_GENERIC, "Generic MFM hard disk (byte level)", tag, owner, clock, "mfm_harddisk", __FILE__)
|
: mfm_harddisk_device(mconfig, MFMHD_GENERIC, "Generic MFM hard disk", tag, owner, clock, "mfm_harddisk", __FILE__)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const device_type MFM_HD_GENERIC = &device_creator<mfm_hd_generic_device>;
|
void mfm_hd_generic_device::setup_characteristics()
|
||||||
|
{
|
||||||
|
m_max_cylinder = 0;
|
||||||
|
m_max_heads = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const device_type MFMHD_GENERIC = &device_creator<mfm_hd_generic_device>;
|
||||||
|
|
||||||
|
mfm_hd_st225_device::mfm_hd_st225_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||||
|
: mfm_harddisk_device(mconfig, MFMHD_ST225, "Seagate ST-225 MFM hard disk", tag, owner, clock, "mfm_hd_st225", __FILE__)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mfm_hd_st225_device::setup_characteristics()
|
||||||
|
{
|
||||||
|
m_max_cylinder = 615;
|
||||||
|
m_max_heads = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
const device_type MFMHD_ST225 = &device_creator<mfm_hd_st225_device>;
|
||||||
|
|
||||||
// ===========================================================
|
// ===========================================================
|
||||||
// Track cache
|
// Track cache
|
||||||
@ -345,12 +421,12 @@ mfmhd_trackimage_cache::mfmhd_trackimage_cache():
|
|||||||
mfmhd_trackimage_cache::~mfmhd_trackimage_cache()
|
mfmhd_trackimage_cache::~mfmhd_trackimage_cache()
|
||||||
{
|
{
|
||||||
mfmhd_trackimage* current = m_tracks;
|
mfmhd_trackimage* current = m_tracks;
|
||||||
logerror("%s: MFM HD cache destroy\n", tag());
|
if (TRACE_CACHE) logerror("%s: MFM HD cache destroy\n", tag());
|
||||||
|
|
||||||
// Still dirty?
|
// Still dirty?
|
||||||
while (current != NULL)
|
while (current != NULL)
|
||||||
{
|
{
|
||||||
logerror("%s: MFM HD cache: evict line cylinder=%d head=%d\n", tag(), current->cylinder, current->head);
|
if (TRACE_CACHE) logerror("%s: MFM HD cache: evict line cylinder=%d head=%d\n", tag(), current->cylinder, current->head);
|
||||||
if (current->dirty) write_back(current);
|
if (current->dirty) write_back(current);
|
||||||
global_free_array(current->encdata);
|
global_free_array(current->encdata);
|
||||||
mfmhd_trackimage* currenttmp = current->next;
|
mfmhd_trackimage* currenttmp = current->next;
|
||||||
@ -362,12 +438,12 @@ mfmhd_trackimage_cache::~mfmhd_trackimage_cache()
|
|||||||
/*
|
/*
|
||||||
Initialize the cache by loading the first <trackslots> tracks.
|
Initialize the cache by loading the first <trackslots> tracks.
|
||||||
*/
|
*/
|
||||||
void mfmhd_trackimage_cache::init(chd_file* chdfile, const char* dtag, int trackslots, mfmhd_enc_t encoding)
|
void mfmhd_trackimage_cache::init(chd_file* chdfile, const char* dtag, int maxcyl, int maxhead, int trackslots, mfmhd_enc_t encoding)
|
||||||
{
|
{
|
||||||
m_encoding = encoding;
|
m_encoding = encoding;
|
||||||
m_tagdev = dtag;
|
m_tagdev = dtag;
|
||||||
|
|
||||||
logerror("%s: MFM HD cache init; using encoding %d\n", m_tagdev, encoding);
|
if (TRACE_CACHE) logerror("%s: MFM HD cache init; using encoding %d\n", m_tagdev, encoding);
|
||||||
chd_error state = CHDERR_NONE;
|
chd_error state = CHDERR_NONE;
|
||||||
mfmhd_trackimage* previous = NULL;
|
mfmhd_trackimage* previous = NULL;
|
||||||
mfmhd_trackimage* current = NULL;
|
mfmhd_trackimage* current = NULL;
|
||||||
@ -394,34 +470,43 @@ void mfmhd_trackimage_cache::init(chd_file* chdfile, const char* dtag, int track
|
|||||||
throw emu_fatalerror("Invalid metadata");
|
throw emu_fatalerror("Invalid metadata");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load some tracks into the cache
|
if (maxcyl != 0 && m_cylinders > maxcyl)
|
||||||
for (int i=0; i < trackslots; i++)
|
|
||||||
{
|
{
|
||||||
logerror("%s: MFM HD allocate cache slot\n", tag());
|
throw emu_fatalerror("Image geometry does not fit this kind of hard drive: drive=(%d,%d), image=(%d,%d)", maxcyl, maxhead, m_cylinders, m_heads);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load some tracks into the cache
|
||||||
|
int track = 0;
|
||||||
|
int head = 0;
|
||||||
|
int cylinder = 0;
|
||||||
|
while (track < trackslots)
|
||||||
|
{
|
||||||
|
if (TRACE_CACHE && TRACE_DETAIL) logerror("%s: MFM HD allocate cache slot\n", tag());
|
||||||
previous = current;
|
previous = current;
|
||||||
current = global_alloc(mfmhd_trackimage);
|
current = global_alloc(mfmhd_trackimage);
|
||||||
current->encdata = global_alloc_array(UINT16, TRACKIMAGE_SIZE);
|
current->encdata = global_alloc_array(UINT16, TRACKIMAGE_SIZE);
|
||||||
|
|
||||||
// Load the first tracks into the slots
|
// Load the first tracks into the slots
|
||||||
state = load_track(current, i, 0, 32, 256, 4);
|
state = load_track(current, cylinder, head, 32, 256, 4);
|
||||||
current->next = NULL;
|
|
||||||
|
|
||||||
if (state != CHDERR_NONE) throw emu_fatalerror("Cannot load cylinder %d head %d from hard disk", i, 0);
|
if (state != CHDERR_NONE) throw emu_fatalerror("Cannot load (c=%d,h=%d) from hard disk", cylinder, head);
|
||||||
|
|
||||||
|
// We will read all heads per cylinder first, then go to the next cylinder.
|
||||||
|
if (++head >= m_heads)
|
||||||
|
{
|
||||||
|
head = 0;
|
||||||
|
cylinder++;
|
||||||
|
}
|
||||||
|
current->next = NULL;
|
||||||
|
|
||||||
if (previous != NULL)
|
if (previous != NULL)
|
||||||
previous->next = current;
|
previous->next = current;
|
||||||
else
|
else
|
||||||
// Head
|
// Head
|
||||||
m_tracks = current;
|
m_tracks = current;
|
||||||
}
|
|
||||||
|
|
||||||
current = m_tracks;
|
// Count the number of loaded tracks
|
||||||
|
track++;
|
||||||
while (current != NULL)
|
|
||||||
{
|
|
||||||
logerror("%s: MFM HD cache: containing line cylinder=%d head=%d\n", tag(), current->cylinder, current->head);
|
|
||||||
mfmhd_trackimage* currenttmp = current->next;
|
|
||||||
current = currenttmp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,7 +576,7 @@ UINT16* mfmhd_trackimage_cache::get_trackimage(int cylinder, int head)
|
|||||||
|
|
||||||
// previous points to the second to last element
|
// previous points to the second to last element
|
||||||
current = previous->next;
|
current = previous->next;
|
||||||
logerror("%s: MFM HD cache: evict line cylinder=%d head=%d\n", tag(), current->cylinder, current->head);
|
if (TRACE_CACHE) logerror("%s: MFM HD cache: evict line (c=%d,h=%d)\n", tag(), current->cylinder, current->head);
|
||||||
|
|
||||||
if (current->dirty) write_back(current);
|
if (current->dirty) write_back(current);
|
||||||
state = load_track(current, cylinder, head, 32, 256, 4);
|
state = load_track(current, cylinder, head, 32, 256, 4);
|
||||||
@ -588,7 +673,7 @@ chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinde
|
|||||||
|
|
||||||
UINT8 sector_content[1024];
|
UINT8 sector_content[1024];
|
||||||
|
|
||||||
logerror("%s: MFM HD cache: load cylinder=%d head=%d from CHD\n", tag(), cylinder, head);
|
if (TRACE_RWTRACK) logerror("%s: MFM HD cache: load (c=%d,h=%d) from CHD\n", tag(), cylinder, head);
|
||||||
|
|
||||||
m_lastbit = false;
|
m_lastbit = false;
|
||||||
int position = 0; // will be incremented by each encode call
|
int position = 0; // will be incremented by each encode call
|
||||||
@ -602,10 +687,10 @@ chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinde
|
|||||||
// Round up
|
// Round up
|
||||||
int delta = (sectorcount + interleave-1) / interleave;
|
int delta = (sectorcount + interleave-1) / interleave;
|
||||||
|
|
||||||
logerror("%02x %02x: ", cylinder&0xff, head&0xff);
|
if (TRACE_DETAIL) logerror("cyl=%02x head=%02x: sector sequence = ", cylinder&0xff, head&0xff);
|
||||||
for (int sector = 0; sector < sectorcount; sector++)
|
for (int sector = 0; sector < sectorcount; sector++)
|
||||||
{
|
{
|
||||||
logerror("%02d ", sec_number);
|
if (TRACE_DETAIL) logerror("%02d ", sec_number);
|
||||||
// Sync gap
|
// Sync gap
|
||||||
mfm_encode(slot, position, 0x00, 13);
|
mfm_encode(slot, position, 0x00, 13);
|
||||||
|
|
||||||
@ -655,15 +740,18 @@ chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinde
|
|||||||
sec_number += delta;
|
sec_number += delta;
|
||||||
if (sec_number >= sectorcount) sec_number = ++sec_il_start;
|
if (sec_number >= sectorcount) sec_number = ++sec_il_start;
|
||||||
}
|
}
|
||||||
|
if (TRACE_DETAIL) logerror("\n");
|
||||||
|
|
||||||
// Gap 4
|
// Gap 4
|
||||||
if (state == CHDERR_NONE)
|
if (state == CHDERR_NONE)
|
||||||
{
|
{
|
||||||
// Fill the rest with 0x4e
|
// Fill the rest with 0x4e
|
||||||
mfm_encode(slot, position, 0x4e, TRACKIMAGE_SIZE-position);
|
mfm_encode(slot, position, 0x4e, TRACKIMAGE_SIZE-position);
|
||||||
logerror("\n");
|
if (TRACE_DETAIL)
|
||||||
|
{
|
||||||
showtrack(slot->encdata, TRACKIMAGE_SIZE);
|
showtrack(slot->encdata, TRACKIMAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
slot->dirty = false;
|
slot->dirty = false;
|
||||||
slot->cylinder = cylinder;
|
slot->cylinder = cylinder;
|
||||||
@ -677,7 +765,7 @@ chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinde
|
|||||||
*/
|
*/
|
||||||
void mfmhd_trackimage_cache::write_back(mfmhd_trackimage* slot)
|
void mfmhd_trackimage_cache::write_back(mfmhd_trackimage* slot)
|
||||||
{
|
{
|
||||||
logerror("%s: MFM HD cache: write back cylinder=%d head=%d to CHD\n", tag(), slot->cylinder, slot->head);
|
if (TRACE_RWTRACK) logerror("%s: MFM HD cache: write back (c=%d,h=%d) to CHD\n", tag(), slot->cylinder, slot->head);
|
||||||
slot->dirty = false;
|
slot->dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,11 +803,22 @@ mfm_harddisk_device* mfm_harddisk_connector::get_device()
|
|||||||
return dynamic_cast<mfm_harddisk_device *>(get_card_device());
|
return dynamic_cast<mfm_harddisk_device *>(get_card_device());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mfm_harddisk_connector::configure(mfmhd_enc_t encoding, int spinupms, int cache)
|
||||||
|
{
|
||||||
|
m_encoding = encoding;
|
||||||
|
m_spinupms = spinupms;
|
||||||
|
m_cachesize = cache;
|
||||||
|
}
|
||||||
|
|
||||||
void mfm_harddisk_connector::device_config_complete()
|
void mfm_harddisk_connector::device_config_complete()
|
||||||
{
|
{
|
||||||
mfm_harddisk_device *dev = get_device();
|
mfm_harddisk_device *dev = get_device();
|
||||||
if (dev != NULL)
|
if (dev != NULL)
|
||||||
|
{
|
||||||
dev->set_encoding(m_encoding);
|
dev->set_encoding(m_encoding);
|
||||||
|
dev->set_spinup_time(m_spinupms);
|
||||||
|
dev->set_cache_size(m_cachesize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const device_type MFM_HD_CONNECTOR = &device_creator<mfm_harddisk_connector>;
|
const device_type MFM_HD_CONNECTOR = &device_creator<mfm_harddisk_connector>;
|
||||||
@ -732,6 +831,17 @@ const device_type MFM_HD_CONNECTOR = &device_creator<mfm_harddisk_connector>;
|
|||||||
|
|
||||||
#include "smc92x4.h"
|
#include "smc92x4.h"
|
||||||
|
|
||||||
|
#define TI99HD_BLOCKNOTFOUND -1
|
||||||
|
|
||||||
|
#define LOG logerror
|
||||||
|
#define VERBOSE 0
|
||||||
|
|
||||||
|
#define GAP1 16
|
||||||
|
#define GAP2 8
|
||||||
|
#define GAP3 15
|
||||||
|
#define GAP4 340
|
||||||
|
#define SYNC 13
|
||||||
|
|
||||||
mfm_harddisk_legacy_device::mfm_harddisk_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
mfm_harddisk_legacy_device::mfm_harddisk_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||||
: device_t(mconfig, TI99_MFMHD_LEG, "MFM Harddisk LEGACY", tag, owner, clock, "mfm_harddisk_leg", __FILE__)
|
: device_t(mconfig, TI99_MFMHD_LEG, "MFM Harddisk LEGACY", tag, owner, clock, "mfm_harddisk_leg", __FILE__)
|
||||||
{
|
{
|
||||||
|
@ -44,7 +44,7 @@ class mfmhd_trackimage_cache
|
|||||||
public:
|
public:
|
||||||
mfmhd_trackimage_cache();
|
mfmhd_trackimage_cache();
|
||||||
~mfmhd_trackimage_cache();
|
~mfmhd_trackimage_cache();
|
||||||
void init(chd_file* chdfile, const char* tag, int trackslots, mfmhd_enc_t encoding);
|
void init(chd_file* chdfile, const char* tag, int maxcyl, int maxhead, int trackslots, mfmhd_enc_t encoding);
|
||||||
UINT16* get_trackimage(int cylinder, int head);
|
UINT16* get_trackimage(int cylinder, int head);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -84,7 +84,11 @@ public:
|
|||||||
void setup_ready_cb(ready_cb cb);
|
void setup_ready_cb(ready_cb cb);
|
||||||
void setup_seek_complete_cb(seek_complete_cb cb);
|
void setup_seek_complete_cb(seek_complete_cb cb);
|
||||||
|
|
||||||
|
// Configuration
|
||||||
void set_encoding(mfmhd_enc_t encoding) { m_encoding = encoding; }
|
void set_encoding(mfmhd_enc_t encoding) { m_encoding = encoding; }
|
||||||
|
void set_spinup_time(int spinupms) { m_spinupms = spinupms; }
|
||||||
|
void set_cache_size(int tracks) { m_cachelines = tracks; }
|
||||||
|
|
||||||
mfmhd_enc_t get_encoding() { return m_encoding; }
|
mfmhd_enc_t get_encoding() { return m_encoding; }
|
||||||
|
|
||||||
// Active low lines. We're using ASSERT=0 / CLEAR=1
|
// Active low lines. We're using ASSERT=0 / CLEAR=1
|
||||||
@ -113,13 +117,21 @@ protected:
|
|||||||
void device_reset();
|
void device_reset();
|
||||||
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||||
|
|
||||||
|
virtual void setup_characteristics() = 0;
|
||||||
|
std::string tts(const attotime &t);
|
||||||
|
|
||||||
emu_timer *m_index_timer, *m_spinup_timer, *m_seek_timer;
|
emu_timer *m_index_timer, *m_spinup_timer, *m_seek_timer;
|
||||||
index_pulse_cb m_index_pulse_cb;
|
index_pulse_cb m_index_pulse_cb;
|
||||||
ready_cb m_ready_cb;
|
ready_cb m_ready_cb;
|
||||||
seek_complete_cb m_seek_complete_cb;
|
seek_complete_cb m_seek_complete_cb;
|
||||||
|
|
||||||
|
int m_max_cylinder;
|
||||||
|
int m_max_heads;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mfmhd_enc_t m_encoding;
|
mfmhd_enc_t m_encoding;
|
||||||
|
int m_spinupms;
|
||||||
|
int m_cachelines;
|
||||||
bool m_ready;
|
bool m_ready;
|
||||||
int m_current_cylinder;
|
int m_current_cylinder;
|
||||||
int m_current_head;
|
int m_current_head;
|
||||||
@ -129,6 +141,7 @@ private:
|
|||||||
bool m_seek_inward;
|
bool m_seek_inward;
|
||||||
//bool m_seeking;
|
//bool m_seeking;
|
||||||
bool m_autotruncation;
|
bool m_autotruncation;
|
||||||
|
bool m_recalibrated;
|
||||||
line_state m_step_line; // keep the last state
|
line_state m_step_line; // keep the last state
|
||||||
|
|
||||||
attotime m_spinup_time;
|
attotime m_spinup_time;
|
||||||
@ -139,15 +152,30 @@ private:
|
|||||||
|
|
||||||
void prepare_track(int cylinder, int head);
|
void prepare_track(int cylinder, int head);
|
||||||
void head_move();
|
void head_move();
|
||||||
|
void recalibrate();
|
||||||
};
|
};
|
||||||
|
|
||||||
class mfm_hd_generic_device : public mfm_harddisk_device
|
class mfm_hd_generic_device : public mfm_harddisk_device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
mfm_hd_generic_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
mfm_hd_generic_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setup_characteristics();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const device_type MFM_HD_GENERIC;
|
extern const device_type MFMHD_GENERIC;
|
||||||
|
|
||||||
|
class mfm_hd_st225_device : public mfm_harddisk_device
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
mfm_hd_st225_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setup_characteristics();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const device_type MFMHD_ST225;
|
||||||
|
|
||||||
/* Connector for a MFM hard disk. See also floppy.c */
|
/* Connector for a MFM hard disk. See also floppy.c */
|
||||||
class mfm_harddisk_connector : public device_t,
|
class mfm_harddisk_connector : public device_t,
|
||||||
@ -159,7 +187,7 @@ public:
|
|||||||
|
|
||||||
mfm_harddisk_device *get_device();
|
mfm_harddisk_device *get_device();
|
||||||
|
|
||||||
void set_encoding(mfmhd_enc_t encoding) { m_encoding = encoding; }
|
void configure(mfmhd_enc_t encoding, int spinupms, int cache);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void device_start() { };
|
void device_start() { };
|
||||||
@ -167,14 +195,28 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
mfmhd_enc_t m_encoding;
|
mfmhd_enc_t m_encoding;
|
||||||
|
int m_spinupms;
|
||||||
|
int m_cachesize;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const device_type MFM_HD_CONNECTOR;
|
extern const device_type MFM_HD_CONNECTOR;
|
||||||
|
|
||||||
#define MCFG_MFM_HARDDISK_ADD(_tag, _slot_intf, _def_slot, _enc) \
|
/*
|
||||||
|
Add a harddisk connector.
|
||||||
|
Parameters:
|
||||||
|
_tag = Tag of the connector
|
||||||
|
_slot_intf = Selection of hard drives
|
||||||
|
_def_slot = Default hard drive
|
||||||
|
_enc = Encoding (see comments in ti99_hd.c)
|
||||||
|
_spinupms = Spinup time in milliseconds (some configurations assume that the
|
||||||
|
user has turned on the hard disk before turning on the system. We cannot
|
||||||
|
emulate this, so we allow for shorter times)
|
||||||
|
_cache = number of cached MFM tracks
|
||||||
|
*/
|
||||||
|
#define MCFG_MFM_HARDDISK_CONN_ADD(_tag, _slot_intf, _def_slot, _enc, _spinupms, _cache) \
|
||||||
MCFG_DEVICE_ADD(_tag, MFM_HD_CONNECTOR, 0) \
|
MCFG_DEVICE_ADD(_tag, MFM_HD_CONNECTOR, 0) \
|
||||||
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \
|
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \
|
||||||
static_cast<mfm_harddisk_connector *>(device)->set_encoding(_enc);
|
static_cast<mfm_harddisk_connector *>(device)->configure(_enc, _spinupms, _cache);
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// Legacy implementation
|
// Legacy implementation
|
||||||
|
Loading…
Reference in New Issue
Block a user