void SASI::write_io8(uint32 addr, uint32 data) { switch(addr) { case 0x1f0: // data if(phase == PHASE_COMMAND) { cmd[cmd_ptr++] = data; if(cmd_ptr == 6) { check_cmd(); } } else if(phase == PHASE_C2) { if(++status_ptr == 10) { set_status(0); } } else if(phase == PHASE_WRITE) { buffer[buffer_ptr++] = data; if(buffer_ptr == 256) { flush(unit); if(--blocks) { sector++; buffer_ptr = 0; if(!seek(unit)) { set_status(0x0f); set_drq(false); } } else { set_status(0); set_drq(false); } } } datareg = data; break; case 0x1f1: // reset reset(); break; case 0x1f2: // select phase = PHASE_SELECT; register_event(this, EVENT_COMMAND, 10, false, NULL); break; case 0x1f3: // mask maskreg = data; break; } }
UINT32 upd3301_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { if (m_status & STATUS_VE) { m_y = 0; m_bitmap = &bitmap; m_data_fifo_pos = 0; m_attr_fifo_pos = 0; m_cursor_frame++; if (m_cursor_frame == m_b) { m_cursor_frame = 0; m_cursor_blink = !m_cursor_blink; } m_attr_frame++; if (m_attr_frame == (m_b << 1)) { m_attr_frame = 0; m_attr_blink = !m_attr_blink; } // start DMA transfer set_drq(1); } else { bitmap.fill(get_black_pen(machine()), cliprect); } return 0; }
void upd3301_device::device_reset() { set_interrupt(0); set_drq(0); recompute_parameters(); }
void UPD765A::reset() { shift_to_idle(); // CANCEL_EVENT(); phase_id = drq_id = lost_id = result7_id = -1; seek_id[0] = seek_id[1] = seek_id[2] = seek_id[3] = -1; set_irq(false); set_drq(false); }
void UPD765A::event_callback(int event_id, int err) { #ifdef SDL request_single_exec(); #endif // SDL if(event_id == EVENT_PHASE) { phase_id = -1; phase = event_phase; process_cmd(command & 0x1f); } else if(event_id == EVENT_DRQ) { drq_id = -1; status |= S_RQM; int drv = hdu & DRIVE_MASK; fdc[drv].cur_position = (fdc[drv].cur_position + 1) % disk[drv]->get_track_size(); fdc[drv].prev_clock = prev_drq_clock = current_clock(); set_drq(true); } else if(event_id == EVENT_LOST) { #ifdef _FDC_DEBUG_LOG emu->out_debug_log("FDC: DATA LOST\n"); #endif lost_id = -1; result = ST1_OR; set_drq(false); shift_to_result7(); } else if(event_id == EVENT_RESULT7) { result7_id = -1; shift_to_result7_event(); } else if(event_id == EVENT_INDEX) { int drv = hdu & DRIVE_MASK; bool now_index = (disk[drv]->inserted && get_cur_position(drv) == 0); if(prev_index != now_index) { write_signals(&outputs_index, now_index ? 0xffffffff : 0); prev_index = now_index; } } else if(event_id >= EVENT_SEEK && event_id < EVENT_SEEK + 4) { int drv = event_id - EVENT_SEEK; seek_id[drv] = -1; seek_event(drv); } }
void UPD765A::shift_to_write(int length) { phase = PHASE_WRITE; status = S_RQM | S_NDM | S_CB; bufptr = buffer; count = length; int drv = hdu & DRIVE_MASK; fdc[drv].cur_position = fdc[drv].next_trans_position; fdc[drv].prev_clock = prev_drq_clock = current_clock(); set_drq(true); }
void UPD765A::initialize() { // initialize d88 handler for(int i = 0; i < 4; i++) { disk[i] = new DISK(emu); } // initialize fdc memset(fdc, 0, sizeof(fdc)); memset(buffer, 0, sizeof(buffer)); phase = prevphase = PHASE_IDLE; status = S_RQM; seekstat = 0; bufptr = buffer; // temporary phase_id = drq_id = lost_id = result7_id = -1; seek_id[0] = seek_id[1] = seek_id[2] = seek_id[3] = -1; no_dma_mode = false; motor_on = false; // motor off force_ready = false; reset_signal = true; irq_masked = drq_masked = false; set_irq(false); set_drq(false); #ifdef UPD765A_EXT_DRVSEL hdu = 0; #else set_hdu(0); #endif // index hole event if(outputs_index.count) { register_event(this, EVENT_INDEX, 4, true, NULL); prev_index = false; } }
void el2_3c503_device::dack_w(int line, uint8_t data) { set_drq(CLEAR_LINE); el2_3c503_mem_write(m_regs.da++, data); }
uint8_t el2_3c503_device::dack_r(int line) { set_drq(CLEAR_LINE); return el2_3c503_mem_read(m_regs.da++); }
inline void upd3301_device::reset_counters() { set_interrupt(0); set_drq(0); }
void wd33c9x_base_device::step(bool timeout) { if (++m_step_count > 1) { return; } const uint8_t cc = (m_regs[COMMAND] & COMMAND_CC); const bool sat = (cc == COMMAND_CC_SELECT_TRANSFER || cc == COMMAND_CC_SELECT_ATN_TRANSFER); uint32_t cycles = 0; do { const uint32_t ctrl = scsi_bus->ctrl_r(); const uint32_t data = scsi_bus->data_r(); m_step_count = 1; LOGMASKED(LOG_STEP, "%s: step - PHASE:%s BSY:%x SEL:%x REQ:%x ACK:%x ATN:%x RST:%x DATA:%x (%d.%d) %s\n", shortname(), phase_strings[ctrl & S_PHASE_MASK], (ctrl & S_BSY) ? 1 : 0, (ctrl & S_SEL) ? 1 : 0, (ctrl & S_REQ) ? 1 : 0, (ctrl & S_ACK) ? 1 : 0, (ctrl & S_ATN) ? 1 : 0, (ctrl & S_RST) ? 1 : 0, data, m_scsi_state & STATE_MASK, m_scsi_state >> SUB_SHIFT, (timeout) ? "timeout" : "change" ); if (m_mode == MODE_I) { if (ctrl & S_BSY) { if (ctrl & S_REQ) { uint8_t xfr_phase = (ctrl & S_PHASE_MASK); switch (m_scsi_state) { case DISC_SEL_ARBITRATION: m_xfr_phase = xfr_phase; break; case INIT_XFR_WAIT_REQ: break; default: if (m_xfr_phase != xfr_phase) { fatalerror("%s: Unexpected phase change during state.\n", shortname()); } break; } } } else { LOGMASKED(LOG_STATE, "%s: Target disconnected\n", shortname()); if (sat) { switch (m_regs[COMMAND_PHASE]) { case COMMAND_PHASE_DISCONNECT_MESSAGE: set_scsi_state(FINISHED); m_regs[COMMAND_PHASE] = COMMAND_PHASE_DISCONNECTED; break; case COMMAND_PHASE_COMMAND_COMPLETE: if (m_regs[CONTROL] & CONTROL_EDI) { set_scsi_state(FINISHED); irq_fifo_push(SCSI_STATUS_SELECT_TRANSFER_SUCCESS); } break; default: fatalerror("%s: Unhandled command phase during Select-and-Transfer disconnect.\n", shortname()); break; } } else { set_scsi_state(FINISHED); irq_fifo_push(SCSI_STATUS_DISCONNECT); } m_mode = MODE_D; scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL); continue; } } switch (m_scsi_state & SUB_MASK ? m_scsi_state & SUB_MASK : m_scsi_state & STATE_MASK) { case IDLE: break; case FINISHED: set_scsi_state(IDLE); m_regs[AUXILIARY_STATUS] &= ~(AUXILIARY_STATUS_CIP | AUXILIARY_STATUS_BSY); update_irq(); break; case ARB_WAIT_BUS_FREE << SUB_SHIFT: if (timeout) { if (!(ctrl & (S_BSY | S_SEL))) { set_scsi_state_sub(ARB_CHECK_FREE); } cycles = 1; } break; case ARB_CHECK_FREE << SUB_SHIFT: if (timeout) { uint8_t next_state; if (ctrl & (S_BSY | S_SEL)) { next_state = ARB_WAIT_BUS_FREE; cycles = 1; } else { scsi_bus->data_w(scsi_refid, 1 << scsi_id); scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); next_state = ARB_EXAMINE_BUS; cycles = 1; } set_scsi_state_sub(next_state); } break; case ARB_EXAMINE_BUS << SUB_SHIFT: if (timeout) { if (ctrl & S_SEL) { scsi_bus->ctrl_w(scsi_refid, 0, S_BSY); scsi_bus->data_w(scsi_refid, 0); set_scsi_state_sub(ARB_WAIT_BUS_FREE); } else { int win; for (win = 7; win >=0 && !(data & (1 << win)); win--) {}; if (win == scsi_id) { scsi_bus->ctrl_w(scsi_refid, S_SEL, S_SEL); set_scsi_state_sub(ARB_ASSERT_SEL); } else { scsi_bus->data_w(scsi_refid, 0); scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); } } cycles = 1; } break; case ARB_ASSERT_SEL << SUB_SHIFT: if (timeout) { scsi_bus->data_w(scsi_refid, (1 << scsi_id) | (1 << (m_regs[DESTINATION_ID] & DESTINATION_ID_DI))); set_scsi_state_sub(ARB_SET_DEST); cycles = 1; } break; case ARB_SET_DEST << SUB_SHIFT: if (timeout) { scsi_bus->ctrl_w(scsi_refid, (cc == COMMAND_CC_SELECT_ATN || cc == COMMAND_CC_SELECT_ATN_TRANSFER) ? S_ATN : 0, S_ATN | S_BSY); set_scsi_state_sub(ARB_RELEASE_BUSY); cycles = 1; } break; case ARB_RELEASE_BUSY << SUB_SHIFT: if (timeout) { if (ctrl & S_BSY) { set_scsi_state_sub(ARB_DESKEW_WAIT); if (cc == COMMAND_CC_RESELECT) { scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); } cycles = 1; } else { set_scsi_state_sub(ARB_TIMEOUT_BUSY); cycles = 1; } } break; case ARB_DESKEW_WAIT << SUB_SHIFT: if (timeout) { scsi_bus->data_w(scsi_refid, 0); scsi_bus->ctrl_w(scsi_refid, 0, S_SEL); m_mode = (cc == COMMAND_CC_RESELECT) ? MODE_T : MODE_I; set_scsi_state_sub(0); ++m_step_count; } break; case ARB_TIMEOUT_BUSY << SUB_SHIFT: if (timeout) { scsi_bus->data_w(scsi_refid, 0); set_scsi_state_sub(ARB_TIMEOUT_ABORT); cycles = 1000; } else if (ctrl & S_BSY) { set_scsi_state_sub(ARB_DESKEW_WAIT); if (cc == COMMAND_CC_RESELECT) { scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); } cycles = 1; } break; case ARB_TIMEOUT_ABORT << SUB_SHIFT: if (timeout) { if (ctrl & S_BSY) { set_scsi_state_sub(ARB_DESKEW_WAIT); if (cc == COMMAND_CC_RESELECT) { scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); } cycles = 1; } else { scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL); m_regs[AUXILIARY_STATUS] &= ~(AUXILIARY_STATUS_CIP | AUXILIARY_STATUS_BSY); m_mode = MODE_D; set_scsi_state(IDLE); irq_fifo_push(SCSI_STATUS_SELECTION_TIMEOUT); update_irq(); } } break; case SEND_WAIT_SETTLE << SUB_SHIFT: if (timeout) { set_scsi_state_sub(SEND_WAIT_REQ_0); ++m_step_count; } break; case SEND_WAIT_REQ_0 << SUB_SHIFT: if (!(ctrl & S_REQ)) { set_scsi_state_sub(0); scsi_bus->data_w(scsi_refid, 0); scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); if (sat) { switch (m_xfr_phase) { case S_PHASE_COMMAND: ++m_regs[COMMAND_PHASE]; break; } } ++m_step_count; } break; case RECV_WAIT_REQ_1 << SUB_SHIFT: if (ctrl & S_REQ) { set_scsi_state_sub(RECV_WAIT_SETTLE); cycles = 1; } break; case RECV_WAIT_SETTLE << SUB_SHIFT: if (timeout) { if (sat) { switch (m_xfr_phase) { case S_PHASE_DATA_IN: data_fifo_push(data); if ((m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) { set_drq(); } else { decrement_transfer_count(); m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; } break; case S_PHASE_STATUS: m_regs[TARGET_LUN] = data; m_regs[COMMAND_PHASE] = COMMAND_PHASE_STATUS_RECEIVED; break; case S_PHASE_MSG_IN: data_fifo_push(data); break; default: fatalerror("%s: Unexpected phase in RECV_WAIT_SETTLE.\n", shortname()); break; } } else { data_fifo_push(data); if (m_xfr_phase == S_PHASE_DATA_IN && (m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) { set_drq(); } else { decrement_transfer_count(); m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; } } set_scsi_state_sub(RECV_WAIT_REQ_0); scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK); ++m_step_count; } break; case RECV_WAIT_REQ_0 << SUB_SHIFT: if (!(ctrl & S_REQ)) { set_scsi_state_sub(0); ++m_step_count; } break; case DISC_SEL_ARBITRATION: scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); if (cc == COMMAND_CC_SELECT || cc == COMMAND_CC_SELECT_ATN) { set_scsi_state(FINISHED); irq_fifo_push(SCSI_STATUS_SELECT_SUCCESS); if (ctrl & S_REQ) { irq_fifo_push(SCSI_STATUS_REQ | m_xfr_phase); } } else { set_scsi_state(INIT_XFR); m_regs[COMMAND_PHASE] = COMMAND_PHASE_SELECTED; } ++m_step_count; break; case INIT_XFR: if (ctrl & S_REQ) { switch (m_xfr_phase) { case S_PHASE_DATA_OUT: if ((m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) { while (!data_fifo_full() && m_transfer_count > 0) { set_drq(); } } if (!data_fifo_empty()) { set_scsi_state(INIT_XFR_WAIT_REQ); cycles = send_byte(); } else if ((m_regs[CONTROL] & CONTROL_DM) == CONTROL_DM_POLLED) { m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; } break; case S_PHASE_COMMAND: if (!data_fifo_empty()) { uint32_t mask; if (sat) { mask = 0; } else { m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; mask = (m_transfer_count == 0 && m_data_fifo_size == 1) ? S_ATN : 0; } set_scsi_state(INIT_XFR_WAIT_REQ); cycles = send_byte(0, mask); } else if (!sat) { m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; } break; case S_PHASE_MSG_OUT: if (sat) { data_fifo_push(get_msg_out()); } if (!data_fifo_empty()) { uint32_t mask; if (sat) { mask = S_ATN; } else { m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; mask = (m_transfer_count == 0 && m_data_fifo_size == 1) ? S_ATN : 0; } set_scsi_state(INIT_XFR_WAIT_REQ); cycles = send_byte(0, mask); } else if (!sat) { m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR; } break; case S_PHASE_DATA_IN: case S_PHASE_STATUS: case S_PHASE_MSG_IN: if (!data_fifo_full()) { // if it's the last message byte, ACK remains asserted, terminate with function_complete() //state = (m_xfr_phase == S_PHASE_MSG_IN && (!dma_command || tcounter == 1)) ? INIT_XFR_RECV_BYTE_NACK : INIT_XFR_RECV_BYTE_ACK; scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); set_scsi_state((RECV_WAIT_REQ_1 << SUB_SHIFT) | INIT_XFR_RECV_BYTE_ACK); if (ctrl & S_REQ) { ++m_step_count; } } break; default: fatalerror("%s: Invalid phase during INIT_XFR.\n", shortname()); break; } } break; case INIT_XFR_WAIT_REQ: if (ctrl & S_REQ) { uint16_t next_state = m_scsi_state; const uint8_t xfr_phase = (ctrl & S_PHASE_MASK); switch ((m_xfr_phase << 3) | xfr_phase) { case ((S_PHASE_MSG_OUT << 3) | S_PHASE_MSG_OUT): case ((S_PHASE_COMMAND << 3) | S_PHASE_COMMAND): case ((S_PHASE_MSG_IN << 3) | S_PHASE_MSG_IN): next_state = INIT_XFR; break; case ((S_PHASE_DATA_IN << 3) | S_PHASE_DATA_IN): case ((S_PHASE_DATA_OUT << 3) | S_PHASE_DATA_OUT): if (sat || cc == COMMAND_CC_TRANSFER_INFO) { if (m_transfer_count > 0 || (m_xfr_phase == S_PHASE_DATA_OUT && !data_fifo_empty())) { next_state = INIT_XFR; } else { next_state = FINISHED; uint8_t scsi_status; if (sat) { m_regs[COMMAND_PHASE] = COMMAND_PHASE_TRANSFER_COUNT; scsi_status = SCSI_STATUS_UNEXPECTED_PHASE; } else { scsi_status = SCSI_STATUS_TRANSFER_SUCCESS; } irq_fifo_push(scsi_status | m_xfr_phase); } } else { fatalerror("%s: Unhandled command in data phase.\n", shortname()); next_state = FINISHED; } break; case ((S_PHASE_MSG_OUT << 3) | S_PHASE_COMMAND): case ((S_PHASE_COMMAND << 3) | S_PHASE_DATA_OUT): case ((S_PHASE_COMMAND << 3) | S_PHASE_DATA_IN): case ((S_PHASE_COMMAND << 3) | S_PHASE_STATUS): case ((S_PHASE_COMMAND << 3) | S_PHASE_MSG_IN): case ((S_PHASE_DATA_OUT << 3) | S_PHASE_STATUS): case ((S_PHASE_DATA_IN << 3) | S_PHASE_STATUS): case ((S_PHASE_STATUS << 3) | S_PHASE_MSG_IN): if (!(m_xfr_phase & 1) && !data_fifo_empty()) { fatalerror("%s: Data FIFO is not empty on phase transition.\n", shortname()); } if (sat) { switch (xfr_phase) { case S_PHASE_MSG_OUT: next_state = INIT_XFR; break; case S_PHASE_COMMAND: next_state = INIT_XFR; m_regs[COMMAND_PHASE] = COMMAND_PHASE_CP_BYTES_0; LOGMASKED(LOG_COMMANDS, "%s: Sending Command:", shortname()); for (uint8_t i = 0; i < m_command_length; ++i) { const uint8_t command_byte = m_regs[CDB_1 + i]; LOGMASKED(LOG_COMMANDS, " %02x", command_byte); data_fifo_push(command_byte); } LOGMASKED(LOG_COMMANDS, " (%d)\n", m_transfer_count); break; case S_PHASE_DATA_OUT: case S_PHASE_DATA_IN: next_state = INIT_XFR; break; case S_PHASE_STATUS: next_state = INIT_XFR; m_regs[COMMAND_PHASE] = COMMAND_PHASE_RECEIVE_STATUS; break; case S_PHASE_MSG_IN: next_state = INIT_XFR; break; default: fatalerror("%s: Unhandled phase in Select-w/Atn-and-Transfer.\n", shortname()); next_state = FINISHED; break; } } else if (cc == COMMAND_CC_TRANSFER_INFO) { next_state = FINISHED; irq_fifo_push(SCSI_STATUS_TRANSFER_SUCCESS | xfr_phase); } else { fatalerror("%s: Unhandled command in data phase.\n", shortname()); next_state = FINISHED; } break; default: fatalerror("%s: Unhandled phase transition in INIT_XFR_WAIT_REQ.\n", shortname()); next_state = FINISHED; break; } if (next_state != m_scsi_state) { set_scsi_state(next_state); ++m_step_count; m_xfr_phase = xfr_phase; } } break; case INIT_XFR_RECV_BYTE_ACK: if (sat && m_xfr_phase == S_PHASE_MSG_IN) { const uint8_t msg = data_fifo_pop(); if (m_regs[COMMAND_PHASE] <= COMMAND_PHASE_CP_BYTES_C) { switch (msg) { case SM_SAVE_DATA_PTR: set_scsi_state(FINISHED); irq_fifo_push(SCSI_STATUS_SAVE_DATA_POINTERS); m_regs[COMMAND_PHASE] = COMMAND_PHASE_SAVE_DATA_POINTER; break; case SM_DISCONNECT: m_regs[COMMAND_PHASE] = COMMAND_PHASE_DISCONNECT_MESSAGE; break; default: fatalerror("%s: Unhandled MSG_IN.\n", shortname()); break; } } else if (m_regs[COMMAND_PHASE] < COMMAND_PHASE_COMMAND_COMPLETE) { switch (msg) { case SM_COMMAND_COMPLETE: set_scsi_state(FINISHED); irq_fifo_push(SCSI_STATUS_SELECT_TRANSFER_SUCCESS); m_regs[COMMAND_PHASE] = COMMAND_PHASE_COMMAND_COMPLETE; break; default: fatalerror("%s: Unhandled MSG_IN.\n", shortname()); break; } } } else { set_scsi_state(INIT_XFR_WAIT_REQ); } scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); ++m_step_count; break; default: fatalerror("%s: Unhandled state in step.\n", shortname()); break; } timeout = false; } while (--m_step_count); if (cycles) { delay(cycles); } }
uint32 UPD765A::read_io8(uint32 addr) { if(addr & 1) { // fdc data if((status & (S_RQM | S_DIO)) == (S_RQM | S_DIO)) { uint8 data; status &= ~S_RQM; switch(phase) { case PHASE_RESULT: data = *bufptr++; #ifdef _FDC_DEBUG_LOG emu->out_debug_log("FDC: RESULT=%2x\n", data); #endif if(--count) { status |= S_RQM; } else { // EPSON QC-10 CP/M Plus bool clear_irq = true; if((command & 0x1f) == 0x08) { for(int i = 0; i < 4; i++) { if(fdc[i].result) { clear_irq = false; break; } } } if(clear_irq) { set_irq(false); } shift_to_idle(); } return data; case PHASE_READ: data = *bufptr++; #ifdef _FDC_DEBUG_LOG emu->out_debug_log("FDC: READ=%2x\n", data); #endif set_drq(false); if(--count) { REGISTER_DRQ_EVENT(); } else { process_cmd(command & 0x1f); } fdc[hdu & DRIVE_MASK].access = true; return data; } } return 0xff; } else { // FIXME: dirty patch for PC-8801 Kimochi Disk 2 if(phase_id != -1 && event_phase == PHASE_EXEC) { cancel_event(this, phase_id); phase_id = -1; phase = event_phase; process_cmd(command & 0x1f); } // fdc status #ifdef _FDC_DEBUG_LOG // emu->out_debug_log(_T("FDC: STATUS=%2x\n"), seekstat | status); #endif return seekstat | status; } }
void UPD765A::write_io8(uint32 addr, uint32 data) { if(addr & 1) { // fdc data if((status & (S_RQM | S_DIO)) == S_RQM) { status &= ~S_RQM; switch(phase) { case PHASE_IDLE: #ifdef _FDC_DEBUG_LOG switch(data & 0x1f) { case 0x02: emu->out_debug_log("FDC: CMD=%2x READ DIAGNOSTIC\n", data); break; case 0x03: emu->out_debug_log("FDC: CMD=%2x SPECIFY\n", data); break; case 0x04: emu->out_debug_log("FDC: CMD=%2x SENCE DEVSTAT\n", data); break; case 0x05: case 0x09: emu->out_debug_log("FDC: CMD=%2x WRITE DATA\n", data); break; case 0x06: case 0x0c: emu->out_debug_log("FDC: CMD=%2x READ DATA\n", data); break; case 0x07: emu->out_debug_log("FDC: CMD=%2x RECALIB\n", data); break; case 0x08: emu->out_debug_log("FDC: CMD=%2x SENCE INTSTAT\n", data); break; case 0x0a: emu->out_debug_log("FDC: CMD=%2x READ ID\n", data); break; case 0x0d: emu->out_debug_log("FDC: CMD=%2x WRITE ID\n", data); break; case 0x0f: emu->out_debug_log("FDC: CMD=%2x SEEK\n", data); break; case 0x11: case 0x19: case 0x1d: emu->out_debug_log("FDC: CMD=%2x SCAN\n", data); break; default: emu->out_debug_log("FDC: CMD=%2x INVALID\n", data); break; } #endif command = data; process_cmd(command & 0x1f); break; case PHASE_CMD: #ifdef _FDC_DEBUG_LOG emu->out_debug_log("FDC: PARAM=%2x\n", data); #endif *bufptr++ = data; if(--count) { status |= S_RQM; } else { process_cmd(command & 0x1f); } break; case PHASE_WRITE: #ifdef _FDC_DEBUG_LOG emu->out_debug_log("FDC: WRITE=%2x\n", data); #endif *bufptr++ = data; set_drq(false); if(--count) { REGISTER_DRQ_EVENT(); } else { process_cmd(command & 0x1f); } fdc[hdu & DRIVE_MASK].access = true; break; case PHASE_SCAN: if(data != 0xff) { if(((command & 0x1f) == 0x11 && *bufptr != data) || ((command & 0x1f) == 0x19 && *bufptr > data) || ((command & 0x1f) == 0x1d && *bufptr < data)) { result &= ~ST2_SH; } } bufptr++; set_drq(false); if(--count) { REGISTER_DRQ_EVENT(); } else { cmd_scan(); } fdc[hdu & DRIVE_MASK].access = true; break; } } } }
uint32 SASI::read_io8(uint32 addr) { uint32 val = 0; switch(addr) { case 0x1f0: // data if(phase == PHASE_READ) { val = buffer[buffer_ptr++]; if(buffer_ptr == 256) { if(--blocks) { sector++; buffer_ptr = 0; if(!seek(unit)) { set_status(0x0f); set_drq(false); } } else { set_status(0); set_drq(false); } } } else if(phase == PHASE_SENSE) { val = status_buf[status_ptr++]; if(status_ptr == 4) { set_status(0); } } else if(phase == PHASE_STATUS) { // val = error ? 0x02 : status; // phase = PHASE_MESSAGE; val = (error ? 2 : 0) | (unit << 5); phase = PHASE_FREE; } // else if(phase == PHASE_MESSAGE) { // phase = PHASE_FREE; // } return val; case 0x1f1: // status val = status_irq_drq; status_irq_drq &= ~STATUS_IRQ; if(phase != PHASE_FREE) { val |= STATUS_BSY; } if(phase > PHASE_SELECT) { val |= STATUS_REQ; } if(phase == PHASE_COMMAND) { val |= STATUS_CXD; } if(phase == PHASE_SENSE) { val |= STATUS_IXD; } if(phase == PHASE_READ) { val |= STATUS_IXD; } if(phase == PHASE_STATUS) { val |= STATUS_IXD | STATUS_CXD; } // if(phase == PHASE_MESSAGE) { // val |= STATUS_IXD | STATUS_CXD | STATUS_MSG; // } return val; } return 0xff; }