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

Cache object: 24a7ba0d6b01bce36856cf663e67add4


[ 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.