lpt.c revision 1.20.16.2 1 /* $NetBSD: lpt.c,v 1.20.16.2 2008/04/05 23:33:22 mjf 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.20.16.2 2008/04/05 23:33:22 mjf 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 <sys/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(device_t, struct cfdata *, void *);
97 static void lpt_attach(device_t, device_t, void *);
98 static int lpt_detach(device_t, 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, D_OTHER
115 };
116
117
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);
123
124 /*
125 * lpt_probe()
126 */
127 static int
128 lpt_probe(device_t 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(device_t parent, device_t self, void *aux)
136 {
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;
142 int maj;
143
144 error = lpt_request_ppbus(sc, 0);
145 if(error) {
146 printf("%s(%s): error (%d) requesting bus(%s). Device not "
147 "properly attached.\n", __func__, self->dv_xname,
148 error, parent->dv_xname);
149 return;
150 }
151
152 /* Record capabilities */
153 ppbdev->capabilities = args->capabilities;
154
155 /* Allocate memory buffers */
156 if(ppbdev->capabilities & PPBUS_HAS_DMA) {
157 if(ppbus_dma_malloc(parent, &(sc->sc_inbuf),
158 &(sc->sc_in_baddr), BUFSIZE)) {
159
160 printf(" : cannot allocate input DMA buffer. Device "
161 "not properly attached!\n");
162 return;
163 }
164 if(ppbus_dma_malloc(parent, &(sc->sc_outbuf),
165 &(sc->sc_out_baddr), BUFSIZE)) {
166
167 ppbus_dma_free(parent, &(sc->sc_inbuf),
168 &(sc->sc_in_baddr), BUFSIZE);
169 printf(" : cannot allocate output DMA buffer. Device "
170 "not properly attached!\n");
171 return;
172 }
173 } else {
174 sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
175 sc->sc_outbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
176 }
177
178 /* Print out mode */
179 ppbdev->ctx.mode = ppbus_get_mode(parent);
180 bitmask_snprintf(ppbdev->ctx.mode, "\20\1COMPATIBLE\2NIBBLE"
181 "\3PS2\4EPP\5ECP\6FAST_CENTR", buf, sizeof(buf));
182 printf(": port mode = %s\n", buf);
183
184 /* Initialize the device on open by default */
185 sc->sc_flags = LPT_PRIME;
186
187 lpt_release_ppbus(sc, 0);
188
189 maj = cdevsw_lookup_major(&lpt_cdevsw);
190 device_register_name(makedev(maj, device_unit(self)), self, true,
191 DEV_OTHER, device_xname(self));
192 }
193
194 static int
195 lpt_detach(device_t self, int flags)
196 {
197 struct lpt_softc * lpt = device_private(self);
198 struct ppbus_device_softc * ppbdev = (struct ppbus_device_softc *) lpt;
199 int err;
200
201 if(lpt->sc_state & HAVEBUS) {
202 err = lpt_release_ppbus(lpt, 0);
203 if(err) {
204 printf("%s error (%d) while releasing bus",
205 self->dv_xname, err);
206 if(flags & DETACH_FORCE) {
207 printf(", continuing (DETACH_FORCE)!\n");
208 }
209 else {
210 printf(", terminating!\n");
211 return 0;
212 }
213 }
214 lpt->sc_state &= ~HAVEBUS;
215 }
216
217 ppbdev->ctx.valid = 0;
218
219 /* Free memory buffers */
220 if(ppbdev->capabilities & PPBUS_HAS_DMA) {
221 ppbus_dma_free(device_parent(self), &(lpt->sc_inbuf),
222 &(lpt->sc_in_baddr), BUFSIZE);
223 ppbus_dma_free(device_parent(self), &(lpt->sc_outbuf),
224 &(lpt->sc_out_baddr), BUFSIZE);
225 } else {
226 free(lpt->sc_inbuf, M_DEVBUF);
227 free(lpt->sc_outbuf, M_DEVBUF);
228 }
229
230 return 1;
231 }
232
233 /* Grab bus for lpt device */
234 static int
235 lpt_request_ppbus(struct lpt_softc * lpt, int how)
236 {
237 device_t dev = &lpt->ppbus_dev.sc_dev;
238 int error;
239
240 error = ppbus_request_bus(device_parent(dev), dev, how, (hz));
241 if (!(error)) {
242 lpt->sc_state |= HAVEBUS;
243 }
244 else {
245 LPT_DPRINTF(("%s(%s): error %d requesting bus.\n", __func__,
246 dev->dv_xname, error));
247 }
248
249 return error;
250 }
251
252 /* Release ppbus to enable other devices to use it. */
253 static int
254 lpt_release_ppbus(struct lpt_softc * lpt, int how)
255 {
256 device_t dev = &lpt->ppbus_dev.sc_dev;
257 int error;
258
259 if(lpt->sc_state & HAVEBUS) {
260 error = ppbus_release_bus(device_parent(dev), dev, how, (hz));
261 if(!(error))
262 lpt->sc_state &= ~HAVEBUS;
263 else
264 LPT_DPRINTF(("%s(%s): error releasing bus.\n", __func__,
265 dev->dv_xname));
266 }
267 else {
268 error = EINVAL;
269 LPT_DPRINTF(("%s(%s): device does not own bus.\n", __func__,
270 dev->dv_xname));
271 }
272
273 return error;
274 }
275
276
277 /*
278 * Probe simplified by replacing multiple loops with a hardcoded
279 * test pattern - 1999/02/08 des (at) freebsd.org
280 *
281 * New lpt port probe Geoff Rehmet - Rhodes University - 14/2/94
282 * Based partially on Rod Grimes' printer probe
283 *
284 * Logic:
285 * 1) If no port address was given, use the bios detected ports
286 * and autodetect what ports the printers are on.
287 * 2) Otherwise, probe the data port at the address given,
288 * using the method in Rod Grimes' port probe.
289 * (Much code ripped off directly from Rod's probe.)
290 *
291 * Comments from Rod's probe:
292 * Logic:
293 * 1) You should be able to write to and read back the same value
294 * to the data port. Do an alternating zeros, alternating ones,
295 * walking zero, and walking one test to check for stuck bits.
296 *
297 * 2) You should be able to write to and read back the same value
298 * to the control port lower 5 bits, the upper 3 bits are reserved
299 * per the IBM PC technical reference manauls and different boards
300 * do different things with them. Do an alternating zeros, alternating
301 * ones, walking zero, and walking one test to check for stuck bits.
302 *
303 * Some printers drag the strobe line down when the are powered off
304 * so this bit has been masked out of the control port test.
305 *
306 * XXX Some printers may not like a fast pulse on init or strobe, I
307 * don't know at this point, if that becomes a problem these bits
308 * should be turned off in the mask byte for the control port test.
309 *
310 * We are finally left with a mask of 0x14, due to some printers
311 * being adamant about holding other bits high ........
312 *
313 * Before probing the control port, we write a 0 to the data port -
314 * If not, some printers chuck out garbage when the strobe line
315 * gets toggled.
316 *
317 * 3) Set the data and control ports to a value of 0
318 *
319 * This probe routine has been tested on Epson Lx-800, HP LJ3P,
320 * Epson FX-1170 and C.Itoh 8510RM
321 * printers.
322 * Quick exit on fail added.
323 */
324 static int
325 lpt_detect(device_t dev)
326 {
327 static const u_char testbyte[18] = {
328 0x55, /* alternating zeros */
329 0xaa, /* alternating ones */
330 0xfe, 0xfd, 0xfb, 0xf7,
331 0xef, 0xdf, 0xbf, 0x7f, /* walking zero */
332 0x01, 0x02, 0x04, 0x08,
333 0x10, 0x20, 0x40, 0x80 /* walking one */
334 };
335 int i, status;
336 u_char dtr, ctr, str, var;
337
338 /* Save register contents */
339 dtr = ppbus_rdtr(dev);
340 ctr = ppbus_rctr(dev);
341 str = ppbus_rstr(dev);
342
343 status = 1; /* assume success */
344
345 /* Test data port */
346 for(i = 0; i < 18; i++) {
347 ppbus_wdtr(dev, testbyte[i]);
348 if((var = ppbus_rdtr(dev)) != testbyte[i]) {
349 status = 0;
350 LPT_DPRINTF(("%s(%s): byte value %x cannot be written "
351 "and read from data port (got %x instead).\n",
352 __func__, dev->dv_xname, testbyte[i], var));
353 goto end;
354 }
355 }
356
357 /* Test control port */
358 ppbus_wdtr(dev, 0);
359 for(i = 0; i < 18; i++) {
360 ppbus_wctr(dev, (testbyte[i] & 0x14));
361 if(((var = ppbus_rctr(dev)) & 0x14) != (testbyte[i] & 0x14)) {
362 status = 0;
363 LPT_DPRINTF(("%s(%s): byte value %x (unmasked value "
364 "%x) cannot be written and read from control "
365 "port (got %x instead).\n", __func__,
366 dev->dv_xname, (testbyte[i] & 0x14),
367 testbyte[i], (var & 0x14)));
368 break;
369 }
370 }
371
372 end:
373 /* Restore contents of registers */
374 ppbus_wdtr(dev, dtr);
375 ppbus_wctr(dev, ctr);
376 ppbus_wstr(dev, str);
377
378 return status;
379 }
380
381 /* Log status of status register for printer port */
382 static int
383 lpt_logstatus(const device_t dev, const unsigned char status)
384 {
385 int err;
386
387 err = EIO;
388 if(!(status & LPS_SEL)) {
389 log(LOG_ERR, "%s: offline.", dev->dv_xname);
390 }
391 else if(!(status & LPS_NBSY)) {
392 log(LOG_ERR, "%s: busy.", dev->dv_xname);
393 }
394 else if(status & LPS_OUT) {
395 log(LOG_ERR, "%s: out of paper.", dev->dv_xname);
396 err = EAGAIN;
397 }
398 else if(!(status & LPS_NERR)) {
399 log(LOG_ERR, "%s: output error.", dev->dv_xname);
400 }
401 else {
402 log(LOG_ERR, "%s: no error indication.", dev->dv_xname);
403 err = 0;
404 }
405
406 return err;
407 }
408
409 /*
410 * lptopen -- reset the printer, then wait until it's selected and not busy.
411 */
412 int
413 lptopen(dev_t dev_id, int flags, int fmt, struct lwp *l)
414 {
415 int trys, err;
416 u_int8_t status;
417 device_t dev;
418 struct lpt_softc * lpt;
419 struct ppbus_device_softc * ppbus_dev;
420 device_t ppbus;
421
422 dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
423 if(!dev) {
424 LPT_DPRINTF(("%s(): device not configured.\n", __func__));
425 return ENXIO;
426 }
427
428 lpt = (struct lpt_softc *) dev;
429
430 ppbus = device_parent(dev);
431 ppbus_dev = &(lpt->ppbus_dev);
432
433 /* Request the ppbus */
434 err = lpt_request_ppbus(lpt, PPBUS_WAIT|PPBUS_INTR);
435 if(err) {
436 LPT_DPRINTF(("%s(%s): error (%d) while requesting bus.\n",
437 __func__, dev->dv_xname, err));
438 return (err);
439 }
440
441 /* Update bus mode */
442 ppbus_dev->ctx.mode = ppbus_get_mode(ppbus);
443
444 /* init printer */
445 if ((lpt->sc_flags & LPT_PRIME) && !LPTCTL(dev_id)) {
446 LPT_VPRINTF(("%s(%s): initializing printer.\n", __func__,
447 dev->dv_xname));
448 lpt->sc_state |= LPTINIT;
449 ppbus_wctr(ppbus, LPC_SEL | LPC_NINIT);
450
451 /* wait till ready (printer running diagnostics) */
452 for(trys = 0, status = ppbus_rstr(ppbus); (status & RDY_MASK)
453 != LP_READY; trys += LPT_STEP, status =
454 ppbus_rstr(ppbus)) {
455
456 /* Time up waiting for the printer */
457 if(trys >= LPT_TIMEOUT)
458 break;
459 /* wait LPT_STEP ticks, give up if we get a signal */
460 else {
461 err = tsleep((void *)lpt, LPPRI|PCATCH,
462 "lptinit", LPT_STEP);
463 if((err) && (err != EWOULDBLOCK)) {
464 lpt->sc_state &= ~LPTINIT;
465 LPT_DPRINTF(("%s(%s): interrupted "
466 "during initialization.\n", __func__,
467 dev->dv_xname));
468 lpt_release_ppbus(lpt, PPBUS_WAIT);
469 return (err);
470 }
471 }
472 }
473
474 lpt->sc_state &= ~LPTINIT;
475 if(trys >= LPT_TIMEOUT) {
476 LPT_DPRINTF(("%s(%s): timed out while initializing "
477 "printer. [status %x]\n", __func__,
478 dev->dv_xname, status));
479 err = lpt_logstatus(dev, status);
480 lpt_release_ppbus(lpt, PPBUS_WAIT);
481 return (err);
482 }
483 else
484 LPT_VPRINTF(("%s(%s): printer ready.\n", __func__,
485 dev->dv_xname));
486 }
487
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);
493
494 /* ready now */
495 lpt->sc_state |= OPEN;
496
497 return 0;
498 }
499
500 /*
501 * lptclose -- close the device, free the local line buffer.
502 *
503 * Check for interrupted write call added.
504 */
505 int
506 lptclose(dev_t dev_id, int flags, int fmt, struct lwp *l)
507 {
508 device_t dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
509 struct lpt_softc *sc = device_private(dev);
510 int err;
511
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__, dev->dv_xname, err));
516 }
517
518 sc->sc_state = 0;
519
520 return err;
521 }
522
523 /*
524 * lptread --retrieve printer status in IEEE1284 NIBBLE mode
525 */
526 int
527 lptread(dev_t dev_id, struct uio *uio, int ioflag)
528 {
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);
533
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__, dev->dv_xname,
537 device_parent(dev)->dv_xname));
538 return (ENODEV);
539 }
540
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);
545
546 /* If error or no more data, stop */
547 if (error) {
548 if (error != EWOULDBLOCK)
549 sc->sc_state |= INTERRUPTED;
550 break;
551 }
552 if (len == 0)
553 break;
554
555 if ((error = uiomove(sc->sc_outbuf, len, uio)))
556 break;
557 }
558
559 return error;
560 }
561
562 /*
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.
565 *
566 * Flagging of interrupted write added.
567 */
568 int
569 lptwrite(dev_t dev_id, struct uio * uio, int ioflag)
570 {
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);
575
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__, dev->dv_xname,
580 device_parent(dev)->dv_xname));
581 return EINVAL;
582 }
583
584 LPT_VPRINTF(("%s(%s): writing %d bytes\n", __func__,
585 dev->dv_xname, uio->uio_resid));
586
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;
594
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;
601 }
602 }
603
604 LPT_VPRINTF(("%s(%s): transfer finished, error %d.\n", __func__,
605 dev->dv_xname, error));
606
607 return error;
608 }
609
610 /* Printer ioctl */
611 int
612 lptioctl(dev_t dev_id, u_long cmd, void *data, int flags, struct lwp *l)
613 {
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;
618
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__, dev->dv_xname,
622 device_parent(dev)->dv_xname));
623 return EBUSY;
624 }
625
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;
651 }
652 *(int *)data = val;
653 break;
654
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;
679 }
680
681 if (!error)
682 error = ppbus_set_mode(device_parent(dev), val, 0);
683
684 break;
685
686 case LPTGFLAGS:
687 fl = 0;
688
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;
695
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;
702
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;
709
710 /* lpt-only flags */
711 fl |= sc->sc_flags;
712
713 *(int *)data = fl;
714 break;
715
716 case LPTSFLAGS:
717 fl = *(int *)data;
718
719 /* DMA */
720 val = (fl & LPT_DMA);
721 error = ppbus_write_ivar(device_parent(dev), PPBUS_IVAR_DMA, &val);
722 if (error)
723 break;
724
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;
730
731 /* interrupts */
732 val = (fl & LPT_INTR);
733 error = ppbus_write_ivar(device_parent(dev), PPBUS_IVAR_INTR, &val);
734 if (error)
735 break;
736
737 /* lpt-only flags */
738 sc->sc_flags = fl & (LPT_PRIME|LPT_AUTOLF);
739
740 break;
741
742 default:
743 error = EINVAL;
744 break;
745 }
746
747 return error;
748 }
749
750