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