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