diff options
Diffstat (limited to 'src/devices/machine/upd765.cpp')
-rw-r--r-- | src/devices/machine/upd765.cpp | 68 |
1 files changed, 33 insertions, 35 deletions
diff --git a/src/devices/machine/upd765.cpp b/src/devices/machine/upd765.cpp index 51f6d0de63d..3788ae3b4d0 100644 --- a/src/devices/machine/upd765.cpp +++ b/src/devices/machine/upd765.cpp @@ -219,6 +219,7 @@ void ps2_fdc_device::set_mode(mode_t _mode) void upd765_family_device::device_start() { save_item(NAME(selected_drive)); + save_item(NAME(drive_busy)); for(int i=0; i != 4; i++) { char name[2]; @@ -483,7 +484,7 @@ void upd765_family_device::tdr_w(uint8_t data) uint8_t upd765_family_device::msr_r() { - uint32_t msr = 0; + uint8_t msr = 0; switch(main_phase) { case PHASE_CMD: msr |= MSR_RQM; @@ -505,11 +506,12 @@ uint8_t upd765_family_device::msr_r() msr |= MSR_RQM|MSR_DIO|MSR_CB; break; } - for(int i=0; i<4; i++) + for(int i=0; i<4; i++) { if(flopi[i].main_state == RECALIBRATE || flopi[i].main_state == SEEK) { msr |= 1<<i; //msr |= MSR_CB; } + } msr |= get_drive_busy(); return msr; @@ -540,7 +542,7 @@ uint8_t upd765_family_device::fifo_r() switch(main_phase) { case PHASE_CMD: if(machine().side_effects_disabled()) - return 0x00; + return 0xff; if(command_pos) fifo_w(0xff); LOGFIFO("fifo_r in command phase\n"); @@ -712,7 +714,7 @@ uint8_t upd765_family_device::fifo_pop(bool internal) if(!fifo_write && !fifo_pos) disable_transfer(); int thr = fifocfg & FIF_THR; - if(fifo_write && fifo_expected && (fifo_pos <= thr || (fifocfg & FIF_DIS))) + if(fifo_write && fifo_expected && (fifo_pos <= thr || (fifocfg & FIF_DIS)) && !tc_done) enable_transfer(); return r; } @@ -1585,8 +1587,10 @@ void upd765_family_device::command_end(floppy_info &fi, bool data_completion) LOGDONE("command done (%s) - %s\n", data_completion ? "data" : "seek", results()); fi.main_state = fi.sub_state = IDLE; irq = true; - if(!data_completion) + if(!data_completion) { fi.st0_filled = true; + drive_busy |= (1 << fi.id); + } check_irq(); } @@ -1611,8 +1615,13 @@ void upd765_family_device::recalibrate_start(floppy_info &fi) fi.dir = 1; fi.counter = recalibrate_steps; fi.ready = get_ready(command[1] & 3); - fi.st0 = (fi.ready ? 0 : ST0_NR); - seek_continue(fi); + fi.st0 = command[1] & 7; + if(fi.ready) { + seek_continue(fi); + } else { + fi.st0 |= ST0_NR | ST0_FAIL | ST0_SE; + command_end(fi, false); + } } void upd765_family_device::seek_start(floppy_info &fi) @@ -1622,8 +1631,13 @@ void upd765_family_device::seek_start(floppy_info &fi) fi.sub_state = SEEK_WAIT_STEP_TIME_DONE; fi.dir = fi.pcn > command[2] ? 1 : 0; fi.ready = get_ready(command[1] & 3); - fi.st0 = (fi.ready ? 0 : ST0_NR); - seek_continue(fi); + fi.st0 = command[1] & 7; + if(fi.ready) { + seek_continue(fi); + } else { + fi.st0 |= ST0_NR | ST0_FAIL | ST0_SE; + command_end(fi, false); + } } void upd765_family_device::delay_cycles(floppy_info &fi, int cycles) @@ -1858,12 +1872,6 @@ void upd765_family_device::read_data_continue(floppy_info &fi) case SCAN_ID: LOGSTATE("SCAN_ID\n"); - if(cur_live.crc) { - fi.st0 |= ST0_FAIL; - st1 |= ST1_DE|ST1_ND; - 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 @@ -1885,6 +1893,13 @@ void upd765_family_device::read_data_continue(floppy_info &fi) live_start(fi, SEARCH_ADDRESS_MARK_HEADER); return; } + if(cur_live.crc) { + fi.st0 |= ST0_FAIL; + st1 |= ST1_DE; + st1 &= ~ST1_ND; + fi.sub_state = COMMAND_DONE; + break; + } st1 &= ~ST1_ND; st2 &= ~ST2_WC; LOGRW("reading sector %02x %02x %02x %02x\n", @@ -2563,7 +2578,7 @@ TIMER_CALLBACK_MEMBER(upd765_family_device::run_drive_ready_polling) LOGCOMMAND("polled %d : %d -> %d\n", fid, flopi[fid].ready, ready); flopi[fid].ready = ready; if(!flopi[fid].st0_filled) { - flopi[fid].st0 = ST0_ABRT | fid; + flopi[fid].st0 = ST0_ABRT | fid | (ready ? 0 : ST0_NR); flopi[fid].st0_filled = true; irq = true; } @@ -2811,7 +2826,6 @@ void i82072_device::device_start() save_item(NAME(motorcfg)); save_item(NAME(motor_off_counter)); save_item(NAME(motor_on_counter)); - save_item(NAME(drive_busy)); save_item(NAME(delayed_command)); } @@ -2975,31 +2989,16 @@ void i82072_device::execute_command(int cmd) } } -/* - * The Intel datasheet says that the drive busy bits in the MSR are supposed to remain - * set after a seek or recalibrate until a sense interrupt status status command is - * executed. The InterPro 2000 diagnostic routine goes further, and tests the drive - * status bits before and after the first sense interrupt status result byte is read, - * and expects the drive busy bit to clear only after. - * - * The Amstrad CPC6128 uses a upd765a and seems to expect the busy bits to be cleared - * immediately after the seek/recalibrate interrupt is generated. - * - * Special casing the i82072 here seems the only way to reconcile this apparently - * different behaviour for now. - */ void i82072_device::command_end(floppy_info &fi, bool data_completion) { - if(!data_completion) - drive_busy |= (1 << fi.id); - // set motor off counter if(motorcfg) motor_off_counter = (2 + ((motorcfg & MOFF) >> 4)) << (motorcfg & HSDA ? 1 : 0); // clear existing interrupt sense data - for(floppy_info &fi : flopi) + for(floppy_info &fi : flopi) { fi.st0_filled = false; + } upd765_family_device::command_end(fi, data_completion); } @@ -3431,7 +3430,6 @@ void hd63266f_device::motor_control(int fid, bool start_motor) if(selected_drive != fid) return; - logerror("motor_on_counter %d\n", motor_on_counter); // decrement motor on counter if(motor_on_counter) motor_on_counter--; |