Beispiel #1
0
void ncr5390_device::bus_complete()
{
	state = IDLE;
	istatus |= I_BUS;
	dma_set(DMA_NONE);
	check_irq();
}
Beispiel #2
0
void i8x9x_device::serial_w(UINT8 val)
{
	sbuf = val;
	sp_stat |= 0x40;
	pending_irq |= IRQ_SERIAL;
	check_irq();
}
Beispiel #3
0
void dp8390_device::do_tx() {
	dynamic_buffer buf;
	int i;
	UINT32 high16 = (m_regs.dcr & 4)?m_regs.rsar<<16:0;
	if(m_reset) return;
	if(LOOPBACK) return;  // TODO: loopback
	m_regs.tsr = 0;
	if(m_regs.tbcr > 1518) logerror("dp8390: trying to send overlong frame\n");
	if(!m_regs.tbcr) { // ? Bochs says solaris actually does this
		m_regs.tsr = 1;
		m_regs.cr &= ~4;
		return;
	}

	buf.resize(m_regs.tbcr);
	for(i = 0; i < m_regs.tbcr; i++) buf[i] = m_mem_read_cb(high16 + (m_regs.tpsr << 8) + i);

	if(send(&buf[0], m_regs.tbcr)) {
		m_regs.tsr = 1;
		m_regs.isr |= 2;
	} else {
		m_regs.tsr = 8; // not quite right but there isn't a generic "tx failed"
		m_regs.isr |= 8;
	}
	m_regs.cr &= ~4;
	check_irq();
}
Beispiel #4
0
void dp8390_device::recv_overflow() {
	m_regs.rsr = 0x10;
	m_regs.isr |= 0x10;
	check_irq();
	m_regs.cntr2++;
	return;
}
Beispiel #5
0
void msx_state::msx_irq_source(int source, int level)
{
	assert(source >= 0 && source < ARRAY_LENGTH(m_irq_state));

	m_irq_state[source] = level;
	check_irq();
}
Beispiel #6
0
void dp8390_device::recv(UINT8 *buf, int len) {
	int i;
	UINT16 start = (m_regs.curr << 8), offset;
	UINT32 high16;
	if(m_reset) return;
	if(m_regs.curr == m_regs.pstop) start = m_regs.pstart << 8;
	offset = start + 4;
	high16 = (m_regs.dcr & 4)?m_regs.rsar<<16:0;
	if(buf[0] & 1) {
		if(!(m_regs.rcr & 4) && !memcmp((const char *)buf, "\xff\xff\xff\xff\xff\xff", 6)) return;
		m_regs.rsr = 0x20;
	} else m_regs.rsr = 0;
	len &= 0xffff;

	for(i = 0; i < len; i++) {
		mem_write(high16 + offset, buf[i]);
		offset++;
		if(!(offset & 0xff)) {
			if((offset >> 8) == m_regs.pstop) offset = m_regs.pstart << 8;
			if((offset >> 8) == m_regs.bnry) return recv_overflow();
		}
	}
	m_regs.rsr |= 1;
	m_regs.isr |= 1;
	m_regs.curr = (offset >> 8) + ((offset & 0xff)?1:0);
	if(m_regs.curr == m_regs.pstop) m_regs.curr = m_regs.pstart;
	len += 4;
	mem_write(start, m_regs.rsr);
	mem_write(start+1, m_regs.curr);
	mem_write(start+2, len & 0xff);
	mem_write(start+3, len >> 8);
	check_irq();
}
Beispiel #7
0
void ncr5390_device::function_complete()
{
	state = IDLE;
	istatus |= I_FUNCTION;
	dma_set(DMA_NONE);
	check_irq();
}
Beispiel #8
0
void i8x9x_device::serial_send_done()
{
	serial_send_timer = 0;
	io->write_word(SERIAL*2, serial_send_buf);
	pending_irq |= IRQ_SERIAL;
	sp_stat |= 0x20;
	check_irq();
}
Beispiel #9
0
void msx_state::machine_reset()
{
	msx_memory_reset ();
	msx_memory_map_all ();
	for (auto & elem : m_irq_state)
	{
		elem = CLEAR_LINE;
	}
	check_irq();
}
Beispiel #10
0
void msx_state::msx_ch_reset_core ()
{
	msx_memory_reset ();
	msx_memory_map_all ();
	for (int i = 0; i < ARRAY_LENGTH(m_irq_state); i++)
	{
		m_irq_state[i] = CLEAR_LINE;
	}
	check_irq();
}
Beispiel #11
0
void mcs96_device::execute_set_input(int inputnum, int state)
{
    switch(inputnum) {
    case EXINT_LINE:
        if(state)
            pending_irq |= 0x80;
        else
            pending_irq &= 0x7f;
        check_irq();
        break;
    }
}
Beispiel #12
0
void i8x9x_device::trigger_cam(int id, UINT64 current_time)
{
	hso_cam_entry &cam = hso_info[id];
	cam.active = false;
	switch(cam.command & 0x0f) {
	case 0x8: case 0x9: case 0xa: case 0xb:
		ios1 |= 1 << (cam.command & 3);
		pending_irq |= IRQ_SOFT;
		check_irq();
		break;

	default:
		logerror("%s: Action %x unimplemented\n", tag(), cam.command & 0x0f);
		break;
	}
}
Beispiel #13
0
void lh5801_cpu_device::execute_run()
{
	do
	{
		check_irq();

		if (m_idle)
			m_icount = 0;
		else
		{
			m_oldpc = P;

			debugger_instruction_hook(this, P);
			lh5801_instruction();
		}

	} while (m_icount > 0);
}
Beispiel #14
0
void dp8390_device::recv(UINT8 *buf, int len) {
	int i;
	UINT16 start = (m_regs.curr << 8), offset;
	UINT32 high16;
	if(m_reset) return;
	if(m_regs.curr == m_regs.pstop) start = m_regs.pstart << 8;
	offset = start + 4;
	high16 = (m_regs.dcr & 4)?m_regs.rsar<<16:0;
	if(buf[0] & 1) {
		if(!memcmp((const char *)buf, "\xff\xff\xff\xff\xff\xff", 6)) {
			if(!(m_regs.rcr & 4)) return;
		} else return; // multicast
		m_regs.rsr = 0x20;
	} else m_regs.rsr = 0;
	len &= 0xffff;

	for(i = 0; i < len; i++) {
		m_mem_write_cb(high16 + offset, buf[i]);
		offset++;
		if(!(offset & 0xff)) {
			if((offset >> 8) == m_regs.pstop) offset = m_regs.pstart << 8;
			if((offset >> 8) == m_regs.bnry) return recv_overflow();
		}
	}
	if(len < 60) {
		// this can't pass to the next page
		for(; i < 60; i++) {
			m_mem_write_cb(high16 + offset, 0);
			offset++;
		}
		len = 60;
	}

	m_regs.rsr |= 1;
	m_regs.isr |= 1;
	m_regs.curr = (offset >> 8) + ((offset & 0xff)?1:0);
	if(m_regs.curr == m_regs.pstop) m_regs.curr = m_regs.pstart;
	len += 4;
	m_mem_write_cb((offs_t)start, m_regs.rsr);
	m_mem_write_cb((offs_t)start+1, m_regs.curr);
	m_mem_write_cb((offs_t)start+2, len & 0xff);
	m_mem_write_cb((offs_t)start+3, len >> 8);
	check_irq();
}
Beispiel #15
0
static CPU_EXECUTE( lh5801 )
{
	lh5801_state *cpustate = get_safe_token(device);

	do
	{
		check_irq(device);

		if (cpustate->idle)
			cpustate->icount = 0;
		else
		{
			cpustate->oldpc = P;

			debugger_instruction_hook(device, P);
			lh5801_instruction(cpustate);
		}

	} while (cpustate->icount > 0);
}
Beispiel #16
0
void pc_fdc_family_device::irq_w(bool state)
{
	fdc_irq = state;
	check_irq();
}
Beispiel #17
0
void i8x9x_device::io_w8(UINT8 adr, UINT8 data)
{
	switch(adr) {
	case 0x02:
		ad_command = data;
		if(ad_command & 8)
			ad_start(get_cycle());
		break;
	case 0x03:
		logerror("%s: hsi_mode %02x (%04x)\n", tag(), data, PPC);
		break;
	case 0x04:
		hso_time = (hso_time & 0xff00) | data;
		break;
	case 0x05:
		hso_time = (hso_time & 0x00ff) | (data << 8);
		commit_hso_cam();
		break;
	case 0x06:
		hso_command = data;
		break;
	case 0x07:
		logerror("%s: sbuf %02x (%04x)\n", tag(), data, PPC);
		serial_send(data);
		break;
	case 0x08:
		PSW = (PSW & 0xff00) | data;
		check_irq();
		break;
	case 0x09:
		pending_irq = data;
		logerror("%s: int_pending %02x (%04x)\n", tag(), data, PPC);
		break;
	case 0x0a:
		logerror("%s: watchdog %02x (%04x)\n", tag(), data, PPC);
		break;
	case 0x0e:
		logerror("%s: baud rate %02x (%04x)\n", tag(), data, PPC);
		break;
	case 0x0f:
		logerror("%s: io port 1 %02x (%04x)\n", tag(), data, PPC);
		io->write_word(P1*2, data);
		break;
	case 0x10:
		logerror("%s: io port 2 %02x (%04x)\n", tag(), data, PPC);
		io->write_word(P2*2, data);
		break;
	case 0x11:
		logerror("%s: sp con %02x (%04x)\n", tag(), data, PPC);
		break;
	case 0x15:
		logerror("%s: ioc0 %02x (%04x)\n", tag(), data, PPC);
		ioc0 = data;
		break;
	case 0x16:
		logerror("%s: ioc1 %02x (%04x)\n", tag(), data, PPC);
		ioc1 = data;
		break;
	case 0x17:
		logerror("%s: pwm control %02x (%04x)\n", tag(), data, PPC);
		break;
	}
	return;
}
Beispiel #18
0
void dp8390_device::check_dma_complete() {
	if(m_regs.rbcr) return;
	m_regs.isr |= 0x40;
	check_irq();
	m_rdma_active = 0;
}
Beispiel #19
0
Point ADS7843 :: getpos(uint8_t *flag)
{
	Point p[ADS7843_READ_TIMES];
	Point P;
	int i;
	int k,j,x_tmp, y_tmp;
	uint32_t sum_x, sum_y;
//	uint16_t tmp;
	
	i=0; sum_x = 0; sum_y = 0;
	
	while(check_irq()){
		
		getPosOnce( (uint16_t *)(&(p[i].x)), (uint16_t *)(&(p[i].y)) );
		
		i++;
		if(i==ADS7843_READ_TIMES){
			/** sort here */
			
			for(k=0; k<ADS7843_READ_TIMES-1; k++){
				for(j=k+1; j<=ADS7843_READ_TIMES; j++){
					if(p[k].x > p[j].x){
						x_tmp = p[j].x;
						p[j].x=p[k].x;
						p[k].x=x_tmp;
					}
					if(p[k].y > p[j].y){
						y_tmp = p[j].y;
						p[j].y=p[k].y;
						p[k].y=y_tmp;
					}
				}
			}

#if ADS7843_DEBUG
			for(k=0; k<ADS7843_READ_TIMES; k++){
				Serial.print(p[k].x);
				Serial.print(" ");
				Serial.print(p[k].y);
				Serial.print(" ");
			}
			Serial.println(" ");
#endif

			for(k=ADS7843_LOST_VAL; k<(ADS7843_READ_TIMES-ADS7843_LOST_VAL); k++){
				sum_x += (uint32_t)p[k].x;
				sum_y += (uint32_t)p[k].y;
			}
			
			sum_x /= (ADS7843_READ_TIMES - 2*ADS7843_LOST_VAL);
			sum_y /= (ADS7843_READ_TIMES - 2*ADS7843_LOST_VAL);
			
#if ADS7843_DEBUG
			Serial.print("SUM:");
			Serial.print(sum_x, DEC);
			Serial.print("   ");
			Serial.print(sum_y, DEC);
			Serial.println();
#endif
			P.x = (uint16_t)sum_x;
			P.y = (uint16_t)sum_y;;

#if ADS7843_DEBUG
			Serial.print("I:");
			Serial.print(P.x, DEC);
			Serial.print("   ");
			Serial.print(P.y, DEC);
			Serial.println();
			Serial.print("C:");
#endif
			*flag = 1;
			return P;
		}
	}
	*flag = 0;
	return P;
}
Beispiel #20
0
void ncr5390_device::step(bool timeout)
{
	UINT32 ctrl = scsi_bus->ctrl_r();
	UINT32 data = scsi_bus->data_r();
	UINT8 c     = command[0] & 0x7f;

	if(0)
		logerror("%s: state=%d.%d %s\n",
					tag(), state & STATE_MASK, (state & SUB_MASK) >> SUB_SHIFT,
					timeout ? "timeout" : "change");

	if(mode == MODE_I && !(ctrl & S_BSY)) {
		state = IDLE;
		istatus |= I_DISCONNECT;
		reset_disconnect();
		check_irq();
	}
	switch(state & SUB_MASK ? state & SUB_MASK : state & STATE_MASK) {
	case IDLE:
		break;

	case ARB_COMPLETE << SUB_SHIFT: {
		if(!timeout)
			break;

		int win;
		for(win=7; win>=0 && !(data & (1<<win)); win--);
		if(win != scsi_id) {
			scsi_bus->data_w(scsi_refid, 0);
			scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
			fatalerror("need to wait for bus free\n");
			break;
		}
		state = (state & STATE_MASK) | (ARB_ASSERT_SEL << SUB_SHIFT);
		scsi_bus->ctrl_w(scsi_refid, S_SEL, S_SEL);
		delay(6);
		break;
	}

	case ARB_ASSERT_SEL << SUB_SHIFT:
		if(!timeout)
			break;

		scsi_bus->data_w(scsi_refid, (1<<scsi_id) | (1<<bus_id));
		state = (state & STATE_MASK) | (ARB_SET_DEST << SUB_SHIFT);
		delay_cycles(4);
		break;

	case ARB_SET_DEST << SUB_SHIFT:
		if(!timeout)
			break;

		state = (state & STATE_MASK) | (ARB_RELEASE_BUSY << SUB_SHIFT);
		scsi_bus->ctrl_w(scsi_refid, c == CD_SELECT_ATN || c == CD_SELECT_ATN_STOP ? S_ATN : 0, S_ATN|S_BSY);
		delay(2);
		break;

	case ARB_RELEASE_BUSY << SUB_SHIFT:
		if(!timeout)
			break;

		if(ctrl & S_BSY) {
			state = (state & STATE_MASK) | (ARB_DESKEW_WAIT << SUB_SHIFT);
			if(c == CD_RESELECT)
				scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY);
			delay_cycles(2);
		} else {
			state = (state & STATE_MASK) | (ARB_TIMEOUT_BUSY << SUB_SHIFT);
#ifdef DELAY_HACK
			delay(1);
#else
			delay(8192*select_timeout);
#endif
		}
		break;

	case ARB_DESKEW_WAIT << SUB_SHIFT:
		if(!timeout)
			break;

		scsi_bus->data_w(scsi_refid, 0);
		scsi_bus->ctrl_w(scsi_refid, 0, S_SEL);

		if(c == CD_RESELECT) {
			logerror("%s: mode switch to Target\n", tag());
			mode = MODE_T;
		} else {
			logerror("%s: mode switch to Initiator\n", tag());
			mode = MODE_I;
		}
		state &= STATE_MASK;
		step(true);
		break;

	case ARB_TIMEOUT_BUSY << SUB_SHIFT:
		if(timeout) {
			scsi_bus->data_w(scsi_refid, 0);
			logerror("%s: select timeout\n", tag());
			state = (state & STATE_MASK) | (ARB_TIMEOUT_ABORT << SUB_SHIFT);
			delay(1000);
		} else if(ctrl & S_BSY) {
			state = (state & STATE_MASK) | (ARB_DESKEW_WAIT << SUB_SHIFT);
			if(c == CD_RESELECT)
				scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY);
			delay_cycles(2);
		}
		break;

	case ARB_TIMEOUT_ABORT << SUB_SHIFT:
		if(!timeout)
			break;

		if(ctrl & S_BSY) {
			state = (state & STATE_MASK) | (ARB_DESKEW_WAIT << SUB_SHIFT);
			if(c == CD_RESELECT)
				scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY);
			delay_cycles(2);
		} else {
			scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
			state = IDLE;
			istatus |= I_DISCONNECT;
			reset_disconnect();
			check_irq();
		}
		break;

	case SEND_WAIT_SETTLE << SUB_SHIFT:
		if(!timeout)
			break;

		state = (state & STATE_MASK) | (SEND_WAIT_REQ_0 << SUB_SHIFT);
		step(false);
		break;

	case SEND_WAIT_REQ_0 << SUB_SHIFT:
		if(ctrl & S_REQ)
			break;
		state = state & STATE_MASK;
		scsi_bus->data_w(scsi_refid, 0);
		scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
		step(false);
		break;

	case RECV_WAIT_REQ_1 << SUB_SHIFT:
		if(!(ctrl & S_REQ))
			break;

		state = (state & STATE_MASK) | (RECV_WAIT_SETTLE << SUB_SHIFT);
		delay_cycles(sync_period);
		break;

	case RECV_WAIT_SETTLE << SUB_SHIFT:
		if(!timeout)
			break;

		if((state & STATE_MASK) != INIT_XFR_RECV_PAD)
			fifo_push(scsi_bus->data_r());
		scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK);
		state = (state & STATE_MASK) | (RECV_WAIT_REQ_0 << SUB_SHIFT);
		step(false);
		break;

	case RECV_WAIT_REQ_0 << SUB_SHIFT:
		if(ctrl & S_REQ)
			break;
		state = state & STATE_MASK;
		step(false);
		break;

	case DISC_SEL_ARBITRATION:
		if(c == CD_SELECT) {
			state = DISC_SEL_WAIT_REQ;
			command_length = derive_msg_size(fifo[0]);
		} else
			state = DISC_SEL_ATN_WAIT_REQ;

		scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ);
		if(ctrl & S_REQ)
			step(false);
		break;

	case DISC_SEL_ATN_WAIT_REQ:
		if(!(ctrl & S_REQ))
			break;
		if((ctrl & S_PHASE_MASK) != S_PHASE_MSG_OUT) {
			function_complete();
			break;
		}
		if(c == CD_SELECT_ATN)
			scsi_bus->ctrl_w(scsi_refid, 0, S_ATN);
		state = DISC_SEL_ATN_SEND_BYTE;
		send_byte();
		break;

	case DISC_SEL_ATN_SEND_BYTE:
		if(c == CD_SELECT_ATN_STOP) {
			seq = 1;
			function_complete();
		} else {
			command_length = derive_msg_size(fifo[0]);
			state = DISC_SEL_WAIT_REQ;
		}
		break;

	case DISC_SEL_WAIT_REQ:
		if(!(ctrl & S_REQ))
			break;
		if((ctrl & S_PHASE_MASK) != S_PHASE_COMMAND) {
			if(!command_length)
				seq = 4;
			scsi_bus->ctrl_wait(scsi_refid, 0, S_REQ);
			function_bus_complete();
			break;
		}
		if(seq < 3)
			seq = 3;
		state = DISC_SEL_SEND_BYTE;
		send_byte();
		break;

	case DISC_SEL_SEND_BYTE:
		if(command_length) {
			command_length--;
			if(!command_length)
				seq = 4;
		}

		state = DISC_SEL_WAIT_REQ;
		break;

	case INIT_CPT_RECV_BYTE_ACK:
		state = INIT_CPT_RECV_WAIT_REQ;
		scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
		break;

	case INIT_CPT_RECV_WAIT_REQ:
		if(!(ctrl & S_REQ))
			break;

		if((ctrl & S_PHASE_MASK) != S_PHASE_MSG_IN) {
			command_pos = 0;
			bus_complete();
		} else {
			state = INIT_CPT_RECV_BYTE_NACK;
			recv_byte();
		}
		break;

	case INIT_CPT_RECV_BYTE_NACK:
		scsi_bus->ctrl_wait(scsi_refid, 0, S_REQ);
		function_complete();
		break;

	case INIT_MSG_WAIT_REQ:
		if((ctrl & (S_REQ|S_BSY)) == S_BSY)
			break;
		bus_complete();
		break;

	case INIT_XFR:
		switch(xfr_phase) {
		case S_PHASE_DATA_OUT:
			dma_set(DMA_OUT);
			if(tcount == 0 && fifo_pos == 1)
				scsi_bus->ctrl_w(scsi_refid, 0, S_ATN);
			state = INIT_XFR_SEND_BYTE;
			send_byte();
			break;

		case S_PHASE_DATA_IN:
			dma_set(DMA_IN);
			state = tcount == fifo_pos+1 ?
				INIT_XFR_RECV_BYTE_NACK : INIT_XFR_RECV_BYTE_ACK;
			recv_byte();
			break;

		default:
			logerror("%s: xfer on phase %d\n", tag(), scsi_bus->ctrl_r() & S_PHASE_MASK);
			function_complete();
			break;
		}
		break;

	case INIT_XFR_WAIT_REQ:
		if(!(ctrl & S_REQ))
			break;

		if((ctrl & S_PHASE_MASK) != xfr_phase) {
			command_pos = 0;
			bus_complete();
		} else {
			state = INIT_XFR;
			step(false);
		}
		break;

	case INIT_XFR_SEND_BYTE:
		if(tcount == 0 && fifo_pos == 0)
			bus_complete();
		else
			state = INIT_XFR_WAIT_REQ;
		break;

	case INIT_XFR_RECV_BYTE_ACK:
		state = INIT_XFR_WAIT_REQ;
		scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
		break;

	case INIT_XFR_RECV_BYTE_NACK:
		function_complete();
		break;

	case INIT_XFR_SEND_PAD_WAIT_REQ:
		if(!(ctrl & S_REQ))
			break;

		if((ctrl & S_PHASE_MASK) != xfr_phase) {
			command_pos = 0;
			bus_complete();
		} else {
			state = INIT_XFR_SEND_PAD;
			send_byte();
		}
		break;

	case INIT_XFR_SEND_PAD:
		tcount--;
		if(tcount) {
			state = INIT_XFR_SEND_PAD_WAIT_REQ;
			step(false);
		} else
			function_complete();
		break;

	case INIT_XFR_RECV_PAD_WAIT_REQ:
		if(!(ctrl & S_REQ))
			break;

		if((ctrl & S_PHASE_MASK) != xfr_phase) {
			command_pos = 0;
			bus_complete();
		} else {
			state = INIT_XFR_RECV_PAD;
			recv_byte();
		}
		break;

	case INIT_XFR_RECV_PAD:
		tcount--;
		if(tcount) {
			state = INIT_XFR_RECV_PAD_WAIT_REQ;
			scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
			step(false);
		} else
			function_complete();
		break;

	default:
		logerror("%s: step() unexpected state %d.%d\n",
					tag(),
					state & STATE_MASK, (state & SUB_MASK) >> SUB_SHIFT);
		exit(0);
	}
}
Beispiel #21
0
void ncr5380n_device::bus_complete()
{
	state = IDLE;
//  istatus |= I_BUS;
	check_irq();
}
Beispiel #22
0
void ncr5380n_device::function_complete()
{
	state = IDLE;
//  istatus |= I_FUNCTION;
	check_irq();
}
Beispiel #23
0
void ncr5380n_device::step(bool timeout)
{
	UINT32 ctrl = scsi_bus->ctrl_r();
	UINT32 data = scsi_bus->data_r();

	if(0)
		printf("%s: state=%d.%d %s\n",
					tag(), state & STATE_MASK, (state & SUB_MASK) >> SUB_SHIFT,
					timeout ? "timeout" : "change");

	if(mode == MODE_I && !(ctrl & S_BSY)) {
		state = IDLE;
		reset_disconnect();
		check_irq();
	}
	switch(state & SUB_MASK ? state & SUB_MASK : state & STATE_MASK) {
	case IDLE:
		break;

	case ARB_COMPLETE << SUB_SHIFT: {
		if(!timeout)
			break;

		int win;
		for(win=7; win>=0 && !(data & (1<<win)); win--);
//      printf("arb complete: data %02x win %02x scsi_id %02x\n", data, win, scsi_id);
		if(win != scsi_id) {
			scsi_bus->data_w(scsi_refid, 0);
			scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
			fatalerror("need to wait for bus free\n");
			break;
		}

		state &= STATE_MASK;
		step(true);
		break;
	}

	case SEND_WAIT_SETTLE << SUB_SHIFT:
		if(!timeout)
			break;

		state = (state & STATE_MASK) | (SEND_WAIT_REQ_0 << SUB_SHIFT);
		step(false);
		break;

	case SEND_WAIT_REQ_0 << SUB_SHIFT:
		if(ctrl & S_REQ)
			break;
		state = state & STATE_MASK;
		scsi_bus->data_w(scsi_refid, 0);
		scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
		step(false);

		// byte's done, ask for another if the target hasn't said otherwise
		if (m_mode & MODE_DMA)
		{
			drq_set();
		}
		break;

	case RECV_WAIT_REQ_1 << SUB_SHIFT:
		if(!(ctrl & S_REQ))
			break;

		state = (state & STATE_MASK) | (RECV_WAIT_SETTLE << SUB_SHIFT);
		delay_cycles(sync_period);
		break;

	case RECV_WAIT_SETTLE << SUB_SHIFT:
		if(!timeout)
			break;

		m_dmalatch = scsi_bus->data_r();
		scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK);
		state = (state & STATE_MASK) | (RECV_WAIT_REQ_0 << SUB_SHIFT);
		step(false);
		break;

	case RECV_WAIT_REQ_0 << SUB_SHIFT:
		if(ctrl & S_REQ)
			break;
		state = state & STATE_MASK;
		step(false);

		drq_set();  // raise DRQ now that we've completed
		break;

	default:
		printf("%s: step() unexpected state %d.%d\n",
					tag(),
					state & STATE_MASK, (state & SUB_MASK) >> SUB_SHIFT);
		exit(0);
	}
}