diff options
author | 2015-06-07 17:50:19 +0200 | |
---|---|---|
committer | 2015-06-07 17:52:23 +0200 | |
commit | 05a79d2e2011ec9efe711019b796634ef8d0cfb0 (patch) | |
tree | f8724457e80dc7d1b35b579b83394e5aff6fcbe6 | |
parent | b6ce8ee991c7e14ca214a2931bfbc4e4a5a0dc0f (diff) |
MFM hard disk WIP; adding config options
-rw-r--r-- | src/emu/bus/ti99_peb/hfdc.c | 16 | ||||
-rw-r--r-- | src/emu/machine/hdc9234.c | 35 | ||||
-rw-r--r-- | src/emu/machine/ti99_hd.c | 238 | ||||
-rw-r--r-- | src/emu/machine/ti99_hd.h | 52 |
4 files changed, 257 insertions, 84 deletions
diff --git a/src/emu/bus/ti99_peb/hfdc.c b/src/emu/bus/ti99_peb/hfdc.c index 0e3c77190f4..5d4f84795d1 100644 --- a/src/emu/bus/ti99_peb/hfdc.c +++ b/src/emu/bus/ti99_peb/hfdc.c @@ -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) { - /* 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)); 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) { - /* 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)); 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) { - /* 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)); signal_drive_status(); } @@ -1005,8 +1005,8 @@ static SLOT_INTERFACE_START( hfdc_floppies ) SLOT_INTERFACE_END static SLOT_INTERFACE_START( hfdc_harddisks ) - SLOT_INTERFACE( "generic", MFM_HD_GENERIC ) // Generic high-level emulation -// SLOT_INTERFACE( "seagatemfm", MFM_HD_SEAGATE ) // Seagate ST-225 and others + SLOT_INTERFACE( "generic", MFMHD_GENERIC ) // Generic high-level emulation + SLOT_INTERFACE( "st225", MFMHD_ST225 ) // Seagate ST-225 and others SLOT_INTERFACE_END 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) // 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_ADD("h2", hfdc_harddisks, NULL, MFM_BYTE) - MCFG_MFM_HARDDISK_ADD("h3", hfdc_harddisks, NULL, MFM_BYTE) + MCFG_MFM_HARDDISK_CONN_ADD("h1", hfdc_harddisks, NULL, MFM_BYTE, 3000, 20) + MCFG_MFM_HARDDISK_CONN_ADD("h2", hfdc_harddisks, NULL, MFM_BYTE, 2000, 20) + MCFG_MFM_HARDDISK_CONN_ADD("h3", hfdc_harddisks, NULL, MFM_BYTE, 2000, 20) MCFG_DEVICE_ADD(CLOCK_TAG, MM58274C, 0) MCFG_MM58274C_MODE24(1) // 24 hour diff --git a/src/emu/machine/hdc9234.c b/src/emu/machine/hdc9234.c index 183d1af2aaf..91c41fc21d6 100644 --- a/src/emu/machine/hdc9234.c +++ b/src/emu/machine/hdc9234.c @@ -607,19 +607,19 @@ void hdc9234_device::wait_line(int line, line_state level, int substate, bool st bool line_at_level = true; 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 { 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 { 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 { @@ -2724,7 +2724,7 @@ void hdc9234_device::live_run_until(attotime limit) void hdc9234_device::live_run_hd_until(attotime limit) { 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) return; @@ -2745,6 +2745,12 @@ void hdc9234_device::live_run_hd_until(attotime limit) switch (m_live_state.state) { 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 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()); 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 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: 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 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; + // 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); 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; - 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) { @@ -2856,6 +2871,8 @@ void hdc9234_device::live_run_hd_until(attotime limit) case READ_DATADEL_FLAG: if (read_from_mfmhd(limit)) return; + if (m_live_state.bit_counter & 15) break; + 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()); @@ -2897,6 +2914,9 @@ void hdc9234_device::live_run_hd_until(attotime limit) 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; 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.next_state = -1; checkpoint(); } @@ -3790,7 +3811,7 @@ void hdc9234_device::connect_hard_drive(mfm_harddisk_device* harddisk) { m_harddisk = harddisk; 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); } /* diff --git a/src/emu/machine/ti99_hd.c b/src/emu/machine/ti99_hd.c index 5ad8fc1a535..49aeb5b69d1 100644 --- a/src/emu/machine/ti99_hd.c +++ b/src/emu/machine/ti99_hd.c @@ -14,22 +14,21 @@ **************************************************************************/ +// TODO: Format + #include "emu.h" #include "formats/imageutl.h" #include "harddisk.h" #include "ti99_hd.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 +#define TRACE_STEPS 0 +#define TRACE_SIGNALS 0 +#define TRACE_READ 0 +#define TRACE_CACHE 0 +#define TRACE_RWTRACK 0 +#define TRACE_BITS 0 +#define TRACE_DETAIL 0 enum { @@ -48,10 +47,20 @@ enum #define TRACKSLOTS 5 #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) : harddisk_image_device(mconfig, type, name, tag, owner, clock, shortname, source), device_slot_card_interface(mconfig, *this) { + m_spinupms = 10000; + m_cachelines = TRACKSLOTS; } mfm_harddisk_device::~mfm_harddisk_device() @@ -63,16 +72,13 @@ void mfm_harddisk_device::device_start() m_index_timer = timer_alloc(INDEX_TM); m_spinup_timer = timer_alloc(SPINUP_TM); m_seek_timer = timer_alloc(SEEK_TM); - m_spinup_time = attotime::from_msec(8000); m_rev_time = attotime::from_hz(60); // 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)); - // Spinup may take up to 24 seconds - m_spinup_timer->adjust(m_spinup_time); - - m_current_cylinder = 10; // for test purpose + m_current_cylinder = 615; // Park position + m_spinup_timer->adjust(attotime::from_msec(m_spinupms)); m_cache = global_alloc(mfmhd_trackimage_cache); } @@ -85,6 +91,7 @@ void mfm_harddisk_device::device_reset() m_seek_inward = false; m_track_delta = 0; m_step_line = CLEAR_LINE; + m_recalibrated = false; } void mfm_harddisk_device::device_stop() @@ -94,15 +101,15 @@ void mfm_harddisk_device::device_stop() bool mfm_harddisk_device::call_load() { - logerror("call_load\n"); + setup_characteristics(); bool loaded = harddisk_image_device::call_load(); 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 { - logerror("Could not load CHD\n"); + logerror("%s: Could not load CHD\n", tag()); } 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 // index pulse to appear earlier (because of rounding effects) attotime nexttime = m_rev_time - attotime::from_nsec(2000); + attotime endtime = attotime::never; + if (!m_ready) { // estimate the next index time; during power-up we assume half the rotational speed // Should never be relevant, though, because READY is false. 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) @@ -142,18 +157,18 @@ void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int { case INDEX_TM: /* 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()) { - m_revolution_start_time = machine().time(); m_index_pulse_cb(this, ASSERT_LINE); m_index_pulse_cb(this, CLEAR_LINE); } break; + case SPINUP_TM: - m_ready = true; - logerror("%s: Spinup complete, drive is ready\n", tag()); - if (!m_ready_cb.isnull()) m_ready_cb(this, ASSERT_LINE); + recalibrate(); break; + case SEEK_TM: 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 m_step_phase = STEP_SETTLE; 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; case STEP_SETTLE: @@ -178,7 +193,17 @@ void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int else { // 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; if (!m_seek_complete_cb.isnull()) m_seek_complete_cb(this, ASSERT_LINE); 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() { int steps = m_track_delta; 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; 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) { 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) 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) { - 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_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"); } + // 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. // Each cell takes 100 ns (10 MHz) 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; - int position = cell / 16; + + int bytepos = cell / 16; // 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; cell = (from_when - m_revolution_start_time).as_ticks(10000000); - position = cell / 16; + bytepos = cell / 16; } - // TODO: fix the actual issue - if (position < 0) position = 0; - - logerror("%s: Reading track %d head %d at position %d\n", tag(), m_current_cylinder, m_current_head, position); - cdata = track[position]; + 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(fw).c_str()); + bytepos = 0; + } + 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; } 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 @@ -345,12 +421,12 @@ mfmhd_trackimage_cache::mfmhd_trackimage_cache(): mfmhd_trackimage_cache::~mfmhd_trackimage_cache() { 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? 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); global_free_array(current->encdata); mfmhd_trackimage* currenttmp = current->next; @@ -362,12 +438,12 @@ mfmhd_trackimage_cache::~mfmhd_trackimage_cache() /* 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_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; mfmhd_trackimage* previous = 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"); } + if (maxcyl != 0 && m_cylinders > maxcyl) + { + 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 - for (int i=0; i < trackslots; i++) + int track = 0; + int head = 0; + int cylinder = 0; + while (track < trackslots) { - logerror("%s: MFM HD allocate cache slot\n", tag()); + if (TRACE_CACHE && TRACE_DETAIL) logerror("%s: MFM HD allocate cache slot\n", tag()); previous = current; current = global_alloc(mfmhd_trackimage); current->encdata = global_alloc_array(UINT16, TRACKIMAGE_SIZE); // Load the first tracks into the slots - state = load_track(current, i, 0, 32, 256, 4); - current->next = NULL; + state = load_track(current, cylinder, head, 32, 256, 4); + + if (state != CHDERR_NONE) throw emu_fatalerror("Cannot load (c=%d,h=%d) from hard disk", cylinder, head); - if (state != CHDERR_NONE) throw emu_fatalerror("Cannot load cylinder %d head %d from hard disk", i, 0); + // 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) previous->next = current; else // Head m_tracks = current; - } - - current = m_tracks; - 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; + // Count the number of loaded tracks + track++; } } @@ -491,7 +576,7 @@ UINT16* mfmhd_trackimage_cache::get_trackimage(int cylinder, int head) // previous points to the second to last element 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); 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]; - 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; 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 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++) { - logerror("%02d ", sec_number); + if (TRACE_DETAIL) logerror("%02d ", sec_number); // Sync gap mfm_encode(slot, position, 0x00, 13); @@ -655,14 +740,17 @@ chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinde sec_number += delta; if (sec_number >= sectorcount) sec_number = ++sec_il_start; } + if (TRACE_DETAIL) logerror("\n"); // Gap 4 if (state == CHDERR_NONE) { // Fill the rest with 0x4e mfm_encode(slot, position, 0x4e, TRACKIMAGE_SIZE-position); - logerror("\n"); - showtrack(slot->encdata, TRACKIMAGE_SIZE); + if (TRACE_DETAIL) + { + showtrack(slot->encdata, TRACKIMAGE_SIZE); + } } slot->dirty = false; @@ -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) { - 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; } @@ -715,11 +803,22 @@ mfm_harddisk_device* mfm_harddisk_connector::get_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() { mfm_harddisk_device *dev = get_device(); if (dev != NULL) + { 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>; @@ -732,6 +831,17 @@ const device_type MFM_HD_CONNECTOR = &device_creator<mfm_harddisk_connector>; #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) : device_t(mconfig, TI99_MFMHD_LEG, "MFM Harddisk LEGACY", tag, owner, clock, "mfm_harddisk_leg", __FILE__) { diff --git a/src/emu/machine/ti99_hd.h b/src/emu/machine/ti99_hd.h index 87de506398f..02f5d4fb4e5 100644 --- a/src/emu/machine/ti99_hd.h +++ b/src/emu/machine/ti99_hd.h @@ -44,7 +44,7 @@ class mfmhd_trackimage_cache public: 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); private: @@ -84,7 +84,11 @@ public: void setup_ready_cb(ready_cb cb); void setup_seek_complete_cb(seek_complete_cb cb); + // Configuration 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; } // Active low lines. We're using ASSERT=0 / CLEAR=1 @@ -113,13 +117,21 @@ protected: void device_reset(); 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; index_pulse_cb m_index_pulse_cb; ready_cb m_ready_cb; seek_complete_cb m_seek_complete_cb; + int m_max_cylinder; + int m_max_heads; + private: mfmhd_enc_t m_encoding; + int m_spinupms; + int m_cachelines; bool m_ready; int m_current_cylinder; int m_current_head; @@ -129,6 +141,7 @@ private: bool m_seek_inward; //bool m_seeking; bool m_autotruncation; + bool m_recalibrated; line_state m_step_line; // keep the last state attotime m_spinup_time; @@ -139,15 +152,30 @@ private: void prepare_track(int cylinder, int head); void head_move(); + void recalibrate(); }; class mfm_hd_generic_device : public mfm_harddisk_device { public: 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 */ class mfm_harddisk_connector : public device_t, @@ -159,7 +187,7 @@ public: 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: void device_start() { }; @@ -167,14 +195,28 @@ protected: private: mfmhd_enc_t m_encoding; + int m_spinupms; + int m_cachesize; }; 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_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 |