home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1992 Peter Edward Cann, all rights reserved */
-
- #include<stdio.h>
- #include<bios.h>
- #include<dos.h>
- #include"port.h"
-
- int index, basereg;
- unsigned char diffintmask, irqnum;
- void (interrupt far *oldvect)();
-
- unsigned char buf[TBUFSIZ]; /* Incoming char ring buffer; T for TERM (old) */
-
- void interrupt far inthndl(_es, _ds, _di, _si, _bp, _sp,
- _bx, _dx, _cx, _ax, _ip, _cs, _flags)
- unsigned _es, _ds, _di, _si, _bp, _sp;
- unsigned _bx, _dx, _cx, _ax, _ip, _cs, _flags;
- {
- while(inp(basereg+STATREG)&RXRDYMASK)
- {
- buf[index++]=inp(basereg);
- if(index>=TBUFSIZ)
- index=0;
- }
- outp(INTBASE2, INTACK);
- outp(INTBASE1, INTACK);
- }
-
- unsigned char lctl;
- unsigned int speed, comnum;
- char databits, parity, stopbits;
-
- unsigned char newintmask, oldintmask, lctl, dlmsb, dllsb;
- unsigned intnum;
- unsigned char oldlctl, olddllsb, olddlmsb, oldintctl, oldmctl;
- int oldfifop;
-
- setport() /* Parse port configuration; not the best name, I know */
- {
- newintmask=0;
- switch(comnum)
- {
- case 0:
- irqnum=4;
- diffintmask=0xff&~0x10;
- basereg=0x3f8;
- break;
- case 1:
- irqnum=3;
- diffintmask=0xff&~0x08;
- basereg=0x2f8;
- break;
- case 2:
- irqnum=4;
- diffintmask=0xff&~0x10;
- basereg=0x3e8;
- break;
- case 3:
- irqnum=3;
- diffintmask=0xff&~0x08;
- basereg=0x2e8;
- break;
- case 4:
- irqnum=2;
- diffintmask=0xff&~0x02;
- basereg=0x3e8;
- break;
- case 5:
- irqnum=2;
- diffintmask=0xff&~0x02;
- basereg=0x2e8;
- break;
- case 6:
- irqnum=5;
- diffintmask=0xff&~0x20;
- basereg=0x3e8;
- break;
- case 7:
- irqnum=5;
- diffintmask=0xff&~0x20;
- basereg=0x2e8;
- break;
- default:
- printf("Bad port choice.\n");
- exit(4);
- }
- intnum=irqnum+8;
- if(speed) /* Speed is in hundreds of bps */
- {
- if(1152%speed) /* IBM UART can't do that exactly */
- {
- printf("Impossible speed.\n");
- exit(5);
- }
- dllsb=(1152/speed)&0xff; /* Div. latch least sig. byte */
- dlmsb=((1152/speed)>>8)&0xff; /* Div. latch most sig. byte */
- }
- else
- dllsb=dlmsb=0; /* Totally bizarre today; tomorrow? */
- lctl=0;
- switch(parity)
- {
- case 'e':
- case 'E':
- lctl |= PARITYEN | PARITYEVEN;
- break;
- case 'o':
- case 'O':
- lctl|=PARITYEN;
- break;
- case 'n':
- case 'N':
- break;
- default:
- printf("Bad parity.\n");
- exit(7);
- }
- switch(databits)
- {
- case '7':
- lctl|=DB7;
- break;
- case '8':
- lctl|=DB8;
- break;
- default:
- printf("Bad data bits.\n");
- exit(8);
- }
- switch(stopbits)
- {
- case '1':
- break;
- case '2':
- lctl|=STOP2;
- break;
- default:
- printf("Bad stop bits.\n");
- exit(9);
- }
- }
-
- readset() /* Snarf old setting for later socially-responsible cleanup */
- {
- oldlctl=inp(basereg+LCTLREG);
- outp(basereg+LCTLREG, DLAB);
- olddllsb=inp(basereg+DLLSBREG);
- olddlmsb=inp(basereg+DLMSBREG);
- outp(basereg+LCTLREG, oldlctl);
- oldvect=_dos_getvect(intnum);
- oldmctl=inp(basereg+MCTLREG);
- oldfifop=((inp(basereg+FIFOCTLREG)&FIFOENMASK)==FIFOENMASK);
- oldintctl=inp(basereg+INTCTLREG);
- oldintmask=(intnum==10)?inp(INTMASK2):inp(INTMASK1);
- }
-
- setup() /* Actually configure the hardware */
- {
- outp(basereg+LCTLREG, DLAB); /* Switch on access to div. latch */
- outp(basereg+DLLSBREG, dllsb);
- outp(basereg+DLMSBREG, dlmsb);
- outp(basereg+LCTLREG, lctl); /* Switch off DL and configure */
- _dos_setvect(intnum, inthndl); /* Install interrupt routine */
- outp(basereg+INTCTLREG, 0x01); /* Enable receive ready interrupt */
- inp(basereg); /* Clear old interrupt in UART */
- outp(basereg+MCTLREG, 0x0b); /* RTS, DTR, OUT2 (IRQ Lo-Z) */
- outp(basereg+FIFOCTLREG, 0x06); /* 16550 clear FIFO; harmless to 450*/
- outp(basereg+FIFOCTLREG, 0x01); /* 16550 FIFO on; int. on first byte*/
- newintmask=diffintmask;
- newintmask&=oldintmask; /* Combine our bit with existing mask */
- if(intnum==10) /* Appropriate interrupt controller */
- outp(INTMASK2, newintmask);
- else
- outp(INTMASK1, newintmask);
- outp(INTBASE1, INTACK); /* While IRQ was floating high, controller */
- outp(INTBASE2, INTACK); /* saw int.; must clear for it to work */
- }
-
- cleanup(flags)
- int flags;
- {
- if(!(flags&INHINT)) /* Inhibit interrupt cleanup; prob. bad idea*/
- {
- if(intnum==10)
- outp(INTMASK2, oldintmask);
- else
- outp(INTMASK1, oldintmask);
- outp(basereg+INTCTLREG, oldintctl);
- _dos_setvect(intnum, oldvect);
- outp(basereg+MCTLREG, 0x03); /* OUT2 off *after* IRQ off */
- }
- if(!(flags&INHCTL)) /* To remove interrupts w/o hanging up DTR */
- {
- outp(basereg+LCTLREG, DLAB);
- outp(basereg+DLLSBREG, olddllsb);
- outp(basereg+DLMSBREG, olddlmsb);
- outp(basereg+LCTLREG, oldlctl);
- outp(basereg+MCTLREG, oldmctl);
- if(!oldfifop)
- outp(basereg+FIFOCTLREG, 0x00);
- }
- }
-
-