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