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"); }
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"); }
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; }
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); }
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; }
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; }
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; }
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(); } }
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]; }
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; } } }
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; } }