summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/upd765.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/upd765.cpp')
-rw-r--r--src/devices/machine/upd765.cpp139
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