141480Smckusick /* 2*63490Sbostic * Copyright (c) 1982, 1990, 1993 3*63490Sbostic * The Regents of the University of California. All rights reserved. 441480Smckusick * 541480Smckusick * %sccs.include.redist.c% 641480Smckusick * 7*63490Sbostic * @(#)ppi.c 8.1 (Berkeley) 06/16/93 841480Smckusick */ 941480Smckusick 1041480Smckusick /* 1141480Smckusick * Printer/Plotter HPIB interface 1241480Smckusick */ 1341480Smckusick 1441480Smckusick #include "ppi.h" 1541480Smckusick #if NPPI > 0 1641480Smckusick 1756507Sbostic #include <sys/param.h> 1856507Sbostic #include <sys/systm.h> 1956507Sbostic #include <sys/errno.h> 2056507Sbostic #include <sys/uio.h> 2156507Sbostic #include <sys/malloc.h> 2241480Smckusick 2356507Sbostic #include <hp/dev/device.h> 2456507Sbostic #include <hp300/dev/ppiioctl.h> 2541480Smckusick 2663489Smckusick int ppiattach(), ppistart(); 2763489Smckusick void ppitimo(); 2841480Smckusick struct driver ppidriver = { 2941480Smckusick ppiattach, "ppi", ppistart, 3041480Smckusick }; 3141480Smckusick 3241480Smckusick struct ppi_softc { 3341480Smckusick int sc_flags; 3441480Smckusick struct devqueue sc_dq; 3541480Smckusick struct hp_device *sc_hd; 3645512Smckusick struct ppiparam sc_param; 3745512Smckusick #define sc_burst sc_param.burst 3845512Smckusick #define sc_timo sc_param.timo 3945512Smckusick #define sc_delay sc_param.delay 4045512Smckusick int sc_sec; 4141480Smckusick } ppi_softc[NPPI]; 4241480Smckusick 4341480Smckusick /* sc_flags values */ 4445512Smckusick #define PPIF_ALIVE 0x01 4545512Smckusick #define PPIF_OPEN 0x02 4645512Smckusick #define PPIF_UIO 0x04 4745512Smckusick #define PPIF_TIMO 0x08 4845512Smckusick #define PPIF_DELAY 0x10 4941480Smckusick 5041480Smckusick #define UNIT(x) minor(x) 5141480Smckusick 5245512Smckusick #ifdef DEBUG 5345512Smckusick int ppidebug = 0x80; 5445512Smckusick #define PDB_FOLLOW 0x01 5545512Smckusick #define PDB_IO 0x02 5645512Smckusick #define PDB_NOCHECK 0x80 5745512Smckusick #endif 5845512Smckusick 5941480Smckusick ppiattach(hd) 6041480Smckusick register struct hp_device *hd; 6141480Smckusick { 6241480Smckusick register struct ppi_softc *sc = &ppi_softc[hd->hp_unit]; 6341480Smckusick 6445512Smckusick #ifdef DEBUG 6545512Smckusick if ((ppidebug & PDB_NOCHECK) == 0) 6645512Smckusick #endif 6741480Smckusick /* 6841480Smckusick * XXX: the printer/plotter doesn't seem to really return 6941480Smckusick * an ID but this will at least prevent us from mistaking 7041480Smckusick * a cs80 disk or tape for a ppi device. 7141480Smckusick */ 7241480Smckusick if (hpibid(hd->hp_ctlr, hd->hp_slave) & 0x200) 7341480Smckusick return(0); 7441480Smckusick sc->sc_flags = PPIF_ALIVE; 7541480Smckusick sc->sc_dq.dq_ctlr = hd->hp_ctlr; 7641480Smckusick sc->sc_dq.dq_unit = hd->hp_unit; 7741480Smckusick sc->sc_dq.dq_slave = hd->hp_slave; 7841480Smckusick sc->sc_dq.dq_driver = &ppidriver; 7941480Smckusick sc->sc_hd = hd; 8041480Smckusick return(1); 8141480Smckusick } 8241480Smckusick 8341480Smckusick ppiopen(dev, flags) 8441480Smckusick dev_t dev; 8541480Smckusick { 8641480Smckusick register int unit = UNIT(dev); 8741480Smckusick register struct ppi_softc *sc = &ppi_softc[unit]; 8841480Smckusick 8941480Smckusick if (unit >= NPPI || (sc->sc_flags & PPIF_ALIVE) == 0) 9041480Smckusick return(ENXIO); 9145512Smckusick #ifdef DEBUG 9245512Smckusick if (ppidebug & PDB_FOLLOW) 9345512Smckusick printf("ppiopen(%x, %x): flags %x\n", 9445512Smckusick dev, flags, sc->sc_flags); 9545512Smckusick #endif 9641480Smckusick if (sc->sc_flags & PPIF_OPEN) 9741480Smckusick return(EBUSY); 9841480Smckusick sc->sc_flags |= PPIF_OPEN; 9945512Smckusick sc->sc_burst = PPI_BURST; 10045512Smckusick sc->sc_timo = ppimstohz(PPI_TIMO); 10145512Smckusick sc->sc_delay = ppimstohz(PPI_DELAY); 10245512Smckusick sc->sc_sec = -1; 10341480Smckusick return(0); 10441480Smckusick } 10541480Smckusick 10641480Smckusick ppiclose(dev, flags) 10741480Smckusick dev_t dev; 10841480Smckusick { 10941480Smckusick register int unit = UNIT(dev); 11041480Smckusick register struct ppi_softc *sc = &ppi_softc[unit]; 11141480Smckusick 11245512Smckusick #ifdef DEBUG 11345512Smckusick if (ppidebug & PDB_FOLLOW) 11445512Smckusick printf("ppiclose(%x, %x): flags %x\n", 11545512Smckusick dev, flags, sc->sc_flags); 11645512Smckusick #endif 11741480Smckusick sc->sc_flags &= ~PPIF_OPEN; 11841480Smckusick return(0); 11941480Smckusick } 12041480Smckusick 12141480Smckusick ppistart(unit) 12245512Smckusick int unit; 12341480Smckusick { 12445512Smckusick #ifdef DEBUG 12545512Smckusick if (ppidebug & PDB_FOLLOW) 12645512Smckusick printf("ppistart(%x)\n", unit); 12745512Smckusick #endif 12845512Smckusick ppi_softc[unit].sc_flags &= ~PPIF_DELAY; 12941480Smckusick wakeup(&ppi_softc[unit]); 13063489Smckusick return (0); 13141480Smckusick } 13241480Smckusick 13363489Smckusick void 13445512Smckusick ppitimo(unit) 13545512Smckusick int unit; 13645512Smckusick { 13745512Smckusick #ifdef DEBUG 13845512Smckusick if (ppidebug & PDB_FOLLOW) 13945512Smckusick printf("ppitimo(%x)\n", unit); 14045512Smckusick #endif 14145512Smckusick ppi_softc[unit].sc_flags &= ~(PPIF_UIO|PPIF_TIMO); 14245512Smckusick wakeup(&ppi_softc[unit]); 14345512Smckusick } 14445512Smckusick 14541480Smckusick ppiread(dev, uio) 14641480Smckusick dev_t dev; 14741480Smckusick struct uio *uio; 14841480Smckusick { 14941480Smckusick 15045512Smckusick #ifdef DEBUG 15145512Smckusick if (ppidebug & PDB_FOLLOW) 15245512Smckusick printf("ppiread(%x, %x)\n", dev, uio); 15345512Smckusick #endif 15445512Smckusick return (ppirw(dev, uio)); 15541480Smckusick } 15641480Smckusick 15741480Smckusick ppiwrite(dev, uio) 15841480Smckusick dev_t dev; 15941480Smckusick struct uio *uio; 16041480Smckusick { 16141480Smckusick 16245512Smckusick #ifdef DEBUG 16345512Smckusick if (ppidebug & PDB_FOLLOW) 16445512Smckusick printf("ppiwrite(%x, %x)\n", dev, uio); 16545512Smckusick #endif 16645512Smckusick return (ppirw(dev, uio)); 16741480Smckusick } 16841480Smckusick 16945512Smckusick ppirw(dev, uio) 17041480Smckusick dev_t dev; 17141480Smckusick register struct uio *uio; 17241480Smckusick { 17345512Smckusick int unit = UNIT(dev); 17445512Smckusick register struct ppi_softc *sc = &ppi_softc[unit]; 17541480Smckusick register int s, len, cnt; 17641480Smckusick register char *cp; 17745512Smckusick int error = 0, gotdata = 0; 17845512Smckusick int buflen; 17945512Smckusick char *buf; 18041480Smckusick 18145512Smckusick if (uio->uio_resid == 0) 18245512Smckusick return(0); 18345512Smckusick 18445512Smckusick #ifdef DEBUG 18545512Smckusick if (ppidebug & (PDB_FOLLOW|PDB_IO)) 18645512Smckusick printf("ppirw(%x, %x, %c): burst %d, timo %d, resid %x\n", 18745512Smckusick dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W', 18845512Smckusick sc->sc_burst, sc->sc_timo, uio->uio_resid); 18945512Smckusick #endif 19055068Spendry buflen = min(sc->sc_burst, uio->uio_resid); 19145512Smckusick buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK); 19245512Smckusick sc->sc_flags |= PPIF_UIO; 19345512Smckusick if (sc->sc_timo > 0) { 19445512Smckusick sc->sc_flags |= PPIF_TIMO; 19563489Smckusick timeout(ppitimo, (void *)unit, sc->sc_timo); 19645512Smckusick } 19741480Smckusick while (uio->uio_resid > 0) { 19855068Spendry len = min(buflen, uio->uio_resid); 19945512Smckusick cp = buf; 20045512Smckusick if (uio->uio_rw == UIO_WRITE) { 20141480Smckusick error = uiomove(cp, len, uio); 20241480Smckusick if (error) 20341480Smckusick break; 20441480Smckusick } 20545512Smckusick again: 20641480Smckusick s = splbio(); 20745512Smckusick if ((sc->sc_flags & PPIF_UIO) && hpibreq(&sc->sc_dq) == 0) 20845512Smckusick sleep(sc, PRIBIO+1); 20945512Smckusick /* 21045512Smckusick * Check if we timed out during sleep or uiomove 21145512Smckusick */ 21245512Smckusick (void) splsoftclock(); 21345512Smckusick if ((sc->sc_flags & PPIF_UIO) == 0) { 21445512Smckusick #ifdef DEBUG 21545512Smckusick if (ppidebug & PDB_IO) 21645512Smckusick printf("ppirw: uiomove/sleep timo, flags %x\n", 21745512Smckusick sc->sc_flags); 21845512Smckusick #endif 21945512Smckusick if (sc->sc_flags & PPIF_TIMO) { 22063489Smckusick untimeout(ppitimo, (void *)unit); 22145512Smckusick sc->sc_flags &= ~PPIF_TIMO; 22245512Smckusick } 22345512Smckusick splx(s); 22445512Smckusick break; 22545512Smckusick } 22641480Smckusick splx(s); 22745512Smckusick /* 22845512Smckusick * Perform the operation 22945512Smckusick */ 23045512Smckusick if (uio->uio_rw == UIO_WRITE) 23141480Smckusick cnt = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 23245512Smckusick sc->sc_sec, cp, len); 23341480Smckusick else 23441480Smckusick cnt = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 23545512Smckusick sc->sc_sec, cp, len); 23641480Smckusick s = splbio(); 23741480Smckusick hpibfree(&sc->sc_dq); 23845512Smckusick #ifdef DEBUG 23945512Smckusick if (ppidebug & PDB_IO) 24045512Smckusick printf("ppirw: %s(%d, %d, %x, %x, %d) -> %d\n", 24145512Smckusick uio->uio_rw == UIO_READ ? "recv" : "send", 24245512Smckusick sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 24345512Smckusick sc->sc_sec, cp, len, cnt); 24445512Smckusick #endif 24541480Smckusick splx(s); 24645512Smckusick if (uio->uio_rw == UIO_READ) { 24745512Smckusick if (cnt) { 24845512Smckusick error = uiomove(cp, cnt, uio); 24945512Smckusick if (error) 25045512Smckusick break; 25145512Smckusick gotdata++; 25245512Smckusick } 25345512Smckusick /* 25445512Smckusick * Didn't get anything this time, but did in the past. 25545512Smckusick * Consider us done. 25645512Smckusick */ 25745512Smckusick else if (gotdata) 25841480Smckusick break; 25941480Smckusick } 26045512Smckusick s = splsoftclock(); 26145512Smckusick /* 26245512Smckusick * Operation timeout (or non-blocking), quit now. 26345512Smckusick */ 26445512Smckusick if ((sc->sc_flags & PPIF_UIO) == 0) { 26545512Smckusick #ifdef DEBUG 26645512Smckusick if (ppidebug & PDB_IO) 26745512Smckusick printf("ppirw: timeout/done\n"); 26845512Smckusick #endif 26945512Smckusick splx(s); 27041480Smckusick break; 27141480Smckusick } 27245512Smckusick /* 27345512Smckusick * Implement inter-read delay 27445512Smckusick */ 27545512Smckusick if (sc->sc_delay > 0) { 27645512Smckusick sc->sc_flags |= PPIF_DELAY; 27763489Smckusick timeout((void (*)__P((void *)))ppistart, (void *)unit, 27863489Smckusick sc->sc_delay); 27945512Smckusick error = tsleep(sc, PCATCH|PZERO+1, "hpib", 0); 28045512Smckusick if (error) { 28145512Smckusick splx(s); 28245512Smckusick break; 28345512Smckusick } 28445512Smckusick } 28545512Smckusick splx(s); 28645512Smckusick /* 28745512Smckusick * Must not call uiomove again til we've used all data 28845512Smckusick * that we already grabbed. 28945512Smckusick */ 29045512Smckusick if (uio->uio_rw == UIO_WRITE && cnt != len) { 29145512Smckusick cp += cnt; 29245512Smckusick len -= cnt; 29345512Smckusick cnt = 0; 29445512Smckusick goto again; 29545512Smckusick } 29641480Smckusick } 29745512Smckusick s = splsoftclock(); 29845512Smckusick if (sc->sc_flags & PPIF_TIMO) { 29963489Smckusick untimeout(ppitimo, (void *)unit); 30045512Smckusick sc->sc_flags &= ~PPIF_TIMO; 30145512Smckusick } 30245512Smckusick if (sc->sc_flags & PPIF_DELAY) { 30363489Smckusick untimeout((void (*)__P((void *)))ppistart, (void *)unit); 30445512Smckusick sc->sc_flags &= ~PPIF_DELAY; 30545512Smckusick } 30645512Smckusick splx(s); 30745512Smckusick /* 30845512Smckusick * Adjust for those chars that we uiomove'ed but never wrote 30945512Smckusick */ 31045512Smckusick if (uio->uio_rw == UIO_WRITE && cnt != len) { 31145512Smckusick uio->uio_resid += (len - cnt); 31245512Smckusick #ifdef DEBUG 31345512Smckusick if (ppidebug & PDB_IO) 31445512Smckusick printf("ppirw: short write, adjust by %d\n", 31545512Smckusick len-cnt); 31645512Smckusick #endif 31745512Smckusick } 31845512Smckusick free(buf, M_DEVBUF); 31945512Smckusick #ifdef DEBUG 32045512Smckusick if (ppidebug & (PDB_FOLLOW|PDB_IO)) 32145512Smckusick printf("ppirw: return %d, resid %d\n", error, uio->uio_resid); 32245512Smckusick #endif 32341480Smckusick return (error); 32441480Smckusick } 32545512Smckusick 32645512Smckusick ppiioctl(dev, cmd, data, flag) 32745512Smckusick dev_t dev; 32845512Smckusick int cmd; 32945512Smckusick caddr_t data; 33045512Smckusick int flag; 33145512Smckusick { 33245512Smckusick struct ppi_softc *sc = &ppi_softc[UNIT(dev)]; 33345512Smckusick struct ppiparam *pp, *upp; 33445512Smckusick int error = 0; 33545512Smckusick 33645512Smckusick switch (cmd) { 33745512Smckusick case PPIIOCGPARAM: 33845512Smckusick pp = &sc->sc_param; 33945512Smckusick upp = (struct ppiparam *)data; 34045512Smckusick upp->burst = pp->burst; 34145512Smckusick upp->timo = ppihztoms(pp->timo); 34245512Smckusick upp->delay = ppihztoms(pp->delay); 34345512Smckusick break; 34445512Smckusick case PPIIOCSPARAM: 34545512Smckusick pp = &sc->sc_param; 34645512Smckusick upp = (struct ppiparam *)data; 34745512Smckusick if (upp->burst < PPI_BURST_MIN || upp->burst > PPI_BURST_MAX || 34845512Smckusick upp->delay < PPI_DELAY_MIN || upp->delay > PPI_DELAY_MAX) 34945512Smckusick return(EINVAL); 35045512Smckusick pp->burst = upp->burst; 35145512Smckusick pp->timo = ppimstohz(upp->timo); 35245512Smckusick pp->delay = ppimstohz(upp->delay); 35345512Smckusick break; 35445512Smckusick case PPIIOCSSEC: 35545512Smckusick sc->sc_sec = *(int *)data; 35645512Smckusick break; 35745512Smckusick default: 35845512Smckusick return(EINVAL); 35945512Smckusick } 36045512Smckusick return (error); 36145512Smckusick } 36245512Smckusick 36345512Smckusick ppihztoms(h) 36445512Smckusick int h; 36545512Smckusick { 36645512Smckusick extern int hz; 36745512Smckusick register int m = h; 36845512Smckusick 36945512Smckusick if (m > 0) 37045512Smckusick m = m * 1000 / hz; 37145512Smckusick return(m); 37245512Smckusick } 37345512Smckusick 37445512Smckusick ppimstohz(m) 37545512Smckusick int m; 37645512Smckusick { 37745512Smckusick extern int hz; 37845512Smckusick register int h = m; 37945512Smckusick 38045512Smckusick if (h > 0) { 38145512Smckusick h = h * hz / 1000; 38245512Smckusick if (h == 0) 38345512Smckusick h = 1000 / hz; 38445512Smckusick } 38545512Smckusick return(h); 38645512Smckusick } 38741480Smckusick #endif 388