Annotation of sys/arch/hp300/dev/ppi.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ppi.c,v 1.16 2006/04/13 20:08:12 miod Exp $ */
2: /* $NetBSD: ppi.c,v 1.13 1997/04/02 22:37:33 scottr Exp $ */
3:
4: /*
5: * Copyright (c) 1996, 1997 Jason R. Thorpe. All rights reserved.
6: * Copyright (c) 1982, 1990, 1993
7: * The Regents of the University of California. All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)ppi.c 8.1 (Berkeley) 6/16/93
34: */
35:
36: /*
37: * Printer/Plotter HPIB interface
38: */
39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/conf.h>
43: #include <sys/device.h>
44: #include <sys/errno.h>
45: #include <sys/kernel.h>
46: #include <sys/malloc.h>
47: #include <sys/proc.h>
48: #include <sys/timeout.h>
49: #include <sys/uio.h>
50:
51: #include <hp300/dev/hpibvar.h>
52:
53: #include <hp300/dev/ppiioctl.h>
54:
55: struct ppi_softc {
56: struct device sc_dev;
57: int sc_flags;
58: struct hpibqueue sc_hq; /* HP-IB job queue entry */
59: struct ppiparam sc_param;
60: #define sc_burst sc_param.burst
61: #define sc_timo sc_param.timo
62: #define sc_delay sc_param.delay
63: int sc_sec;
64: int sc_slave; /* HP-IB slave address */
65: struct timeout sc_to; /* ppitimo timeout */
66: struct timeout sc_start_to; /* ppistart timeout */
67: };
68:
69: /* sc_flags values */
70: #define PPIF_ALIVE 0x01
71: #define PPIF_OPEN 0x02
72: #define PPIF_UIO 0x04
73: #define PPIF_TIMO 0x08
74: #define PPIF_DELAY 0x10
75:
76: int ppimatch(struct device *, void *, void *);
77: void ppiattach(struct device *, struct device *, void *);
78:
79: struct cfattach ppi_ca = {
80: sizeof(struct ppi_softc), ppimatch, ppiattach
81: };
82:
83: struct cfdriver ppi_cd = {
84: NULL, "ppi", DV_DULL
85: };
86:
87: void ppistart(void *);
88: void ppinoop(void *);
89:
90: void ppitimo(void *);
91: int ppirw(dev_t, struct uio *);
92: int ppihztoms(int);
93: int ppimstohz(int);
94:
95: cdev_decl(ppi);
96:
97: #define UNIT(x) minor(x)
98:
99: #ifdef DEBUG
100: int ppidebug = 0x80;
101: #define PDB_FOLLOW 0x01
102: #define PDB_IO 0x02
103: #define PDB_NOCHECK 0x80
104: #endif
105:
106: int
107: ppimatch(parent, match, aux)
108: struct device *parent;
109: void *match, *aux;
110: {
111: struct cfdata *cf = match;
112: struct hpibbus_attach_args *ha = aux;
113:
114: /*
115: * The printer/plotter doesn't return an ID tag.
116: * The check below prevents us from matching a CS80
117: * device by mistake.
118: */
119: if (ha->ha_id & 0x200)
120: return (0);
121:
122: /*
123: * To prevent matching all unused slots on the bus, we
124: * don't allow wildcarded locators.
125: */
126: if (cf->hpibbuscf_slave == HPIBBUS_SLAVE_UNK ||
127: cf->hpibbuscf_punit == HPIBBUS_PUNIT_UNK)
128: return (0);
129:
130: return (1);
131: }
132:
133: void
134: ppiattach(parent, self, aux)
135: struct device *parent, *self;
136: void *aux;
137: {
138: struct ppi_softc *sc = (struct ppi_softc *)self;
139: struct hpibbus_attach_args *ha = aux;
140:
141: printf("\n");
142:
143: sc->sc_slave = ha->ha_slave;
144:
145: /* Initialize the hpib queue entry. */
146: sc->sc_hq.hq_softc = sc;
147: sc->sc_hq.hq_slave = sc->sc_slave;
148: sc->sc_hq.hq_start = ppistart;
149: sc->sc_hq.hq_go = ppinoop;
150: sc->sc_hq.hq_intr = ppinoop;
151:
152: sc->sc_flags = PPIF_ALIVE;
153:
154: /* Initialize timeout structures */
155: timeout_set(&sc->sc_to, ppitimo, sc);
156: timeout_set(&sc->sc_start_to, ppistart, sc);
157: }
158:
159: void
160: ppinoop(arg)
161: void *arg;
162: {
163: /* Noop! */
164: }
165:
166: int
167: ppiopen(dev, flags, fmt, p)
168: dev_t dev;
169: int flags, fmt;
170: struct proc *p;
171: {
172: int unit = UNIT(dev);
173: struct ppi_softc *sc;
174:
175: if (unit >= ppi_cd.cd_ndevs ||
176: (sc = ppi_cd.cd_devs[unit]) == NULL ||
177: (sc->sc_flags & PPIF_ALIVE) == 0)
178: return (ENXIO);
179:
180: #ifdef DEBUG
181: if (ppidebug & PDB_FOLLOW)
182: printf("ppiopen(%x, %x): flags %x\n",
183: dev, flags, sc->sc_flags);
184: #endif
185: if (sc->sc_flags & PPIF_OPEN)
186: return (EBUSY);
187: sc->sc_flags |= PPIF_OPEN;
188: sc->sc_burst = PPI_BURST;
189: sc->sc_timo = ppimstohz(PPI_TIMO);
190: sc->sc_delay = ppimstohz(PPI_DELAY);
191: sc->sc_sec = -1;
192: return(0);
193: }
194:
195: int
196: ppiclose(dev, flags, fmt, p)
197: dev_t dev;
198: int flags, fmt;
199: struct proc *p;
200: {
201: int unit = UNIT(dev);
202: struct ppi_softc *sc = ppi_cd.cd_devs[unit];
203:
204: #ifdef DEBUG
205: if (ppidebug & PDB_FOLLOW)
206: printf("ppiclose(%x, %x): flags %x\n",
207: dev, flags, sc->sc_flags);
208: #endif
209: sc->sc_flags &= ~PPIF_OPEN;
210: return(0);
211: }
212:
213: void
214: ppistart(arg)
215: void *arg;
216: {
217: struct ppi_softc *sc = arg;
218:
219: #ifdef DEBUG
220: if (ppidebug & PDB_FOLLOW)
221: printf("ppistart(%x)\n", sc->sc_dev.dv_unit);
222: #endif
223: sc->sc_flags &= ~PPIF_DELAY;
224: wakeup(sc);
225: }
226:
227: void
228: ppitimo(arg)
229: void *arg;
230: {
231: struct ppi_softc *sc = arg;
232:
233: #ifdef DEBUG
234: if (ppidebug & PDB_FOLLOW)
235: printf("ppitimo(%x)\n", sc->sc_dev.dv_unit);
236: #endif
237: sc->sc_flags &= ~(PPIF_UIO|PPIF_TIMO);
238: wakeup(sc);
239: }
240:
241: int
242: ppiread(dev, uio, flags)
243: dev_t dev;
244: struct uio *uio;
245: int flags;
246: {
247:
248: #ifdef DEBUG
249: if (ppidebug & PDB_FOLLOW)
250: printf("ppiread(%x, %p)\n", dev, uio);
251: #endif
252: return (ppirw(dev, uio));
253: }
254:
255: int
256: ppiwrite(dev, uio, flags)
257: dev_t dev;
258: struct uio *uio;
259: int flags;
260: {
261:
262: #ifdef DEBUG
263: if (ppidebug & PDB_FOLLOW)
264: printf("ppiwrite(%x, %p)\n", dev, uio);
265: #endif
266: return (ppirw(dev, uio));
267: }
268:
269: int
270: ppirw(dev, uio)
271: dev_t dev;
272: struct uio *uio;
273: {
274: int unit = UNIT(dev);
275: struct ppi_softc *sc = ppi_cd.cd_devs[unit];
276: int s, len, cnt;
277: char *cp;
278: int error = 0, gotdata = 0;
279: int buflen, ctlr, slave;
280: char *buf;
281:
282: if (uio->uio_resid == 0)
283: return(0);
284:
285: ctlr = sc->sc_dev.dv_parent->dv_unit;
286: slave = sc->sc_slave;
287:
288: #ifdef DEBUG
289: if (ppidebug & (PDB_FOLLOW|PDB_IO))
290: printf("ppirw(%x, %p, %c): burst %d, timo %d, resid %x\n",
291: dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W',
292: sc->sc_burst, sc->sc_timo, uio->uio_resid);
293: #endif
294: buflen = min(sc->sc_burst, uio->uio_resid);
295: buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK);
296: sc->sc_flags |= PPIF_UIO;
297: if (sc->sc_timo > 0) {
298: sc->sc_flags |= PPIF_TIMO;
299: timeout_add(&sc->sc_to, sc->sc_timo);
300: }
301: len = cnt = 0;
302: while (uio->uio_resid > 0) {
303: len = min(buflen, uio->uio_resid);
304: cp = buf;
305: if (uio->uio_rw == UIO_WRITE) {
306: error = uiomove(cp, len, uio);
307: if (error)
308: break;
309: }
310: again:
311: s = splbio();
312: if ((sc->sc_flags & PPIF_UIO) &&
313: hpibreq(sc->sc_dev.dv_parent, &sc->sc_hq) == 0)
314: tsleep(sc, PRIBIO+1, "ppirw", 0);
315: /*
316: * Check if we timed out during sleep or uiomove
317: */
318: if ((sc->sc_flags & PPIF_UIO) == 0) {
319: #ifdef DEBUG
320: if (ppidebug & PDB_IO)
321: printf("ppirw: uiomove/sleep timo, flags %x\n",
322: sc->sc_flags);
323: #endif
324: if (sc->sc_flags & PPIF_TIMO) {
325: timeout_del(&sc->sc_to);
326: sc->sc_flags &= ~PPIF_TIMO;
327: }
328: splx(s);
329: break;
330: }
331: /*
332: * Perform the operation
333: */
334: if (uio->uio_rw == UIO_WRITE)
335: cnt = hpibsend(ctlr, slave, sc->sc_sec, cp, len);
336: else
337: cnt = hpibrecv(ctlr, slave, sc->sc_sec, cp, len);
338: hpibfree(sc->sc_dev.dv_parent, &sc->sc_hq);
339: #ifdef DEBUG
340: if (ppidebug & PDB_IO)
341: printf("ppirw: %s(%d, %d, %x, %p, %d) -> %d\n",
342: uio->uio_rw == UIO_READ ? "recv" : "send",
343: ctlr, slave, sc->sc_sec, cp, len, cnt);
344: #endif
345: if (uio->uio_rw == UIO_READ) {
346: if (cnt) {
347: error = uiomove(cp, cnt, uio);
348: if (error) {
349: splx(s);
350: break;
351: }
352: gotdata++;
353: }
354: /*
355: * Didn't get anything this time, but did in the past.
356: * Consider us done.
357: */
358: else if (gotdata) {
359: splx(s);
360: break;
361: }
362: }
363: /*
364: * Operation timeout (or non-blocking), quit now.
365: */
366: if ((sc->sc_flags & PPIF_UIO) == 0) {
367: #ifdef DEBUG
368: if (ppidebug & PDB_IO)
369: printf("ppirw: timeout/done\n");
370: #endif
371: splx(s);
372: break;
373: }
374: /*
375: * Implement inter-read delay
376: */
377: if (sc->sc_delay > 0) {
378: sc->sc_flags |= PPIF_DELAY;
379: timeout_add(&sc->sc_start_to, sc->sc_delay);
380: error = tsleep(sc, (PCATCH|PZERO) + 1, "hpib", 0);
381: if (error) {
382: splx(s);
383: break;
384: }
385: }
386: /*
387: * Must not call uiomove again til we've used all data
388: * that we already grabbed.
389: */
390: if (uio->uio_rw == UIO_WRITE && cnt != len) {
391: cp += cnt;
392: len -= cnt;
393: cnt = 0;
394: splx(s);
395: goto again;
396: }
397: splx(s);
398: }
399: if (sc->sc_flags & PPIF_TIMO) {
400: timeout_del(&sc->sc_to);
401: sc->sc_flags &= ~PPIF_TIMO;
402: }
403: if (sc->sc_flags & PPIF_DELAY) {
404: timeout_del(&sc->sc_start_to);
405: sc->sc_flags &= ~PPIF_DELAY;
406: }
407: /*
408: * Adjust for those chars that we uiomove'ed but never wrote
409: */
410: if (uio->uio_rw == UIO_WRITE && cnt != len) {
411: uio->uio_resid += (len - cnt);
412: #ifdef DEBUG
413: if (ppidebug & PDB_IO)
414: printf("ppirw: short write, adjust by %d\n",
415: len-cnt);
416: #endif
417: }
418: free(buf, M_DEVBUF);
419: #ifdef DEBUG
420: if (ppidebug & (PDB_FOLLOW|PDB_IO))
421: printf("ppirw: return %d, resid %d\n", error, uio->uio_resid);
422: #endif
423: return (error);
424: }
425:
426: int
427: ppiioctl(dev, cmd, data, flag, p)
428: dev_t dev;
429: u_long cmd;
430: caddr_t data;
431: int flag;
432: struct proc *p;
433: {
434: struct ppi_softc *sc = ppi_cd.cd_devs[UNIT(dev)];
435: struct ppiparam *pp, *upp;
436: int tmp;
437: int error = 0;
438:
439: switch (cmd) {
440: case PPIIOCGPARAM:
441: pp = &sc->sc_param;
442: upp = (struct ppiparam *)data;
443: upp->burst = pp->burst;
444: upp->timo = ppihztoms(pp->timo);
445: upp->delay = ppihztoms(pp->delay);
446: break;
447: case PPIIOCSPARAM:
448: pp = &sc->sc_param;
449: upp = (struct ppiparam *)data;
450: if (upp->burst < PPI_BURST_MIN || upp->burst > PPI_BURST_MAX ||
451: upp->delay < PPI_DELAY_MIN || upp->delay > PPI_DELAY_MAX)
452: return(EINVAL);
453: pp->burst = upp->burst;
454: pp->timo = ppimstohz(upp->timo);
455: pp->delay = ppimstohz(upp->delay);
456: break;
457: case PPIIOCSSEC:
458: tmp = *(int *)data;
459: if (tmp == -1 || (tmp >= 0 && tmp <= 0x1f))
460: sc->sc_sec = tmp;
461: else
462: error = EINVAL;
463: break;
464: default:
465: return (ENOTTY);
466: }
467: return (error);
468: }
469:
470: int
471: ppihztoms(h)
472: int h;
473: {
474: int m = h;
475:
476: if (m > 0)
477: m = m * 1000 / hz;
478: return(m);
479: }
480:
481: int
482: ppimstohz(m)
483: int m;
484: {
485: int h = m;
486:
487: if (h > 0) {
488: h = h * hz / 1000;
489: if (h == 0)
490: h = 1000 / hz;
491: }
492: return(h);
493: }
CVSweb