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