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 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 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 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 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 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 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 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 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 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 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 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 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