SIO.C
上传用户:sunrenlu
上传日期:2022-06-13
资源大小:1419k
文件大小:20k
源码类别:

操作系统开发

开发平台:

DOS

  1. /*
  2.  * SIO - Serial port I/O
  3.  * Copyright (c) 1990, 2000 Erick Engelke
  4.  * Utilizes special interrupt handling to support
  5.  *      - multiple COM ports per irq
  6.  *      - low latency for other interrupts on system board
  7.  *          - does not disable interrupts for long like most serial code
  8.  */
  9. #define TERM
  10. #define NEW
  11. #include <dos.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <rtos.h>
  15. #include <sio.h>
  16. #include <mem.h>
  17. #ifdef __DJGPP__
  18. #include <go32.h>
  19. #include <pc.h>
  20. #endif
  21. //#define FIFO    /* Use FIFO if found */
  22. #define RBR 0   /* receive  buffer register */
  23. #define THR 0   /* transmit buffer register */
  24. #define IER 1   /* interrupt enable register */
  25. #define IIR 2   /* interrupt ID register */
  26. #define LCR 3   /* line control register */
  27. #define MCR 4   /* modem control register */
  28. #define LSR 5   /* line status register */
  29. #define MSR 6   /* modem status register */
  30. #define DLL 0   /* divisor latch LSB when DLAB=1 */
  31. #define DLM 1   /* divisor latch MSB when DLAB=1 */
  32. #define DLAB      0x80   /* divisor latch bit */
  33. #define OUT2      0x8    /* interrupt enable on PC compatibles */
  34. #define IIRMASK   0x7    /* valid bits in the IIR register */
  35. #define IERENABLE 0xf    /* enable all SIO interrupt conditions */
  36. #define FIFOMASK  0x8
  37. #define DTR     0x01   /* data terminal ready */
  38. #define RTS     0x02   /* ready to send */
  39. #define CTS     0x10   /* ready to send */
  40. #define DELTA_CTS 0x01 /* change in CTS */
  41. #define DELTA_DSR 0x02 /* change in DSR */
  42. #define SETBRK 0x40 /* Break control */
  43. #define OCW1    0x21    /* 8259 */
  44. #define OCW2    0x20
  45. /* Line Status Register bits
  46.  */
  47. #define LSR_DR     0x01  /* receive data ready */
  48. #define LSR_OVRRUN 0x02  
  49. #define LSR_PARITY 0x04
  50. #define LSR_FRAME  0x08
  51. #define LSR_BREAK  0x10
  52. #define LSR_THRE   0x20  /* transmit holding register empty */
  53. #define LSR_TSRE   0x40
  54. #define TX_READY   (LSR_THRE|LSR_TSRE)
  55. #define MAXIRQS 15
  56. #if defined(__DJGPP__)
  57.   #define IntrHandler   struct irq_handler_info
  58.   #define NULL_ISR      { {0,0}, {0,0} }
  59. #elif defined(__TURBOC__)
  60.   typedef void interrupt (*IntrHandler)(void);
  61.   #define NULL_HANDLER  ((void far*)0)
  62.   #define NULL_ISR      ((void far*)0)
  63. #elif defined(__BORLANDC__)
  64.   typedef void (cdecl interrupt *IntrHandler)(void);
  65.   #define NULL_HANDLER  ((void far*)0)
  66.   #define NULL_ISR      ((void far*)0)
  67. #else
  68.   #error Unsupported compiler
  69. #endif
  70. static IntrHandler oldisrs[ MAXIRQS + 1 ] =
  71.    { NULL_ISR, NULL_ISR, NULL_ISR, NULL_ISR,
  72.      NULL_ISR, NULL_ISR, NULL_ISR, NULL_ISR,
  73.      NULL_ISR, NULL_ISR, NULL_ISR, NULL_ISR,
  74.      NULL_ISR, NULL_ISR, NULL_ISR, NULL_ISR };
  75. typedef struct _sio_str {
  76.     WORD    sio_port;
  77.     WORD    sio_irq;
  78.     WORD    sio_int;    /* 8 + irq or ... */
  79.     IntrHandler sio_previsr;
  80.     bq_str *sio_rbq;    /* receive byte queue */
  81.     bq_str *sio_tbq;    /* transmit byte queue */
  82.     thread_x *sio_notify;
  83.     int     sio_message;
  84.     BYTE    sio_hwflow;             // Hardware flow control enable
  85.     BYTE    sio_modemstatus;
  86.     int     sio_highwater;  // Receive buffer high water mark
  87.     int     sio_lowwater;   // Receive buffer low water mark
  88. } sio_str;
  89. static sio_str sio[ MAXSIO ] = {
  90.         {0, 0, 0, NULL_ISR, NULL, NULL, NULL, 0, 0, 0, 0, 0},
  91.         {0, 0, 0, NULL_ISR, NULL, NULL, NULL, 0, 0, 0, 0, 0},
  92.         {0, 0, 0, NULL_ISR, NULL, NULL, NULL, 0, 0, 0, 0, 0},
  93.         {0, 0, 0, NULL_ISR, NULL, NULL, NULL, 0, 0, 0, 0, 0}};
  94. static char *sio_err = "SIO call with com port out of range";
  95. static struct {
  96.        DWORD num_rm_intr;
  97.        DWORD num_pm_intr;
  98.        DWORD num_thre;
  99.        DWORD num_rx_intr;
  100.        DWORD num_fifo_rx_intr;
  101.        DWORD num_modem_stat;
  102.        struct {
  103.          DWORD general;
  104.          DWORD overrun;
  105.          DWORD parity;
  106.          DWORD framing;
  107.          DWORD breaking;
  108.        } num_line_stat;
  109.      } sio_stats [MAXSIO];
  110. #define test_com_valid( n )  do {                      
  111.                                if (!n || (n > MAXSIO)) 
  112.                                   rt_halt (sio_err);   
  113.                              } while (0)
  114. #if defined(__BORLANDC__) || defined(__TURBOC__)
  115. #pragma option -N-   /* disable stack checking */
  116. #endif
  117. static int sio_isr(int irq)
  118. {
  119.     int com;
  120.     int handled = 0;
  121.     sio_str *s;
  122.     WORD intid;
  123.     WORD base;
  124.     BYTE b;
  125.     BYTE status;
  126.     for ( com = 0 ; com < MAXSIO ; ++com ) {
  127.         s = &sio[ com ];
  128.         base = s->sio_port;
  129.         if ( base == 0 )
  130.             continue;
  131.         if ( s->sio_irq != irq )
  132.             continue;
  133. #ifdef __DJGPP__
  134.         sio_stats[com].num_pm_intr++; /* to-do: use a bimodal handler */
  135. #else
  136.         sio_stats[com].num_rm_intr++;
  137. #endif
  138.         while ( 1 ) {
  139.             intid = inportb( base + IIR );
  140.             if ( intid & 1 )
  141.                 break;  /* no interrupt pending */
  142.             switch ( intid & IIRMASK ) {
  143.                 case 0  :   /* change in modem status */
  144.                             s->sio_modemstatus = inportb( base + MSR );
  145.                             sio_stats[com].num_modem_stat++;
  146.                             if (s->sio_notify)
  147.                                 ksendmessage (s->sio_notify , s->sio_message+2, s->sio_modemstatus);
  148.                             if (s->sio_hwflow) {
  149.                                 if (s->sio_modemstatus & CTS) {
  150.                                     if (inportb (base + LSR) & LSR_THRE) {
  151.                                         if (bq_getbyte (s->sio_tbq, &b))
  152.                                             outportb (base + THR, b);
  153.                                     }
  154.                                 }
  155.                             }
  156.                             break;
  157.                 case 2  :   /* ready to transmit */
  158.                             sio_stats[com].num_thre++;
  159.                             if (s->sio_hwflow) {
  160.                                 if (!(s->sio_modemstatus & CTS))
  161.                                     break;
  162.                             }
  163.                             if ( bq_getbyte( s->sio_tbq, &b ) )
  164.                                 outportb( base + THR, b );
  165.                             break;
  166.                 case 4  :   /* received data */
  167.                             if (intid & FIFOMASK)
  168.                                  sio_stats[com].num_fifo_rx_intr++;
  169.                             else sio_stats[com].num_rx_intr++;
  170.                             b = inportb( base + RBR );
  171.                             bq_sendbyte( s->sio_rbq , b );
  172. #if 0
  173.                             if (s->sio_notify)
  174.                                ksend1message (s->sio_notify , s->sio_message, b);
  175. #endif
  176.                             if (s->sio_hwflow) {
  177.                                 if (bq_readcount (s->sio_rbq) >= s->sio_highwater) {
  178.                                     status = inportb (base + MCR);
  179.                                     outportb (base + MCR, status & ~RTS);
  180.                                 }
  181.                             }
  182.                             break;
  183.                 case 6  :   /* line status */
  184.                             b = inportb( base + LSR );
  185.                             sio_stats[com].num_line_stat.general++;
  186.                             if (b & LSR_OVRRUN)
  187.                                sio_stats[com].num_line_stat.overrun++;
  188.                             if (b & LSR_PARITY)
  189.                                sio_stats[com].num_line_stat.parity++;
  190.                             if (b & LSR_FRAME)
  191.                                sio_stats[com].num_line_stat.framing++;
  192.                             if (b & LSR_BREAK)
  193.                                sio_stats[com].num_line_stat.breaking++;
  194. #if 0
  195.                             if (s->sio_notify)
  196.                               ksendmessage (s->sio_notify , s->sio_message+1, b);
  197. #endif
  198.                             break;
  199.                default :    /* ! added */
  200.                             (void) inportb (base + LSR);
  201.                             (void) inportb (base + MSR);
  202.                             handled--;
  203.                             break;
  204.             }
  205.             handled++;
  206.         }
  207.    }
  208.    return (handled);
  209. }
  210. //-----------------------------------------------------------------------
  211. // ----------------------------------------------------------------------
  212. #define IEC_PRIMARY 0x21
  213. #define IEC_SECONDARY 0xA1
  214. #if defined(__DJGPP__)
  215.   #define do_chain(irq)  ((void)0) /* never chain */
  216. #elif defined(__BORLANDC__) || defined(__TURBOC__)
  217.   #define do_chain(irq)  if (oldisrs[irq]) (*oldisrs[irq])()
  218. #endif
  219. /* this code produces low latency for other interrupt handlers */
  220. #define UART_INT( irqlevel, iec ) 
  221.     void interrupt uart_int##irqlevel ( void ) 
  222.     {           
  223.         kinisr++; 
  224.         outportb( iec , inportb( iec ) | ( 1 << irqlevel )); 
  225.         if ( iec == IEC_SECONDARY ) 
  226.             outportb( 0xA0, 0x60|irqlevel); /* specific EOI */  
  227.         outportb( 0x20, 0x60|irqlevel); 
  228.         enable(); 
  229.                   
  230.         /*!! Shouldn't EOI be sent after our work is done? */ 
  231.         if (!sio_isr( irqlevel )) 
  232.            do_chain (irqlevel);   
  233.         else { 
  234.           disable(); 
  235.           outportb( iec, inportb( iec ) & ~ ( 1 << irqlevel )); 
  236.         }  
  237.         kinisr--; 
  238.     }
  239. UART_INT( 3, IEC_PRIMARY )
  240. UART_INT( 4, IEC_PRIMARY )
  241. UART_INT( 5, IEC_PRIMARY )
  242. UART_INT( 6, IEC_PRIMARY )
  243. UART_INT( 7, IEC_PRIMARY )
  244. UART_INT( 9, IEC_SECONDARY )
  245. UART_INT(10, IEC_SECONDARY )
  246. UART_INT(11, IEC_SECONDARY )
  247. UART_INT(12, IEC_SECONDARY )
  248. UART_INT(13, IEC_SECONDARY )
  249. UART_INT(14, IEC_SECONDARY )
  250. UART_INT(15, IEC_SECONDARY )
  251. #if defined(__BORLANDC__) || defined(__TURBOC__)
  252. #pragma option -N.   /* default stack checking */
  253. #endif
  254. //---------------------------------------------------------------------------
  255. int uart_detect( WORD base )
  256. {
  257.     BYTE x, ov, scr = 1;
  258.     // check for LCR
  259.     ov = inportb( base + 3 );
  260.     outportb( base + 3, 0x1b );
  261.     if ( inportb( base + 3 ) != 0x1b ) return -1;
  262.     outportb( base + 3, 0x03 );
  263.     if ( inportb( base + 3 ) != 0x03 ) return -1;
  264.     // restore its value
  265.     outportb( base + 3, ov );
  266.     // look for scratch register
  267.     ov = inportb( base + 7 );
  268.     outportb( base + 7, 0x55 );
  269.     if ( inportb( base + 7 ) != 0x55 ) scr = 0;
  270.     outportb( base + 7, 0xAA ) ;
  271.     if ( inportb( base + 7 ) != 0xAA ) scr = 0;
  272.     outportb( base + 7, ov );
  273.     // look for FIFO
  274.     outportb( base +2, 0x01);
  275.     x = inportb( base + 2 );
  276.     outportb( base + 2, 0 );
  277.     if ( ! ( x & 0x80 ) ) return scr;
  278.     if ( ! ( x & 0x40 ) ) return scr + 2;
  279.     return scr + 4;
  280. }
  281. int uart_enable_fifo( WORD base, WORD trigger )
  282. {
  283.     // 0 on success or no FIFO
  284.     // -1 on error
  285.     BYTE x;
  286.     outportb( base + 2, 1 );        // key to getting C0 right
  287.     x = inportb( base + 2 ) & 0xC0 ;
  288.     if ( x == 0 ) return( -1 );
  289.     if ( x == 0x80 ) {
  290.         outportb( base + 2, 0 );
  291.         return -1;      // bad fifo, disabled it
  292.     }
  293.     outportb( base + 2, trigger & (0xc0 | 0x07) );
  294.     return 0 ;
  295. }
  296. void uart_disable_fifo( WORD base )
  297. {
  298.     outportb( base + 2, 0 );
  299. }
  300. //--------------------------------------------------------------------
  301. void sio_print_stats (int com)
  302. {
  303.   if (com < 1 || com >= MAXSIO-1)
  304.      return;
  305.   com--;
  306.   printf ("COM%d stats: intr %lu/%lu, THRE %lu, Rx-intr %lu, FIFO %lu, "
  307.           "modem %lu, line %lun",
  308.           com+1, sio_stats[com].num_rm_intr, sio_stats[com].num_pm_intr,
  309.           sio_stats[com].num_thre, sio_stats[com].num_rx_intr,
  310.           sio_stats[com].num_fifo_rx_intr, sio_stats[com].num_modem_stat,
  311.           sio_stats[com].num_line_stat.general);
  312.   printf ("  (overrun %lu, parity %lu, framing %lu, breaking %lu)n",
  313.           sio_stats[com].num_line_stat.overrun,
  314.           sio_stats[com].num_line_stat.parity,
  315.           sio_stats[com].num_line_stat.framing,
  316.           sio_stats[com].num_line_stat.breaking);
  317. }
  318. //----------------------------------------------------------------------
  319. void
  320. sio_init (int com, int port, int irq, int rbufsize, int tbufsize, thread_x *notify, int message)
  321. {
  322.     static int atexit_done = 0;
  323.     WORD flags;
  324.     sio_str *s;
  325.     void interrupt (*isr)() = NULL;
  326.     sio_close( com );   /* clean up any previous stuff */
  327.     test_com_valid (com);
  328.     rt_cpu_block( &flags );
  329.     s = &sio[ com - 1 ];
  330.     s->sio_port = port;
  331.     s->sio_irq = irq;
  332.     s->sio_notify = notify;
  333.     s->sio_message = message;
  334.     s->sio_highwater = (int)(((long)rbufsize * 90L)/100L);
  335.     s->sio_lowwater = (int)(((long)rbufsize * 10L)/100L);
  336.     s->sio_hwflow = 0;
  337.     s->sio_modemstatus = 0;
  338.     if ( s->sio_rbq != NULL ) bq_free( s->sio_rbq );
  339.     if ( s->sio_tbq != NULL ) bq_free( s->sio_tbq );
  340.     s->sio_rbq = bq_alloc( rbufsize );
  341.     s->sio_tbq = bq_alloc( tbufsize );
  342.     /* disable ints */
  343.     outportb (port + IER , 0);
  344.     switch ( irq ) {
  345.         case  3 : isr = uart_int3;    break;
  346.         case  4 : isr = uart_int4;    break;
  347.         case  5 : isr = uart_int5;    break;
  348.         case  6 : isr = uart_int6;    break;
  349.         case  7 : isr = uart_int7;    break;
  350.         case  9 : isr = uart_int9;    break;
  351.         case 10 : isr = uart_int10;   break;
  352.         case 11 : isr = uart_int11;   break;
  353.         case 12 : isr = uart_int12;   break;
  354.         case 13 : isr = uart_int13;   break;
  355.         case 14 : isr = uart_int14;   break;
  356.         case 15 : isr = uart_int15;   break;
  357.     }
  358. #ifdef OLD
  359. switch (com)
  360. {
  361. case 1:
  362.     isr = sio_isr1;
  363. break;
  364. case 2:
  365.     isr = sio_isr2;
  366. break;
  367. }
  368. #endif
  369. #ifdef __DJGPP__
  370.     if ( oldisrs[ irq ].new_handler.pm_offset == 0 ) {
  371.         irq_handler_info *inf = rt_enableirq( irq, isr );
  372.         if (!inf)
  373.         {
  374.           fprintf (stderr,"called to hook IRQ %dn", irq);
  375.           return;
  376.         }
  377.         oldisrs[irq] = *inf;
  378.     }
  379. #else
  380.     if ( oldisrs[ irq ] == NULL_HANDLER ) {
  381.         oldisrs[irq] = rt_enableirq( irq, isr );
  382.     }
  383. //  s->sio_previsr = rt_enableirq (irq, isr);
  384. #endif
  385.     if (!atexit_done)
  386.        atexit (sio_exit);
  387.     atexit_done = 1;
  388.     rt_cpu_unblock( &flags );
  389. }
  390. void sio_close( int com )
  391. {
  392.     WORD base;
  393.     sio_str *s;
  394.     int tempcom, count;
  395.     test_com_valid( com );
  396.     s = &sio[ com - 1 ];
  397.     base = s->sio_port;
  398.     if ( base ) {
  399.         /* disable sio ints */
  400.         outportb( base + IER, 0 );
  401.         for ( tempcom = count = 0; tempcom < MAXSIO ; ++tempcom )
  402.             if ( sio[ tempcom ].sio_irq == s->sio_irq ) count++;
  403.         /* only remove ISR if we are the last one using it */
  404.         if ( count == 1 )
  405.         {
  406. #ifdef __DJGPP__
  407.            if ( oldisrs[ s->sio_irq].new_handler.pm_offset)
  408.            {
  409.              rt_disableirq ( s->sio_irq, &oldisrs[ s->sio_irq ] );
  410.              oldisrs[ s->sio_irq ].new_handler.pm_offset = 0;
  411.            }
  412. #else
  413.            if ( oldisrs[ s->sio_irq] != NULL_HANDLER )
  414.            {
  415.              rt_disableirq ( s->sio_irq, oldisrs[ s->sio_irq ] );
  416.              oldisrs[ s->sio_irq ] = NULL_HANDLER;
  417.            }
  418. #endif
  419.         }
  420.         /* bring down com line  */
  421.         outportb (base + MCR , 0);
  422. #ifdef FIFO
  423.         uart_disable_fifo( base );
  424. #endif
  425.         s->sio_port = 0;
  426.         s->sio_irq = 0;     /* so last sio_close() on that IRQ knows it */
  427.     }
  428.     if ( s->sio_rbq != NULL ) {
  429.         bq_free( s->sio_rbq );
  430.         s->sio_rbq = NULL;
  431.     }
  432.     if ( s->sio_tbq != NULL ) {
  433.         bq_free( s->sio_tbq );
  434.         s->sio_tbq = NULL;
  435.     }
  436. }
  437. void
  438. sio_setup (int com, DWORD baud, int bits, int parity, int stop, BYTE hwflow)
  439. {
  440.     WORD flags;
  441.     WORD divisor;
  442.     WORD base;
  443.     BYTE parmbyte;
  444.     sio_str *s;
  445.     BYTE b;
  446.     test_com_valid( com );
  447. #define LOW(  x ) ( x & 255 )
  448. #define HIGH( x ) ( x >> 8 )
  449.     s = &sio[ com - 1];
  450.     divisor = (WORD) (115200L / baud);
  451.     /* word length from [5,8] gives results [0,3] */
  452.     if ( bits == 0 ) bits = 8;
  453.     parmbyte = bits - 5;
  454.     parmbyte |= (stop -1) << 2;
  455.     if (parity) parmbyte |= 8;
  456.     if (parity == SIO_PARITY_EVEN) parmbyte |= 16;
  457.     rt_cpu_block( &flags );
  458.     base = s->sio_port;
  459.     s->sio_hwflow = hwflow; // establish hardware flow control
  460.     /* disable sio int */
  461.     outportb( base + IER, 0 );  /* disable all serial interrupts */
  462.     /* disable adapter, DTR RTS */
  463.     outportb( base + MCR , 0 );
  464.     /* set DLAB for a moment */
  465.     outportb( base + LCR , inportb( base + LCR ) | DLAB );
  466.     /* pass the divisor */
  467.     outportb( base + DLL , LOW( divisor ));
  468.     outportb( base + DLM , HIGH( divisor ));
  469.     /* clear DLAB */
  470.     outportb( base + LCR , inportb( base + LCR ) & ~DLAB );
  471.     /* set word length and parity */
  472.     outportb( base + LCR, parmbyte );
  473.     /* clear any trash */
  474.     while (inportb (base + LSR) & LSR_DR)
  475.          inportb (base + RBR);
  476.     // Send the initial notification of the line status
  477.     b = inportb (base + LSR);
  478.     if (s->sio_notify)
  479.        ksendmessage (s->sio_notify , s->sio_message+1, b);
  480.     // Send the initial notification of the modem status
  481.     s->sio_modemstatus = inportb( base + MSR );
  482.     if (s->sio_notify)
  483.        ksendmessage (s->sio_notify , s->sio_message+2,
  484.                      s->sio_modemstatus | DELTA_CTS | DELTA_DSR);
  485.     /* enable adapter, DTR RTS */
  486.     outportb( base + MCR , DTR | RTS | OUT2 );
  487.     /* enable sio int */
  488.     outportb( base + IER, IERENABLE );  /* enable all serial interrupts */
  489. #ifdef FIFO
  490.     uart_enable_fifo( base, 0xC0 );
  491. #endif
  492.     rt_cpu_unblock( &flags );
  493. }
  494. int sio_recv_waiting( int com )
  495. {
  496.     test_com_valid( com );
  497.     return( bq_readcount( sio[ com - 1 ].sio_rbq ) );
  498. }
  499. int sio_tran_waiting( int com )
  500. {
  501.     test_com_valid( com );
  502.     return( bq_readcount( sio[ com - 1 ].sio_tbq ) );
  503. }
  504. BYTE sio_readbyte( int com )
  505. {
  506.     BYTE x;
  507.     BYTE status;
  508.     WORD base;
  509.     sio_str *s;
  510.     test_com_valid( com );
  511.     s = &sio[ com - 1];
  512.     base = s->sio_port;
  513.     bq_readbyte( s->sio_rbq , &x ) ;
  514.     if (s->sio_hwflow)
  515.     {
  516.       if (bq_readcount (s->sio_rbq) <= s->sio_lowwater)
  517.       {
  518.         status = inportb (base + MCR);
  519.         outportb (base + MCR, status | RTS);
  520.       }
  521.     }
  522.     return( x );
  523. }
  524. void sio_writebyte (int com, BYTE b)
  525. {
  526.     sio_str *s;
  527.     BYTE status;
  528.     WORD base;
  529.     WORD flags;
  530.     test_com_valid (com);
  531.     s = &sio[com - 1];
  532.     base = s->sio_port;
  533.     /* always send it to the queue */
  534.     bq_writebyte (s->sio_tbq, b);
  535.     /* now check if we need to start the UART siphon */
  536.     rt_cpu_block( &flags );
  537.     if (!(s->sio_hwflow) || (s->sio_modemstatus & CTS)) {
  538.         status = inportb (base + LSR);    /* get UART status */
  539.         if (status & LSR_THRE) {
  540.             /* holding register is empty, fill it if data is available */
  541.             if (bq_getbyte (s->sio_tbq, &b))
  542.                 outportb (base + THR, b);
  543.         }
  544.     }
  545.     rt_cpu_unblock (&flags);
  546. }
  547. void sio_exit (void)
  548. {
  549.     int i;
  550.     for (i = 1 ; i < MAXSIO ; ++i)
  551.     {
  552.         if (kdebug > 2)
  553.            sio_print_stats (i);
  554.         sio_close (i);
  555.     }
  556. }
  557. void sio_msg( int com, int xmit, int recv )
  558. {
  559.     sio_str *s;
  560.     test_com_valid( com );
  561.     s = &sio[ com - 1 ];
  562.     if ( xmit ) bq_msg( s->sio_tbq, EMSG_BQ_AVAIL );
  563.     if ( recv ) bq_msg( s->sio_rbq, EMSG_BQ_WAITING );
  564. }
  565. BYTE sio_getmcr (int com)
  566. {
  567.     sio_str *s;
  568.     test_com_valid (com);
  569.     s = &sio[com - 1];
  570.     return (inportb (s->sio_port + MCR));
  571. }
  572. void sio_setmcr (int com, BYTE mcr)
  573. {
  574.     sio_str *s;
  575.     test_com_valid (com);
  576.     s = &sio[com - 1];
  577.     outportb (s->sio_port + MCR, mcr);
  578. }
  579. void sio_setbreak (int com, BYTE brk)
  580. {
  581.     sio_str *s;
  582.     test_com_valid (com);
  583.     s = &sio[com - 1];
  584.     outportb (s->sio_port + LCR,
  585.               (inportb (s->sio_port + LCR) & ~SETBRK) | (brk & SETBRK));
  586. }