home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 183_01 / comsup.c < prev    next >
Text File  |  1984-06-22  |  19KB  |  960 lines

  1. /*
  2.  
  3.  commsupp.c    - communications support for DeSmet C
  4.  
  5.  Tom Poindexter- March, 1984
  6.  
  7.  routines:
  8.  
  9.   init_com     - initialize comm port, interrupts, baud, data, parity, stop
  10.   uninit_com   - disable interrupts, flushes buffer
  11.   send_brk     - send break signal
  12.   set_xoff     - enable XON, XOFF protocol
  13.   recd_xoff    - return true if XOFF received
  14.   sent_xoff    - return true if XOFF sent
  15.   inp_cnt      - returns the number of unread bytes in receive buffer
  16.   inp_char     - return one byte from buffer
  17.   inp_strn     - transfer n bytes from buffer to string
  18.   outp_char    - send one byte
  19.   outp_strn    - send n bytes of a string, up to end of string
  20.   com_stat     - return line status (high byte) and modem status (low byte)
  21.   on_com       - specify a routine to execute when a byte is received
  22.  
  23.  internal routines:
  24.   -in commsupp.c-
  25.   port_chk     - validate the port number (C88)
  26.  
  27.   -in commasm.a-
  28.   int_c_handlr - interrupt driven port read, com1:, store in buffer (ASM88)
  29.   int_b_handlr - interrupt driven port read, com2:, store in buffer (ASM88)
  30.   sysint       - call a system routine (ASM88)
  31.   inb           - input byte from hardware port (ASM88)
  32.   outb           - output byte to hardware port (ASM88)
  33.   cli           - clear interrupts (ASM88)
  34.   sti           - set interrupts   (ASM88)
  35.  
  36.  standard DeSmet C library functions called:
  37.  
  38.   _lmove     - block move outside C data
  39.   _move      - block move within C data
  40.   _showcs    - get code segment
  41.   _showds    - get data segment
  42.   malloc     - allocate memory
  43.  
  44.  
  45. */
  46.  
  47. /* global parm data for two com ports */
  48.  
  49. struct
  50.  {
  51.   int  port_base;
  52.   char *buff_addr;
  53.   int  buff_len;
  54.   char *buff_head;
  55.   char *buff_tail;
  56.   int  buff_cnt;
  57.   int  x_state;
  58.   int  x_recd;
  59.   int  x_sent;
  60.   int  org_int_off;
  61.   int  org_int_seg;
  62.   int  (*on_com_rtn)();
  63.  }
  64.  _com_parms[2];
  65.  
  66.  
  67. /* global defines */
  68. #define FALSE      0
  69. #define TRUE      1
  70. #define ERROR      -1
  71.  
  72. /* defines for 8250 serial controller */
  73. #define DATAPORT  0
  74. #define INT_REG   1
  75. #define INT_ID      2
  76. #define LCTL_REG  3
  77. #define MDM_REG   4
  78. #define LCTL_STAT 5
  79. #define MDM_STAT  6
  80. #define LSB_BAUD  0
  81. #define MSB_BAUD  1
  82. #define DLAB      0x80
  83. #define DLAB_OFF  0x7f
  84. #define MDM_BRK   0x40
  85. #define PAR_NONE  0x00
  86. #define PAR_EVEN  0x18
  87. #define PAR_ODD   0x08
  88. #define PAR_STICK 0x20
  89. #define DATA_RDY  0x01
  90. #define OUT2_DR   0x0b
  91. #define BREAK_ON  0x40
  92. #define THRE      0x20
  93. /* count to wait for THRE */
  94. #define TIME      0xffff
  95.  
  96. /* defines for break request */
  97. #define TIME_OF_DAY 0x1a
  98. #define HALF_SEC  9
  99.  
  100. /* baud rate divisor constants */
  101. #define B110      1047
  102. #define B150      768
  103. #define B300      384
  104. #define B450      256
  105. #define B600      192
  106. #define B1200      96
  107. #define B2400      48
  108. #define B4800      24
  109. #define B9600      12
  110. /* defines to mask baud divisors MSB and LSB */
  111. #define MASK_LSB  0xff00
  112. #define MASK_MSB  0x00ff
  113.  
  114. /* defines for 8259 interrupt controller */
  115. #define C8259_1   0x21
  116. #define C8259_3   0x20
  117. #define ENBL_IRQ4 0xef
  118. #define DIS_IRQ4  0x10
  119. #define ENBL_IRQ3 0xf7
  120. #define DIS_IRQ3  0x08
  121. #define EOI_IRQ4  0x64
  122. #define EOI_IRQ3  0x63
  123. #define IRQ4_VEC  0x0c
  124. #define IRQ3_VEC  0x0b
  125.  
  126. /* defines for data areas */
  127. #define SYS_VEC   0x0
  128. #define ROM_DATA  0x40
  129. #define INT_DSEG  2
  130.  
  131.  
  132. /****************************************************************************/
  133.  
  134. /* init_com
  135.  
  136.       parms:
  137.         port: 1 = com1:, 2 = com2:
  138.         baud: 110, 150, 300, 450, 600, 1200, 2400, 4800, 9600
  139.       parity: 0 = none, 1 = odd, 2 = even, 3 = mark, 4 = space
  140.         data: 5, 6, 7, 8
  141.         stop: 1, 2
  142.     buff_len: length desired for receive buffer ( 0 < buff_len < 32767 )
  143.  
  144.    returns:
  145.       ERROR = com port not available or invalid parm value
  146.        TRUE = ok
  147.  
  148. */
  149.  
  150. init_com (port, baud, parity, data, stop, buff_len)
  151.  
  152. int port;
  153. int baud;
  154. int parity;
  155. int data;
  156. int stop;
  157. int buff_len;
  158.  
  159. {
  160.  
  161.   int divisor;
  162.   int buff_addr;
  163.   int line_reg;
  164.   int data_seg;
  165.   int code_seg;
  166.   int int_c_handlr();
  167.   int int_b_handlr();
  168.   int int_handlr_addr;
  169.  
  170.   /*  get C program segment registers */
  171.  
  172.   data_seg = _showds ();
  173.   code_seg = _showcs ();
  174.  
  175.   /* validate port; store port address */
  176.  
  177.   if (port < 1 || port > 2)
  178.     return (ERROR);
  179.   else
  180.    {
  181.     port--;
  182.     _lmove (2,port*2,ROM_DATA,&_com_parms[port].port_base,data_seg);
  183.     if (_com_parms[port].port_base == 0)
  184.       return (ERROR);
  185.    }
  186.  
  187.  
  188.   /* validate baud; set baud divisors */
  189.  
  190.   switch (baud)
  191.    {
  192.     case  110:
  193.       divisor =  B110;
  194.       break;
  195.     case  150:
  196.       divisor =  B150;
  197.       break;
  198.     case  300:
  199.       divisor =  B300;
  200.       break;
  201.     case  450:
  202.       divisor =  B450;
  203.       break;
  204.     case  600:
  205.       divisor =  B600;
  206.       break;
  207.     case 1200:
  208.       divisor = B1200;
  209.       break;
  210.     case 2400:
  211.       divisor = B2400;
  212.       break;
  213.     case 4800:
  214.       divisor = B4800;
  215.       break;
  216.     case 9600:
  217.       divisor = B9600;
  218.       break;
  219.     default:
  220.       return (ERROR);
  221.    }
  222.  
  223.  
  224.   /* validate parity; set line control register parity */
  225.  
  226.   switch (parity)
  227.    {
  228.      case 0:  /* none  */
  229.        line_reg = PAR_NONE;
  230.        break;
  231.      case 1:  /* odd   */
  232.        line_reg = PAR_ODD;
  233.        break;
  234.      case 2:  /* even  */
  235.        line_reg = PAR_EVEN;
  236.        break;
  237.      case 3:  /* mark  */
  238.        line_reg = PAR_ODD | PAR_STICK;
  239.        break;
  240.      case 4:  /* space */
  241.        line_reg = PAR_EVEN | PAR_STICK;
  242.        break;
  243.      default:
  244.        return (ERROR);
  245.     }
  246.  
  247.  
  248.   /* validate data len; set line control register data length */
  249.  
  250.   if (data < 5 || data > 8)
  251.     return (ERROR);
  252.   else
  253.     line_reg |= data - 5;
  254.  
  255.  
  256.   /* validate stop bits; set line control register stop bits */
  257.  
  258.   if (stop < 1 || stop > 2)
  259.     return (ERROR);
  260.   else
  261.     line_reg |=  (stop - 1) << 2;
  262.  
  263.  
  264.   /* validate buffer len; allocate memory, set initial settings */
  265.  
  266.   if (buff_len < 1 || buff_len > 32767)
  267.     return (ERROR);
  268.   else
  269.    {
  270.     _com_parms[port].buff_addr    = malloc (buff_len);
  271.     if (_com_parms[port].buff_addr == 0)
  272.       return (ERROR);
  273.     _com_parms[port].buff_len    = buff_len;
  274.     _com_parms[port].buff_head    = _com_parms[port].buff_addr;
  275.     _com_parms[port].buff_tail    = _com_parms[port].buff_addr;
  276.     _com_parms[port].buff_cnt    = 0;
  277.     _com_parms[port].x_state    = FALSE;
  278.     _com_parms[port].x_recd    = FALSE;
  279.     _com_parms[port].x_sent    = FALSE;
  280.     _com_parms[port].on_com_rtn = FALSE;
  281.    }
  282.  
  283.   /* set 8250 baud divisor */
  284.  
  285.   outb (_com_parms[port].port_base + LCTL_REG, DLAB);
  286.   outb (_com_parms[port].port_base + LSB_BAUD, divisor & MASK_MSB);
  287.   outb (_com_parms[port].port_base + MSB_BAUD, (divisor & MASK_LSB) >> 8);
  288.  
  289.  
  290.   /* set 8250 line control register */
  291.  
  292.   outb (_com_parms[port].port_base + LCTL_REG, line_reg);
  293.  
  294.  
  295.   /* set IRQx interrupt to point to interrupt handler ;
  296.      enable 8259 IRQx interrupts;
  297.      enable 8250 data ready interrupts;
  298.      enable 8250 OUT2 ,DTR, RTS */
  299.  
  300.   cli ();
  301.  
  302.   if (port == 0)
  303.    {
  304.     /* IRQ4, com1: */
  305.     _lmove (2,IRQ4_VEC*4,  SYS_VEC,&_com_parms[port].org_int_off,data_seg);
  306.     _lmove (2,IRQ4_VEC*4+2,SYS_VEC,&_com_parms[port].org_int_seg,data_seg);
  307.  
  308.     int_handlr_addr = (unsigned) &int_c_handlr;
  309.     _lmove (2,&int_handlr_addr,data_seg,IRQ4_VEC*4,  SYS_VEC);
  310.     _lmove (2,&code_seg,       data_seg,IRQ4_VEC*4+2,SYS_VEC);
  311.  
  312.     outb (C8259_1, (inb (C8259_1) & ENBL_IRQ4));
  313.  
  314.    }
  315.  
  316.   else
  317.    {
  318.     /* IRQ3, com2: */
  319.     _lmove (2,IRQ3_VEC*4,  SYS_VEC,&_com_parms[port].org_int_off,data_seg);
  320.     _lmove (2,IRQ3_VEC*4+2,SYS_VEC,&_com_parms[port].org_int_seg,data_seg);
  321.  
  322.     int_handlr_addr = (unsigned) &int_b_handlr;
  323.     _lmove (2,&int_handlr_addr,data_seg,IRQ3_VEC*4,  SYS_VEC);
  324.     _lmove (2,&code_seg,       data_seg,IRQ3_VEC*4+2,SYS_VEC);
  325.  
  326.     outb (C8259_1, (inb (C8259_1) & ENBL_IRQ3));
  327.  
  328.    }
  329.  
  330.   /* save C data segment in interrupt handlr routine */
  331.   int_handlr_addr = (unsigned) &int_c_handlr + INT_DSEG;
  332.   _lmove (2,&data_seg,data_seg,int_handlr_addr,code_seg);
  333.  
  334.  
  335.   outb (_com_parms[port].port_base + INT_REG, DATA_RDY);
  336.  
  337.   outb (_com_parms[port].port_base + MDM_REG, OUT2_DR);
  338.  
  339.   sti ();
  340.  
  341.   return (TRUE);
  342.   /* end of init_com */
  343.  
  344. }
  345.  
  346.  
  347. /****************************************************************************/
  348.  
  349. /* port_chk
  350.  
  351.       parms:
  352.         port: 1 = com1:, 2 = com2:
  353.  
  354.    returns:
  355.       ERROR = com port never initialized, invalid port number
  356.       TRUE = ok
  357.  
  358. */
  359.  
  360. port_chk(port)
  361.  
  362. int port;
  363.  
  364. {
  365.   if (port < 1 || port > 2)
  366.     return (ERROR);
  367.  
  368.   if (_com_parms[--port].port_base == FALSE)
  369.     return (ERROR);
  370.  
  371.   return (TRUE);
  372.  
  373. }
  374.  
  375.  
  376. /****************************************************************************/
  377.  
  378. /* uninit_com
  379.  
  380.       parms:
  381.         port: 1 = com1:, 2 = com2:
  382.      lv_open: TRUE = leave comm open (DTR true), FALSE = turn off
  383.  
  384.    returns:
  385.       ERROR = com port never initialized
  386.       TRUE = ok
  387.  
  388. */
  389.  
  390.  
  391. uninit_com (port,lv_open)
  392.  
  393. int port;
  394. int lv_open;
  395.  
  396. {
  397.   int data_seg;
  398.   int code_seg;
  399.  
  400.   /*  get C program segment registers */
  401.  
  402.   data_seg = _showds ();
  403.   code_seg = _showcs ();
  404.  
  405.  
  406.   /* validate port; reset interrupts ; disable data ready, out2 */
  407.  
  408.   if (port_chk(port) == ERROR)
  409.     return (ERROR);
  410.   else
  411.     port--;
  412.  
  413.   cli ();
  414.  
  415.   /* restore original interrupt vectors, mask 8259 interrupt handling */
  416.   if (port == 0)
  417.    {
  418.     /* IRQ4, com1: */
  419.     _lmove (2,&_com_parms[port].org_int_off,data_seg,IRQ4_VEC*4,  SYS_VEC);
  420.     _lmove (2,&_com_parms[port].org_int_seg,data_seg,IRQ4_VEC*4+2,SYS_VEC);
  421.  
  422.     outb (C8259_1, inb (C8259_1) | DIS_IRQ4);
  423.    }
  424.   else
  425.    {
  426.     /* IRQ3, com2: */
  427.     _lmove (2,&_com_parms[port].org_int_off,data_seg,IRQ3_VEC*4,  SYS_VEC);
  428.     _lmove (2,&_com_parms[port].org_int_seg,data_seg,IRQ3_VEC*4+2,SYS_VEC);
  429.  
  430.     outb (C8259_1, inb (C8259_1) | DIS_IRQ3);
  431.    }
  432.  
  433.   /* disable 8250 interrupt generation */
  434.   outb (_com_parms[port].port_base + LCTL_REG,
  435.      inb (_com_parms[port].port_base + LCTL_REG) & DLAB_OFF);
  436.   outb (_com_parms[port].port_base + INT_REG, FALSE);
  437.  
  438.   /* leave serial port enabled if requested, else drop DTR */
  439.   if (!lv_open)
  440.     outb (_com_parms[port].port_base + MDM_REG, FALSE);
  441.  
  442.   sti ();
  443.  
  444.   /* free buffer storage */
  445.   free (_com_parms[port].buff_addr);
  446.   _com_parms[port].port_base = FALSE;
  447.  
  448.   return (TRUE);
  449.   /* end of uninit_com */
  450.  
  451. }
  452.  
  453.  
  454. /****************************************************************************/
  455.  
  456.  
  457. /* send_brk
  458.  
  459.       parms:
  460.         port: 1 = com1:, 2 = com2:
  461.  
  462.    returns:
  463.       ERROR = com port never initialized or bad parm
  464.       TRUE = ok
  465.  
  466. */
  467.  
  468.  
  469. send_brk (port)
  470.  
  471. int port;
  472.  
  473. {
  474.  
  475.   int line_reg;
  476.   int ticks;
  477.   int count;
  478.  
  479.   struct
  480.    {int ax,bx,cx,dx,si,di,ds,es;} r;
  481.  
  482.   r.ax = r.bx = r.cx = r.dx = r.si = r.di = r.ds = r.es = 0;
  483.  
  484.   /* validate port; send break (1/2 second) */
  485.  
  486.   if (port_chk(port) == ERROR)
  487.     return (ERROR);
  488.   else
  489.     port--;
  490.  
  491.   /* get current line reg */
  492.   line_reg = inb (_com_parms[port].port_base + LCTL_REG);
  493.  
  494.   /* set break */
  495.   outb (_com_parms[port].port_base + LCTL_REG, line_reg | BREAK_ON);
  496.  
  497.   /* delay for 1/2 second using time-of-day counter */
  498.   /* dx returned is the lower 16 bits of the counter */
  499.   for (count = 0; count < HALF_SEC; count++)
  500.    {
  501.     sysint (TIME_OF_DAY,&r,&r);
  502.     ticks = r.dx;
  503.     while (ticks == r.dx)
  504.       sysint (TIME_OF_DAY,&r,&r);
  505.    }
  506.  
  507.   /* reset line reg */
  508.   outb (_com_parms[port].port_base + LCTL_REG, line_reg);
  509.  
  510.  
  511.   return (TRUE);
  512.   /* end of send_brk */
  513.  
  514. }
  515.  
  516.  
  517. /****************************************************************************/
  518.  
  519. /* set_xoff
  520.  
  521.       parms:
  522.         port: 1 = com1:, 2 = com2:
  523.        state: TRUE = XON/XOFF enabled, FALSE = XON/XOFF disabled
  524.  
  525.    returns:
  526.       ERROR = com port never initialized
  527.       TRUE = ok
  528.  
  529. */
  530.  
  531.  
  532. set_xoff (port,state)
  533.  
  534. int port;
  535. int state;
  536.  
  537. {
  538.  
  539.   /* validate port */
  540.   if (port_chk(port) == ERROR)
  541.     return (ERROR);
  542.   else
  543.     port--;
  544.  
  545.   /* set XON/XOFF state */
  546.   _com_parms[port].x_state = state;
  547.  
  548.   /* reset flags */
  549.   _com_parms[port].x_recd = FALSE;
  550.   _com_parms[port].x_sent = FALSE;
  551.  
  552.   return (TRUE);
  553.   /* end of set_xoff */
  554.  
  555. }
  556.  
  557.  
  558. /****************************************************************************/
  559.  
  560. /* recd_xoff
  561.  
  562.       parms:
  563.         port: 1 = com1:, 2 = com2:
  564.  
  565.    returns:
  566.       ERROR = com port never initialized
  567.       FALSE = XOFF never received
  568.       TRUE = XOFF received
  569.  
  570. */
  571.  
  572.  
  573. recd_xoff (port)
  574.  
  575. int port;
  576.  
  577. {
  578.   int state;
  579.  
  580.   /* validate port */
  581.   if (port_chk(port) == ERROR)
  582.     return (ERROR);
  583.   else
  584.     port--;
  585.  
  586.  
  587.   state = _com_parms[port].x_recd;
  588.  
  589.   _com_parms[port].x_recd = FALSE;
  590.  
  591.   return (state);
  592.   /* end of recd_xoff */
  593.  
  594. }
  595.  
  596.  
  597. /****************************************************************************/
  598.  
  599. /* sent_xoff
  600.  
  601.       parms:
  602.         port: 1 = com1:, 2 = com2:
  603.  
  604.    returns:
  605.       ERROR = com port never initialized
  606.       FALSE = XOFF never sent
  607.       TRUE = XOFF sent
  608.  
  609. */
  610.  
  611.  
  612. sent_xoff (port)
  613.  
  614. int port;
  615.  
  616. {
  617.   int state;
  618.  
  619.   /* validate port */
  620.   if (port_chk(port) == ERROR)
  621.     return (ERROR);
  622.   else
  623.     port--;
  624.  
  625.  
  626.   state = _com_parms[port].x_sent;
  627.  
  628.   _com_parms[port].x_sent = FALSE;
  629.  
  630.   return (state);
  631.   /* end of sent_xoff */
  632.  
  633. }
  634.  
  635.  
  636. /****************************************************************************/
  637.  
  638. /* inp_cnt
  639.  
  640.       parms:
  641.         port: 1 = com1:, 2 = com2:
  642.  
  643.    returns:
  644.       ERROR = com port never initialized, bad parm
  645.       other = number of bytes in buffer
  646.  
  647. */
  648.  
  649.  
  650. inp_cnt (port)
  651.  
  652. int port;
  653.  
  654. {
  655.  
  656.   /* validate port */
  657.   if (port_chk(port) == ERROR)
  658.     return (ERROR);
  659.   else
  660.     port--;
  661.  
  662.  
  663.   return (_com_parms[port].buff_cnt);
  664.   /* end of inp_cnt */
  665.  
  666. }
  667.  
  668.  
  669.  
  670. /****************************************************************************/
  671.  
  672. /* inp_char
  673.  
  674.       parms:
  675.         port: 1 = com1:, 2 = com2:
  676.  
  677.    returns:
  678.       ERROR = com port never initialized, bad parm, nothing to get
  679.       other = next (FIFO) char in buffer
  680.  
  681. */
  682.  
  683.  
  684. inp_char (port)
  685.  
  686. int port;
  687.  
  688. {
  689.   char c;
  690.  
  691.   /* validate port */
  692.   if (port_chk(port) == ERROR)
  693.     return (ERROR);
  694.   else
  695.     port--;
  696.  
  697.  
  698.   if (_com_parms[port].buff_cnt)
  699.    {
  700.     _com_parms[port].buff_cnt--;
  701.     c = *_com_parms[port].buff_tail;
  702.  
  703.     if ( (unsigned int) ++_com_parms[port].buff_tail >=
  704.      (unsigned int)   _com_parms[port].buff_addr +
  705.      (unsigned int)   _com_parms[port].buff_len   )
  706.       _com_parms[port].buff_tail = _com_parms[port].buff_addr;
  707.  
  708.     return (c);
  709.    }
  710.   else
  711.    return (ERROR);
  712.  
  713.   /* end of inp_char */
  714.  
  715. }
  716.  
  717.  
  718.  
  719. /****************************************************************************/
  720.  
  721. /* inp_strn
  722.  
  723.       parms:
  724.         port: 1 = com1:, 2 = com2:
  725.         addr: address of string to put incoming chars
  726.          cnt: number of bytes to transfer (up to actual number in buffer)
  727.  
  728.    returns:
  729.       ERROR = com port never initialized, bad parm, nothing to get
  730.       other = the actual number of chars transferred
  731.  
  732. */
  733.  
  734.  
  735. inp_strn (port,addr,cnt)
  736.  
  737. int port;
  738. char *addr;
  739. int cnt;
  740.  
  741. {
  742.   int rest_buff;
  743.  
  744.   /* validate port */
  745.   if (port_chk(port) == ERROR)
  746.     return (ERROR);
  747.   else
  748.     port--;
  749.  
  750.   /* max transfer = buff count */
  751.   if (cnt > _com_parms[port].buff_cnt)
  752.     cnt = _com_parms[port].buff_cnt;
  753.  
  754.   if (cnt)
  755.    {
  756.     rest_buff = ( (unsigned int) _com_parms[port].buff_addr +
  757.           (unsigned int) _com_parms[port].buff_len ) -
  758.         (unsigned int) _com_parms[port].buff_tail;
  759.  
  760.     if (cnt > rest_buff)
  761.      {
  762.        /* circle around buffer */
  763.        _move(rest_buff,_com_parms[port].buff_tail,addr);
  764.        _move(cnt - rest_buff,_com_parms[port].buff_addr,addr + rest_buff);
  765.        _com_parms[port].buff_tail =
  766.          (unsigned int) _com_parms[port].buff_addr + (cnt - rest_buff);
  767.       }
  768.     else
  769.       {
  770.        _move(cnt,_com_parms[port].buff_tail,addr);
  771.        _com_parms[port].buff_tail += cnt;
  772.        if (cnt == rest_buff)
  773.      _com_parms[port].buff_tail = _com_parms[port].buff_addr;
  774.       }
  775.  
  776.     _com_parms[port].buff_cnt -= cnt;
  777.     return (cnt);
  778.  
  779.    }
  780.  
  781.   else
  782.    return (ERROR);
  783.  
  784.   /* end of inp_strn */
  785.  
  786. }
  787.  
  788.  
  789.  
  790. /****************************************************************************/
  791.  
  792. /* outp_char
  793.  
  794.       parms:
  795.         port: 1 = com1:, 2 = com2:
  796.            c: the character to send
  797.  
  798.    returns:
  799.       TRUE = OK
  800.       ERROR = timeout condition
  801.  
  802.  
  803. */
  804.  
  805.  
  806. outp_char (port,c)
  807.  
  808. int  port;
  809. char c;
  810.  
  811. {
  812.  
  813.   unsigned int time_out;
  814.  
  815.   /* validate port; return state */
  816.   if (port_chk(port) == ERROR)
  817.     return (ERROR);
  818.   else
  819.     port--;
  820.  
  821.   /* wait for THRE (transmitter holding register empty) */
  822.  
  823.   for (time_out = TIME;
  824.        (inb (_com_parms[port].port_base + LCTL_STAT) & THRE) == FALSE
  825.       && time_out > 0;
  826.        time_out--)
  827.     ;
  828.  
  829.   if (time_out == 0)
  830.     /* THRE timeout error */
  831.     return (ERROR);
  832.  
  833.  
  834.   /* everything ok, send it */
  835.  
  836.   outb (_com_parms[port].port_base + DATAPORT, c);
  837.  
  838.   return (TRUE);
  839.   /* end of outp_char */
  840.  
  841. }
  842.  
  843.  
  844. /****************************************************************************/
  845.  
  846. /* outp_strn
  847.  
  848.       parms:
  849.         port: 1 = com1:, 2 = com2:
  850.         addr: the string to send
  851.          cnt: the maximum number of characters to send
  852.  
  853.    returns:
  854.       TRUE = OK
  855.       ERROR = timeout condition
  856.  
  857.  
  858. */
  859.  
  860.  
  861. outp_strn (port,addr,cnt)
  862.  
  863. int  port;
  864. char addr[];
  865. int cnt;
  866.  
  867. {
  868.   int n;
  869.  
  870.   for (n = 0; n <= cnt && addr[n] != '\0'; n++)
  871.     if (outp_char(port,addr[n]) == ERROR)
  872.       return (ERROR);
  873.  
  874.  
  875.   return (TRUE);
  876.   /* end of outp_strn */
  877.  
  878. }
  879.  
  880.  
  881. /****************************************************************************/
  882.  
  883. /* com_stat
  884.  
  885.       parms:
  886.         port: 1 = com1:, 2 = com2:
  887.  
  888.    returns:
  889.       line status (MSB) and modem status (LSB)
  890.       ERROR = invalid com port, never initialized
  891.  
  892.  
  893. */
  894.  
  895.  
  896. com_stat (port)
  897.  
  898. int  port;
  899.  
  900. {
  901.   int status;
  902.  
  903.   /* validate port */
  904.   if (port_chk(port) == ERROR)
  905.     return (ERROR);
  906.   else
  907.     port--;
  908.  
  909.   status = inb (_com_parms[port].port_base + LCTL_STAT) << 8;
  910.  
  911.   status |= inb (_com_parms[port].port_base + MDM_STAT);
  912.  
  913.   return (status);
  914.   /* end of com_stat */
  915.  
  916. }
  917.  
  918.  
  919. /****************************************************************************/
  920.  
  921. /* on_com
  922.  
  923.       parms:
  924.         port: 1 = com1:, 2 = com2:
  925.          rtn: pointer to a C routine
  926.  
  927.    returns:
  928.       TRUE = ok
  929.       ERROR = invalid com port, never initialized
  930.  
  931.  
  932. */
  933.  
  934.  
  935. on_com (port,rtn)
  936.  
  937. int  port;
  938. int  (*rtn)();
  939.  
  940. {
  941.  
  942.   /* validate port */
  943.   if (port_chk(port) == ERROR)
  944.     return (ERROR);
  945.   else
  946.     port--;
  947.  
  948.   _com_parms[port].on_com_rtn = rtn;
  949.  
  950.   return (TRUE);
  951.   /* end of on_com */
  952.  
  953. }
  954.  
  955.  
  956. /****************************************************************************/
  957.  
  958.  
  959. /* end of commsupp.c */
  960.