diff options
Diffstat (limited to 'src/devices/machine/upd765.cpp')
-rw-r--r-- | src/devices/machine/upd765.cpp | 139 |
1 files changed, 75 insertions, 64 deletions
diff --git a/src/devices/machine/upd765.cpp b/src/devices/machine/upd765.cpp index bfbf277449b..64b844dd222 100644 --- a/src/devices/machine/upd765.cpp +++ b/src/devices/machine/upd765.cpp @@ -18,6 +18,7 @@ #define LOG_MATCH (1U << 10) // Sector matching #define LOG_STATE (1U << 11) // State machine #define LOG_LIVE (1U << 12) // Live states +#define LOG_DONE (1U << 13) // Command done #define VERBOSE (LOG_GENERAL | LOG_WARN ) @@ -38,6 +39,7 @@ #define LOGMATCH(...) LOGMASKED(LOG_MATCH, __VA_ARGS__) #define LOGSTATE(...) LOGMASKED(LOG_STATE, __VA_ARGS__) #define LOGLIVE(...) LOGMASKED(LOG_LIVE, __VA_ARGS__) +#define LOGDONE(...) LOGMASKED(LOG_DONE, __VA_ARGS__) DEFINE_DEVICE_TYPE(UPD765A, upd765a_device, "upd765a", "NEC uPD765A FDC") DEFINE_DEVICE_TYPE(UPD765B, upd765b_device, "upd765b", "NEC uPD765B FDC") @@ -166,7 +168,9 @@ upd765_family_device::upd765_family_device(const machine_config &mconfig, device pc_fdc_interface(mconfig, type, tag, owner, clock), intrq_cb(*this), drq_cb(*this), - hdl_cb(*this) + hdl_cb(*this), + idx_cb(*this), + us_cb(*this) { ready_polled = true; ready_connected = true; @@ -191,14 +195,19 @@ void upd765_family_device::set_mode(int _mode) mode = _mode; } -void upd765_family_device::device_start() +void upd765_family_device::device_resolve_objects() { - save_item(NAME(motorcfg)); - save_item(NAME(selected_drive)); - intrq_cb.resolve_safe(); drq_cb.resolve_safe(); hdl_cb.resolve_safe(); + idx_cb.resolve_safe(); + us_cb.resolve_safe(); +} + +void upd765_family_device::device_start() +{ + save_item(NAME(motorcfg)); + save_item(NAME(selected_drive)); for(int i=0; i != 4; i++) { char name[2]; @@ -327,6 +336,7 @@ void upd765_family_device::set_ds(int fid) for(floppy_info &fi : flopi) if(fi.dev) fi.dev->ds_w(fid); + us_cb(fid); // record selected drive selected_drive = fid; @@ -341,9 +351,11 @@ void upd765_family_device::set_floppy(floppy_image_device *flop) } if(flop) flop->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&upd765_family_device::index_callback, this)); + else + idx_cb(0); } -READ8_MEMBER(upd765_family_device::sra_r) +uint8_t upd765_family_device::sra_r() { uint8_t sra = 0; int fid = dor & 3; @@ -366,17 +378,17 @@ READ8_MEMBER(upd765_family_device::sra_r) return sra; } -READ8_MEMBER(upd765_family_device::srb_r) +uint8_t upd765_family_device::srb_r() { return 0; } -READ8_MEMBER(upd765_family_device::dor_r) +uint8_t upd765_family_device::dor_r() { return dor; } -WRITE8_MEMBER(upd765_family_device::dor_w) +void upd765_family_device::dor_w(uint8_t data) { LOGREGS("dor = %02x\n", data); uint8_t diff = dor ^ data; @@ -392,21 +404,16 @@ WRITE8_MEMBER(upd765_family_device::dor_w) check_irq(); } -READ8_MEMBER(upd765_family_device::tdr_r) +uint8_t upd765_family_device::tdr_r() { return 0; } -WRITE8_MEMBER(upd765_family_device::tdr_w) -{ -} - -READ8_MEMBER(upd765_family_device::msr_r) +void upd765_family_device::tdr_w(uint8_t data) { - return read_msr(); } -uint8_t upd765_family_device::read_msr() +uint8_t upd765_family_device::msr_r() { uint32_t msr = 0; switch(main_phase) { @@ -437,7 +444,7 @@ uint8_t upd765_family_device::read_msr() } msr |= get_drive_busy(); - if(data_irq) { + if(data_irq && !machine().side_effects_disabled()) { data_irq = false; check_irq(); } @@ -445,7 +452,7 @@ uint8_t upd765_family_device::read_msr() return msr; } -WRITE8_MEMBER(upd765_family_device::dsr_w) +void upd765_family_device::dsr_w(uint8_t data) { LOGREGS("dsr_w %02x (%s)\n", data, machine().describe_context()); if(data & 0x80) @@ -459,39 +466,43 @@ void upd765_family_device::set_rate(int rate) cur_rate = rate; } -uint8_t upd765_family_device::read_fifo() +uint8_t upd765_family_device::fifo_r() { uint8_t r = 0xff; switch(main_phase) { case PHASE_EXEC: + if(machine().side_effects_disabled()) + return fifo[0]; if(internal_drq) return fifo_pop(false); - LOGFIFO("read_fifo in phase %d\n", main_phase); + LOGFIFO("fifo_r in phase %d\n", main_phase); break; case PHASE_RESULT: r = result[0]; - result_pos--; - memmove(result, result+1, result_pos); - if(!result_pos) - main_phase = PHASE_CMD; - else if(result_pos == 1) { - // clear drive busy bit after the first sense interrupt status result byte is read - for(floppy_info &fi : flopi) - if((fi.main_state == RECALIBRATE || fi.main_state == SEEK) && fi.sub_state == IDLE && fi.st0_filled == false) - fi.main_state = IDLE; - clr_drive_busy(); + if(!machine().side_effects_disabled()) { + result_pos--; + memmove(result, result+1, result_pos); + if(!result_pos) + main_phase = PHASE_CMD; + else if(result_pos == 1) { + // clear drive busy bit after the first sense interrupt status result byte is read + for(floppy_info &fi : flopi) + if((fi.main_state == RECALIBRATE || fi.main_state == SEEK) && fi.sub_state == IDLE && fi.st0_filled == false) + fi.main_state = IDLE; + clr_drive_busy(); + } } break; default: - LOGFIFO("read_fifo in phase %d\n", main_phase); + LOGFIFO("fifo_r in phase %d\n", main_phase); break; } return r; } -void upd765_family_device::write_fifo(uint8_t data) +void upd765_family_device::fifo_w(uint8_t data) { switch(main_phase) { case PHASE_CMD: { @@ -517,11 +528,11 @@ void upd765_family_device::write_fifo(uint8_t data) fifo_push(data, false); return; } - LOGFIFO("write_fifo in phase %d\n", main_phase); + LOGFIFO("fifo_w in phase %d\n", main_phase); break; default: - LOGFIFO("write_fifo in phase %d\n", main_phase); + LOGFIFO("fifo_w in phase %d\n", main_phase); break; } } @@ -534,12 +545,7 @@ uint8_t upd765_family_device::do_dir_r() return 0x00; } -READ8_MEMBER(upd765_family_device::dir_r) -{ - return do_dir_r(); -} - -WRITE8_MEMBER(upd765_family_device::ccr_w) +void upd765_family_device::ccr_w(uint8_t data) { dsr = (dsr & 0xfc) | (data & 3); cur_rate = rates[data & 3]; @@ -641,18 +647,10 @@ void upd765_family_device::fifo_expect(int size, bool write) enable_transfer(); } -READ8_MEMBER(upd765_family_device::mdma_r) -{ - return dma_r(); -} - -WRITE8_MEMBER(upd765_family_device::mdma_w) -{ - dma_w(data); -} - uint8_t upd765_family_device::dma_r() { + if(machine().side_effects_disabled()) + return fifo[0]; return fifo_pop(false); } @@ -1474,7 +1472,7 @@ void upd765_family_device::execute_command(int cmd) void upd765_family_device::command_end(floppy_info &fi, bool data_completion) { - LOGCOMMAND("command done (%s) - %s\n", data_completion ? "data" : "seek", results()); + LOGDONE("command done (%s) - %s\n", data_completion ? "data" : "seek", results()); fi.main_state = fi.sub_state = IDLE; if(data_completion) data_irq = true; @@ -1746,7 +1744,16 @@ void upd765_family_device::read_data_continue(floppy_info &fi) fi.sub_state = COMMAND_DONE; break; } + // MZ: This st1 handling ensures that both HX5102 floppy and the + // Speedlock protection scheme are properly working. + // a) HX5102 requires that the ND flag not be set when no address + // marks could be found on the track at all (particularly due to + // wrong density) + // b) Speedlock requires the ND flag be set when there are valid + // sectors on the track, but the desired sector is missing, also + // when it has no valid address marks st1 &= ~ST1_MA; + st1 |= ST1_ND; if(!sector_matches()) { if(cur_live.idbuf[0] != command[2]) { if(cur_live.idbuf[0] == 0xff) @@ -1758,6 +1765,7 @@ void upd765_family_device::read_data_continue(floppy_info &fi) live_start(fi, SEARCH_ADDRESS_MARK_HEADER); return; } + st1 &= ~ST1_ND; LOGRW("reading sector %02x %02x %02x %02x\n", cur_live.idbuf[0], cur_live.idbuf[1], @@ -1776,11 +1784,6 @@ void upd765_family_device::read_data_continue(floppy_info &fi) case SCAN_ID_FAILED: LOGSTATE("SCAN_ID_FAILED\n"); fi.st0 |= ST0_FAIL; - // MZ: The HX5102 does not correctly detect a FM/MFM mismatch - // when the ND bit is set, because in the firmware the ND bit wins - // against MA, and thus concludes that the format is correct - // but the sector is missing. - // st1 |= ST1_ND; fi.sub_state = COMMAND_DONE; break; @@ -1852,7 +1855,7 @@ void upd765_family_device::write_data_start(floppy_info &fi) fi.main_state = WRITE_DATA; fi.sub_state = HEAD_LOAD; mfm = command[0] & 0x40; - LOGRW("command write%s data%s%s cmd=%02x sel=%x chrn=(%d, %d, %d, %d) eot=%02x gpl=%02x dtl=%02x rate=%d\n", + LOGCOMMAND("command write%s data%s%s cmd=%02x sel=%x chrn=(%d, %d, %d, %d) eot=%02x gpl=%02x dtl=%02x rate=%d\n", command[0] & 0x08 ? " deleted" : "", command[0] & 0x80 ? " mt" : "", command[0] & 0x40 ? " mfm" : "", @@ -1920,6 +1923,11 @@ void upd765_family_device::write_data_continue(floppy_info &fi) break; } st1 &= ~ST1_MA; + LOGRW("writing sector %02x %02x %02x %02x\n", + cur_live.idbuf[0], + cur_live.idbuf[1], + cur_live.idbuf[2], + cur_live.idbuf[3]); sector_size = calc_sector_size(cur_live.idbuf[3]); fifo_expect(sector_size, true); fi.sub_state = SECTOR_WRITTEN; @@ -1992,7 +2000,7 @@ void upd765_family_device::read_track_start(floppy_info &fi) mfm = command[0] & 0x40; sectors_read = 0; - LOGRW("command read track%s cmd=%02x sel=%x chrn=(%d, %d, %d, %d) eot=%02x gpl=%02x dtl=%02x rate=%d\n", + LOGCOMMAND("command read track%s cmd=%02x sel=%x chrn=(%d, %d, %d, %d) eot=%02x gpl=%02x dtl=%02x rate=%d\n", command[0] & 0x40 ? " mfm" : "", command[0], command[1], @@ -2284,6 +2292,9 @@ void upd765_family_device::read_id_start(floppy_info &fi) return; } + for(int i=0; i<4; i++) + cur_live.idbuf[i] = command[i+2]; + read_id_continue(fi); } @@ -2316,8 +2327,7 @@ void upd765_family_device::read_id_continue(floppy_info &fi) case SCAN_ID_FAILED: LOGSTATE("SCAN_ID_FAILED\n"); fi.st0 |= ST0_FAIL; - // st1 |= ST1_ND|ST1_MA; - st1 = ST1_MA; + st1 |= ST1_ND|ST1_MA; fi.sub_state = COMMAND_DONE; break; @@ -2443,6 +2453,7 @@ void upd765_family_device::index_callback(floppy_image_device *floppy, int state if(fi.live) live_sync(); fi.index = state; + idx_cb(state); if(!state) { general_continue(fi); @@ -2955,7 +2966,7 @@ void mcs3201_device::device_start() m_input_handler.resolve_safe(0); } -READ8_MEMBER( mcs3201_device::input_r ) +uint8_t mcs3201_device::input_r() { return m_input_handler(); } @@ -2975,7 +2986,7 @@ void tc8566af_device::device_start() save_item(NAME(m_cr1)); } -WRITE8_MEMBER(tc8566af_device::cr1_w) +void tc8566af_device::cr1_w(uint8_t data) { m_cr1 = data; @@ -2985,7 +2996,7 @@ WRITE8_MEMBER(tc8566af_device::cr1_w) } } -WRITE8_MEMBER(upd72065_device::auxcmd_w) +void upd72065_device::auxcmd_w(uint8_t data) { switch(data) { case 0x36: // reset |