1 /* $NetBSD: lpt.c,v 1.32 2019/12/27 09:28:41 msaitoh 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.32 2019/12/27 09:28:41 msaitoh 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, cfdata_t, 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_NEW(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 .d_open = lptopen,
114 .d_close = lptclose,
115 .d_read = lptread,
116 .d_write = lptwrite,
117 .d_ioctl = lptioctl,
118 .d_stop = nostop,
119 .d_tty = notty,
120 .d_poll = nopoll,
121 .d_mmap = nommap,
122 .d_kqfilter = nokqfilter,
123 .d_discard = nodiscard,
124 .d_flag = D_OTHER
125 };
126
127
128 /* Function prototypes */
129 static int lpt_detect(device_t);
130 static int lpt_request_ppbus(struct lpt_softc *, int);
131 static int lpt_release_ppbus(struct lpt_softc *, int);
132 static int lpt_logstatus(const device_t, const unsigned char);
133
134 /*
135 * lpt_probe()
136 */
137 static int
lpt_probe(device_t parent,cfdata_t match,void * aux)138 lpt_probe(device_t parent, cfdata_t match, void *aux)
139 {
140 /* Test ppbus's capability */
141 return lpt_detect(parent);
142 }
143
144 static void
lpt_attach(device_t parent,device_t self,void * aux)145 lpt_attach(device_t parent, device_t self, void *aux)
146 {
147 struct lpt_softc * sc = device_private(self);
148 struct ppbus_device_softc * ppbdev = &(sc->ppbus_dev);
149 struct ppbus_attach_args * args = aux;
150 char buf[64];
151 int error;
152
153 ppbdev->sc_dev = self;
154
155 error = lpt_request_ppbus(sc, 0);
156 if(error) {
157 printf("%s(%s): error (%d) requesting bus(%s). Device not "
158 "properly attached.\n", __func__, device_xname(self),
159 error, device_xname(parent));
160 return;
161 }
162
163 /* Record capabilities */
164 ppbdev->capabilities = args->capabilities;
165
166 /* Allocate memory buffers */
167 if(ppbdev->capabilities & PPBUS_HAS_DMA) {
168 if(ppbus_dma_malloc(parent, &(sc->sc_inbuf),
169 &(sc->sc_in_baddr), BUFSIZE)) {
170
171 printf(" : cannot allocate input DMA buffer. Device "
172 "not properly attached!\n");
173 return;
174 }
175 if(ppbus_dma_malloc(parent, &(sc->sc_outbuf),
176 &(sc->sc_out_baddr), BUFSIZE)) {
177
178 ppbus_dma_free(parent, &(sc->sc_inbuf),
179 &(sc->sc_in_baddr), BUFSIZE);
180 printf(" : cannot allocate output DMA buffer. Device "
181 "not properly attached!\n");
182 return;
183 }
184 } else {
185 sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
186 sc->sc_outbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
187 }
188
189 /* Print out mode */
190 ppbdev->ctx.mode = ppbus_get_mode(parent);
191 snprintb(buf, sizeof(buf),
192 "\20\1COMPATIBLE\2NIBBLE\3PS2\4EPP\5ECP\6FAST_CENTR",
193 ppbdev->ctx.mode);
194 printf(": port mode = %s\n", buf);
195
196 /* Initialize the device on open by default */
197 sc->sc_flags = LPT_PRIME;
198
199 lpt_release_ppbus(sc, 0);
200 }
201
202 static int
lpt_detach(device_t self,int flags)203 lpt_detach(device_t self, int flags)
204 {
205 struct lpt_softc * lpt = device_private(self);
206 struct ppbus_device_softc * ppbdev = (struct ppbus_device_softc *) lpt;
207 int err;
208
209 if(lpt->sc_state & HAVEBUS) {
210 err = lpt_release_ppbus(lpt, 0);
211 if(err) {
212 printf("%s error (%d) while releasing bus",
213 device_xname(self), err);
214 if(flags & DETACH_FORCE) {
215 printf(", continuing (DETACH_FORCE)!\n");
216 }
217 else {
218 printf(", terminating!\n");
219 return 0;
220 }
221 }
222 lpt->sc_state &= ~HAVEBUS;
223 }
224
225 ppbdev->ctx.valid = 0;
226
227 /* Free memory buffers */
228 if(ppbdev->capabilities & PPBUS_HAS_DMA) {
229 ppbus_dma_free(device_parent(self), &(lpt->sc_inbuf),
230 &(lpt->sc_in_baddr), BUFSIZE);
231 ppbus_dma_free(device_parent(self), &(lpt->sc_outbuf),
232 &(lpt->sc_out_baddr), BUFSIZE);
233 } else {
234 free(lpt->sc_inbuf, M_DEVBUF);
235 free(lpt->sc_outbuf, M_DEVBUF);
236 }
237
238 return 1;
239 }
240
241 /* Grab bus for lpt device */
242 static int
lpt_request_ppbus(struct lpt_softc * lpt,int how)243 lpt_request_ppbus(struct lpt_softc * lpt, int how)
244 {
245 device_t dev = lpt->ppbus_dev.sc_dev;
246 int error;
247
248 error = ppbus_request_bus(device_parent(dev), dev, how, (hz));
249 if (!(error)) {
250 lpt->sc_state |= HAVEBUS;
251 }
252 else {
253 LPT_DPRINTF(("%s(%s): error %d requesting bus.\n", __func__,
254 device_xname(dev), error));
255 }
256
257 return error;
258 }
259
260 /* Release ppbus to enable other devices to use it. */
261 static int
lpt_release_ppbus(struct lpt_softc * lpt,int how)262 lpt_release_ppbus(struct lpt_softc * lpt, int how)
263 {
264 device_t dev = lpt->ppbus_dev.sc_dev;
265 int error;
266
267 if(lpt->sc_state & HAVEBUS) {
268 error = ppbus_release_bus(device_parent(dev), dev, how, (hz));
269 if(!(error))
270 lpt->sc_state &= ~HAVEBUS;
271 else {
272 LPT_DPRINTF(("%s(%s): error releasing bus.\n", __func__,
273 device_xname(dev)));
274 }
275 }
276 else {
277 error = EINVAL;
278 LPT_DPRINTF(("%s(%s): device does not own bus.\n", __func__,
279 device_xname(dev)));
280 }
281
282 return error;
283 }
284
285
286 /*
287 * Probe simplified by replacing multiple loops with a hardcoded
288 * test pattern - 1999/02/08 des@freebsd.org
289 *
290 * New lpt port probe Geoff Rehmet - Rhodes University - 14/2/94
291 * Based partially on Rod Grimes' printer probe
292 *
293 * Logic:
294 * 1) If no port address was given, use the bios detected ports
295 * and autodetect what ports the printers are on.
296 * 2) Otherwise, probe the data port at the address given,
297 * using the method in Rod Grimes' port probe.
298 * (Much code ripped off directly from Rod's probe.)
299 *
300 * Comments from Rod's probe:
301 * Logic:
302 * 1) You should be able to write to and read back the same value
303 * to the data port. Do an alternating zeros, alternating ones,
304 * walking zero, and walking one test to check for stuck bits.
305 *
306 * 2) You should be able to write to and read back the same value
307 * to the control port lower 5 bits, the upper 3 bits are reserved
308 * per the IBM PC technical reference manuals and different boards
309 * do different things with them. Do an alternating zeros, alternating
310 * ones, walking zero, and walking one test to check for stuck bits.
311 *
312 * Some printers drag the strobe line down when the are powered off
313 * so this bit has been masked out of the control port test.
314 *
315 * XXX Some printers may not like a fast pulse on init or strobe, I
316 * don't know at this point, if that becomes a problem these bits
317 * should be turned off in the mask byte for the control port test.
318 *
319 * We are finally left with a mask of 0x14, due to some printers
320 * being adamant about holding other bits high ........
321 *
322 * Before probing the control port, we write a 0 to the data port -
323 * If not, some printers chuck out garbage when the strobe line
324 * gets toggled.
325 *
326 * 3) Set the data and control ports to a value of 0
327 *
328 * This probe routine has been tested on Epson Lx-800, HP LJ3P,
329 * Epson FX-1170 and C.Itoh 8510RM
330 * printers.
331 * Quick exit on fail added.
332 */
333 static int
lpt_detect(device_t dev)334 lpt_detect(device_t dev)
335 {
336 static const u_char testbyte[18] = {
337 0x55, /* alternating zeros */
338 0xaa, /* alternating ones */
339 0xfe, 0xfd, 0xfb, 0xf7,
340 0xef, 0xdf, 0xbf, 0x7f, /* walking zero */
341 0x01, 0x02, 0x04, 0x08,
342 0x10, 0x20, 0x40, 0x80 /* walking one */
343 };
344 int i, status;
345 u_char dtr, ctr, str, var;
346
347 /* Save register contents */
348 dtr = ppbus_rdtr(dev);
349 ctr = ppbus_rctr(dev);
350 str = ppbus_rstr(dev);
351
352 status = 1; /* assume success */
353
354 /* Test data port */
355 for(i = 0; i < 18; i++) {
356 ppbus_wdtr(dev, testbyte[i]);
357 if((var = ppbus_rdtr(dev)) != testbyte[i]) {
358 status = 0;
359 LPT_DPRINTF(("%s(%s): byte value %x cannot be written "
360 "and read from data port (got %x instead).\n",
361 __func__, device_xname(dev), testbyte[i], var));
362 goto end;
363 }
364 }
365
366 /* Test control port */
367 ppbus_wdtr(dev, 0);
368 for(i = 0; i < 18; i++) {
369 ppbus_wctr(dev, (testbyte[i] & 0x14));
370 if(((var = ppbus_rctr(dev)) & 0x14) != (testbyte[i] & 0x14)) {
371 status = 0;
372 LPT_DPRINTF(("%s(%s): byte value %x (unmasked value "
373 "%x) cannot be written and read from control "
374 "port (got %x instead).\n", __func__,
375 device_xname(dev), (testbyte[i] & 0x14),
376 testbyte[i], (var & 0x14)));
377 break;
378 }
379 }
380
381 end:
382 /* Restore contents of registers */
383 ppbus_wdtr(dev, dtr);
384 ppbus_wctr(dev, ctr);
385 ppbus_wstr(dev, str);
386
387 return status;
388 }
389
390 /* Log status of status register for printer port */
391 static int
lpt_logstatus(const device_t dev,const unsigned char status)392 lpt_logstatus(const device_t dev, const unsigned char status)
393 {
394 int err;
395
396 err = EIO;
397 if(!(status & LPS_SEL)) {
398 log(LOG_ERR, "%s: offline.", device_xname(dev));
399 }
400 else if(!(status & LPS_NBSY)) {
401 log(LOG_ERR, "%s: busy.", device_xname(dev));
402 }
403 else if(status & LPS_OUT) {
404 log(LOG_ERR, "%s: out of paper.", device_xname(dev));
405 err = EAGAIN;
406 }
407 else if(!(status & LPS_NERR)) {
408 log(LOG_ERR, "%s: output error.", device_xname(dev));
409 }
410 else {
411 log(LOG_ERR, "%s: no error indication.", device_xname(dev));
412 err = 0;
413 }
414
415 return err;
416 }
417
418 /*
419 * lptopen -- reset the printer, then wait until it's selected and not busy.
420 */
421 int
lptopen(dev_t dev_id,int flags,int fmt,struct lwp * l)422 lptopen(dev_t dev_id, int flags, int fmt, struct lwp *l)
423 {
424 int trys, err;
425 u_int8_t status;
426 device_t dev;
427 struct lpt_softc * lpt;
428 struct ppbus_device_softc * ppbus_dev;
429 device_t ppbus;
430
431 dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
432 if(!dev) {
433 LPT_DPRINTF(("%s(): device not configured.\n", __func__));
434 return ENXIO;
435 }
436
437 lpt = device_private(dev);
438
439 ppbus = device_parent(dev);
440 ppbus_dev = &(lpt->ppbus_dev);
441
442 /* Request the ppbus */
443 err = lpt_request_ppbus(lpt, PPBUS_WAIT|PPBUS_INTR);
444 if(err) {
445 LPT_DPRINTF(("%s(%s): error (%d) while requesting bus.\n",
446 __func__, device_xname(dev), err));
447 return (err);
448 }
449
450 /* Update bus mode */
451 ppbus_dev->ctx.mode = ppbus_get_mode(ppbus);
452
453 /* init printer */
454 if ((lpt->sc_flags & LPT_PRIME) && !LPTCTL(dev_id)) {
455 LPT_VPRINTF(("%s(%s): initializing printer.\n", __func__,
456 device_xname(dev)));
457 lpt->sc_state |= LPTINIT;
458 ppbus_wctr(ppbus, LPC_SEL | LPC_NINIT);
459
460 /* wait till ready (printer running diagnostics) */
461 for(trys = 0, status = ppbus_rstr(ppbus); (status & RDY_MASK)
462 != LP_READY; trys += LPT_STEP, status =
463 ppbus_rstr(ppbus)) {
464
465 /* Time up waiting for the printer */
466 if(trys >= LPT_TIMEOUT)
467 break;
468 /* wait LPT_STEP ticks, give up if we get a signal */
469 else {
470 err = tsleep((void *)lpt, LPPRI|PCATCH,
471 "lptinit", LPT_STEP);
472 if((err) && (err != EWOULDBLOCK)) {
473 lpt->sc_state &= ~LPTINIT;
474 LPT_DPRINTF(("%s(%s): interrupted "
475 "during initialization.\n", __func__,
476 device_xname(dev)));
477 lpt_release_ppbus(lpt, PPBUS_WAIT);
478 return (err);
479 }
480 }
481 }
482
483 lpt->sc_state &= ~LPTINIT;
484 if(trys >= LPT_TIMEOUT) {
485 LPT_DPRINTF(("%s(%s): timed out while initializing "
486 "printer. [status %x]\n", __func__,
487 device_xname(dev), status));
488 err = lpt_logstatus(dev, status);
489 lpt_release_ppbus(lpt, PPBUS_WAIT);
490 return (err);
491 }
492 else {
493 LPT_VPRINTF(("%s(%s): printer ready.\n", __func__,
494 device_xname(dev)));
495 }
496 }
497
498 /* Set autolinefeed if requested */
499 if (lpt->sc_flags & LPT_AUTOLF)
500 ppbus_wctr(ppbus, LPC_AUTOL);
501 else
502 ppbus_wctr(ppbus, 0);
503
504 /* ready now */
505 lpt->sc_state |= OPEN;
506
507 return 0;
508 }
509
510 /*
511 * lptclose -- close the device, free the local line buffer.
512 *
513 * Check for interrupted write call added.
514 */
515 int
lptclose(dev_t dev_id,int flags,int fmt,struct lwp * l)516 lptclose(dev_t dev_id, int flags, int fmt, struct lwp *l)
517 {
518 device_t dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
519 struct lpt_softc *sc = device_private(dev);
520 int err;
521
522 err = lpt_release_ppbus(sc, PPBUS_WAIT|PPBUS_INTR);
523 if(err) {
524 LPT_DPRINTF(("%s(%s): error (%d) while releasing ppbus.\n",
525 __func__, device_xname(dev), err));
526 }
527
528 sc->sc_state = 0;
529
530 return err;
531 }
532
533 /*
534 * lptread --retrieve printer status in IEEE1284 NIBBLE mode
535 */
536 int
lptread(dev_t dev_id,struct uio * uio,int ioflag)537 lptread(dev_t dev_id, struct uio *uio, int ioflag)
538 {
539 size_t len = 0;
540 int error = 0;
541 device_t dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
542 struct lpt_softc *sc = device_private(dev);
543
544 if(!(sc->sc_state & HAVEBUS)) {
545 LPT_DPRINTF(("%s(%s): attempt to read using device which does "
546 "not own the bus(%s).\n", __func__, device_xname(dev),
547 device_xname(device_parent(dev))));
548 return (ENODEV);
549 }
550
551 sc->sc_state &= ~INTERRUPTED;
552 while (uio->uio_resid) {
553 error = ppbus_read(device_parent(dev), sc->sc_outbuf,
554 uimin(BUFSIZE, uio->uio_resid), 0, &len);
555
556 /* If error or no more data, stop */
557 if (error) {
558 if (error != EWOULDBLOCK)
559 sc->sc_state |= INTERRUPTED;
560 break;
561 }
562 if (len == 0)
563 break;
564
565 if ((error = uiomove(sc->sc_outbuf, len, uio)))
566 break;
567 }
568
569 return error;
570 }
571
572 /*
573 * lptwrite --copy a line from user space to a local buffer, then call
574 * putc to get the chars moved to the output queue.
575 *
576 * Flagging of interrupted write added.
577 */
578 int
lptwrite(dev_t dev_id,struct uio * uio,int ioflag)579 lptwrite(dev_t dev_id, struct uio * uio, int ioflag)
580 {
581 int error=0;
582 size_t n, cnt;
583 device_t dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
584 struct lpt_softc * sc = device_private(dev);
585
586 /* Check state and flags */
587 if(!(sc->sc_state & HAVEBUS)) {
588 LPT_DPRINTF(("%s(%s): attempt to write using device which does "
589 "not own the bus(%s).\n", __func__, device_xname(dev),
590 device_xname(device_parent(dev))));
591 return EINVAL;
592 }
593
594 LPT_VPRINTF(("%s(%s): writing %zu bytes\n", __func__,
595 device_xname(dev), uio->uio_resid));
596
597 /* Write the data */
598 sc->sc_state &= ~INTERRUPTED;
599 while (uio->uio_resid) {
600 n = MIN(BUFSIZE, uio->uio_resid);
601 error = uiomove(sc->sc_inbuf, n, uio);
602 if (error)
603 break;
604
605 error = ppbus_write(device_parent(dev), sc->sc_inbuf, n, ioflag,
606 &cnt);
607 if (error) {
608 if (error != EWOULDBLOCK)
609 sc->sc_state |= INTERRUPTED;
610 break;
611 }
612 }
613
614 LPT_VPRINTF(("%s(%s): transfer finished, error %d.\n", __func__,
615 device_xname(dev), error));
616
617 return error;
618 }
619
620 /* Printer ioctl */
621 int
lptioctl(dev_t dev_id,u_long cmd,void * data,int flags,struct lwp * l)622 lptioctl(dev_t dev_id, u_long cmd, void *data, int flags, struct lwp *l)
623 {
624 device_t dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
625 struct lpt_softc *sc = device_private(dev);
626 int val, fl;
627 int error=0;
628
629 if(!(sc->sc_state & HAVEBUS)) {
630 LPT_DPRINTF(("%s(%s): attempt to perform ioctl on device which "
631 "does not own the bus(%s).\n", __func__, device_xname(dev),
632 device_xname(device_parent(dev))));
633 return EBUSY;
634 }
635
636 switch (cmd) {
637 case LPTGMODE:
638 switch (ppbus_get_mode(device_parent(dev))) {
639 case PPBUS_COMPATIBLE:
640 val = mode_standard;
641 break;
642 case PPBUS_NIBBLE:
643 val = mode_nibble;
644 break;
645 case PPBUS_PS2:
646 val = mode_ps2;
647 break;
648 case PPBUS_FAST:
649 val = mode_fast;
650 break;
651 case PPBUS_EPP:
652 val = mode_epp;
653 break;
654 case PPBUS_ECP:
655 val = mode_ecp;
656 break;
657 default:
658 error = EINVAL;
659 val = mode_unknown;
660 break;
661 }
662 *(int *)data = val;
663 break;
664
665 case LPTSMODE:
666 switch (*(int *)data) {
667 case mode_standard:
668 val = PPBUS_COMPATIBLE;
669 break;
670 case mode_nibble:
671 val = PPBUS_NIBBLE;
672 break;
673 case mode_ps2:
674 val = PPBUS_PS2;
675 break;
676 case mode_fast:
677 val = PPBUS_FAST;
678 break;
679 case mode_epp:
680 val = PPBUS_EPP;
681 break;
682 case mode_ecp:
683 val = PPBUS_ECP;
684 break;
685 default:
686 error = EINVAL;
687 val = mode_unknown;
688 break;
689 }
690
691 if (!error)
692 error = ppbus_set_mode(device_parent(dev), val, 0);
693
694 break;
695
696 case LPTGFLAGS:
697 fl = 0;
698
699 /* DMA */
700 error = ppbus_read_ivar(device_parent(dev), PPBUS_IVAR_DMA, &val);
701 if (error)
702 break;
703 if (val)
704 fl |= LPT_DMA;
705
706 /* IEEE mode negotiation */
707 error = ppbus_read_ivar(device_parent(dev), PPBUS_IVAR_IEEE, &val);
708 if (error)
709 break;
710 if (val)
711 fl |= LPT_IEEE;
712
713 /* interrupts */
714 error = ppbus_read_ivar(device_parent(dev), PPBUS_IVAR_INTR, &val);
715 if (error)
716 break;
717 if (val)
718 fl |= LPT_INTR;
719
720 /* lpt-only flags */
721 fl |= sc->sc_flags;
722
723 *(int *)data = fl;
724 break;
725
726 case LPTSFLAGS:
727 fl = *(int *)data;
728
729 /* DMA */
730 val = (fl & LPT_DMA);
731 error = ppbus_write_ivar(device_parent(dev), PPBUS_IVAR_DMA, &val);
732 if (error)
733 break;
734
735 /* IEEE mode negotiation */
736 val = (fl & LPT_IEEE);
737 error = ppbus_write_ivar(device_parent(dev), PPBUS_IVAR_IEEE, &val);
738 if (error)
739 break;
740
741 /* interrupts */
742 val = (fl & LPT_INTR);
743 error = ppbus_write_ivar(device_parent(dev), PPBUS_IVAR_INTR, &val);
744 if (error)
745 break;
746
747 /* lpt-only flags */
748 sc->sc_flags = fl & (LPT_PRIME|LPT_AUTOLF);
749
750 break;
751
752 default:
753 error = EINVAL;
754 break;
755 }
756
757 return error;
758 }
759
760