xref: /netbsd-src/sys/dev/ppbus/lpt.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /* $NetBSD: lpt.c,v 1.12 2004/02/03 21:15:03 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.12 2004/02/03 21:15:03 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 	/* Initialize the device on open by default */
184 	sc->sc_flags = LPT_PRIME;
185 
186 	lpt_release_ppbus(sc, 0);
187 }
188 
189 static int
190 lpt_detach(struct device * self, int flags)
191 {
192 	struct lpt_softc * lpt = (struct lpt_softc *) self;
193 	struct ppbus_device_softc * ppbdev = (struct ppbus_device_softc *) lpt;
194 	int err;
195 
196 	if(lpt->sc_state & HAVEBUS) {
197 		err = lpt_release_ppbus(lpt, 0);
198 		if(err) {
199 			printf("%s error (%d) while releasing bus",
200 				self->dv_xname, err);
201 			if(flags & DETACH_FORCE) {
202 				printf(", continuing (DETACH_FORCE)!\n");
203 			}
204 			else {
205 				printf(", terminating!\n");
206 				return 0;
207 			}
208 		}
209 		lpt->sc_state &= ~HAVEBUS;
210 	}
211 
212 	ppbdev->ctx.valid = 0;
213 
214 	/* Free memory buffers */
215 	if(ppbdev->capabilities & PPBUS_HAS_DMA) {
216 		ppbus_dma_free(self->dv_parent, &(lpt->sc_inbuf),
217 			&(lpt->sc_in_baddr), BUFSIZE);
218 		ppbus_dma_free(self->dv_parent, &(lpt->sc_outbuf),
219 			&(lpt->sc_out_baddr), BUFSIZE);
220 	} else {
221 		free(lpt->sc_inbuf, M_DEVBUF);
222 		free(lpt->sc_outbuf, M_DEVBUF);
223 	}
224 
225 	if(!(flags & DETACH_QUIET)) {
226 		printf("%s detached", self->dv_xname);
227 	}
228 
229 	return 1;
230 }
231 
232 /* Grab bus for lpt device */
233 static int
234 lpt_request_ppbus(struct lpt_softc * lpt, int how)
235 {
236 	struct device * dev = (struct device *) lpt;
237 	int error;
238 
239 	error = ppbus_request_bus(dev->dv_parent, dev, how, (hz));
240 	if (!(error)) {
241 		lpt->sc_state |= HAVEBUS;
242 	}
243 	else {
244 		LPT_DPRINTF(("%s(%s): error %d requesting bus.\n", __func__,
245 			dev->dv_xname, error));
246 	}
247 
248 	return error;
249 }
250 
251 /* Release ppbus to enable other devices to use it. */
252 static int
253 lpt_release_ppbus(struct lpt_softc * lpt, int how)
254 {
255 	struct device * dev = (struct device *) lpt;
256 	int error;
257 
258 	if(lpt->sc_state & HAVEBUS) {
259 		error = ppbus_release_bus(dev->dv_parent, dev, how, (hz));
260 		if(!(error))
261 			lpt->sc_state &= ~HAVEBUS;
262 		else
263 			LPT_DPRINTF(("%s(%s): error releasing bus.\n", __func__,
264 				dev->dv_xname));
265 	}
266 	else {
267 		error = EINVAL;
268 		LPT_DPRINTF(("%s(%s): device does not own bus.\n", __func__,
269 			dev->dv_xname));
270 	}
271 
272 	return error;
273 }
274 
275 
276 /*
277  * Probe simplified by replacing multiple loops with a hardcoded
278  * test pattern - 1999/02/08 des@freebsd.org
279  *
280  * New lpt port probe Geoff Rehmet - Rhodes University - 14/2/94
281  * Based partially on Rod Grimes' printer probe
282  *
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.)
289  *
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.
295  *
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.
301  *
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.
304  *
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.
308  *
309  *	   We are finally left with a mask of 0x14, due to some printers
310  *	   being adamant about holding other bits high ........
311  *
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.
315  *
316  *	3) Set the data and control ports to a value of 0
317  *
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.
322  */
323 static int
324 lpt_detect(struct device * dev)
325 {
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 */
333 	};
334 	int i, status;
335 	u_char dtr, ctr, str, var;
336 
337 	/* Save register contents */
338 	dtr = ppbus_rdtr(dev);
339 	ctr = ppbus_rctr(dev);
340 	str = ppbus_rstr(dev);
341 
342 	status = 1;				/* assume success */
343 
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__, dev->dv_xname, testbyte[i], var));
352 			goto end;
353 		}
354 	}
355 
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 				dev->dv_xname, (testbyte[i] & 0x14),
366 				testbyte[i], (var & 0x14)));
367 			break;
368 		}
369 	}
370 
371 end:
372 	/* Restore contents of registers */
373 	ppbus_wdtr(dev, dtr);
374 	ppbus_wctr(dev, ctr);
375 	ppbus_wstr(dev, str);
376 
377 	return status;
378 }
379 
380 /* Log status of status register for printer port */
381 static int
382 lpt_logstatus(const struct device * const dev, const unsigned char status)
383 {
384 	int err;
385 
386 	err = EIO;
387 	if(!(status & LPS_SEL)) {
388 		log(LOG_ERR, "%s: offline.", dev->dv_xname);
389 	}
390 	else if(!(status & LPS_NBSY)) {
391 		log(LOG_ERR, "%s: busy.", dev->dv_xname);
392 	}
393 	else if(status & LPS_OUT) {
394 		log(LOG_ERR, "%s: out of paper.", dev->dv_xname);
395 		err = EAGAIN;
396 	}
397 	else if(!(status & LPS_NERR)) {
398 		log(LOG_ERR, "%s: output error.", dev->dv_xname);
399 	}
400 	else {
401 		log(LOG_ERR, "%s: no error indication.", dev->dv_xname);
402 		err = 0;
403 	}
404 
405 	return err;
406 }
407 
408 /*
409  * lptopen -- reset the printer, then wait until it's selected and not busy.
410  */
411 int
412 lptopen(dev_t dev_id, int flags, int fmt, struct proc *p)
413 {
414 	int trys, err;
415 	u_int8_t status;
416 	struct device * dev;
417 	struct lpt_softc * lpt;
418 	struct ppbus_device_softc * ppbus_dev;
419 	struct device * ppbus;
420 
421 	dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
422 	if(!dev) {
423 		LPT_DPRINTF(("%s(): device not configured.\n", __func__));
424 		return ENXIO;
425 	}
426 
427 	lpt = (struct lpt_softc *) dev;
428 
429 	ppbus = dev->dv_parent;
430 	ppbus_dev = &(lpt->ppbus_dev);
431 
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__, dev->dv_xname, err));
437 		return (err);
438 	}
439 
440 	/* Update bus mode */
441 	ppbus_dev->ctx.mode = ppbus_get_mode(ppbus);
442 
443 	/* init printer */
444 	if ((lpt->sc_flags & LPT_PRIME) && !LPTCTL(dev_id)) {
445 		LPT_VPRINTF(("%s(%s): initializing printer.\n", __func__,
446 			dev->dv_xname));
447 		lpt->sc_state |= LPTINIT;
448 		ppbus_wctr(ppbus, LPC_SEL | LPC_NINIT);
449 
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)) {
454 
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((caddr_t)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 					dev->dv_xname));
467 					lpt_release_ppbus(lpt, PPBUS_WAIT);
468 					return (err);
469 				}
470 			}
471 		}
472 
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 				dev->dv_xname, status));
478 			err = lpt_logstatus(dev, status);
479 			lpt_release_ppbus(lpt, PPBUS_WAIT);
480 			return (err);
481 		}
482 		else
483 			LPT_VPRINTF(("%s(%s): printer ready.\n", __func__,
484 				dev->dv_xname));
485 	}
486 
487 	/* Set autolinefeed if requested */
488 	if (lpt->sc_flags & LPT_AUTOLF)
489 		ppbus_wctr(ppbus, LPC_AUTOL);
490 	else
491 		ppbus_wctr(ppbus, 0);
492 
493 	/* ready now */
494 	lpt->sc_state |= OPEN;
495 
496 	return 0;
497 }
498 
499 /*
500  * lptclose -- close the device, free the local line buffer.
501  *
502  * Check for interrupted write call added.
503  */
504 int
505 lptclose(dev_t dev_id, int flags, int fmt, struct proc *p)
506 {
507 	struct device * dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
508 	struct lpt_softc * sc = (struct lpt_softc *) dev;
509 	int err;
510 
511 	err = lpt_release_ppbus(sc, PPBUS_WAIT|PPBUS_INTR);
512 	if(err) {
513 		LPT_DPRINTF(("%s(%s): error (%d) while releasing ppbus.\n",
514 			__func__, dev->dv_xname, err));
515 	}
516 
517 	sc->sc_state = 0;
518 
519 	return err;
520 }
521 
522 /*
523  * lptread --retrieve printer status in IEEE1284 NIBBLE mode
524  */
525 int
526 lptread(dev_t dev_id, struct uio *uio, int ioflag)
527 {
528 	size_t len = 0;
529 	int error = 0;
530 	struct device * dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
531 	struct lpt_softc * sc = (struct lpt_softc *) dev;
532 
533 	if(!(sc->sc_state & HAVEBUS)) {
534 		LPT_DPRINTF(("%s(%s): attempt to read using device which does "
535 			"not own the bus(%s).\n", __func__, dev->dv_xname,
536 			dev->dv_parent->dv_xname));
537 		return (ENODEV);
538 	}
539 
540 	sc->sc_state &= ~INTERRUPTED;
541 	while (uio->uio_resid) {
542 		error = ppbus_read(dev->dv_parent, sc->sc_outbuf,
543 			min(BUFSIZE, uio->uio_resid), 0, &len);
544 
545 		/* If error or no more data, stop */
546 		if (error) {
547 			if (error != EWOULDBLOCK)
548 				sc->sc_state |= INTERRUPTED;
549 			break;
550 		}
551 		if (len == 0)
552 			break;
553 
554 		if ((error = uiomove(sc->sc_outbuf, len, uio)))
555 			break;
556 	}
557 
558 	return error;
559 }
560 
561 /*
562  * lptwrite --copy a line from user space to a local buffer, then call
563  * putc to get the chars moved to the output queue.
564  *
565  * Flagging of interrupted write added.
566  */
567 int
568 lptwrite(dev_t dev_id, struct uio * uio, int ioflag)
569 {
570 	int error=0;
571 	size_t n, cnt;
572 	struct device * dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
573 	struct lpt_softc * sc = (struct lpt_softc *) dev;
574 
575 	/* Check state and flags */
576 	if(!(sc->sc_state & HAVEBUS)) {
577 		LPT_DPRINTF(("%s(%s): attempt to write using device which does "
578 			"not own the bus(%s).\n", __func__, dev->dv_xname,
579 			dev->dv_parent->dv_xname));
580 		return EINVAL;
581 	}
582 
583 	LPT_VPRINTF(("%s(%s): writing %d bytes\n", __func__,
584 	    dev->dv_xname, uio->uio_resid));
585 
586 	/* Write the data */
587 	sc->sc_state &= ~INTERRUPTED;
588 	while (uio->uio_resid) {
589 		n = MIN(BUFSIZE, uio->uio_resid);
590 		error = uiomove(sc->sc_inbuf, n, uio);
591 		if (error)
592 			break;
593 
594 		error = ppbus_write(dev->dv_parent, sc->sc_inbuf, n, ioflag,
595 			&cnt);
596 		if (error) {
597 			if (error != EWOULDBLOCK)
598 				sc->sc_state |= INTERRUPTED;
599 			break;
600 		}
601 	}
602 
603 	LPT_VPRINTF(("%s(%s): transfer finished, error %d.\n", __func__,
604 	    dev->dv_xname, error));
605 
606 	return error;
607 }
608 
609 /* Printer ioctl */
610 int
611 lptioctl(dev_t dev_id, u_long cmd, caddr_t data, int flags, struct proc *p)
612 {
613 	struct device *dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
614 	struct lpt_softc *sc = (struct lpt_softc *) dev;
615 	int val, fl;
616 	int error=0;
617 
618 	if(!(sc->sc_state & HAVEBUS)) {
619 		LPT_DPRINTF(("%s(%s): attempt to perform ioctl on device which "
620 			"does not own the bus(%s).\n", __func__, dev->dv_xname,
621 			dev->dv_parent->dv_xname));
622 		return EBUSY;
623 	}
624 
625 	switch (cmd) {
626 	case LPTGMODE:
627         	switch (ppbus_get_mode(dev->dv_parent)) {
628 		case PPBUS_COMPATIBLE:
629 			val = mode_standard;
630 			break;
631 		case PPBUS_NIBBLE:
632 			val = mode_nibble;
633 			break;
634 		case PPBUS_PS2:
635 			val = mode_ps2;
636 			break;
637 		case PPBUS_FAST:
638 			val = mode_fast;
639 			break;
640 		case PPBUS_EPP:
641 			val = mode_epp;
642 			break;
643 		case PPBUS_ECP:
644 			val = mode_ecp;
645 			break;
646 		default:
647 			error = EINVAL;
648 			val = mode_unknown;
649 			break;
650 		}
651 		*(int *)data = val;
652 		break;
653 
654 	case LPTSMODE:
655         	switch (*(int *)data) {
656 		case mode_standard:
657 			val = PPBUS_COMPATIBLE;
658 			break;
659 		case mode_nibble:
660 			val = PPBUS_NIBBLE;
661 			break;
662 		case mode_ps2:
663 			val = PPBUS_PS2;
664 			break;
665 		case mode_fast:
666 			val = PPBUS_FAST;
667 			break;
668 		case mode_epp:
669 			val = PPBUS_EPP;
670 			break;
671 		case mode_ecp:
672 			val = PPBUS_ECP;
673 			break;
674 		default:
675 			error = EINVAL;
676 			val = mode_unknown;
677 			break;
678 		}
679 
680 		if (!error)
681 			error = ppbus_set_mode(dev->dv_parent, val, 0);
682 
683 		break;
684 
685 	case LPTGFLAGS:
686 		fl = 0;
687 
688 		/* DMA */
689 		error = ppbus_read_ivar(dev->dv_parent, PPBUS_IVAR_DMA, &val);
690 		if (error)
691 			break;
692 		if (val)
693 			fl |= LPT_DMA;
694 
695 		/* IEEE mode negotiation */
696 		error = ppbus_read_ivar(dev->dv_parent, PPBUS_IVAR_IEEE, &val);
697 		if (error)
698 			break;
699 		if (val)
700 			fl |= LPT_IEEE;
701 
702 		/* interrupts */
703 		error = ppbus_read_ivar(dev->dv_parent, PPBUS_IVAR_INTR, &val);
704 		if (error)
705 			break;
706 		if (val)
707 			fl |= LPT_INTR;
708 
709 		/* lpt-only flags */
710 		fl |= sc->sc_flags;
711 
712 		*(int *)data = fl;
713 		break;
714 
715 	case LPTSFLAGS:
716 		fl = *(int *)data;
717 
718 		/* DMA */
719 		val = (fl & LPT_DMA);
720 		error = ppbus_write_ivar(dev->dv_parent, PPBUS_IVAR_DMA, &val);
721 		if (error)
722 			break;
723 
724 		/* IEEE mode negotiation */
725 		val = (fl & LPT_IEEE);
726 		error = ppbus_write_ivar(dev->dv_parent, PPBUS_IVAR_IEEE, &val);
727 		if (error)
728 			break;
729 
730 		/* interrupts */
731 		val = (fl & LPT_INTR);
732 		error = ppbus_write_ivar(dev->dv_parent, PPBUS_IVAR_INTR, &val);
733 		if (error)
734 			break;
735 
736 		/* lpt-only flags */
737 		sc->sc_flags = fl & (LPT_PRIME|LPT_AUTOLF);
738 
739 		break;
740 
741 	default:
742 		error = EINVAL;
743 		break;
744 	}
745 
746 	return error;
747 }
748 
749