home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / SERIAL.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  10KB  |  345 lines

  1. /* +++Date last modified: 05-Jul-1997 */
  2.  
  3. /*
  4. +----------------------------------------------------+
  5. |               Thunderbird Software                 |
  6. +----------------------------------------------------+
  7. | Filespec  :  Serial.c                              |
  8. | Date      :  October 24, 1991                      |
  9. | Time      :  15:03                                 |
  10. | Revision  :  1.1                                   |
  11. |     Update: August 29, 1994                        |
  12. +----------------------------------------------------+
  13. | Programmer:  Scott Andrews                         |
  14. | Address   :  5358 Summit RD SW                     |
  15. | City/State:  Pataskala, Ohio                       |
  16. | Zip       :  43062                                 |
  17. +----------------------------------------------------+
  18. | Released to the Public Domain                      |
  19. +----------------------------------------------------+
  20. */
  21.  
  22. /*
  23. +----------------------------------------------------------+
  24. |  Call open_serial to install the interrupt handler       |
  25. |  You must call close_serial before exiting your program  |
  26. |  or a machine crash will occur!                          |
  27. +----------------------------------------------------------+
  28. */
  29.  
  30. #include <stdlib.h>
  31. #include <dos.h>
  32. #include <string.h>
  33. #include "serial.h"
  34. #include "queue.h"
  35.  
  36. QUEUE *Serial_In_Queue;
  37. QUEUE *Serial_Out_Queue;
  38.  
  39. OLD_COMM_PARAMS old_comm_params;
  40. COMM_STATUS     comm_status;
  41.  
  42. void (INTERRUPT FAR *oldvector_serial )(); 
  43. /* save addr for intr handler */
  44.  
  45. int  ComBase;                        /* Comm port address */
  46. int  IrqNum;                         /* Comm interrupt request */
  47.  
  48. int OpenComPort ( char Port )        /* install int. handler */
  49. {
  50.       unsigned status;
  51.       int retval = -1;
  52.     
  53.       /* allocate input and output queues */
  54.  
  55.       Serial_In_Queue = alloc_queue( SerInBufSize );
  56.       if ( (QUEUE *) 0 == Serial_In_Queue)
  57.             return retval;
  58.       Serial_Out_Queue = alloc_queue( SerOutBufSize );
  59.       if ( (QUEUE *) 0 == Serial_Out_Queue)
  60.       {
  61.             free ( Serial_In_Queue );
  62.             return retval;
  63.       }
  64.       retval = 0;
  65.  
  66.       /* Setup Comm base port address and IRQ number */
  67.  
  68.       switch ( Port)
  69.       {
  70.             case '1': ComBase = 0x3F8; IrqNum = 4; break;
  71.             case '2': ComBase = 0x2F8; IrqNum = 3; break;
  72.             case '3': ComBase = 0x3E8; IrqNum = 4; break;
  73.             case '4': ComBase = 0x2E8; IrqNum = 3; break;
  74.             default : ComBase = 0x3F8; IrqNum = 4; break;
  75.       }
  76.       old_comm_params.int_enable = inp ( ComBase + INT_EN );
  77.       outp ( ComBase + INT_EN, 0 ); /* turn off comm interrupts */
  78.  
  79.       /* save old comm parameters */
  80.  
  81.       old_comm_params.line = inp ( ComBase + LINE_CNTRL );
  82.       old_comm_params.modem = inp ( ComBase + MODEM_CNTRL );
  83.       status = inp ( ComBase + LINE_CNTRL );
  84.       outp ( ComBase + LINE_CNTRL, (unsigned char) status | 0x80 );
  85.       old_comm_params.baud_lsb = inp ( ComBase + BAUD_LSB );
  86.       old_comm_params.baud_msb = inp ( ComBase + BAUD_MSB );
  87.       status = inp ( ComBase + LINE_CNTRL );
  88.       outp ( ComBase + LINE_CNTRL, (unsigned char) status | 0x7F );
  89.       status = OUT2 | DTR;              /* DTR/OUT2 must be set! */
  90.       outp ( ComBase + MODEM_CNTRL, (unsigned char) status );
  91.  
  92.       /* get serial port address/vector */
  93.  
  94.       oldvector_serial = (void(INTERRUPT FAR *)(void))getvect(IrqNum + 8 );
  95.  
  96.       /* set our interrupt handler */
  97.  
  98.       setvect ( IrqNum + 8, serial );
  99.  
  100.       /* save the PIC */
  101.  
  102.       old_comm_params.int_cntrl = inp ( 0x21 );
  103.       status = ( 1 << IrqNum);      /* calculate int enable bit */
  104.       status = ~status;
  105.  
  106.       /* ok enable comm ints */
  107.  
  108.       outp ( 0x21, (unsigned char) old_comm_params.int_cntrl & 
  109.             (unsigned char) status );
  110.       return retval;
  111. }
  112.  
  113. void CloseComPort ( void )
  114. {
  115.       int status;
  116.  
  117.       /* restore UART to previous state */
  118.  
  119.       outp ( ComBase + INT_EN, (unsigned char) 0 );
  120.       outp ( ComBase + MODEM_CNTRL, 
  121.             (unsigned char) old_comm_params.modem );
  122.       status = inp ( ComBase + LINE_CNTRL );
  123.       outp ( ComBase + LINE_CNTRL, 
  124.             (unsigned char) status | 0x80 );
  125.       outp ( ComBase + BAUD_LSB, 
  126.             (unsigned char) old_comm_params.baud_lsb );
  127.       outp ( ComBase + BAUD_MSB, 
  128.             (unsigned char) old_comm_params.baud_msb );
  129.       outp ( ComBase + LINE_CNTRL, 
  130.             (unsigned char) old_comm_params.line );
  131.       outp ( 0x21, (unsigned char) old_comm_params.int_cntrl );
  132.  
  133.       /* restore old interrupt handler */
  134.  
  135.       setvect ( IrqNum + 8, oldvector_serial );
  136.  
  137.       /* free input and output queues */
  138.  
  139.       free ( Serial_In_Queue );
  140.       free ( Serial_Out_Queue );
  141.       return;
  142. }
  143.  
  144. void InitComPort ( char Baud[], char Databits, 
  145.                    char Parity, char Stopbits )
  146. {
  147.       int status;
  148.       long baudrate;
  149.       unsigned divisor;
  150.  
  151.       /* set baud rate */
  152.  
  153.       status = inp ( ComBase + LINE_CNTRL );
  154.       outp ( ComBase + LINE_CNTRL, 
  155.             (unsigned char) status | 0x80 );
  156.       baudrate = atol ( Baud );
  157.       if ( baudrate == 0)
  158.             baudrate = 2400L;
  159.       divisor = (unsigned) ( 115200L / baudrate);
  160.       outp ( ComBase + BAUD_LSB, 
  161.             (unsigned char) ( divisor & 0x00FF) );
  162.       outp ( ComBase + BAUD_MSB, 
  163.             (unsigned char) ( ( divisor >> 8) & 0x00FF) );
  164.       status = 0x00;
  165.  
  166.       /* set parity */
  167.  
  168.       switch ( Parity)                    /* set parity value     */
  169.       {
  170.       case 'O':                           /* odd parity           */
  171.       case 'o':
  172.             status = 0x08; break;
  173.  
  174.       case 'E':                           /* even parity          */
  175.       case 'e':
  176.             status = 0x18; break;
  177.  
  178.       case 'S':                           /* stick parity         */
  179.       case 's':
  180.             status = 0x28; break;
  181.  
  182.       case 'N':                           /* no parity            */
  183.       case 'n':
  184.             default :   status = 0x00;
  185.       }
  186.  
  187.     /* set number data bits */
  188.  
  189.       switch ( Databits)
  190.       {
  191.       case '5':
  192.             break;
  193.  
  194.       case '6':
  195.             status = status | 0x01;
  196.             break;
  197.  
  198.       case '7':
  199.             status = status | 0x02;
  200.             break;
  201.  
  202.       case '8':
  203.       default :
  204.             status = status | 0x03;
  205.       }
  206.  
  207.       /* set number stop bits */
  208.  
  209.       switch ( Stopbits)
  210.       {
  211.       case '2':
  212.             status = status | 0x04;
  213.             break;
  214.  
  215.       case '1':
  216.       default :
  217.             ;
  218.       }
  219.       outp ( ComBase + LINE_CNTRL, (unsigned char) status );
  220.       status = OUT2 | DTR;        /* DTR/OUT2 must be set! */
  221.       outp ( ComBase + MODEM_CNTRL, (unsigned char) status );
  222.  
  223.       /* enable serial interrupts */
  224.  
  225.       outp ( ComBase + INT_EN, RX_INT | ERR_INT | RS_INT );
  226.       return;
  227. }
  228.  
  229. void DropDtr ( void )
  230. {
  231.       int status;
  232.  
  233.       status = inp ( ComBase + MODEM_CNTRL );
  234.       status &= 0xFE;                 /* turn off DTR bit */
  235.       outp ( ComBase + MODEM_CNTRL, (unsigned char) status );
  236.       return;
  237. }
  238.  
  239. void RaiseDtr ( void )
  240. {
  241.       int status;
  242.  
  243.       status = inp ( ComBase + MODEM_CNTRL );
  244.       status |= 0x01;                  /* turn on DTR bit */
  245.       outp ( ComBase + MODEM_CNTRL, (unsigned char) status );
  246.       return;
  247. }
  248.  
  249. int ComRecChar ( void )
  250. {
  251.       return de_queue ( Serial_In_Queue );
  252. }
  253.  
  254. int ComSendString ( char *string )
  255. {
  256.       int retval;
  257.       char *pointer;
  258.       pointer = string;
  259.  
  260.       while ( *pointer)
  261.       {
  262.             retval = en_queue ( Serial_Out_Queue, *pointer );
  263.             pointer++;
  264.       }
  265.       if ( 0x0 == (comm_status.modem & 0x40))
  266.             RaiseDtr ();
  267.       outp ( ComBase + INT_EN, RX_INT | TBE_INT | ERR_INT | RS_INT );
  268.       return retval;
  269. }
  270.  
  271. int ComSendChar ( char character )
  272. {
  273.       int retval;
  274.  
  275.       /* interrupt driven send */
  276.  
  277.       if ( 0x0 == (comm_status.modem & 0x40))
  278.             RaiseDtr ();
  279.       retval = en_queue ( Serial_Out_Queue, character );
  280.       if ( - 1 != retval)
  281.             outp ( ComBase + INT_EN, RX_INT | TBE_INT | ERR_INT | RS_INT );
  282.       return retval;
  283. }
  284.  
  285. int ComStatus ( void )
  286. {
  287.       unsigned status;
  288.       unsigned retval;
  289.  
  290.       retval = inp ( ComBase + LINE_STATUS );
  291.       retval = retval << 8;
  292.       status = inp ( ComBase + MODEM_STATUS );
  293.       retval = retval | status;
  294.       if ( queue_empty ( Serial_In_Queue ))
  295.             retval &= 0xFEFF;
  296.       else  retval |= 0x0100;
  297.       return (int) retval;
  298. }
  299.  
  300. void INTERRUPT FAR serial ( void )            /* interrupt handler */
  301. {
  302.       int temp;
  303.  
  304.       disable ();
  305.       while ( 1)
  306.       {
  307.             comm_status.intrupt = inp ( ComBase + INT_ID );
  308.             comm_status.intrupt &= 0x0f;
  309.             switch ( comm_status.intrupt)
  310.             {
  311.             case 0x00:                 /* modem interrupt */
  312.                   comm_status.modem = inp( ComBase + MODEM_STATUS );
  313.                   break;
  314.  
  315.             case 0x02:                 /* xmit interrupt */
  316.                   if ( queue_empty ( Serial_Out_Queue ))
  317.                         outp(ComBase + INT_EN, RX_INT|ERR_INT|RS_INT );
  318.                   else
  319.                   {
  320.                         temp = de_queue ( Serial_Out_Queue );
  321.                         if ( - 1 != temp)
  322.                               outp ( ComBase + XMIT, temp );
  323.                   }
  324.                   break;
  325.  
  326.             case 0x04:                 /* receive interrupt */
  327.                   en_queue(Serial_In_Queue, (char)inp(ComBase + REC));
  328.                   break;
  329.  
  330.             case 0x06:                 /* line interrupt */
  331.                   comm_status.line = inp ( ComBase + LINE_STATUS );
  332.                   (void) inp ( ComBase + REC );
  333.                   en_queue ( Serial_In_Queue, '!' );
  334.                   break;
  335.  
  336.             default:                   /* No Mo` Left */
  337.                   comm_status.modem = inp ( ComBase + MODEM_STATUS );
  338.                   outp ( 0x20, 0x20 );
  339.                   enable ();
  340.                   return;
  341.             }   /* switch */
  342.       }   /* while */
  343. }
  344. /* End of Serial.C */
  345.