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