home *** CD-ROM | disk | FTP | other *** search
- #define LINT_ARGS
- #include <stdio.h>
-
- #ifdef MSC
- #include <conio.h>
- #include <dos.h>
- #else
- #define inp(x) inportb(x)
- #define outp(x,y) outportb(x,y)
- #define int86(x,y,z) sysint(x,y,z)
- struct WORDREGS {
- unsigned int ax;
- unsigned int bx;
- unsigned int cx;
- unsigned int dx;
- unsigned int si;
- unsigned int di;
- unsigned int ds;
- unsigned int es;
- };
- struct BYTEREGS {
- unsigned char al, ah;
- unsigned char bl, bh;
- unsigned char cl, ch;
- unsigned char dl, dh;
- };
- union REGS {
- struct WORDREGS x;
- struct BYTEREGS h;
- };
- #endif
-
- #define COMBUFSIZE 2048
- #define OUTBUFSIZE 2048
- #define TIMEOUT EOF
- #define TICKSPERSEC 18
- char combuf[COMBUFSIZE];
- int inbufin = 0;
- int inbufout = 0;
- int inchrcnt = 0;
-
- char outbuf[OUTBUFSIZE];
- int outchrcnt = 0;
- int outbufin = 0,
- outbufout = 0;
-
- #ifdef DEBUG
- print_status()
- {
- fprintf(stderr,"\033[s\033[23;20H");
- fprintf(stderr,"inbufin=%02d inbufout=%02d inchrcnt=%02d ",
- inbufin,inbufout,inchrcnt);
- fprintf(stderr,"outbufin=%02d outbufout=%02d outchrcnt=%02d ",
- outbufin,outbufout,outchrcnt);
- fprintf(stderr,"\033[u");
- }
- #endif
-
- int comadr;
- int comport;
- int intnum, intmask, intreg;
-
- #ifdef MSC
- unsigned peekw(offset,segment)
- unsigned offset,segment;
- {
- union { unsigned far *ptr; struct { unsigned off, seg } parts } peeker;
- peeker.parts.off = offset; peeker.parts.seg = segment;
- return *(peeker.ptr);
- }
- #endif
-
- outbuf_purge()
- {
- cli();
- outchrcnt = outbufin = outbufout = 0;
- sti();
- }
-
- inbuf_purge()
- {
- cli();
- inchrcnt = inbufin = inbufout = 0;
- sti();
- }
-
- async_status()
- {
- return inchrcnt;
- }
-
- /*
- * timeout_read(timeout)
- * waits for data from com port for timeout seconds
- */
-
- unsigned long clock()
- {
- static union REGS regs;
- regs.x.ax = 0;
- int86(0x1A,®s,®s);
- return ((long)regs.x.dx+((long)regs.x.cx << 16));
- }
-
- long timerset(timeout)
- int timeout;
- {
- return (clock() + ((timeout/10)*TICKSPERSEC));
- }
-
- int timeup(timer)
- long timer;
- {
- if (timer < clock())
- return 1;
- return 0;
- }
-
- int carrier()
- {
- /* carrier detect is the msb of the modem status register */
- return (inp(comadr+6) & 0x80);
- }
-
- unsigned timeout_read(timeout)
- int timeout;
- {
- unsigned long time;
- unsigned char async_getc();
- if (timeout == 0) /* if they don't want to wait */
- return (async_status() ? async_getc() : TIMEOUT);
- time = clock();
- /* adjust from tenths (about 2 per clock tick) to clock ticks */
- time += (long)(timeout << 1);
- /* loop until timeout or char ready */
- while (time > clock())
- {
- if (async_status())
- return async_getc();
- }
- return (TIMEOUT);
- }
-
- async_putc(c)
- unsigned c;
- {
-
- /* if output buffer is full then poll till it is */
- if (outchrcnt == OUTBUFSIZE)
- while(outchrcnt == OUTBUFSIZE)
- ;
- outbuf[outbufin] = c;
- if (++outbufin == OUTBUFSIZE)
- outbufin = 0;
- outchrcnt++;
- /* enable data available, tx holding empty */
- outp(comadr+1,0x3);
- }
-
- unsigned char
- async_getc()
- {
- register unsigned char c;
- while(!async_status())
- ;
- c = combuf[inbufout++];
- --inchrcnt;
- if (inbufout == COMBUFSIZE)
- inbufout = 0;
- return c;
- }
-
- #ifdef MSC
- /* #pragma check_stack- */
- #endif
-
- void comserv()
- {
- register unsigned c;
- register unsigned int_reason;
- outp(0x20,0x20); /* signal non-specific EOI */
-
- /* check for character read */
- if (4 == (int_reason = inp(comadr+2)))
- {
- /* check line status for data ready */
- if ( inp(comadr+5) & 0x1 )
- {
- rcvdata:
- c = inp(comadr);
- combuf[inbufin++] = c;
- if (inbufin == COMBUFSIZE)
- inbufin = 0;
- ++inchrcnt;
- }
- /* if the transmit holding buffer isn't empty, return */
- if ( inp(comadr+5) & 0x20 )
- goto snddata;
- else
- return;
- }
-
- /* check for character write */
- if (2 == int_reason)
- {
- if ( inp(comadr+5) & 0x20 )
- {
- snddata:
- if (outchrcnt)
- {
- outp(comadr,outbuf[outbufout]);
- if (++outbufout == OUTBUFSIZE)
- outbufout = 0;
- if (!--outchrcnt)
- /* disable tx holding empty interrupt */
- outp(comadr+1,0x1);
- }
- }
- /* check for data ready */
- if ( inp(comadr+5) & 0x1 )
- goto rcvdata;
- else
- return;
- }
- }
-
- #ifdef MSC
- /* #pragma check_stack+ */
- #endif
-
- async_port_setup(com,baud,parity,wordwidth,stopbits)
- {
- union REGS regs;
- register setup_mask;
- register port_mask;
- switch(com)
- {
- case 0: comport = 0; break;
- case 1: comport = 1; break;
- default: return -1;
- }
- switch(baud)
- {
- case 110: setup_mask = 0; break;
- case 300: setup_mask = 0x40; break;
- case 600: setup_mask = 0x60; break;
- case 1200: setup_mask = 0x80; break;
- case 2400: setup_mask = 0xA0; break;
- case 4800: setup_mask = 0xC0; break;
- case 9600: setup_mask = 0xE0; break;
- default: return -1;
- }
- switch (parity)
- {
- case 0: break;
- case 1: setup_mask |= 0x8; break;
- case 2: setup_mask |= 0xA; break;
- default: return -1;
- }
- switch (stopbits)
- {
- case 1: break;
- case 2: setup_mask |= 0x4; break;
- default: return -1;
- }
- switch (wordwidth)
- {
- case 7: setup_mask |= 0x2; break;
- case 8: setup_mask |= 0x3; break;
- default: return -1;
- }
- /* call rom bios to set port parms */
- regs.x.ax = setup_mask & 0xFF;
- regs.x.dx = comport;
- int86(0x14,®s,®s);
- return 0;
- }
-
- async_init(com)
- {
- register setup_mask;
- register port_mask;
-
- switch(com)
- {
- case 0: comport = 0; intnum = 0xC; intmask = 0xEF; break;
- case 1: comport = 1; intnum = 0xB; intmask = 0xF7; break;
- default: return -1;
- }
- /* purge the buffers */
- inbuf_purge(); outbuf_purge();
- /* set up the communications interrupt */
- setup_comint(intnum);
-
- /* get comport base address out of rom bios data segment */
- comadr = peekw(comport << 1,0x40);
-
- /* get int enable port mask */
- intreg = inp(comadr+1);
-
- /* enable data available */
- outp(comadr+1,intreg | 0x1);
-
- /* turn on OUT2 */
- outp(comadr+4,0xB);
-
- inp(comadr); inp(comadr); /* two dummy reads to clear status */
-
- port_mask = inp(0x21); /* get int controller mask */
- outp(0x21,port_mask & intmask); /* turn on interrupts from com port */
- outp(0x20,0x20); /* signal EOI */
- return 0;
- }
-
- async_restore()
- {
- register int port_mask;
- /* disable com port interrupts */
- outp(comadr+1,intreg);
-
- /* get currently masked interrupts */
- port_mask = inp(0x21);
- /* set the appropriate bit for current com port */
- outp(0x21, (port_mask | (intmask ^ 0xFF)));
-
- /* restore interrupt handler */
- restore_comint(intnum);
- }
-