home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / comm / ykh121.zip / YKHSRC.ZIP / SERIAL.C < prev    next >
C/C++ Source or Header  |  1992-11-03  |  14KB  |  418 lines

  1. #include <stdio.h>
  2. #include <dos.h>
  3. #include "serial.h"
  4.  
  5. #define MDMDAT1 0x03F8            /* Address of modem port 1 data */
  6. #define MDMSTS1 0x03FD            /* Address of modem port 1 status  */
  7. #define MDMCOM1 0x03FB            /* Address of modem port 1 command */
  8. #define MDMDAT2 0x02F8            /* Address of modem port 2 data */
  9. #define MDMSTS2 0x02FD            /* Address of modem port 2 status */
  10. #define MDMCOM2 0x02FB            /* Address of modem port 2 command */
  11. #define MDMINTV 0x000C            /* Com 1 interrupt vector */
  12. #define MDINTV2 0x000B            /* Com 2 interrupt vector */
  13. #define MDMINTO 0x0EF             /* Mask to enable IRQ3 for port 1 */
  14. #define MDINTO2 0x0F7             /* Mask to enable IRQ4 for port 2 */
  15. #define MDMINTC 0x010             /* Mask to Disable IRQ4 for port 1 */
  16. #define MDINTC2 0x008             /* Mask to Disable IRQ3 for port 2 */
  17. #define INTCONT 0x0021            /* 8259 interrupt controller ICW2-3 */
  18. #define INTCON1 0x0020            /* Address of 8259 ICW1 */
  19.  
  20. #define COM_BUFF_SIZE 1024        /* Communications port buffer size */
  21. #define XOFFPT  COM_BUFF_SIZE*3/4 /* chars in buff before sending XOFF */
  22. #define XONPT   COM_BUFF_SIZE*1/4 /* chars in buff to send XON after XOFF */
  23. #define XOFF    0x13              /* XOFF value */
  24. #define XON     0x11              /* XON value */
  25.  
  26. /*****************************************************************************/
  27. /* function prototypes                                                       */
  28.  
  29. void TTinit();                    /* Initialize the communications system */
  30. int ttopen();                     /* Open a port for communications */
  31. int ttclose( void );              /* Close the communications port */
  32. int ttchk( void );                /* Return count of received characters */
  33. void ttoc( unsigned char );       /* Output a character to the com port */
  34. int ttinc( void );                /* Input a character from circular buffer */
  35. void ttflui( void );              /* Flush circular buffer of characters */
  36. int dobaud( unsigned int );       /* Set the baud rate for the port */
  37. void coms( int );                 /* Establish modem data */
  38. void serini( void );              /* Initialize the com port for interrupts */
  39. void serrst( void );              /* Reset the com port to original settings */
  40. void interrupt serint( void );    /* Com port receiver ISR */
  41.  
  42.  
  43. /*****************************************************************************/
  44. /* Global Data                                                               */
  45.  
  46. unsigned int port;                /* COM port */
  47. unsigned int speed;               /* BAUD rate */
  48. char parity[5];                   /* Parity setting */
  49. unsigned int databits;            /* Number of Data bits */
  50. unsigned int stopbits;            /* Number of Stop bits */
  51.  
  52. /*****************************************************************************/
  53. /* External variables                                                        */
  54.  
  55.  
  56.  
  57. /*****************************************************************************/
  58. /* Local Static Data                                                         */
  59.  
  60. static char buffer[COM_BUFF_SIZE];/* Circular buffer */
  61. static char *inptr;               /* Pointer to input point of circular buff*/
  62. static char *outptr;              /* Pointer to output point of circular buff*/
  63. static int  count = 0;            /* Number of characters in buffer */
  64. static unsigned serial_port=0;
  65.  
  66. struct mdminfo {                  /* struct to hold current com port info */
  67.     unsigned int mddat;             /* 8250 data register */
  68.     unsigned int mdstat;            /* 8250 line-status register */
  69.     unsigned int mdcom;             /* 8250 line-control register */
  70.     unsigned char mden;             /* 8259 IRQ enable mask */
  71.     unsigned char mddis;            /* 8259 IRQ disable mask */
  72.     unsigned char mdintv;           /* Interrupt for selected com port */
  73. } modem ;
  74.  
  75. void interrupt (*oldvec)();       /* Vector of previous com interrupt */
  76. int portin = 0;                   /* Flag to indicate com port is open */
  77. int xofsnt = 0;                   /* Flag to indicate an XOFF transmitted */
  78. int xofrcv = 0;                   /* Flag to indicate an XOFF received */
  79.  
  80. /*****************************************************************************/
  81.  
  82. void serial_fixport(unsigned p)
  83. {
  84. serial_port=p;
  85. }
  86.  
  87. void ttos(char* s)
  88. {
  89. while (*s)
  90.   ttoc(*s++);
  91. }
  92.  
  93. unsigned serial_presence(void)
  94. {
  95. return 0;
  96. }
  97.  
  98. unsigned serial_open (unsigned char *service)
  99. {
  100. char* a=0;
  101. char* b=0;
  102. char* c=0;
  103. char* s=0;
  104.  
  105. if ((s=malloc(strlen(service)+1))==NULL)
  106.   return -1;
  107. strcpy(s,service);
  108.  
  109. a=strtok(s   ,":");
  110. b=strtok(NULL,":");
  111.  
  112. ttinit();
  113.  
  114. if (serial_port)
  115.   port=serial_port;
  116. if (a)
  117.   speed=atoi(a);
  118. if (b && strlen(b)==3)
  119.   {
  120.   databits=*b++-'0';
  121.   switch(*b++)
  122.     {
  123.     case 'O': strcpy(parity,"ODD" ); break;
  124.     case 'E': strcpy(parity,"EVEN"); break;
  125.     }
  126.   stopbits=*b;
  127.   }
  128.  
  129. ttopen();
  130.  
  131. free(s);
  132. return 0;
  133. }
  134.  
  135. void serial_close (void)
  136. {
  137. ttclose();
  138. }
  139.  
  140. unsigned serial_send (char c)
  141. {
  142. ttoc(c);
  143. return 0;
  144. }
  145.  
  146. unsigned serial_ready(void)
  147. {
  148. return ttchk();
  149. }
  150.  
  151. char serial_get(void)
  152. {
  153. return ttinc();
  154. }
  155.  
  156. char serial_status(void)
  157. {
  158. return 0;
  159. }
  160.  
  161.  
  162.  
  163. /*  T T I N I T  -- Initialize the communications system */
  164.  
  165. void TTinit()
  166. {
  167. port = 1;
  168. speed = 2400;
  169. strcpy(parity,"NONE");
  170. databits = 8;
  171. stopbits = 1;
  172. }
  173.  
  174.  
  175. /*  T T O P E N  -- Open the communications port */
  176.  
  177. ttopen() {
  178.     if (portin == 0) {            /* Ignore call if already open */
  179.         switch (port) {
  180.             case 1:
  181.                 coms(1);             /* COM 1 */
  182.                 break;
  183.             case 2:
  184.                 coms(2);             /* COM 2 */
  185.                 break;
  186.             default:                 /* others not supported, return error */
  187.                 return(-1);
  188.         }
  189.         dobaud(speed);               /* Set baud rate */
  190.         serini();                    /* enable interrupt handler */
  191.     }
  192.     return(0);                    /* return success */
  193. }
  194.  
  195.  
  196. /*  T T C L O S E --  Close the communications port  */
  197.  
  198. ttclose() {
  199.     if (portin != 0)              /* Ignore if port is already closed */
  200.         serrst();                    /* otherwise disable interrupts */
  201.     return(0);                    /* return success */
  202. }
  203.  
  204.  
  205.  
  206.  
  207. /* T T C H K  --  Return a count of characters at the serial port */
  208.  
  209. ttchk() {
  210.     return( count );              /* return maintained count */
  211. }
  212.  
  213.  
  214. /* T T O C -- Output a character to the current serial port */
  215.  
  216. void ttoc( unsigned char c ) {
  217.  
  218.     while( (inportb(modem.mdstat) & 0x20) == 0 )
  219.        ;                          /* Wait til transmitter is ready */
  220.     outportb(modem.mddat,c);      /* then output the character */
  221. }
  222.  
  223.  
  224. /* T T F L U I  --  Clear the input buffer of characters */
  225.  
  226.  
  227. void ttflui() {
  228.  
  229.     if (xofsnt){                  /* Check if XON should be sent after XOFF */
  230.        xofsnt = 0;                  /* if so then reset XOFF sent status */
  231.        ttoc(XON);                   /* and send the XON */
  232.        }
  233.     disable();                    /* NO interrupts allowed now */
  234.     inptr = outptr = buffer;      /* Reset input out output pointers */
  235.     count = 0;                    /* Set received characters count to 0 */
  236.     enable();                     /* Now interrupts are ok */
  237. }
  238.  
  239.  
  240. /* T T I N C  -- Read a character from serial ports circular buffer */
  241.  
  242. ttinc() {
  243.     int c;
  244.     register char * ptr;
  245.  
  246.     if (count < XONPT && xofsnt){ /* Check if XON should be sent after XOFF */
  247.        xofsnt = 0;                  /* if so then reset XOFF sent status */
  248.        ttoc(XON);                   /* and send the XON */
  249.        }
  250.  
  251.     while (count == 0)            /* If no characters have arrived then */
  252.         ;                            /* wait til one arrives */
  253.  
  254.     ptr = outptr;                 /* Save address of buffer output point */
  255.  
  256.     c = *ptr++;                   /* Get this character and increment ptr */
  257.  
  258.                                   /* See if circular buff should be wrapped */
  259.     if (ptr == &buffer[COM_BUFF_SIZE])
  260.         ptr = buffer;                /* if so then save new output point */
  261.  
  262.     disable();                    /* NO interrupts allowed now */
  263.     outptr = ptr;                 /* Save the address of output point */
  264.     count--;                      /* Decrement count of received characters */
  265.     enable();                     /* Interrupts can continue now */
  266.  
  267.     return(c);                    /* Return the received character */
  268. }
  269.  
  270.  
  271. /* D O B A U D  --  Set the baud rate for the current port */
  272.  
  273. dobaud( unsigned int baudrate ) {
  274.    unsigned char portval;
  275.    unsigned char blo, bhi;
  276.    switch (baudrate) {            /* Get 8250 baud rate divisor values */
  277.        case 50:     bhi = 0x9;  blo = 0x00;  break;
  278.        case 75:     bhi = 0x6;  blo = 0x00;  break;
  279.        case 110:    bhi = 0x4;  blo = 0x17;  break;
  280.        case 150:    bhi = 0x3;  blo = 0x00;  break;
  281.        case 300:    bhi = 0x1;  blo = 0x80;  break;
  282.        case 600:    bhi = 0x0;  blo = 0xC0;  break;
  283.        case 1200:   bhi = 0x0;  blo = 0x60;  break;
  284.        case 1800:   bhi = 0x0;  blo = 0x40;  break;
  285.        case 2000:   bhi = 0x0;  blo = 0x3A;  break;
  286.        case 2400:   bhi = 0x0;  blo = 0x30;  break;
  287.        case 4800:   bhi = 0x0;  blo = 0x18;  break;
  288.        case 9600:   bhi = 0x0;  blo = 0x0C;  break;
  289.        case 19200:  bhi = 0x0;  blo = 0x06;  break;
  290.        case 38400:  bhi = 0x0;  blo = 0x03;  break;
  291.  
  292.        default:                   /* Return failure if baud unsupported */
  293.            return(-1);
  294.    }
  295.  
  296.    portval = inportb(modem.mdcom);/* Save current value of command register */
  297.  
  298.                                   /* In order to set the baud rate the */
  299.                                   /* high bit of command data register is */
  300.    outportb(modem.mdcom,portval | 0x80 ); /* set before sending baud data */
  301.  
  302.    outportb(modem.mddat,blo);     /* Set LSB Baud-Rate divisor for baud */
  303.    outportb(modem.mddat + 1,bhi); /* Set MSB Baud-Rate divisor for baud */
  304.  
  305.    outportb(modem.mdcom,portval); /* Reset original command register value */
  306.  
  307.    return(0);                     /* Return success */
  308. }
  309.  
  310.  
  311. /*  C O M S  --  Set up the modem structure for the specified com port */
  312.  
  313. void coms( int portid ) {
  314.  
  315.     if (portid == 1) {            /* Port data for COM 1 */
  316.         modem.mddat = MDMDAT1;       /* Port 1 Data register */
  317.         modem.mdstat = MDMSTS1;      /* Port 1 Status register */
  318.         modem.mdcom = MDMCOM1;       /* Port 1 Command register */
  319.         modem.mddis = MDMINTC;       /* Port 1 8259 IRQ4 disable mask */
  320.         modem.mden = MDMINTO;        /* Port 1 8259 IRQ4 enable mask */
  321.         modem.mdintv = MDMINTV;      /* Port 1 interrupt number */
  322.     }
  323.     else if (portid == 2) {       /* Port data for COM 2 */
  324.         modem.mddat = MDMDAT2;       /* Port 2 Data register */
  325.         modem.mdstat = MDMSTS2;      /* Port 2 Status register */
  326.         modem.mdcom = MDMCOM2;       /* Port 2 Command register */
  327.         modem.mddis = MDINTC2;       /* Port 2 8259 IRQ4 disable mask */
  328.         modem.mden = MDINTO2;        /* Port 2 8259 IRQ4 enable mask */
  329.         modem.mdintv = MDINTV2;      /* Port 2 interrupt number */
  330.     }
  331. }
  332.  
  333. /* S E R I N I  -- initialize the serial port for interrupts */
  334.  
  335. void serini() {
  336.     unsigned char portval;
  337.  
  338.     if (portin == 0) {            /* Ignore if already open */
  339.         portin = 1;                  /* save port open status */
  340.         inptr = outptr = buffer;     /* set circular buffer pointers */
  341.         count = 0;                   /* indicate no characters received */
  342.         oldvec=getvect(modem.mdintv);/* save old com interrupt */
  343.         setvect(modem.mdintv,serint);/* set SERINT as communications ISR */
  344.  
  345.         portval = 0;              /* Byte value to output to the Line */
  346.                                   /* Control Register (LCR) to set the */
  347.                                   /* Parity, Stopbits, Databits */
  348.                                   /* Start out with all bits zero */
  349.  
  350.         if (strcmp(parity,"EVEN") == 0)
  351.            portval |= 0x8;        /* Set bit 3 on for odd parity */
  352.         else if (strcmp(parity,"ODD") == 0)
  353.            portval |= 0x18;       /* Set bits 3 and 4 on for even parity */
  354.                                   /* Leave bits 3 and 4 off for no parity */
  355.  
  356.  
  357.         if (stopbits == 2)        /* Set bit 2 on if 2 Stopbits are used */
  358.            portval |= 0x4;
  359.                                   /* Leave bit 2 off for 1 Stopbit */
  360.  
  361.         if (databits == 6)        /* Set bit 0 on for 6 data bits */
  362.            portval |= 0x1;
  363.         else if (databits == 7)   /* Set bit 1 on for 7 data bits */
  364.            portval |= 0x2;
  365.         else if (databits == 8)   /* Set bits 0 and 1 on for 8 data bits */
  366.            portval |= 0x3;
  367.                                   /* Leave bits 0 and 1 off for 5 data bits */
  368.  
  369.         outportb(modem.mdcom,portval);  /* Output the settings to the LCR */
  370.  
  371.  
  372.         outportb(modem.mdcom + 1,0xb); /* Assert OUT2, RTS, DTR */
  373.  
  374.         inportb(modem.mddat);        /* Clear any left over characters */
  375.         outportb(modem.mddat+1,0x1); /* Enable receiver interrupts */
  376.  
  377.         portval = inportb(INTCONT);  /* Read 8259 interrupt enable mask */
  378.         outportb(INTCONT,modem.mden & portval); /*Set bit on for com IRQ */
  379.     }
  380. }
  381.  
  382.  
  383. /* S E R R S T -- Reset serial port interrupts */
  384.  
  385. void serrst() {
  386.     unsigned char portval;
  387.  
  388.     if (portin != 0) {            /* Ignore if interrupts already disabled */
  389.         portin = 0;                    /* save port closed status */
  390.         portval = inportb(INTCONT);    /* Read 8259 interrupt enable mask */
  391.         outportb(INTCONT,modem.mddis | portval);/*Set bit off for com IRQ */
  392.         setvect(modem.mdintv,oldvec);  /* return original interrupt vector */
  393.     }
  394. }
  395.  
  396.  
  397. /*  S E R I N T  -- Serial interrupt handler, recieves incoming characters */
  398.  
  399. void interrupt serint() {
  400.  
  401.     *inptr++=inportb(modem.mddat);/* Quickly read arriving character */
  402.     count++;                      /* Increment received count */
  403.  
  404.     if (count > XOFFPT && xofsnt != 1){ /* If buffer almost full then */
  405.        ttoc(XOFF);                /* send an XOFF */
  406.        xofsnt = 1;                /* and save XOFF sent status */
  407.        }
  408.     disable();                    /* NO interrupts are allowed while */
  409.                                   /* new input pointer is stored */
  410.     if (inptr == &buffer[COM_BUFF_SIZE]) /* At end of circular buff? */
  411.        inptr = buffer;                /* if so then save new output point */
  412.  
  413.     enable();                     /* Interrupts ok now */
  414.  
  415.     outportb(0x20,0x20);          /* send End Of Interrupt to 8259 */
  416. }
  417.  
  418.