home *** CD-ROM | disk | FTP | other *** search
- //=====================================================================
- //
- // asynch.cpp
- //
- // dos protected mode asynch device services
- //
- // Copyright (c) 1994, Kevin Morgan, All rights reserved.
- //
- //=====================================================================
- #include <dos.h>
- #include <setjmp.h>
- #include <stdio.h>
-
- #include "dpmish.h"
- #include "dosext.h"
-
-
- #pragma check_stack(off)
-
- #ifdef PROTECTV
- typedef DpmiInterruptVector INTERRUPT_VECTOR;
- #else
- typedef void interrupt (far *INTERRUPT_VECTOR)(...);
- #endif
-
- extern void patchExceptionHandler(DpmiInterruptVector);
-
- #define INBUFSIZE 512
- #define OUTBUFSIZE 512
-
- void far interrupt protHandler(...);
-
- void far interrupt realHandler(...);
-
- //*************************************************************************
- // AsyncDevice
- // this is a class wrapper for the ISR for async interrupts
- //*************************************************************************
- class AsyncDevice
- {
-
- private:
- int dummy; // to give this object a size
- int vector;
- int port, enableIRQ, disableIRQ;
- int thr, rdr, brdl, brdh, ier, iir, lcr, mcr, lsr, msr;
-
- char inbuf[INBUFSIZE];
- char outbuf[OUTBUFSIZE];
-
- int inbufs, inbufe;
- int outbufs, outbufe;
- int inbufcnt, outbufcnt;
-
- void interrupt (far * oldRealHandler)(...);
- void interrupt (far * oldProtHandler)(...);
-
-
-
- void storeChar(char); // into inbuf
- int fetchChar(); // from outbuf
-
- int getChar();
- public:
-
- void handler();
- AsyncDevice(int);
- ~AsyncDevice();
- void setParams(int baud, int flags);
- void setHandshake(int flags);
- void putChar(char c);
- void writeComm( CommRequest far * req );
- void readComm( CommRequest far * req );
- };
-
-
-
- //*************************************************************************
- // AsyncDevice
- // this is a class wrapper for the ISR for async interrupts
- // Provides low level hardware handler for 8250 uart
- //*************************************************************************
-
- const short int Ctrl8259_0 = 0x20;
- const short int Ctrl8259_1 = 0x21;
- const short int EOI = 0x20;
-
- AsyncDevice *dev = 0;
-
- AsyncDevice::AsyncDevice(int p) :
- inbufs(0), outbufs(0),
- inbufe(0), outbufe(0),
- inbufcnt(0), outbufcnt(0),
- vector ( 0),
- thr ( 0),
- rdr ( 0),
- brdl ( 0),
- brdh ( 0),
- ier ( 0),
- iir ( 0),
- lcr ( 0),
- mcr ( 0),
- lsr ( 0),
- msr ( 0),
- port ( 0),
- enableIRQ ( 0),
- disableIRQ ( 0),
- oldProtHandler(0),
- oldRealHandler(0)
- {
- dev = this;
- switch (p) {
- case 0:
- port = 0x3f8;
- vector = 0x0c;
- enableIRQ = 0xef;
- disableIRQ = 0x10;
- break;
- case 1:
- port = 0x2f8;
- vector = 0x0b;
- enableIRQ = 0xf7;
- disableIRQ = 0x08;
- break;
- case 2:
- port = 0x3e8;
- vector = 0x0c;
- enableIRQ = 0xef;
- disableIRQ = 0x10;
- break;
- case 3:
- port = 0x2e8;
- vector = 0x0b;
- enableIRQ = 0xf7;
- disableIRQ = 0x08;
- break;
- }
- thr = port+0;
- rdr = port+0;
- brdl = port+0;
- brdh = port+1;
- ier = port+1;
- iir = port+2;
- lcr = port+3;
- mcr = port+4;
- lsr = port+5;
- msr = port+6;
-
- oldRealHandler = Dpmi.getRealVect( vector );
- oldProtHandler = Dpmi.getProtVect( vector );
-
- Dpmi.setRealVect( vector, realHandler );
-
- DpmiInterruptVector h = (DpmiInterruptVector) protHandler;
- patchExceptionHandler(h);
- FP_SEG(h) = _CS;
- Dpmi.setProtVect( vector, h );
-
- _disable();
- // enable 8259
- int w = inportb(Ctrl8259_1);
- outportb(Ctrl8259_1, w&enableIRQ);
-
- // enable 8250 interrupt on data ready
- w = inportb(lcr);
- outportb(lcr, w&0x7f);
-
- outportb(ier, 0);
- if (inportb(ier)==0) {
- outportb(ier, 3);
-
- // clear 8250 status and data
- do {
- w = inportb(rdr);
- w = inportb(lsr);
- w = inportb(msr);
- w = inportb(iir);
- } while ((w&1)==0);
-
- // set bit 3 of MCR -- enable interrupts
- w = inportb(mcr);
- outportb(mcr, w|0x08);
- }
- outportb(thr,0); // null
- _enable();
- }
-
- AsyncDevice::~AsyncDevice()
- {
- // mprintf("~AsyncDevice: this = %04x:%04x\r\n", FP_SEG(this), FP_OFF(this) );
- setHandshake(0);
- _disable();
- // disable 8259 interrupt
- int w = inportb(Ctrl8259_1);
- outportb(Ctrl8259_1, w|disableIRQ);
- // disable 8250 interrupt
- w = inportb(lcr);
- outportb(lcr, w&0x7f);
- outportb(ier, 0);
- w = inportb(mcr);
- outportb(mcr, w&0xf7);
- _enable();
- Dpmi.setProtVect( vector, oldProtHandler );
- Dpmi.setRealVect( vector, oldRealHandler );
- dev = 0;
- }
-
- void AsyncDevice::setParams(int baudrate, int flags)
- {
- if (baudrate) {
- int w = 115200l / baudrate;
- _disable();
- outportb(lcr, 0xff);
- outportb(brdl, w);
- outportb(brdh, w>>8);
- outportb(lcr, flags&0x7f);
- _enable();
- }
- }
-
- void AsyncDevice::putChar(char c)
- {
- outportb(thr,c);
- outportb(ier, 3);
- }
-
- void AsyncDevice::storeChar(char c)
- {
- if (inbufcnt<INBUFSIZE) {
- if (inbufe>=INBUFSIZE)
- inbufe = 0;
- inbuf[inbufe++] = c;
- inbufcnt++;
- }
- // else overrun
- }
-
- int AsyncDevice::fetchChar()
- {
- if (outbufcnt) {
- if (outbufs>=OUTBUFSIZE)
- outbufs = 0;
-
- char c = outbuf[outbufs++];
- outbufcnt--;
- return c;
- }
- // underrun
- return -1;
- }
-
- #ifdef DEBUG
- char far *video;
- char far *myvideo;
-
- void watch(char c, char color)
- {
- if (FP_OFF(myvideo)>24*80) FP_OFF(myvideo) = 0;
- *myvideo++ = c;
- *myvideo++ = color;
- }
- #else
- #define watch(a,b)
- #endif
-
- void AsyncDevice::writeComm( CommRequest far * req )
- {
- int i = 0;
- char far *reqp = req->buf;
- for (i=0;i<req->bufcnt;i++) {
- if (outbufcnt>=OUTBUFSIZE)
- break;
- if (outbufe>=OUTBUFSIZE)
- outbufe = 0;
- outbuf[outbufe++] = *reqp++;
- outbufcnt++;
- }
- req->iocount = i;
- outportb(ier, 3); // enable transmit empty interrupt
- req->status = 0;
- }
-
- void AsyncDevice::readComm( CommRequest far * req )
- {
- int i = 0;
- char far *reqp = req->buf;
- for (i=0;i<req->bufcnt;i++) {
- if (inbufcnt<=0)
- break;
- inbufcnt--;
- if (inbufs>=INBUFSIZE)
- inbufs = 0;
- *reqp++ = inbuf[inbufs++];
- }
- req->iocount = i;
- req->status = 0;
- }
-
- void AsyncDevice::handler(void)
- {
- char a = inportb(iir)&6;
- if (a==4) { // receive interrupts
- char c = inportb(rdr);
- storeChar(c);
- watch(c, 0x57);
- outportb(Ctrl8259_0, EOI);
- char w = inportb(ier);
- outportb(ier,0);
- outportb(ier,w);
- }
- else if (a==2) { // transmit interrupt
- if (outbufcnt) {
- char c = fetchChar();
- watch(c, 0x17);
- outportb(thr, c );
- outportb(ier, 3);
- }
- else
- outportb(ier, 1);
- outportb(Ctrl8259_0, EOI);
- char w = inportb(ier);
- outportb(ier,0);
- outportb(ier,w);
- }
- }
-
-
- void interrupt protHandler(...)
- {
- #ifdef DEBUG
- FP_SEG(myvideo) = FP_SEG(video);
- #endif
- if (dev) dev->handler();
- }
-
-
- void interrupt realHandler(...)
- {
- #ifdef DEBUG
- FP_SEG(myvideo) = 0xb800;
- #endif
- if (dev) dev->handler();
- }
-
- void AsyncDevice::setHandshake(int flags)
- {
- outportb(mcr, flags | 0x08);
- }
-
- void initComm(int p, int aBaud, int aFlags)
- {
- #ifdef DEBUG
- video = (char far *) Dpmi.makeDescriptor( 0xb800 );
- myvideo=(char far *) MK_FP(0,12*80);
- #endif
- if (dev) delete dev;
- dev = new AsyncDevice(p);
- dev->setParams(aBaud, aFlags);
- }
-
- #pragma argsused
- void termComm(int p)
- {
- if (dev) delete dev;
- }
-
- #pragma argsused
- void readComm(int p, CommRequest far *req)
- {
- if (dev) dev->readComm( req );
- else req->status = 1;
- }
-
- #pragma argsused
- void writeComm(int p, CommRequest far *req)
- {
- if (dev) dev->writeComm( req );
- else req->status = 1;
- }
-
-