Exemplo n.º 1
0
void z80ctc_irq_reti(int which)
{
	z80ctc *ctc = ctcs + which;
	int ch;

	/* loop over all channels */
	for (ch = 0; ch < 4; ch++)

		/* find the first channel with an IEO pending */
		if (ctc->int_state[ch] & Z80_DAISY_IEO)
		{
			VPRINTF(("CTC IRQReti ch%d\n", ch));

			/* clear the IEO state and update the IRQs */
			ctc->int_state[ch] &= ~Z80_DAISY_IEO;
			interrupt_check(which);
			return;
		}

	logerror("z80ctc_irq_reti: failed to find an interrupt to clear IEO on!\n");
}
Exemplo n.º 2
0
void z80ctc_device::z80daisy_irq_reti()
{
	// loop over all channels
	for (int ch = 0; ch < 4; ch++)
	{
		ctc_channel &channel = m_channel[ch];

		// find the first channel with an IEO pending
		if (channel.m_int_state & Z80_DAISY_IEO)
		{
			VPRINTF(("CTC IRQReti ch%d\n", ch));

			// clear the IEO state and update the IRQs
			channel.m_int_state &= ~Z80_DAISY_IEO;
			interrupt_check();
			return;
		}
	}

	//logerror("z80ctc_irq_reti: failed to find an interrupt to clear IEO on!\n");
}
Exemplo n.º 3
0
void z80sio_d_w(int which, int ch, UINT8 data)
{
	z80sio *sio = sios + which;
	sio_channel *chan = &sio->chan[ch];

	VPRINTF(("%04X:sio_data_w(%c) = %02X\n", activecpu_get_pc(), 'A' + ch, data));

	/* if tx not enabled, just ignore it */
	if (!(chan->regs[5] & SIO_WR5_TX_ENABLE))
		return;

	/* update the status register */
	chan->status[0] &= ~SIO_RR0_TX_BUFFER_EMPTY;

	/* reset the transmit interrupt */
	sio->int_state[INT_CHA_TRANSMIT - 4*ch] &= ~Z80_DAISY_INT;
	interrupt_check(sio);

	/* stash the character */
	chan->outbuf = data;
}
Exemplo n.º 4
0
static void reset_channel(z80sio *sio, int ch)
{
	attotime tpc = compute_time_per_character(sio, ch);
	sio_channel *chan = &sio->chan[ch];

	chan->status[0] = SIO_RR0_TX_BUFFER_EMPTY;
	chan->status[1] = 0x00;
	chan->status[2] = 0x00;
	chan->int_on_next_rx = 0;
	chan->outbuf = -1;

	sio->int_state[0 + 4*ch] = 0;
	sio->int_state[1 + 4*ch] = 0;
	sio->int_state[2 + 4*ch] = 0;
	sio->int_state[3 + 4*ch] = 0;

	interrupt_check(sio);

	/* start the receive timer running */
	timer_adjust(chan->receive_timer, tpc, ((sio - sios) << 1) | ch, tpc);
}
Exemplo n.º 5
0
int z80ctc_device::z80daisy_irq_ack()
{
	// loop over all channels
	for (int ch = 0; ch < 4; ch++)
	{
		ctc_channel &channel = m_channel[ch];

		// find the first channel with an interrupt requested
		if (channel.m_int_state & Z80_DAISY_INT)
		{
			VPRINTF(("CTC IRQAck ch%d\n", ch));

			// clear interrupt, switch to the IEO state, and update the IRQs
			channel.m_int_state = Z80_DAISY_IEO;
			interrupt_check();
			return m_vector + ch * 2;
		}
	}

	//logerror("z80ctc_irq_ack: failed to find an interrupt to ack!\n");
	return m_vector;
}
Exemplo n.º 6
0
int z80ctc_irq_ack(int which)
{
	z80ctc *ctc = ctcs + which;
	int ch;

	/* loop over all channels */
	for (ch = 0; ch < 4; ch++)

		/* find the first channel with an interrupt requested */
		if (ctc->int_state[ch] & Z80_DAISY_INT)
		{
			VPRINTF(("CTC IRQAck ch%d\n", ch));

			/* clear interrupt, switch to the IEO state, and update the IRQs */
			ctc->int_state[ch] = Z80_DAISY_IEO;
			interrupt_check(which);
			return ctc->vector + ch * 2;
		}

	logerror("z80ctc_irq_ack: failed to find an interrupt to ack!\n");
	return ctc->vector;
}
Exemplo n.º 7
0
int z80dma_device::z80daisy_irq_ack()
{
	if (m_ip)
	{
	    if (LOG) logerror("Z80DMA '%s' Interrupt Acknowledge\n", tag());

		// clear interrupt pending flag
		m_ip = 0;
	    interrupt_check();

		// set interrupt under service flag
		m_ius = 1;

		// disable DMA
		m_dma_enabled = 0;

		return m_vector;
	}

	logerror("z80dma_irq_ack: failed to find an interrupt to ack!\n");

	return 0;
}
Exemplo n.º 8
0
void z80dma_device::trigger_interrupt(int level)
{
	if (!m_ius && INTERRUPT_ENABLE)
	{
		// set interrupt pending flag
		m_ip = 1;

		// set interrupt vector
		if (STATUS_AFFECTS_VECTOR)
		{
			m_vector = (INTERRUPT_VECTOR & 0xf9) | (level << 1);
		}
		else
		{
			m_vector = INTERRUPT_VECTOR;
		}

		m_status &= ~0x08;

		if (LOG) logerror("Z80DMA '%s' Interrupt Pending\n", tag());

		interrupt_check();
	}
}
Exemplo n.º 9
0
static void timercallback(int param)
{
	int which = param >> 2;
	int ch = param & 3;
	z80ctc *ctc = ctcs + which;

	/* down counter has reached zero - see if we should interrupt */
	if ((ctc->mode[ch] & INTERRUPT) == INTERRUPT_ON)
	{
		ctc->int_state[ch] |= Z80_DAISY_INT;
		VPRINTF(("CTC timer ch%d\n", ch));
		interrupt_check(which);
	}

	/* generate the clock pulse */
	if (ctc->zc[ch])
	{
		(*ctc->zc[ch])(0,1);
		(*ctc->zc[ch])(0,0);
	}

	/* reset the down counter */
	ctc->down[ch] = ctc->tconst[ch];
}
Exemplo n.º 10
0
void z80dma_device::write(UINT8 data)
{
	if (LOG) logerror("Z80DMA '%s' Write %02x\n", tag(), data);

	if (m_num_follow == 0)
	{
		m_reset_pointer = 0;

		if ((data & 0x87) == 0) // WR2
		{
			WR2 = data;
			if (data & 0x40)
				m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_TIMING);
		}
		else if ((data & 0x87) == 0x04) // WR1
		{
			WR1 = data;
			if (data & 0x40)
				m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_TIMING);
		}
		else if ((data & 0x80) == 0) // WR0
		{
			WR0 = data;
			if (data & 0x08)
				m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_ADDRESS_L);
			if (data & 0x10)
				m_regs_follow[m_num_follow++] = GET_REGNUM(PORTA_ADDRESS_H);
			if (data & 0x20)
				m_regs_follow[m_num_follow++] = GET_REGNUM(BLOCKLEN_L);
			if (data & 0x40)
				m_regs_follow[m_num_follow++] = GET_REGNUM(BLOCKLEN_H);
		}
		else if ((data & 0x83) == 0x80) // WR3
		{
			WR3 = data;
			if (data & 0x08)
				m_regs_follow[m_num_follow++] = GET_REGNUM(MASK_BYTE);
			if (data & 0x10)
				m_regs_follow[m_num_follow++] = GET_REGNUM(MATCH_BYTE);
		}
		else if ((data & 0x83) == 0x81) // WR4
		{
			WR4 = data;
			if (data & 0x04)
				m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_ADDRESS_L);
			if (data & 0x08)
				m_regs_follow[m_num_follow++] = GET_REGNUM(PORTB_ADDRESS_H);
			if (data & 0x10)
				m_regs_follow[m_num_follow++] = GET_REGNUM(INTERRUPT_CTRL);
		}
		else if ((data & 0xC7) == 0x82) // WR5
		{
			WR5 = data;
		}
		else if ((data & 0x83) == 0x83) // WR6
		{
			m_dma_enabled = 0;

			WR6 = data;

			switch (data)
			{
				case COMMAND_ENABLE_AFTER_RETI:
					fatalerror("Z80DMA '%s' Unimplemented WR6 command %02x", tag(), data);
					break;
				case COMMAND_READ_STATUS_BYTE:
					if (LOG) logerror("Z80DMA '%s' CMD Read status Byte\n", tag());
        			READ_MASK = 0;
        			break;
				case COMMAND_RESET_AND_DISABLE_INTERRUPTS:
					WR3 &= ~0x20;
					m_ip = 0;
					m_ius = 0;
					m_force_ready = 0;
					m_status |= 0x08;
					break;
				case COMMAND_INITIATE_READ_SEQUENCE:
					if (LOG) logerror("Z80DMA '%s' Initiate Read Sequence\n", tag());
					m_read_cur_follow = m_read_num_follow = 0;
					if(READ_MASK & 0x01) { m_read_regs_follow[m_read_num_follow++] = m_status; }
					if(READ_MASK & 0x02) { m_read_regs_follow[m_read_num_follow++] = BLOCKLEN_L; } //byte counter (low)
					if(READ_MASK & 0x04) { m_read_regs_follow[m_read_num_follow++] = BLOCKLEN_H; } //byte counter (high)
					if(READ_MASK & 0x08) { m_read_regs_follow[m_read_num_follow++] = PORTA_ADDRESS_L; } //port A address (low)
					if(READ_MASK & 0x10) { m_read_regs_follow[m_read_num_follow++] = PORTA_ADDRESS_H; } //port A address (high)
					if(READ_MASK & 0x20) { m_read_regs_follow[m_read_num_follow++] = PORTB_ADDRESS_L; } //port B address (low)
					if(READ_MASK & 0x40) { m_read_regs_follow[m_read_num_follow++] = PORTB_ADDRESS_H; } //port B address (high)
					break;
				case COMMAND_RESET:
					if (LOG) logerror("Z80DMA '%s' Reset\n", tag());
					m_dma_enabled = 0;
					m_force_ready = 0;
					m_ip = 0;
					m_ius = 0;
					interrupt_check();
					// Needs six reset commands to reset the DMA
					{
						UINT8 WRi;

						for(WRi=0;WRi<7;WRi++)
							REG(WRi,m_reset_pointer) = 0;

						m_reset_pointer++;
						if(m_reset_pointer >= 6) { m_reset_pointer = 0; }
					}
					m_status = 0x38;
					break;
				case COMMAND_LOAD:
					m_force_ready = 0;
					m_addressA = PORTA_ADDRESS;
					m_addressB = PORTB_ADDRESS;
					m_count = BLOCKLEN;
					m_status |= 0x30;
					if (LOG) logerror("Z80DMA '%s' Load A: %x B: %x N: %x\n", tag(), m_addressA, m_addressB, m_count);
					break;
				case COMMAND_DISABLE_DMA:
					if (LOG) logerror("Z80DMA '%s' Disable DMA\n", tag());
					m_dma_enabled = 0;
					break;
				case COMMAND_ENABLE_DMA:
					if (LOG) logerror("Z80DMA '%s' Enable DMA\n", tag());
					m_dma_enabled = 1;
					update_status();
					break;
				case COMMAND_READ_MASK_FOLLOWS:
					if (LOG) logerror("Z80DMA '%s' Set Read Mask\n", tag());
					m_regs_follow[m_num_follow++] = GET_REGNUM(READ_MASK);
					break;
				case COMMAND_CONTINUE:
					if (LOG) logerror("Z80DMA '%s' Continue\n", tag());
					m_count = BLOCKLEN;
					m_dma_enabled = 1;
					//"match not found" & "end of block" status flags zeroed here
					m_status |= 0x30;
					break;
				case COMMAND_RESET_PORT_A_TIMING:
					if (LOG) logerror("Z80DMA '%s' Reset Port A Timing\n", tag());
					PORTA_TIMING = 0;
					break;
				case COMMAND_RESET_PORT_B_TIMING:
					if (LOG) logerror("Z80DMA '%s' Reset Port B Timing\n", tag());
					PORTB_TIMING = 0;
					break;
				case COMMAND_FORCE_READY:
					if (LOG) logerror("Z80DMA '%s' Force Ready\n", tag());
					m_force_ready = 1;
					update_status();
					break;
				case COMMAND_ENABLE_INTERRUPTS:
					if (LOG) logerror("Z80DMA '%s' Enable IRQ\n", tag());
					WR3 |= 0x20;
					break;
				case COMMAND_DISABLE_INTERRUPTS:
					if (LOG) logerror("Z80DMA '%s' Disable IRQ\n", tag());
					WR3 &= ~0x20;
					break;
				case COMMAND_REINITIALIZE_STATUS_BYTE:
					if (LOG) logerror("Z80DMA '%s' Reinitialize status byte\n", tag());
					m_status |= 0x30;
					m_ip = 0;
					break;
				case 0xFB:
					if (LOG) logerror("Z80DMA '%s' undocumented command triggered 0x%02X!\n", tag(), data);
					break;
				default:
					fatalerror("Z80DMA '%s' Unknown WR6 command %02x", tag(), data);
			}
		}
		else
			fatalerror("Z80DMA '%s' Unknown base register %02x", tag(), data);
		m_cur_follow = 0;
	}
	else
	{
		int nreg = m_regs_follow[m_cur_follow];
		m_regs[nreg] = data;
		m_cur_follow++;
		if (m_cur_follow>=m_num_follow)
			m_num_follow = 0;
		if (nreg == REGNUM(4,3))
		{
			m_num_follow=0;
			if (data & 0x08)
				m_regs_follow[m_num_follow++] = GET_REGNUM(PULSE_CTRL);
			if (data & 0x10)
				m_regs_follow[m_num_follow++] = GET_REGNUM(INTERRUPT_VECTOR);
			m_cur_follow = 0;
		}

		m_reset_pointer++;
		if(m_reset_pointer >= 6) { m_reset_pointer = 0; }
	}
}
Exemplo n.º 11
0
void z80sio_c_w(int which, int ch, UINT8 data)
{
	z80sio *sio = sios + which;
	sio_channel *chan = &sio->chan[ch];
	int reg = chan->regs[0] & 7;
	UINT8 old = chan->regs[reg];

	if (reg != 0 || (reg & 0xf8))
		VPRINTF(("%04X:sio_reg_w(%c,%d) = %02X\n", activecpu_get_pc(), 'A' + ch, reg, data));

	/* write a new value to the selected register */
	chan->regs[reg] = data;

	/* clear the register number for the next write */
	if (reg != 0)
		chan->regs[0] &= ~7;

	/* switch off the register for live state changes */
	switch (reg)
	{
		/* SIO write register 0 */
		case 0:
			switch (data & SIO_WR0_COMMAND_MASK)
			{
				case SIO_WR0_COMMAND_CH_RESET:
					VPRINTF(("%04X:SIO reset channel %c\n", activecpu_get_pc(), 'A' + ch));
					reset_channel(sio, ch);
					break;

				case SIO_WR0_COMMAND_RES_STATUS_INT:
					sio->int_state[INT_CHA_STATUS - 4*ch] &= ~Z80_DAISY_INT;
					interrupt_check(sio);
					break;

				case SIO_WR0_COMMAND_ENA_RX_INT:
					chan->int_on_next_rx = TRUE;
					interrupt_check(sio);
					break;

				case SIO_WR0_COMMAND_RES_TX_INT:
					sio->int_state[INT_CHA_TRANSMIT - 4*ch] &= ~Z80_DAISY_INT;
					interrupt_check(sio);
					break;

				case SIO_WR0_COMMAND_RES_ERROR:
					sio->int_state[INT_CHA_ERROR - 4*ch] &= ~Z80_DAISY_INT;
					interrupt_check(sio);
					break;
			}
			break;

		/* SIO write register 1 */
		case 1:
			interrupt_check(sio);
			break;

		/* SIO write register 5 */
		case 5:
			if (((old ^ data) & SIO_WR5_DTR) && sio->dtr_changed_cb)
				(*sio->dtr_changed_cb)(ch, (data & SIO_WR5_DTR) != 0);
			if (((old ^ data) & SIO_WR5_SEND_BREAK) && sio->break_changed_cb)
				(*sio->break_changed_cb)(ch, (data & SIO_WR5_SEND_BREAK) != 0);
			if (((old ^ data) & SIO_WR5_RTS) && sio->rts_changed_cb)
				(*sio->rts_changed_cb)(ch, (data & SIO_WR5_RTS) != 0);
			break;
	}
}