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

  1. /*
  2.    TSKPRN.C - CTask - Printer 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 "prt.h"
  14.  
  15. #define STKSZ     256   /* Printer Task stack size */
  16.  
  17. /*
  18.    The following values may need some tuning for optimum performance.
  19. */
  20. /* 
  21.    MAX_WAIT_xx: Maximum number of times through the loop when waiting
  22.                 for the printer to get ready.
  23. */
  24.  
  25. #define MAX_WAIT_INT    30 /* For interrupt output */
  26. #define MAX_WAIT_POLL   30 /* For polling output */
  27.  
  28. /* 
  29.    xx_DELAY: Ticks to wait before trying again when printer was not ready.
  30. */
  31.  
  32. #define INT_DELAY    5L  /* For interrupt output */
  33. #define POLL_DELAY   5L  /* For polling output */
  34.  
  35. #define INT_TIMEOUT  2L  /* Timeout for ACK interrupt wait */
  36.  
  37.  
  38. #define MK_FP(seg,ofs)    ((farptr)(((dword)(seg) << 16) | (ofs)))
  39. typedef void (interrupt far * intprocptr)(void);
  40.  
  41. #define inta00    0x20   /* 8259 interrupt controller control-port */
  42. #define inta01    0x21   /* 8259 interrupt controller mask-port */
  43.  
  44. #define rdserv    0x0b   /* read service register control value */
  45. #define eoi       0x20   /* end of interrupt signal for 8259 */
  46.  
  47. #define data      0x00
  48. #define status    0x01
  49. #define control   0x02
  50.  
  51. #define STROBE    0x01
  52. #define IRQENA    0x10
  53.  
  54. #define dflt_control    (INIT | SELECT)
  55.  
  56.  
  57. /*
  58.    To add support for other LPT-Ports, define
  59.       - Port base
  60.       - IRQ-Bit (optional)
  61.       - Interrupt vector (optional)
  62.    here, add the necessary data to the pr_port_descr array, and, if irq
  63.    was specified, define the corresponding interrupt function by 
  64.    duplicating prtint0, replacing the index into the prt_data array.
  65. */
  66.  
  67. #define PORTS  3              /* Number of defined ports */
  68.  
  69. #define lpt1_base    0x3bc    /* LPT1 port base (mono card) */
  70. #define lpt2_base    0x378    /* LPT2 port base (IBM printer adapter) */
  71. #define lpt3_base    0x278    /* LPT3 port base (secondary parallel) */
  72.  
  73. #define lpt1_irq     0x80     /* IRQ-Bit for LPT1 */
  74. #define lpt2_irq     0x80     /* IRQ-Bit for LPT2 */
  75. #define lpt3_irq     0x20     /* IRQ-Bit for LPT3 */
  76.  
  77. #define lpt1_vect    0x0f     /* Interrupt vector for LPT1 */
  78. #define lpt2_vect    0x0f     /* Interrupt vector for LPT2 */
  79. #define lpt3_vect    0x0d     /* Interrupt vector for LPT3 */
  80.  
  81. typedef struct {
  82.                intprocptr  proc;
  83.                int         base;
  84.                byte        irq;
  85.                byte        vector;
  86.                } port_data;
  87.  
  88. local void interrupt far prtint0 (void);
  89. local void interrupt far prtint1 (void);
  90. local void interrupt far prtint2 (void);
  91.  
  92. port_data pr_port_descr [PORTS] = {
  93.                                  { prtint0, lpt1_base, lpt1_irq, lpt1_vect },
  94.                                  { prtint1, lpt2_base, lpt2_irq, lpt2_vect },
  95.                                  { prtint2, lpt3_base, lpt3_irq, lpt3_vect }
  96.                                   };
  97.  
  98. /*-------------------------------------------------------------------------*/
  99.  
  100. typedef struct {
  101.                farptr   savvect;       /* Interrupt vector save location */
  102.                int      port_base;     /* Port base I/O address */
  103.                byte     irqbit;        /* IRQ-Bit for this port */
  104.                byte     civect;        /* Interrupt Vector for this port */
  105.                byte     wait_xmit;     /* Transmit delayed */
  106.                byte     xmit_pending;  /* Transmit in progress */
  107.                byte     polling;       /* Use polling if on */
  108.                     byte        ccontrol;        /* Current control reg */
  109.                pipe     xmit_pipe;     /* Transmit pipe */
  110.                flag     pready;        /* Printer ready flag */
  111.                tcb      pr_task;       /* Printer task */
  112.                byte     pr_stack [STKSZ]; /* Printer task stack */
  113.                } prt_datarec;
  114.  
  115. typedef prt_datarec *prtptr;
  116.  
  117. static prt_datarec prt_data [PORTS];
  118.  
  119. /*-------------------------------------------------------------------------*/
  120.  
  121. local void near prtint (prtptr prt)
  122. {
  123.    /* Turn off int */
  124.    prt->ccontrol &= ~IRQENA;
  125.    tsk_outp (prt->port_base + control, prt->ccontrol);
  126.  
  127.    /* Signal print char complete */
  128.    set_flag (&prt->pready);
  129.    tsk_outp (inta00, eoi);
  130. }
  131.  
  132.  
  133. local void interrupt far prtint0 (void)
  134. {
  135.    prtint (&prt_data [0]);
  136. }
  137.  
  138. local void interrupt far prtint1 (void)
  139. {
  140.    prtint (&prt_data [1]);
  141. }
  142.  
  143. local void interrupt far prtint2 (void)
  144. {
  145.    prtint (&prt_data [2]);
  146. }
  147.  
  148. /*-------------------------------------------------------------------------*/
  149.  
  150.  
  151. local void near pr_toggle_strobe (int port_base, byte ctl)
  152. {
  153.    tsk_outp (port_base + control, ctl | STROBE);
  154.    tsk_nop ();
  155.    tsk_outp (port_base + control, ctl);
  156. }
  157.  
  158. local int near pr_ready (int port_base)
  159. {
  160.    return (tsk_inp (port_base + status) & (BUSY | ACK | PEND | SELIN | ERROR))
  161.           == (BUSY | ACK | SELIN | ERROR);
  162. }
  163.  
  164.  
  165. local void near pr_output_poll (prtptr prt, byte ch)
  166. {
  167.    int wait_count;
  168.    int port_base;
  169.  
  170.    port_base = prt->port_base;
  171.    while (!pr_ready (port_base))
  172.       {
  173.       for (wait_count = 0; wait_count < MAX_WAIT_POLL; wait_count++)
  174.          if (pr_ready (port_base))
  175.             break;
  176.       if (!pr_ready (port_base))
  177.          t_delay (POLL_DELAY);
  178.       }
  179.    tsk_outp (port_base + data, ch);
  180.    pr_toggle_strobe (port_base, prt->ccontrol);
  181. }
  182.  
  183.  
  184. local void near pr_output_int (prtptr prt, byte ch)
  185. {
  186.    int wait_count;
  187.    int port_base;
  188.  
  189.    port_base = prt->port_base;
  190.    while (!pr_ready (port_base))
  191.       {
  192.       for (wait_count = 0; wait_count < MAX_WAIT_INT; wait_count++)
  193.          if (pr_ready (port_base))
  194.             break;
  195.       if (!pr_ready (port_base))
  196.          t_delay (INT_DELAY);
  197.       }
  198.  
  199.    clear_flag (&prt->pready);
  200.  
  201.    tsk_outp (port_base + data, ch);
  202.    pr_toggle_strobe (port_base, prt->ccontrol | IRQENA);
  203.  
  204.    for (wait_count = 0; wait_count < MAX_WAIT_INT; wait_count++)
  205.       if (check_flag (&prt->pready))
  206.          return;
  207.  
  208.    if (wait_flag_set (&prt->pready, INT_TIMEOUT) < 0)
  209.       tsk_outp (prt->port_base + control, prt->ccontrol &= ~IRQENA);
  210. }
  211.  
  212.  
  213. local void far pr_task (prtptr prt)
  214. {
  215.    int ch;
  216.  
  217.    while (1)
  218.       {
  219.       ch = read_pipe (&prt->xmit_pipe, 0L);
  220.       if (prt->polling)
  221.          pr_output_poll (prt, (byte)ch);
  222.       else
  223.          pr_output_int (prt, (byte)ch);
  224.       }
  225. }
  226.  
  227. /*-------------------------------------------------------------------------*/
  228.  
  229. int far prt_install (int port, byte polling, word prior,
  230.                      farptr xmitbuf, word xmitsize)
  231. {
  232.    prtptr prt;
  233.    int pbase;
  234.    intprocptr far *intptr;
  235.  
  236.    if (port < 0 || port >= PORTS || !xmitsize)
  237.       return -1;
  238.  
  239.    prt = &prt_data [port];
  240.  
  241.    create_pipe (&prt->xmit_pipe, xmitbuf, xmitsize);
  242.    create_flag (&prt->pready);
  243.    create_task (&prt->pr_task, pr_task, prt->pr_stack, STKSZ, prior, prt);
  244.  
  245.    pbase = prt->port_base = pr_port_descr [port].base;
  246.    prt->civect = pr_port_descr [port].vector;
  247.    prt->irqbit = pr_port_descr [port].irq;
  248.    prt->ccontrol = dflt_control;
  249.    prt->wait_xmit = prt->xmit_pending = 0;
  250.  
  251.    if (!prt->irqbit)
  252.       polling = 1;
  253.  
  254.    prt->polling = polling;
  255.  
  256.    tsk_outp (pbase + control, dflt_control);
  257.    if (!polling)
  258.       {
  259.       intptr = (intprocptr far *)MK_FP (0, prt->civect * 4);
  260.       tsk_cli ();
  261.       prt->savvect = *intptr;
  262.       *intptr = pr_port_descr [port].proc;
  263.       tsk_sti ();
  264.       tsk_outp (inta01, tsk_inp (inta01) & ~prt->irqbit);
  265.       }
  266.  
  267.    start_task (&prt->pr_task);
  268.     return 0;
  269.    }
  270.  
  271.  
  272. void far prt_remove (int port)
  273.    {
  274.    prtptr prt;
  275.    intprocptr far *intptr;
  276.  
  277.    prt = &prt_data [port];
  278.    tsk_outp (prt->port_base + control, prt->ccontrol & ~IRQENA);
  279.  
  280.    if (!prt->polling)
  281.       {
  282.       tsk_outp (inta01, tsk_inp (inta01) | prt->irqbit);
  283.       intptr = (intprocptr far *)MK_FP (0, prt->civect * 4);
  284.       tsk_cli ();
  285.       *intptr = prt->savvect;
  286.       tsk_sti ();
  287.       }
  288.    kill_task (&prt->pr_task);
  289.    delete_pipe (&prt->xmit_pipe);
  290.    delete_flag (&prt->pready);
  291.    }
  292.  
  293.  
  294. /*-------------------------------------------------------------------------*/
  295.  
  296.  
  297. void far prt_change_control (int port, byte ctl)
  298. {
  299.    prtptr prt;
  300.    CRITICAL;
  301.  
  302.    prt = &prt_data [port];
  303.    C_ENTER;
  304.    prt->ccontrol = (prt->ccontrol & ~(AUTOFEED | INIT | SELECT))
  305.                    | (ctl & (AUTOFEED | INIT | SELECT));
  306.    C_LEAVE;
  307.    tsk_outp (prt->port_base + control, prt->ccontrol);
  308. }
  309.  
  310.  
  311. int far prt_write (int port, byte ch, dword timeout)
  312. {
  313.    return write_pipe (&prt_data [port].xmit_pipe, ch, timeout);
  314. }
  315.  
  316.  
  317. int far prt_status (int port)
  318. {
  319.    return tsk_inp (prt_data [port].port_base + status);
  320. }
  321.  
  322.  
  323. int far prt_complete (int port)
  324. {
  325.    return (check_pipe (&prt_data [port].xmit_pipe) == -1);
  326. }
  327.  
  328.  
  329. int far prt_wait_complete (int port, dword timeout)
  330. {
  331.    return wait_pipe_empty (&prt_data [port].xmit_pipe, timeout);
  332. }
  333.  
  334.