The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ppbus/lpt.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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, "\2\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 

Cache object: 4ceab200e8b108bcdddd5b90b4b4f336


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.