/* Copyright (C) Magna Carta Software, Inc. 1990, 1991. All Rights Reserved Z80SIOI.C -- Z-80 SIO interrupt handling routines. */ #define CCT_DEVELOPMENT #if (defined(CCTW) || defined(_WINDOWS)) #include #endif #include #include #include #if !defined(__NDPC__) #include #endif /* UZ80_DEINSTALL_IPR -- Generic Z80 family IPR deinstallation procedure. */ short uz80_deinstall_ipr_(COMM_PORT *p, WORD itype) { short i, val=0, ret=0; _disable(); /* serial interrupts could already be in use */ switch(itype) { case UZ80_ES: case MODEM_STATUS: break; case UZ80_RX_ALL: case RECEIVE: if (p->a_ipr[2] == (void FAR_ *) com_dummy_) ret = EOF; else { p->a_ipr[2] = (void FAR_ *) com_dummy_; val |= UZ80_RX_ALL; p->c_read = uz80_read_; p->rxstat = uz80_rxstat_; } break; case UZ80_TX_ALL: case TRANSMIT: if (p->a_ipr[1] == (void FAR_ *) com_dummy_) ret = EOF; else { p->a_ipr[1] = (void FAR_ *) com_dummy_; val |= UZ80_TX_ALL; p->c_write = p->c_write_; /* single byte port write function */ p->txstat = p->txstat_; } break; default: ret = EOF; break; } if (!ret) { uz80_int_set_(p, val, FALSE); for (i=0; i < MAX_IPRS; i++) if (p->a_ipr[i] != (void FAR_ *) com_dummy_) break; if (i == MAX_IPRS) { /* ALL IPRs NUKED -- DEINSTALL THE ISR */ deinstall_isr(p); } } _enable(); return (ret); } /* UZ80_DISABLE_COMM_INT -- Disable interrupts at the communications chip. */ short uz80_disable_comm_int_(COMM_PORT *p, WORD int_type) { return(uz80_int_set_(p, int_type, FALSE)); } /* UZ80_ENABLE_COMM_INT -- Enable interrupts at the communications chip. */ short uz80_enable_comm_int_(COMM_PORT *p, WORD int_type) { return(uz80_int_set_(p, int_type, TRUE)); } /* UZ80_INSTALL_IPR -- Install an interrupt processing routine. */ short uz80_install_ipr_(COMM_PORT *p, WORD itype, void FAR_ *fn, BYTE FAR_ *buf, WORD buflen) { short ret = 0; _disable(); /* serial interrupts could already be in use */ switch(itype) { case UZ80_ES: case MODEM_STATUS: #if 0 if (fn == NULL) p->a_ipr[3] = com_ls_int; else p->a_ipr[3] = fn; #endif break; case UZ80_RX_ALL: case RECEIVE: itype = UZ80_RX_ALL; if (fn == NULL) p->a_ipr[2] = (void FAR_ *) uz80_rx_int_; else p->a_ipr[2] = fn; p->rxbufhead = p->rxbuftail = p->rxbuf = buf; p->rx_bufsiz = buflen; p->rxbufend = buf + p->rx_bufsiz - 1; if (!p->highwater) p->highwater = (p->rx_bufsiz/10) * 8; /* 80% full */ if (!p->lowwater) p->lowwater = (p->rx_bufsiz/10) * 2; /* 20% full */ p->c_read = i_read; p->rxstat = i_rxstat; break; case UZ80_TX_ALL: case TRANSMIT: itype = UZ80_TX_ALL; if (fn == NULL) p->a_ipr[1] = (void FAR_ *) uz80_tx_int_; else p->a_ipr[1] = fn; p->txbufhead = p->txbuftail = p->txbuf = buf; p->tx_bufsiz = buflen; p->txbufend = buf + p->tx_bufsiz - 1; p->c_write = (short (*)(COMM_PORT *, WORD)) i_write; p->txstat = i_txstat; p->txstart = i_txstart; break; default: ret = EOF; } /* ENABLE INTERRUPTS AT THE Z80SIO */ if (!ret) uz80_int_set_(p, itype, TRUE); _enable(); return (ret); } /* UZ80_INT_SET -- Enable or disable the desired type of Z80SIO/DART communications interrupt by setting or clearing the correct bit in the Z80 Interrupt Enable register. Arguments: COMM_PORT *p -- pointer to the comm. port structure unsigned type -- the condition that generates an interrupt 0X2 = Tx character 0X8 = Rx first character 0X10 = Rx all characters (parity error is a special receive condition) 0X18 = Rx all characters (parity error is NOT a special receive condition) */ short uz80_int_set_(COMM_PORT *p, WORD itype, WORD state) { int regval; regval = uz80_get_wr_(p, WR1); /* SET THE BIT CORRESPONDING TO THE INTERRUPT TYPE IN THE 8250 */ if (state) { if (itype == UZ80_RX_ALL || itype == UZ80_RX_ALL_SPECIAL_RECEIVE || itype == UZ80_RX_FIRST_CHARACTER) p->intr |= 1; if (itype & UZ80_TX_ALL) p->intr |= 2; /* CLEAR OUT GARBAGE */ while (c_inchar(p) != EOF); regval |= itype; } /* CLEAR THE BIT CORRESPONDING TO THE INTERRUPT TYPE IN THE 8250 */ else { regval &= ~itype; if (itype == UZ80_RX_ALL || itype == UZ80_RX_ALL_SPECIAL_RECEIVE || itype == UZ80_RX_FIRST_CHARACTER) p->intr &= ~1; if (itype & UZ80_TX_ALL) p->intr &= ~2; } uz80_set_reg_(p, WR1, regval); return (0); } /* SAMPLE Z80 SIO ISRs. USE IF YOU WISH */ #if 0 #define AST 0X300 /* base address of AST port */ #define RXBUFSIZE 1024*2 /* Receive interrupt buffer size */ #define TXBUFSIZE 1024 /* Transmit interrupt buffer size */ /* UZ80_RX_INT -- interrupt handler for receive data. Note: A circular buffer of char "buff1" must be declared prior to use. EOI must be defined as 0X20. BYTE is typedef unsigned char BYTE. */ void INTERRUPT_ uz80_rx_int_(void) { #if XDEBUG static BYTE c, rr1; #endif static volatile BYTE FAR_ *b_ptr; _enable(); #if defined(CCT_TEST) outp(AST+3,1); /* read register 1 for int type */ rr1 = inp(AST+3); if (rr1 & 0X20) { c = 'o'; /* receiver overrun error */ outp(AST+3, 0X30); /* issue error reset command */ if (inp(AST+3) & 1) inp(AST+3); /* IF a char is ready get it */ } else if (rr1 & 0X40) { c = 'f'; /* receiver framing error */ outp(AST+3, 0X30); /* issue error reset command */ if (inp(AST+3) & 1) inp(AST+1); /* IF a char is ready get it */ } #endif if (inp(AST+3) & 1) { /* IF a char is ready get it */ b_ptr = sio0->rxbufhead + 1; if (b_ptr > sio0->rxbufend) b_ptr = sio0->rxbuf; if (!(b_ptr == sio0->rxbuftail)) { /* buffer is full */ *sio0->rxbufhead = (BYTE) inp(AST+1); sio0->rxbufhead = b_ptr; } } outp(EOINT, 0X20); /* Send EOI to 8259 */ } #if XDEBUG WORD FAR_ *s = (WORD FAR_ *) 0XB8000000L; #endif /* UZ80_TX_INT -- Interrupt handler for the Z80SIO/DART transmit data interrupt. For use under the IBM architecture. Note: A circular buffer of char "txbuff1" must be declared prior to use. EOI must be defined as 0X20. The comm port number must be specified. BYTE is typedef unsigned char BYTE. */ void INTERRUPT_ uz80_tx_int_(void) { /* _enable(); */ if (sio0->txbuftail == sio0->txbufhead) { sio0->f_txbusy |= FALSE; uz80_set_reg_(sio0, WR0, UZ80_TX_RESET); } else { outp(sio0->udata_reg_addr, *sio0->txbuftail++); /* send byte */ if (sio0->txbuftail > sio0->txbufend) sio0->txbuftail = sio0->txbuf; #if XDEBUG **s++ = (0XF << 8) | 'o'; #endif } /* _disable(); */ outp(EOINT, 0X20); /* Send EOI to 8259 */ } #endif