1 /* 2 * Copyright (c) 1982, 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)ppi.c 7.1 (Berkeley) 05/08/90 8 */ 9 10 /* 11 * Printer/Plotter HPIB interface 12 */ 13 14 #include "ppi.h" 15 #if NPPI > 0 16 17 #include "param.h" 18 #include "errno.h" 19 #include "uio.h" 20 #include "malloc.h" 21 22 #include "device.h" 23 24 int ppiattach(), ppistart(); 25 struct driver ppidriver = { 26 ppiattach, "ppi", ppistart, 27 }; 28 29 struct ppi_softc { 30 int sc_flags; 31 struct devqueue sc_dq; 32 struct hp_device *sc_hd; 33 } ppi_softc[NPPI]; 34 35 /* sc_flags values */ 36 #define PPIF_ALIVE 0x1 37 #define PPIF_OPEN 0x2 38 39 #define UNIT(x) minor(x) 40 41 ppiattach(hd) 42 register struct hp_device *hd; 43 { 44 register struct ppi_softc *sc = &ppi_softc[hd->hp_unit]; 45 46 /* 47 * XXX: the printer/plotter doesn't seem to really return 48 * an ID but this will at least prevent us from mistaking 49 * a cs80 disk or tape for a ppi device. 50 */ 51 if (hpibid(hd->hp_ctlr, hd->hp_slave) & 0x200) 52 return(0); 53 sc->sc_flags = PPIF_ALIVE; 54 sc->sc_dq.dq_ctlr = hd->hp_ctlr; 55 sc->sc_dq.dq_unit = hd->hp_unit; 56 sc->sc_dq.dq_slave = hd->hp_slave; 57 sc->sc_dq.dq_driver = &ppidriver; 58 sc->sc_hd = hd; 59 return(1); 60 } 61 62 ppiopen(dev, flags) 63 dev_t dev; 64 { 65 register int unit = UNIT(dev); 66 register struct ppi_softc *sc = &ppi_softc[unit]; 67 68 if (unit >= NPPI || (sc->sc_flags & PPIF_ALIVE) == 0) 69 return(ENXIO); 70 if (sc->sc_flags & PPIF_OPEN) 71 return(EBUSY); 72 sc->sc_flags |= PPIF_OPEN; 73 return(0); 74 } 75 76 ppiclose(dev, flags) 77 dev_t dev; 78 { 79 register int unit = UNIT(dev); 80 register struct ppi_softc *sc = &ppi_softc[unit]; 81 82 sc->sc_flags &= ~PPIF_OPEN; 83 return(0); 84 } 85 86 ppistart(unit) 87 register int unit; 88 { 89 wakeup(&ppi_softc[unit]); 90 } 91 92 ppiread(dev, uio) 93 dev_t dev; 94 struct uio *uio; 95 { 96 97 return (ppirw(dev, uio, UIO_READ)); 98 } 99 100 ppiwrite(dev, uio) 101 dev_t dev; 102 struct uio *uio; 103 { 104 105 return (ppirw(dev, uio, UIO_WRITE)); 106 } 107 108 ppirw(dev, uio, rw) 109 dev_t dev; 110 register struct uio *uio; 111 enum uio_rw rw; 112 { 113 register struct ppi_softc *sc = &ppi_softc[UNIT(dev)]; 114 register int s, len, cnt; 115 register char *cp; 116 int error = 0; 117 118 len = MIN(CLBYTES, uio->uio_resid); 119 cp = (char *)malloc(len, M_TEMP, M_WAITOK); 120 while (uio->uio_resid > 0) { 121 len = MIN(CLBYTES, uio->uio_resid); 122 if (rw == UIO_WRITE) { 123 error = uiomove(cp, len, uio); 124 if (error) 125 break; 126 } 127 s = splbio(); 128 if (hpibreq(&sc->sc_dq) == 0) 129 sleep(sc, PRIBIO + 1); 130 splx(s); 131 if (rw == UIO_WRITE) 132 cnt = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 133 -1, cp, len); 134 else 135 cnt = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 136 -1, cp, len); 137 s = splbio(); 138 hpibfree(&sc->sc_dq); 139 splx(s); 140 if (rw == UIO_READ) { 141 error = uiomove(cp, cnt, uio); 142 if (error) 143 break; 144 } 145 if (cnt != len) { 146 if (rw == UIO_WRITE) 147 uio->uio_resid += len - cnt; 148 break; 149 } 150 } 151 free(cp, M_TEMP); 152 return (error); 153 } 154 #endif 155