141480Smckusick /* 241480Smckusick * Copyright (c) 1982, 1990 The Regents of the University of California. 341480Smckusick * All rights reserved. 441480Smckusick * 541480Smckusick * %sccs.include.redist.c% 641480Smckusick * 7*45512Smckusick * @(#)ppi.c 7.2 (Berkeley) 11/04/90 841480Smckusick */ 941480Smckusick 1041480Smckusick /* 1141480Smckusick * Printer/Plotter HPIB interface 1241480Smckusick */ 1341480Smckusick 1441480Smckusick #include "ppi.h" 1541480Smckusick #if NPPI > 0 1641480Smckusick 1741480Smckusick #include "param.h" 1841480Smckusick #include "errno.h" 1941480Smckusick #include "uio.h" 2041480Smckusick #include "malloc.h" 2141480Smckusick 2241480Smckusick #include "device.h" 23*45512Smckusick #include "ppiioctl.h" 2441480Smckusick 25*45512Smckusick int ppiattach(), ppistart(), ppitimo(); 2641480Smckusick struct driver ppidriver = { 2741480Smckusick ppiattach, "ppi", ppistart, 2841480Smckusick }; 2941480Smckusick 3041480Smckusick struct ppi_softc { 3141480Smckusick int sc_flags; 3241480Smckusick struct devqueue sc_dq; 3341480Smckusick struct hp_device *sc_hd; 34*45512Smckusick struct ppiparam sc_param; 35*45512Smckusick #define sc_burst sc_param.burst 36*45512Smckusick #define sc_timo sc_param.timo 37*45512Smckusick #define sc_delay sc_param.delay 38*45512Smckusick int sc_sec; 3941480Smckusick } ppi_softc[NPPI]; 4041480Smckusick 4141480Smckusick /* sc_flags values */ 42*45512Smckusick #define PPIF_ALIVE 0x01 43*45512Smckusick #define PPIF_OPEN 0x02 44*45512Smckusick #define PPIF_UIO 0x04 45*45512Smckusick #define PPIF_TIMO 0x08 46*45512Smckusick #define PPIF_DELAY 0x10 4741480Smckusick 4841480Smckusick #define UNIT(x) minor(x) 4941480Smckusick 50*45512Smckusick #ifdef DEBUG 51*45512Smckusick int ppidebug = 0x80; 52*45512Smckusick #define PDB_FOLLOW 0x01 53*45512Smckusick #define PDB_IO 0x02 54*45512Smckusick #define PDB_NOCHECK 0x80 55*45512Smckusick #endif 56*45512Smckusick 5741480Smckusick ppiattach(hd) 5841480Smckusick register struct hp_device *hd; 5941480Smckusick { 6041480Smckusick register struct ppi_softc *sc = &ppi_softc[hd->hp_unit]; 6141480Smckusick 62*45512Smckusick #ifdef DEBUG 63*45512Smckusick if ((ppidebug & PDB_NOCHECK) == 0) 64*45512Smckusick #endif 6541480Smckusick /* 6641480Smckusick * XXX: the printer/plotter doesn't seem to really return 6741480Smckusick * an ID but this will at least prevent us from mistaking 6841480Smckusick * a cs80 disk or tape for a ppi device. 6941480Smckusick */ 7041480Smckusick if (hpibid(hd->hp_ctlr, hd->hp_slave) & 0x200) 7141480Smckusick return(0); 7241480Smckusick sc->sc_flags = PPIF_ALIVE; 7341480Smckusick sc->sc_dq.dq_ctlr = hd->hp_ctlr; 7441480Smckusick sc->sc_dq.dq_unit = hd->hp_unit; 7541480Smckusick sc->sc_dq.dq_slave = hd->hp_slave; 7641480Smckusick sc->sc_dq.dq_driver = &ppidriver; 7741480Smckusick sc->sc_hd = hd; 7841480Smckusick return(1); 7941480Smckusick } 8041480Smckusick 8141480Smckusick ppiopen(dev, flags) 8241480Smckusick dev_t dev; 8341480Smckusick { 8441480Smckusick register int unit = UNIT(dev); 8541480Smckusick register struct ppi_softc *sc = &ppi_softc[unit]; 8641480Smckusick 8741480Smckusick if (unit >= NPPI || (sc->sc_flags & PPIF_ALIVE) == 0) 8841480Smckusick return(ENXIO); 89*45512Smckusick #ifdef DEBUG 90*45512Smckusick if (ppidebug & PDB_FOLLOW) 91*45512Smckusick printf("ppiopen(%x, %x): flags %x\n", 92*45512Smckusick dev, flags, sc->sc_flags); 93*45512Smckusick #endif 9441480Smckusick if (sc->sc_flags & PPIF_OPEN) 9541480Smckusick return(EBUSY); 9641480Smckusick sc->sc_flags |= PPIF_OPEN; 97*45512Smckusick sc->sc_burst = PPI_BURST; 98*45512Smckusick sc->sc_timo = ppimstohz(PPI_TIMO); 99*45512Smckusick sc->sc_delay = ppimstohz(PPI_DELAY); 100*45512Smckusick sc->sc_sec = -1; 10141480Smckusick return(0); 10241480Smckusick } 10341480Smckusick 10441480Smckusick ppiclose(dev, flags) 10541480Smckusick dev_t dev; 10641480Smckusick { 10741480Smckusick register int unit = UNIT(dev); 10841480Smckusick register struct ppi_softc *sc = &ppi_softc[unit]; 10941480Smckusick 110*45512Smckusick #ifdef DEBUG 111*45512Smckusick if (ppidebug & PDB_FOLLOW) 112*45512Smckusick printf("ppiclose(%x, %x): flags %x\n", 113*45512Smckusick dev, flags, sc->sc_flags); 114*45512Smckusick #endif 11541480Smckusick sc->sc_flags &= ~PPIF_OPEN; 11641480Smckusick return(0); 11741480Smckusick } 11841480Smckusick 11941480Smckusick ppistart(unit) 120*45512Smckusick int unit; 12141480Smckusick { 122*45512Smckusick #ifdef DEBUG 123*45512Smckusick if (ppidebug & PDB_FOLLOW) 124*45512Smckusick printf("ppistart(%x)\n", unit); 125*45512Smckusick #endif 126*45512Smckusick ppi_softc[unit].sc_flags &= ~PPIF_DELAY; 12741480Smckusick wakeup(&ppi_softc[unit]); 12841480Smckusick } 12941480Smckusick 130*45512Smckusick ppitimo(unit) 131*45512Smckusick int unit; 132*45512Smckusick { 133*45512Smckusick #ifdef DEBUG 134*45512Smckusick if (ppidebug & PDB_FOLLOW) 135*45512Smckusick printf("ppitimo(%x)\n", unit); 136*45512Smckusick #endif 137*45512Smckusick ppi_softc[unit].sc_flags &= ~(PPIF_UIO|PPIF_TIMO); 138*45512Smckusick wakeup(&ppi_softc[unit]); 139*45512Smckusick } 140*45512Smckusick 14141480Smckusick ppiread(dev, uio) 14241480Smckusick dev_t dev; 14341480Smckusick struct uio *uio; 14441480Smckusick { 14541480Smckusick 146*45512Smckusick #ifdef DEBUG 147*45512Smckusick if (ppidebug & PDB_FOLLOW) 148*45512Smckusick printf("ppiread(%x, %x)\n", dev, uio); 149*45512Smckusick #endif 150*45512Smckusick return (ppirw(dev, uio)); 15141480Smckusick } 15241480Smckusick 15341480Smckusick ppiwrite(dev, uio) 15441480Smckusick dev_t dev; 15541480Smckusick struct uio *uio; 15641480Smckusick { 15741480Smckusick 158*45512Smckusick #ifdef DEBUG 159*45512Smckusick if (ppidebug & PDB_FOLLOW) 160*45512Smckusick printf("ppiwrite(%x, %x)\n", dev, uio); 161*45512Smckusick #endif 162*45512Smckusick return (ppirw(dev, uio)); 16341480Smckusick } 16441480Smckusick 165*45512Smckusick ppirw(dev, uio) 16641480Smckusick dev_t dev; 16741480Smckusick register struct uio *uio; 16841480Smckusick { 169*45512Smckusick int unit = UNIT(dev); 170*45512Smckusick register struct ppi_softc *sc = &ppi_softc[unit]; 17141480Smckusick register int s, len, cnt; 17241480Smckusick register char *cp; 173*45512Smckusick int error = 0, gotdata = 0; 174*45512Smckusick int buflen; 175*45512Smckusick char *buf; 17641480Smckusick 177*45512Smckusick if (uio->uio_resid == 0) 178*45512Smckusick return(0); 179*45512Smckusick 180*45512Smckusick #ifdef DEBUG 181*45512Smckusick if (ppidebug & (PDB_FOLLOW|PDB_IO)) 182*45512Smckusick printf("ppirw(%x, %x, %c): burst %d, timo %d, resid %x\n", 183*45512Smckusick dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W', 184*45512Smckusick sc->sc_burst, sc->sc_timo, uio->uio_resid); 185*45512Smckusick #endif 186*45512Smckusick buflen = MIN(sc->sc_burst, uio->uio_resid); 187*45512Smckusick buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK); 188*45512Smckusick sc->sc_flags |= PPIF_UIO; 189*45512Smckusick if (sc->sc_timo > 0) { 190*45512Smckusick sc->sc_flags |= PPIF_TIMO; 191*45512Smckusick timeout(ppitimo, unit, sc->sc_timo); 192*45512Smckusick } 19341480Smckusick while (uio->uio_resid > 0) { 194*45512Smckusick len = MIN(buflen, uio->uio_resid); 195*45512Smckusick cp = buf; 196*45512Smckusick if (uio->uio_rw == UIO_WRITE) { 19741480Smckusick error = uiomove(cp, len, uio); 19841480Smckusick if (error) 19941480Smckusick break; 20041480Smckusick } 201*45512Smckusick again: 20241480Smckusick s = splbio(); 203*45512Smckusick if ((sc->sc_flags & PPIF_UIO) && hpibreq(&sc->sc_dq) == 0) 204*45512Smckusick sleep(sc, PRIBIO+1); 205*45512Smckusick /* 206*45512Smckusick * Check if we timed out during sleep or uiomove 207*45512Smckusick */ 208*45512Smckusick (void) splsoftclock(); 209*45512Smckusick if ((sc->sc_flags & PPIF_UIO) == 0) { 210*45512Smckusick #ifdef DEBUG 211*45512Smckusick if (ppidebug & PDB_IO) 212*45512Smckusick printf("ppirw: uiomove/sleep timo, flags %x\n", 213*45512Smckusick sc->sc_flags); 214*45512Smckusick #endif 215*45512Smckusick if (sc->sc_flags & PPIF_TIMO) { 216*45512Smckusick untimeout(ppitimo, unit); 217*45512Smckusick sc->sc_flags &= ~PPIF_TIMO; 218*45512Smckusick } 219*45512Smckusick splx(s); 220*45512Smckusick break; 221*45512Smckusick } 22241480Smckusick splx(s); 223*45512Smckusick /* 224*45512Smckusick * Perform the operation 225*45512Smckusick */ 226*45512Smckusick if (uio->uio_rw == UIO_WRITE) 22741480Smckusick cnt = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 228*45512Smckusick sc->sc_sec, cp, len); 22941480Smckusick else 23041480Smckusick cnt = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 231*45512Smckusick sc->sc_sec, cp, len); 23241480Smckusick s = splbio(); 23341480Smckusick hpibfree(&sc->sc_dq); 234*45512Smckusick #ifdef DEBUG 235*45512Smckusick if (ppidebug & PDB_IO) 236*45512Smckusick printf("ppirw: %s(%d, %d, %x, %x, %d) -> %d\n", 237*45512Smckusick uio->uio_rw == UIO_READ ? "recv" : "send", 238*45512Smckusick sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 239*45512Smckusick sc->sc_sec, cp, len, cnt); 240*45512Smckusick #endif 24141480Smckusick splx(s); 242*45512Smckusick if (uio->uio_rw == UIO_READ) { 243*45512Smckusick if (cnt) { 244*45512Smckusick error = uiomove(cp, cnt, uio); 245*45512Smckusick if (error) 246*45512Smckusick break; 247*45512Smckusick gotdata++; 248*45512Smckusick } 249*45512Smckusick /* 250*45512Smckusick * Didn't get anything this time, but did in the past. 251*45512Smckusick * Consider us done. 252*45512Smckusick */ 253*45512Smckusick else if (gotdata) 25441480Smckusick break; 25541480Smckusick } 256*45512Smckusick s = splsoftclock(); 257*45512Smckusick /* 258*45512Smckusick * Operation timeout (or non-blocking), quit now. 259*45512Smckusick */ 260*45512Smckusick if ((sc->sc_flags & PPIF_UIO) == 0) { 261*45512Smckusick #ifdef DEBUG 262*45512Smckusick if (ppidebug & PDB_IO) 263*45512Smckusick printf("ppirw: timeout/done\n"); 264*45512Smckusick #endif 265*45512Smckusick splx(s); 26641480Smckusick break; 26741480Smckusick } 268*45512Smckusick /* 269*45512Smckusick * Implement inter-read delay 270*45512Smckusick */ 271*45512Smckusick if (sc->sc_delay > 0) { 272*45512Smckusick sc->sc_flags |= PPIF_DELAY; 273*45512Smckusick timeout(ppistart, unit, sc->sc_delay); 274*45512Smckusick error = tsleep(sc, PCATCH|PZERO+1, "hpib", 0); 275*45512Smckusick if (error) { 276*45512Smckusick splx(s); 277*45512Smckusick break; 278*45512Smckusick } 279*45512Smckusick } 280*45512Smckusick splx(s); 281*45512Smckusick /* 282*45512Smckusick * Must not call uiomove again til we've used all data 283*45512Smckusick * that we already grabbed. 284*45512Smckusick */ 285*45512Smckusick if (uio->uio_rw == UIO_WRITE && cnt != len) { 286*45512Smckusick cp += cnt; 287*45512Smckusick len -= cnt; 288*45512Smckusick cnt = 0; 289*45512Smckusick goto again; 290*45512Smckusick } 29141480Smckusick } 292*45512Smckusick s = splsoftclock(); 293*45512Smckusick if (sc->sc_flags & PPIF_TIMO) { 294*45512Smckusick untimeout(ppitimo, unit); 295*45512Smckusick sc->sc_flags &= ~PPIF_TIMO; 296*45512Smckusick } 297*45512Smckusick if (sc->sc_flags & PPIF_DELAY) { 298*45512Smckusick untimeout(ppistart, unit); 299*45512Smckusick sc->sc_flags &= ~PPIF_DELAY; 300*45512Smckusick } 301*45512Smckusick splx(s); 302*45512Smckusick /* 303*45512Smckusick * Adjust for those chars that we uiomove'ed but never wrote 304*45512Smckusick */ 305*45512Smckusick if (uio->uio_rw == UIO_WRITE && cnt != len) { 306*45512Smckusick uio->uio_resid += (len - cnt); 307*45512Smckusick #ifdef DEBUG 308*45512Smckusick if (ppidebug & PDB_IO) 309*45512Smckusick printf("ppirw: short write, adjust by %d\n", 310*45512Smckusick len-cnt); 311*45512Smckusick #endif 312*45512Smckusick } 313*45512Smckusick free(buf, M_DEVBUF); 314*45512Smckusick #ifdef DEBUG 315*45512Smckusick if (ppidebug & (PDB_FOLLOW|PDB_IO)) 316*45512Smckusick printf("ppirw: return %d, resid %d\n", error, uio->uio_resid); 317*45512Smckusick #endif 31841480Smckusick return (error); 31941480Smckusick } 320*45512Smckusick 321*45512Smckusick ppiioctl(dev, cmd, data, flag) 322*45512Smckusick dev_t dev; 323*45512Smckusick int cmd; 324*45512Smckusick caddr_t data; 325*45512Smckusick int flag; 326*45512Smckusick { 327*45512Smckusick struct ppi_softc *sc = &ppi_softc[UNIT(dev)]; 328*45512Smckusick struct ppiparam *pp, *upp; 329*45512Smckusick int error = 0; 330*45512Smckusick 331*45512Smckusick switch (cmd) { 332*45512Smckusick case PPIIOCGPARAM: 333*45512Smckusick pp = &sc->sc_param; 334*45512Smckusick upp = (struct ppiparam *)data; 335*45512Smckusick upp->burst = pp->burst; 336*45512Smckusick upp->timo = ppihztoms(pp->timo); 337*45512Smckusick upp->delay = ppihztoms(pp->delay); 338*45512Smckusick break; 339*45512Smckusick case PPIIOCSPARAM: 340*45512Smckusick pp = &sc->sc_param; 341*45512Smckusick upp = (struct ppiparam *)data; 342*45512Smckusick if (upp->burst < PPI_BURST_MIN || upp->burst > PPI_BURST_MAX || 343*45512Smckusick upp->delay < PPI_DELAY_MIN || upp->delay > PPI_DELAY_MAX) 344*45512Smckusick return(EINVAL); 345*45512Smckusick pp->burst = upp->burst; 346*45512Smckusick pp->timo = ppimstohz(upp->timo); 347*45512Smckusick pp->delay = ppimstohz(upp->delay); 348*45512Smckusick break; 349*45512Smckusick case PPIIOCSSEC: 350*45512Smckusick sc->sc_sec = *(int *)data; 351*45512Smckusick break; 352*45512Smckusick default: 353*45512Smckusick return(EINVAL); 354*45512Smckusick } 355*45512Smckusick return (error); 356*45512Smckusick } 357*45512Smckusick 358*45512Smckusick ppihztoms(h) 359*45512Smckusick int h; 360*45512Smckusick { 361*45512Smckusick extern int hz; 362*45512Smckusick register int m = h; 363*45512Smckusick 364*45512Smckusick if (m > 0) 365*45512Smckusick m = m * 1000 / hz; 366*45512Smckusick return(m); 367*45512Smckusick } 368*45512Smckusick 369*45512Smckusick ppimstohz(m) 370*45512Smckusick int m; 371*45512Smckusick { 372*45512Smckusick extern int hz; 373*45512Smckusick register int h = m; 374*45512Smckusick 375*45512Smckusick if (h > 0) { 376*45512Smckusick h = h * hz / 1000; 377*45512Smckusick if (h == 0) 378*45512Smckusick h = 1000 / hz; 379*45512Smckusick } 380*45512Smckusick return(h); 381*45512Smckusick } 38241480Smckusick #endif 383