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