home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: DFÜ und Kommunikation / SOS-DFUE.ISO / programm / dos / utility / pccp076 / port.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-14  |  4.7 KB  |  204 lines

  1. /* Copyright (C) 1992 Peter Edward Cann, all rights reserved */
  2.  
  3. #include<stdio.h>
  4. #include<bios.h>
  5. #include<dos.h>
  6. #include"port.h"
  7.  
  8. int index, basereg;
  9. unsigned char diffintmask, irqnum;
  10. void (interrupt far *oldvect)();
  11.  
  12. unsigned char buf[TBUFSIZ]; /* Incoming char ring buffer; T for TERM (old) */
  13.  
  14. void interrupt far inthndl(_es, _ds, _di, _si, _bp, _sp,
  15.               _bx, _dx, _cx, _ax, _ip, _cs, _flags)
  16.     unsigned _es, _ds, _di, _si, _bp, _sp;
  17.     unsigned _bx, _dx, _cx, _ax, _ip, _cs, _flags;
  18.     {
  19.     while(inp(basereg+STATREG)&RXRDYMASK)
  20.         {
  21.         buf[index++]=inp(basereg);
  22.         if(index>=TBUFSIZ)
  23.             index=0;
  24.         }
  25.     outp(INTBASE2, INTACK);
  26.     outp(INTBASE1, INTACK);
  27.     }
  28.  
  29. unsigned char lctl;
  30. unsigned int speed, comnum;
  31. char databits, parity, stopbits;
  32.  
  33. unsigned char newintmask, oldintmask, lctl, dlmsb, dllsb;
  34. unsigned intnum;
  35. unsigned char oldlctl, olddllsb, olddlmsb, oldintctl, oldmctl;
  36. int oldfifop;
  37.  
  38. setport() /* Parse port configuration; not the best name, I know */
  39.     {
  40.     newintmask=0;
  41.     switch(comnum)
  42.         {
  43.         case 0:
  44.             irqnum=4;
  45.             diffintmask=0xff&~0x10;
  46.             basereg=0x3f8;
  47.             break;
  48.         case 1:
  49.             irqnum=3;
  50.             diffintmask=0xff&~0x08;
  51.             basereg=0x2f8;
  52.             break;
  53.         case 2:
  54.             irqnum=4;
  55.             diffintmask=0xff&~0x10;
  56.             basereg=0x3e8;
  57.             break;
  58.         case 3:
  59.             irqnum=3;
  60.             diffintmask=0xff&~0x08;
  61.             basereg=0x2e8;
  62.             break;
  63.         case 4:
  64.             irqnum=2;
  65.             diffintmask=0xff&~0x02;
  66.             basereg=0x3e8;
  67.             break;
  68.         case 5:
  69.             irqnum=2;
  70.             diffintmask=0xff&~0x02;
  71.             basereg=0x2e8;
  72.             break;
  73.         case 6:
  74.             irqnum=5;
  75.             diffintmask=0xff&~0x20;
  76.             basereg=0x3e8;
  77.             break;
  78.         case 7:
  79.             irqnum=5;
  80.             diffintmask=0xff&~0x20;
  81.             basereg=0x2e8;
  82.             break;
  83.         default:
  84.             printf("Bad port choice.\n");
  85.             exit(4);
  86.         }
  87.     intnum=irqnum+8;
  88.     if(speed) /* Speed is in hundreds of bps */
  89.         {
  90.         if(1152%speed) /* IBM UART can't do that exactly */
  91.             {
  92.             printf("Impossible speed.\n");
  93.             exit(5);
  94.             }
  95.         dllsb=(1152/speed)&0xff;      /* Div. latch least sig. byte */
  96.         dlmsb=((1152/speed)>>8)&0xff; /* Div. latch most sig. byte */
  97.         }
  98.     else
  99.         dllsb=dlmsb=0; /* Totally bizarre today; tomorrow? */
  100.     lctl=0;
  101.     switch(parity)
  102.         {
  103.         case 'e':
  104.         case 'E':
  105.             lctl |= PARITYEN | PARITYEVEN;
  106.             break;
  107.         case 'o':
  108.         case 'O':
  109.             lctl|=PARITYEN;
  110.             break;
  111.         case 'n':
  112.         case 'N':
  113.             break;
  114.         default:
  115.             printf("Bad parity.\n");
  116.             exit(7);
  117.         }
  118.     switch(databits)
  119.         {
  120.         case '7':
  121.             lctl|=DB7;
  122.             break;
  123.         case '8':
  124.             lctl|=DB8;
  125.             break;
  126.         default:
  127.             printf("Bad data bits.\n");
  128.             exit(8);
  129.         }
  130.     switch(stopbits)
  131.         {
  132.         case '1':
  133.             break;
  134.         case '2':
  135.             lctl|=STOP2;
  136.             break;
  137.         default:
  138.             printf("Bad stop bits.\n");
  139.             exit(9);
  140.         }
  141.     }
  142.  
  143. readset() /* Snarf old setting for later socially-responsible cleanup */
  144.     {
  145.     oldlctl=inp(basereg+LCTLREG);
  146.     outp(basereg+LCTLREG, DLAB);
  147.     olddllsb=inp(basereg+DLLSBREG);
  148.     olddlmsb=inp(basereg+DLMSBREG);
  149.     outp(basereg+LCTLREG, oldlctl);
  150.     oldvect=_dos_getvect(intnum);
  151.     oldmctl=inp(basereg+MCTLREG);
  152.     oldfifop=((inp(basereg+FIFOCTLREG)&FIFOENMASK)==FIFOENMASK);
  153.     oldintctl=inp(basereg+INTCTLREG);
  154.     oldintmask=(intnum==10)?inp(INTMASK2):inp(INTMASK1);
  155.     }
  156.     
  157. setup() /* Actually configure the hardware */
  158.     {
  159.     outp(basereg+LCTLREG, DLAB);    /* Switch on access to div. latch */
  160.     outp(basereg+DLLSBREG, dllsb);
  161.     outp(basereg+DLMSBREG, dlmsb);
  162.     outp(basereg+LCTLREG, lctl);    /* Switch off DL and configure */
  163.     _dos_setvect(intnum, inthndl);    /* Install interrupt routine */
  164.     outp(basereg+INTCTLREG, 0x01);    /* Enable receive ready interrupt */
  165.     inp(basereg);            /* Clear old interrupt in UART */
  166.     outp(basereg+MCTLREG, 0x0b);    /* RTS, DTR, OUT2 (IRQ Lo-Z) */
  167.     outp(basereg+FIFOCTLREG, 0x06);    /* 16550 clear FIFO; harmless to 450*/
  168.     outp(basereg+FIFOCTLREG, 0x01); /* 16550 FIFO on; int. on first byte*/
  169.     newintmask=diffintmask;
  170.     newintmask&=oldintmask; /* Combine our bit with existing mask */
  171.     if(intnum==10)            /* Appropriate interrupt controller */
  172.         outp(INTMASK2, newintmask);
  173.     else
  174.         outp(INTMASK1, newintmask);
  175.     outp(INTBASE1, INTACK);    /* While IRQ was floating high, controller */
  176.     outp(INTBASE2, INTACK); /* saw int.; must clear for it to work */
  177.     }
  178.  
  179. cleanup(flags)
  180.     int flags;
  181.     {
  182.     if(!(flags&INHINT))    /* Inhibit interrupt cleanup; prob. bad idea*/
  183.         {
  184.         if(intnum==10)
  185.             outp(INTMASK2, oldintmask);
  186.         else
  187.             outp(INTMASK1, oldintmask);
  188.         outp(basereg+INTCTLREG, oldintctl);
  189.         _dos_setvect(intnum, oldvect);
  190.         outp(basereg+MCTLREG, 0x03); /* OUT2 off *after* IRQ off */
  191.         }
  192.     if(!(flags&INHCTL)) /* To remove interrupts w/o hanging up DTR */
  193.         {
  194.         outp(basereg+LCTLREG, DLAB);
  195.         outp(basereg+DLLSBREG, olddllsb);
  196.         outp(basereg+DLMSBREG, olddlmsb);
  197.         outp(basereg+LCTLREG, oldlctl);
  198.         outp(basereg+MCTLREG, oldmctl);
  199.         if(!oldfifop)
  200.             outp(basereg+FIFOCTLREG, 0x00);
  201.         }
  202.     }
  203.  
  204.