home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / c / library / dos / tvision / dpmi / dpmirun / asynch.cpp next >
Encoding:
C/C++ Source or Header  |  1994-05-29  |  8.3 KB  |  382 lines

  1. //=====================================================================
  2. //
  3. //  asynch.cpp
  4. //
  5. //  dos protected mode asynch device services
  6. //
  7. //  Copyright (c) 1994, Kevin Morgan, All rights reserved.
  8. //
  9. //=====================================================================
  10. #include <dos.h>
  11. #include <setjmp.h>
  12. #include <stdio.h>
  13.  
  14. #include "dpmish.h"
  15. #include "dosext.h"
  16.  
  17.  
  18. #pragma check_stack(off)
  19.  
  20. #ifdef PROTECTV
  21. typedef DpmiInterruptVector INTERRUPT_VECTOR;
  22. #else
  23. typedef    void interrupt (far *INTERRUPT_VECTOR)(...);
  24. #endif
  25.  
  26. extern void patchExceptionHandler(DpmiInterruptVector);
  27.  
  28. #define INBUFSIZE 512
  29. #define OUTBUFSIZE 512
  30.  
  31. void far interrupt protHandler(...);
  32.  
  33. void far interrupt realHandler(...);
  34.  
  35. //*************************************************************************
  36. // AsyncDevice
  37. // this is a class wrapper for the ISR for async interrupts
  38. //*************************************************************************
  39. class AsyncDevice
  40. {
  41.     
  42. private:
  43.     int dummy;  // to give this object a size
  44.     int vector;
  45.     int port, enableIRQ, disableIRQ;
  46.     int thr, rdr, brdl, brdh, ier, iir, lcr, mcr, lsr, msr;
  47.  
  48.     char inbuf[INBUFSIZE];
  49.     char outbuf[OUTBUFSIZE];
  50.  
  51.     int inbufs, inbufe;
  52.     int outbufs, outbufe;
  53.     int inbufcnt, outbufcnt;
  54.  
  55.     void interrupt (far * oldRealHandler)(...);
  56.     void interrupt (far * oldProtHandler)(...);
  57.  
  58.  
  59.  
  60.     void storeChar(char);   // into inbuf
  61.     int  fetchChar();       // from outbuf
  62.  
  63.     int  getChar();
  64. public:
  65.  
  66.     void handler();
  67.     AsyncDevice(int);
  68.     ~AsyncDevice();
  69.     void setParams(int baud, int flags);
  70.     void setHandshake(int flags);
  71.     void putChar(char c);
  72.     void writeComm( CommRequest far * req );
  73.     void readComm( CommRequest far * req );
  74. };
  75.  
  76.  
  77.  
  78. //*************************************************************************
  79. // AsyncDevice
  80. // this is a class wrapper for the ISR for async interrupts
  81. // Provides low level hardware handler for 8250 uart
  82. //*************************************************************************
  83.  
  84. const short int Ctrl8259_0 = 0x20;
  85. const short int Ctrl8259_1 = 0x21;
  86. const short int EOI = 0x20;
  87.  
  88. AsyncDevice *dev = 0;
  89.  
  90. AsyncDevice::AsyncDevice(int p) :
  91.     inbufs(0), outbufs(0),
  92.     inbufe(0), outbufe(0),
  93.     inbufcnt(0), outbufcnt(0),
  94.     vector ( 0),
  95.     thr    ( 0),
  96.     rdr    ( 0),
  97.     brdl   ( 0),
  98.     brdh   ( 0),
  99.     ier    ( 0),
  100.     iir    ( 0),
  101.     lcr    ( 0),
  102.     mcr    ( 0),
  103.     lsr    ( 0),
  104.     msr    ( 0),
  105.     port   ( 0),
  106.     enableIRQ ( 0),
  107.     disableIRQ ( 0),
  108.     oldProtHandler(0),
  109.     oldRealHandler(0)
  110. {
  111.     dev = this;
  112.     switch (p) {
  113.         case 0:
  114.             port = 0x3f8;
  115.             vector = 0x0c;
  116.             enableIRQ = 0xef;
  117.             disableIRQ = 0x10;
  118.             break;
  119.         case 1:
  120.             port = 0x2f8;
  121.             vector = 0x0b;
  122.             enableIRQ = 0xf7;
  123.             disableIRQ = 0x08;
  124.             break;
  125.         case 2:
  126.             port = 0x3e8;
  127.             vector = 0x0c;
  128.             enableIRQ = 0xef;
  129.             disableIRQ = 0x10;
  130.             break;
  131.         case 3:
  132.             port = 0x2e8;
  133.             vector = 0x0b;
  134.             enableIRQ = 0xf7;
  135.             disableIRQ = 0x08;
  136.             break;
  137.     }
  138.     thr  = port+0;
  139.     rdr  = port+0;
  140.     brdl = port+0;
  141.     brdh = port+1;
  142.     ier  = port+1;
  143.     iir  = port+2;
  144.     lcr  = port+3;
  145.     mcr  = port+4;
  146.     lsr  = port+5;
  147.     msr  = port+6;
  148.  
  149.     oldRealHandler = Dpmi.getRealVect( vector );
  150.     oldProtHandler = Dpmi.getProtVect( vector );
  151.  
  152.     Dpmi.setRealVect( vector, realHandler );
  153.  
  154.     DpmiInterruptVector h = (DpmiInterruptVector) protHandler;
  155.     patchExceptionHandler(h);
  156.     FP_SEG(h) = _CS;
  157.     Dpmi.setProtVect( vector, h );
  158.  
  159.     _disable();
  160.     // enable 8259
  161.     int w = inportb(Ctrl8259_1);
  162.     outportb(Ctrl8259_1, w&enableIRQ);
  163.  
  164.     // enable 8250 interrupt on data ready
  165.     w = inportb(lcr);
  166.     outportb(lcr, w&0x7f);
  167.  
  168.     outportb(ier, 0);
  169.     if (inportb(ier)==0) {
  170.         outportb(ier, 3);
  171.  
  172.         // clear 8250 status and data
  173.         do {
  174.             w = inportb(rdr);
  175.             w = inportb(lsr);
  176.             w = inportb(msr);
  177.             w = inportb(iir);
  178.         } while ((w&1)==0);
  179.  
  180.         // set bit 3 of MCR -- enable interrupts
  181.         w = inportb(mcr);
  182.         outportb(mcr, w|0x08);
  183.     }
  184.     outportb(thr,0);    // null
  185.     _enable();
  186. }
  187.  
  188. AsyncDevice::~AsyncDevice()
  189. {
  190. //    mprintf("~AsyncDevice: this = %04x:%04x\r\n", FP_SEG(this), FP_OFF(this) );
  191.     setHandshake(0);
  192.     _disable();
  193.     // disable 8259 interrupt
  194.     int w = inportb(Ctrl8259_1);
  195.     outportb(Ctrl8259_1, w|disableIRQ);
  196.     // disable 8250 interrupt
  197.     w = inportb(lcr);
  198.     outportb(lcr, w&0x7f);
  199.     outportb(ier, 0);
  200.     w = inportb(mcr);
  201.     outportb(mcr, w&0xf7);
  202.     _enable();
  203.     Dpmi.setProtVect( vector, oldProtHandler );
  204.     Dpmi.setRealVect( vector, oldRealHandler );
  205.     dev = 0;
  206. }
  207.  
  208. void AsyncDevice::setParams(int baudrate, int flags)
  209. {
  210.     if (baudrate) {
  211.         int w = 115200l / baudrate;
  212.         _disable();
  213.         outportb(lcr, 0xff);
  214.         outportb(brdl, w);
  215.         outportb(brdh, w>>8);
  216.         outportb(lcr, flags&0x7f);
  217.         _enable();
  218.     }
  219. }
  220.  
  221. void AsyncDevice::putChar(char c)
  222. {
  223.     outportb(thr,c);
  224.     outportb(ier, 3);
  225. }
  226.  
  227. void AsyncDevice::storeChar(char c)
  228. {
  229.     if (inbufcnt<INBUFSIZE) {
  230.         if (inbufe>=INBUFSIZE)
  231.             inbufe = 0;
  232.         inbuf[inbufe++] = c;
  233.         inbufcnt++;
  234.     }
  235.     // else overrun
  236. }
  237.  
  238. int AsyncDevice::fetchChar()
  239. {
  240.     if (outbufcnt) {
  241.         if (outbufs>=OUTBUFSIZE)
  242.             outbufs = 0;
  243.  
  244.         char c = outbuf[outbufs++];
  245.         outbufcnt--;
  246.         return c;
  247.     }
  248.     // underrun
  249.     return -1;
  250. }
  251.  
  252. #ifdef DEBUG
  253. char far *video;
  254. char far *myvideo;
  255.  
  256. void watch(char c, char color)
  257. {
  258.     if (FP_OFF(myvideo)>24*80) FP_OFF(myvideo) = 0;
  259.     *myvideo++ = c;
  260.     *myvideo++ = color;
  261. }
  262. #else
  263. #define watch(a,b)
  264. #endif
  265.  
  266. void AsyncDevice::writeComm( CommRequest far * req )
  267. {
  268.     int i = 0;
  269.     char far *reqp = req->buf;
  270.     for (i=0;i<req->bufcnt;i++) {
  271.         if (outbufcnt>=OUTBUFSIZE)
  272.             break;
  273.         if (outbufe>=OUTBUFSIZE)
  274.             outbufe = 0;
  275.         outbuf[outbufe++] = *reqp++;
  276.         outbufcnt++;
  277.     }
  278.     req->iocount = i;
  279.     outportb(ier, 3);   // enable transmit empty interrupt
  280.     req->status = 0;
  281. }
  282.  
  283. void AsyncDevice::readComm( CommRequest far * req )
  284. {
  285.     int i = 0;
  286.     char far *reqp = req->buf;
  287.     for (i=0;i<req->bufcnt;i++) {
  288.         if (inbufcnt<=0)
  289.             break;
  290.         inbufcnt--;
  291.         if (inbufs>=INBUFSIZE)
  292.             inbufs = 0;
  293.         *reqp++ = inbuf[inbufs++];
  294.     }
  295.     req->iocount = i;
  296.     req->status = 0;
  297. }
  298.  
  299. void AsyncDevice::handler(void)
  300. {
  301.     char a = inportb(iir)&6;
  302.     if (a==4) { // receive interrupts
  303.         char c = inportb(rdr);
  304.         storeChar(c);
  305.         watch(c, 0x57);
  306.         outportb(Ctrl8259_0, EOI);
  307.         char w = inportb(ier);
  308.         outportb(ier,0);
  309.         outportb(ier,w);
  310.     }
  311.     else if (a==2) { // transmit interrupt
  312.         if (outbufcnt) {
  313.             char c = fetchChar();
  314.             watch(c, 0x17);
  315.             outportb(thr, c );
  316.             outportb(ier, 3);
  317.         }
  318.         else
  319.             outportb(ier, 1);
  320.         outportb(Ctrl8259_0, EOI);
  321.         char w = inportb(ier);
  322.         outportb(ier,0);
  323.         outportb(ier,w);
  324.     }
  325. }
  326.  
  327.  
  328. void interrupt protHandler(...)
  329. {
  330. #ifdef DEBUG
  331.     FP_SEG(myvideo) = FP_SEG(video);
  332. #endif
  333.     if (dev) dev->handler();
  334. }
  335.  
  336.  
  337. void interrupt realHandler(...)
  338. {
  339. #ifdef DEBUG
  340.     FP_SEG(myvideo) = 0xb800;
  341. #endif
  342.     if (dev) dev->handler();
  343. }
  344.  
  345. void AsyncDevice::setHandshake(int flags)
  346. {
  347.     outportb(mcr, flags | 0x08);
  348. }
  349.  
  350. void initComm(int p, int aBaud, int aFlags)
  351. {
  352. #ifdef DEBUG
  353.     video = (char far *) Dpmi.makeDescriptor( 0xb800 );
  354.     myvideo=(char far *) MK_FP(0,12*80);
  355. #endif
  356.     if (dev) delete dev;
  357.     dev = new AsyncDevice(p);
  358.     dev->setParams(aBaud, aFlags);
  359. }
  360.  
  361. #pragma argsused
  362. void termComm(int p)
  363. {
  364.     if (dev) delete dev;
  365. }
  366.  
  367. #pragma argsused
  368. void readComm(int p, CommRequest far *req)
  369. {
  370.     if (dev) dev->readComm( req );
  371.     else req->status = 1;
  372. }
  373.  
  374. #pragma argsused
  375. void writeComm(int p, CommRequest far *req)
  376. {
  377.     if (dev) dev->writeComm( req );
  378.     else req->status = 1;
  379. }
  380.  
  381.  
  382.