home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / unix / bsd / 4810 < prev    next >
Encoding:
Text File  |  1992-08-29  |  9.4 KB  |  598 lines

  1. Newsgroups: comp.unix.bsd
  2. Path: sparky!uunet!munnari.oz.au!uniwa!cujo!marsh!cproto
  3. From: cproto@marsh.cs.curtin.edu.au (Computer Protocol)
  4. Subject: 386bsd 0.1 printer driver source resubmitted
  5. Message-ID: <cproto.715011443@marsh>
  6. Summary: 386bsd printer driver source resubmitted
  7. Keywords: 386bsd /dev/lp0 lpt printer parallel port
  8. Sender: news@cujo.curtin.edu.au (News Manager)
  9. Organization: Curtin University of Technology
  10. Date: Fri, 28 Aug 1992 14:17:23 GMT
  11. Lines: 585
  12.  
  13.  
  14. Hi there,
  15.  
  16. as a number of people requested it, I resubmit my trivial but working
  17. printer driver.
  18.  
  19. Add file lp.c and apply the other changes.
  20.  
  21. Do the following:
  22.  
  23.     config YOURCONF
  24.     cd ../../compile/YOURCONF
  25.     make depend
  26.     make
  27.     mv /386bsd /386bsd.save
  28.     mv 386bsd /
  29.     
  30. Create the device entry by doing a
  31.  
  32.     mknod /dev/lp0 c 14 0
  33.  
  34. Reboot using:
  35.  
  36.     sync;sync;fastboot
  37.  
  38. Print using something like:
  39.  
  40.     cat printfile > /dev/lp0
  41.  
  42. Have fun
  43.  
  44. Regards - Tibor Sashegyi - cproto@abel.cs.curtin.edu.au
  45.  
  46. ------------- /sys/i386/isa/lp.c --------------
  47.  
  48. /*
  49. ** parallel port printer driver
  50. ** by Tibor Sashegyi 19/04/92
  51. ** (ideas from everywhere)
  52. ** stage 2
  53. */
  54.  
  55. #include "lp.h"
  56.  
  57. #if NLP > 0
  58.  
  59. #include "param.h"
  60. #include "systm.h"
  61. #include "proc.h"
  62. #include "user.h"
  63. #include "conf.h"
  64. #include "file.h"
  65. #include "uio.h"
  66. #include "kernel.h"
  67. #include "syslog.h"
  68. #include "buf.h"
  69.  
  70. #include "i386/isa/isa_device.h"
  71.  
  72. /*
  73. ** printer port base addresses
  74. */
  75.  
  76.  
  77. #define LPB_1_BASE 0x378    /* base i/o address printer 1 */
  78. #define LPB_2_BASE 0x3BC    /* base i/o address printer 2 */
  79. #define LPB_3_BASE 0x278    /* base i/o address printer 3 */
  80.  
  81. /*
  82. ** i/o registers
  83. */
  84.  
  85. #define LPR_DATA 0x00        /* data register */
  86. #define LPR_STAT 0x01        /* status register */
  87. #define LPR_CTRL 0x02        /* control register */
  88.  
  89. /*
  90. ** control bits
  91. */
  92.  
  93. #define LPC_INIT   0x08        /* select and init printer */
  94. #define LPC_STROBE 0x1D        /* strobe data */
  95. #define LPC_READY  0x1C        /* idle IRQ enabled */
  96. #define LPC_SELECT 0x0C        /* select */
  97.  
  98. /*
  99. ** status bits
  100. */
  101.  
  102. #define LPS_ERROR  0x08        /* 0 general error */
  103. #define LPS_SELECT 0x10        /* 1 selected */
  104. #define LPS_PAPER  0x20        /* 1 out of paper */
  105. #define LPS_BUSY   0x80        /* 0 busy */
  106.  
  107. /*
  108. ** lp control block
  109. */
  110.  
  111. #define LPF_ACTIVE 0x01
  112. #define LPF_OPEN   0x02
  113. #define LPF_BUSY   0x04
  114. #define LPF_PAPER  0x08
  115. #define LPF_ERROR  0x10
  116.  
  117. #define MAXBUF     0x100
  118.  
  119. struct lpctrl
  120.     {
  121.     int            unit;
  122.     int            port;
  123.     char        flags;
  124.     int            error;
  125.     int            count;
  126.     char        *cp;
  127.     char        buf[MAXBUF];
  128.     } lp_ctrl[NLP];
  129.  
  130. /*
  131. ** misc
  132. */
  133.  
  134. #define LPWATCH   1
  135.  
  136. int lpprobe(), lpattach(), lpphysio(), lpstrategy();
  137. void lpwatchdog(), lpintr(), lpiowait(), lpiodone();
  138.  
  139. /*
  140. ** define autoconfig entries
  141. */
  142.  
  143. struct isa_driver lpdriver =
  144.     {
  145.     lpprobe, lpattach, "lp"
  146.     };
  147.  
  148. #define    UNIT(x)        minor(x)
  149.  
  150. /*
  151. ** the following delay value is about right for my machine
  152. ** fix it for anything else
  153. */
  154.  
  155. #define CPUSPEED 7
  156. #define    LPDELAY(n)    { register int N = (n) * CPUSPEED; while (--N > 0); }
  157.  
  158. /*
  159. ** probe for device 
  160. ** I really should probe for the parallel port
  161. ** and maybe even the printer, but I trust the
  162. ** configuration (silly me).
  163. */
  164.  
  165. int lpprobe(idev)
  166. struct isa_device *idev;
  167.     {
  168.     if (idev->id_unit >= NLP)
  169.         return(0);
  170.  
  171.     if (   idev->id_iobase != LPB_1_BASE
  172.         && idev->id_iobase != LPB_2_BASE
  173.         && idev->id_iobase != LPB_3_BASE)
  174.         {
  175.         printf("lp base out of range:%x\n", idev->id_iobase);
  176.         return(0);
  177.         }
  178.  
  179.     return(1);
  180.     }
  181.  
  182. /*
  183. ** attach device
  184. */
  185.  
  186. int lpattach(idev)
  187. struct isa_device *idev;
  188.     {
  189.     int unit = idev->id_unit;
  190.     int port = idev->id_iobase;
  191.     struct lpctrl *lpc = &lp_ctrl[unit];
  192.  
  193.  
  194.     lpc->unit = unit;
  195.     lpc->port = port;
  196.     lpc->flags = LPF_ACTIVE;
  197.  
  198.     /*
  199.     ** init printer (pulse width at least 50 us)
  200.     */
  201.  
  202.     outb(port + LPR_CTRL, LPC_INIT);
  203.     LPDELAY(51);
  204.  
  205.     /*
  206.     ** keep selected
  207.     */
  208.  
  209.     outb(port + LPR_CTRL, LPC_SELECT);
  210.  
  211.     return (1);
  212.     }
  213.  
  214. /*
  215. ** open device
  216. */
  217.  
  218. lpopen(dev, flag, mode, p)
  219.     dev_t dev;
  220.     int flag, mode;
  221.     struct proc *p;
  222.     {
  223.     int unit = UNIT(dev);
  224.     struct lpctrl *lpc = &lp_ctrl[unit];
  225.     char val;
  226.  
  227.     /*
  228.     ** make sure device is configured 
  229.     */
  230.  
  231.     if (unit >= NLP || (lpc->flags & LPF_ACTIVE) == 0)
  232.         return(ENXIO);
  233.  
  234.     /*
  235.     ** only one open !
  236.     */
  237.  
  238.     if (lpc->flags & LPF_OPEN)
  239.         return(EBUSY);
  240.  
  241.     /*
  242.     **    check direction
  243.     */
  244.  
  245.     if (flag & FREAD)
  246.         return(ENODEV);
  247.  
  248.     /*
  249.     ** check printer status
  250.     */
  251.  
  252.     val = inb(lpc->port + LPR_STAT);
  253.     if (val & LPS_PAPER)
  254.         {
  255.         uprintf("lp%d: out of paper\n", unit);
  256.         return(EIO);
  257.         }
  258.  
  259.     if ((val & LPS_ERROR) == 0 || (val & LPS_SELECT) == 0)
  260.         {
  261.         uprintf("lp%d: not ready\n", unit);
  262.         return(EIO);
  263.         }
  264.  
  265.     /*
  266.     ** start watchdog timer
  267.     */
  268.  
  269.     timeout(lpwatchdog, lpc, LPWATCH*hz);
  270.     
  271.     /*
  272.     ** enable interrupts and mark as opened
  273.     */
  274.  
  275.     outb(lpc->port + LPR_CTRL, LPC_READY);
  276.     lpc->flags |= LPF_OPEN;
  277.  
  278.     return(0);
  279.     }
  280.  
  281. /*
  282. ** close device
  283. */
  284.  
  285. int lpclose(dev, flag, mode, p)
  286.     dev_t dev;
  287.     int flag, mode;
  288.     struct proc *p;
  289.     {
  290.     int unit = UNIT(dev);
  291.     struct lpctrl *lpc = &lp_ctrl[unit];
  292.  
  293.     /*
  294.     ** disable interrupts but keep selected, mark as closed
  295.     */
  296.  
  297.     outb(lpc->port + LPR_CTRL, LPC_SELECT);
  298.     lpc->flags &= ~LPF_OPEN;
  299.  
  300.     return(0);
  301.     }
  302.  
  303. /*
  304. ** write to device
  305. */
  306.  
  307. int lpwrite(dev, uio)
  308.     dev_t dev;
  309.     struct uio *uio;
  310. {
  311.     return (uioapply(lpphysio, lpstrategy, dev, uio));
  312. }
  313.  
  314. /*
  315. ** check access, lock and call lpstrategy 
  316. ** to output next printer buffer
  317. */
  318.  
  319. int lpphysio(strat, dev, off, rw, base, len, p)
  320.     int (*strat)(); 
  321.     dev_t dev;
  322.     int rw, off;
  323.     caddr_t base;
  324.     int *len;
  325.     struct proc *p;
  326. {
  327.     int error;
  328.     int rest = *len;
  329.     int cnt;
  330.     caddr_t addr = base;
  331.  
  332.     rw = rw == UIO_READ ? B_READ : 0;
  333.  
  334.     /*
  335.     ** check if accessible
  336.     */
  337.  
  338.     if (rw == B_READ && !useracc(base, *len, B_WRITE))
  339.         return (EFAULT);
  340.  
  341.     if (rw == B_WRITE && !useracc(base, *len, B_READ))
  342.         return (EFAULT);
  343.  
  344.     /*
  345.     ** lock in core
  346.     */
  347.  
  348.     vslock (base, *len);
  349.  
  350.     /*
  351.     ** perform transfer
  352.     */
  353.  
  354.     error = 0;
  355.     while(error == 0 && rest > 0)
  356.         {
  357.         cnt = min(rest, MAXBUF);
  358.         rest -= cnt;
  359.         error = lpstrategy(UNIT(dev), addr, cnt);
  360.         addr += cnt;
  361.         }
  362.  
  363.     /*
  364.     ** unlock
  365.     */
  366.  
  367.     vsunlock (base, *len, 0);
  368.  
  369.     *len = 0;
  370.     return (error);
  371.     }
  372.  
  373. /*
  374. ** fetch next buffer and start output
  375. */
  376.  
  377. int lpstrategy(unit, addr, len)
  378.     int unit;
  379.     caddr_t addr;
  380.     int len;
  381.     {
  382.     struct lpctrl *lpc = &lp_ctrl[unit];
  383.     int s;
  384.  
  385.     lpc->count = len;
  386.     if (copyin(addr, lpc->buf, len))
  387.         {
  388.         lpiodone(lpc);
  389.         return(EFAULT);
  390.         }
  391.  
  392.     lpc->cp = lpc->buf;
  393.     lpc->flags |= LPF_BUSY;
  394.     lpc->error = 0;
  395.  
  396.     s = splhigh();
  397.     lpintr(unit);
  398.     splx(s);
  399.     
  400.     /*
  401.     ** wait for i/o to complete
  402.     */
  403.  
  404.     lpiowait(lpc);
  405.  
  406.     return(lpc->error);
  407.     }
  408.  
  409. /*
  410. ** output next characters until printer becomes busy
  411. ** interrupt driven except for the first time
  412. */
  413.  
  414. void lpintr(unit)
  415.     int unit;
  416. {
  417.     struct lpctrl *lpc = &lp_ctrl[unit];
  418.     int port = lpc->port;
  419.     char val;
  420.  
  421.     /*
  422.     ** check for spurious interrupt
  423.     */
  424.  
  425.     if (!(lpc->flags & LPF_BUSY))
  426.         return;
  427.  
  428.     /*
  429.     ** any more to print
  430.     */
  431.  
  432.     while (lpc->count)
  433.         {
  434.         val = inb(lpc->port + LPR_STAT);
  435.         if ((val & LPS_BUSY) == 0)
  436.             return;
  437.         /*
  438.         ** output the character
  439.         */
  440.  
  441.         outb(port + LPR_DATA, *lpc->cp++);
  442.         --lpc->count;
  443.  
  444.         /*
  445.         ** valid data must be present for at least 0.5 us
  446.         */
  447.  
  448.         LPDELAY(1);
  449.  
  450.         /*
  451.         ** strobe for 1 us
  452.         */
  453.  
  454.         outb(port + LPR_CTRL, LPC_STROBE);
  455.         LPDELAY(1);
  456.         outb(port + LPR_CTRL, LPC_READY);
  457.  
  458.         /*
  459.         ** valid data must be present for at least 0.5 us
  460.         */
  461.  
  462.         LPDELAY(1);
  463.         }
  464.  
  465.     lpiodone(lpc);
  466.     }
  467.  
  468. /*
  469. ** wait for i/o to finish
  470. */
  471.  
  472. void lpiowait(lpc)
  473.     struct lpctrl *lpc;
  474.     {
  475.     while (lpc->flags & LPF_BUSY) 
  476.         {
  477.         if (lpc->error = tsleep(lpc, PRIBIO|PCATCH, NULL, 0))
  478.             lpc->flags &= ~LPF_BUSY;
  479.         }
  480.     }
  481.  
  482. /*
  483. ** wakeup strategy function
  484. */
  485.  
  486. void lpiodone(lpc)
  487.     struct lpctrl *lpc;
  488.     {
  489.     lpc->flags &= ~LPF_BUSY;
  490.     wakeup(lpc);
  491.     }
  492.  
  493. /*
  494. ** handle watchdog timeout
  495. */
  496.  
  497. void lpwatchdog(lpc)
  498.     struct lpctrl *lpc;
  499.     {
  500.     char val;
  501.     int s;
  502.  
  503.     /*
  504.     ** are we still running ?
  505.     */
  506.  
  507.     s = splhigh();    /* bit of an overkill ?!? */
  508.  
  509.     if ((lpc->flags & LPF_OPEN) == 0)
  510.         {
  511.         splx(s);
  512.         return;
  513.         }
  514.  
  515.     /*
  516.     ** check printer status
  517.     */
  518.  
  519.     val = inb(lpc->port + LPR_STAT);
  520.  
  521.     /*
  522.     ** report errors only once
  523.     */
  524.  
  525.     if (val & LPS_PAPER && (lpc->flags & LPF_PAPER) == 0)
  526.         {
  527.         printf("lp%d: out of paper, please fix\n", lpc->unit);
  528.         lpc->flags |= LPF_PAPER;
  529.         }
  530.     if (lpc->flags & LPF_PAPER && (val & LPS_PAPER) == 0)
  531.         lpc->flags &= ~LPF_PAPER;
  532.  
  533.     if ((val & LPS_ERROR) == 0 && (lpc->flags & LPF_ERROR) == 0)
  534.         {
  535.         printf("lp%d: not ready, please fix\n", lpc->unit);
  536.         lpc->flags |= LPF_ERROR;
  537.         }
  538.     if (lpc->flags & LPF_ERROR && (val & LPS_ERROR) == 0)
  539.         lpc->flags &= ~LPF_ERROR;
  540.     
  541.     /*
  542.     ** restart watchdog timer
  543.     */
  544.  
  545.     timeout(lpwatchdog, lpc, LPWATCH*hz);
  546.     splx(s);
  547.     }
  548.  
  549. #endif
  550. ----------------- /sys/i386/conf/files.i386 --------------
  551.  
  552. add this:
  553.  
  554. i386/isa/lp.c        optional lp device-driver
  555.  
  556. --------------- /sys/i386/conf/YOURCONF -------------------
  557.  
  558. add this:
  559.  
  560. device        lp0        at isa? port "IO_LPT1" irq 7 vector lpintr
  561.  
  562. --------------- /sys/i386/i386/conf.c ----------------------
  563.  
  564. apply the following patch:
  565.  
  566. *** /sys/i386/i386/conf.c    Sat May 30 23:48:08 1992
  567. --- conf.c    Tue Aug 25 22:34:52 1992
  568. ***************
  569. *** 165,170 ****
  570. --- 165,179 ----
  571.   #define    com_tty        NULL
  572.   #endif
  573.   
  574. + #include "lp.h"
  575. + #if NLP > 0
  576. + int lpopen(),lpclose(),lpwrite();
  577. + #else
  578. + #define lpopen        enxio
  579. + #define lpclose        enxio
  580. + #define lpwrite        enxio
  581. + #endif
  582.   int    logopen(),logclose(),logread(),logioctl(),logselect();
  583.   
  584.   int    ttselect(), seltrue();
  585. ***************
  586. *** 214,219 ****
  587. --- 223,231 ----
  588.       { asopen,    asclose,    rawread,    rawwrite,    /*D*/
  589.         asioctl,    enodev,        nullop,        NULL,
  590.         seltrue,    enodev,        asstrategy },
  591. +     { lpopen,    lpclose,    enodev,        lpwrite,    /*E*/
  592. +       enodev,    enodev,        nullop,        NULL,
  593. +       seltrue,    enodev,        NULL},
  594.   };
  595.   int    nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]);
  596. -------------------------- end of hack -------------------------
  597.