lpt.c revision 1.2 1 /*
2 * Copyright (c) 1990 William F. Jolitz, TeleMuse
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This software is a component of "386BSD" developed by
16 * William F. Jolitz, TeleMuse.
17 * 4. Neither the name of the developer nor the name "386BSD"
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
22 * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
23 * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
24 * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
25 * NOT MAKE USE OF THIS WORK.
26 *
27 * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
28 * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
29 * REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES
30 * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
31 * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
32 * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
33 * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
34 * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
37 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39 * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE
40 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
42 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
44 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
45 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46 * SUCH DAMAGE.
47 *
48 * from: unknown origin, 386BSD 0.1
49 * From Id: lpt.c,v 1.55.2.1 1996/11/12 09:08:38 phk Exp
50 * From Id: nlpt.c,v 1.14 1999/02/08 13:55:43 des Exp
51 * $FreeBSD: src/sys/dev/ppbus/lpt.c,v 1.15.2.3 2000/07/07 00:30:40 obrien Exp $
52 */
53
54 /*
55 * Device Driver for AT parallel printer port
56 * Written by William Jolitz 12/18/90
57 */
58
59 /*
60 * Updated for ppbus by Nicolas Souchu
61 * [Mon Jul 28 1997]
62 */
63
64 #include "opt_ppbus_lpt.h"
65
66 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/conf.h>
69 #include <sys/kernel.h>
70 #include <sys/proc.h>
71 #include <sys/malloc.h>
72 #include <sys/file.h>
73 #include <sys/uio.h>
74 #include <sys/ioctl.h>
75 #include <sys/types.h>
76 #include <sys/syslog.h>
77
78 #include <machine/bus.h>
79
80 #include <dev/ppbus/ppbus_1284.h>
81 #include <dev/ppbus/ppbus_base.h>
82 #include <dev/ppbus/ppbus_io.h>
83 #include <dev/ppbus/ppbus_msq.h>
84 #include <dev/ppbus/ppbus_var.h>
85
86 #include <dev/ppbus/lptvar.h>
87 #include <dev/ppbus/lptreg.h>
88 #include <dev/ppbus/lptio.h>
89
90 /* Autoconf functions */
91 static int lpt_probe(struct device *, struct cfdata *, void *);
92 static void lpt_attach(struct device *, struct device *, void *);
93 static int lpt_detach(struct device *, int);
94
95 /* Autoconf structure */
96 CFATTACH_DECL(lpt_ppbus, sizeof(struct lpt_softc), lpt_probe, lpt_attach,
97 lpt_detach, NULL);
98
99 extern struct cfdriver lpt_cd;
100
101 dev_type_open(lptopen);
102 dev_type_close(lptclose);
103 dev_type_read(lptread);
104 dev_type_write(lptwrite);
105 dev_type_ioctl(lptioctl);
106
107 const struct cdevsw lpt_cdevsw = {
108 lptopen, lptclose, lptread, lptwrite, lptioctl,
109 nostop, notty, nopoll, nommap, nokqfilter
110 };
111
112
113 /* Function prototypes */
114 static int lpt_detect(struct device *);
115 static int lpt_request_ppbus(struct lpt_softc *, int);
116 static int lpt_release_ppbus(struct lpt_softc *, int);
117 static int lpt_logstatus(const struct device * const, const unsigned char);
118
119 /*
120 * lpt_probe()
121 */
122 static int
123 lpt_probe(struct device * parent, struct cfdata * match, void * aux)
124 {
125 /* Test ppbus's capability */
126 return lpt_detect(parent);
127 }
128
129 static void
130 lpt_attach(struct device * parent, struct device * self, void * aux)
131 {
132 struct lpt_softc * sc = (struct lpt_softc *) self;
133 struct ppbus_device_softc * ppbdev = &(sc->ppbus_dev);
134 struct ppbus_attach_args * args = aux;
135 char buf[64];
136 int error;
137
138 sc->sc_dev_ok = LPT_NOK;
139
140 error = lpt_request_ppbus(sc, 0);
141 if(error) {
142 printf("%s(%s): error (%d) requesting bus(%s). Device not "
143 "properly attached.\n", __func__, self->dv_xname,
144 error, parent->dv_xname);
145 return;
146 }
147
148 /* Record capabilities */
149 ppbdev->capabilities = args->capabilities;
150
151 /* Allocate memory buffers */
152 if(ppbdev->capabilities & PPBUS_HAS_DMA) {
153 if(ppbus_dma_malloc(parent, &(sc->sc_inbuf),
154 &(sc->sc_in_baddr), BUFSIZE)) {
155
156 printf(" : cannot allocate input DMA buffer. Device "
157 "not properly attached!\n");
158 return;
159 }
160 if(ppbus_dma_malloc(parent, &(sc->sc_outbuf),
161 &(sc->sc_out_baddr), BUFSIZE)) {
162
163 ppbus_dma_free(parent, &(sc->sc_inbuf),
164 &(sc->sc_in_baddr), BUFSIZE);
165 printf(" : cannot allocate output DMA buffer. Device "
166 "not properly attached!\n");
167 return;
168 }
169 }
170 else {
171 sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
172 sc->sc_outbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
173 }
174
175 /* Print out mode */
176 ppbdev->ctx.mode = ppbus_get_mode(parent);
177 bitmask_snprintf(ppbdev->ctx.mode, "\20\1COMPATIBLE\2NIBBLE"
178 "\3PS2\4EPP\5ECP\6FAST_CENTR", buf, sizeof(buf));
179 printf(": mode = %s\n", buf);
180
181 /* Set ok flag */
182 sc->sc_dev_ok = LPT_OK;
183
184 lpt_release_ppbus(sc, 0);
185
186 return;
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_dev_ok == LPT_NOK) {
197 printf("%s: device not properly attached,\n", self->dv_xname);
198 if(flags & DETACH_FORCE) {
199 printf(", continuing (DETACH_FORCE)!\n");
200 }
201 else {
202 printf(", terminating!\n");
203 return 0;
204 }
205 }
206
207 if(lpt->sc_state & HAVEBUS) {
208 err = lpt_release_ppbus(lpt, 0);
209 if(err) {
210 printf("%s error (%d) while releasing bus",
211 self->dv_xname, err);
212 if(flags & DETACH_FORCE) {
213 printf(", continuing (DETACH_FORCE)!\n");
214 }
215 else {
216 printf(", terminating!\n");
217 return 0;
218 }
219 }
220 lpt->sc_state &= ~HAVEBUS;
221 }
222
223 lpt->sc_dev_ok = LPT_NOK;
224 lpt->sc_irq = 0;
225
226 ppbdev->ctx.valid = 0;
227
228 /* Free memory buffers */
229 if(ppbdev->capabilities & PPBUS_HAS_DMA) {
230 ppbus_dma_free(self->dv_parent, &(lpt->sc_inbuf),
231 &(lpt->sc_in_baddr), BUFSIZE);
232 ppbus_dma_free(self->dv_parent, &(lpt->sc_outbuf),
233 &(lpt->sc_out_baddr), BUFSIZE);
234 }
235 else {
236 free(lpt->sc_inbuf, M_DEVBUF);
237 free(lpt->sc_outbuf, M_DEVBUF);
238 }
239
240 if(!(flags & DETACH_QUIET)) {
241 printf("%s detached", self->dv_xname);
242 }
243
244 return 1;
245 }
246
247 /* Grab bus for lpt device */
248 static int
249 lpt_request_ppbus(struct lpt_softc * lpt, int how)
250 {
251 struct device * dev = (struct device *) lpt;
252 int error;
253
254 error = ppbus_request_bus(dev->dv_parent, dev, how, (hz));
255 if (!(error)) {
256 lpt->sc_state |= HAVEBUS;
257 }
258 else {
259 LPT_DPRINTF(("%s(%s): error %d requesting bus.\n", __func__,
260 dev->dv_xname, error));
261 }
262
263 return error;
264 }
265
266 /* Release ppbus to enable other devices to use it. */
267 static int
268 lpt_release_ppbus(struct lpt_softc * lpt, int how)
269 {
270 struct device * dev = (struct device *) lpt;
271 int error;
272
273 if(lpt->sc_state & HAVEBUS) {
274 error = ppbus_release_bus(dev->dv_parent, dev, how, (hz));
275 if(!(error))
276 lpt->sc_state &= ~HAVEBUS;
277 else
278 LPT_DPRINTF(("%s(%s): error releasing bus.\n", __func__,
279 dev->dv_xname));
280 }
281 else {
282 error = EINVAL;
283 LPT_DPRINTF(("%s(%s): device does not own bus.\n", __func__,
284 dev->dv_xname));
285 }
286
287 return error;
288 }
289
290
291 /*
292 * Probe simplified by replacing multiple loops with a hardcoded
293 * test pattern - 1999/02/08 des (at) freebsd.org
294 *
295 * New lpt port probe Geoff Rehmet - Rhodes University - 14/2/94
296 * Based partially on Rod Grimes' printer probe
297 *
298 * Logic:
299 * 1) If no port address was given, use the bios detected ports
300 * and autodetect what ports the printers are on.
301 * 2) Otherwise, probe the data port at the address given,
302 * using the method in Rod Grimes' port probe.
303 * (Much code ripped off directly from Rod's probe.)
304 *
305 * Comments from Rod's probe:
306 * Logic:
307 * 1) You should be able to write to and read back the same value
308 * to the data port. Do an alternating zeros, alternating ones,
309 * walking zero, and walking one test to check for stuck bits.
310 *
311 * 2) You should be able to write to and read back the same value
312 * to the control port lower 5 bits, the upper 3 bits are reserved
313 * per the IBM PC technical reference manauls and different boards
314 * do different things with them. Do an alternating zeros, alternating
315 * ones, walking zero, and walking one test to check for stuck bits.
316 *
317 * Some printers drag the strobe line down when the are powered off
318 * so this bit has been masked out of the control port test.
319 *
320 * XXX Some printers may not like a fast pulse on init or strobe, I
321 * don't know at this point, if that becomes a problem these bits
322 * should be turned off in the mask byte for the control port test.
323 *
324 * We are finally left with a mask of 0x14, due to some printers
325 * being adamant about holding other bits high ........
326 *
327 * Before probing the control port, we write a 0 to the data port -
328 * If not, some printers chuck out garbage when the strobe line
329 * gets toggled.
330 *
331 * 3) Set the data and control ports to a value of 0
332 *
333 * This probe routine has been tested on Epson Lx-800, HP LJ3P,
334 * Epson FX-1170 and C.Itoh 8510RM
335 * printers.
336 * Quick exit on fail added.
337 */
338 static int
339 lpt_detect(struct device * dev)
340 {
341 u_char testbyte[18] = {
342 0x55, /* alternating zeros */
343 0xaa, /* alternating ones */
344 0xfe, 0xfd, 0xfb, 0xf7,
345 0xef, 0xdf, 0xbf, 0x7f, /* walking zero */
346 0x01, 0x02, 0x04, 0x08,
347 0x10, 0x20, 0x40, 0x80 /* walking one */
348 };
349 int i, status;
350 u_char dtr, ctr, str, var;
351
352 /* Save register contents */
353 dtr = ppbus_rdtr(dev);
354 ctr = ppbus_rctr(dev);
355 str = ppbus_rstr(dev);
356
357 status = 1; /* assume success */
358
359 /* Test data port */
360 for(i = 0; i < 18; i++) {
361 ppbus_wdtr(dev, testbyte[i]);
362 if((var = ppbus_rdtr(dev)) != testbyte[i]) {
363 status = 0;
364 LPT_DPRINTF(("%s(%s): byte value %x cannot be written "
365 "and read from data port (got %x instead).\n",
366 __func__, dev->dv_xname, testbyte[i], var));
367 goto end;
368 }
369 }
370
371 /* Test control port */
372 ppbus_wdtr(dev, 0);
373 for(i = 0; i < 18; i++) {
374 ppbus_wctr(dev, (testbyte[i] & 0x14));
375 if(((var = ppbus_rctr(dev)) & 0x14) != (testbyte[i] & 0x14)) {
376 status = 0;
377 LPT_DPRINTF(("%s(%s): byte value %x (unmasked value "
378 "%x) cannot be written and read from control "
379 "port (got %x instead).\n", __func__,
380 dev->dv_xname, (testbyte[i] & 0x14),
381 testbyte[i], (var & 0x14)));
382 break;
383 }
384 }
385
386 end:
387 /* Restore contents of registers */
388 ppbus_wdtr(dev, dtr);
389 ppbus_wctr(dev, ctr);
390 ppbus_wstr(dev, str);
391
392 return status;
393 }
394
395 /* Log status of status register for printer port */
396 static int
397 lpt_logstatus(const struct device * const dev, const unsigned char status)
398 {
399 int err;
400
401 err = EIO;
402 if(!(status & LPS_SEL)) {
403 log(LOG_ERR, "%s: offline.", dev->dv_xname);
404 }
405 else if(!(status & LPS_NBSY)) {
406 log(LOG_ERR, "%s: busy.", dev->dv_xname);
407 }
408 else if(status & LPS_OUT) {
409 log(LOG_ERR, "%s: out of paper.", dev->dv_xname);
410 err = EAGAIN;
411 }
412 else if(!(status & LPS_NERR)) {
413 log(LOG_ERR, "%s: output error.", dev->dv_xname);
414 }
415 else {
416 log(LOG_ERR, "%s: no error indication.", dev->dv_xname);
417 err = 0;
418 }
419
420 return err;
421 }
422
423 /*
424 * lptopen -- reset the printer, then wait until it's selected and not busy.
425 */
426 int
427 lptopen(dev_t dev_id, int flags, int fmt, struct proc *p)
428 {
429 int trys, err, val;
430 u_int8_t status;
431 struct device * dev;
432 struct lpt_softc * lpt;
433 struct ppbus_device_softc * ppbus_dev;
434 struct device * ppbus;
435
436 dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
437 if(!dev) {
438 LPT_DPRINTF(("%s(): device not configured.\n", __func__));
439 return ENXIO;
440 }
441
442 lpt = (struct lpt_softc *) dev;
443
444 if(lpt->sc_dev_ok != LPT_OK) {
445 LPT_DPRINTF(("%s(): device not attached properly [sc = %p, "
446 "sc_dev_ok = %x].\n", __func__, dev, lpt->sc_dev_ok));
447 return ENODEV;
448 }
449
450 ppbus = dev->dv_parent;
451 ppbus_dev = &(lpt->ppbus_dev);
452
453 /* Request the ppbus */
454 err = lpt_request_ppbus(lpt, PPBUS_WAIT|PPBUS_INTR);
455 if(err) {
456 LPT_DPRINTF(("%s(%s): error (%d) while requesting bus.\n",
457 __func__, dev->dv_xname, err));
458 return (err);
459 }
460
461 /* Get device flags */
462 lpt->sc_flags = LPTFLAGS(dev_id);
463
464 /* Update bus mode */
465 ppbus_dev->ctx.mode = ppbus_get_mode(ppbus);
466
467 /* Configure interrupts/polling */
468 if(lpt->sc_flags & LPT_NOINTR) {
469 val = 0;
470 err = ppbus_write_ivar(ppbus, PPBUS_IVAR_INTR, &val);
471 if(err) {
472 lpt_release_ppbus(lpt, PPBUS_WAIT);
473 return err;
474 }
475 }
476 else {
477 val = 1;
478 err = ppbus_write_ivar(ppbus, PPBUS_IVAR_INTR, &val);
479 if(err) {
480 lpt_release_ppbus(lpt, PPBUS_WAIT);
481 return err;
482 }
483 }
484 if(err) {
485 lpt_release_ppbus(lpt, PPBUS_WAIT);
486 return err;
487 }
488
489 /* init printer */
490 if(!(lpt->sc_flags & LPT_NOPRIME)) {
491 LPT_VPRINTF(("%s(%s): initializing printer.\n", __func__,
492 dev->dv_xname));
493 lpt->sc_state |= LPTINIT;
494 ppbus_wctr(ppbus, LPC_SEL | LPC_NINIT);
495
496 /* wait till ready (printer running diagnostics) */
497 for(trys = 0, status = ppbus_rstr(ppbus); (status & RDY_MASK)
498 != LP_READY; trys += LPT_STEP, status =
499 ppbus_rstr(ppbus)) {
500
501 /* Time up waiting for the printer */
502 if(trys >= LPT_TIMEOUT)
503 break;
504 /* wait LPT_STEP ticks, give up if we get a signal */
505 else {
506 err = tsleep((caddr_t)lpt, LPPRI|PCATCH,
507 "lptinit", LPT_STEP);
508 if((err) && (err != EWOULDBLOCK)) {
509 lpt->sc_state &= ~LPTINIT;
510 LPT_DPRINTF(("%s(%s): interrupted "
511 "during initialization.\n", __func__,
512 dev->dv_xname));
513 lpt_release_ppbus(lpt, PPBUS_WAIT);
514 return (err);
515 }
516 }
517 }
518
519 lpt->sc_state &= ~LPTINIT;
520 if(trys >= LPT_TIMEOUT) {
521 LPT_DPRINTF(("%s(%s): timed out while initializing "
522 "printer. [status %x]\n", __func__,
523 dev->dv_xname, status));
524 err = lpt_logstatus(dev, status);
525 lpt_release_ppbus(lpt, PPBUS_WAIT);
526 return (err);
527 }
528 else
529 LPT_VPRINTF(("%s(%s): printer ready.\n", __func__,
530 dev->dv_xname));
531 }
532
533 /* Set autolinefeed */
534 if(lpt->sc_flags & LPT_AUTOLF) {
535 lpt->sc_control |= LPC_AUTOL;
536 }
537
538 /* Write out the control register */
539 ppbus_wctr(ppbus, lpt->sc_control);
540
541 lpt->sc_xfercnt = 0;
542 lpt->sc_state |= OPEN;
543
544 return 0;
545 }
546
547 /*
548 * lptclose -- close the device, free the local line buffer.
549 *
550 * Check for interrupted write call added.
551 */
552 int
553 lptclose(dev_t dev_id, int flags, int fmt, struct proc *p)
554 {
555 struct device * dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
556 struct lpt_softc * sc = (struct lpt_softc *) dev;
557 int err;
558
559 err = lpt_release_ppbus(sc, PPBUS_WAIT|PPBUS_INTR);
560 if(err) {
561 LPT_DPRINTF(("%s(%s): error (%d) while releasing ppbus.\n",
562 __func__, dev->dv_xname, err));
563 }
564
565 sc->sc_state = 0;
566 sc->sc_xfercnt = 0;
567
568 return err;
569 }
570
571 /*
572 * lptread --retrieve printer status in IEEE1284 NIBBLE mode
573 */
574 int
575 lptread(dev_t dev_id, struct uio *uio, int ioflag)
576 {
577 int error = 0;
578 int len = 0;
579 struct device * dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
580 struct lpt_softc * sc = (struct lpt_softc *) dev;
581
582 if(!(sc->sc_state & HAVEBUS)) {
583 LPT_DPRINTF(("%s(%s): attempt to read using device which does "
584 "not own the bus(%s).\n", __func__, dev->dv_xname,
585 dev->dv_parent->dv_xname));
586 return (ENODEV);
587 }
588
589 sc->sc_state &= ~INTERRUPTED;
590 while (uio->uio_resid) {
591 error = ppbus_read(dev->dv_parent, sc->sc_outbuf,
592 min(BUFSIZE, uio->uio_resid), 0, &len);
593
594 /* If error or no more data, stop */
595 if(error) {
596 if(error != EWOULDBLOCK)
597 sc->sc_state |= INTERRUPTED;
598 break;
599 }
600 else if(len == 0)
601 break;
602
603 error = uiomove(sc->sc_outbuf, len, uio);
604 if (error)
605 break;
606 }
607
608 return error;
609 }
610
611 /*
612 * lptwrite --copy a line from user space to a local buffer, then call
613 * putc to get the chars moved to the output queue.
614 *
615 * Flagging of interrupted write added.
616 */
617 int
618 lptwrite(dev_t dev_id, struct uio * uio, int ioflag)
619 {
620 unsigned n;
621 int err = 0;
622 size_t cnt;
623 struct device * dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
624 struct lpt_softc * sc = (struct lpt_softc *) dev;
625
626 /* Check state and flags */
627 if(!(sc->sc_state & HAVEBUS)) {
628 LPT_DPRINTF(("%s(%s): attempt to write using device which does "
629 "not own the bus(%s).\n", __func__, dev->dv_xname,
630 dev->dv_parent->dv_xname));
631 return EINVAL;
632 }
633
634 /* Write the data */
635 sc->sc_state &= ~INTERRUPTED;
636 while(uio->uio_resid) {
637 n = min(BUFSIZE, uio->uio_resid);
638 err = uiomove(sc->sc_inbuf, n, uio);
639 if(err)
640 break;
641
642 err = ppbus_write(dev->dv_parent, sc->sc_inbuf, n, ioflag,
643 &cnt);
644 sc->sc_xfercnt += cnt;
645 if(err) {
646 if(err != EWOULDBLOCK)
647 sc->sc_state |= INTERRUPTED;
648 break;
649 }
650 }
651
652 LPT_VPRINTF(("%s(%s): %d bytes sent.\n", __func__, dev->dv_xname,
653 sc->sc_xfercnt));
654
655 return err;
656 }
657
658 /* Printer ioctl */
659 int
660 lptioctl(dev_t dev_id, u_long cmd, caddr_t data, int flags, struct proc *p)
661 {
662 struct device * dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
663 struct lpt_softc * sc = (struct lpt_softc *) dev;
664 int val;
665 int error = 0;
666
667 if(!(sc->sc_state & HAVEBUS)) {
668 LPT_DPRINTF(("%s(%s): attempt to perform ioctl on device which "
669 "does not own the bus(%s).\n", __func__, dev->dv_xname,
670 dev->dv_parent->dv_xname));
671 return EBUSY;
672 }
673
674 switch (cmd) {
675 case LPTIO_ENABLE_DMA :
676 if((sc->ppbus_dev).capabilities & PPBUS_HAS_DMA) {
677 val = 1;
678 error = ppbus_write_ivar(dev->dv_parent,
679 PPBUS_IVAR_DMA, &val);
680 }
681 else {
682 LPT_DPRINTF(("%s(%s): device does not have DMA "
683 "capability.\n", __func__, dev->dv_xname));
684 error = ENODEV;
685 }
686 break;
687
688 case LPTIO_DISABLE_DMA :
689 if((sc->ppbus_dev).capabilities & PPBUS_HAS_DMA) {
690 val = 0;
691 error = ppbus_write_ivar(dev->dv_parent,
692 PPBUS_IVAR_DMA, &val);
693 }
694 else {
695 LPT_DPRINTF(("%s(%s): device does not have DMA "
696 "capability.\n", __func__, dev->dv_xname));
697 error = ENODEV;
698 }
699 break;
700
701 case LPTIO_MODE_STD:
702 error = ppbus_set_mode(dev->dv_parent, PPBUS_COMPATIBLE, 0);
703 break;
704
705 case LPTIO_MODE_NIBBLE:
706 error = ppbus_set_mode(dev->dv_parent, PPBUS_NIBBLE, 0);
707 break;
708
709 case LPTIO_MODE_PS2:
710 error = ppbus_set_mode(dev->dv_parent, PPBUS_PS2, 0);
711 break;
712
713 case LPTIO_MODE_FAST:
714 error = ppbus_set_mode(dev->dv_parent, PPBUS_FAST, 0);
715 break;
716
717 case LPTIO_MODE_ECP:
718 error = ppbus_set_mode(dev->dv_parent, PPBUS_ECP, 0);
719 break;
720
721 case LPTIO_MODE_EPP:
722 error = ppbus_set_mode(dev->dv_parent, PPBUS_EPP, 0);
723 break;
724
725 case LPTIO_ENABLE_IEEE:
726 val = 1;
727 error = ppbus_write_ivar(dev->dv_parent, PPBUS_IVAR_IEEE, &val);
728 break;
729
730 case LPTIO_DISABLE_IEEE:
731 val = 0;
732 error = ppbus_write_ivar(dev->dv_parent, PPBUS_IVAR_IEEE, &val);
733 break;
734
735 case LPTIO_GET_STATUS:
736 {
737 LPT_INFO_T * status = (LPT_INFO_T *)data;
738
739 error = ppbus_read_ivar(dev->dv_parent, PPBUS_IVAR_DMA, &val);
740 if(error) {
741 break;
742 }
743 else if(val) {
744 status->dma_status = true;
745 }
746 else {
747 status->dma_status = false;
748 }
749
750 error = ppbus_read_ivar(dev->dv_parent, PPBUS_IVAR_IEEE, &val);
751 if(error) {
752 break;
753 }
754 else if(val) {
755 status->ieee_status = true;
756 }
757 else {
758 status->ieee_status = false;
759 }
760
761 switch(ppbus_get_mode(dev->dv_parent)) {
762 case PPBUS_COMPATIBLE:
763 status->mode_status = standard;
764 break;
765 case PPBUS_NIBBLE:
766 status->mode_status = nibble;
767 break;
768 case PPBUS_PS2:
769 status->mode_status = ps2;
770 break;
771 case PPBUS_FAST:
772 status->mode_status = fast;
773 break;
774 case PPBUS_EPP:
775 status->mode_status = epp;
776 break;
777 case PPBUS_ECP:
778 status->mode_status = ecp;
779 break;
780 }
781 break;
782 }
783 default:
784 error = EINVAL;
785 }
786
787 return error;
788 }
789
790