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