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