lpt.c revision 1.7.4.11 1 /*
2 * Copyright (c) 1993 Charles Hannum.
3 * Copyright (c) 1990 William F. Jolitz, TeleMuse
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This software is a component of "386BSD" developed by
17 * William F. Jolitz, TeleMuse.
18 * 4. Neither the name of the developer nor the name "386BSD"
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
23 * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
24 * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
25 * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
26 * NOT MAKE USE OF THIS WORK.
27 *
28 * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
29 * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
30 * REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES
31 * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
32 * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
33 * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
34 * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
35 * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
38 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40 * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE
41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 *
49 * $Id: lpt.c,v 1.7.4.11 1993/10/17 05:32:53 mycroft Exp $
50 */
51
52 /*
53 * Device Driver for AT parallel printer port
54 */
55
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/proc.h>
59 #include <sys/user.h>
60 #include <sys/buf.h>
61 #include <sys/kernel.h>
62 #include <sys/ioctl.h>
63 #include <sys/uio.h>
64 #include <sys/device.h>
65 #include <sys/syslog.h>
66
67 #include <machine/cpu.h>
68 #include <machine/pio.h>
69
70 #include <i386/isa/isavar.h>
71 #include <i386/isa/icu.h>
72 #include <i386/isa/lptreg.h>
73
74 #define TIMEOUT hz*16 /* wait up to 4 seconds for a ready */
75 #define STEP hz/4
76
77 #define MAX_SPIN 255
78
79 #define LPTPRI (PZERO+8)
80 #define LPT_BSIZE 1024
81
82 #ifndef DEBUG
83 #define lprintf
84 #else
85 #define lprintf if (lptdebug) printf
86 int lptdebug = 1;
87 #endif
88
89 struct lpt_softc {
90 struct device sc_dev;
91 struct isadev sc_id;
92 struct intrhand sc_ih;
93
94 size_t sc_count;
95 struct buf *sc_inbuf;
96 u_char *sc_cp ;
97 u_short sc_iobase;
98 u_short sc_irq;
99 u_char sc_state;
100 /* bits for state */
101 #define LPT_OPEN 0x01 /* device is open */
102 #define LPT_OBUSY 0x02 /* printer is busy doing output */
103 #define LPT_INIT 0x04 /* waiting to initialize for open */
104 u_char sc_flags;
105 #define LPT_AUTOLF 0x20 /* automatic LF on CR */
106 #define LPT_NOPRIME 0x40 /* don't prime on open */
107 #define LPT_NOINTR 0x80 /* do not use interrupt */
108 u_char sc_control;
109 u_char sc_smax;
110 };
111
112 static int lptprobe __P((struct device *, struct cfdata *, void *));
113 static void lptforceintr __P((void *));
114 static void lptattach __P((struct device *, struct device *, void *));
115 static int lptintr __P((void *));
116
117 struct cfdriver lptcd =
118 { NULL, "lpt", lptprobe, lptattach, DV_TTY, sizeof(struct lpt_softc) };
119
120 #define LPTUNIT(s) ((s)&0x1f)
121 #define LPTFLAGS(s) ((s)&0xe0)
122
123 #define LPS_INVERT (LPS_SELECT|LPS_NERR|LPS_NBSY|LPS_NACK)
124 #define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NBSY|LPS_NACK|LPS_NOPAPER)
125 #define NOT_READY() isready(inb(iobase + lpt_status), sc)
126
127 static int isready __P((u_char, struct lpt_softc *));
128 static void lptout __P((struct lpt_softc *));
129 static int pushbytes __P((struct lpt_softc *));
130
131 /*
132 * Internal routine to lptprobe to do port tests of one byte value
133 */
134 int
135 lpt_port_test(port, data, mask)
136 u_short port;
137 u_char data, mask;
138 {
139 int timeout;
140 u_char temp;
141
142 data &= mask;
143 outb(port, data);
144 timeout = 100;
145 do {
146 temp = inb(port) & mask;
147 } while (temp != data && --timeout);
148 lprintf("lpt: port=0x%x out=0x%x in=0x%x\n", port, data, temp);
149 return (temp == data);
150 }
151
152 /*
153 * Logic:
154 * 1) You should be able to write to and read back the same value
155 * to the data port. Do an alternating zeros, alternating ones,
156 * walking zero, and walking one test to check for stuck bits.
157 *
158 * 2) You should be able to write to and read back the same value
159 * to the control port lower 5 bits, the upper 3 bits are reserved
160 * per the IBM PC technical reference manauls and different boards
161 * do different things with them. Do an alternating zeros, alternating
162 * ones, walking zero, and walking one test to check for stuck bits.
163 *
164 * Some printers drag the strobe line down when the are powered off
165 * so this bit has been masked out of the control port test.
166 *
167 * XXX Some printers may not like a fast pulse on init or strobe, I
168 * don't know at this point, if that becomes a problem these bits
169 * should be turned off in the mask byte for the control port test.
170 *
171 * 3) Set the data and control ports to a value of 0
172 */
173
174 static int
175 lptprobe(parent, cf, aux)
176 struct device *parent;
177 struct cfdata *cf;
178 void *aux;
179 {
180 struct isa_attach_args *ia = aux;
181 u_short iobase = ia->ia_iobase;
182 u_short port = iobase + lpt_data;
183 u_char mask = 0xff;
184 u_char data;
185 int i;
186
187 if (iobase == IOBASEUNK)
188 return 0;
189
190 for (;;) {
191 data = 0x55; /* Alternating zeros */
192 if (!lpt_port_test(port, data, mask))
193 return 0;
194
195 data = 0xaa; /* Alternating ones */
196 if (!lpt_port_test(port, data, mask))
197 return 0;
198
199 for (i = 0; i < CHAR_BIT; i++) { /* Walking zero */
200 data = ~(1 << i);
201 if (!lpt_port_test(port, data, mask))
202 return 0;
203 }
204
205 for (i = 0; i < CHAR_BIT; i++) { /* Walking one */
206 data = (1 << i);
207 if (!lpt_port_test(port, data, mask))
208 return 0;
209 }
210
211 if (port == iobase + lpt_data) {
212 port = iobase + lpt_control;
213 mask = 0x1e;
214 } else
215 break;
216 }
217 outb(iobase + lpt_data, 0);
218 outb(iobase + lpt_control, 0);
219
220 if (ia->ia_irq == IRQUNK)
221 ia->ia_irq = isa_discoverintr(lptforceintr, aux);
222 /* okay if we don't have an irq; will force polling */
223
224 ia->ia_iosize = LPT_NPORTS;
225 ia->ia_drq = DRQUNK;
226 ia->ia_msize = 0;
227 return 1;
228 }
229
230 static void
231 lptattach(parent, self, aux)
232 struct device *parent, *self;
233 void *aux;
234 {
235 struct isa_attach_args *ia = aux;
236 struct lpt_softc *sc = (struct lpt_softc *)self;
237 u_short iobase = ia->ia_iobase;
238 u_short irq = ia->ia_irq;
239
240 sc->sc_iobase = iobase;
241 sc->sc_irq = irq;
242 sc->sc_state = 0;
243 outb(iobase + lpt_control, LPC_NINIT);
244
245 printf(": %sparallel port\n", irq == IRQNONE ? "polled " : "");
246 isa_establish(&sc->sc_id, &sc->sc_dev);
247
248 if (irq != IRQNONE) {
249 sc->sc_ih.ih_fun = lptintr;
250 sc->sc_ih.ih_arg = sc;
251 intr_establish(ia->ia_irq, &sc->sc_ih, DV_TTY);
252 }
253 }
254
255 /*
256 * lptopen -- reset the printer, then wait until it's selected and not busy.
257 */
258 int
259 lptopen(dev, flag)
260 dev_t dev;
261 int flag;
262 {
263 int unit = LPTUNIT(minor(dev));
264 u_char flags = LPTFLAGS(minor(dev));
265 struct lpt_softc *sc;
266 u_short iobase;
267 u_char control;
268 int error;
269 int spin;
270
271 if (unit >= lptcd.cd_ndevs)
272 return ENXIO;
273 sc = lptcd.cd_devs[unit];
274 if (!sc)
275 return ENXIO;
276
277 if (sc->sc_irq == IRQNONE && (flags & LPT_NOINTR) == 0)
278 return ENXIO;
279
280 if (sc->sc_state)
281 return EBUSY;
282
283 #ifdef DIAGNOSTIC
284 if (sc->sc_state)
285 printf("%s: state=0x%x not zero\n", sc->sc_dev.dv_xname,
286 sc->sc_state);
287 #endif
288
289 sc->sc_state = LPT_INIT;
290
291 sc->sc_flags = flags;
292 lprintf("%s: open flags=0x%x\n", sc->sc_dev.dv_xname, flags);
293 iobase = sc->sc_iobase;
294
295 if ((flags & LPT_NOPRIME) == 0) {
296 /* assert INIT for 100 usec to start up printer */
297 outb(iobase + lpt_control, LPC_SELECT);
298 delay(100);
299 }
300
301 control = LPC_SELECT | LPC_NINIT;
302 outb(iobase + lpt_control, control);
303
304 /* wait till ready (printer running diagnostics) */
305 for (spin = 0; NOT_READY(); spin += STEP) {
306 if (spin >= TIMEOUT) {
307 sc->sc_state = 0;
308 return EBUSY;
309 }
310
311 /* wait 1/4 second, give up if we get a signal */
312 if (error = tsleep((caddr_t)sc,
313 LPTPRI | PCATCH, "lptopen", STEP) != EWOULDBLOCK) {
314 sc->sc_state = 0;
315 return error;
316 }
317 }
318
319 if ((flags & LPT_NOINTR) == 0)
320 control |= LPC_IENABLE;
321 if (flags & LPT_AUTOLF)
322 control |= LPC_AUTOLF;
323 sc->sc_control = control;
324 outb(iobase + lpt_control, control);
325
326 sc->sc_state = LPT_OPEN;
327 sc->sc_inbuf = geteblk(LPT_BSIZE);
328 sc->sc_count = 0;
329 lptout(sc);
330
331 lprintf("%s: opened\n", sc->sc_dev.dv_xname);
332 return 0;
333 }
334
335 static int
336 isready(status, sc)
337 u_char status;
338 struct lpt_softc *sc;
339 {
340 status ^= LPS_INVERT;
341
342 if (status & LPS_NOPAPER)
343 log(LOG_NOTICE, "%s: out of paper\n", sc->sc_dev.dv_xname);
344 else if (status & LPS_SELECT)
345 log(LOG_NOTICE, "%s: offline\n", sc->sc_dev.dv_xname);
346 else if (status & LPS_NERR)
347 log(LOG_NOTICE, "%s: output error\n", sc->sc_dev.dv_xname);
348
349 return status;
350 }
351
352 static void
353 lptout(sc)
354 struct lpt_softc *sc;
355 {
356 int s;
357
358 if ((sc->sc_state & LPT_OPEN) == 0)
359 return;
360 if (sc->sc_flags & LPT_NOINTR)
361 return;
362
363 /*
364 * Avoid possible hangs due to missed interrupts
365 */
366 if (sc->sc_count) {
367 s = spltty();
368 (void) lptintr(sc);
369 splx(s);
370 } else {
371 sc->sc_state &= ~LPT_OBUSY;
372 wakeup((caddr_t)sc);
373 }
374
375 timeout((timeout_t)lptout, (caddr_t)sc, STEP);
376 }
377
378 /*
379 * lptclose -- close the device, free the local line buffer.
380 */
381 int
382 lptclose(dev, flag)
383 dev_t dev;
384 int flag;
385 {
386 int unit = LPTUNIT(minor(dev));
387 struct lpt_softc *sc = lptcd.cd_devs[unit];
388 u_short iobase = sc->sc_iobase;
389 int error;
390
391 if (error = pushbytes(sc))
392 return error;
393
394 outb(iobase + lpt_control, LPC_NINIT);
395 brelse(sc->sc_inbuf);
396 sc->sc_state = 0;
397
398 lprintf("%s: closed\n", sc->sc_dev.dv_xname);
399 return 0;
400 }
401
402 static int
403 pushbytes(sc)
404 struct lpt_softc *sc;
405 {
406 u_short iobase = sc->sc_iobase;
407 int error;
408
409 if (sc->sc_flags & LPT_NOINTR) {
410 int spin, tic;
411 u_char control = sc->sc_control;
412 u_char ch;
413
414 while (sc->sc_count > 0) {
415 spin = tic = 0;
416 while (NOT_READY())
417 if (++spin >= sc->sc_smax) {
418 /* exponential backoff */
419 tic = tic + tic + 1;
420 if (error = tsleep((caddr_t)sc,
421 LPTPRI | PCATCH, "lptwrite1", tic))
422 return error;
423 }
424
425 outb(iobase + lpt_data, *sc->sc_cp++);
426 outb(iobase + lpt_control, control | LPC_STROBE);
427 sc->sc_count--;
428 outb(iobase + lpt_control, control);
429
430 /* adapt busy-wait algorithm */
431 if (spin >= sc->sc_smax && sc->sc_smax < MAX_SPIN)
432 sc->sc_smax++;
433 if (spin*2 < sc->sc_smax)
434 sc->sc_smax--;
435 }
436 } else {
437 int s;
438
439 while (sc->sc_count > 0) {
440 /* if the printer is ready for a char, give it one */
441 if ((sc->sc_state & LPT_OBUSY) == 0) {
442 lprintf("%s: write %d\n", sc->sc_dev.dv_xname,
443 sc->sc_count);
444 s = spltty();
445 (void) lptintr(sc);
446 splx(s);
447 }
448 if (error = tsleep((caddr_t)sc,
449 LPTPRI | PCATCH, "lptwrite2", 0))
450 return error;
451 }
452 }
453 }
454
455 /*
456 * copy a line from user space to a local buffer, then call
457 * putc to get the chars moved to the output queue.
458 */
459 int
460 lptwrite(dev, uio)
461 dev_t dev;
462 struct uio *uio;
463 {
464 int unit = LPTUNIT(minor(dev));
465 struct lpt_softc *sc = lptcd.cd_devs[unit];
466 size_t n;
467 int error = 0;
468
469 while (n = MIN(LPT_BSIZE, uio->uio_resid)) {
470 uiomove(sc->sc_cp = sc->sc_inbuf->b_un.b_addr, n, uio);
471 sc->sc_count = n;
472 error = pushbytes(sc);
473 if (error) {
474 /* return accurate residual if interrupted or
475 timed out */
476 uio->uio_resid += sc->sc_count;
477 sc->sc_count = 0;
478 return error;
479 }
480 }
481 return 0;
482 }
483
484 /*
485 * lptintr -- handle printer interrupts which occur when the printer is
486 * ready to accept another char.
487 */
488 static int
489 lptintr(arg)
490 void *arg;
491 {
492 struct lpt_softc *sc = (struct lpt_softc *)arg;
493 u_short iobase = sc->sc_iobase;
494 u_char control = sc->sc_control;
495 u_char status;
496
497 if ((sc->sc_state & LPT_OPEN) == 0)
498 return 0;
499
500 /* is printer online and ready for output */
501 if (NOT_READY())
502 return 0;
503
504 if (sc->sc_count) {
505 /* send char */
506 sc->sc_state |= LPT_OBUSY;
507 while (sc->sc_count && !NOT_READY()) {
508 outb(iobase + lpt_data, *sc->sc_cp++);
509 outb(iobase + lpt_control, control | LPC_STROBE);
510 sc->sc_count--;
511 outb(iobase + lpt_control, control);
512 }
513 } else {
514 /* none, wake up the top half to get more */
515 sc->sc_state &= ~LPT_OBUSY;
516 wakeup((caddr_t)sc);
517 }
518
519 return 1;
520 }
521
522 int
523 lptioctl(dev, cmd, data, flag)
524 dev_t dev;
525 int cmd;
526 caddr_t data;
527 int flag;
528 {
529 int error = 0;
530
531 switch (cmd) {
532 default:
533 error = ENODEV;
534 }
535
536 return error;
537 }
538