xref: /original-bsd/sys/hp300/dev/ppi.c (revision cde01d6c)
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.6 (Berkeley) 10/11/92
8  */
9 
10 /*
11  * Printer/Plotter HPIB interface
12  */
13 
14 #include "ppi.h"
15 #if NPPI > 0
16 
17 #include <sys/param.h>
18 #include <sys/systm.h>
19 #include <sys/errno.h>
20 #include <sys/uio.h>
21 #include <sys/malloc.h>
22 
23 #include <hp/dev/device.h>
24 #include <hp300/dev/ppiioctl.h>
25 
26 int	ppiattach(), ppistart(), ppitimo();
27 struct	driver ppidriver = {
28 	ppiattach, "ppi", ppistart,
29 };
30 
31 struct	ppi_softc {
32 	int	sc_flags;
33 	struct	devqueue sc_dq;
34 	struct	hp_device *sc_hd;
35 	struct	ppiparam sc_param;
36 #define sc_burst sc_param.burst
37 #define sc_timo  sc_param.timo
38 #define sc_delay sc_param.delay
39 	int	sc_sec;
40 } ppi_softc[NPPI];
41 
42 /* sc_flags values */
43 #define	PPIF_ALIVE	0x01
44 #define	PPIF_OPEN	0x02
45 #define PPIF_UIO	0x04
46 #define PPIF_TIMO	0x08
47 #define PPIF_DELAY	0x10
48 
49 #define UNIT(x)		minor(x)
50 
51 #ifdef DEBUG
52 int	ppidebug = 0x80;
53 #define PDB_FOLLOW	0x01
54 #define PDB_IO		0x02
55 #define PDB_NOCHECK	0x80
56 #endif
57 
58 ppiattach(hd)
59 	register struct hp_device *hd;
60 {
61 	register struct ppi_softc *sc = &ppi_softc[hd->hp_unit];
62 
63 #ifdef DEBUG
64 	if ((ppidebug & PDB_NOCHECK) == 0)
65 #endif
66 	/*
67 	 * XXX: the printer/plotter doesn't seem to really return
68 	 * an ID but this will at least prevent us from mistaking
69 	 * a cs80 disk or tape for a ppi device.
70 	 */
71 	if (hpibid(hd->hp_ctlr, hd->hp_slave) & 0x200)
72 		return(0);
73 	sc->sc_flags = PPIF_ALIVE;
74 	sc->sc_dq.dq_ctlr = hd->hp_ctlr;
75 	sc->sc_dq.dq_unit = hd->hp_unit;
76 	sc->sc_dq.dq_slave = hd->hp_slave;
77 	sc->sc_dq.dq_driver = &ppidriver;
78 	sc->sc_hd = hd;
79 	return(1);
80 }
81 
82 ppiopen(dev, flags)
83 	dev_t dev;
84 {
85 	register int unit = UNIT(dev);
86 	register struct ppi_softc *sc = &ppi_softc[unit];
87 
88 	if (unit >= NPPI || (sc->sc_flags & PPIF_ALIVE) == 0)
89 		return(ENXIO);
90 #ifdef DEBUG
91 	if (ppidebug & PDB_FOLLOW)
92 		printf("ppiopen(%x, %x): flags %x\n",
93 		       dev, flags, sc->sc_flags);
94 #endif
95 	if (sc->sc_flags & PPIF_OPEN)
96 		return(EBUSY);
97 	sc->sc_flags |= PPIF_OPEN;
98 	sc->sc_burst = PPI_BURST;
99 	sc->sc_timo = ppimstohz(PPI_TIMO);
100 	sc->sc_delay = ppimstohz(PPI_DELAY);
101 	sc->sc_sec = -1;
102 	return(0);
103 }
104 
105 ppiclose(dev, flags)
106 	dev_t dev;
107 {
108 	register int unit = UNIT(dev);
109 	register struct ppi_softc *sc = &ppi_softc[unit];
110 
111 #ifdef DEBUG
112 	if (ppidebug & PDB_FOLLOW)
113 		printf("ppiclose(%x, %x): flags %x\n",
114 		       dev, flags, sc->sc_flags);
115 #endif
116 	sc->sc_flags &= ~PPIF_OPEN;
117 	return(0);
118 }
119 
120 ppistart(unit)
121 	int unit;
122 {
123 #ifdef DEBUG
124 	if (ppidebug & PDB_FOLLOW)
125 		printf("ppistart(%x)\n", unit);
126 #endif
127 	ppi_softc[unit].sc_flags &= ~PPIF_DELAY;
128 	wakeup(&ppi_softc[unit]);
129 }
130 
131 ppitimo(unit)
132 	int unit;
133 {
134 #ifdef DEBUG
135 	if (ppidebug & PDB_FOLLOW)
136 		printf("ppitimo(%x)\n", unit);
137 #endif
138 	ppi_softc[unit].sc_flags &= ~(PPIF_UIO|PPIF_TIMO);
139 	wakeup(&ppi_softc[unit]);
140 }
141 
142 ppiread(dev, uio)
143 	dev_t dev;
144 	struct uio *uio;
145 {
146 
147 #ifdef DEBUG
148 	if (ppidebug & PDB_FOLLOW)
149 		printf("ppiread(%x, %x)\n", dev, uio);
150 #endif
151 	return (ppirw(dev, uio));
152 }
153 
154 ppiwrite(dev, uio)
155 	dev_t dev;
156 	struct uio *uio;
157 {
158 
159 #ifdef DEBUG
160 	if (ppidebug & PDB_FOLLOW)
161 		printf("ppiwrite(%x, %x)\n", dev, uio);
162 #endif
163 	return (ppirw(dev, uio));
164 }
165 
166 ppirw(dev, uio)
167 	dev_t dev;
168 	register struct uio *uio;
169 {
170 	int unit = UNIT(dev);
171 	register struct ppi_softc *sc = &ppi_softc[unit];
172 	register int s, len, cnt;
173 	register char *cp;
174 	int error = 0, gotdata = 0;
175 	int buflen;
176 	char *buf;
177 
178 	if (uio->uio_resid == 0)
179 		return(0);
180 
181 #ifdef DEBUG
182 	if (ppidebug & (PDB_FOLLOW|PDB_IO))
183 		printf("ppirw(%x, %x, %c): burst %d, timo %d, resid %x\n",
184 		       dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W',
185 		       sc->sc_burst, sc->sc_timo, uio->uio_resid);
186 #endif
187 	buflen = min(sc->sc_burst, uio->uio_resid);
188 	buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK);
189 	sc->sc_flags |= PPIF_UIO;
190 	if (sc->sc_timo > 0) {
191 		sc->sc_flags |= PPIF_TIMO;
192 		timeout(ppitimo, unit, sc->sc_timo);
193 	}
194 	while (uio->uio_resid > 0) {
195 		len = min(buflen, uio->uio_resid);
196 		cp = buf;
197 		if (uio->uio_rw == UIO_WRITE) {
198 			error = uiomove(cp, len, uio);
199 			if (error)
200 				break;
201 		}
202 again:
203 		s = splbio();
204 		if ((sc->sc_flags & PPIF_UIO) && hpibreq(&sc->sc_dq) == 0)
205 			sleep(sc, PRIBIO+1);
206 		/*
207 		 * Check if we timed out during sleep or uiomove
208 		 */
209 		(void) splsoftclock();
210 		if ((sc->sc_flags & PPIF_UIO) == 0) {
211 #ifdef DEBUG
212 			if (ppidebug & PDB_IO)
213 				printf("ppirw: uiomove/sleep timo, flags %x\n",
214 				       sc->sc_flags);
215 #endif
216 			if (sc->sc_flags & PPIF_TIMO) {
217 				untimeout(ppitimo, unit);
218 				sc->sc_flags &= ~PPIF_TIMO;
219 			}
220 			splx(s);
221 			break;
222 		}
223 		splx(s);
224 		/*
225 		 * Perform the operation
226 		 */
227 		if (uio->uio_rw == UIO_WRITE)
228 			cnt = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
229 				       sc->sc_sec, cp, len);
230 		else
231 			cnt = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
232 				       sc->sc_sec, cp, len);
233 		s = splbio();
234 		hpibfree(&sc->sc_dq);
235 #ifdef DEBUG
236 		if (ppidebug & PDB_IO)
237 			printf("ppirw: %s(%d, %d, %x, %x, %d) -> %d\n",
238 			       uio->uio_rw == UIO_READ ? "recv" : "send",
239 			       sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
240 			       sc->sc_sec, cp, len, cnt);
241 #endif
242 		splx(s);
243 		if (uio->uio_rw == UIO_READ) {
244 			if (cnt) {
245 				error = uiomove(cp, cnt, uio);
246 				if (error)
247 					break;
248 				gotdata++;
249 			}
250 			/*
251 			 * Didn't get anything this time, but did in the past.
252 			 * Consider us done.
253 			 */
254 			else if (gotdata)
255 				break;
256 		}
257 		s = splsoftclock();
258 		/*
259 		 * Operation timeout (or non-blocking), quit now.
260 		 */
261 		if ((sc->sc_flags & PPIF_UIO) == 0) {
262 #ifdef DEBUG
263 			if (ppidebug & PDB_IO)
264 				printf("ppirw: timeout/done\n");
265 #endif
266 			splx(s);
267 			break;
268 		}
269 		/*
270 		 * Implement inter-read delay
271 		 */
272 		if (sc->sc_delay > 0) {
273 			sc->sc_flags |= PPIF_DELAY;
274 			timeout(ppistart, unit, sc->sc_delay);
275 			error = tsleep(sc, PCATCH|PZERO+1, "hpib", 0);
276 			if (error) {
277 				splx(s);
278 				break;
279 			}
280 		}
281 		splx(s);
282 		/*
283 		 * Must not call uiomove again til we've used all data
284 		 * that we already grabbed.
285 		 */
286 		if (uio->uio_rw == UIO_WRITE && cnt != len) {
287 			cp += cnt;
288 			len -= cnt;
289 			cnt = 0;
290 			goto again;
291 		}
292 	}
293 	s = splsoftclock();
294 	if (sc->sc_flags & PPIF_TIMO) {
295 		untimeout(ppitimo, unit);
296 		sc->sc_flags &= ~PPIF_TIMO;
297 	}
298 	if (sc->sc_flags & PPIF_DELAY) {
299 		untimeout(ppistart, unit);
300 		sc->sc_flags &= ~PPIF_DELAY;
301 	}
302 	splx(s);
303 	/*
304 	 * Adjust for those chars that we uiomove'ed but never wrote
305 	 */
306 	if (uio->uio_rw == UIO_WRITE && cnt != len) {
307 		uio->uio_resid += (len - cnt);
308 #ifdef DEBUG
309 		if (ppidebug & PDB_IO)
310 			printf("ppirw: short write, adjust by %d\n",
311 			       len-cnt);
312 #endif
313 	}
314 	free(buf, M_DEVBUF);
315 #ifdef DEBUG
316 	if (ppidebug & (PDB_FOLLOW|PDB_IO))
317 		printf("ppirw: return %d, resid %d\n", error, uio->uio_resid);
318 #endif
319 	return (error);
320 }
321 
322 ppiioctl(dev, cmd, data, flag)
323 	dev_t dev;
324 	int cmd;
325 	caddr_t data;
326 	int flag;
327 {
328 	struct ppi_softc *sc = &ppi_softc[UNIT(dev)];
329 	struct ppiparam *pp, *upp;
330 	int error = 0;
331 
332 	switch (cmd) {
333 	case PPIIOCGPARAM:
334 		pp = &sc->sc_param;
335 		upp = (struct ppiparam *)data;
336 		upp->burst = pp->burst;
337 		upp->timo = ppihztoms(pp->timo);
338 		upp->delay = ppihztoms(pp->delay);
339 		break;
340 	case PPIIOCSPARAM:
341 		pp = &sc->sc_param;
342 		upp = (struct ppiparam *)data;
343 		if (upp->burst < PPI_BURST_MIN || upp->burst > PPI_BURST_MAX ||
344 		    upp->delay < PPI_DELAY_MIN || upp->delay > PPI_DELAY_MAX)
345 			return(EINVAL);
346 		pp->burst = upp->burst;
347 		pp->timo = ppimstohz(upp->timo);
348 		pp->delay = ppimstohz(upp->delay);
349 		break;
350 	case PPIIOCSSEC:
351 		sc->sc_sec = *(int *)data;
352 		break;
353 	default:
354 		return(EINVAL);
355 	}
356 	return (error);
357 }
358 
359 ppihztoms(h)
360 	int h;
361 {
362 	extern int hz;
363 	register int m = h;
364 
365 	if (m > 0)
366 		m = m * 1000 / hz;
367 	return(m);
368 }
369 
370 ppimstohz(m)
371 	int m;
372 {
373 	extern int hz;
374 	register int h = m;
375 
376 	if (h > 0) {
377 		h = h * hz / 1000;
378 		if (h == 0)
379 			h = 1000 / hz;
380 	}
381 	return(h);
382 }
383 #endif
384