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 /*
    2  * Copyright (c) 1990 William F. Jolitz, TeleMuse
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This software is a component of "386BSD" developed by
   16  *      William F. Jolitz, TeleMuse.
   17  * 4. Neither the name of the developer nor the name "386BSD"
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
   22  * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
   23  * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
   24  * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
   25  * NOT MAKE USE OF THIS WORK.
   26  *
   27  * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
   28  * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
   29  * REFERENCES SUCH AS THE  "PORTING UNIX TO THE 386" SERIES
   30  * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
   31  * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
   32  * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
   33  * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
   34  * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
   35  *
   36  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
   37  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   39  * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPER BE LIABLE
   40  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   41  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   42  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   44  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   45  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   46  * SUCH DAMAGE.
   47  *
   48  *      from: unknown origin, 386BSD 0.1
   49  *      From Id: lpt.c,v 1.55.2.1 1996/11/12 09:08:38 phk Exp
   50  *      From Id: nlpt.c,v 1.14 1999/02/08 13:55:43 des Exp
   51  * $FreeBSD$
   52  */
   53 
   54 /*
   55  * Device Driver for AT parallel printer port
   56  * Written by William Jolitz 12/18/90
   57  */
   58 
   59 /*
   60  * Updated for ppbus by Nicolas Souchu
   61  * [Mon Jul 28 1997]
   62  */
   63 
   64 
   65 #ifdef KERNEL
   66 #include "opt_devfs.h"
   67 
   68 #include <sys/param.h>
   69 #include <sys/systm.h>
   70 #include <sys/conf.h>
   71 #include <sys/buf.h>
   72 #include <sys/kernel.h>
   73 #include <sys/uio.h>
   74 #include <sys/syslog.h>
   75 #ifdef DEVFS
   76 #include <sys/devfsext.h>
   77 #endif /*DEVFS*/
   78 #include <sys/malloc.h>
   79 
   80 #include <machine/clock.h>
   81 #include <machine/lpt.h>
   82 #endif /*KERNEL*/
   83 
   84 #include <dev/ppbus/ppbconf.h>
   85 #include <dev/ppbus/ppb_1284.h>
   86 #include <dev/ppbus/lpt.h>
   87 
   88 #include "opt_lpt.h"
   89 
   90 #ifndef LPT_DEBUG
   91 #define lprintf(args)
   92 #else
   93 #define lprintf(args)                                           \
   94                 do {                                            \
   95                         if (lptflag)                            \
   96                                 printf args;                    \
   97                 } while (0)
   98 static int volatile lptflag = 1;
   99 #endif
  100 
  101 #define LPINITRDY       4       /* wait up to 4 seconds for a ready */
  102 #define LPTOUTINITIAL   10      /* initial timeout to wait for ready 1/10 s */
  103 #define LPTOUTMAX       1       /* maximal timeout 1 s */
  104 #define LPPRI           (PZERO+8)
  105 #define BUFSIZE         1024
  106 #define BUFSTATSIZE     32
  107 
  108 #define LPTUNIT(s)      ((s)&0x03)
  109 #define LPTFLAGS(s)     ((s)&0xfc)
  110 
  111 struct lpt_data {
  112         unsigned short lpt_unit;
  113 
  114         struct ppb_device lpt_dev;
  115 
  116         short   sc_state;
  117         /* default case: negative prime, negative ack, handshake strobe,
  118            prime once */
  119         u_char  sc_control;
  120         char    sc_flags;
  121 #define LP_POS_INIT     0x04    /* if we are a postive init signal */
  122 #define LP_POS_ACK      0x08    /* if we are a positive going ack */
  123 #define LP_NO_PRIME     0x10    /* don't prime the printer at all */
  124 #define LP_PRIMEOPEN    0x20    /* prime on every open */
  125 #define LP_AUTOLF       0x40    /* tell printer to do an automatic lf */
  126 #define LP_BYPASS       0x80    /* bypass  printer ready checks */
  127         struct  buf *sc_inbuf;
  128         struct  buf *sc_statbuf;
  129         short   sc_xfercnt ;
  130         char    sc_primed;
  131         char    *sc_cp ;
  132         u_short sc_irq ;        /* IRQ status of port */
  133 #define LP_HAS_IRQ      0x01    /* we have an irq available */
  134 #define LP_USE_IRQ      0x02    /* we are using our irq */
  135 #define LP_ENABLE_IRQ   0x04    /* enable IRQ on open */
  136 #define LP_ENABLE_EXT   0x10    /* we shall use advanced mode when possible */
  137         u_char  sc_backoff ;    /* time to call lptout() again */
  138 
  139 #ifdef DEVFS
  140         void    *devfs_token;
  141         void    *devfs_token_ctl;
  142 #endif
  143 };
  144 
  145 static int      nlpt = 0;
  146 #define MAXLPT  8                       /* XXX not much better! */
  147 static struct lpt_data *lptdata[MAXLPT];
  148 
  149 #define LPT_NAME        "lpt"           /* our official name */
  150 
  151 static timeout_t lptout;
  152 static int      lpt_port_test(struct lpt_data *sc, u_char data, u_char mask);
  153 static int      lpt_detect(struct lpt_data *sc);
  154 
  155 /*
  156  * Make ourselves visible as a ppbus driver
  157  */
  158 
  159 static struct ppb_device        *lptprobe(struct ppb_data *ppb);
  160 static int                      lptattach(struct ppb_device *dev);
  161 static void                     lptintr(int unit);
  162 static void                     lpt_drvinit(void *unused);
  163 
  164 static void                     lpt_intr(int unit);     /* without spls */
  165 
  166 #ifdef KERNEL
  167 
  168 static struct ppb_driver lptdriver = {
  169     lptprobe, lptattach, LPT_NAME
  170 };
  171 DATA_SET(ppbdriver_set, lptdriver);
  172 
  173 #endif /* KERNEL */
  174 
  175 /* bits for state */
  176 #define OPEN            (1<<0)  /* device is open */
  177 #define ASLP            (1<<1)  /* awaiting draining of printer */
  178 #define EERROR          (1<<2)  /* error was received from printer */
  179 #define OBUSY           (1<<3)  /* printer is busy doing output */
  180 #define LPTOUT          (1<<4)  /* timeout while not selected */
  181 #define TOUT            (1<<5)  /* timeout while not selected */
  182 #define LPTINIT         (1<<6)  /* waiting to initialize for open */
  183 #define INTERRUPTED     (1<<7)  /* write call was interrupted */
  184 
  185 #define HAVEBUS         (1<<8)  /* the driver owns the bus */
  186 
  187 
  188 /* status masks to interrogate printer status */
  189 #define RDY_MASK        (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)     /* ready ? */
  190 #define LP_READY        (LPS_SEL|LPS_NBSY|LPS_NERR)
  191 
  192 /* Printer Ready condition  - from lpa.c */
  193 /* Only used in polling code */
  194 #define LPS_INVERT      (LPS_NBSY | LPS_NACK |           LPS_SEL | LPS_NERR)
  195 #define LPS_MASK        (LPS_NBSY | LPS_NACK | LPS_OUT | LPS_SEL | LPS_NERR)
  196 #define NOT_READY(lpt)  ((ppb_rstr(&(lpt)->lpt_dev)^LPS_INVERT)&LPS_MASK)
  197 
  198 #define MAX_SLEEP       (hz*5)  /* Timeout while waiting for device ready */
  199 #define MAX_SPIN        20      /* Max delay for device ready in usecs */
  200 
  201 
  202 static  d_open_t        lptopen;
  203 static  d_close_t       lptclose;
  204 static  d_write_t       lptwrite;
  205 static  d_read_t        lptread;
  206 static  d_ioctl_t       lptioctl;
  207 
  208 #define CDEV_MAJOR 16
  209 static struct cdevsw lpt_cdevsw = 
  210         { lptopen,      lptclose,       lptread,        lptwrite,       /*16*/
  211           lptioctl,     nullstop,       nullreset,      nodevtotty,     /* lpt */
  212           seltrue,      nommap,         nostrat,        LPT_NAME,       NULL,   -1 };
  213 
  214 static int
  215 lpt_request_ppbus(struct lpt_data *sc, int how)
  216 {
  217         int error;
  218 
  219         if (sc->sc_state & HAVEBUS)
  220                 return (0);
  221 
  222         /* we have the bus only if the request succeded */
  223         if ((error = ppb_request_bus(&sc->lpt_dev, how)) == 0)
  224                 sc->sc_state |= HAVEBUS;
  225 
  226         return (error);
  227 }
  228 
  229 static int
  230 lpt_release_ppbus(struct lpt_data *sc)
  231 {
  232         ppb_release_bus(&sc->lpt_dev);
  233         sc->sc_state &= ~HAVEBUS;
  234 
  235         return (0);
  236 }
  237 
  238 /*
  239  * Internal routine to lptprobe to do port tests of one byte value
  240  */
  241 static int
  242 lpt_port_test(struct lpt_data *sc, u_char data, u_char mask)
  243 {
  244         int     temp, timeout;
  245 
  246         data = data & mask;
  247         ppb_wdtr(&sc->lpt_dev, data);
  248         timeout = 10000;
  249         do {
  250                 DELAY(10);
  251                 temp = ppb_rdtr(&sc->lpt_dev) & mask;
  252         }
  253         while (temp != data && --timeout);
  254         lprintf(("out=%x\tin=%x\ttout=%d\n", data, temp, timeout));
  255         return (temp == data);
  256 }
  257 
  258 /*
  259  * Probe simplified by replacing multiple loops with a hardcoded
  260  * test pattern - 1999/02/08 des@freebsd.org
  261  *
  262  * New lpt port probe Geoff Rehmet - Rhodes University - 14/2/94
  263  * Based partially on Rod Grimes' printer probe
  264  *
  265  * Logic:
  266  *      1) If no port address was given, use the bios detected ports
  267  *         and autodetect what ports the printers are on.
  268  *      2) Otherwise, probe the data port at the address given,
  269  *         using the method in Rod Grimes' port probe.
  270  *         (Much code ripped off directly from Rod's probe.)
  271  *
  272  * Comments from Rod's probe:
  273  * Logic:
  274  *      1) You should be able to write to and read back the same value
  275  *         to the data port.  Do an alternating zeros, alternating ones,
  276  *         walking zero, and walking one test to check for stuck bits.
  277  *
  278  *      2) You should be able to write to and read back the same value
  279  *         to the control port lower 5 bits, the upper 3 bits are reserved
  280  *         per the IBM PC technical reference manauls and different boards
  281  *         do different things with them.  Do an alternating zeros, alternating
  282  *         ones, walking zero, and walking one test to check for stuck bits.
  283  *
  284  *         Some printers drag the strobe line down when the are powered off
  285  *         so this bit has been masked out of the control port test.
  286  *
  287  *         XXX Some printers may not like a fast pulse on init or strobe, I
  288  *         don't know at this point, if that becomes a problem these bits
  289  *         should be turned off in the mask byte for the control port test.
  290  *
  291  *         We are finally left with a mask of 0x14, due to some printers
  292  *         being adamant about holding other bits high ........
  293  *
  294  *         Before probing the control port, we write a 0 to the data port -
  295  *         If not, some printers chuck out garbage when the strobe line
  296  *         gets toggled.
  297  *
  298  *      3) Set the data and control ports to a value of 0
  299  *
  300  *      This probe routine has been tested on Epson Lx-800, HP LJ3P,
  301  *      Epson FX-1170 and C.Itoh 8510RM
  302  *      printers.
  303  *      Quick exit on fail added.
  304  */
  305 static int
  306 lpt_detect(struct lpt_data *sc)
  307 {
  308         static u_char   testbyte[18] = {
  309                 0x55,                   /* alternating zeros */
  310                 0xaa,                   /* alternating ones */
  311                 0xfe, 0xfd, 0xfb, 0xf7,
  312                 0xef, 0xdf, 0xbf, 0x7f, /* walking zero */
  313                 0x01, 0x02, 0x04, 0x08,
  314                 0x10, 0x20, 0x40, 0x80  /* walking one */
  315         };
  316         int             i, error, status;
  317 
  318         status = 1;                             /* assume success */
  319 
  320         if ((error = lpt_request_ppbus(sc, PPB_DONTWAIT))) {
  321                 printf(LPT_NAME ": cannot alloc ppbus (%d)!\n", error);
  322                 status = 0;
  323                 goto end_probe;
  324         }
  325 
  326         for (i = 0; i < 18 && status; i++)
  327                 if (!lpt_port_test(sc, testbyte[i], 0xff)) {
  328                         status = 0;
  329                         goto end_probe;
  330                 }
  331 
  332 end_probe:
  333         /* write 0's to control and data ports */
  334         ppb_wdtr(&sc->lpt_dev, 0);
  335         ppb_wctr(&sc->lpt_dev, 0);
  336 
  337         lpt_release_ppbus(sc);
  338 
  339         return (status);
  340 }
  341 
  342 /*
  343  * lptprobe()
  344  */
  345 static struct ppb_device *
  346 lptprobe(struct ppb_data *ppb)
  347 {
  348         struct lpt_data *sc;
  349 
  350         sc = (struct lpt_data *) malloc(sizeof(struct lpt_data),
  351                                                         M_TEMP, M_NOWAIT);
  352         if (!sc) {
  353                 printf(LPT_NAME ": cannot malloc!\n");
  354                 return (0);
  355         }
  356         bzero(sc, sizeof(struct lpt_data));
  357 
  358         lptdata[nlpt] = sc;
  359 
  360         /*
  361          * lpt dependent initialisation.
  362          */
  363         sc->lpt_unit = nlpt;
  364 
  365         /*
  366          * ppbus dependent initialisation.
  367          */
  368         sc->lpt_dev.id_unit = sc->lpt_unit;
  369         sc->lpt_dev.name = lptdriver.name;
  370         sc->lpt_dev.ppb = ppb;
  371         sc->lpt_dev.intr = lptintr;
  372 
  373         /*
  374          * Now, try to detect the printer.
  375          */
  376         if (!lpt_detect(sc)) {
  377                 free(sc, M_TEMP);
  378                 return (0);
  379         }
  380 
  381         /* Ok, go to next device on next probe */
  382         nlpt ++;
  383 
  384         return (&sc->lpt_dev);
  385 }
  386 
  387 static int
  388 lptattach(struct ppb_device *dev)
  389 {
  390         struct lpt_data *sc = lptdata[dev->id_unit];
  391         int error;
  392 
  393         /*
  394          * Report ourselves
  395          */
  396         printf(LPT_NAME "%d: <generic printer> on ppbus %d\n",
  397                dev->id_unit, dev->ppb->ppb_link->adapter_unit);
  398 
  399         sc->sc_primed = 0;      /* not primed yet */
  400 
  401         if ((error = lpt_request_ppbus(sc, PPB_DONTWAIT))) {
  402                 printf(LPT_NAME ": cannot alloc ppbus (%d)!\n", error);
  403                 return (0);
  404         }
  405 
  406         ppb_wctr(&sc->lpt_dev, LPC_NINIT);
  407 
  408         /* check if we can use interrupt, should be done by ppc stuff */
  409         lprintf(("oldirq %x\n", sc->sc_irq));
  410         if (ppb_get_irq(&sc->lpt_dev)) {
  411                 sc->sc_irq = LP_HAS_IRQ | LP_USE_IRQ | LP_ENABLE_IRQ;
  412                 printf(LPT_NAME "%d: Interrupt-driven port\n", dev->id_unit);
  413         } else {
  414                 sc->sc_irq = 0;
  415                 lprintf((LPT_NAME "%d: Polled port\n", dev->id_unit));
  416         }
  417         lprintf(("irq %x\n", sc->sc_irq));
  418 
  419         lpt_release_ppbus(sc);
  420 
  421 #ifdef DEVFS
  422         sc->devfs_token = devfs_add_devswf(&lpt_cdevsw,
  423                 dev->id_unit, DV_CHR,
  424                 UID_ROOT, GID_WHEEL, 0600, LPT_NAME "%d", dev->id_unit);
  425         sc->devfs_token_ctl = devfs_add_devswf(&lpt_cdevsw,
  426                 dev->id_unit | LP_BYPASS, DV_CHR,
  427                 UID_ROOT, GID_WHEEL, 0600, LPT_NAME "%d.ctl", dev->id_unit);
  428 #endif
  429 
  430         return (1);
  431 }
  432 
  433 static void
  434 lptout(void *arg)
  435 {
  436         struct lpt_data *sc = arg;
  437         int pl;
  438 
  439         lprintf(("T %x ", ppb_rstr(&sc->lpt_dev)));
  440         if (sc->sc_state & OPEN) {
  441                 sc->sc_backoff++;
  442                 if (sc->sc_backoff > hz/LPTOUTMAX)
  443                         sc->sc_backoff = sc->sc_backoff > hz/LPTOUTMAX;
  444                 timeout(lptout, (caddr_t)sc, sc->sc_backoff);
  445         } else
  446                 sc->sc_state &= ~TOUT;
  447 
  448         if (sc->sc_state & EERROR)
  449                 sc->sc_state &= ~EERROR;
  450 
  451         /*
  452          * Avoid possible hangs do to missed interrupts
  453          */
  454         if (sc->sc_xfercnt) {
  455                 pl = spltty();
  456                 lpt_intr(sc->lpt_unit);
  457                 splx(pl);
  458         } else {
  459                 sc->sc_state &= ~OBUSY;
  460                 wakeup((caddr_t)sc);
  461         }
  462 }
  463 
  464 /*
  465  * lptopen -- reset the printer, then wait until it's selected and not busy.
  466  *      If LP_BYPASS flag is selected, then we do not try to select the
  467  *      printer -- this is just used for passing ioctls.
  468  */
  469 
  470 static  int
  471 lptopen(dev_t dev, int flags, int fmt, struct proc *p)
  472 {
  473         struct lpt_data *sc;
  474 
  475         int s;
  476         int trys, err;
  477         u_int unit = LPTUNIT(minor(dev));
  478 
  479         if ((unit >= nlpt))
  480                 return (ENXIO);
  481 
  482         sc = lptdata[unit];
  483 
  484         if (sc->sc_state) {
  485                 lprintf((LPT_NAME ": still open %x\n", sc->sc_state));
  486                 return(EBUSY);
  487         } else
  488                 sc->sc_state |= LPTINIT;
  489 
  490         sc->sc_flags = LPTFLAGS(minor(dev));
  491 
  492         /* Check for open with BYPASS flag set. */
  493         if (sc->sc_flags & LP_BYPASS) {
  494                 sc->sc_state = OPEN;
  495                 return(0);
  496         }
  497 
  498         /* request the ppbus only if we don't have it already */
  499         if ((err = lpt_request_ppbus(sc, PPB_WAIT|PPB_INTR)) != 0)
  500                 return (err);
  501 
  502         s = spltty();
  503         lprintf((LPT_NAME " flags 0x%x\n", sc->sc_flags));
  504 
  505         /* set IRQ status according to ENABLE_IRQ flag */
  506         if (sc->sc_irq & LP_ENABLE_IRQ)
  507                 sc->sc_irq |= LP_USE_IRQ;
  508         else
  509                 sc->sc_irq &= ~LP_USE_IRQ;
  510 
  511         /* init printer */
  512         if ((sc->sc_flags & LP_NO_PRIME) == 0) {
  513                 if((sc->sc_flags & LP_PRIMEOPEN) || sc->sc_primed == 0) {
  514                         ppb_wctr(&sc->lpt_dev, 0);
  515                         sc->sc_primed++;
  516                         DELAY(500);
  517                 }
  518         }
  519 
  520         ppb_wctr(&sc->lpt_dev, LPC_SEL|LPC_NINIT);
  521 
  522         /* wait till ready (printer running diagnostics) */
  523         trys = 0;
  524         do {
  525                 /* ran out of waiting for the printer */
  526                 if (trys++ >= LPINITRDY*4) {
  527                         splx(s);
  528                         sc->sc_state = 0;
  529                         lprintf(("status %x\n", ppb_rstr(&sc->lpt_dev)));
  530 
  531                         lpt_release_ppbus(sc);
  532                         return (EBUSY);
  533                 }
  534 
  535                 /* wait 1/4 second, give up if we get a signal */
  536                 if (tsleep((caddr_t)sc, LPPRI|PCATCH, "lptinit", hz/4) !=
  537                     EWOULDBLOCK) {
  538                         sc->sc_state = 0;
  539                         splx(s);
  540 
  541                         lpt_release_ppbus(sc);
  542                         return (EBUSY);
  543                 }
  544 
  545                 /* is printer online and ready for output */
  546         } while ((ppb_rstr(&sc->lpt_dev) &
  547                         (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)) !=
  548                                         (LPS_SEL|LPS_NBSY|LPS_NERR));
  549 
  550         sc->sc_control = LPC_SEL|LPC_NINIT;
  551         if (sc->sc_flags & LP_AUTOLF)
  552                 sc->sc_control |= LPC_AUTOL;
  553 
  554         /* enable interrupt if interrupt-driven */
  555         if (sc->sc_irq & LP_USE_IRQ)
  556                 sc->sc_control |= LPC_ENA;
  557 
  558         ppb_wctr(&sc->lpt_dev, sc->sc_control);
  559 
  560         sc->sc_state = OPEN;
  561         sc->sc_inbuf = geteblk(BUFSIZE);
  562         sc->sc_statbuf = geteblk(BUFSTATSIZE);
  563         sc->sc_xfercnt = 0;
  564         splx(s);
  565 
  566         /* release the ppbus */
  567         lpt_release_ppbus(sc);
  568 
  569         /* only use timeout if using interrupt */
  570         lprintf(("irq %x\n", sc->sc_irq));
  571         if (sc->sc_irq & LP_USE_IRQ) {
  572                 sc->sc_state |= TOUT;
  573                 timeout(lptout, (caddr_t)sc,
  574                          (sc->sc_backoff = hz/LPTOUTINITIAL));
  575         }
  576 
  577         lprintf(("opened.\n"));
  578         return(0);
  579 }
  580 
  581 /*
  582  * lptclose -- close the device, free the local line buffer.
  583  *
  584  * Check for interrupted write call added.
  585  */
  586 
  587 static  int
  588 lptclose(dev_t dev, int flags, int fmt, struct proc *p)
  589 {
  590         struct lpt_data *sc = lptdata[LPTUNIT(minor(dev))];
  591         int err;
  592 
  593         if(sc->sc_flags & LP_BYPASS)
  594                 goto end_close;
  595 
  596         if ((err = lpt_request_ppbus(sc, PPB_WAIT|PPB_INTR)) != 0)
  597                 return (err);
  598 
  599         sc->sc_state &= ~OPEN;
  600 
  601         /* if the last write was interrupted, don't complete it */
  602         if((!(sc->sc_state  & INTERRUPTED)) && (sc->sc_irq & LP_USE_IRQ))
  603                 while ((ppb_rstr(&sc->lpt_dev) &
  604                         (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)) !=
  605                         (LPS_SEL|LPS_NBSY|LPS_NERR) || sc->sc_xfercnt)
  606                         /* wait 1/4 second, give up if we get a signal */
  607                         if (tsleep((caddr_t)sc, LPPRI|PCATCH,
  608                                 "lpclose", hz) != EWOULDBLOCK)
  609                                 break;
  610 
  611         ppb_wctr(&sc->lpt_dev, LPC_NINIT);
  612         brelse(sc->sc_inbuf);
  613         brelse(sc->sc_statbuf);
  614 
  615 end_close:
  616         /* release the bus anyway */
  617         lpt_release_ppbus(sc);
  618 
  619         sc->sc_state = 0;
  620         sc->sc_xfercnt = 0;
  621         lprintf(("closed.\n"));
  622         return(0);
  623 }
  624 
  625 /*
  626  * lpt_pushbytes()
  627  *      Workhorse for actually spinning and writing bytes to printer
  628  *      Derived from lpa.c
  629  *      Originally by ?
  630  *
  631  *      This code is only used when we are polling the port
  632  */
  633 static int
  634 lpt_pushbytes(struct lpt_data *sc)
  635 {
  636         int spin, err, tic;
  637         char ch;
  638 
  639         lprintf(("p"));
  640         /* loop for every character .. */
  641         while (sc->sc_xfercnt > 0) {
  642                 /* printer data */
  643                 ch = *(sc->sc_cp);
  644                 sc->sc_cp++;
  645                 sc->sc_xfercnt--;
  646 
  647                 /*
  648                  * Wait for printer ready.
  649                  * Loop 20 usecs testing BUSY bit, then sleep
  650                  * for exponentially increasing timeout. (vak)
  651                  */
  652                 for (spin = 0; NOT_READY(sc) && spin < MAX_SPIN; ++spin)
  653                         DELAY(1);       /* XXX delay is NOT this accurate! */
  654                 if (spin >= MAX_SPIN) {
  655                         tic = 0;
  656                         while (NOT_READY(sc)) {
  657                                 /*
  658                                  * Now sleep, every cycle a
  659                                  * little longer ..
  660                                  */
  661                                 tic = tic + tic + 1;
  662                                 /*
  663                                  * But no more than 10 seconds. (vak)
  664                                  */
  665                                 if (tic > MAX_SLEEP)
  666                                         tic = MAX_SLEEP;
  667                                 err = tsleep((caddr_t)sc, LPPRI,
  668                                         LPT_NAME "poll", tic);
  669                                 if (err != EWOULDBLOCK) {
  670                                         return (err);
  671                                 }
  672                         }
  673                 }
  674 
  675                 /* output data */
  676                 ppb_wdtr(&sc->lpt_dev, ch);
  677                 /* strobe */
  678                 ppb_wctr(&sc->lpt_dev, sc->sc_control|LPC_STB);
  679                 ppb_wctr(&sc->lpt_dev, sc->sc_control);
  680 
  681         }
  682         return(0);
  683 }
  684 
  685 /*
  686  * lptread --retrieve printer status in IEEE1284 NIBBLE mode
  687  */
  688 
  689 static int
  690 lptread(dev_t dev, struct uio *uio, int ioflag)
  691 {
  692         struct lpt_data *sc = lptdata[LPTUNIT(minor(dev))];
  693         int error = 0, len;
  694 
  695         if (sc->sc_flags & LP_BYPASS) {
  696                 /* we can't do reads in bypass mode */
  697                 return (EPERM);
  698         }
  699 
  700         if ((error = ppb_1284_negociate(&sc->lpt_dev, PPB_NIBBLE, 0)))
  701                 return (error);
  702 
  703         /* read data in an other buffer, read/write may be simultaneous */
  704         len = 0;
  705         while (uio->uio_resid) {
  706                 if ((error = ppb_1284_read(&sc->lpt_dev, PPB_NIBBLE,
  707                                 sc->sc_statbuf->b_data, min(BUFSTATSIZE,
  708                                 uio->uio_resid), &len))) {
  709                         goto error;
  710                 }
  711 
  712                 if (!len)
  713                         goto error;             /* no more data */
  714 
  715                 if ((error = uiomove(sc->sc_statbuf->b_data, len, uio)))
  716                         goto error;
  717         }
  718 
  719 error:
  720         ppb_1284_terminate(&sc->lpt_dev);
  721         return (error);
  722 }
  723 
  724 /*
  725  * lptwrite --copy a line from user space to a local buffer, then call
  726  * putc to get the chars moved to the output queue.
  727  *
  728  * Flagging of interrupted write added.
  729  */
  730 
  731 static  int
  732 lptwrite(dev_t dev, struct uio *uio, int ioflag)
  733 {
  734         register unsigned n;
  735         int pl, err;
  736         u_int   unit = LPTUNIT(minor(dev));
  737         struct lpt_data *sc = lptdata[LPTUNIT(minor(dev))];
  738 
  739         if(sc->sc_flags & LP_BYPASS) {
  740                 /* we can't do writes in bypass mode */
  741                 return(EPERM);
  742         }
  743 
  744         /* request the ppbus only if we don't have it already */
  745         if ((err = lpt_request_ppbus(sc, PPB_WAIT|PPB_INTR)) != 0)
  746                 return (err);
  747 
  748         sc->sc_state &= ~INTERRUPTED;
  749         while ((n = min(BUFSIZE, uio->uio_resid)) != 0) {
  750                 sc->sc_cp = sc->sc_inbuf->b_data ;
  751                 uiomove(sc->sc_cp, n, uio);
  752                 sc->sc_xfercnt = n ;
  753 
  754                 if (sc->sc_irq & LP_ENABLE_EXT) {
  755                         /* try any extended mode */
  756                         err = ppb_write(&sc->lpt_dev, sc->sc_cp,
  757                                                         sc->sc_xfercnt, 0);
  758                         switch (err) {
  759                         case 0:
  760                                 /* if not all data was sent, we could rely
  761                                  * on polling for the last bytes */
  762                                 sc->sc_xfercnt = 0;
  763                                 break;
  764                         case EINTR:
  765                                 sc->sc_state |= INTERRUPTED;    
  766                                 return(err);
  767                         case EINVAL:
  768                                 /* advanced mode not avail */
  769                                 log(LOG_NOTICE, LPT_NAME "%d: advanced mode not avail, polling\n", unit);
  770                                 break;
  771                         default:
  772                                 return(err);
  773                         }
  774                 } else while ((sc->sc_xfercnt > 0)&&(sc->sc_irq & LP_USE_IRQ)) {
  775                         lprintf(("i"));
  776                         /* if the printer is ready for a char, */
  777                         /* give it one */
  778                         if ((sc->sc_state & OBUSY) == 0){
  779                                 lprintf(("\nC %d. ", sc->sc_xfercnt));
  780                                 pl = spltty();
  781                                 lpt_intr(sc->lpt_unit);
  782                                 (void) splx(pl);
  783                         }
  784                         lprintf(("W "));
  785                         if (sc->sc_state & OBUSY)
  786                                 if ((err = tsleep((caddr_t)sc,
  787                                          LPPRI|PCATCH, LPT_NAME "write", 0))) {
  788                                         sc->sc_state |= INTERRUPTED;
  789                                         return(err);
  790                                 }
  791                 }
  792 
  793                 /* check to see if we must do a polled write */
  794                 if(!(sc->sc_irq & LP_USE_IRQ) && (sc->sc_xfercnt)) {
  795                         lprintf(("p"));
  796 
  797                         err = lpt_pushbytes(sc);
  798 
  799                         if (err)
  800                                 return(err);
  801                 }
  802         }
  803 
  804         /* we have not been interrupted, release the ppbus */
  805         lpt_release_ppbus(sc);
  806 
  807         return(0);
  808 }
  809 
  810 /*
  811  * lpt_intr -- handle printer interrupts which occur when the printer is
  812  * ready to accept another char.
  813  *
  814  * do checking for interrupted write call.
  815  */
  816 
  817 static void
  818 lpt_intr(int unit)
  819 {
  820         struct lpt_data *sc = lptdata[unit];
  821         int sts;
  822         int i;
  823         
  824         /* we must own the bus to use it */
  825         if ((sc->sc_state & HAVEBUS) == 0)
  826                 return;
  827 
  828         /*
  829          * Is printer online and ready for output?
  830          *
  831          * Avoid falling back to lptout() too quickly.  First spin-loop
  832          * to see if the printer will become ready ``really soon now''.
  833          */
  834         for (i = 0; i < 100 &&
  835              ((sts=ppb_rstr(&sc->lpt_dev)) & RDY_MASK) != LP_READY; i++) ;
  836 
  837         if ((sts & RDY_MASK) == LP_READY) {
  838                 sc->sc_state = (sc->sc_state | OBUSY) & ~EERROR;
  839                 sc->sc_backoff = hz/LPTOUTINITIAL;
  840 
  841                 if (sc->sc_xfercnt) {
  842                         /* send char */
  843                         /*lprintf(("%x ", *sc->sc_cp)); */
  844                         ppb_wdtr(&sc->lpt_dev, *sc->sc_cp++) ;
  845                         ppb_wctr(&sc->lpt_dev, sc->sc_control|LPC_STB);
  846                         /* DELAY(X) */
  847                         ppb_wctr(&sc->lpt_dev, sc->sc_control);
  848 
  849                         /* any more data for printer */
  850                         if(--(sc->sc_xfercnt) > 0) return;
  851                 }
  852 
  853                 /*
  854                  * No more data waiting for printer.
  855                  * Wakeup is not done if write call was interrupted.
  856                  */
  857                 sc->sc_state &= ~OBUSY;
  858 
  859                 if(!(sc->sc_state & INTERRUPTED))
  860                         wakeup((caddr_t)sc);
  861                 lprintf(("w "));
  862                 return;
  863         } else  {       /* check for error */
  864                 if(((sts & (LPS_NERR | LPS_OUT) ) != LPS_NERR) &&
  865                                 (sc->sc_state & OPEN))
  866                         sc->sc_state |= EERROR;
  867                 /* lptout() will jump in and try to restart. */
  868         }
  869         lprintf(("sts %x ", sts));
  870 }
  871 
  872 static void
  873 lptintr(int unit)
  874 {
  875         /* call the interrupt at required spl level */
  876         int s = spltty();
  877 
  878         lpt_intr(unit);
  879 
  880         splx(s);
  881         return;
  882 }
  883 
  884 static  int
  885 lptioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
  886 {
  887         int     error = 0;
  888         struct  lpt_data *sc;
  889         u_int   unit = LPTUNIT(minor(dev));
  890         u_char  old_sc_irq;     /* old printer IRQ status */
  891 
  892         sc = lptdata[unit];
  893 
  894         switch (cmd) {
  895         case LPT_IRQ :
  896                 if(sc->sc_irq & LP_HAS_IRQ) {
  897                         /*
  898                          * NOTE:
  899                          * If the IRQ status is changed,
  900                          * this will only be visible on the
  901                          * next open.
  902                          *
  903                          * If interrupt status changes,
  904                          * this gets syslog'd.
  905                          */
  906                         old_sc_irq = sc->sc_irq;
  907                         switch(*(int*)data) {
  908                         case 0:
  909                                 sc->sc_irq &= (~LP_ENABLE_IRQ);
  910                                 break;
  911                         case 1:
  912                                 sc->sc_irq &= (~LP_ENABLE_EXT);
  913                                 sc->sc_irq |= LP_ENABLE_IRQ;
  914                                 break;
  915                         case 2:
  916                                 /* classic irq based transfer and advanced
  917                                  * modes are in conflict
  918                                  */
  919                                 sc->sc_irq &= (~LP_ENABLE_IRQ);
  920                                 sc->sc_irq |= LP_ENABLE_EXT;
  921                                 break;
  922                         case 3:
  923                                 sc->sc_irq &= (~LP_ENABLE_EXT);
  924                                 break;
  925                         default:
  926                                 break;
  927                         }
  928                                 
  929                         if (old_sc_irq != sc->sc_irq )
  930                                 log(LOG_NOTICE, LPT_NAME "%d: switched to %s %s mode\n",
  931                                         unit,
  932                                         (sc->sc_irq & LP_ENABLE_IRQ)?
  933                                         "interrupt-driven":"polled",
  934                                         (sc->sc_irq & LP_ENABLE_EXT)?
  935                                         "extended":"standard");
  936                 } else /* polled port */
  937                         error = EOPNOTSUPP;
  938                 break;
  939         default:
  940                 error = ENODEV;
  941         }
  942 
  943         return(error);
  944 }
  945 
  946 static lpt_devsw_installed = 0;
  947 
  948 static void
  949 lpt_drvinit(void *unused)
  950 {
  951         dev_t dev;
  952 
  953         if( ! lpt_devsw_installed ) {
  954                 dev = makedev(CDEV_MAJOR, 0);
  955                 cdevsw_add(&dev,&lpt_cdevsw, NULL);
  956                 lpt_devsw_installed = 1;
  957         }
  958 }
  959 
  960 SYSINIT(lptdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,lpt_drvinit,NULL)

Cache object: 4f2167b6adc2141c9d94725c57e2d87b


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