/* * ports.ti: * serial port stuff for TI Professionals * * Copyright (c) 1989 University of Toronto. All rights reserved. * Anyone may use or copy this software, except that it may not be * sold for profit, that this copyright notice remain intact, and that * credit is given where it is due. The University of Toronto and the * author make no warranty and accept no liability for this software. */ /* * layout based in part on modempro.pas from Qkermit and msxtip.asm. * TI Pro serial port information obtained from msxtip.asm, the * TI Pro Technical Manual, and the Zilog Z8530 SCC product spec. */ static char rcsid[] = "$Header: /homes/ugw/pkern/src/cterm/RCS/ports.ti,v 1.3 89/07/06 19:45:48 pkern Exp $"; #include #include "cterm.h" #include "ti.h" extern int nbaud, n_port; extern uchar flowctl, bpc, stopbits, parity, m_prty, xoff; #ifdef LOCAL extern uchar local; #endif #ifdef ECHO extern uchar echo; #endif static uchar buffer[BUFMAX]; static int xout=0, xin=0, n_intr=0; static int a_cmd=0, b_cmd=0, a_data=0, b_data=0; static int bufovfl=BUFMAX/2, /* flow control XOFF trigger */ bufmpty=BUFMAX/8; /* flow control XON trigger */ static uchar flxoff=0; /* flowctl XOFF-sent flag */ #define BUFC(a,b) ((a bufovfl) { xmit_chr(XOFF); flxoff=1; } } enable(); outportb(IC8259r1, 0x20); /* 8259 : End-of-interrupt */ } /* * set_prt - Set the baud rate, parity and stop bits for serial port. */ set_prt() { int i; if (!a_cmd) return(-1); if (nbaud > EXTA) nbaud = B9600; i = nbaud; /* WR13 : baud rate time const upper byte */ outportb(a_cmd, 13); outportb(a_cmd, bdivs[i] >> 8); /* WR12 : baud rate time const lower byte */ outportb(a_cmd, 12); outportb(a_cmd, bdivs[i] & 0xff); /* WR4 : x16 clock mode, 1 or 2 stopbits, parity */ i = 0x40; /* x16 clock mode */ i |= (stopbits) ? 0x0c : 0x04; /* stop bits ? 2 : 1 */ i |= (parity << 1) | m_prty; /* parity type & mode */ outportb(a_cmd, 4); outportb(a_cmd, i); bufovfl = BUFMAX/2; bufmpty = BUFMAX/8; #ifdef debug regs[13] = BUFMAX; regs[14] = bufovfl; regs[15] = bufmpty; #endif i = (7 + bpc) - 5; /* WR5 : DTR, RTS, bpc, Tx enable */ outportb(a_cmd, 5); outportb(a_cmd, 0x8A | bpctab[i]); /* WR3 : bpc, Rx enable */ outportb(a_cmd, 3); outportb(a_cmd, 0x01 | (bpctab[i]<<1)); i = 3; outportb(a_cmd, 14); outportb(a_cmd, i); #ifdef ECHO outportb(b_cmd, 14); outportb(b_cmd, 0x13); /* BR gen enable/src, local loopback */ #endif } /* * init_prt - Initialize the port and install the port ISR. */ init_prt() { int i, x; extern unsigned int sysconfig; /* pick a port number(n_port) based on sysconfig */ for (i=0; n_port < 0 && i < NPORTS; i++) if (sysconfig & (0x10 << i)) n_port = i; if (n_port < 0 || n_port > NPORTS-1) return(-1); n_intr = ports[n_port].vect; a_cmd = ports[n_port].base + A_CMD; b_cmd = ports[n_port].base + B_CMD; a_data = ports[n_port].base + A_DATA; b_data = ports[n_port].base + B_DATA; /* clrbuf */ for (i=0; i<8; i++) x = inportb(a_data); x = inportb(a_cmd); /* makes it point to WR0 */ /* serina */ for (i=0; !(init_a[i] & 0x80); i+=2) { outportb(a_cmd, init_a[i]); outportb(a_cmd, init_a[i+1]); } x = inportb(b_cmd); /* makes it point to WR0 */ /* serinb */ for (i=0; !(init_b[i] & 0x80); i+=2) { outportb(b_cmd, init_b[i]); outportb(b_cmd, init_b[i+1]); } xin = xout = 0; /* initialize buffer indices */ /* save old intr vector to another spot */ o_portisr = getvect(n_intr); /* install the new interrupt routine */ disable(); setvect(n_intr, port_isr); enable(); /* enable IR0, IR1, IR2, or IR4 */ outportb(IC8259r2, inportb(IC8259r2) & ports[n_port].enable); /* outportb(IC8259r1, ports[n_port].disable); */ set_prt(); } /* * reset_prt - restore the original interrupt, drop DTR and RTS */ reset_prt() { if (!n_intr || !a_cmd) return(-1); /* WR9 : disable 8530 interrupts */ outportb(a_cmd, 9); outportb(a_cmd, 0); /* WR5 : no DTR, no RTS, Tx enable, bpc */ outportb(a_cmd, 5); outportb(a_cmd, 0x64 & bpctab[(7+bpc)-5]); /* disable interrupts */ outportb(IC8259r2, inportb(IC8259r2) | ports[n_port].disable); /* restore the old interrupt vector */ setvect(n_intr, o_portisr); } /* * conn_prt - checks DCD and CTS. * (a historical relic, no longer used) */ conn_prt() { int i; i = ((inportb(a_cmd) & 0x24) != 0x24); return(i); } /* * recv_chr - Receive a Character from the serial port. * returns: c - if there is a character in the buffer. * -1 - if no character found. */ recv_chr() { uchar c; if (flxoff && !xoff && BUFC(xin,xout) < bufmpty) { xmit_chr(XON); flxoff=0; } if (BUFC(xin,xout) > 0) { /* get char from buffer */ c = buffer[xout++] & 0x7f; xout %= BUFMAX; return(c); } return(-1); } recv_byt() { uchar c; if (BUFC(xin,xout) > 0) { c = buffer[xout++]; xout %= BUFMAX; return(c); } return(-1); } /* * xmit_chr - Send a character thru the serial port. * It waits for the previous character to be sent before * sending the current character. */ xmit_chr(c) int c; { while (!(inportb(a_cmd) & 0x04)) ; #ifdef debug regs[13] = inportb(a_cmd); #endif outportb(a_data, c & 0xff); } xmit_eko(c) int c; { #ifdef ECHO while (!(inportb(a_cmd) & 0x04)) ; outportb(a_data, c & 0xff); while (!(inportb(b_cmd) & 0x04)) ; outportb(b_data, c & 0xff); #else xmit_lcl(c); xmit_eko(c); #endif } xmit_lcl(c) int c; { #ifdef LOCAL while (!(inportb(b_cmd) & 0x04)) ; outportb(b_data, c & 0xff); #else buffer[xin++] = c; xin %= BUFMAX; #endif } /* * xmit_str - Same as xmit_chr() except a string is sent instead. */ xmit_str(p) char *p; { int c; while (c = *p++) { while (!(inportb(a_cmd) & 0x04)) ; outportb(a_data, c & 0xff); } } /* * send_brk- Send a long break via the comm port. */ send_brk() { if (!a_cmd) return(-1); /* WR5 : DTR, RTS, send break, Tx enable, bpc */ outportb(a_cmd, 0x05); outportb(a_cmd, 0x9A | bpctab[(7+bpc)-5]); dsleep(250); /* 1/4 sec. delay */ /* WR5 : DTR, RTS, Tx enable, bpc */ outportb(a_cmd, 0x05); outportb(a_cmd, 0x8A | bpctab[(7+bpc)-5]); } /* * hang_up- Drop the comm port connection */ hang_up() { if (!a_cmd) return(-1); /* WR5 : no DTR, no RTS, Tx enable, bpc */ outportb(a_cmd, 0x05); outportb(a_cmd, 0x08 | bpctab[(7+bpc)-5]); dsleep(250); /* 1/4 sec. delay */ /* WR5 : DTR, RTS, Tx enable, bpc */ outportb(a_cmd, 0x05); outportb(a_cmd, 0x8A | bpctab[(7+bpc)-5]); } #ifndef ECHO /* put char into incoming data buffer (ie. simulate echo) */ loop_chr(c) int c; { disable(); buffer[xin++] = c; xin %= BUFMAX; enable(); } #endif /* * trns_chr: same as recv_chr but translate control chars */ trns_chr() { uchar c; if (flxoff && !xoff && BUFC(xin,xout) < bufmpty) { xmit_chr(XON); flxoff=0; } if (BUFC(xin,xout) > 0) { /* get char from buffer */ c = buffer[xout++] & 0x7F; if (c & 0x60) xout %= BUFMAX; else { buffer[--xout] = c | 0x40; /* '@' */ c = '^'; } return(c); } return(-1); } /* return bdivs index for speed n */ prtspd(n) unsigned int n; { int i; for (i=0; spdtab[i]; i+=2) if (spdtab[i] == n) return(spdtab[i+1]); return(nbaud); }