1 /* $NetBSD: lpt.c,v 1.12 2004/02/03 21:15:03 jdolecek 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.12 2004/02/03 21:15:03 jdolecek 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 <machine/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(struct device *, struct cfdata *, void *); 97 static void lpt_attach(struct device *, struct device *, void *); 98 static int lpt_detach(struct device *, int); 99 100 /* Autoconf structure */ 101 CFATTACH_DECL(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 115 }; 116 117 118 /* Function prototypes */ 119 static int lpt_detect(struct device *); 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 struct device * const, const unsigned char); 123 124 /* 125 * lpt_probe() 126 */ 127 static int 128 lpt_probe(struct device * parent, struct cfdata * match, void * aux) 129 { 130 /* Test ppbus's capability */ 131 return lpt_detect(parent); 132 } 133 134 static void 135 lpt_attach(struct device * parent, struct device * self, void * aux) 136 { 137 struct lpt_softc * sc = (struct lpt_softc *) 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 error = lpt_request_ppbus(sc, 0); 144 if(error) { 145 printf("%s(%s): error (%d) requesting bus(%s). Device not " 146 "properly attached.\n", __func__, self->dv_xname, 147 error, parent->dv_xname); 148 return; 149 } 150 151 /* Record capabilities */ 152 ppbdev->capabilities = args->capabilities; 153 154 /* Allocate memory buffers */ 155 if(ppbdev->capabilities & PPBUS_HAS_DMA) { 156 if(ppbus_dma_malloc(parent, &(sc->sc_inbuf), 157 &(sc->sc_in_baddr), BUFSIZE)) { 158 159 printf(" : cannot allocate input DMA buffer. Device " 160 "not properly attached!\n"); 161 return; 162 } 163 if(ppbus_dma_malloc(parent, &(sc->sc_outbuf), 164 &(sc->sc_out_baddr), BUFSIZE)) { 165 166 ppbus_dma_free(parent, &(sc->sc_inbuf), 167 &(sc->sc_in_baddr), BUFSIZE); 168 printf(" : cannot allocate output DMA buffer. Device " 169 "not properly attached!\n"); 170 return; 171 } 172 } else { 173 sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK); 174 sc->sc_outbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK); 175 } 176 177 /* Print out mode */ 178 ppbdev->ctx.mode = ppbus_get_mode(parent); 179 bitmask_snprintf(ppbdev->ctx.mode, "\20\1COMPATIBLE\2NIBBLE" 180 "\3PS2\4EPP\5ECP\6FAST_CENTR", buf, sizeof(buf)); 181 printf(": port mode = %s\n", buf); 182 183 /* Initialize the device on open by default */ 184 sc->sc_flags = LPT_PRIME; 185 186 lpt_release_ppbus(sc, 0); 187 } 188 189 static int 190 lpt_detach(struct device * self, int flags) 191 { 192 struct lpt_softc * lpt = (struct lpt_softc *) self; 193 struct ppbus_device_softc * ppbdev = (struct ppbus_device_softc *) lpt; 194 int err; 195 196 if(lpt->sc_state & HAVEBUS) { 197 err = lpt_release_ppbus(lpt, 0); 198 if(err) { 199 printf("%s error (%d) while releasing bus", 200 self->dv_xname, err); 201 if(flags & DETACH_FORCE) { 202 printf(", continuing (DETACH_FORCE)!\n"); 203 } 204 else { 205 printf(", terminating!\n"); 206 return 0; 207 } 208 } 209 lpt->sc_state &= ~HAVEBUS; 210 } 211 212 ppbdev->ctx.valid = 0; 213 214 /* Free memory buffers */ 215 if(ppbdev->capabilities & PPBUS_HAS_DMA) { 216 ppbus_dma_free(self->dv_parent, &(lpt->sc_inbuf), 217 &(lpt->sc_in_baddr), BUFSIZE); 218 ppbus_dma_free(self->dv_parent, &(lpt->sc_outbuf), 219 &(lpt->sc_out_baddr), BUFSIZE); 220 } else { 221 free(lpt->sc_inbuf, M_DEVBUF); 222 free(lpt->sc_outbuf, M_DEVBUF); 223 } 224 225 if(!(flags & DETACH_QUIET)) { 226 printf("%s detached", self->dv_xname); 227 } 228 229 return 1; 230 } 231 232 /* Grab bus for lpt device */ 233 static int 234 lpt_request_ppbus(struct lpt_softc * lpt, int how) 235 { 236 struct device * dev = (struct device *) lpt; 237 int error; 238 239 error = ppbus_request_bus(dev->dv_parent, dev, how, (hz)); 240 if (!(error)) { 241 lpt->sc_state |= HAVEBUS; 242 } 243 else { 244 LPT_DPRINTF(("%s(%s): error %d requesting bus.\n", __func__, 245 dev->dv_xname, error)); 246 } 247 248 return error; 249 } 250 251 /* Release ppbus to enable other devices to use it. */ 252 static int 253 lpt_release_ppbus(struct lpt_softc * lpt, int how) 254 { 255 struct device * dev = (struct device *) lpt; 256 int error; 257 258 if(lpt->sc_state & HAVEBUS) { 259 error = ppbus_release_bus(dev->dv_parent, dev, how, (hz)); 260 if(!(error)) 261 lpt->sc_state &= ~HAVEBUS; 262 else 263 LPT_DPRINTF(("%s(%s): error releasing bus.\n", __func__, 264 dev->dv_xname)); 265 } 266 else { 267 error = EINVAL; 268 LPT_DPRINTF(("%s(%s): device does not own bus.\n", __func__, 269 dev->dv_xname)); 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(struct device * 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__, dev->dv_xname, 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 dev->dv_xname, (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 struct device * const dev, const unsigned char status) 383 { 384 int err; 385 386 err = EIO; 387 if(!(status & LPS_SEL)) { 388 log(LOG_ERR, "%s: offline.", dev->dv_xname); 389 } 390 else if(!(status & LPS_NBSY)) { 391 log(LOG_ERR, "%s: busy.", dev->dv_xname); 392 } 393 else if(status & LPS_OUT) { 394 log(LOG_ERR, "%s: out of paper.", dev->dv_xname); 395 err = EAGAIN; 396 } 397 else if(!(status & LPS_NERR)) { 398 log(LOG_ERR, "%s: output error.", dev->dv_xname); 399 } 400 else { 401 log(LOG_ERR, "%s: no error indication.", dev->dv_xname); 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 proc *p) 413 { 414 int trys, err; 415 u_int8_t status; 416 struct device * dev; 417 struct lpt_softc * lpt; 418 struct ppbus_device_softc * ppbus_dev; 419 struct device * 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 = (struct lpt_softc *) dev; 428 429 ppbus = dev->dv_parent; 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__, dev->dv_xname, 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 dev->dv_xname)); 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((caddr_t)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 dev->dv_xname)); 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 dev->dv_xname, 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 dev->dv_xname)); 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 proc *p) 506 { 507 struct device * dev = device_lookup(&lpt_cd, LPTUNIT(dev_id)); 508 struct lpt_softc * sc = (struct lpt_softc *) 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__, dev->dv_xname, 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 struct device * dev = device_lookup(&lpt_cd, LPTUNIT(dev_id)); 531 struct lpt_softc * sc = (struct lpt_softc *) 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__, dev->dv_xname, 536 dev->dv_parent->dv_xname)); 537 return (ENODEV); 538 } 539 540 sc->sc_state &= ~INTERRUPTED; 541 while (uio->uio_resid) { 542 error = ppbus_read(dev->dv_parent, 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 struct device * dev = device_lookup(&lpt_cd, LPTUNIT(dev_id)); 573 struct lpt_softc * sc = (struct lpt_softc *) 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__, dev->dv_xname, 579 dev->dv_parent->dv_xname)); 580 return EINVAL; 581 } 582 583 LPT_VPRINTF(("%s(%s): writing %d bytes\n", __func__, 584 dev->dv_xname, 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(dev->dv_parent, 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 dev->dv_xname, error)); 605 606 return error; 607 } 608 609 /* Printer ioctl */ 610 int 611 lptioctl(dev_t dev_id, u_long cmd, caddr_t data, int flags, struct proc *p) 612 { 613 struct device *dev = device_lookup(&lpt_cd, LPTUNIT(dev_id)); 614 struct lpt_softc *sc = (struct lpt_softc *) 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__, dev->dv_xname, 621 dev->dv_parent->dv_xname)); 622 return EBUSY; 623 } 624 625 switch (cmd) { 626 case LPTGMODE: 627 switch (ppbus_get_mode(dev->dv_parent)) { 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(dev->dv_parent, val, 0); 682 683 break; 684 685 case LPTGFLAGS: 686 fl = 0; 687 688 /* DMA */ 689 error = ppbus_read_ivar(dev->dv_parent, 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(dev->dv_parent, PPBUS_IVAR_IEEE, &val); 697 if (error) 698 break; 699 if (val) 700 fl |= LPT_IEEE; 701 702 /* interrupts */ 703 error = ppbus_read_ivar(dev->dv_parent, 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(dev->dv_parent, PPBUS_IVAR_DMA, &val); 721 if (error) 722 break; 723 724 /* IEEE mode negotiation */ 725 val = (fl & LPT_IEEE); 726 error = ppbus_write_ivar(dev->dv_parent, PPBUS_IVAR_IEEE, &val); 727 if (error) 728 break; 729 730 /* interrupts */ 731 val = (fl & LPT_INTR); 732 error = ppbus_write_ivar(dev->dv_parent, 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