home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / hp300 / dev / ppi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  9.2 KB  |  409 lines

  1. /*
  2.  * Copyright (c) 1982, 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)ppi.c    7.3 (Berkeley) 12/16/90
  34.  */
  35.  
  36. /*
  37.  * Printer/Plotter HPIB interface
  38.  */
  39.  
  40. #include "ppi.h"
  41. #if NPPI > 0
  42.  
  43. #include "sys/param.h"
  44. #include "sys/errno.h"
  45. #include "sys/uio.h"
  46. #include "sys/malloc.h"
  47.  
  48. #include "device.h"
  49. #include "ppiioctl.h"
  50.  
  51. int    ppiattach(), ppistart(), ppitimo();
  52. struct    driver ppidriver = {
  53.     ppiattach, "ppi", ppistart,
  54. };
  55.  
  56. struct    ppi_softc {
  57.     int    sc_flags;
  58.     struct    devqueue sc_dq;
  59.     struct    hp_device *sc_hd;
  60.     struct    ppiparam sc_param;
  61. #define sc_burst sc_param.burst
  62. #define sc_timo  sc_param.timo
  63. #define sc_delay sc_param.delay
  64.     int    sc_sec;
  65. } ppi_softc[NPPI];
  66.  
  67. /* sc_flags values */
  68. #define    PPIF_ALIVE    0x01    
  69. #define    PPIF_OPEN    0x02    
  70. #define PPIF_UIO    0x04
  71. #define PPIF_TIMO    0x08
  72. #define PPIF_DELAY    0x10
  73.  
  74. #define UNIT(x)        minor(x)
  75.  
  76. #ifdef DEBUG
  77. int    ppidebug = 0x80;
  78. #define PDB_FOLLOW    0x01
  79. #define PDB_IO        0x02
  80. #define PDB_NOCHECK    0x80
  81. #endif
  82.  
  83. ppiattach(hd)
  84.     register struct hp_device *hd;
  85. {
  86.     register struct ppi_softc *sc = &ppi_softc[hd->hp_unit];
  87.  
  88. #ifdef DEBUG
  89.     if ((ppidebug & PDB_NOCHECK) == 0)
  90. #endif
  91.     /*
  92.      * XXX: the printer/plotter doesn't seem to really return
  93.      * an ID but this will at least prevent us from mistaking
  94.      * a cs80 disk or tape for a ppi device.
  95.      */
  96.     if (hpibid(hd->hp_ctlr, hd->hp_slave) & 0x200)
  97.         return(0);
  98.     sc->sc_flags = PPIF_ALIVE;
  99.     sc->sc_dq.dq_ctlr = hd->hp_ctlr;
  100.     sc->sc_dq.dq_unit = hd->hp_unit;
  101.     sc->sc_dq.dq_slave = hd->hp_slave;
  102.     sc->sc_dq.dq_driver = &ppidriver;
  103.     sc->sc_hd = hd;
  104.     return(1);
  105. }
  106.  
  107. ppiopen(dev, flags)
  108.     dev_t dev;
  109. {
  110.     register int unit = UNIT(dev);
  111.     register struct ppi_softc *sc = &ppi_softc[unit];
  112.  
  113.     if (unit >= NPPI || (sc->sc_flags & PPIF_ALIVE) == 0)
  114.         return(ENXIO);
  115. #ifdef DEBUG
  116.     if (ppidebug & PDB_FOLLOW)
  117.         printf("ppiopen(%x, %x): flags %x\n",
  118.                dev, flags, sc->sc_flags);
  119. #endif
  120.     if (sc->sc_flags & PPIF_OPEN)
  121.         return(EBUSY);
  122.     sc->sc_flags |= PPIF_OPEN;
  123.     sc->sc_burst = PPI_BURST;
  124.     sc->sc_timo = ppimstohz(PPI_TIMO);
  125.     sc->sc_delay = ppimstohz(PPI_DELAY);
  126.     sc->sc_sec = -1;
  127.     return(0);
  128. }
  129.  
  130. ppiclose(dev, flags)
  131.     dev_t dev;
  132. {
  133.     register int unit = UNIT(dev);
  134.     register struct ppi_softc *sc = &ppi_softc[unit];
  135.  
  136. #ifdef DEBUG
  137.     if (ppidebug & PDB_FOLLOW)
  138.         printf("ppiclose(%x, %x): flags %x\n",
  139.                dev, flags, sc->sc_flags);
  140. #endif
  141.     sc->sc_flags &= ~PPIF_OPEN;
  142.     return(0);
  143. }
  144.  
  145. ppistart(unit)
  146.     int unit;
  147. {
  148. #ifdef DEBUG
  149.     if (ppidebug & PDB_FOLLOW)
  150.         printf("ppistart(%x)\n", unit);
  151. #endif
  152.     ppi_softc[unit].sc_flags &= ~PPIF_DELAY;
  153.     wakeup(&ppi_softc[unit]);
  154. }
  155.  
  156. ppitimo(unit)
  157.     int unit;
  158. {
  159. #ifdef DEBUG
  160.     if (ppidebug & PDB_FOLLOW)
  161.         printf("ppitimo(%x)\n", unit);
  162. #endif
  163.     ppi_softc[unit].sc_flags &= ~(PPIF_UIO|PPIF_TIMO);
  164.     wakeup(&ppi_softc[unit]);
  165. }
  166.  
  167. ppiread(dev, uio)
  168.     dev_t dev;
  169.     struct uio *uio;
  170. {
  171.  
  172. #ifdef DEBUG
  173.     if (ppidebug & PDB_FOLLOW)
  174.         printf("ppiread(%x, %x)\n", dev, uio);
  175. #endif
  176.     return (ppirw(dev, uio));
  177. }
  178.  
  179. ppiwrite(dev, uio)
  180.     dev_t dev;
  181.     struct uio *uio;
  182. {
  183.  
  184. #ifdef DEBUG
  185.     if (ppidebug & PDB_FOLLOW)
  186.         printf("ppiwrite(%x, %x)\n", dev, uio);
  187. #endif
  188.     return (ppirw(dev, uio));
  189. }
  190.  
  191. ppirw(dev, uio)
  192.     dev_t dev;
  193.     register struct uio *uio;
  194. {
  195.     int unit = UNIT(dev);
  196.     register struct ppi_softc *sc = &ppi_softc[unit];
  197.     register int s, len, cnt;
  198.     register char *cp;
  199.     int error = 0, gotdata = 0;
  200.     int buflen;
  201.     char *buf;
  202.  
  203.     if (uio->uio_resid == 0)
  204.         return(0);
  205.  
  206. #ifdef DEBUG
  207.     if (ppidebug & (PDB_FOLLOW|PDB_IO))
  208.         printf("ppirw(%x, %x, %c): burst %d, timo %d, resid %x\n",
  209.                dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W',
  210.                sc->sc_burst, sc->sc_timo, uio->uio_resid);
  211. #endif
  212.     buflen = MIN(sc->sc_burst, uio->uio_resid);
  213.     buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK);
  214.     sc->sc_flags |= PPIF_UIO;
  215.     if (sc->sc_timo > 0) {
  216.         sc->sc_flags |= PPIF_TIMO;
  217.         timeout(ppitimo, unit, sc->sc_timo);
  218.     }
  219.     while (uio->uio_resid > 0) {
  220.         len = MIN(buflen, uio->uio_resid);
  221.         cp = buf;
  222.         if (uio->uio_rw == UIO_WRITE) {
  223.             error = uiomove(cp, len, uio);
  224.             if (error)
  225.                 break;
  226.         }
  227. again:
  228.         s = splbio();
  229.         if ((sc->sc_flags & PPIF_UIO) && hpibreq(&sc->sc_dq) == 0)
  230.             sleep(sc, PRIBIO+1);
  231.         /*
  232.          * Check if we timed out during sleep or uiomove
  233.          */
  234.         (void) splsoftclock();
  235.         if ((sc->sc_flags & PPIF_UIO) == 0) {
  236. #ifdef DEBUG
  237.             if (ppidebug & PDB_IO)
  238.                 printf("ppirw: uiomove/sleep timo, flags %x\n",
  239.                        sc->sc_flags);
  240. #endif
  241.             if (sc->sc_flags & PPIF_TIMO) {
  242.                 untimeout(ppitimo, unit);
  243.                 sc->sc_flags &= ~PPIF_TIMO;
  244.             }
  245.             splx(s);
  246.             break;
  247.         }
  248.         splx(s);
  249.         /*
  250.          * Perform the operation
  251.          */
  252.         if (uio->uio_rw == UIO_WRITE)
  253.             cnt = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
  254.                        sc->sc_sec, cp, len);
  255.         else
  256.             cnt = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
  257.                        sc->sc_sec, cp, len);
  258.         s = splbio();
  259.         hpibfree(&sc->sc_dq);
  260. #ifdef DEBUG
  261.         if (ppidebug & PDB_IO)
  262.             printf("ppirw: %s(%d, %d, %x, %x, %d) -> %d\n",
  263.                    uio->uio_rw == UIO_READ ? "recv" : "send",
  264.                    sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
  265.                    sc->sc_sec, cp, len, cnt);
  266. #endif
  267.         splx(s);
  268.         if (uio->uio_rw == UIO_READ) {
  269.             if (cnt) {
  270.                 error = uiomove(cp, cnt, uio);
  271.                 if (error)
  272.                     break;
  273.                 gotdata++;
  274.             }
  275.             /*
  276.              * Didn't get anything this time, but did in the past.
  277.              * Consider us done.
  278.              */
  279.             else if (gotdata)
  280.                 break;
  281.         }
  282.         s = splsoftclock();
  283.         /*
  284.          * Operation timeout (or non-blocking), quit now.
  285.          */
  286.         if ((sc->sc_flags & PPIF_UIO) == 0) {
  287. #ifdef DEBUG
  288.             if (ppidebug & PDB_IO)
  289.                 printf("ppirw: timeout/done\n");
  290. #endif
  291.             splx(s);
  292.             break;
  293.         }
  294.         /*
  295.          * Implement inter-read delay
  296.          */
  297.         if (sc->sc_delay > 0) {
  298.             sc->sc_flags |= PPIF_DELAY;
  299.             timeout(ppistart, unit, sc->sc_delay);
  300.             error = tsleep(sc, PCATCH|PZERO+1, "hpib", 0);
  301.             if (error) {
  302.                 splx(s);
  303.                 break;
  304.             }
  305.         }
  306.         splx(s);
  307.         /*
  308.          * Must not call uiomove again til we've used all data
  309.          * that we already grabbed.
  310.          */
  311.         if (uio->uio_rw == UIO_WRITE && cnt != len) {
  312.             cp += cnt;
  313.             len -= cnt;
  314.             cnt = 0;
  315.             goto again;
  316.         }
  317.     }
  318.     s = splsoftclock();
  319.     if (sc->sc_flags & PPIF_TIMO) {
  320.         untimeout(ppitimo, unit);
  321.         sc->sc_flags &= ~PPIF_TIMO;
  322.     }
  323.     if (sc->sc_flags & PPIF_DELAY) {
  324.         untimeout(ppistart, unit);
  325.         sc->sc_flags &= ~PPIF_DELAY;
  326.     }
  327.     splx(s);
  328.     /*
  329.      * Adjust for those chars that we uiomove'ed but never wrote
  330.      */
  331.     if (uio->uio_rw == UIO_WRITE && cnt != len) {
  332.         uio->uio_resid += (len - cnt);
  333. #ifdef DEBUG
  334.         if (ppidebug & PDB_IO)
  335.             printf("ppirw: short write, adjust by %d\n",
  336.                    len-cnt);
  337. #endif
  338.     }
  339.     free(buf, M_DEVBUF);
  340. #ifdef DEBUG
  341.     if (ppidebug & (PDB_FOLLOW|PDB_IO))
  342.         printf("ppirw: return %d, resid %d\n", error, uio->uio_resid);
  343. #endif
  344.     return (error);
  345. }
  346.  
  347. ppiioctl(dev, cmd, data, flag)
  348.     dev_t dev;
  349.     int cmd;
  350.     caddr_t data;
  351.     int flag;
  352. {
  353.     struct ppi_softc *sc = &ppi_softc[UNIT(dev)];
  354.     struct ppiparam *pp, *upp;
  355.     int error = 0;
  356.  
  357.     switch (cmd) {
  358.     case PPIIOCGPARAM:
  359.         pp = &sc->sc_param;
  360.         upp = (struct ppiparam *)data;
  361.         upp->burst = pp->burst;
  362.         upp->timo = ppihztoms(pp->timo);
  363.         upp->delay = ppihztoms(pp->delay);
  364.         break;
  365.     case PPIIOCSPARAM:
  366.         pp = &sc->sc_param;
  367.         upp = (struct ppiparam *)data;
  368.         if (upp->burst < PPI_BURST_MIN || upp->burst > PPI_BURST_MAX ||
  369.             upp->delay < PPI_DELAY_MIN || upp->delay > PPI_DELAY_MAX)
  370.             return(EINVAL);
  371.         pp->burst = upp->burst;
  372.         pp->timo = ppimstohz(upp->timo);
  373.         pp->delay = ppimstohz(upp->delay);
  374.         break;
  375.     case PPIIOCSSEC:
  376.         sc->sc_sec = *(int *)data;
  377.         break;
  378.     default:
  379.         return(EINVAL);
  380.     }
  381.     return (error);
  382. }
  383.  
  384. ppihztoms(h)
  385.     int h;
  386. {
  387.     extern int hz;
  388.     register int m = h;
  389.  
  390.     if (m > 0)
  391.         m = m * 1000 / hz;
  392.     return(m);
  393. }
  394.  
  395. ppimstohz(m)
  396.     int m;
  397. {
  398.     extern int hz;
  399.     register int h = m;
  400.  
  401.     if (h > 0) {
  402.         h = h * hz / 1000;
  403.         if (h == 0)
  404.             h = 1000 / hz;
  405.     }
  406.     return(h);
  407. }
  408. #endif
  409.