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