lpt.c revision 1.11 1 /* $NetBSD: lpt.c,v 1.11 2004/02/03 19:57:00 jdolecek Exp $ */
2
3 /*
4 * Copyright (c) 1990 William F. Jolitz, TeleMuse
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This software is a component of "386BSD" developed by
18 * William F. Jolitz, TeleMuse.
19 * 4. Neither the name of the developer nor the name "386BSD"
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
24 * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
25 * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
26 * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
27 * NOT MAKE USE OF THIS WORK.
28 *
29 * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
30 * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
31 * REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES
32 * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
33 * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
34 * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
35 * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
36 * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE
42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 *
50 * from: unknown origin, 386BSD 0.1
51 * From Id: lpt.c,v 1.55.2.1 1996/11/12 09:08:38 phk Exp
52 * From Id: nlpt.c,v 1.14 1999/02/08 13:55:43 des Exp
53 * FreeBSD: src/sys/dev/ppbus/lpt.c,v 1.15.2.3 2000/07/07 00:30:40 obrien Exp
54 */
55
56 /*
57 * Device Driver for AT parallel printer port
58 * Written by William Jolitz 12/18/90
59 */
60
61 /*
62 * Updated for ppbus by Nicolas Souchu
63 * [Mon Jul 28 1997]
64 */
65
66 #include <sys/cdefs.h>
67 __KERNEL_RCSID(0, "$NetBSD: lpt.c,v 1.11 2004/02/03 19:57:00 jdolecek Exp $");
68
69 #include "opt_ppbus_lpt.h"
70
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/conf.h>
74 #include <sys/kernel.h>
75 #include <sys/proc.h>
76 #include <sys/malloc.h>
77 #include <sys/file.h>
78 #include <sys/uio.h>
79 #include <sys/ioctl.h>
80 #include <sys/types.h>
81 #include <sys/syslog.h>
82
83 #include <machine/bus.h>
84
85 #include <dev/ppbus/ppbus_1284.h>
86 #include <dev/ppbus/ppbus_base.h>
87 #include <dev/ppbus/ppbus_io.h>
88 #include <dev/ppbus/ppbus_msq.h>
89 #include <dev/ppbus/ppbus_var.h>
90
91 #include <dev/ppbus/lptvar.h>
92 #include <dev/ppbus/lptreg.h>
93 #include <dev/ppbus/lptio.h>
94
95 /* Autoconf functions */
96 static int lpt_probe(struct device *, struct cfdata *, void *);
97 static void lpt_attach(struct device *, struct device *, void *);
98 static int lpt_detach(struct device *, int);
99
100 /* Autoconf structure */
101 CFATTACH_DECL(lpt_ppbus, sizeof(struct lpt_softc), lpt_probe, lpt_attach,
102 lpt_detach, NULL);
103
104 extern struct cfdriver lpt_cd;
105
106 dev_type_open(lptopen);
107 dev_type_close(lptclose);
108 dev_type_read(lptread);
109 dev_type_write(lptwrite);
110 dev_type_ioctl(lptioctl);
111
112 const struct cdevsw lpt_cdevsw = {
113 lptopen, lptclose, lptread, lptwrite, lptioctl,
114 nostop, notty, nopoll, nommap, nokqfilter
115 };
116
117
118 /* Function prototypes */
119 static int lpt_detect(struct device *);
120 static int lpt_request_ppbus(struct lpt_softc *, int);
121 static int lpt_release_ppbus(struct lpt_softc *, int);
122 static int lpt_logstatus(const struct device * const, const unsigned char);
123
124 /*
125 * lpt_probe()
126 */
127 static int
128 lpt_probe(struct device * parent, struct cfdata * match, void * aux)
129 {
130 /* Test ppbus's capability */
131 return lpt_detect(parent);
132 }
133
134 static void
135 lpt_attach(struct device * parent, struct device * self, void * aux)
136 {
137 struct lpt_softc * sc = (struct lpt_softc *) self;
138 struct ppbus_device_softc * ppbdev = &(sc->ppbus_dev);
139 struct ppbus_attach_args * args = aux;
140 char buf[64];
141 int error;
142
143 error = lpt_request_ppbus(sc, 0);
144 if(error) {
145 printf("%s(%s): error (%d) requesting bus(%s). Device not "
146 "properly attached.\n", __func__, self->dv_xname,
147 error, parent->dv_xname);
148 return;
149 }
150
151 /* Record capabilities */
152 ppbdev->capabilities = args->capabilities;
153
154 /* Allocate memory buffers */
155 if(ppbdev->capabilities & PPBUS_HAS_DMA) {
156 if(ppbus_dma_malloc(parent, &(sc->sc_inbuf),
157 &(sc->sc_in_baddr), BUFSIZE)) {
158
159 printf(" : cannot allocate input DMA buffer. Device "
160 "not properly attached!\n");
161 return;
162 }
163 if(ppbus_dma_malloc(parent, &(sc->sc_outbuf),
164 &(sc->sc_out_baddr), BUFSIZE)) {
165
166 ppbus_dma_free(parent, &(sc->sc_inbuf),
167 &(sc->sc_in_baddr), BUFSIZE);
168 printf(" : cannot allocate output DMA buffer. Device "
169 "not properly attached!\n");
170 return;
171 }
172 } else {
173 sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
174 sc->sc_outbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
175 }
176
177 /* Print out mode */
178 ppbdev->ctx.mode = ppbus_get_mode(parent);
179 bitmask_snprintf(ppbdev->ctx.mode, "\20\1COMPATIBLE\2NIBBLE"
180 "\3PS2\4EPP\5ECP\6FAST_CENTR", buf, sizeof(buf));
181 printf(": port mode = %s\n", buf);
182
183 lpt_release_ppbus(sc, 0);
184 }
185
186 static int
187 lpt_detach(struct device * self, int flags)
188 {
189 struct lpt_softc * lpt = (struct lpt_softc *) self;
190 struct ppbus_device_softc * ppbdev = (struct ppbus_device_softc *) lpt;
191 int err;
192
193 if(lpt->sc_state & HAVEBUS) {
194 err = lpt_release_ppbus(lpt, 0);
195 if(err) {
196 printf("%s error (%d) while releasing bus",
197 self->dv_xname, err);
198 if(flags & DETACH_FORCE) {
199 printf(", continuing (DETACH_FORCE)!\n");
200 }
201 else {
202 printf(", terminating!\n");
203 return 0;
204 }
205 }
206 lpt->sc_state &= ~HAVEBUS;
207 }
208
209 ppbdev->ctx.valid = 0;
210
211 /* Free memory buffers */
212 if(ppbdev->capabilities & PPBUS_HAS_DMA) {
213 ppbus_dma_free(self->dv_parent, &(lpt->sc_inbuf),
214 &(lpt->sc_in_baddr), BUFSIZE);
215 ppbus_dma_free(self->dv_parent, &(lpt->sc_outbuf),
216 &(lpt->sc_out_baddr), BUFSIZE);
217 } else {
218 free(lpt->sc_inbuf, M_DEVBUF);
219 free(lpt->sc_outbuf, M_DEVBUF);
220 }
221
222 if(!(flags & DETACH_QUIET)) {
223 printf("%s detached", self->dv_xname);
224 }
225
226 return 1;
227 }
228
229 /* Grab bus for lpt device */
230 static int
231 lpt_request_ppbus(struct lpt_softc * lpt, int how)
232 {
233 struct device * dev = (struct device *) lpt;
234 int error;
235
236 error = ppbus_request_bus(dev->dv_parent, dev, how, (hz));
237 if (!(error)) {
238 lpt->sc_state |= HAVEBUS;
239 }
240 else {
241 LPT_DPRINTF(("%s(%s): error %d requesting bus.\n", __func__,
242 dev->dv_xname, error));
243 }
244
245 return error;
246 }
247
248 /* Release ppbus to enable other devices to use it. */
249 static int
250 lpt_release_ppbus(struct lpt_softc * lpt, int how)
251 {
252 struct device * dev = (struct device *) lpt;
253 int error;
254
255 if(lpt->sc_state & HAVEBUS) {
256 error = ppbus_release_bus(dev->dv_parent, dev, how, (hz));
257 if(!(error))
258 lpt->sc_state &= ~HAVEBUS;
259 else
260 LPT_DPRINTF(("%s(%s): error releasing bus.\n", __func__,
261 dev->dv_xname));
262 }
263 else {
264 error = EINVAL;
265 LPT_DPRINTF(("%s(%s): device does not own bus.\n", __func__,
266 dev->dv_xname));
267 }
268
269 return error;
270 }
271
272
273 /*
274 * Probe simplified by replacing multiple loops with a hardcoded
275 * test pattern - 1999/02/08 des (at) freebsd.org
276 *
277 * New lpt port probe Geoff Rehmet - Rhodes University - 14/2/94
278 * Based partially on Rod Grimes' printer probe
279 *
280 * Logic:
281 * 1) If no port address was given, use the bios detected ports
282 * and autodetect what ports the printers are on.
283 * 2) Otherwise, probe the data port at the address given,
284 * using the method in Rod Grimes' port probe.
285 * (Much code ripped off directly from Rod's probe.)
286 *
287 * Comments from Rod's probe:
288 * Logic:
289 * 1) You should be able to write to and read back the same value
290 * to the data port. Do an alternating zeros, alternating ones,
291 * walking zero, and walking one test to check for stuck bits.
292 *
293 * 2) You should be able to write to and read back the same value
294 * to the control port lower 5 bits, the upper 3 bits are reserved
295 * per the IBM PC technical reference manauls and different boards
296 * do different things with them. Do an alternating zeros, alternating
297 * ones, walking zero, and walking one test to check for stuck bits.
298 *
299 * Some printers drag the strobe line down when the are powered off
300 * so this bit has been masked out of the control port test.
301 *
302 * XXX Some printers may not like a fast pulse on init or strobe, I
303 * don't know at this point, if that becomes a problem these bits
304 * should be turned off in the mask byte for the control port test.
305 *
306 * We are finally left with a mask of 0x14, due to some printers
307 * being adamant about holding other bits high ........
308 *
309 * Before probing the control port, we write a 0 to the data port -
310 * If not, some printers chuck out garbage when the strobe line
311 * gets toggled.
312 *
313 * 3) Set the data and control ports to a value of 0
314 *
315 * This probe routine has been tested on Epson Lx-800, HP LJ3P,
316 * Epson FX-1170 and C.Itoh 8510RM
317 * printers.
318 * Quick exit on fail added.
319 */
320 static int
321 lpt_detect(struct device * dev)
322 {
323 static const u_char testbyte[18] = {
324 0x55, /* alternating zeros */
325 0xaa, /* alternating ones */
326 0xfe, 0xfd, 0xfb, 0xf7,
327 0xef, 0xdf, 0xbf, 0x7f, /* walking zero */
328 0x01, 0x02, 0x04, 0x08,
329 0x10, 0x20, 0x40, 0x80 /* walking one */
330 };
331 int i, status;
332 u_char dtr, ctr, str, var;
333
334 /* Save register contents */
335 dtr = ppbus_rdtr(dev);
336 ctr = ppbus_rctr(dev);
337 str = ppbus_rstr(dev);
338
339 status = 1; /* assume success */
340
341 /* Test data port */
342 for(i = 0; i < 18; i++) {
343 ppbus_wdtr(dev, testbyte[i]);
344 if((var = ppbus_rdtr(dev)) != testbyte[i]) {
345 status = 0;
346 LPT_DPRINTF(("%s(%s): byte value %x cannot be written "
347 "and read from data port (got %x instead).\n",
348 __func__, dev->dv_xname, testbyte[i], var));
349 goto end;
350 }
351 }
352
353 /* Test control port */
354 ppbus_wdtr(dev, 0);
355 for(i = 0; i < 18; i++) {
356 ppbus_wctr(dev, (testbyte[i] & 0x14));
357 if(((var = ppbus_rctr(dev)) & 0x14) != (testbyte[i] & 0x14)) {
358 status = 0;
359 LPT_DPRINTF(("%s(%s): byte value %x (unmasked value "
360 "%x) cannot be written and read from control "
361 "port (got %x instead).\n", __func__,
362 dev->dv_xname, (testbyte[i] & 0x14),
363 testbyte[i], (var & 0x14)));
364 break;
365 }
366 }
367
368 end:
369 /* Restore contents of registers */
370 ppbus_wdtr(dev, dtr);
371 ppbus_wctr(dev, ctr);
372 ppbus_wstr(dev, str);
373
374 return status;
375 }
376
377 /* Log status of status register for printer port */
378 static int
379 lpt_logstatus(const struct device * const dev, const unsigned char status)
380 {
381 int err;
382
383 err = EIO;
384 if(!(status & LPS_SEL)) {
385 log(LOG_ERR, "%s: offline.", dev->dv_xname);
386 }
387 else if(!(status & LPS_NBSY)) {
388 log(LOG_ERR, "%s: busy.", dev->dv_xname);
389 }
390 else if(status & LPS_OUT) {
391 log(LOG_ERR, "%s: out of paper.", dev->dv_xname);
392 err = EAGAIN;
393 }
394 else if(!(status & LPS_NERR)) {
395 log(LOG_ERR, "%s: output error.", dev->dv_xname);
396 }
397 else {
398 log(LOG_ERR, "%s: no error indication.", dev->dv_xname);
399 err = 0;
400 }
401
402 return err;
403 }
404
405 /*
406 * lptopen -- reset the printer, then wait until it's selected and not busy.
407 */
408 int
409 lptopen(dev_t dev_id, int flags, int fmt, struct proc *p)
410 {
411 int trys, err, val;
412 u_int8_t status;
413 struct device * dev;
414 struct lpt_softc * lpt;
415 struct ppbus_device_softc * ppbus_dev;
416 struct device * ppbus;
417
418 dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
419 if(!dev) {
420 LPT_DPRINTF(("%s(): device not configured.\n", __func__));
421 return ENXIO;
422 }
423
424 lpt = (struct lpt_softc *) dev;
425
426 ppbus = dev->dv_parent;
427 ppbus_dev = &(lpt->ppbus_dev);
428
429 /* Request the ppbus */
430 err = lpt_request_ppbus(lpt, PPBUS_WAIT|PPBUS_INTR);
431 if(err) {
432 LPT_DPRINTF(("%s(%s): error (%d) while requesting bus.\n",
433 __func__, dev->dv_xname, err));
434 return (err);
435 }
436
437 /* Get device flags */
438 lpt->sc_flags = LPTFLAGS(dev_id);
439
440 /* Update bus mode */
441 ppbus_dev->ctx.mode = ppbus_get_mode(ppbus);
442
443 /* Configure interrupts/polling */
444 if(lpt->sc_flags & LPT_NOINTR) {
445 val = 0;
446 err = ppbus_write_ivar(ppbus, PPBUS_IVAR_INTR, &val);
447 if(err) {
448 lpt_release_ppbus(lpt, PPBUS_WAIT);
449 return err;
450 }
451 }
452 else {
453 val = 1;
454 err = ppbus_write_ivar(ppbus, PPBUS_IVAR_INTR, &val);
455 if(err) {
456 lpt_release_ppbus(lpt, PPBUS_WAIT);
457 return err;
458 }
459 }
460 if(err) {
461 lpt_release_ppbus(lpt, PPBUS_WAIT);
462 return err;
463 }
464
465 /* init printer */
466 if(!(lpt->sc_flags & LPT_NOPRIME)) {
467 LPT_VPRINTF(("%s(%s): initializing printer.\n", __func__,
468 dev->dv_xname));
469 lpt->sc_state |= LPTINIT;
470 ppbus_wctr(ppbus, LPC_SEL | LPC_NINIT);
471
472 /* wait till ready (printer running diagnostics) */
473 for(trys = 0, status = ppbus_rstr(ppbus); (status & RDY_MASK)
474 != LP_READY; trys += LPT_STEP, status =
475 ppbus_rstr(ppbus)) {
476
477 /* Time up waiting for the printer */
478 if(trys >= LPT_TIMEOUT)
479 break;
480 /* wait LPT_STEP ticks, give up if we get a signal */
481 else {
482 err = tsleep((caddr_t)lpt, LPPRI|PCATCH,
483 "lptinit", LPT_STEP);
484 if((err) && (err != EWOULDBLOCK)) {
485 lpt->sc_state &= ~LPTINIT;
486 LPT_DPRINTF(("%s(%s): interrupted "
487 "during initialization.\n", __func__,
488 dev->dv_xname));
489 lpt_release_ppbus(lpt, PPBUS_WAIT);
490 return (err);
491 }
492 }
493 }
494
495 lpt->sc_state &= ~LPTINIT;
496 if(trys >= LPT_TIMEOUT) {
497 LPT_DPRINTF(("%s(%s): timed out while initializing "
498 "printer. [status %x]\n", __func__,
499 dev->dv_xname, status));
500 err = lpt_logstatus(dev, status);
501 lpt_release_ppbus(lpt, PPBUS_WAIT);
502 return (err);
503 }
504 else
505 LPT_VPRINTF(("%s(%s): printer ready.\n", __func__,
506 dev->dv_xname));
507 }
508
509 /* Set autolinefeed */
510 if(lpt->sc_flags & LPT_AUTOLF) {
511 lpt->sc_control |= LPC_AUTOL;
512 }
513
514 /* Write out the control register */
515 ppbus_wctr(ppbus, lpt->sc_control);
516
517 lpt->sc_state |= OPEN;
518
519 return 0;
520 }
521
522 /*
523 * lptclose -- close the device, free the local line buffer.
524 *
525 * Check for interrupted write call added.
526 */
527 int
528 lptclose(dev_t dev_id, int flags, int fmt, struct proc *p)
529 {
530 struct device * dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
531 struct lpt_softc * sc = (struct lpt_softc *) dev;
532 int err;
533
534 err = lpt_release_ppbus(sc, PPBUS_WAIT|PPBUS_INTR);
535 if(err) {
536 LPT_DPRINTF(("%s(%s): error (%d) while releasing ppbus.\n",
537 __func__, dev->dv_xname, err));
538 }
539
540 sc->sc_state = 0;
541
542 return err;
543 }
544
545 /*
546 * lptread --retrieve printer status in IEEE1284 NIBBLE mode
547 */
548 int
549 lptread(dev_t dev_id, struct uio *uio, int ioflag)
550 {
551 size_t len = 0;
552 int error = 0;
553 struct device * dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
554 struct lpt_softc * sc = (struct lpt_softc *) dev;
555
556 if(!(sc->sc_state & HAVEBUS)) {
557 LPT_DPRINTF(("%s(%s): attempt to read using device which does "
558 "not own the bus(%s).\n", __func__, dev->dv_xname,
559 dev->dv_parent->dv_xname));
560 return (ENODEV);
561 }
562
563 sc->sc_state &= ~INTERRUPTED;
564 while (uio->uio_resid) {
565 error = ppbus_read(dev->dv_parent, sc->sc_outbuf,
566 min(BUFSIZE, uio->uio_resid), 0, &len);
567
568 /* If error or no more data, stop */
569 if (error) {
570 if (error != EWOULDBLOCK)
571 sc->sc_state |= INTERRUPTED;
572 break;
573 }
574 if (len == 0)
575 break;
576
577 if ((error = uiomove(sc->sc_outbuf, len, uio)))
578 break;
579 }
580
581 return error;
582 }
583
584 /*
585 * lptwrite --copy a line from user space to a local buffer, then call
586 * putc to get the chars moved to the output queue.
587 *
588 * Flagging of interrupted write added.
589 */
590 int
591 lptwrite(dev_t dev_id, struct uio * uio, int ioflag)
592 {
593 int error=0;
594 size_t n, cnt;
595 struct device * dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
596 struct lpt_softc * sc = (struct lpt_softc *) dev;
597
598 /* Check state and flags */
599 if(!(sc->sc_state & HAVEBUS)) {
600 LPT_DPRINTF(("%s(%s): attempt to write using device which does "
601 "not own the bus(%s).\n", __func__, dev->dv_xname,
602 dev->dv_parent->dv_xname));
603 return EINVAL;
604 }
605
606 LPT_VPRINTF(("%s(%s): writing %d bytes\n", __func__,
607 dev->dv_xname, uio->uio_resid));
608
609 /* Write the data */
610 sc->sc_state &= ~INTERRUPTED;
611 while (uio->uio_resid) {
612 n = MIN(BUFSIZE, uio->uio_resid);
613 error = uiomove(sc->sc_inbuf, n, uio);
614 if (error)
615 break;
616
617 error = ppbus_write(dev->dv_parent, sc->sc_inbuf, n, ioflag,
618 &cnt);
619 if (error) {
620 if (error != EWOULDBLOCK)
621 sc->sc_state |= INTERRUPTED;
622 break;
623 }
624 }
625
626 LPT_VPRINTF(("%s(%s): transfer finished, error %d.\n", __func__,
627 dev->dv_xname, error));
628
629 return error;
630 }
631
632 /* Printer ioctl */
633 int
634 lptioctl(dev_t dev_id, u_long cmd, caddr_t data, int flags, struct proc *p)
635 {
636 struct device * dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
637 struct lpt_softc * sc = (struct lpt_softc *) dev;
638 int val, fl;
639 int error=0;
640
641 if(!(sc->sc_state & HAVEBUS)) {
642 LPT_DPRINTF(("%s(%s): attempt to perform ioctl on device which "
643 "does not own the bus(%s).\n", __func__, dev->dv_xname,
644 dev->dv_parent->dv_xname));
645 return EBUSY;
646 }
647
648 switch (cmd) {
649 case LPTGMODE:
650 switch (ppbus_get_mode(dev->dv_parent)) {
651 case PPBUS_COMPATIBLE:
652 val = mode_standard;
653 break;
654 case PPBUS_NIBBLE:
655 val = mode_nibble;
656 break;
657 case PPBUS_PS2:
658 val = mode_ps2;
659 break;
660 case PPBUS_FAST:
661 val = mode_fast;
662 break;
663 case PPBUS_EPP:
664 val = mode_epp;
665 break;
666 case PPBUS_ECP:
667 val = mode_ecp;
668 break;
669 default:
670 error = EINVAL;
671 val = mode_unknown;
672 break;
673 }
674 *(int *)data = val;
675 break;
676
677 case LPTSMODE:
678 switch (*(int *)data) {
679 case mode_standard:
680 val = PPBUS_COMPATIBLE;
681 break;
682 case mode_nibble:
683 val = PPBUS_NIBBLE;
684 break;
685 case mode_ps2:
686 val = PPBUS_PS2;
687 break;
688 case mode_fast:
689 val = PPBUS_FAST;
690 break;
691 case mode_epp:
692 val = PPBUS_EPP;
693 break;
694 case mode_ecp:
695 val = PPBUS_ECP;
696 break;
697 default:
698 error = EINVAL;
699 val = mode_unknown;
700 break;
701 }
702
703 if (!error)
704 error = ppbus_set_mode(dev->dv_parent, val, 0);
705
706 break;
707
708 case LPTGFLAGS:
709 fl = 0;
710
711 error = ppbus_read_ivar(dev->dv_parent, PPBUS_IVAR_DMA, &val);
712 if (error)
713 break;
714 if (val)
715 fl |= LPT_DMA;
716
717 error = ppbus_read_ivar(dev->dv_parent, PPBUS_IVAR_IEEE, &val);
718 if (error)
719 break;
720 if (val)
721 fl |= LPT_IEEE;
722
723 *(int *)data = fl;
724 break;
725
726 case LPTSFLAGS:
727 fl = *(int *)data;
728
729 val = (fl & LPT_DMA);
730 error = ppbus_write_ivar(dev->dv_parent, PPBUS_IVAR_DMA, &val);
731 if (error)
732 break;
733
734 val = (fl & LPT_IEEE);
735 error = ppbus_write_ivar(dev->dv_parent, PPBUS_IVAR_IEEE, &val);
736 break;
737
738 default:
739 error = EINVAL;
740 break;
741 }
742
743 return error;
744 }
745
746