Sync usage with man page.
[netbsd-mini2440.git] / sys / dev / ppbus / lpt.c
blob3ab4d732d934cc578166defbcd0f8bd9a7e5a776
1 /* $NetBSD: lpt.c,v 1.27 2008/04/16 09:39:01 cegger Exp $ */
3 /*
4 * Copyright (c) 1990 William F. Jolitz, TeleMuse
5 * All rights reserved.
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.
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.
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.
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.
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
57 * Device Driver for AT parallel printer port
58 * Written by William Jolitz 12/18/90
62 * Updated for ppbus by Nicolas Souchu
63 * [Mon Jul 28 1997]
66 #include <sys/cdefs.h>
67 __KERNEL_RCSID(0, "$NetBSD: lpt.c,v 1.27 2008/04/16 09:39:01 cegger Exp $");
69 #include "opt_ppbus_lpt.h"
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>
83 #include <sys/bus.h>
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>
91 #include <dev/ppbus/lptvar.h>
92 #include <dev/ppbus/lptreg.h>
93 #include <dev/ppbus/lptio.h>
95 /* Autoconf functions */
96 static int lpt_probe(device_t, cfdata_t, void *);
97 static void lpt_attach(device_t, device_t, void *);
98 static int lpt_detach(device_t, int);
100 /* Autoconf structure */
101 CFATTACH_DECL_NEW(lpt_ppbus, sizeof(struct lpt_softc), lpt_probe, lpt_attach,
102 lpt_detach, NULL);
104 extern struct cfdriver lpt_cd;
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);
112 const struct cdevsw lpt_cdevsw = {
113 lptopen, lptclose, lptread, lptwrite, lptioctl,
114 nostop, notty, nopoll, nommap, nokqfilter, D_OTHER
118 /* Function prototypes */
119 static int lpt_detect(device_t);
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 device_t, const unsigned char);
125 * lpt_probe()
127 static int
128 lpt_probe(device_t parent, cfdata_t match, void *aux)
130 /* Test ppbus's capability */
131 return lpt_detect(parent);
134 static void
135 lpt_attach(device_t parent, device_t self, void *aux)
137 struct lpt_softc * sc = device_private(self);
138 struct ppbus_device_softc * ppbdev = &(sc->ppbus_dev);
139 struct ppbus_attach_args * args = aux;
140 char buf[64];
141 int error;
143 ppbdev->sc_dev = self;
145 error = lpt_request_ppbus(sc, 0);
146 if(error) {
147 printf("%s(%s): error (%d) requesting bus(%s). Device not "
148 "properly attached.\n", __func__, device_xname(self),
149 error, device_xname(parent));
150 return;
153 /* Record capabilities */
154 ppbdev->capabilities = args->capabilities;
156 /* Allocate memory buffers */
157 if(ppbdev->capabilities & PPBUS_HAS_DMA) {
158 if(ppbus_dma_malloc(parent, &(sc->sc_inbuf),
159 &(sc->sc_in_baddr), BUFSIZE)) {
161 printf(" : cannot allocate input DMA buffer. Device "
162 "not properly attached!\n");
163 return;
165 if(ppbus_dma_malloc(parent, &(sc->sc_outbuf),
166 &(sc->sc_out_baddr), BUFSIZE)) {
168 ppbus_dma_free(parent, &(sc->sc_inbuf),
169 &(sc->sc_in_baddr), BUFSIZE);
170 printf(" : cannot allocate output DMA buffer. Device "
171 "not properly attached!\n");
172 return;
174 } else {
175 sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
176 sc->sc_outbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
179 /* Print out mode */
180 ppbdev->ctx.mode = ppbus_get_mode(parent);
181 snprintb(buf, sizeof(buf),
182 "\20\1COMPATIBLE\2NIBBLE\3PS2\4EPP\5ECP\6FAST_CENTR",
183 ppbdev->ctx.mode);
184 printf(": port mode = %s\n", buf);
186 /* Initialize the device on open by default */
187 sc->sc_flags = LPT_PRIME;
189 lpt_release_ppbus(sc, 0);
192 static int
193 lpt_detach(device_t self, int flags)
195 struct lpt_softc * lpt = device_private(self);
196 struct ppbus_device_softc * ppbdev = (struct ppbus_device_softc *) lpt;
197 int err;
199 if(lpt->sc_state & HAVEBUS) {
200 err = lpt_release_ppbus(lpt, 0);
201 if(err) {
202 printf("%s error (%d) while releasing bus",
203 device_xname(self), err);
204 if(flags & DETACH_FORCE) {
205 printf(", continuing (DETACH_FORCE)!\n");
207 else {
208 printf(", terminating!\n");
209 return 0;
212 lpt->sc_state &= ~HAVEBUS;
215 ppbdev->ctx.valid = 0;
217 /* Free memory buffers */
218 if(ppbdev->capabilities & PPBUS_HAS_DMA) {
219 ppbus_dma_free(device_parent(self), &(lpt->sc_inbuf),
220 &(lpt->sc_in_baddr), BUFSIZE);
221 ppbus_dma_free(device_parent(self), &(lpt->sc_outbuf),
222 &(lpt->sc_out_baddr), BUFSIZE);
223 } else {
224 free(lpt->sc_inbuf, M_DEVBUF);
225 free(lpt->sc_outbuf, M_DEVBUF);
228 return 1;
231 /* Grab bus for lpt device */
232 static int
233 lpt_request_ppbus(struct lpt_softc * lpt, int how)
235 device_t dev = lpt->ppbus_dev.sc_dev;
236 int error;
238 error = ppbus_request_bus(device_parent(dev), dev, how, (hz));
239 if (!(error)) {
240 lpt->sc_state |= HAVEBUS;
242 else {
243 LPT_DPRINTF(("%s(%s): error %d requesting bus.\n", __func__,
244 device_xname(dev), error));
247 return error;
250 /* Release ppbus to enable other devices to use it. */
251 static int
252 lpt_release_ppbus(struct lpt_softc * lpt, int how)
254 device_t dev = lpt->ppbus_dev.sc_dev;
255 int error;
257 if(lpt->sc_state & HAVEBUS) {
258 error = ppbus_release_bus(device_parent(dev), dev, how, (hz));
259 if(!(error))
260 lpt->sc_state &= ~HAVEBUS;
261 else {
262 LPT_DPRINTF(("%s(%s): error releasing bus.\n", __func__,
263 device_xname(dev)));
266 else {
267 error = EINVAL;
268 LPT_DPRINTF(("%s(%s): device does not own bus.\n", __func__,
269 device_xname(dev)));
272 return error;
277 * Probe simplified by replacing multiple loops with a hardcoded
278 * test pattern - 1999/02/08 des@freebsd.org
280 * New lpt port probe Geoff Rehmet - Rhodes University - 14/2/94
281 * Based partially on Rod Grimes' printer probe
283 * Logic:
284 * 1) If no port address was given, use the bios detected ports
285 * and autodetect what ports the printers are on.
286 * 2) Otherwise, probe the data port at the address given,
287 * using the method in Rod Grimes' port probe.
288 * (Much code ripped off directly from Rod's probe.)
290 * Comments from Rod's probe:
291 * Logic:
292 * 1) You should be able to write to and read back the same value
293 * to the data port. Do an alternating zeros, alternating ones,
294 * walking zero, and walking one test to check for stuck bits.
296 * 2) You should be able to write to and read back the same value
297 * to the control port lower 5 bits, the upper 3 bits are reserved
298 * per the IBM PC technical reference manauls and different boards
299 * do different things with them. Do an alternating zeros, alternating
300 * ones, walking zero, and walking one test to check for stuck bits.
302 * Some printers drag the strobe line down when the are powered off
303 * so this bit has been masked out of the control port test.
305 * XXX Some printers may not like a fast pulse on init or strobe, I
306 * don't know at this point, if that becomes a problem these bits
307 * should be turned off in the mask byte for the control port test.
309 * We are finally left with a mask of 0x14, due to some printers
310 * being adamant about holding other bits high ........
312 * Before probing the control port, we write a 0 to the data port -
313 * If not, some printers chuck out garbage when the strobe line
314 * gets toggled.
316 * 3) Set the data and control ports to a value of 0
318 * This probe routine has been tested on Epson Lx-800, HP LJ3P,
319 * Epson FX-1170 and C.Itoh 8510RM
320 * printers.
321 * Quick exit on fail added.
323 static int
324 lpt_detect(device_t dev)
326 static const u_char testbyte[18] = {
327 0x55, /* alternating zeros */
328 0xaa, /* alternating ones */
329 0xfe, 0xfd, 0xfb, 0xf7,
330 0xef, 0xdf, 0xbf, 0x7f, /* walking zero */
331 0x01, 0x02, 0x04, 0x08,
332 0x10, 0x20, 0x40, 0x80 /* walking one */
334 int i, status;
335 u_char dtr, ctr, str, var;
337 /* Save register contents */
338 dtr = ppbus_rdtr(dev);
339 ctr = ppbus_rctr(dev);
340 str = ppbus_rstr(dev);
342 status = 1; /* assume success */
344 /* Test data port */
345 for(i = 0; i < 18; i++) {
346 ppbus_wdtr(dev, testbyte[i]);
347 if((var = ppbus_rdtr(dev)) != testbyte[i]) {
348 status = 0;
349 LPT_DPRINTF(("%s(%s): byte value %x cannot be written "
350 "and read from data port (got %x instead).\n",
351 __func__, device_xname(dev), testbyte[i], var));
352 goto end;
356 /* Test control port */
357 ppbus_wdtr(dev, 0);
358 for(i = 0; i < 18; i++) {
359 ppbus_wctr(dev, (testbyte[i] & 0x14));
360 if(((var = ppbus_rctr(dev)) & 0x14) != (testbyte[i] & 0x14)) {
361 status = 0;
362 LPT_DPRINTF(("%s(%s): byte value %x (unmasked value "
363 "%x) cannot be written and read from control "
364 "port (got %x instead).\n", __func__,
365 device_xname(dev), (testbyte[i] & 0x14),
366 testbyte[i], (var & 0x14)));
367 break;
371 end:
372 /* Restore contents of registers */
373 ppbus_wdtr(dev, dtr);
374 ppbus_wctr(dev, ctr);
375 ppbus_wstr(dev, str);
377 return status;
380 /* Log status of status register for printer port */
381 static int
382 lpt_logstatus(const device_t dev, const unsigned char status)
384 int err;
386 err = EIO;
387 if(!(status & LPS_SEL)) {
388 log(LOG_ERR, "%s: offline.", device_xname(dev));
390 else if(!(status & LPS_NBSY)) {
391 log(LOG_ERR, "%s: busy.", device_xname(dev));
393 else if(status & LPS_OUT) {
394 log(LOG_ERR, "%s: out of paper.", device_xname(dev));
395 err = EAGAIN;
397 else if(!(status & LPS_NERR)) {
398 log(LOG_ERR, "%s: output error.", device_xname(dev));
400 else {
401 log(LOG_ERR, "%s: no error indication.", device_xname(dev));
402 err = 0;
405 return err;
409 * lptopen -- reset the printer, then wait until it's selected and not busy.
412 lptopen(dev_t dev_id, int flags, int fmt, struct lwp *l)
414 int trys, err;
415 u_int8_t status;
416 device_t dev;
417 struct lpt_softc * lpt;
418 struct ppbus_device_softc * ppbus_dev;
419 device_t ppbus;
421 dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
422 if(!dev) {
423 LPT_DPRINTF(("%s(): device not configured.\n", __func__));
424 return ENXIO;
427 lpt = device_private(dev);
429 ppbus = device_parent(dev);
430 ppbus_dev = &(lpt->ppbus_dev);
432 /* Request the ppbus */
433 err = lpt_request_ppbus(lpt, PPBUS_WAIT|PPBUS_INTR);
434 if(err) {
435 LPT_DPRINTF(("%s(%s): error (%d) while requesting bus.\n",
436 __func__, device_xname(dev), err));
437 return (err);
440 /* Update bus mode */
441 ppbus_dev->ctx.mode = ppbus_get_mode(ppbus);
443 /* init printer */
444 if ((lpt->sc_flags & LPT_PRIME) && !LPTCTL(dev_id)) {
445 LPT_VPRINTF(("%s(%s): initializing printer.\n", __func__,
446 device_xname(dev)));
447 lpt->sc_state |= LPTINIT;
448 ppbus_wctr(ppbus, LPC_SEL | LPC_NINIT);
450 /* wait till ready (printer running diagnostics) */
451 for(trys = 0, status = ppbus_rstr(ppbus); (status & RDY_MASK)
452 != LP_READY; trys += LPT_STEP, status =
453 ppbus_rstr(ppbus)) {
455 /* Time up waiting for the printer */
456 if(trys >= LPT_TIMEOUT)
457 break;
458 /* wait LPT_STEP ticks, give up if we get a signal */
459 else {
460 err = tsleep((void *)lpt, LPPRI|PCATCH,
461 "lptinit", LPT_STEP);
462 if((err) && (err != EWOULDBLOCK)) {
463 lpt->sc_state &= ~LPTINIT;
464 LPT_DPRINTF(("%s(%s): interrupted "
465 "during initialization.\n", __func__,
466 device_xname(dev)));
467 lpt_release_ppbus(lpt, PPBUS_WAIT);
468 return (err);
473 lpt->sc_state &= ~LPTINIT;
474 if(trys >= LPT_TIMEOUT) {
475 LPT_DPRINTF(("%s(%s): timed out while initializing "
476 "printer. [status %x]\n", __func__,
477 device_xname(dev), status));
478 err = lpt_logstatus(dev, status);
479 lpt_release_ppbus(lpt, PPBUS_WAIT);
480 return (err);
482 else {
483 LPT_VPRINTF(("%s(%s): printer ready.\n", __func__,
484 device_xname(dev)));
488 /* Set autolinefeed if requested */
489 if (lpt->sc_flags & LPT_AUTOLF)
490 ppbus_wctr(ppbus, LPC_AUTOL);
491 else
492 ppbus_wctr(ppbus, 0);
494 /* ready now */
495 lpt->sc_state |= OPEN;
497 return 0;
501 * lptclose -- close the device, free the local line buffer.
503 * Check for interrupted write call added.
506 lptclose(dev_t dev_id, int flags, int fmt, struct lwp *l)
508 device_t dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
509 struct lpt_softc *sc = device_private(dev);
510 int err;
512 err = lpt_release_ppbus(sc, PPBUS_WAIT|PPBUS_INTR);
513 if(err) {
514 LPT_DPRINTF(("%s(%s): error (%d) while releasing ppbus.\n",
515 __func__, device_xname(dev), err));
518 sc->sc_state = 0;
520 return err;
524 * lptread --retrieve printer status in IEEE1284 NIBBLE mode
527 lptread(dev_t dev_id, struct uio *uio, int ioflag)
529 size_t len = 0;
530 int error = 0;
531 device_t dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
532 struct lpt_softc *sc = device_private(dev);
534 if(!(sc->sc_state & HAVEBUS)) {
535 LPT_DPRINTF(("%s(%s): attempt to read using device which does "
536 "not own the bus(%s).\n", __func__, device_xname(dev),
537 device_xname(device_parent(dev))));
538 return (ENODEV);
541 sc->sc_state &= ~INTERRUPTED;
542 while (uio->uio_resid) {
543 error = ppbus_read(device_parent(dev), sc->sc_outbuf,
544 min(BUFSIZE, uio->uio_resid), 0, &len);
546 /* If error or no more data, stop */
547 if (error) {
548 if (error != EWOULDBLOCK)
549 sc->sc_state |= INTERRUPTED;
550 break;
552 if (len == 0)
553 break;
555 if ((error = uiomove(sc->sc_outbuf, len, uio)))
556 break;
559 return error;
563 * lptwrite --copy a line from user space to a local buffer, then call
564 * putc to get the chars moved to the output queue.
566 * Flagging of interrupted write added.
569 lptwrite(dev_t dev_id, struct uio * uio, int ioflag)
571 int error=0;
572 size_t n, cnt;
573 device_t dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
574 struct lpt_softc * sc = device_private(dev);
576 /* Check state and flags */
577 if(!(sc->sc_state & HAVEBUS)) {
578 LPT_DPRINTF(("%s(%s): attempt to write using device which does "
579 "not own the bus(%s).\n", __func__, device_xname(dev),
580 device_xname(device_parent(dev))));
581 return EINVAL;
584 LPT_VPRINTF(("%s(%s): writing %zu bytes\n", __func__,
585 device_xname(dev), uio->uio_resid));
587 /* Write the data */
588 sc->sc_state &= ~INTERRUPTED;
589 while (uio->uio_resid) {
590 n = MIN(BUFSIZE, uio->uio_resid);
591 error = uiomove(sc->sc_inbuf, n, uio);
592 if (error)
593 break;
595 error = ppbus_write(device_parent(dev), sc->sc_inbuf, n, ioflag,
596 &cnt);
597 if (error) {
598 if (error != EWOULDBLOCK)
599 sc->sc_state |= INTERRUPTED;
600 break;
604 LPT_VPRINTF(("%s(%s): transfer finished, error %d.\n", __func__,
605 device_xname(dev), error));
607 return error;
610 /* Printer ioctl */
612 lptioctl(dev_t dev_id, u_long cmd, void *data, int flags, struct lwp *l)
614 device_t dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
615 struct lpt_softc *sc = device_private(dev);
616 int val, fl;
617 int error=0;
619 if(!(sc->sc_state & HAVEBUS)) {
620 LPT_DPRINTF(("%s(%s): attempt to perform ioctl on device which "
621 "does not own the bus(%s).\n", __func__, device_xname(dev),
622 device_xname(device_parent(dev))));
623 return EBUSY;
626 switch (cmd) {
627 case LPTGMODE:
628 switch (ppbus_get_mode(device_parent(dev))) {
629 case PPBUS_COMPATIBLE:
630 val = mode_standard;
631 break;
632 case PPBUS_NIBBLE:
633 val = mode_nibble;
634 break;
635 case PPBUS_PS2:
636 val = mode_ps2;
637 break;
638 case PPBUS_FAST:
639 val = mode_fast;
640 break;
641 case PPBUS_EPP:
642 val = mode_epp;
643 break;
644 case PPBUS_ECP:
645 val = mode_ecp;
646 break;
647 default:
648 error = EINVAL;
649 val = mode_unknown;
650 break;
652 *(int *)data = val;
653 break;
655 case LPTSMODE:
656 switch (*(int *)data) {
657 case mode_standard:
658 val = PPBUS_COMPATIBLE;
659 break;
660 case mode_nibble:
661 val = PPBUS_NIBBLE;
662 break;
663 case mode_ps2:
664 val = PPBUS_PS2;
665 break;
666 case mode_fast:
667 val = PPBUS_FAST;
668 break;
669 case mode_epp:
670 val = PPBUS_EPP;
671 break;
672 case mode_ecp:
673 val = PPBUS_ECP;
674 break;
675 default:
676 error = EINVAL;
677 val = mode_unknown;
678 break;
681 if (!error)
682 error = ppbus_set_mode(device_parent(dev), val, 0);
684 break;
686 case LPTGFLAGS:
687 fl = 0;
689 /* DMA */
690 error = ppbus_read_ivar(device_parent(dev), PPBUS_IVAR_DMA, &val);
691 if (error)
692 break;
693 if (val)
694 fl |= LPT_DMA;
696 /* IEEE mode negotiation */
697 error = ppbus_read_ivar(device_parent(dev), PPBUS_IVAR_IEEE, &val);
698 if (error)
699 break;
700 if (val)
701 fl |= LPT_IEEE;
703 /* interrupts */
704 error = ppbus_read_ivar(device_parent(dev), PPBUS_IVAR_INTR, &val);
705 if (error)
706 break;
707 if (val)
708 fl |= LPT_INTR;
710 /* lpt-only flags */
711 fl |= sc->sc_flags;
713 *(int *)data = fl;
714 break;
716 case LPTSFLAGS:
717 fl = *(int *)data;
719 /* DMA */
720 val = (fl & LPT_DMA);
721 error = ppbus_write_ivar(device_parent(dev), PPBUS_IVAR_DMA, &val);
722 if (error)
723 break;
725 /* IEEE mode negotiation */
726 val = (fl & LPT_IEEE);
727 error = ppbus_write_ivar(device_parent(dev), PPBUS_IVAR_IEEE, &val);
728 if (error)
729 break;
731 /* interrupts */
732 val = (fl & LPT_INTR);
733 error = ppbus_write_ivar(device_parent(dev), PPBUS_IVAR_INTR, &val);
734 if (error)
735 break;
737 /* lpt-only flags */
738 sc->sc_flags = fl & (LPT_PRIME|LPT_AUTOLF);
740 break;
742 default:
743 error = EINVAL;
744 break;
747 return error;