141480Smckusick /*
263490Sbostic * Copyright (c) 1982, 1990, 1993
363490Sbostic * The Regents of the University of California. All rights reserved.
441480Smckusick *
541480Smckusick * %sccs.include.redist.c%
641480Smckusick *
7*68179Scgd * @(#)ppi.c 8.2 (Berkeley) 01/09/95
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
ppiattach(hd)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
ppiopen(dev,flags)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
ppiclose(dev,flags)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
ppistart(unit)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
ppitimo(unit)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
ppiread(dev,uio)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
ppiwrite(dev,uio)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
ppirw(dev,uio)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
ppiioctl(dev,cmd,data,flag)32645512Smckusick ppiioctl(dev, cmd, data, flag)
32745512Smckusick dev_t dev;
328*68179Scgd u_long 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
ppihztoms(h)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
ppimstohz(m)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