Beispiel #1
0
void wd33c9x_base_device::update_irq()
{
	if (m_regs[AUXILIARY_STATUS] & AUXILIARY_STATUS_INT) {
		m_regs[AUXILIARY_STATUS] &= ~AUXILIARY_STATUS_INT;
		LOGMASKED(LOG_LINES, "%s: Clearing IRQ\n", shortname());
		m_irq_cb(CLEAR_LINE);
	}
	if (!irq_fifo_empty()) {
		m_regs[SCSI_STATUS] = irq_fifo_pop();
		m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_INT;

		const uint8_t cc = (m_regs[COMMAND] & COMMAND_CC);
		if (cc == COMMAND_CC_SELECT_TRANSFER || cc == COMMAND_CC_SELECT_ATN_TRANSFER) {
			switch (m_regs[SCSI_STATUS]) {
			case SCSI_STATUS_DISCONNECT:
				if (!(m_regs[CONTROL] & CONTROL_IDI)) {
					return;
				}
				break;

			case SCSI_STATUS_SELECT_TRANSFER_SUCCESS:
				if ((m_regs[CONTROL] & CONTROL_EDI) && m_mode != MODE_D) {
					return;
				}
				break;
			}
		}

		LOGMASKED(LOG_LINES, "%s: Asserting IRQ - SCSI Status (%02x)\n", shortname(), m_regs[SCSI_STATUS]);
		m_irq_cb(ASSERT_LINE);
	}
}
Beispiel #2
0
/*
    should be called after any change to int_state or enabled_ints.
*/
void tms9901_device::field_interrupts()
{
	int current_ints;

	// m_int_state: inverted state of lines INT1*-INT15*. Bits are set by set_single_int only.
	current_ints = m_int_state;
	if (m_clock_register != 0)
	{
		// if timer is enabled, INT3 pin is overridden by timer
		if (m_timer_int_pending)
		{
			LOGMASKED(LOG_INT, "INT3 (timer) asserted\n");
			current_ints |= INT3;
		}
		else
		{
			LOGMASKED(LOG_INT, "INT3 (timer) cleared\n");
			current_ints &= ~INT3;
		}
	}

	// enabled_ints: enabled interrupts
	// Remove all settings from pins that are set as outputs (INT7*-INT15* share the same pins as P15-P7)
	current_ints &= m_enabled_ints & (~m_pio_direction_mirror);

	// Check whether we have a new state. For systems that use level-triggered
	// interrupts it should not do any harm if the line is re-asserted
	// but we may as well avoid this.
	if (current_ints == m_old_int_state)
		return;

	m_old_int_state = current_ints;

	if (current_ints != 0)
	{
		// find which interrupt tripped us:
		// the number of the first (i.e. least significant) non-zero bit among
		// the 16 first bits
		// we simply look for the first bit set to 1 in current_ints...
		int level = 0;

		while ((current_ints & 1)==0)
		{
			current_ints >>= 1; /* try next bit */
			level++;
		}
		LOGMASKED(LOG_INT, "Triggering interrupt, level %d\n", level);
		m_int_pending = true;
		if (!m_interrupt.isnull())
			m_interrupt(level, 1, 0xff);  // the offset carries the IC0-3 level
	}
Beispiel #3
0
uint8_t m68340_cpu_device::int_ack(offs_t offset)
{
	uint8_t pit_iarb = pit_arbitrate(offset);
	uint8_t scu_iarb = m_serial->arbitrate(offset);
	uint8_t t1_iarb = m_timer[0]->arbitrate(offset);
	uint8_t t2_iarb = m_timer[1]->arbitrate(offset);
	uint8_t iarb = std::max({pit_iarb, scu_iarb, t1_iarb, t2_iarb});
	LOGMASKED(LOG_IPL, "Level %d interrupt arbitration: PIT = %X, SCU = %X, T1 = %X, T2 = %X\n", offset, pit_iarb, scu_iarb, t1_iarb, t2_iarb);
	int response = 0;
	uint8_t vector = 0x18; // Spurious interrupt

	// Valid IARB levels are F (high) to 1 (low) and should be unique among modules using the same interrupt level
	if (iarb != 0)
	{
		if (iarb == scu_iarb)
		{
			vector = m_serial->irq_vector();
			LOGMASKED(LOG_IPL, "SCU acknowledged interrupt with vector %02X\n", vector);
			response++;
		}

		if (iarb == t1_iarb)
		{
			vector = m_timer[0]->irq_vector();
			LOGMASKED(LOG_IPL, "T1 acknowledged interrupt with vector %02X\n", vector);
			response++;
		}

		if (iarb == t2_iarb)
		{
			vector = m_timer[1]->irq_vector();
			LOGMASKED(LOG_IPL, "T2 acknowledged interrupt with vector %02X\n", vector);
			response++;
		}

		if (iarb == pit_iarb)
		{
			vector = pit_iack();
			LOGMASKED(LOG_IPL, "PIT acknowledged interrupt with vector %02X\n", vector);
			response++;
		}
	}

	if (response == 0)
		logerror("Spurious interrupt (level %d)\n", offset);
	else if (response > 1)
		logerror("%d modules responded to interrupt (level %d, IARB = %X)\n", response, offset, iarb);

	return vector;
}
Beispiel #4
0
void i8155_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	if (m_count_extra)
	{
		m_count_extra = false;
		return;
	}

	// count down by twos
	m_counter -= 2;

	if (m_counter == 1)
	{
		LOGMASKED(LOG_TIMER, "Timer count half finished\n");

		// reload the even half of the count
		m_counter = m_count_loaded & 0x3ffe;

		// square wave modes produce a low output in the second half of the counting period
		if ((get_timer_mode() & TIMER_MODE_TC_PULSE) == 0)
			timer_output(0);
	}
	else if (m_counter == 2)
	{
		if ((get_timer_mode() & TIMER_MODE_TC_PULSE) != 0)
		{
			// pulse low on TC being reached
			timer_output(0);
		}

		// set timer flag
		m_status |= STATUS_TIMER;
	}
	else if (m_counter == 0)
	{
		timer_output(1);

		if ((get_timer_mode() & TIMER_MODE_AUTO_RELOAD) == 0 || (m_command & COMMAND_TM_MASK) == COMMAND_TM_STOP_AFTER_TC)
		{
			// stop timer
			timer_stop_count();
			LOGMASKED(LOG_TIMER, "Timer stopped\n");
		}
		else
		{
			// automatically reload the counter
			timer_reload_count();
		}
	}
}
Beispiel #5
0
void aic6250_device::offset_cntrl_w(u8 data)
{
	LOGMASKED(LOG_REG, "offset_cntrl_w 0x%02x\n", data);

	if (VERBOSE & LOG_CONFIG)
	{
		if (data & R04W_OFFSET)
		{
			double divisor = 4.0 + ((data & R04W_SYNC_XFER_RATE) >> 4);

			LOGMASKED(LOG_CONFIG, "synchronous offset %d speed %.3f\n",
				data & R04W_OFFSET, clock() / divisor);
		}
		else
Beispiel #6
0
bool wd33c9x_base_device::set_command_length(const uint8_t cc)
{
	const bool eaf = ((m_regs[OWN_ID] & OWN_ID_EAF) != 0);
	bool ret;
	if (eaf && (cc == COMMAND_CC_SELECT_TRANSFER || cc == COMMAND_CC_SELECT_ATN_TRANSFER)) {
		m_command_length &= OWN_ID_CDB_SIZE;
		ret = true;
	}
	else if (eaf && cc == COMMAND_CC_WAIT_SELECT_RECEIVE_DATA) {
		m_command_length = 6;
		m_regs[COMMAND_PHASE] = COMMAND_PHASE_CP_BYTES_1;
		irq_fifo_push(SCSI_STATUS_NEED_COMMAND_SIZE);
		update_irq();
		ret = false;
	}
	else {
		switch (m_regs[CDB_1] >> 5) {
		default:
		case 0: m_command_length = 6;  break;
		case 1: m_command_length = 10; break;
		case 5: m_command_length = 12; break;
		}
		ret = true;
	}
	LOGMASKED(LOG_COMMANDS, "%s: SCSI Command Length %d bytes\n", shortname(), m_command_length);
	return ret;
}
Beispiel #7
0
void wd33c9x_base_device::set_drq()
{
	if (!m_drq_state) {
		LOGMASKED(LOG_LINES, "%s: Asserting DRQ\n", shortname());
		m_drq_state = true;
		m_drq_cb(ASSERT_LINE);
	}
}
Beispiel #8
0
void wd33c9x_base_device::clear_drq()
{
	if (m_drq_state) {
		LOGMASKED(LOG_LINES, "%s: Clearing DRQ\n", shortname());
		m_drq_state = false;
		m_drq_cb(CLEAR_LINE);
	}
}
Beispiel #9
0
inline void i8155_device::timer_output(int to)
{
	if (to == m_to)
		return;

	m_to = to;
	m_out_to_cb(to);

	LOGMASKED(LOG_TIMER, "Timer output: %u\n", to);
}
Beispiel #10
0
uint8_t a2bus_echoii_device::read_c0nx(uint8_t offset)
{
	// offset is completely ignored on the echoii (but not so on the echo+), so the same register maps to the entire space.
	uint8_t retval = 0xff; // pull-up resistor pack on the tms5220 bus

	// upon the falling edge of /DEVREAD, the active part of the read...
	if (m_readlatch_flag == false) // /RS was low, so we need to return a value from the tms5220
	{
		retval = 0x1f | m_tms->status_r(machine().dummy_space(), 0, 0xff);
		LOGMASKED(LOG_READ,"Returning status of speech chip, which is %02x\n", retval);
	}
	else
		LOGMASKED(LOG_READ,"chip status read on odd cycle, returning pull-up value of %02x\n", retval);

	// upon the rising edge of /DEVREAD, i.e. after the read has finished (so no updating retval after this)
	m_readlatch_flag = (!m_readlatch_flag); // latch inverts itself upon each read...
	m_tms->rsq_w(m_readlatch_flag); // update the /RS pin
	return retval;
}
Beispiel #11
0
inline void i8155_device::timer_reload_count()
{
	m_count_loaded = m_count_length;

	// valid counts range from 2 to 3FFF
	if ((m_count_length & 0x3fff) < 2)
	{
		timer_stop_count();
		return;
	}

	// begin the odd half of the count, with one extra cycle if count is odd
	m_counter = (m_count_loaded & 0x3ffe) | 1;
	m_count_extra = BIT(m_count_loaded, 0);

	// set up our timer
	m_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
	timer_output(1);

	switch (get_timer_mode())
	{
	case 0:
		// puts out LOW during second half of count
		LOGMASKED(LOG_TIMER, "Timer loaded with %d (Mode: LOW)\n", m_count_loaded & 0x3fff);
		break;

	case TIMER_MODE_AUTO_RELOAD:
		// square wave, i.e. the period of the square wave equals the count length programmed with automatic reload at terminal count
		LOGMASKED(LOG_TIMER, "Timer loaded with %d (Mode: Square wave)\n", m_count_loaded & 0x3fff);
		break;

	case TIMER_MODE_TC_PULSE:
		// single pulse upon TC being reached
		LOGMASKED(LOG_TIMER, "Timer loaded with %d (Mode: Single pulse)\n", m_count_loaded & 0x3fff);
		break;

	case TIMER_MODE_TC_PULSE | TIMER_MODE_AUTO_RELOAD:
		// automatic reload, i.e. single pulse every time TC is reached
		LOGMASKED(LOG_TIMER, "Timer loaded with %d (Mode: Automatic reload)\n", m_count_loaded & 0x3fff);
		break;
	}
}
Beispiel #12
0
uint8_t ps2_keyboard_controller_device::status_r()
{
	u8 const data = m_mcu->upi41_master_r(machine().dummy_space(), 1U);
	LOGMASKED(LOG_STATUS, "status_r 0x%02x%s%s%s%s%s%s%s%s (%s)\n", data,
		BIT(data, 7) ? " PER" : "",     BIT(data, 6) ? " GTO" : "",
		BIT(data, 5) ? " AUX_OBF" : "", BIT(data, 4) ? " INH" : "",
		BIT(data, 3) ? " CMD" : "",     BIT(data, 2) ? " SYS" : "",
		BIT(data, 1) ? " IBF" : "",     BIT(data, 0) ? " OBF" : "",
		machine().describe_context());
	return data;
}
Beispiel #13
0
void peribox_device::lcp_join(int slot, int state)
{
	LOGMASKED(LOG_INT, "propagating LCP from slot %d to SGCPU: %d\n", slot, state);
	if (state==ASSERT_LINE)
		m_lcp_flag |= (1 << slot);
	else
		m_lcp_flag &= ~(1 << slot);

	// Not propagated to console
	if (!m_ioport_connected)
		m_slot1_lcp((m_lcp_flag != 0)? ASSERT_LINE : CLEAR_LINE);
}
Beispiel #14
0
/*
    The INTA*, INTB*, and READY* lines are connected to each PEB card and are
    pulled up when inactive. If any card asserts the line (pulling down), the
    line state goes down. So we must keep a record which cards pull down the
    line.

    (We're doing a kind of wired-AND here.)
*/
void peribox_device::inta_join(int slot, int state)
{
	LOGMASKED(LOG_INT, "propagating INTA from slot %d to console: %d\n", slot, state);
	if (state==ASSERT_LINE)
		m_inta_flag |= (1 << slot);
	else
		m_inta_flag &= ~(1 << slot);

	if (m_ioport_connected)
		set_extint((m_inta_flag != 0)? ASSERT_LINE : CLEAR_LINE);
	else
		m_slot1_inta((m_inta_flag != 0)? ASSERT_LINE : CLEAR_LINE);
}
Beispiel #15
0
/*
    When any device pulls down READY, READY goes down.
*/
void peribox_device::ready_join(int slot, int state)
{
	LOGMASKED(LOG_READY, "Incoming READY=%d from slot %d\n", state, slot);
	// We store the inverse state
	if (state==CLEAR_LINE)
		m_ready_flag |= (1 << slot);
	else
		m_ready_flag &= ~(1 << slot);

	if (m_ioport_connected)
		set_ready((m_ready_flag != 0)? CLEAR_LINE : ASSERT_LINE);
	else
		m_slot1_ready((m_ready_flag != 0)? CLEAR_LINE : ASSERT_LINE);
}
Beispiel #16
0
void peribox_device::device_start()
{
	// Resolve the callback lines to the console
	m_slot1_inta.resolve();
	m_slot1_intb.resolve();
	m_slot1_lcp.resolve();
	m_slot1_ready.resolve();

	m_ioport_connected = (m_slot1_inta.isnull()); // TODO: init

	LOGMASKED(LOG_CONFIG, "AMA/B/C address prefix set to %05x\n", m_address_prefix);
	for (int i=2; i < 9; i++)
	{
		LOGMASKED(LOG_CONFIG, "Slot %d = %s\n", i, (m_slot[i] != nullptr)? m_slot[i]->card_name() : "empty");
	}

	save_item(NAME(m_inta_flag));
	save_item(NAME(m_intb_flag));
	save_item(NAME(m_lcp_flag));
	save_item(NAME(m_ready_flag));
	save_item(NAME(m_msast));
	save_item(NAME(m_memen));
}
Beispiel #17
0
void a2bus_echoii_device::write_c0nx(uint8_t offset, uint8_t data)
{
	// offset is completely ignored on the echoii (but not so on the echo+), so the same register maps to the entire space.
	if (m_writelatch_flag == false)
		logerror("Data in echoii latch (%02x) was clobbered with new write (%02x) before being read by speech chip!\n", m_writelatch_data, data);
	else
		LOGMASKED(LOG_WRITE,"Data written to latch of %02x\n", data);

	m_writelatch_data = data;

	m_writelatch_flag = false; // /DEVWRITE clears the latch on its falling edge
	m_tms->wsq_w(m_writelatch_flag);
	m_tms->data_w(machine().dummy_space(), 0, m_writelatch_data);
}
Beispiel #18
0
void wd33c9x_base_device::load_transfer_count()
{
	if (m_regs[COMMAND] & COMMAND_SBT) {
		m_transfer_count = 1;
	}
	else {
		m_transfer_count = (
			(uint32_t(m_regs[TRANSFER_COUNT_MSB]) << 16) |
			(uint32_t(m_regs[TRANSFER_COUNT])     <<  8) |
			(uint32_t(m_regs[TRANSFER_COUNT_LSB]) <<  0)
		);
		if (m_transfer_count == 0) {
			m_transfer_count = 1;
		}
	}
	LOGMASKED(LOG_COMMANDS, "%s: Transfer Count %d bytes\n", shortname(), m_transfer_count);
}
Beispiel #19
0
void m68340_cpu_device::update_ipl()
{
	uint8_t new_ipl = std::max({
		pit_irq_level(),
		m_serial->irq_level(),
		m_timer[0]->irq_level(),
		m_timer[1]->irq_level()
	});
	if (m_ipl != new_ipl)
	{
		if (m_ipl != 0)
			set_input_line(m_ipl, CLEAR_LINE);
		LOGMASKED(LOG_IPL, "Changing interrupt level from %d to %d\n", m_ipl, new_ipl);
		m_ipl = new_ipl;
		if (m_ipl != 0)
			set_input_line(m_ipl, ASSERT_LINE);
	}
}
Beispiel #20
0
void aic6250_device::int_msk_reg_0_w(u8 data)
{
	LOGMASKED(LOG_REG, "int_msk_reg_0_w 0x%02x\n", data);

	/*
	 * Writing a zero to Bits 0 and 1 of this register will reset the selected
	 * or reselected interrupt status in Status Register 1 (Register 08),
	 * causing the interrupt status to be lost.
	 */
	if (!(data & R03W_EN_SELECT_INT))
		m_status_reg_1 &= ~R08R_SELECTED;

	if (!(data & R03W_EN_RESEL_INT))
		m_status_reg_1 &= ~R08R_RESELECTED;

	/*
	 * This bit will be reset to 0 when the Enable Command Done interrupt bit (Reg 03, Bit 3) is set to zero.
	 */
	if (!(data & R03W_EN_CMD_DONE_INT))
		m_status_reg_1 &= ~R08R_CMD_DONE;

	if ((m_int_msk_reg_0 ^ data) & R03W_ARB_SEL_START)
	{
		if (data & R03W_ARB_SEL_START)
		{
			if (m_state != IDLE)
				fatalerror("attempted to start selection while not idle\n");

			m_state = ARB_BUS_FREE;
			m_state_timer->adjust(attotime::zero);
		}
		else
		{
			if (m_state == IDLE)
				fatalerror("attempted to abort selection while idle\n");

			m_state = IDLE;
		}
	}

	m_int_msk_reg_0 = data;

	int_check();
}
Beispiel #21
0
INPUT_PORTS_END


/****************************************************************************
    CRU handling
*****************************************************************************/

#define CRU_CONTROL_BASE 0x1ee0
#define CRU_SSTEP_BASE 0x13c0

void geneve_state::cruwrite(offs_t offset, uint8_t data)
{
	int addroff = offset << 1;

	// Single step
	// 13c0 - 13fe: 0001 0011 11xx xxx0
	if ((addroff & 0xffc0) == CRU_SSTEP_BASE)
	{
		int bit = (addroff & 0x003e)>>1;
		LOGMASKED(LOG_WARN, "Single step not implemented; bit %d set to %d\n", bit, data);
		return;
	}
Beispiel #22
0
void at_kbc_device_base::command_w(uint8_t data)
{
	if (VERBOSE & LOG_COMMAND)
	{
		switch (data)
		{
		case 0x00: case 0x01: case 0x02: case 0x03:
		case 0x04: case 0x05: case 0x06: case 0x07:
		case 0x08: case 0x09: case 0x0a: case 0x0b:
		case 0x0c: case 0x0d: case 0x0e: case 0x0f:
		case 0x10: case 0x11: case 0x12: case 0x13:
		case 0x14: case 0x15: case 0x16: case 0x17:
		case 0x18: case 0x19: case 0x1a: case 0x1b:
		case 0x1c: case 0x1d: case 0x1e: case 0x1f:
			LOGMASKED(LOG_COMMAND, "read controller ram indirect 0x%02x (%s)\n", data & 0x3f, machine().describe_context());
			break;

		case 0x20: LOGMASKED(LOG_COMMAND, "read command byte (%s)\n", machine().describe_context()); break;

				   case 0x21: case 0x22: case 0x23:
		case 0x24: case 0x25: case 0x26: case 0x27:
		case 0x28: case 0x29: case 0x2a: case 0x2b:
		case 0x2c: case 0x2d: case 0x2e: case 0x2f:
		case 0x30: case 0x31: case 0x32: case 0x33:
		case 0x34: case 0x35: case 0x36: case 0x37:
		case 0x38: case 0x39: case 0x3a: case 0x3b:
		case 0x3c: case 0x3d: case 0x3e: case 0x3f:
			LOGMASKED(LOG_COMMAND, "read controller ram offset 0x%02x (%s)\n", data & 0x3f, machine().describe_context());
			break;

		case 0x40: case 0x41: case 0x42: case 0x43:
		case 0x44: case 0x45: case 0x46: case 0x47:
		case 0x48: case 0x49: case 0x4a: case 0x4b:
		case 0x4c: case 0x4d: case 0x4e: case 0x4f:
		case 0x50: case 0x51: case 0x52: case 0x53:
		case 0x54: case 0x55: case 0x56: case 0x57:
		case 0x58: case 0x59: case 0x5a: case 0x5b:
		case 0x5c: case 0x5d: case 0x5e: case 0x5f:
			LOGMASKED(LOG_COMMAND, "write controller ram indirect 0x%02x (%s)\n", data & 0x3f, machine().describe_context());
			break;

		case 0x60: LOGMASKED(LOG_COMMAND, "write command byte (%s)\n", machine().describe_context()); break;

				   case 0x61: case 0x62: case 0x63:
		case 0x64: case 0x65: case 0x66: case 0x67:
		case 0x68: case 0x69: case 0x6a: case 0x6b:
		case 0x6c: case 0x6d: case 0x6e: case 0x6f:
		case 0x70: case 0x71: case 0x72: case 0x73:
		case 0x74: case 0x75: case 0x76: case 0x77:
		case 0x78: case 0x79: case 0x7a: case 0x7b:
		case 0x7c: case 0x7d: case 0x7e: case 0x7f:
			LOGMASKED(LOG_COMMAND, "write controller ram offset 0x%02x (%s)\n", data & 0x3f, machine().describe_context());
			break;

		case 0x90: case 0x91: case 0x92: case 0x93:
		case 0x94: case 0x95: case 0x96: case 0x97:
		case 0x98: case 0x99: case 0x9a: case 0x9b:
		case 0x9c: case 0x9d: case 0x9e: case 0x9f:
			LOGMASKED(LOG_COMMAND, "write output port 0x%1x (%s)\n", data & 0xf, machine().describe_context());
			break;

		case 0xa1: LOGMASKED(LOG_COMMAND, "get version number (%s)\n", machine().describe_context()); break;
		case 0xa4: LOGMASKED(LOG_COMMAND, "test password installed (%s)\n", machine().describe_context()); break;
		case 0xa5: LOGMASKED(LOG_COMMAND, "load security (%s)\n", machine().describe_context()); break;
		case 0xa6: LOGMASKED(LOG_COMMAND, "enable security (%s)\n", machine().describe_context()); break;
		case 0xa7: LOGMASKED(LOG_COMMAND, "disable auxiliary interface (%s)\n", machine().describe_context()); break;
		case 0xa8: LOGMASKED(LOG_COMMAND, "enable auxiliary interface (%s)\n", machine().describe_context()); break;
		case 0xa9: LOGMASKED(LOG_COMMAND, "auxiliary interface test (%s)\n", machine().describe_context()); break;
		case 0xaa: LOGMASKED(LOG_COMMAND, "controller self-test (%s)\n", machine().describe_context()); break;
		case 0xab: LOGMASKED(LOG_COMMAND, "keyboard interface test (%s)\n", machine().describe_context()); break;
		case 0xac: LOGMASKED(LOG_COMMAND, "diagnostic dump (%s)\n", machine().describe_context()); break;
		case 0xad: LOGMASKED(LOG_COMMAND, "disable keyboard interface (%s)\n", machine().describe_context()); break;
		case 0xae: LOGMASKED(LOG_COMMAND, "enable keyboard interface (%s)\n", machine().describe_context()); break;
		case 0xaf: LOGMASKED(LOG_COMMAND, "get version (%s)\n", machine().describe_context()); break;
		case 0xc0: LOGMASKED(LOG_COMMAND, "read input port (%s)\n", machine().describe_context()); break;
		case 0xc1: LOGMASKED(LOG_COMMAND, "poll input port low (%s)\n", machine().describe_context()); break;
		case 0xc2: LOGMASKED(LOG_COMMAND, "poll input port high (%s)\n", machine().describe_context()); break;
		case 0xd0: LOGMASKED(LOG_COMMAND, "read output port (%s)\n", machine().describe_context()); break;
		case 0xd1: LOGMASKED(LOG_COMMAND, "write output port (%s)\n", machine().describe_context()); break;
		case 0xd2: LOGMASKED(LOG_COMMAND, "write keyboard output buffer (%s)\n", machine().describe_context()); break;
		case 0xd3: LOGMASKED(LOG_COMMAND, "write auxiliary output buffer (%s)\n", machine().describe_context()); break;
		case 0xd4: LOGMASKED(LOG_COMMAND, "write auxiliary device (%s)\n", machine().describe_context()); break;
		case 0xe0: LOGMASKED(LOG_COMMAND, "read test inputs (%s)\n", machine().describe_context()); break;

		case 0xf0: case 0xf1: case 0xf2: case 0xf3:
		case 0xf4: case 0xf5: case 0xf6: case 0xf7:
		case 0xf8: case 0xf9: case 0xfa: case 0xfb:
		case 0xfc: case 0xfd: case 0xfe: case 0xff:
			LOGMASKED(LOG_COMMAND, "pulse output port 0x%1x (%s)\n", data & 0xf, machine().describe_context());
			break;

		default:
			LOGMASKED(LOG_COMMAND, "unknown command 0x%02x (%s)\n", data, machine().describe_context());
			break;
		}
	}
	else
		LOG("command_w 0x%02x (%s)\n", data, machine().describe_context());

	machine().scheduler().synchronize(timer_expired_delegate(FUNC(at_kbc_device_base::write_command), this), unsigned(data));
}
Beispiel #23
0
void i8155_device::register_w(int offset, uint8_t data)
{
	switch (offset & 0x07)
	{
	case REGISTER_COMMAND:
		m_command = data;

		LOGMASKED(LOG_PORT, "Port A Mode: %s\n", (data & COMMAND_PA) ? "output" : "input");
		LOGMASKED(LOG_PORT, "Port B Mode: %s\n", (data & COMMAND_PB) ? "output" : "input");

		LOGMASKED(LOG_PORT, "Port A Interrupt: %s\n", (data & COMMAND_IEA) ? "enabled" : "disabled");
		LOGMASKED(LOG_PORT, "Port B Interrupt: %s\n", (data & COMMAND_IEB) ? "enabled" : "disabled");

		switch (data & COMMAND_PC_MASK)
		{
		case COMMAND_PC_ALT_1:
			LOGMASKED(LOG_PORT, "Port C Mode: Alt 1\n");
			break;

		case COMMAND_PC_ALT_2:
			LOGMASKED(LOG_PORT, "Port C Mode: Alt 2\n");
			break;

		case COMMAND_PC_ALT_3:
			LOGMASKED(LOG_PORT, "Port C Mode: Alt 3\n");
			break;

		case COMMAND_PC_ALT_4:
			LOGMASKED(LOG_PORT, "Port C Mode: Alt 4\n");
			break;
		}

		switch (data & COMMAND_TM_MASK)
		{
		case COMMAND_TM_NOP:
			// do not affect counter operation
			break;

		case COMMAND_TM_STOP:
			// NOP if timer has not started, stop counting if the timer is running
			LOGMASKED(LOG_PORT, "Timer Command: Stop\n");
			timer_stop_count();
			break;

		case COMMAND_TM_STOP_AFTER_TC:
			// stop immediately after present TC is reached (NOP if timer has not started)
			LOGMASKED(LOG_PORT, "Timer Command: Stop after TC\n");
			break;

		case COMMAND_TM_START:
			LOGMASKED(LOG_PORT, "Timer Command: Start\n");

			if (m_timer->enabled())
			{
				// if timer is running, start the new mode and CNT length immediately after present TC is reached
			}
			else
			{
				// load mode and CNT length and start immediately after loading (if timer is not running)
				timer_reload_count();
			}
			break;
		}
		break;

	case REGISTER_PORT_A:
		write_port(PORT_A, data);
		break;

	case REGISTER_PORT_B:
		write_port(PORT_B, data);
		break;

	case REGISTER_PORT_C:
		write_port(PORT_C, data & 0x3f);
		break;

	case REGISTER_TIMER_LOW:
		m_count_length = (m_count_length & 0xff00) | data;
		break;

	case REGISTER_TIMER_HIGH:
		m_count_length = (data << 8) | (m_count_length & 0xff);
		break;
	}
}
Beispiel #24
0
void hx5102_device::update_readyff_input()
{
	LOGMASKED(LOG_READY, "MON=%d, MSP=%d, WAIT=%d, INT*=%d, DRQ*=%d, DCS=%d\n", m_motor_on, m_mspeed_on, m_wait, !m_pending_int, !m_pending_drq, m_dcs);
	m_readyff->d_w(m_motor_on && m_mspeed_on && m_wait && !m_pending_int && !m_pending_drq && m_dcs);
}
Beispiel #25
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);
	}
}
Beispiel #26
0
void wd33c9x_base_device::start_command()
{
	const uint8_t cc = m_regs[COMMAND] & COMMAND_CC;

	// Command In Progress
	//  The CIP flag being set only means that the WD33C9x is
	//  *interpreting* the contents of the Command Register.
	//  It shouldn't actually be set.
	//m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_CIP;
	if (cc > COMMAND_CC_DISCONNECT && cc != COMMAND_CC_SET_IDI) {
		m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_BSY;
	}

	switch (cc) {
	case COMMAND_CC_RESET:
		LOGMASKED(LOG_COMMANDS, "%s: Reset Command\n", shortname());
		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[OWN_ID] = m_command_length;
		memset(&m_regs[CONTROL], 0, SOURCE_ID - CONTROL);
		m_regs[COMMAND] = 0;
		m_regs[AUXILIARY_STATUS] &= ~AUXILIARY_STATUS_DBR;
		m_mode = MODE_D;
		data_fifo_reset();
		irq_fifo_reset();
		update_irq();
		set_scsi_state(FINISHED);
		irq_fifo_push((m_regs[OWN_ID] & OWN_ID_EAF) ? SCSI_STATUS_RESET_EAF : SCSI_STATUS_RESET);
		scsi_id = (m_regs[OWN_ID] & OWN_ID_SCSI_ID);
		break;

	case COMMAND_CC_ABORT:
		LOGMASKED(LOG_COMMANDS, "%s: Abort Command\n", shortname());
		set_scsi_state(FINISHED);
		// FIXME
		irq_fifo_push((m_regs[OWN_ID] & OWN_ID_EAF) ? SCSI_STATUS_RESET_EAF : SCSI_STATUS_RESET);
		break;

	case COMMAND_CC_ASSERT_ATN:
		LOGMASKED(LOG_COMMANDS, "%s: Assert ATN Command\n", shortname());
		if (m_mode != MODE_I) {
			fatalerror("%s: ASSERT_ATN command only valid in the Initiator state.", shortname());
		}
		scsi_bus->ctrl_w(scsi_refid, S_ATN, S_ATN);
		return;

	case COMMAND_CC_NEGATE_ACK:
		LOGMASKED(LOG_COMMANDS, "%s: Negate ACK Command\n", shortname());
		// FIXME - This is causing problems, so ignore for now.
		//if (m_mode != MODE_I) {
		//  fatalerror("NEGATE_ACK command only valid in the Initiator state.");
		//}
		scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
		return;

	case COMMAND_CC_DISCONNECT:
		LOGMASKED(LOG_COMMANDS, "%s: Disconnect Command\n", shortname());
		scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
		scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL);
		m_mode = MODE_D;
		set_scsi_state(IDLE);
		m_regs[AUXILIARY_STATUS] &= ~(AUXILIARY_STATUS_CIP | AUXILIARY_STATUS_BSY);
		break;

	case COMMAND_CC_SELECT:
	case COMMAND_CC_SELECT_ATN:
		LOGMASKED(LOG_COMMANDS, "%s: %s Command\n", shortname(), select_strings[cc - COMMAND_CC_SELECT_ATN]);
		if (m_mode != MODE_D) {
			fatalerror("Select commands only valid in the Disconnected state.");
		}
		set_scsi_state((ARB_WAIT_BUS_FREE << SUB_SHIFT) | DISC_SEL_ARBITRATION);
		break;

	case COMMAND_CC_SELECT_TRANSFER:
	case COMMAND_CC_SELECT_ATN_TRANSFER:
		LOGMASKED(LOG_COMMANDS, "%s: %s Command\n", shortname(), select_strings[cc - COMMAND_CC_SELECT_ATN]);
		if (m_mode == MODE_D) {
			set_scsi_state((ARB_WAIT_BUS_FREE << SUB_SHIFT) | DISC_SEL_ARBITRATION);
			m_regs[COMMAND_PHASE] = COMMAND_PHASE_ZERO;
		}
		else if (m_mode == MODE_I) {
			set_scsi_state(INIT_XFR);
		}
		else {
			fatalerror("%s: Select-and-Transfer commands only valid in the Disconnected and Initiator states.", shortname());
		}
		set_command_length(cc);
		load_transfer_count();
		break;

	case COMMAND_CC_TRANSFER_INFO:
		LOGMASKED(LOG_COMMANDS, "%s: Transfer Info Command\n", shortname());
		if (m_mode != MODE_I) {
			fatalerror("%s: TRANSFER_INFO command only valid in the Initiator state.", shortname());
		}
		m_regs[AUXILIARY_STATUS] &= ~AUXILIARY_STATUS_DBR;
		set_scsi_state(INIT_XFR);
		set_command_length(COMMAND_CC_TRANSFER_INFO);
		load_transfer_count();
		m_xfr_phase = (scsi_bus->ctrl_r() & S_PHASE_MASK);
		step(false);
		return;

	default:
		fatalerror("%s: Unimplemented command: 0x%02x", shortname(), cc);
		break;
	}

	delay(1);
}
Beispiel #27
0
void wd33c9x_base_device::set_scsi_state(uint16_t state)
{
	LOGMASKED(LOG_STEP, "%s: SCSI state change: %x to %x\n", shortname(), m_scsi_state, state);
	m_scsi_state = state;
}