diff options
Diffstat (limited to 'src/devices/imagedev/mfmhd.cpp')
-rw-r--r-- | src/devices/imagedev/mfmhd.cpp | 464 |
1 files changed, 234 insertions, 230 deletions
diff --git a/src/devices/imagedev/mfmhd.cpp b/src/devices/imagedev/mfmhd.cpp index 1d6d3574c07..ecb886676a0 100644 --- a/src/devices/imagedev/mfmhd.cpp +++ b/src/devices/imagedev/mfmhd.cpp @@ -270,24 +270,29 @@ **************************************************************************/ #include "emu.h" -#include "harddisk.h" +#include "romload.h" #include "mfmhd.h" +#include "util/ioprocs.h" +#include "util/ioprocsfilter.h" -#define TRACE_STEPS 0 -#define TRACE_SIGNALS 0 -#define TRACE_READ 0 -#define TRACE_WRITE 0 -#define TRACE_CACHE 0 -#define TRACE_BITS 0 -#define TRACE_DETAIL 0 -#define TRACE_TIMING 0 -#define TRACE_STATE 1 -#define TRACE_CONFIG 1 +#define LOG_WARN (1U << 1) // Warnings +#define LOG_CONFIG (1U << 2) // Configuration +#define LOG_STEPS (1U << 3) // Steps +#define LOG_STEPSDETAIL (1U << 4) // Steps, more detail +#define LOG_SIGNALS (1U << 5) // Signals +#define LOG_READ (1U << 6) // Read operations +#define LOG_WRITE (1U << 7) // Write operations +#define LOG_BITS (1U << 8) // Bit transfer +#define LOG_TIMING (1U << 9) // Timing + + +#define VERBOSE (LOG_GENERAL | LOG_CONFIG | LOG_WARN) + +#include "logmacro.h" enum { INDEX_TM = 0, - SPINUP_TM, SEEK_TM, CACHE_TM }; @@ -299,17 +304,9 @@ enum STEP_SETTLE }; -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 *tag, device_t *owner, uint32_t clock) - : harddisk_image_device(mconfig, type, tag, owner, clock), - device_slot_card_interface(mconfig, *this), + : device_t(mconfig, type, tag, owner, clock), + device_image_interface(mconfig, *this), m_index_timer(nullptr), m_spinup_timer(nullptr), m_seek_timer(nullptr), @@ -352,10 +349,10 @@ mfm_harddisk_device::~mfm_harddisk_device() 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_cache_timer = timer_alloc(CACHE_TM); + m_index_timer = timer_alloc(FUNC(mfm_harddisk_device::index_timer), this); + m_spinup_timer = timer_alloc(FUNC(mfm_harddisk_device::recalibrate), this); + m_seek_timer = timer_alloc(FUNC(mfm_harddisk_device::seek_update), this); + m_cache_timer = timer_alloc(FUNC(mfm_harddisk_device::cache_update), this); m_rev_time = attotime::from_hz(m_rpm/60); m_index_timer->adjust(attotime::from_hz(m_rpm/60), 0, attotime::from_hz(m_rpm/60)); @@ -363,7 +360,7 @@ void mfm_harddisk_device::device_start() m_current_cylinder = m_landing_zone; // Park position m_spinup_timer->adjust(attotime::from_msec(m_spinupms)); - m_cache = global_alloc(mfmhd_trackimage_cache(machine())); + m_cache = std::make_unique<mfmhd_trackimage_cache>(machine()); // In 5 second periods, check whether the cache has dirty lines m_cache_timer->adjust(attotime::from_msec(5000), 0, attotime::from_msec(5000)); @@ -408,7 +405,7 @@ void mfm_harddisk_device::device_reset() void mfm_harddisk_device::device_stop() { - if (m_cache!=nullptr) global_free(m_cache); + m_cache.reset(); } /* @@ -416,129 +413,135 @@ void mfm_harddisk_device::device_stop() because we need the number of cylinders, and for generic drives we get them from the CHD. */ -image_init_result mfm_harddisk_device::call_load() +std::pair<std::error_condition, std::string> mfm_harddisk_device::call_load() { - image_init_result loaded = harddisk_image_device::call_load(); + std::error_condition err; + + /* open the CHD file */ + if (loaded_through_softlist()) + { + m_chd = machine().rom_load().get_disk_handle(device().subtag("harddriv").c_str()); + } + else + { + auto io = util::random_read_write_fill(image_core_file(), 0xff); + if (!io) + return std::make_pair(std::errc::not_enough_memory, std::string()); + + m_chd = new chd_file; // FIXME: this is never deleted + err = m_chd->open(std::move(io), true); + } std::string devtag(tag()); devtag += ":format"; m_format->set_tag(devtag); - if (loaded==image_init_result::PASS) + if (err) { - std::string metadata; - chd_file* chdfile = get_chd_file(); + LOGMASKED(LOG_WARN, "Could not load CHD\n"); + return std::make_pair(err, std::string()); + } - if (chdfile==nullptr) - { - logerror("chdfile is null\n"); - return image_init_result::FAIL; - } + if (!m_chd) + { + LOG("m_chd is null\n"); + return std::make_pair(image_error::UNSPECIFIED, std::string()); + } - // Read the hard disk metadata - chd_error state = chdfile->read_metadata(HARD_DISK_METADATA_TAG, 0, metadata); - if (state != CHDERR_NONE) - { - logerror("Failed to read CHD metadata\n"); - return image_init_result::FAIL; - } + // Read the hard disk metadata + std::string metadata; + std::error_condition state = m_chd->read_metadata(HARD_DISK_METADATA_TAG, 0, metadata); + if (state) + return std::make_pair(state, "Failed to read CHD metadata"); - if (TRACE_CONFIG) logerror("CHD metadata: %s\n", metadata.c_str()); + LOGMASKED(LOG_CONFIG, "CHD metadata: %s\n", metadata.c_str()); - // Parse the metadata - mfmhd_layout_params param; - param.encoding = m_encoding; - if (TRACE_CONFIG) logerror("Set encoding to %d\n", m_encoding); + // Parse the metadata + mfmhd_layout_params param; + param.encoding = m_encoding; + LOGMASKED(LOG_CONFIG, "Set encoding to %d\n", m_encoding); - if (sscanf(metadata.c_str(), HARD_DISK_METADATA_FORMAT, ¶m.cylinders, ¶m.heads, ¶m.sectors_per_track, ¶m.sector_size) != 4) - { - logerror("Invalid CHD metadata\n"); - return image_init_result::FAIL; - } + if (sscanf(metadata.c_str(), HARD_DISK_METADATA_FORMAT, ¶m.cylinders, ¶m.heads, ¶m.sectors_per_track, ¶m.sector_size) != 4) + return std::make_pair(image_error::INVALIDIMAGE, "Invalid CHD metadata"); - if (TRACE_CONFIG) logerror("CHD image has geometry cyl=%d, head=%d, sect=%d, size=%d\n", param.cylinders, param.heads, param.sectors_per_track, param.sector_size); + LOGMASKED(LOG_CONFIG, "CHD image has geometry cyl=%d, head=%d, sect=%d, size=%d\n", param.cylinders, param.heads, param.sectors_per_track, param.sector_size); - if (m_max_cylinders != 0 && (param.cylinders != m_max_cylinders || param.heads != m_max_heads)) - { - throw emu_fatalerror("Image geometry does not fit this kind of hard drive: drive=(%d,%d), image=(%d,%d)", m_max_cylinders, m_max_heads, param.cylinders, param.heads); - } + if (m_max_cylinders != 0 && (param.cylinders != m_max_cylinders || param.heads != m_max_heads)) + { + // TODO: does this really need to be a fatal error? + throw emu_fatalerror("Image geometry does not fit this kind of hard drive: drive=(%d,%d), image=(%d,%d)", m_max_cylinders, m_max_heads, param.cylinders, param.heads); + } - // MDM format specs - param.interleave = 0; - param.cylskew = 0; - param.headskew = 0; - param.write_precomp_cylinder = -1; - param.reduced_wcurr_cylinder = -1; + // MDM format specs + param.interleave = 0; + param.cylskew = 0; + param.headskew = 0; + param.write_precomp_cylinder = -1; + param.reduced_wcurr_cylinder = -1; - state = chdfile->read_metadata(MFM_HARD_DISK_METADATA_TAG, 0, metadata); - if (state != CHDERR_NONE) - { - logerror("Failed to read CHD sector arrangement/recording specs, applying defaults\n"); - } - else - { - sscanf(metadata.c_str(), MFMHD_REC_METADATA_FORMAT, ¶m.interleave, ¶m.cylskew, ¶m.headskew, ¶m.write_precomp_cylinder, ¶m.reduced_wcurr_cylinder); - } + state = m_chd->read_metadata(MFM_HARD_DISK_METADATA_TAG, 0, metadata); + if (state) + LOGMASKED(LOG_WARN, "Failed to read CHD sector arrangement/recording specs, applying defaults\n"); + else + sscanf(metadata.c_str(), MFMHD_REC_METADATA_FORMAT, ¶m.interleave, ¶m.cylskew, ¶m.headskew, ¶m.write_precomp_cylinder, ¶m.reduced_wcurr_cylinder); - if (!param.sane_rec()) - { - if (TRACE_CONFIG) logerror("Sector arrangement/recording specs have invalid values, applying defaults\n"); - param.reset_rec(); - } - else - if (TRACE_CONFIG) logerror("MFM HD rec specs: interleave=%d, cylskew=%d, headskew=%d, wpcom=%d, rwc=%d\n", + if (!param.sane_rec()) + { + LOGMASKED(LOG_CONFIG, "Sector arrangement/recording specs have invalid values, applying defaults\n"); + param.reset_rec(); + } + else + { + LOGMASKED(LOG_CONFIG, + "MFM HD rec specs: interleave=%d, cylskew=%d, headskew=%d, wpcom=%d, rwc=%d\n", param.interleave, param.cylskew, param.headskew, param.write_precomp_cylinder, param.reduced_wcurr_cylinder); + } - state = chdfile->read_metadata(MFM_HARD_DISK_METADATA_TAG, 1, metadata); - if (state != CHDERR_NONE) - { - logerror("Failed to read CHD track gap specs, applying defaults\n"); - } - else - { - sscanf(metadata.c_str(), MFMHD_GAP_METADATA_FORMAT, ¶m.gap1, ¶m.gap2, ¶m.gap3, ¶m.sync, ¶m.headerlen, ¶m.ecctype); - } + state = m_chd->read_metadata(MFM_HARD_DISK_METADATA_TAG, 1, metadata); + if (state) + LOGMASKED(LOG_WARN, "Failed to read CHD track gap specs, applying defaults\n"); + else + sscanf(metadata.c_str(), MFMHD_GAP_METADATA_FORMAT, ¶m.gap1, ¶m.gap2, ¶m.gap3, ¶m.sync, ¶m.headerlen, ¶m.ecctype); - if (!param.sane_gap()) - { - if (TRACE_CONFIG) logerror("MFM HD gap specs have invalid values, applying defaults\n"); - param.reset_gap(); - } - else - if (TRACE_CONFIG) logerror("MFM HD gap specs: gap1=%d, gap2=%d, gap3=%d, sync=%d, headerlen=%d, ecctype=%d\n", + if (!param.sane_gap()) + { + LOGMASKED(LOG_CONFIG, "MFM HD gap specs have invalid values, applying defaults\n"); + param.reset_gap(); + } + else + { + LOGMASKED(LOG_CONFIG, + "MFM HD gap specs: gap1=%d, gap2=%d, gap3=%d, sync=%d, headerlen=%d, ecctype=%d\n", param.gap1, param.gap2, param.gap3, param.sync, param.headerlen, param.ecctype); + } - m_format->set_layout_params(param); + m_format->set_layout_params(param); - m_cache->init(this, m_trackimage_size, m_cachelines); + m_cache->init(this, m_trackimage_size, m_cachelines); - // Head timing - // We assume that the real times are 80% of the max times - // The single-step time includes the settle time, so does the max time - // From that we calculate the actual cylinder-by-cylinder time and the settle time + // Head timing + // We assume that the real times are 80% of the max times + // The single-step time includes the settle time, so does the max time + // From that we calculate the actual cylinder-by-cylinder time and the settle time - m_actual_cylinders = param.cylinders; + m_actual_cylinders = param.cylinders; - if (m_phys_cylinders == 0) m_phys_cylinders = m_actual_cylinders+1; - if (m_landing_zone == 0) m_landing_zone = m_phys_cylinders-1; + if (m_phys_cylinders == 0) m_phys_cylinders = m_actual_cylinders+1; + if (m_landing_zone == 0) m_landing_zone = m_phys_cylinders-1; - float realnext = (m_seeknext_time==0)? 10 : (m_seeknext_time * 0.8); - float realmax = (m_maxseek_time==0)? (m_actual_cylinders * 0.2) : (m_maxseek_time * 0.8); - float settle_us = ((m_actual_cylinders-1.0) * realnext - realmax) / (m_actual_cylinders-2.0) * 1000; - float step_us = realnext * 1000 - settle_us; - if (TRACE_CONFIG) logerror("Calculated settle time: %0.2f ms, step: %d us\n", settle_us/1000, (int)step_us); + float realnext = (m_seeknext_time==0)? 10 : (m_seeknext_time * 0.8); + float realmax = (m_maxseek_time==0)? (m_actual_cylinders * 0.2) : (m_maxseek_time * 0.8); + float settle_us = ((m_actual_cylinders-1.0) * realnext - realmax) / (m_actual_cylinders-2.0) * 1000; + float step_us = realnext * 1000 - settle_us; + LOGMASKED(LOG_CONFIG, "Calculated settle time: %0.2f ms, step: %d us\n", settle_us/1000, (int)step_us); - m_settle_time = attotime::from_usec((int)settle_us); - m_step_time = attotime::from_usec((int)step_us); + m_settle_time = attotime::from_usec((int)settle_us); + m_step_time = attotime::from_usec((int)step_us); - m_current_cylinder = m_landing_zone; - } - else - { - logerror("Could not load CHD\n"); - } - return loaded; + m_current_cylinder = m_landing_zone; + + return std::make_pair(std::error_condition(), std::string()); } const char *MFMHD_REC_METADATA_FORMAT = "IL:%d,CSKEW:%d,HSKEW:%d,WPCOM:%d,RWC:%d"; @@ -555,29 +558,26 @@ void mfm_harddisk_device::call_unload() if (m_format->save_param(MFMHD_IL) && !params->equals_rec(oldparams)) { - logerror("MFM HD sector arrangement and recording specs have changed; updating CHD metadata\n"); - chd_file* chdfile = get_chd_file(); - - chd_error err = chdfile->write_metadata(MFM_HARD_DISK_METADATA_TAG, 0, string_format(MFMHD_REC_METADATA_FORMAT, params->interleave, params->cylskew, params->headskew, params->write_precomp_cylinder, params->reduced_wcurr_cylinder), 0); - if (err != CHDERR_NONE) + LOGMASKED(LOG_WARN, "MFM HD sector arrangement and recording specs have changed; updating CHD metadata\n"); + std::error_condition err = m_chd->write_metadata(MFM_HARD_DISK_METADATA_TAG, 0, string_format(MFMHD_REC_METADATA_FORMAT, params->interleave, params->cylskew, params->headskew, params->write_precomp_cylinder, params->reduced_wcurr_cylinder), 0); + if (err) { - logerror("Failed to save MFM HD sector arrangement/recording specs to CHD\n"); + LOGMASKED(LOG_WARN, "Failed to save MFM HD sector arrangement/recording specs to CHD\n"); } } if (m_format->save_param(MFMHD_GAP1) && !params->equals_gap(oldparams)) { - logerror("MFM HD track gap specs have changed; updating CHD metadata\n"); - chd_file* chdfile = get_chd_file(); - - chd_error err = chdfile->write_metadata(MFM_HARD_DISK_METADATA_TAG, 1, string_format(MFMHD_GAP_METADATA_FORMAT, params->gap1, params->gap2, params->gap3, params->sync, params->headerlen, params->ecctype), 0); - if (err != CHDERR_NONE) + LOGMASKED(LOG_WARN, "MFM HD track gap specs have changed; updating CHD metadata\n"); + std::error_condition err = m_chd->write_metadata(MFM_HARD_DISK_METADATA_TAG, 1, string_format(MFMHD_GAP_METADATA_FORMAT, params->gap1, params->gap2, params->gap3, params->sync, params->headerlen, params->ecctype), 0); + if (err) { - logerror("Failed to save MFM HD track gap specs to CHD\n"); + LOGMASKED(LOG_WARN, "Failed to save MFM HD track gap specs to CHD\n"); } } } - harddisk_image_device::call_unload(); + + m_chd = nullptr; } void mfm_harddisk_device::setup_index_pulse_cb(index_pulse_cb cb) @@ -612,104 +612,99 @@ attotime mfm_harddisk_device::track_end_time() if (!m_revolution_start_time.is_never()) { endtime = m_revolution_start_time + nexttime; - if (TRACE_TIMING) logerror("Track start time = %s, end time = %s\n", tts(m_revolution_start_time).c_str(), tts(endtime).c_str()); + LOGMASKED(LOG_TIMING, "Track start time = %s, end time = %s\n", (m_revolution_start_time).to_string(), (endtime).to_string()); } return endtime; } -void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(mfm_harddisk_device::index_timer) { - switch (id) + // 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()) { - 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_index_pulse_cb(this, ASSERT_LINE); - m_index_pulse_cb(this, CLEAR_LINE); - } - break; + m_index_pulse_cb(this, ASSERT_LINE); + m_index_pulse_cb(this, CLEAR_LINE); + } +} - case SPINUP_TM: - recalibrate(); - break; +TIMER_CALLBACK_MEMBER(mfm_harddisk_device::recalibrate) +{ + LOGMASKED(LOG_STEPS, "Recalibrate to track 0\n"); + direction_in_w(CLEAR_LINE); + while (-m_track_delta < m_phys_cylinders) + { + step_w(ASSERT_LINE); + step_w(CLEAR_LINE); + } +} - case CACHE_TM: - m_cache->write_back_one(); +TIMER_CALLBACK_MEMBER(mfm_harddisk_device::seek_update) +{ + switch (m_step_phase) + { + case STEP_COLLECT: + // Collect timer has expired; start moving head + head_move(); break; - - case SEEK_TM: - switch (m_step_phase) + case STEP_MOVING: + // Head has reached final position + // Check whether we have a new delta + if (m_track_delta == 0) + { + // Start the settle timer + m_step_phase = STEP_SETTLE; + m_seek_timer->adjust(m_settle_time); + LOGMASKED(LOG_STEPSDETAIL, "Arrived at target cylinder %d, settling ...[%s]\n", m_current_cylinder, machine().time().to_string()); + } + else { - case STEP_COLLECT: - // Collect timer has expired; start moving head + // need to move the head again head_move(); - break; - case STEP_MOVING: - // Head has reached final position - // Check whether we have a new delta - if (m_track_delta == 0) - { - // Start the settle timer - m_step_phase = STEP_SETTLE; - m_seek_timer->adjust(m_settle_time); - if (TRACE_STEPS && TRACE_DETAIL) logerror("Arrived at target cylinder %d, settling ...\n", m_current_cylinder); - } - else + } + break; + case STEP_SETTLE: + // Do we have new step pulses? + if (m_track_delta != 0) head_move(); + else + { + // Seek completed + if (!m_recalibrated) { - // need to move the head again - head_move(); + m_ready = true; + m_recalibrated = true; + LOGMASKED(LOG_CONFIG, "Spinup complete, drive recalibrated and positioned at cylinder %d; drive is READY\n", m_current_cylinder); + if (!m_ready_cb.isnull()) m_ready_cb(this, ASSERT_LINE); } - break; - case STEP_SETTLE: - // Do we have new step pulses? - if (m_track_delta != 0) head_move(); else { - // Seek completed - if (!m_recalibrated) - { - m_ready = true; - m_recalibrated = true; - if (TRACE_STATE) logerror("Spinup complete, drive recalibrated and positioned at cylinder %d; drive is READY\n", m_current_cylinder); - if (!m_ready_cb.isnull()) m_ready_cb(this, ASSERT_LINE); - } - else - { - if (TRACE_SIGNALS) logerror("Settling done at cylinder %d, seek complete\n", 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; + LOGMASKED(LOG_STEPSDETAIL, "Settling done at cylinder %d, seek complete [%s]\n", m_current_cylinder, machine().time().to_string()); } - break; + m_seek_complete = true; + if (!m_seek_complete_cb.isnull()) m_seek_complete_cb(this, ASSERT_LINE); + m_step_phase = STEP_COLLECT; } + break; } } -void mfm_harddisk_device::recalibrate() +TIMER_CALLBACK_MEMBER(mfm_harddisk_device::cache_update) { - if (TRACE_STEPS) logerror("Recalibrate to track 0\n"); - direction_in_w(CLEAR_LINE); - while (-m_track_delta < m_phys_cylinders) - { - step_w(ASSERT_LINE); - step_w(CLEAR_LINE); - } + m_cache->write_back_one(); } void mfm_harddisk_device::head_move() { int steps = m_track_delta; if (steps < 0) steps = -steps; - if (TRACE_STEPS) logerror("Moving head by %d step(s) %s\n", steps, (m_track_delta<0)? "outward" : "inward"); + LOGMASKED(LOG_STEPS, "Moving head by %d step(s) %s\n", steps, (m_track_delta<0)? "outward" : "inward"); // We simulate the head movement by pausing for n*step_time with n being the cylinder delta m_step_phase = STEP_MOVING; m_seek_timer->adjust(m_step_time * steps); - if (TRACE_TIMING) logerror("Head movement takes %s time\n", tts(m_step_time * steps).c_str()); + long moveus = (m_step_time.attoseconds() * steps) / ATTOSECONDS_PER_MICROSECOND; + LOGMASKED(LOG_STEPSDETAIL, "Head movement takes %.1f ms time [%s]\n", moveus/1000., machine().time().to_string()); // We pretend that we already arrived // TODO: Check auto truncation? m_current_cylinder += m_track_delta; @@ -720,8 +715,8 @@ void mfm_harddisk_device::head_move() void mfm_harddisk_device::direction_in_w(line_state line) { + if (m_seek_inward != (line == ASSERT_LINE)) LOGMASKED(LOG_STEPSDETAIL, "Setting seek direction %s\n", m_seek_inward? "inward" : "outward"); m_seek_inward = (line == ASSERT_LINE); - if (TRACE_STEPS && TRACE_DETAIL) logerror("Setting seek direction %s\n", m_seek_inward? "inward" : "outward"); } /* @@ -772,10 +767,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; - if (TRACE_STEPS && TRACE_DETAIL) logerror("Got seek pulse; track delta %d\n", m_track_delta); + LOGMASKED(LOG_STEPSDETAIL, "Got seek pulse; track delta %d\n", m_track_delta); if (m_track_delta < -m_phys_cylinders || m_track_delta > m_phys_cylinders) { - if (TRACE_STEPS) logerror("Excessive step pulses - doing auto-truncation\n"); + LOGMASKED(LOG_STEPS, "Excessive step pulses - doing auto-truncation\n"); m_autotruncation = true; } m_seek_timer->adjust(attotime::from_usec(250)); // Start step collect timer @@ -808,7 +803,7 @@ bool mfm_harddisk_device::find_position(attotime &from_when, const attotime &lim // Reached the end if (bytepos >= m_trackimage_size) { - if (TRACE_TIMING) logerror("Reached end: rev_start = %s, live = %s\n", tts(m_revolution_start_time).c_str(), tts(from_when).c_str()); + LOGMASKED(LOG_TIMING, "Reached end: rev_start = %s, live = %s\n", (m_revolution_start_time).to_string(), (from_when).to_string()); m_revolution_start_time += m_rev_time; cell = (from_when - m_revolution_start_time).as_ticks(freq); bytepos = cell / 16; @@ -816,7 +811,7 @@ bool mfm_harddisk_device::find_position(attotime &from_when, const attotime &lim if (bytepos < 0) { - if (TRACE_TIMING) logerror("Negative cell number: rev_start = %s, live = %s\n", tts(m_revolution_start_time).c_str(), tts(from_when).c_str()); + LOGMASKED(LOG_TIMING, "Negative cell number: rev_start = %s, live = %s\n", (m_revolution_start_time).to_string(), (from_when).to_string()); bytepos = 0; } bit = cell % 16; @@ -837,7 +832,9 @@ bool mfm_harddisk_device::read(attotime &from_when, const attotime &limit, uint1 if (track==nullptr) { // What shall we do in this case? - throw emu_fatalerror("Cannot read CHD image"); + // throw emu_fatalerror("Cannot read CHD image"); // a bit too harsh, just return a constant 0 + cdata = 0; + return false; } // Get a copy for later debug output @@ -853,12 +850,12 @@ bool mfm_harddisk_device::read(attotime &from_when, const attotime &limit, uint1 { // We will deliver a single bit cdata = ((track[bytepos] << bitpos) & 0x8000) >> 15; - if (TRACE_BITS) logerror("Reading (c=%d,h=%d,bit=%d) at cell %d [%s] = %d\n", m_current_cylinder, m_current_head, bitpos, ((bytepos<<4) + bitpos), tts(fw).c_str(), cdata); + LOGMASKED(LOG_BITS, "Reading (c=%d,h=%d,bit=%d) at cell %d [%s] = %d\n", m_current_cylinder, m_current_head, bitpos, ((bytepos<<4) + bitpos), fw.to_string(), cdata); } else { // We will deliver a whole byte - if (TRACE_READ) logerror("Reading (c=%d,h=%d) at position %d\n", m_current_cylinder, m_current_head, bytepos); + LOGMASKED(LOG_READ, "Reading (c=%d,h=%d) at position %d\n", m_current_cylinder, m_current_head, bytepos); cdata = track[bytepos]; } return false; @@ -876,7 +873,8 @@ bool mfm_harddisk_device::write(attotime &from_when, const attotime &limit, uint if (track==nullptr) { // What shall we do in this case? - throw emu_fatalerror("Cannot read CHD image"); + // throw emu_fatalerror("Cannot read CHD image"); // a bit too harsh, just return without doing anything + return false; } int bytepos = 0; @@ -911,14 +909,14 @@ bool mfm_harddisk_device::write(attotime &from_when, const attotime &limit, uint if (wpcom && (params->write_precomp_cylinder == -1 || m_current_cylinder < params->write_precomp_cylinder)) params->write_precomp_cylinder = m_current_cylinder; - if (TRACE_WRITE) if ((bitpos&0x0f)==0) logerror("Wrote data=%04x (c=%d,h=%d) at position %04x, wpcom=%d, rwc=%d\n", track[bytepos], m_current_cylinder, m_current_head, bytepos, wpcom, reduced_wc); + if ((bitpos&0x0f)==0) + LOGMASKED(LOG_WRITE, "Wrote data=%04x (c=%d,h=%d) at position %04x, wpcom=%d, rwc=%d\n", track[bytepos], m_current_cylinder, m_current_head, bytepos, wpcom, reduced_wc); return false; } -chd_error mfm_harddisk_device::load_track(uint16_t* data, int cylinder, int head) +std::error_condition mfm_harddisk_device::load_track(uint16_t* data, int cylinder, int head) { - chd_error state = m_format->load(m_chd, data, m_trackimage_size, cylinder, head); - return state; + return m_format->load(m_chd, data, m_trackimage_size, cylinder, head); } void mfm_harddisk_device::write_track(uint16_t* data, int cylinder, int head) @@ -989,6 +987,9 @@ DEFINE_DEVICE_TYPE(MFMHD_ST251, mfm_hd_st251_device, "mfm_hd_st251", "Seagate ST // This is a write-back LRU cache. // =========================================================== +#define TRACE_CACHE 0 +#define TRACE_DETAIL 0 + mfmhd_trackimage_cache::mfmhd_trackimage_cache(running_machine &machine): m_mfmhd(nullptr), m_tracks(nullptr), @@ -1003,9 +1004,8 @@ mfmhd_trackimage_cache::~mfmhd_trackimage_cache() while (current != nullptr) { - global_free_array(current->encdata); mfmhd_trackimage* currenttmp = current->next; - global_free(current); + delete current; current = currenttmp; } } @@ -1018,7 +1018,7 @@ void mfmhd_trackimage_cache::write_back_one() { if (current->dirty) { - m_mfmhd->write_track(current->encdata, current->cylinder, current->head); + m_mfmhd->write_track(current->encdata.get(), current->cylinder, current->head); current->dirty = false; break; } @@ -1038,7 +1038,7 @@ void mfmhd_trackimage_cache::cleanup() if (TRACE_CACHE) m_machine.logerror("[%s:cache] MFM HD cache: evict line cylinder=%d head=%d\n", m_mfmhd->tag(), current->cylinder, current->head); if (current->dirty) { - m_mfmhd->write_track(current->encdata, current->cylinder, current->head); + m_mfmhd->write_track(current->encdata.get(), current->cylinder, current->head); current->dirty = false; } mfmhd_trackimage* currenttmp = current->next; @@ -1055,8 +1055,6 @@ void mfmhd_trackimage_cache::mark_current_as_dirty() m_tracks->dirty = true; } -const char *encnames[] = { "MFM_BITS","MFM_BYTE","SEPARATE","SSIMPLE " }; - /* Initialize the cache by loading the first <trackslots> tracks. */ @@ -1064,7 +1062,7 @@ void mfmhd_trackimage_cache::init(mfm_harddisk_device* mfmhd, int tracksize, int { if (TRACE_CACHE) m_machine.logerror("[%s:cache] MFM HD cache init; cache size is %d tracks\n", mfmhd->tag(), trackslots); - chd_error state; + std::error_condition state; mfmhd_trackimage* previous; mfmhd_trackimage* current = nullptr; @@ -1078,14 +1076,15 @@ void mfmhd_trackimage_cache::init(mfm_harddisk_device* mfmhd, int tracksize, int while (track < trackslots) { - if (TRACE_CACHE && TRACE_DETAIL) m_machine.logerror("[%s:cache] MFM HD allocate cache slot\n", mfmhd->tag()); + if (TRACE_DETAIL) m_machine.logerror("[%s:cache] MFM HD allocate cache slot\n", mfmhd->tag()); previous = current; - current = global_alloc(mfmhd_trackimage); - current->encdata = global_alloc_array(uint16_t, tracksize); + current = new mfmhd_trackimage; + current->encdata = std::make_unique<uint16_t []>(tracksize); // Load the first tracks into the slots - state = m_mfmhd->load_track(current->encdata, cylinder, head); - if (state != CHDERR_NONE) throw emu_fatalerror("Cannot load (c=%d,h=%d) from hard disk", cylinder, head); + state = m_mfmhd->load_track(current->encdata.get(), cylinder, head); + if (state) + throw emu_fatalerror("Cannot load (c=%d,h=%d) from hard disk", cylinder, head); current->dirty = false; current->cylinder = cylinder; @@ -1122,11 +1121,11 @@ uint16_t* mfmhd_trackimage_cache::get_trackimage(int cylinder, int head) mfmhd_trackimage* current = m_tracks; mfmhd_trackimage* previous = nullptr; - chd_error state = CHDERR_NONE; + std::error_condition state; // Repeat the search. This loop should run at most twice; once for a direct hit, // and twice on miss, then the second iteration will be a hit. - while (state == CHDERR_NONE) + while (!state) { // A simple linear search while (current != nullptr) @@ -1141,7 +1140,7 @@ uint16_t* mfmhd_trackimage_cache::get_trackimage(int cylinder, int head) current->next = m_tracks; // put the previous head into the next field m_tracks = current; // set this line as new head } - return current->encdata; + return current->encdata.get(); } else { @@ -1156,16 +1155,21 @@ uint16_t* mfmhd_trackimage_cache::get_trackimage(int cylinder, int head) // Then look it up again, which will move it to the front // previous points to the second to last element + + // If still null, the cache was never initialized, which means there is no drive image + if (previous == nullptr) + return nullptr; + current = previous->next; if (TRACE_CACHE) m_machine.logerror("[%s:cache] evict line (c=%d,h=%d)\n", m_mfmhd->tag(), current->cylinder, current->head); if (current->dirty) { - m_mfmhd->write_track(current->encdata, current->cylinder, current->head); + m_mfmhd->write_track(current->encdata.get(), current->cylinder, current->head); current->dirty = false; } - state = m_mfmhd->load_track(current->encdata, cylinder, head); + state = m_mfmhd->load_track(current->encdata.get(), cylinder, head); current->dirty = false; current->cylinder = cylinder; |