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/i386/isa/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  * $FreeBSD: src/sys/i386/isa/lpt.c,v 1.55.2.4 1999/09/05 08:13:10 peter Exp $
   50  */
   51 
   52 /*
   53  * Device Driver for AT parallel printer port
   54  * Written by William Jolitz 12/18/90
   55  */
   56 
   57 /*
   58  * Parallel port TCP/IP interfaces added.  I looked at the driver from
   59  * MACH but this is a complete rewrite, and btw. incompatible, and it
   60  * should perform better too.  I have never run the MACH driver though.
   61  *
   62  * This driver sends two bytes (0x08, 0x00) in front of each packet,
   63  * to allow us to distinguish another format later.
   64  *
   65  * Now added an Linux/Crynwr compatibility mode which is enabled using
   66  * IF_LINK0 - Tim Wilkinson.
   67  *
   68  * TODO:
   69  *    Make HDLC/PPP mode, use IF_LLC1 to enable.
   70  *
   71  * Connect the two computers using a Laplink parallel cable to use this
   72  * feature:
   73  *
   74  *      +----------------------------------------+
   75  *      |A-name A-End   B-End   Descr.  Port/Bit |
   76  *      +----------------------------------------+
   77  *      |DATA0  2       15      Data    0/0x01   |
   78  *      |-ERROR 15      2               1/0x08   |
   79  *      +----------------------------------------+
   80  *      |DATA1  3       13      Data    0/0x02   |
   81  *      |+SLCT  13      3               1/0x10   |
   82  *      +----------------------------------------+
   83  *      |DATA2  4       12      Data    0/0x04   |
   84  *      |+PE    12      4               1/0x20   |
   85  *      +----------------------------------------+
   86  *      |DATA3  5       10      Strobe  0/0x08   |
   87  *      |-ACK   10      5               1/0x40   |
   88  *      +----------------------------------------+
   89  *      |DATA4  6       11      Data    0/0x10   |
   90  *      |BUSY   11      6               1/~0x80  |
   91  *      +----------------------------------------+
   92  *      |GND    18-25   18-25   GND     -        |
   93  *      +----------------------------------------+
   94  *
   95  * Expect transfer-rates up to 75 kbyte/sec.
   96  *
   97  * If GCC could correctly grok
   98  *      register int port asm("edx")
   99  * the code would be cleaner
  100  *
  101  * Poul-Henning Kamp <phk@freebsd.org>
  102  */
  103 
  104 #include "lpt.h"
  105 
  106 #include <sys/param.h>
  107 #include <sys/systm.h>
  108 #include <sys/conf.h>
  109 #include <sys/proc.h>
  110 #include <sys/buf.h>
  111 #include <sys/kernel.h>
  112 #include <sys/ioctl.h>
  113 #include <sys/uio.h>
  114 #include <sys/syslog.h>
  115 #ifdef DEVFS
  116 #include <sys/devfsext.h>
  117 #endif /*DEVFS*/
  118 
  119 #include <machine/clock.h>
  120 #include <machine/lpt.h>
  121 
  122 #include <vm/vm.h>
  123 #include <vm/vm_param.h>
  124 #include <vm/pmap.h>
  125 
  126 #include <i386/isa/isa.h>
  127 #include <i386/isa/isa_device.h>
  128 #include <i386/isa/lptreg.h>
  129 
  130 #ifdef INET
  131 #include <sys/mbuf.h>
  132 #include <sys/socket.h>
  133 #include <net/if.h>
  134 #include <net/if_types.h>
  135 #include <net/netisr.h>
  136 #include <net/route.h>
  137 #include <netinet/in.h>
  138 #include <netinet/in_systm.h>
  139 #include <netinet/in_var.h>
  140 #include <netinet/ip.h>
  141 #include <netinet/if_ether.h>
  142 #include "bpfilter.h"
  143 #if NBPFILTER > 0
  144 #include <net/bpf.h>
  145 #include <net/bpfdesc.h>
  146 #endif
  147 #endif /* INET */
  148 
  149 
  150 #define LPINITRDY       4       /* wait up to 4 seconds for a ready */
  151 #define LPTOUTINITIAL   10      /* initial timeout to wait for ready 1/10 s */
  152 #define LPTOUTMAX       1       /* maximal timeout 1 s */
  153 #define LPPRI           (PZERO+8)
  154 #define BUFSIZE         1024
  155 
  156 #ifdef INET
  157 #ifndef LPMTU                   /* MTU for the lp# interfaces */
  158 #define LPMTU   1500
  159 #endif
  160 
  161 #ifndef LPMAXSPIN1              /* DELAY factor for the lp# interfaces */
  162 #define LPMAXSPIN1      8000   /* Spinning for remote intr to happen */
  163 #endif
  164 
  165 #ifndef LPMAXSPIN2              /* DELAY factor for the lp# interfaces */
  166 #define LPMAXSPIN2      500     /* Spinning for remote handshake to happen */
  167 #endif
  168 
  169 #ifndef LPMAXERRS               /* Max errors before !RUNNING */
  170 #define LPMAXERRS       100
  171 #endif
  172 
  173 #define CLPIPHDRLEN     14      /* We send dummy ethernet addresses (two) + packet type in front of packet */
  174 #define CLPIP_SHAKE     0x80    /* This bit toggles between nibble reception */
  175 #define MLPIPHDRLEN     CLPIPHDRLEN
  176 
  177 #define LPIPHDRLEN      2       /* We send 0x08, 0x00 in front of packet */
  178 #define LPIP_SHAKE      0x40    /* This bit toggles between nibble reception */
  179 #if !defined(MLPIPHDRLEN) || LPIPHDRLEN > MLPIPHDRLEN
  180 #define MLPIPHDRLEN     LPIPHDRLEN
  181 #endif
  182 
  183 #define LPIPTBLSIZE     256     /* Size of octet translation table */
  184 
  185 #endif /* INET */
  186 
  187 /* BIOS printer list - used by BIOS probe*/
  188 #define BIOS_LPT_PORTS  0x408
  189 #define BIOS_PORTS      (short *)(KERNBASE+BIOS_LPT_PORTS)
  190 #define BIOS_MAX_LPT    4
  191 
  192 
  193 #ifndef DEBUG
  194 #define lprintf (void)
  195 #else
  196 #define lprintf         if (lptflag) printf
  197 static int volatile lptflag = 1;
  198 #endif
  199 
  200 #define LPTUNIT(s)      ((s)&0x03)
  201 #define LPTFLAGS(s)     ((s)&0xfc)
  202 
  203 static struct lpt_softc {
  204         int     sc_port;
  205         short   sc_state;
  206         /* default case: negative prime, negative ack, handshake strobe,
  207            prime once */
  208         u_char  sc_control;
  209         char    sc_flags;
  210 #define LP_POS_INIT     0x04    /* if we are a postive init signal */
  211 #define LP_POS_ACK      0x08    /* if we are a positive going ack */
  212 #define LP_NO_PRIME     0x10    /* don't prime the printer at all */
  213 #define LP_PRIMEOPEN    0x20    /* prime on every open */
  214 #define LP_AUTOLF       0x40    /* tell printer to do an automatic lf */
  215 #define LP_BYPASS       0x80    /* bypass  printer ready checks */
  216         struct  buf *sc_inbuf;
  217         short   sc_xfercnt ;
  218         char    sc_primed;
  219         char    *sc_cp ;
  220         u_char  sc_irq ;        /* IRQ status of port */
  221 #define LP_HAS_IRQ      0x01    /* we have an irq available */
  222 #define LP_USE_IRQ      0x02    /* we are using our irq */
  223 #define LP_ENABLE_IRQ   0x04    /* enable IRQ on open */
  224         u_char  sc_backoff ;    /* time to call lptout() again */
  225 
  226 #ifdef INET
  227         struct  ifnet   sc_if;
  228         u_char          *sc_ifbuf;
  229         int             sc_iferrs;
  230 #endif
  231 #ifdef DEVFS
  232         void    *devfs_token;
  233         void    *devfs_token_ctl;
  234 #endif
  235 } lpt_sc[NLPT] ;
  236 
  237 /* bits for state */
  238 #define OPEN            (1<<0)  /* device is open */
  239 #define ASLP            (1<<1)  /* awaiting draining of printer */
  240 #define ERROR           (1<<2)  /* error was received from printer */
  241 #define OBUSY           (1<<3)  /* printer is busy doing output */
  242 #define LPTOUT          (1<<4)  /* timeout while not selected */
  243 #define TOUT            (1<<5)  /* timeout while not selected */
  244 #define INIT            (1<<6)  /* waiting to initialize for open */
  245 #define INTERRUPTED     (1<<7)  /* write call was interrupted */
  246 
  247 
  248 /* status masks to interrogate printer status */
  249 #define RDY_MASK        (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)     /* ready ? */
  250 #define LP_READY        (LPS_SEL|LPS_NBSY|LPS_NERR)
  251 
  252 /* Printer Ready condition  - from lpa.c */
  253 /* Only used in polling code */
  254 #define LPS_INVERT      (LPS_NBSY | LPS_NACK |           LPS_SEL | LPS_NERR)
  255 #define LPS_MASK        (LPS_NBSY | LPS_NACK | LPS_OUT | LPS_SEL | LPS_NERR)
  256 #define NOT_READY(x)    ((inb(x)^LPS_INVERT)&LPS_MASK)
  257 
  258 #define MAX_SLEEP       (hz*5)  /* Timeout while waiting for device ready */
  259 #define MAX_SPIN        20      /* Max delay for device ready in usecs */
  260 
  261 static void     lptout (struct lpt_softc * sc);
  262 static int      lptprobe (struct isa_device *dvp);
  263 static int      lptattach (struct isa_device *isdp);
  264 
  265 #ifdef INET
  266 
  267 /* Tables for the lp# interface */
  268 static u_char *txmith;
  269 #define txmitl (txmith+(1*LPIPTBLSIZE))
  270 #define trecvh (txmith+(2*LPIPTBLSIZE))
  271 #define trecvl (txmith+(3*LPIPTBLSIZE))
  272 
  273 static u_char *ctxmith;
  274 #define ctxmitl (ctxmith+(1*LPIPTBLSIZE))
  275 #define ctrecvh (ctxmith+(2*LPIPTBLSIZE))
  276 #define ctrecvl (ctxmith+(3*LPIPTBLSIZE))
  277 
  278 /* Functions for the lp# interface */
  279 static void lpattach(struct lpt_softc *,int);
  280 static int lpinittables(void);
  281 static int lpioctl(struct ifnet *, int, caddr_t);
  282 static int lpoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
  283         struct rtentry *);
  284 static void lpintr(int);
  285 #endif /* INET */
  286 
  287 struct  isa_driver lptdriver = {
  288         lptprobe, lptattach, "lpt"
  289 };
  290 
  291 static  d_open_t        lptopen;
  292 static  d_close_t       lptclose;
  293 static  d_write_t       lptwrite;
  294 static  d_ioctl_t       lptioctl;
  295 
  296 #define CDEV_MAJOR 16
  297 static struct cdevsw lpt_cdevsw = 
  298         { lptopen,      lptclose,       noread,         lptwrite,       /*16*/
  299           lptioctl,     nullstop,       nullreset,      nodevtotty,/* lpt */
  300           seltrue,      nommap,         nostrat,        "lpt",  NULL,   -1 };
  301 
  302 
  303 /*
  304  * Internal routine to lptprobe to do port tests of one byte value
  305  */
  306 static int
  307 lpt_port_test (int port, u_char data, u_char mask)
  308 {
  309         int     temp, timeout;
  310 
  311         data = data & mask;
  312         outb(port, data);
  313         timeout = 10000;
  314         do {
  315                 DELAY(10);
  316                 temp = inb(port) & mask;
  317         }
  318         while (temp != data && --timeout);
  319         lprintf("Port 0x%x\tout=%x\tin=%x\ttout=%d\n",
  320                 port, data, temp, timeout);
  321         return (temp == data);
  322 }
  323 
  324 /*
  325  * New lpt port probe Geoff Rehmet - Rhodes University - 14/2/94
  326  * Based partially on Rod Grimes' printer probe
  327  *
  328  * Logic:
  329  *      1) If no port address was given, use the bios detected ports
  330  *         and autodetect what ports the printers are on.
  331  *      2) Otherwise, probe the data port at the address given,
  332  *         using the method in Rod Grimes' port probe.
  333  *         (Much code ripped off directly from Rod's probe.)
  334  *
  335  * Comments from Rod's probe:
  336  * Logic:
  337  *      1) You should be able to write to and read back the same value
  338  *         to the data port.  Do an alternating zeros, alternating ones,
  339  *         walking zero, and walking one test to check for stuck bits.
  340  *
  341  *      2) You should be able to write to and read back the same value
  342  *         to the control port lower 5 bits, the upper 3 bits are reserved
  343  *         per the IBM PC technical reference manauls and different boards
  344  *         do different things with them.  Do an alternating zeros, alternating
  345  *         ones, walking zero, and walking one test to check for stuck bits.
  346  *
  347  *         Some printers drag the strobe line down when the are powered off
  348  *         so this bit has been masked out of the control port test.
  349  *
  350  *         XXX Some printers may not like a fast pulse on init or strobe, I
  351  *         don't know at this point, if that becomes a problem these bits
  352  *         should be turned off in the mask byte for the control port test.
  353  *
  354  *         We are finally left with a mask of 0x14, due to some printers
  355  *         being adamant about holding other bits high ........
  356  *
  357  *         Before probing the control port, we write a 0 to the data port -
  358  *         If not, some printers chuck out garbage when the strobe line
  359  *         gets toggled.
  360  *
  361  *      3) Set the data and control ports to a value of 0
  362  *
  363  *      This probe routine has been tested on Epson Lx-800, HP LJ3P,
  364  *      Epson FX-1170 and C.Itoh 8510RM
  365  *      printers.
  366  *      Quick exit on fail added.
  367  */
  368 int
  369 lptprobe(struct isa_device *dvp)
  370 {
  371         int             port;
  372         static short    next_bios_lpt = 0;
  373         int             status;
  374         static u_char   testbyte[18] = {
  375                 0x55,                   /* alternating zeros */
  376                 0xaa,                   /* alternating ones */
  377                 0xfe, 0xfd, 0xfb, 0xf7,
  378                 0xef, 0xdf, 0xbf, 0x7f, /* walking zero */
  379                 0x01, 0x02, 0x04, 0x08,
  380                 0x10, 0x20, 0x40, 0x80  /* walking one */
  381         };
  382         int             i;
  383 
  384         /*
  385          * Make sure there is some way for lptopen to see that
  386          * the port is not configured
  387          * This 0 will remain if the port isn't attached
  388          */
  389         (lpt_sc + dvp->id_unit)->sc_port = 0;
  390 
  391         status = IO_LPTSIZE;
  392         /* If port not specified, use bios list */
  393         if(dvp->id_iobase < 0) {        /* port? */
  394                 if((next_bios_lpt < BIOS_MAX_LPT) &&
  395                                 (*(BIOS_PORTS+next_bios_lpt) != 0) ) {
  396                         dvp->id_iobase = *(BIOS_PORTS+next_bios_lpt++);
  397                         goto end_probe;
  398                 } else
  399                         return (0);
  400         }
  401 
  402         /* Port was explicitly specified */
  403         /* This allows probing of ports unknown to the BIOS */
  404         port = dvp->id_iobase + lpt_data;
  405         for (i = 0; i < 18; i++) {
  406                 if (!lpt_port_test(port, testbyte[i], 0xff)) {
  407                         status = 0;
  408                         goto end_probe;
  409                 }
  410         }
  411 
  412 end_probe:
  413         /* write 0's to control and data ports */
  414         outb(dvp->id_iobase+lpt_data, 0);
  415         outb(dvp->id_iobase+lpt_control, 0);
  416 
  417         return (status);
  418 }
  419 
  420 /* XXX Todo - try and detect if interrupt is working */
  421 int
  422 lptattach(struct isa_device *isdp)
  423 {
  424         struct  lpt_softc       *sc;
  425         int     unit;
  426 
  427         unit = isdp->id_unit;
  428         sc = lpt_sc + unit;
  429         sc->sc_port = isdp->id_iobase;
  430         sc->sc_primed = 0;      /* not primed yet */
  431         outb(sc->sc_port+lpt_control, LPC_NINIT);
  432 
  433         /* check if we can use interrupt */
  434         lprintf("oldirq %x\n", sc->sc_irq);
  435         if (isdp->id_irq) {
  436                 sc->sc_irq = LP_HAS_IRQ | LP_USE_IRQ | LP_ENABLE_IRQ;
  437                 printf("lpt%d: Interrupt-driven port\n", unit);
  438 #ifdef INET
  439                 lpattach(sc, unit);
  440 #endif
  441         } else {
  442                 sc->sc_irq = 0;
  443                 lprintf("lpt%d: Polled port\n", unit);
  444         }
  445         lprintf("irq %x\n", sc->sc_irq);
  446 
  447 #ifdef DEVFS
  448         /* XXX what to do about the flags in the minor number? */
  449         sc->devfs_token = devfs_add_devswf(&lpt_cdevsw,
  450                 unit, DV_CHR,
  451                 UID_ROOT, GID_WHEEL, 0600, "lpt%d", unit);
  452         sc->devfs_token_ctl = devfs_add_devswf(&lpt_cdevsw,
  453                 unit | LP_BYPASS, DV_CHR,
  454                 UID_ROOT, GID_WHEEL, 0600, "lpctl%d", unit);
  455 #endif
  456         return (1);
  457 }
  458 
  459 /*
  460  * lptopen -- reset the printer, then wait until it's selected and not busy.
  461  *      If LP_BYPASS flag is selected, then we do not try to select the
  462  *      printer -- this is just used for passing ioctls.
  463  */
  464 
  465 static  int
  466 lptopen (dev_t dev, int flags, int fmt, struct proc *p)
  467 {
  468         struct lpt_softc *sc;
  469         int s;
  470         int trys, port;
  471         u_int unit = LPTUNIT(minor(dev));
  472 
  473         sc = lpt_sc + unit;
  474         if ((unit >= NLPT) || (sc->sc_port == 0))
  475                 return (ENXIO);
  476 
  477 #ifdef INET
  478         if (sc->sc_if.if_flags & IFF_UP)
  479                 return(EBUSY);
  480 #endif
  481 
  482         if (sc->sc_state) {
  483                 lprintf("lp: still open %x\n", sc->sc_state);
  484                 return(EBUSY);
  485         } else
  486                 sc->sc_state |= INIT;
  487 
  488         sc->sc_flags = LPTFLAGS(minor(dev));
  489 
  490         /* Check for open with BYPASS flag set. */
  491         if (sc->sc_flags & LP_BYPASS) {
  492                 sc->sc_state = OPEN;
  493                 return(0);
  494         }
  495 
  496         s = spltty();
  497         lprintf("lp flags 0x%x\n", sc->sc_flags);
  498         port = sc->sc_port;
  499 
  500         /* set IRQ status according to ENABLE_IRQ flag */
  501         if (sc->sc_irq & LP_ENABLE_IRQ)
  502                 sc->sc_irq |= LP_USE_IRQ;
  503         else
  504                 sc->sc_irq &= ~LP_USE_IRQ;
  505 
  506         /* init printer */
  507         if ((sc->sc_flags & LP_NO_PRIME) == 0) {
  508                 if((sc->sc_flags & LP_PRIMEOPEN) || sc->sc_primed == 0) {
  509                         outb(port+lpt_control, 0);
  510                         sc->sc_primed++;
  511                         DELAY(500);
  512                 }
  513         }
  514 
  515         outb (port+lpt_control, LPC_SEL|LPC_NINIT);
  516 
  517         /* wait till ready (printer running diagnostics) */
  518         trys = 0;
  519         do {
  520                 /* ran out of waiting for the printer */
  521                 if (trys++ >= LPINITRDY*4) {
  522                         splx(s);
  523                         sc->sc_state = 0;
  524                         lprintf ("status %x\n", inb(port+lpt_status) );
  525                         return (EBUSY);
  526                 }
  527 
  528                 /* wait 1/4 second, give up if we get a signal */
  529                 if (tsleep ((caddr_t)sc, LPPRI|PCATCH, "lptinit", hz/4) !=
  530                     EWOULDBLOCK) {
  531                         sc->sc_state = 0;
  532                         splx(s);
  533                         return (EBUSY);
  534                 }
  535 
  536                 /* is printer online and ready for output */
  537         } while ((inb(port+lpt_status) & (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)) !=
  538                  (LPS_SEL|LPS_NBSY|LPS_NERR));
  539 
  540         sc->sc_control = LPC_SEL|LPC_NINIT;
  541         if (sc->sc_flags & LP_AUTOLF)
  542                 sc->sc_control |= LPC_AUTOL;
  543 
  544         /* enable interrupt if interrupt-driven */
  545         if (sc->sc_irq & LP_USE_IRQ)
  546                 sc->sc_control |= LPC_ENA;
  547 
  548         outb(port+lpt_control, sc->sc_control);
  549 
  550         sc->sc_state = OPEN;
  551         sc->sc_inbuf = geteblk(BUFSIZE);
  552         sc->sc_xfercnt = 0;
  553         splx(s);
  554 
  555         /* only use timeout if using interrupt */
  556         lprintf("irq %x\n", sc->sc_irq);
  557         if (sc->sc_irq & LP_USE_IRQ) {
  558                 sc->sc_state |= TOUT;
  559                 timeout ((timeout_func_t)lptout, (caddr_t)sc,
  560                          (sc->sc_backoff = hz/LPTOUTINITIAL));
  561         }
  562 
  563         lprintf("opened.\n");
  564         return(0);
  565 }
  566 
  567 static void
  568 lptout (struct lpt_softc * sc)
  569 {       int pl;
  570 
  571         lprintf ("T %x ", inb(sc->sc_port+lpt_status));
  572         if (sc->sc_state & OPEN) {
  573                 sc->sc_backoff++;
  574                 if (sc->sc_backoff > hz/LPTOUTMAX)
  575                         sc->sc_backoff = sc->sc_backoff > hz/LPTOUTMAX;
  576                 timeout ((timeout_func_t)lptout, (caddr_t)sc, sc->sc_backoff);
  577         } else
  578                 sc->sc_state &= ~TOUT;
  579 
  580         if (sc->sc_state & ERROR)
  581                 sc->sc_state &= ~ERROR;
  582 
  583         /*
  584          * Avoid possible hangs do to missed interrupts
  585          */
  586         if (sc->sc_xfercnt) {
  587                 pl = spltty();
  588                 lptintr(sc - lpt_sc);
  589                 splx(pl);
  590         } else {
  591                 sc->sc_state &= ~OBUSY;
  592                 wakeup((caddr_t)sc);
  593         }
  594 }
  595 
  596 /*
  597  * lptclose -- close the device, free the local line buffer.
  598  *
  599  * Check for interrupted write call added.
  600  */
  601 
  602 static  int
  603 lptclose(dev_t dev, int flags, int fmt, struct proc *p)
  604 {
  605         struct lpt_softc *sc = lpt_sc + LPTUNIT(minor(dev));
  606         int port = sc->sc_port;
  607 
  608         if(sc->sc_flags & LP_BYPASS)
  609                 goto end_close;
  610 
  611         sc->sc_state &= ~OPEN;
  612 
  613         /* if the last write was interrupted, don't complete it */
  614         if((!(sc->sc_state  & INTERRUPTED)) && (sc->sc_irq & LP_USE_IRQ))
  615                 while ((inb(port+lpt_status) & (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)) !=
  616                         (LPS_SEL|LPS_NBSY|LPS_NERR) || sc->sc_xfercnt)
  617                         /* wait 1/4 second, give up if we get a signal */
  618                         if (tsleep ((caddr_t)sc, LPPRI|PCATCH,
  619                                 "lpclose", hz) != EWOULDBLOCK)
  620                                 break;
  621 
  622         outb(sc->sc_port+lpt_control, LPC_NINIT);
  623         brelse(sc->sc_inbuf);
  624 
  625 end_close:
  626         sc->sc_state = 0;
  627         sc->sc_xfercnt = 0;
  628         lprintf("closed.\n");
  629         return(0);
  630 }
  631 
  632 /*
  633  * pushbytes()
  634  *      Workhorse for actually spinning and writing bytes to printer
  635  *      Derived from lpa.c
  636  *      Originally by ?
  637  *
  638  *      This code is only used when we are polling the port
  639  */
  640 static int
  641 pushbytes(struct lpt_softc * sc)
  642 {
  643         int spin, err, tic;
  644         char ch;
  645         int port = sc->sc_port;
  646 
  647         lprintf("p");
  648         /* loop for every character .. */
  649         while (sc->sc_xfercnt > 0) {
  650                 /* printer data */
  651                 ch = *(sc->sc_cp);
  652                 sc->sc_cp++;
  653                 sc->sc_xfercnt--;
  654 
  655                 /*
  656                  * Wait for printer ready.
  657                  * Loop 20 usecs testing BUSY bit, then sleep
  658                  * for exponentially increasing timeout. (vak)
  659                  */
  660                 for (spin=0; NOT_READY(port+lpt_status) && spin<MAX_SPIN; ++spin)
  661                         DELAY(1);       /* XXX delay is NOT this accurate! */
  662                 if (spin >= MAX_SPIN) {
  663                         tic = 0;
  664                         while (NOT_READY(port+lpt_status)) {
  665                                 /*
  666                                  * Now sleep, every cycle a
  667                                  * little longer ..
  668                                  */
  669                                 tic = tic + tic + 1;
  670                                 /*
  671                                  * But no more than 10 seconds. (vak)
  672                                  */
  673                                 if (tic > MAX_SLEEP)
  674                                         tic = MAX_SLEEP;
  675                                 err = tsleep((caddr_t)sc, LPPRI,
  676                                         "lptpoll", tic);
  677                                 if (err != EWOULDBLOCK) {
  678                                         return (err);
  679                                 }
  680                         }
  681                 }
  682 
  683                 /* output data */
  684                 outb(port+lpt_data, ch);
  685                 /* strobe */
  686                 outb(port+lpt_control, sc->sc_control|LPC_STB);
  687                 outb(port+lpt_control, sc->sc_control);
  688 
  689         }
  690         return(0);
  691 }
  692 
  693 /*
  694  * lptwrite --copy a line from user space to a local buffer, then call
  695  * putc to get the chars moved to the output queue.
  696  *
  697  * Flagging of interrupted write added.
  698  */
  699 
  700 static  int
  701 lptwrite(dev_t dev, struct uio * uio, int ioflag)
  702 {
  703         register unsigned n;
  704         int pl, err;
  705         struct lpt_softc *sc = lpt_sc + LPTUNIT(minor(dev));
  706 
  707         if(sc->sc_flags & LP_BYPASS) {
  708                 /* we can't do writes in bypass mode */
  709                 return(EPERM);
  710         }
  711 
  712         sc->sc_state &= ~INTERRUPTED;
  713         while ((n = min(BUFSIZE, uio->uio_resid)) != 0) {
  714                 sc->sc_cp = sc->sc_inbuf->b_un.b_addr ;
  715                 uiomove(sc->sc_cp, n, uio);
  716                 sc->sc_xfercnt = n ;
  717                 while ((sc->sc_xfercnt > 0)&&(sc->sc_irq & LP_USE_IRQ)) {
  718                         lprintf("i");
  719                         /* if the printer is ready for a char, */
  720                         /* give it one */
  721                         if ((sc->sc_state & OBUSY) == 0){
  722                                 lprintf("\nC %d. ", sc->sc_xfercnt);
  723                                 pl = spltty();
  724                                 lptintr(sc - lpt_sc);
  725                                 (void) splx(pl);
  726                         }
  727                         lprintf("W ");
  728                         if (sc->sc_state & OBUSY)
  729                                 if ((err = tsleep ((caddr_t)sc,
  730                                          LPPRI|PCATCH, "lpwrite", 0))) {
  731                                         sc->sc_state |= INTERRUPTED;
  732                                         return(err);
  733                                 }
  734                 }
  735                 /* check to see if we must do a polled write */
  736                 if(!(sc->sc_irq & LP_USE_IRQ) && (sc->sc_xfercnt)) {
  737                         lprintf("p");
  738                         if((err = pushbytes(sc)))
  739                                 return(err);
  740                 }
  741         }
  742         return(0);
  743 }
  744 
  745 /*
  746  * lptintr -- handle printer interrupts which occur when the printer is
  747  * ready to accept another char.
  748  *
  749  * do checking for interrupted write call.
  750  */
  751 
  752 void
  753 lptintr(int unit)
  754 {
  755         struct lpt_softc *sc = lpt_sc + unit;
  756         int port = sc->sc_port, sts;
  757         int i;
  758 
  759 #ifdef INET
  760         if(sc->sc_if.if_flags & IFF_UP) {
  761             lpintr(unit);
  762             return;
  763         }
  764 #endif /* INET */
  765 
  766         /*
  767          * Is printer online and ready for output?
  768          *
  769          * Avoid falling back to lptout() too quickly.  First spin-loop
  770          * to see if the printer will become ready ``really soon now''.
  771          */
  772         for (i = 0;
  773              i < 100 &&
  774              ((sts=inb(port+lpt_status)) & RDY_MASK) != LP_READY;
  775              i++) ;
  776         if ((sts & RDY_MASK) == LP_READY) {
  777                 sc->sc_state = (sc->sc_state | OBUSY) & ~ERROR;
  778                 sc->sc_backoff = hz/LPTOUTINITIAL;
  779 
  780                 if (sc->sc_xfercnt) {
  781                         /* send char */
  782                         /*lprintf("%x ", *sc->sc_cp); */
  783                         outb(port+lpt_data, *sc->sc_cp++) ;
  784                         outb(port+lpt_control, sc->sc_control|LPC_STB);
  785                         /* DELAY(X) */
  786                         outb(port+lpt_control, sc->sc_control);
  787 
  788                         /* any more data for printer */
  789                         if(--(sc->sc_xfercnt) > 0) return;
  790                 }
  791 
  792                 /*
  793                  * No more data waiting for printer.
  794                  * Wakeup is not done if write call was interrupted.
  795                  */
  796                 sc->sc_state &= ~OBUSY;
  797                 if(!(sc->sc_state & INTERRUPTED))
  798                         wakeup((caddr_t)sc);
  799                 lprintf("w ");
  800                 return;
  801         } else  {       /* check for error */
  802                 if(((sts & (LPS_NERR | LPS_OUT) ) != LPS_NERR) &&
  803                                 (sc->sc_state & OPEN))
  804                         sc->sc_state |= ERROR;
  805                 /* lptout() will jump in and try to restart. */
  806         }
  807         lprintf("sts %x ", sts);
  808 }
  809 
  810 static  int
  811 lptioctl(dev_t dev, int cmd, caddr_t data, int flags, struct proc *p)
  812 {
  813         int     error = 0;
  814         struct  lpt_softc *sc;
  815         u_int   unit = LPTUNIT(minor(dev));
  816         u_char  old_sc_irq;     /* old printer IRQ status */
  817 
  818         sc = lpt_sc + unit;
  819 
  820         switch (cmd) {
  821         case LPT_IRQ :
  822                 if(sc->sc_irq & LP_HAS_IRQ) {
  823                         /*
  824                          * NOTE:
  825                          * If the IRQ status is changed,
  826                          * this will only be visible on the
  827                          * next open.
  828                          *
  829                          * If interrupt status changes,
  830                          * this gets syslog'd.
  831                          */
  832                         old_sc_irq = sc->sc_irq;
  833                         if(*(int*)data == 0)
  834                                 sc->sc_irq &= (~LP_ENABLE_IRQ);
  835                         else
  836                                 sc->sc_irq |= LP_ENABLE_IRQ;
  837                         if (old_sc_irq != sc->sc_irq )
  838                                 log(LOG_NOTICE, "lpt%c switched to %s mode\n",
  839                                         (char)unit+'',
  840                                         (sc->sc_irq & LP_ENABLE_IRQ)?
  841                                         "interrupt-driven":"polled");
  842                 } else /* polled port */
  843                         error = EOPNOTSUPP;
  844                 break;
  845         default:
  846                 error = ENODEV;
  847         }
  848 
  849         return(error);
  850 }
  851 
  852 #ifdef INET
  853 
  854 static void
  855 lpattach (struct lpt_softc *sc, int unit)
  856 {
  857         struct ifnet *ifp = &sc->sc_if;
  858 
  859         ifp->if_softc = sc;
  860         ifp->if_name = "lp";
  861         ifp->if_unit = unit;
  862         ifp->if_mtu = LPMTU;
  863         ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST;
  864         ifp->if_ioctl = lpioctl;
  865         ifp->if_output = lpoutput;
  866         ifp->if_type = IFT_PARA;
  867         ifp->if_hdrlen = 0;
  868         ifp->if_addrlen = 0;
  869         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  870         if_attach(ifp);
  871         printf("lp%d: TCP/IP capable interface\n", unit);
  872 
  873 #if NBPFILTER > 0
  874         bpfattach(ifp, DLT_NULL, LPIPHDRLEN);
  875 #endif
  876 }
  877 /*
  878  * Build the translation tables for the LPIP (BSD unix) protocol.
  879  * We don't want to calculate these nasties in our tight loop, so we
  880  * precalculate them when we initialize.
  881  */
  882 static int
  883 lpinittables (void)
  884 {
  885     int i;
  886 
  887     if (!txmith)
  888         txmith = malloc(4*LPIPTBLSIZE, M_DEVBUF, M_NOWAIT);
  889 
  890     if (!txmith)
  891         return 1;
  892 
  893     if (!ctxmith)
  894         ctxmith = malloc(4*LPIPTBLSIZE, M_DEVBUF, M_NOWAIT);
  895 
  896     if (!ctxmith)
  897         return 1;
  898 
  899     for (i=0; i < LPIPTBLSIZE; i++) {
  900         ctxmith[i] = (i & 0xF0) >> 4;
  901         ctxmitl[i] = 0x10 | (i & 0x0F);
  902         ctrecvh[i] = (i & 0x78) << 1;
  903         ctrecvl[i] = (i & 0x78) >> 3;
  904     }
  905 
  906     for (i=0; i < LPIPTBLSIZE; i++) {
  907         txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08;
  908         txmitl[i] = ((i & 0x08) << 1) | (i & 0x07);
  909         trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1);
  910         trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3);
  911     }
  912 
  913     return 0;
  914 }
  915 
  916 /*
  917  * Process an ioctl request.
  918  */
  919 
  920 static int
  921 lpioctl (struct ifnet *ifp, int cmd, caddr_t data)
  922 {
  923     struct lpt_softc *sc = lpt_sc + ifp->if_unit;
  924     struct ifaddr *ifa = (struct ifaddr *)data;
  925     struct ifreq *ifr = (struct ifreq *)data;
  926     u_char *ptr;
  927 
  928     switch (cmd) {
  929 
  930     case SIOCSIFDSTADDR:
  931     case SIOCAIFADDR:
  932     case SIOCSIFADDR:
  933         if (ifa->ifa_addr->sa_family != AF_INET)
  934             return EAFNOSUPPORT;
  935         ifp->if_flags |= IFF_UP;
  936         /* FALLTHROUGH */
  937     case SIOCSIFFLAGS:
  938         if ((!(ifp->if_flags & IFF_UP)) && (ifp->if_flags & IFF_RUNNING)) {
  939             outb(sc->sc_port + lpt_control, 0x00);
  940             ifp->if_flags &= ~IFF_RUNNING;
  941             break;
  942         }
  943         if (((ifp->if_flags & IFF_UP)) && (!(ifp->if_flags & IFF_RUNNING))) {
  944             if (lpinittables())
  945                 return ENOBUFS;
  946             sc->sc_ifbuf = malloc(sc->sc_if.if_mtu + MLPIPHDRLEN,
  947                                   M_DEVBUF, M_WAITOK);
  948             if (!sc->sc_ifbuf)
  949                 return ENOBUFS;
  950 
  951             outb(sc->sc_port + lpt_control, LPC_ENA);
  952             ifp->if_flags |= IFF_RUNNING;
  953         }
  954         break;
  955 
  956     case SIOCSIFMTU:
  957         ptr = sc->sc_ifbuf;
  958         sc->sc_ifbuf = malloc(ifr->ifr_mtu+MLPIPHDRLEN, M_DEVBUF, M_NOWAIT);
  959         if (!sc->sc_ifbuf) {
  960             sc->sc_ifbuf = ptr;
  961             return ENOBUFS;
  962         }
  963         if (ptr)
  964             free(ptr,M_DEVBUF);
  965         sc->sc_if.if_mtu = ifr->ifr_mtu;
  966         break;
  967 
  968     case SIOCGIFMTU:
  969         ifr->ifr_mtu = sc->sc_if.if_mtu;
  970         break;
  971 
  972     case SIOCADDMULTI:
  973     case SIOCDELMULTI:
  974         if (ifr == 0) {
  975             return EAFNOSUPPORT;                /* XXX */
  976         }
  977         switch (ifr->ifr_addr.sa_family) {
  978 
  979 #ifdef INET
  980         case AF_INET:
  981             break;
  982 #endif
  983 
  984         default:
  985             return EAFNOSUPPORT;
  986         }
  987         break;
  988 
  989     default:
  990         lprintf("LP:ioctl(0x%x)\n",cmd);
  991         return EINVAL;
  992     }
  993     return 0;
  994 }
  995 
  996 static __inline int
  997 clpoutbyte (u_char byte, int spin, int data_port, int status_port)
  998 {
  999         outb(data_port, ctxmitl[byte]);
 1000         while (inb(status_port) & CLPIP_SHAKE)
 1001                 if (--spin == 0) {
 1002                         return 1;
 1003                 }
 1004         outb(data_port, ctxmith[byte]);
 1005         while (!(inb(status_port) & CLPIP_SHAKE))
 1006                 if (--spin == 0) {
 1007                         return 1;
 1008                 }
 1009         return 0;
 1010 }
 1011 
 1012 static __inline int
 1013 clpinbyte (int spin, int data_port, int status_port)
 1014 {
 1015         int c, cl;
 1016 
 1017         while((inb(status_port) & CLPIP_SHAKE))
 1018             if(!--spin) {
 1019                 return -1;
 1020             }
 1021         cl = inb(status_port);
 1022         outb(data_port, 0x10);
 1023 
 1024         while(!(inb(status_port) & CLPIP_SHAKE))
 1025             if(!--spin) {
 1026                 return -1;
 1027             }
 1028         c = inb(status_port);
 1029         outb(data_port, 0x00);
 1030 
 1031         return (ctrecvl[cl] | ctrecvh[c]);
 1032 }
 1033 
 1034 static void
 1035 lpintr (int unit)
 1036 {
 1037         struct   lpt_softc *sc = lpt_sc + unit;
 1038         register int lpt_data_port = sc->sc_port + lpt_data;
 1039         register int lpt_stat_port = sc->sc_port + lpt_status;
 1040                  int lpt_ctrl_port = sc->sc_port + lpt_control;
 1041         int len, s, j;
 1042         u_char *bp;
 1043         u_char c, cl;
 1044         struct mbuf *top;
 1045 
 1046         s = splhigh();
 1047 
 1048         if (sc->sc_if.if_flags & IFF_LINK0) {
 1049 
 1050             /* Ack. the request */
 1051             outb(lpt_data_port, 0x01);
 1052 
 1053             /* Get the packet length */
 1054             j = clpinbyte(LPMAXSPIN2, lpt_data_port, lpt_stat_port);
 1055             if (j == -1)
 1056                 goto err;
 1057             len = j;
 1058             j = clpinbyte(LPMAXSPIN2, lpt_data_port, lpt_stat_port);
 1059             if (j == -1)
 1060                 goto err;
 1061             len = len + (j << 8);
 1062             if (len > sc->sc_if.if_mtu + MLPIPHDRLEN)
 1063                 goto err;
 1064 
 1065             bp  = sc->sc_ifbuf;
 1066         
 1067             while (len--) {
 1068                 j = clpinbyte(LPMAXSPIN2, lpt_data_port, lpt_stat_port);
 1069                 if (j == -1) {
 1070                     goto err;
 1071                 }
 1072                 *bp++ = j;
 1073             }
 1074             /* Get and ignore checksum */
 1075             j = clpinbyte(LPMAXSPIN2, lpt_data_port, lpt_stat_port);
 1076             if (j == -1) {
 1077                 goto err;
 1078             }
 1079 
 1080             len = bp - sc->sc_ifbuf;
 1081             if (len <= CLPIPHDRLEN)
 1082                 goto err;
 1083 
 1084             sc->sc_iferrs = 0;
 1085 
 1086             if (IF_QFULL(&ipintrq)) {
 1087                 lprintf("DROP");
 1088                 IF_DROP(&ipintrq);
 1089                 goto done;
 1090             }
 1091             len -= CLPIPHDRLEN;
 1092             sc->sc_if.if_ipackets++;
 1093             sc->sc_if.if_ibytes += len;
 1094             top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, &sc->sc_if, 0);
 1095             if (top) {
 1096                 IF_ENQUEUE(&ipintrq, top);
 1097                 schednetisr(NETISR_IP);
 1098             }
 1099             goto done;
 1100         }
 1101         while ((inb(lpt_stat_port) & LPIP_SHAKE)) {
 1102             len = sc->sc_if.if_mtu + LPIPHDRLEN;
 1103             bp  = sc->sc_ifbuf;
 1104             while (len--) {
 1105 
 1106                 cl = inb(lpt_stat_port);
 1107                 outb(lpt_data_port, 8);
 1108 
 1109                 j = LPMAXSPIN2;
 1110                 while((inb(lpt_stat_port) & LPIP_SHAKE))
 1111                     if(!--j) goto err;
 1112 
 1113                 c = inb(lpt_stat_port);
 1114                 outb(lpt_data_port, 0);
 1115 
 1116                 *bp++= trecvh[cl] | trecvl[c];
 1117 
 1118                 j = LPMAXSPIN2;
 1119                 while (!((cl=inb(lpt_stat_port)) & LPIP_SHAKE)) {
 1120                     if (cl != c &&
 1121                         (((cl = inb(lpt_stat_port)) ^ 0xb8) & 0xf8) ==
 1122                           (c & 0xf8))
 1123                         goto end;
 1124                     if (!--j) goto err;
 1125                 }
 1126             }
 1127 
 1128         end:
 1129             len = bp - sc->sc_ifbuf;
 1130             if (len <= LPIPHDRLEN)
 1131                 goto err;
 1132 
 1133             sc->sc_iferrs = 0;
 1134 
 1135             if (IF_QFULL(&ipintrq)) {
 1136                 lprintf("DROP");
 1137                 IF_DROP(&ipintrq);
 1138                 goto done;
 1139             }
 1140 #if NBPFILTER > 0
 1141             if (sc->sc_if.if_bpf) {
 1142                 bpf_tap(&sc->sc_if, sc->sc_ifbuf, len);
 1143             }
 1144 #endif
 1145             len -= LPIPHDRLEN;
 1146             sc->sc_if.if_ipackets++;
 1147             sc->sc_if.if_ibytes += len;
 1148             top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, &sc->sc_if, 0);
 1149             if (top) {
 1150                     IF_ENQUEUE(&ipintrq, top);
 1151                     schednetisr(NETISR_IP);
 1152             }
 1153         }
 1154         goto done;
 1155 
 1156     err:
 1157         outb(lpt_data_port, 0);
 1158         lprintf("R");
 1159         sc->sc_if.if_ierrors++;
 1160         sc->sc_iferrs++;
 1161 
 1162         /*
 1163          * We are not able to send receive anything for now,
 1164          * so stop wasting our time
 1165          */
 1166         if (sc->sc_iferrs > LPMAXERRS) {
 1167             printf("lp%d: Too many errors, Going off-line.\n", unit);
 1168             outb(lpt_ctrl_port, 0x00);
 1169             sc->sc_if.if_flags &= ~IFF_RUNNING;
 1170             sc->sc_iferrs=0;
 1171         }
 1172 
 1173     done:
 1174         splx(s);
 1175         return;
 1176 }
 1177 
 1178 static __inline int
 1179 lpoutbyte (u_char byte, int spin, int data_port, int status_port)
 1180 {
 1181     outb(data_port, txmith[byte]);
 1182     while (!(inb(status_port) & LPIP_SHAKE))
 1183         if (--spin == 0)
 1184                 return 1;
 1185     outb(data_port, txmitl[byte]);
 1186     while (inb(status_port) & LPIP_SHAKE)
 1187         if (--spin == 0)
 1188                 return 1;
 1189     return 0;
 1190 }
 1191 
 1192 static int
 1193 lpoutput (struct ifnet *ifp, struct mbuf *m,
 1194           struct sockaddr *dst, struct rtentry *rt)
 1195 {
 1196     register int lpt_data_port = lpt_sc[ifp->if_unit].sc_port + lpt_data;
 1197     register int lpt_stat_port = lpt_sc[ifp->if_unit].sc_port + lpt_status;
 1198              int lpt_ctrl_port = lpt_sc[ifp->if_unit].sc_port + lpt_control;
 1199 
 1200     int s, err;
 1201     struct mbuf *mm;
 1202     u_char *cp = "\0\0";
 1203     u_char chksum = 0;
 1204     int count = 0;
 1205     int i;
 1206     int spin;
 1207 
 1208     /* We need a sensible value if we abort */
 1209     cp++;
 1210     ifp->if_flags |= IFF_RUNNING;
 1211 
 1212     err = 1;                    /* assume we're aborting because of an error */
 1213 
 1214     s = splhigh();
 1215 
 1216     /* Suspend (on laptops) or receive-errors might have taken us offline */
 1217     outb(lpt_ctrl_port, LPC_ENA);
 1218 
 1219     if (ifp->if_flags & IFF_LINK0) {
 1220 
 1221         if (!(inb(lpt_stat_port) & CLPIP_SHAKE)) {
 1222             lprintf("&");
 1223             lptintr(ifp->if_unit);
 1224         }
 1225 
 1226         /* Alert other end to pending packet */
 1227         spin = LPMAXSPIN1;
 1228         outb(lpt_data_port, 0x08);
 1229         while ((inb(lpt_stat_port) & 0x08) == 0)
 1230                 if (--spin == 0) {
 1231                         goto nend;
 1232                 }
 1233 
 1234         /* Calculate length of packet, then send that */
 1235 
 1236         count += 14;            /* Ethernet header len */
 1237 
 1238         mm = m;
 1239         for (mm = m; mm; mm = mm->m_next) {
 1240                 count += mm->m_len;
 1241         }
 1242         if (clpoutbyte(count & 0xFF, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
 1243                 goto nend;
 1244         if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
 1245                 goto nend;
 1246 
 1247         /* Send dummy ethernet header */
 1248         for (i = 0; i < 12; i++) {
 1249                 if (clpoutbyte(i, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
 1250                         goto nend;
 1251                 chksum += i;
 1252         }
 1253 
 1254         if (clpoutbyte(0x08, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
 1255                 goto nend;
 1256         if (clpoutbyte(0x00, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
 1257                 goto nend;
 1258         chksum += 0x08 + 0x00;          /* Add into checksum */
 1259 
 1260         mm = m;
 1261         do {
 1262                 cp = mtod(mm, u_char *);
 1263                 while (mm->m_len--) {
 1264                         chksum += *cp;
 1265                         if (clpoutbyte(*cp++, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
 1266                                 goto nend;
 1267                 }
 1268         } while ((mm = mm->m_next));
 1269 
 1270         /* Send checksum */
 1271         if (clpoutbyte(chksum, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
 1272                 goto nend;
 1273 
 1274         /* Go quiescent */
 1275         outb(lpt_data_port, 0);
 1276 
 1277         err = 0;                        /* No errors */
 1278 
 1279         nend:
 1280         if (err)  {                             /* if we didn't timeout... */
 1281                 ifp->if_oerrors++;
 1282                 lprintf("X");
 1283         } else {
 1284                 ifp->if_opackets++;
 1285                 ifp->if_obytes += m->m_pkthdr.len;
 1286         }
 1287 
 1288         m_freem(m);
 1289 
 1290         if (!(inb(lpt_stat_port) & CLPIP_SHAKE)) {
 1291                 lprintf("^");
 1292                 lptintr(ifp->if_unit);
 1293         }
 1294         (void) splx(s);
 1295         return 0;
 1296     }
 1297 
 1298     if (inb(lpt_stat_port) & LPIP_SHAKE) {
 1299         lprintf("&");
 1300         lptintr(ifp->if_unit);
 1301     }
 1302 
 1303     if (lpoutbyte(0x08, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
 1304         goto end;
 1305     if (lpoutbyte(0x00, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
 1306         goto end;
 1307 
 1308     mm = m;
 1309     do {
 1310         cp = mtod(mm,u_char *);
 1311         while (mm->m_len--)
 1312             if (lpoutbyte(*cp++, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
 1313                 goto end;
 1314     } while ((mm = mm->m_next));
 1315 
 1316     err = 0;                            /* no errors were encountered */
 1317 
 1318     end:
 1319     --cp;
 1320     outb(lpt_data_port, txmitl[*cp] ^ 0x17);
 1321 
 1322     if (err)  {                         /* if we didn't timeout... */
 1323         ifp->if_oerrors++;
 1324         lprintf("X");
 1325     } else {
 1326         ifp->if_opackets++;
 1327         ifp->if_obytes += m->m_pkthdr.len;
 1328 #if NBPFILTER > 0
 1329         if (ifp->if_bpf) {
 1330             /*
 1331              * We need to prepend the packet type as
 1332              * a two byte field.  Cons up a dummy header
 1333              * to pacify bpf.  This is safe because bpf
 1334              * will only read from the mbuf (i.e., it won't
 1335              * try to free it or keep a pointer to it).
 1336              */
 1337             struct mbuf m0;
 1338             u_short hdr = 0x800;
 1339 
 1340             m0.m_next = m;
 1341             m0.m_len = 2;
 1342             m0.m_data = (char *)&hdr;
 1343 
 1344             bpf_mtap(ifp, &m0);
 1345         }
 1346 #endif
 1347     }
 1348 
 1349     m_freem(m);
 1350 
 1351     if (inb(lpt_stat_port) & LPIP_SHAKE) {
 1352         lprintf("^");
 1353         lptintr(ifp->if_unit);
 1354     }
 1355 
 1356     (void) splx(s);
 1357     return 0;
 1358 }
 1359 
 1360 #endif /* INET */
 1361 
 1362 static lpt_devsw_installed = 0;
 1363 
 1364 static void     lpt_drvinit(void *unused)
 1365 {
 1366         dev_t dev;
 1367 
 1368         if( ! lpt_devsw_installed ) {
 1369                 dev = makedev(CDEV_MAJOR, 0);
 1370                 cdevsw_add(&dev,&lpt_cdevsw, NULL);
 1371                 lpt_devsw_installed = 1;
 1372         }
 1373 }
 1374 
 1375 SYSINIT(lptdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,lpt_drvinit,NULL)
 1376 

Cache object: c7a48f7ad9f217b629306de2aab36e19


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