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