xref: /csrg-svn/sys/hp300/dev/ppi.c (revision 68179)
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