home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / ctask.zip / TSKSIO.C < prev    next >
C/C++ Source or Header  |  1988-03-01  |  15KB  |  583 lines

  1. /*
  2.    TSKSIO.C - CTask - Serial I/O interface routines.
  3.  
  4.    Public Domain Software written by
  5.       Thomas Wagner
  6.       Patschkauer Weg 31
  7.       D-1000 Berlin 33
  8.       West Germany
  9. */
  10.  
  11.  
  12. #include "tsk.h"
  13. #include "sio.h"
  14.  
  15. #define MK_FP(seg,ofs)    ((farptr)(((dword)(seg) << 16) | (ofs)))
  16. typedef void (interrupt far * intprocptr)(void);
  17.  
  18. #define RTS       0x02
  19. #define DTR       0x01
  20.  
  21. #define ERR_MASK  0x1e
  22.  
  23. #define inta00    0x20   /* 8259 interrupt controller control-port */
  24. #define inta01    0x21   /* 8259 interrupt controller mask-port */
  25.  
  26. #define rdserv    0x0b   /* read service register control value */
  27. #define eoi       0x20   /* end of interrupt signal for 8259 */
  28.  
  29. #define intdata   0x0b   /* Enable Interrupts except Line status */
  30.  
  31. #define rxreadybit 0x01
  32. #define txemptybit 0x40
  33. #define txreadybit 0x20
  34. #define framingbit 0x08
  35. #define breakbit   0x10
  36.  
  37. #define linecontrol  0x0b
  38. #define linestatus   0x0d
  39. #define intid        0x0a
  40. #define intenable    0x09
  41. #define modemcontrol 0x0c
  42. #define modemstatus  0x0e
  43. #define receivedata  0x08
  44. #define transmitdata 0x08
  45.  
  46. #define baudreg_dll  0x08     /* baud rate least significant byte */
  47. #define baudreg_dlm  0x09     /* baud rate most significant byte */
  48.  
  49. /*
  50.    Default values for initialising the ports.
  51.    Change to your liking.
  52. */
  53.  
  54. #define dflt_modcon 0x0f   /* Modem Control: Activate DTR & RTS */
  55. #define dflt_baud   96     /* Baud Rate Divisor: 1200 Baud */
  56. #define dflt_lcon   0x03   /* Line Control: No Parity, 1 Stop, 8 Data */
  57.  
  58.  
  59. /*
  60.    To add support for other COM-Ports, define
  61.       - Port base
  62.       - IRQ-Bit
  63.       - Interrupt vector
  64.    here, add the necessary data to the port_descr array,
  65.    and define the corresponding interrupt function by duplicating sioint0,
  66.    replacing the index into the sio_data array.
  67. */
  68.  
  69. #define PORTS  2              /* Number of defined ports */
  70.  
  71. #define com1_base    0x3f0    /* COM1 port base */
  72. #define com2_base    0x2f0    /* COM2 port base */
  73.  
  74. #define com1_irq     0x10     /* IRQ-Bit for COM1 */
  75. #define com2_irq     0x08     /* IRQ-Bit for COM2 */
  76.  
  77. #define com1_vect    0x0c     /* Interrupt vector for COM1 */
  78. #define com2_vect    0x0b     /* Interrupt vector for COM2 */
  79.  
  80. typedef struct {
  81.                intprocptr  proc;
  82.                int         base;
  83.                byte        irq;
  84.                byte        vector;
  85.                } port_data;
  86.  
  87. local void interrupt far sioint0 (void);
  88. local void interrupt far sioint1 (void);
  89.  
  90. port_data port_descr [PORTS] = {
  91.                                  { sioint0, com1_base, com1_irq, com1_vect },
  92.                                  { sioint1, com2_base, com2_irq, com2_vect }
  93.                                };
  94.  
  95.  
  96. static long baud_table [] = {
  97.                                50L, 2304L,
  98.                                75L, 1536L,
  99.                               110L, 1047L,
  100.                               134L,  857L,
  101.                               150L,  768L,
  102.                               300L,  384L,
  103.                               600L,  192L,
  104.                              1200L,   96L,
  105.                              1800L,   64L,
  106.                              2000L,   58L,
  107.                              2400L,   48L,
  108.                              3600L,   32L,
  109.                              4800L,   24L,
  110.                              7200L,   16L,
  111.                              9600L,   12L,
  112.                             19200L,    6L,
  113.                             38400L,    3L,
  114.                                 0L,    0L };
  115.  
  116. /*-------------------------------------------------------------------------*/
  117.  
  118. typedef struct {
  119.                farptr   savvect;       /* Interrupt vector save location */
  120.                int      port_base;     /* Port base I/O address */
  121.                int      r_xoff;        /* Receive disable (XOFF sent) */
  122.                int      t_xoff;        /* Transmit disable (XOFF received) */
  123.                     int        xoff_threshold; /* Pipe free threshold for XOFF */
  124.                     int        xon_threshold; /* Pipe free threshold for XON */
  125.                byte     clcontrol;     /* Current line control reg */
  126.                byte     cmodcontrol;   /* Current modem control reg */
  127.                byte     irqbit;        /* IRQ-Bit for this port */
  128.                byte     civect;        /* Interrupt Vector for this port */
  129.                byte     modstat;       /* Current modem status */
  130.                byte     wait_xmit;     /* Transmit delayed */
  131.                byte     xmit_pending;  /* Transmit in progress */
  132.                byte     rtsoff;        /* RTS turned off by protocol */
  133.                byte     overrun;       /* Pipe full on receive */
  134.                byte     modem_flags;   /* Transmit enable modem flags */
  135.                byte     flags;         /* Protocol flags */
  136.  
  137.                wpipe    rcv_pipe;      /* Received characters */
  138.                pipe     xmit_pipe;     /* Transmit pipe */
  139.  
  140.                } sio_datarec;
  141.  
  142. typedef sio_datarec *sioptr;
  143.  
  144. static sio_datarec sio_data [PORTS];
  145.  
  146. /*-------------------------------------------------------------------------*/
  147.  
  148. local void near change_rts (sioptr data, int on)
  149. {
  150.    data->rtsoff = (byte)(!on);
  151.    data->cmodcontrol = (data->cmodcontrol & ~RTS) | ((on) ? RTS : 0);
  152.    tsk_outp (data->port_base + modemcontrol, data->cmodcontrol);
  153. }
  154.  
  155.  
  156. local void near transmit_ready (sioptr data)
  157. {
  158.    int i;
  159.  
  160.    if ((i = data->r_xoff) < 0)
  161.       {
  162.       tsk_outp (data->port_base + transmitdata, 
  163.                 (byte)((i == -1) ? XOFF : XON));
  164.       data->r_xoff = (i == -1) ? 1 : 0;
  165.       data->xmit_pending = 1;
  166.       return;
  167.       }
  168.  
  169.    data->xmit_pending = 0;
  170.  
  171.    if (!(data->wait_xmit = (byte)(check_pipe (&data->xmit_pipe) != -1)))
  172.       return;
  173.  
  174.    if ((data->modem_flags & data->modstat) ^ data->modem_flags)
  175.       return;
  176.  
  177.    if (data->flags & XONXOFF && data->t_xoff)
  178.       return;
  179.  
  180.    data->wait_xmit = 0;
  181.  
  182.    if ((i = c_read_pipe (&data->xmit_pipe)) < 0)
  183.       return;
  184.  
  185.    tsk_outp (data->port_base + transmitdata, (byte)i);
  186.    data->xmit_pending = 1;
  187. }
  188.  
  189.  
  190. local void near modem_status_int (sioptr data)
  191. {
  192.    data->modstat = tsk_inp (data->port_base + modemstatus);
  193.  
  194.    if (data->wait_xmit)
  195.       transmit_ready (data);
  196. }
  197.  
  198.  
  199. local void near receive_ready (sioptr data)
  200. {
  201.    word status;
  202.    word ch;
  203.  
  204.    while ((status = tsk_inp (data->port_base + linestatus)) & rxreadybit)
  205.       {
  206.       ch = tsk_inp (data->port_base + receivedata);
  207.  
  208.       if (data->flags & XONXOFF)
  209.          {
  210.          if (ch == XON)
  211.             {
  212.             data->t_xoff = 0;
  213.             if (data->wait_xmit)
  214.                transmit_ready (data);
  215.             continue;
  216.             }
  217.          else if (ch == XOFF)
  218.             {
  219.             data->t_xoff = 1;
  220.             continue;
  221.             }
  222.          if (!data->r_xoff && 
  223.              wpipe_free (&data->rcv_pipe) < data->xoff_threshold)
  224.             {
  225.             data->r_xoff = -1;
  226.             if (!data->xmit_pending)
  227.                transmit_ready (data);
  228.             }
  229.          }
  230.  
  231.       if (data->flags & RTSCTS && !data->rtsoff)
  232.          if (wpipe_free (&data->rcv_pipe) < data->xoff_threshold)
  233.             change_rts (data, 0);
  234.  
  235.       status = (status & ERR_MASK) << 8;
  236.       if (c_write_wpipe (&data->rcv_pipe, ch | status) < 0)
  237.          data->overrun = 1;
  238.       }
  239. }
  240.  
  241.  
  242. /*-------------------------------------------------------------------------*/
  243.  
  244.  
  245. local void near sioint (sioptr data)
  246. {
  247.    int id;
  248.  
  249.    tsk_sti ();
  250.    while (!((id = tsk_inp (data->port_base + intid)) & 1))
  251.       switch (id & 0x07)
  252.          {
  253.          case 0x00:  modem_status_int (data);
  254.                      break;
  255.  
  256.          case 0x02:  transmit_ready (data);
  257.                      break;
  258.  
  259.          case 0x04:  receive_ready (data);
  260.                      break;
  261.  
  262. /*       case 0x06:  line_status_int (data); (currently not used)
  263.                      break;
  264. */
  265.          }
  266.    tsk_cli ();
  267.    tsk_outp (inta00, eoi);
  268. }
  269.  
  270.  
  271. local void interrupt far sioint0 (void)
  272. {
  273.    sioint (&sio_data [0]);
  274. }
  275.  
  276. local void interrupt far sioint1 (void)
  277. {
  278.    sioint (&sio_data [1]);
  279. }
  280.  
  281. /*-------------------------------------------------------------------------*/
  282.  
  283.  
  284. int far v24_install (int port, 
  285.                      farptr rcvbuf, word rcvsize,
  286.                      farptr xmitbuf, word xmitsize)
  287. {
  288.    sioptr sio;
  289.    int pbase;
  290.    intprocptr far *intptr;
  291.  
  292.    if (port < 0 || port >= PORTS || !rcvsize || !xmitsize)
  293.       return -1;
  294.  
  295.    sio = &sio_data [port];
  296.  
  297.    create_pipe (&sio->xmit_pipe, xmitbuf, xmitsize);
  298.    create_wpipe (&sio->rcv_pipe, rcvbuf, rcvsize);
  299.  
  300.    pbase = sio->port_base = port_descr [port].base;
  301.    sio->civect = port_descr [port].vector;
  302.    sio->irqbit = port_descr [port].irq;
  303.  
  304.    sio->clcontrol = dflt_lcon;
  305.    sio->cmodcontrol = dflt_modcon;
  306.    sio->wait_xmit = sio->xmit_pending = 0;
  307.    sio->overrun = 0;
  308.    sio->flags = 0;
  309.    sio->modem_flags = 0;
  310.    sio->r_xoff = sio->t_xoff = 0;
  311.    sio->rtsoff = 0;
  312.  
  313.    tsk_outp (pbase + intenable, 0);
  314.  
  315.    intptr = (intprocptr far *)MK_FP (0, sio->civect * 4);
  316.    tsk_cli ();
  317.    sio->savvect = *intptr;
  318.    *intptr = port_descr [port].proc;
  319.    tsk_sti ();
  320.  
  321.    tsk_outp (pbase + linecontrol, dflt_lcon | 0x80);
  322.    tsk_outp (pbase + baudreg_dll, dflt_baud);
  323.    tsk_outp (pbase + baudreg_dlm, dflt_baud >> 8);
  324.    tsk_outp (pbase + linecontrol, dflt_lcon);
  325.    tsk_outp (pbase + modemcontrol, dflt_modcon);
  326.    while (tsk_inp (pbase + linestatus) & rxreadybit)
  327.       tsk_inp (pbase + receivedata);
  328.    tsk_inp (pbase + linestatus);
  329.    sio->modstat = tsk_inp (pbase + modemstatus);
  330.    tsk_inp (pbase + intid);
  331.  
  332.    tsk_outp (inta01, tsk_inp (inta01) & ~sio->irqbit);
  333.    tsk_outp (pbase + intenable, intdata);
  334.     return 0;
  335.    }
  336.  
  337.  
  338. void far v24_remove (int port)
  339.    {
  340.    sioptr sio;
  341.    intprocptr far *intptr;
  342.  
  343.    sio = &sio_data [port];
  344.    tsk_outp (sio->port_base + intenable, 0);
  345.    tsk_outp (inta01, tsk_inp (inta01) | sio->irqbit);
  346.    intptr = (intprocptr far *)MK_FP (0, sio->civect * 4);
  347.    tsk_cli ();
  348.    *intptr = sio->savvect;
  349.    tsk_sti ();
  350.  
  351.    delete_pipe (&sio->xmit_pipe);
  352.    delete_wpipe (&sio->rcv_pipe);
  353.    }
  354.  
  355.  
  356. /*-------------------------------------------------------------------------*/
  357.  
  358. /*
  359.    void v24_change_rts (int port, int on)
  360. */
  361.  
  362. void far v24_change_rts (int port, int on)
  363. {
  364.    sioptr sio;
  365.  
  366.    sio = &sio_data [port];
  367.    sio->cmodcontrol = (sio->cmodcontrol & ~RTS) | ((on) ? RTS : 0);
  368.    tsk_outp (sio->port_base + modemcontrol, sio->cmodcontrol);
  369. }
  370.  
  371. /*
  372.    void v24_change_dtr (int port, int on)
  373. */
  374.  
  375. void far v24_change_dtr (int port, int on)
  376. {
  377.    sioptr sio;
  378.  
  379.    sio = &sio_data [port];
  380.    sio->cmodcontrol = (sio->cmodcontrol & ~DTR) | ((on) ? DTR : 0);
  381.    tsk_outp (sio->port_base + modemcontrol, sio->cmodcontrol);
  382. }
  383.  
  384.  
  385. /*
  386.    void far v24_change_baud (int port, int rate)
  387. */
  388.  
  389. void far v24_change_baud (int port, long rate)
  390. {
  391.    int i;
  392.    sioptr sio;
  393.  
  394.    sio = &sio_data [port];
  395.  
  396.    for (i = 0; baud_table [i]; i += 2)
  397.       if (baud_table [i] == rate)
  398.          break;
  399.    if (!(i = (int)baud_table [i + 1]))
  400.       return;
  401.  
  402.    tsk_outp (sio->port_base + linecontrol, sio->clcontrol | (byte)0x80);
  403.    tsk_outp (sio->port_base + baudreg_dll, (byte)i);
  404.    tsk_outp (sio->port_base + baudreg_dlm, (byte)(i >> 8));
  405.    tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
  406. }
  407.  
  408.  
  409. void far v24_change_parity (int port, int par)
  410. {
  411.    sioptr sio;
  412.  
  413.    sio = &sio_data [port];
  414.  
  415.    sio->clcontrol = (sio->clcontrol & 0xc7) | par;
  416.    tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
  417. }
  418.  
  419.  
  420. void far v24_change_wordlength (int port, int len)
  421. {
  422.    int i;
  423.    sioptr sio;
  424.  
  425.    sio = &sio_data [port];
  426.  
  427.    switch (len)
  428.       {
  429.       case 5:  i = 0x00; break;
  430.       case 6:  i = 0x01; break;
  431.       case 7:  i = 0x02; break;
  432.       case 8:  i = 0x03; break;
  433.       default: return;
  434.       }
  435.    sio->clcontrol = (sio->clcontrol & 0xfc) | i;
  436.    tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
  437. }
  438.  
  439.  
  440. void far v24_change_stopbits (int port, int n)
  441. {
  442.    int i;
  443.    sioptr sio;
  444.  
  445.    sio = &sio_data [port];
  446.  
  447.    switch (n)
  448.       {
  449.       case 1:  i = 0x00; break;
  450.       case 2:  i = 0x04; break;
  451.       default: return;
  452.       }
  453.    sio->clcontrol = (sio->clcontrol & 0xfb) | i;
  454.    tsk_outp (sio->port_base + linecontrol, sio->clcontrol);
  455. }
  456.  
  457.  
  458. void far v24_watch_modem (int port, byte flags)
  459. {
  460.    sio_data [port].modem_flags = flags & (CTS | DSR | RI | CD);
  461. }
  462.  
  463.  
  464. void far v24_protocol (int port, int prot, word offthresh, word onthresh)
  465. {
  466.    byte old;
  467.    sioptr sio;
  468.    
  469.    sio = &sio_data [port];
  470.    old = sio->flags;
  471.    sio->flags = (byte)prot;
  472.    if (prot)
  473.       {
  474.       if (!offthresh)
  475.          offthresh = 10;
  476.       sio->xoff_threshold = offthresh;
  477.       if (onthresh <= offthresh)
  478.          onthresh = offthresh + 10;
  479.       sio->xon_threshold = onthresh;
  480.       }
  481.  
  482.    if ((old & RTSCTS) != ((byte)prot & RTSCTS))
  483.       {
  484.       change_rts (sio, 1);
  485.       sio->modem_flags = (sio->modem_flags & ~CTS) |
  486.                          ((prot & RTSCTS) ? CTS : 0);
  487.       }
  488.  
  489.    if (!(prot & XONXOFF))
  490.       {
  491.       if (sio->r_xoff)
  492.          sio->r_xoff = -2;
  493.       sio->t_xoff = 0;
  494.       }
  495.  
  496.    if (!sio->xmit_pending)
  497.       transmit_ready (sio);
  498. }
  499.  
  500.  
  501. /*-------------------------------------------------------------------------*/
  502.  
  503.  
  504. int far v24_send (int port, byte ch, dword timeout)
  505. {
  506.    int res;
  507.  
  508.    if ((res = write_pipe (&sio_data [port].xmit_pipe, ch, timeout)) < 0)
  509.       return res;
  510.    tsk_cli ();
  511.    if (!sio_data [port].xmit_pending)
  512.       transmit_ready (&sio_data [port]);
  513.    tsk_sti ();
  514.    return 0;
  515. }
  516.  
  517.  
  518. int far v24_receive (int port, dword timeout)
  519. {
  520.    int res;
  521.    sioptr sio;
  522.    
  523.    sio = &sio_data [port];
  524.  
  525.    if ((res = (int)read_wpipe (&sio->rcv_pipe, timeout)) < 0)
  526.       return res;
  527.  
  528.    if (!sio->flags)
  529.       return res;
  530.  
  531.    if (wpipe_free (&sio->rcv_pipe) > sio->xon_threshold)
  532.       {
  533.       tsk_cli ();
  534.       if (sio->r_xoff)
  535.          {
  536.          sio->r_xoff = -2;
  537.          if (!sio->xmit_pending)
  538.             transmit_ready (sio);
  539.          }
  540.       tsk_sti ();
  541.  
  542.       if (sio->rtsoff)
  543.          change_rts (sio, 1);
  544.       }
  545.    return res;
  546. }
  547.  
  548.  
  549. int far v24_overrun (int port)
  550. {
  551.    int res;
  552.  
  553.    res = sio_data [port].overrun;
  554.    sio_data [port].overrun = 0;
  555.    return res;
  556. }
  557.  
  558.  
  559. int far v24_check (int port)
  560. {
  561.    return check_wpipe (&sio_data [port].rcv_pipe);
  562. }
  563.  
  564.  
  565. int far v24_modem_status (int port)
  566. {
  567.    return sio_data [port].modstat;
  568. }
  569.  
  570.  
  571. int far v24_complete (int port)
  572. {
  573.    return (check_pipe (&sio_data [port].xmit_pipe) == -1);
  574. }
  575.  
  576.  
  577. int far v24_wait_complete (int port, dword timeout)
  578. {
  579.    return wait_pipe_empty (&sio_data [port].xmit_pipe, timeout);
  580. }
  581.  
  582.  
  583.