Esempio n. 1
0
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;
	}
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
void upd3301_device::device_reset()
{
	set_interrupt(0);
	set_drq(0);

	recompute_parameters();
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
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);
	}
}
Esempio n. 6
0
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);
}
Esempio n. 7
0
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;
	}
}
Esempio n. 8
0
void el2_3c503_device::dack_w(int line, uint8_t data) {
	set_drq(CLEAR_LINE);
	el2_3c503_mem_write(m_regs.da++, data);
}
Esempio n. 9
0
uint8_t el2_3c503_device::dack_r(int line) {
	set_drq(CLEAR_LINE);
	return el2_3c503_mem_read(m_regs.da++);
}
Esempio n. 10
0
inline void upd3301_device::reset_counters()
{
	set_interrupt(0);
	set_drq(0);
}
Esempio n. 11
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);
	}
}
Esempio n. 12
0
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;
	}
}
Esempio n. 13
0
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;
			}
		}
	}
}
Esempio n. 14
0
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;
}