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