date and time created 94/01/05 12:54:31 by pendry
[unix-history] / usr / src / sys / hp300 / dev / ppi.c
CommitLineData
60f56dfc 1/*
66ba08f6
KB
2 * Copyright (c) 1982, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
60f56dfc
KM
4 *
5 * %sccs.include.redist.c%
6 *
66ba08f6 7 * @(#)ppi.c 8.1 (Berkeley) %G%
60f56dfc
KM
8 */
9
10/*
11 * Printer/Plotter HPIB interface
12 */
13
14#include "ppi.h"
15#if NPPI > 0
16
38a01dbe
KB
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>
60f56dfc 22
38a01dbe
KB
23#include <hp/dev/device.h>
24#include <hp300/dev/ppiioctl.h>
60f56dfc 25
ef4c025f
KM
26int ppiattach(), ppistart();
27void ppitimo();
60f56dfc
KM
28struct driver ppidriver = {
29 ppiattach, "ppi", ppistart,
30};
31
32struct ppi_softc {
33 int sc_flags;
34 struct devqueue sc_dq;
35 struct hp_device *sc_hd;
a47d912d
KM
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;
60f56dfc
KM
41} ppi_softc[NPPI];
42
43/* sc_flags values */
a47d912d
KM
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
60f56dfc
KM
49
50#define UNIT(x) minor(x)
51
a47d912d
KM
52#ifdef DEBUG
53int ppidebug = 0x80;
54#define PDB_FOLLOW 0x01
55#define PDB_IO 0x02
56#define PDB_NOCHECK 0x80
57#endif
58
60f56dfc
KM
59ppiattach(hd)
60 register struct hp_device *hd;
61{
62 register struct ppi_softc *sc = &ppi_softc[hd->hp_unit];
63
a47d912d
KM
64#ifdef DEBUG
65 if ((ppidebug & PDB_NOCHECK) == 0)
66#endif
60f56dfc
KM
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
83ppiopen(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);
a47d912d
KM
91#ifdef DEBUG
92 if (ppidebug & PDB_FOLLOW)
93 printf("ppiopen(%x, %x): flags %x\n",
94 dev, flags, sc->sc_flags);
95#endif
60f56dfc
KM
96 if (sc->sc_flags & PPIF_OPEN)
97 return(EBUSY);
98 sc->sc_flags |= PPIF_OPEN;
a47d912d
KM
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;
60f56dfc
KM
103 return(0);
104}
105
106ppiclose(dev, flags)
107 dev_t dev;
108{
109 register int unit = UNIT(dev);
110 register struct ppi_softc *sc = &ppi_softc[unit];
111
a47d912d
KM
112#ifdef DEBUG
113 if (ppidebug & PDB_FOLLOW)
114 printf("ppiclose(%x, %x): flags %x\n",
115 dev, flags, sc->sc_flags);
116#endif
60f56dfc
KM
117 sc->sc_flags &= ~PPIF_OPEN;
118 return(0);
119}
120
121ppistart(unit)
a47d912d
KM
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]);
ef4c025f 130 return (0);
a47d912d
KM
131}
132
ef4c025f 133void
a47d912d
KM
134ppitimo(unit)
135 int unit;
60f56dfc 136{
a47d912d
KM
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);
60f56dfc
KM
142 wakeup(&ppi_softc[unit]);
143}
144
145ppiread(dev, uio)
146 dev_t dev;
147 struct uio *uio;
148{
149
a47d912d
KM
150#ifdef DEBUG
151 if (ppidebug & PDB_FOLLOW)
152 printf("ppiread(%x, %x)\n", dev, uio);
153#endif
154 return (ppirw(dev, uio));
60f56dfc
KM
155}
156
157ppiwrite(dev, uio)
158 dev_t dev;
159 struct uio *uio;
160{
161
a47d912d
KM
162#ifdef DEBUG
163 if (ppidebug & PDB_FOLLOW)
164 printf("ppiwrite(%x, %x)\n", dev, uio);
165#endif
166 return (ppirw(dev, uio));
60f56dfc
KM
167}
168
a47d912d 169ppirw(dev, uio)
60f56dfc
KM
170 dev_t dev;
171 register struct uio *uio;
60f56dfc 172{
a47d912d
KM
173 int unit = UNIT(dev);
174 register struct ppi_softc *sc = &ppi_softc[unit];
60f56dfc
KM
175 register int s, len, cnt;
176 register char *cp;
a47d912d
KM
177 int error = 0, gotdata = 0;
178 int buflen;
179 char *buf;
180
181 if (uio->uio_resid == 0)
182 return(0);
60f56dfc 183
a47d912d
KM
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
479c0df7 190 buflen = min(sc->sc_burst, uio->uio_resid);
a47d912d
KM
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;
ef4c025f 195 timeout(ppitimo, (void *)unit, sc->sc_timo);
a47d912d 196 }
60f56dfc 197 while (uio->uio_resid > 0) {
479c0df7 198 len = min(buflen, uio->uio_resid);
a47d912d
KM
199 cp = buf;
200 if (uio->uio_rw == UIO_WRITE) {
60f56dfc
KM
201 error = uiomove(cp, len, uio);
202 if (error)
203 break;
204 }
a47d912d 205again:
60f56dfc 206 s = splbio();
a47d912d
KM
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) {
ef4c025f 220 untimeout(ppitimo, (void *)unit);
a47d912d
KM
221 sc->sc_flags &= ~PPIF_TIMO;
222 }
223 splx(s);
224 break;
225 }
60f56dfc 226 splx(s);
a47d912d
KM
227 /*
228 * Perform the operation
229 */
230 if (uio->uio_rw == UIO_WRITE)
60f56dfc 231 cnt = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
a47d912d 232 sc->sc_sec, cp, len);
60f56dfc
KM
233 else
234 cnt = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave,
a47d912d 235 sc->sc_sec, cp, len);
60f56dfc
KM
236 s = splbio();
237 hpibfree(&sc->sc_dq);
a47d912d
KM
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
60f56dfc 245 splx(s);
a47d912d
KM
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)
60f56dfc
KM
258 break;
259 }
a47d912d
KM
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);
60f56dfc
KM
270 break;
271 }
a47d912d
KM
272 /*
273 * Implement inter-read delay
274 */
275 if (sc->sc_delay > 0) {
276 sc->sc_flags |= PPIF_DELAY;
ef4c025f
KM
277 timeout((void (*)__P((void *)))ppistart, (void *)unit,
278 sc->sc_delay);
a47d912d
KM
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) {
ef4c025f 299 untimeout(ppitimo, (void *)unit);
a47d912d
KM
300 sc->sc_flags &= ~PPIF_TIMO;
301 }
302 if (sc->sc_flags & PPIF_DELAY) {
ef4c025f 303 untimeout((void (*)__P((void *)))ppistart, (void *)unit);
a47d912d
KM
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
326ppiioctl(dev, cmd, data, flag)
327 dev_t dev;
328 int 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);
60f56dfc 359 }
60f56dfc
KM
360 return (error);
361}
a47d912d
KM
362
363ppihztoms(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
374ppimstohz(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}
60f56dfc 387#endif