summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>1999-02-10 02:41:24 +0000
committerdes <des@FreeBSD.org>1999-02-10 02:41:24 +0000
commit7dd9b0cd6255e68f4e371d6d9400791dfdb5efb7 (patch)
treef73442f75a98c9340272ba7801325b5933733d82 /sys
parentd57c230beb0024deb217d38bcd43e84a12e64bca (diff)
downloadFreeBSD-src-7dd9b0cd6255e68f4e371d6d9400791dfdb5efb7.zip
FreeBSD-src-7dd9b0cd6255e68f4e371d6d9400791dfdb5efb7.tar.gz
Remove the lpt driver, as discussed on -hackers.
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/NOTES14
-rw-r--r--sys/conf/files.i3863
-rw-r--r--sys/i386/conf/LINT14
-rw-r--r--sys/i386/conf/NOTES14
-rw-r--r--sys/i386/conf/files.i3863
-rw-r--r--sys/i386/isa/lpt.c1381
6 files changed, 11 insertions, 1418 deletions
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index ec06de5..fd466759 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.550 1999/02/07 20:33:05 joerg Exp $
+# $Id: LINT,v 1.551 1999/02/09 01:03:17 mjacob Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -1113,19 +1113,11 @@ disk fd0 at fdc0 drive 0
disk fd1 at fdc0 drive 1
#
-# Other standard PC hardware: `lpt', `mse', `sio', etc.
+# Other standard PC hardware: `mse', `sio', etc.
#
-# lpt: printer port
-# lpt specials:
-# The port may be specified as ?. This will cause the
-# driver to scan the BIOS port list.
-# The irq clause may be omitted. This will force the port
-# into polling mode.
# mse: Logitech and ATI InPort bus mouse ports
# sio: serial ports (see sio(4))
-device lpt0 at isa? port? tty irq 7
-device lpt1 at isa? port "IO_LPT3" tty irq 5
device mse0 at isa? port 0x23c tty irq 5
device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4
@@ -1837,7 +1829,7 @@ pseudo-device "i4bisppp" 4
# vpo Iomega Zip Drive
# Requires SCSI disk support ('scbus' and 'da'), best
# performance is achieved with ports in EPP 1.9 mode.
-# nlpt Parallel Printer, use _instead_ of lpt0
+# nlpt Parallel Printer
# plip Parallel network interface
# ppi General-purpose I/O ("Geek Port")
# pps Pulse per second Timing Interface
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 6993be0..ffb26d3 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.219 1999/01/19 11:31:22 yokota Exp $
+# $Id: files.i386,v 1.220 1999/01/20 03:29:52 msmith Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@@ -146,7 +146,6 @@ i386/isa/isa.c optional isa device-driver
i386/isa/istallion.c optional stli device-driver
i386/isa/joy.c optional joy device-driver
i386/isa/loran.c optional loran device-driver
-i386/isa/lpt.c optional lpt device-driver
i386/isa/labpc.c optional labpc device-driver
i386/isa/mcd.c optional mcd device-driver
i386/isa/mse.c optional mse device-driver
diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT
index ec06de5..fd466759 100644
--- a/sys/i386/conf/LINT
+++ b/sys/i386/conf/LINT
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.550 1999/02/07 20:33:05 joerg Exp $
+# $Id: LINT,v 1.551 1999/02/09 01:03:17 mjacob Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -1113,19 +1113,11 @@ disk fd0 at fdc0 drive 0
disk fd1 at fdc0 drive 1
#
-# Other standard PC hardware: `lpt', `mse', `sio', etc.
+# Other standard PC hardware: `mse', `sio', etc.
#
-# lpt: printer port
-# lpt specials:
-# The port may be specified as ?. This will cause the
-# driver to scan the BIOS port list.
-# The irq clause may be omitted. This will force the port
-# into polling mode.
# mse: Logitech and ATI InPort bus mouse ports
# sio: serial ports (see sio(4))
-device lpt0 at isa? port? tty irq 7
-device lpt1 at isa? port "IO_LPT3" tty irq 5
device mse0 at isa? port 0x23c tty irq 5
device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4
@@ -1837,7 +1829,7 @@ pseudo-device "i4bisppp" 4
# vpo Iomega Zip Drive
# Requires SCSI disk support ('scbus' and 'da'), best
# performance is achieved with ports in EPP 1.9 mode.
-# nlpt Parallel Printer, use _instead_ of lpt0
+# nlpt Parallel Printer
# plip Parallel network interface
# ppi General-purpose I/O ("Geek Port")
# pps Pulse per second Timing Interface
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index ec06de5..fd466759 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can.
#
-# $Id: LINT,v 1.550 1999/02/07 20:33:05 joerg Exp $
+# $Id: LINT,v 1.551 1999/02/09 01:03:17 mjacob Exp $
#
# NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from
@@ -1113,19 +1113,11 @@ disk fd0 at fdc0 drive 0
disk fd1 at fdc0 drive 1
#
-# Other standard PC hardware: `lpt', `mse', `sio', etc.
+# Other standard PC hardware: `mse', `sio', etc.
#
-# lpt: printer port
-# lpt specials:
-# The port may be specified as ?. This will cause the
-# driver to scan the BIOS port list.
-# The irq clause may be omitted. This will force the port
-# into polling mode.
# mse: Logitech and ATI InPort bus mouse ports
# sio: serial ports (see sio(4))
-device lpt0 at isa? port? tty irq 7
-device lpt1 at isa? port "IO_LPT3" tty irq 5
device mse0 at isa? port 0x23c tty irq 5
device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4
@@ -1837,7 +1829,7 @@ pseudo-device "i4bisppp" 4
# vpo Iomega Zip Drive
# Requires SCSI disk support ('scbus' and 'da'), best
# performance is achieved with ports in EPP 1.9 mode.
-# nlpt Parallel Printer, use _instead_ of lpt0
+# nlpt Parallel Printer
# plip Parallel network interface
# ppi General-purpose I/O ("Geek Port")
# pps Pulse per second Timing Interface
diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386
index 6993be0..ffb26d3 100644
--- a/sys/i386/conf/files.i386
+++ b/sys/i386/conf/files.i386
@@ -1,7 +1,7 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.219 1999/01/19 11:31:22 yokota Exp $
+# $Id: files.i386,v 1.220 1999/01/20 03:29:52 msmith Exp $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@@ -146,7 +146,6 @@ i386/isa/isa.c optional isa device-driver
i386/isa/istallion.c optional stli device-driver
i386/isa/joy.c optional joy device-driver
i386/isa/loran.c optional loran device-driver
-i386/isa/lpt.c optional lpt device-driver
i386/isa/labpc.c optional labpc device-driver
i386/isa/mcd.c optional mcd device-driver
i386/isa/mse.c optional mse device-driver
diff --git a/sys/i386/isa/lpt.c b/sys/i386/isa/lpt.c
deleted file mode 100644
index 2b56158..0000000
--- a/sys/i386/isa/lpt.c
+++ /dev/null
@@ -1,1381 +0,0 @@
-/*
- * Copyright (c) 1990 William F. Jolitz, TeleMuse
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This software is a component of "386BSD" developed by
- * William F. Jolitz, TeleMuse.
- * 4. Neither the name of the developer nor the name "386BSD"
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
- * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
- * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
- * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
- * NOT MAKE USE OF THIS WORK.
- *
- * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
- * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
- * REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES
- * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
- * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
- * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
- * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
- * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * from: unknown origin, 386BSD 0.1
- * $Id: lpt.c,v 1.71 1998/10/22 05:58:39 bde Exp $
- */
-
-/*
- * Device Driver for AT parallel printer port
- * Written by William Jolitz 12/18/90
- */
-
-/*
- * Parallel port TCP/IP interfaces added. I looked at the driver from
- * MACH but this is a complete rewrite, and btw. incompatible, and it
- * should perform better too. I have never run the MACH driver though.
- *
- * This driver sends two bytes (0x08, 0x00) in front of each packet,
- * to allow us to distinguish another format later.
- *
- * Now added an Linux/Crynwr compatibility mode which is enabled using
- * IF_LINK0 - Tim Wilkinson.
- *
- * TODO:
- * Make HDLC/PPP mode, use IF_LLC1 to enable.
- *
- * Connect the two computers using a Laplink parallel cable to use this
- * feature:
- *
- * +----------------------------------------+
- * |A-name A-End B-End Descr. Port/Bit |
- * +----------------------------------------+
- * |DATA0 2 15 Data 0/0x01 |
- * |-ERROR 15 2 1/0x08 |
- * +----------------------------------------+
- * |DATA1 3 13 Data 0/0x02 |
- * |+SLCT 13 3 1/0x10 |
- * +----------------------------------------+
- * |DATA2 4 12 Data 0/0x04 |
- * |+PE 12 4 1/0x20 |
- * +----------------------------------------+
- * |DATA3 5 10 Strobe 0/0x08 |
- * |-ACK 10 5 1/0x40 |
- * +----------------------------------------+
- * |DATA4 6 11 Data 0/0x10 |
- * |BUSY 11 6 1/~0x80 |
- * +----------------------------------------+
- * |GND 18-25 18-25 GND - |
- * +----------------------------------------+
- *
- * Expect transfer-rates up to 75 kbyte/sec.
- *
- * If GCC could correctly grok
- * register int port asm("edx")
- * the code would be cleaner
- *
- * Poul-Henning Kamp <phk@freebsd.org>
- */
-
-#include "lpt.h"
-#include "opt_devfs.h"
-#include "opt_inet.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/buf.h>
-#include <sys/kernel.h>
-#include <sys/uio.h>
-#include <sys/syslog.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-
-#include <machine/clock.h>
-#include <machine/lpt.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-
-#include <i386/isa/isa.h>
-#include <i386/isa/isa_device.h>
-#include <i386/isa/lptreg.h>
-
-#ifdef INET
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-
-#include <net/if.h>
-#include <net/if_types.h>
-#include <net/netisr.h>
-#include <netinet/in.h>
-#include <netinet/in_var.h>
-#include "bpfilter.h"
-#if NBPFILTER > 0
-#include <net/bpf.h>
-#endif
-#endif /* INET */
-
-
-#define LPINITRDY 4 /* wait up to 4 seconds for a ready */
-#define LPTOUTINITIAL 10 /* initial timeout to wait for ready 1/10 s */
-#define LPTOUTMAX 1 /* maximal timeout 1 s */
-#define LPPRI (PZERO+8)
-#define BUFSIZE 1024
-
-#ifdef INET
-#ifndef LPMTU /* MTU for the lp# interfaces */
-#define LPMTU 1500
-#endif
-
-#ifndef LPMAXSPIN1 /* DELAY factor for the lp# interfaces */
-#define LPMAXSPIN1 8000 /* Spinning for remote intr to happen */
-#endif
-
-#ifndef LPMAXSPIN2 /* DELAY factor for the lp# interfaces */
-#define LPMAXSPIN2 500 /* Spinning for remote handshake to happen */
-#endif
-
-#ifndef LPMAXERRS /* Max errors before !RUNNING */
-#define LPMAXERRS 100
-#endif
-
-#define CLPIPHDRLEN 14 /* We send dummy ethernet addresses (two) + packet type in front of packet */
-#define CLPIP_SHAKE 0x80 /* This bit toggles between nibble reception */
-#define MLPIPHDRLEN CLPIPHDRLEN
-
-#define LPIPHDRLEN 2 /* We send 0x08, 0x00 in front of packet */
-#define LPIP_SHAKE 0x40 /* This bit toggles between nibble reception */
-#if !defined(MLPIPHDRLEN) || LPIPHDRLEN > MLPIPHDRLEN
-#define MLPIPHDRLEN LPIPHDRLEN
-#endif
-
-#define LPIPTBLSIZE 256 /* Size of octet translation table */
-
-#endif /* INET */
-
-/* BIOS printer list - used by BIOS probe*/
-#define BIOS_LPT_PORTS 0x408
-#define BIOS_PORTS (short *)(KERNBASE+BIOS_LPT_PORTS)
-#define BIOS_MAX_LPT 4
-
-
-#ifndef DEBUG
-#define lprintf(args)
-#else
-#define lprintf(args) do { \
- if (lptflag) \
- printf args; \
- } while (0)
-static int volatile lptflag = 1;
-#endif
-
-#define LPTUNIT(s) ((s)&0x03)
-#define LPTFLAGS(s) ((s)&0xfc)
-
-static struct lpt_softc {
- int sc_port;
- short sc_state;
- /* default case: negative prime, negative ack, handshake strobe,
- prime once */
- u_char sc_control;
- char sc_flags;
-#define LP_POS_INIT 0x04 /* if we are a postive init signal */
-#define LP_POS_ACK 0x08 /* if we are a positive going ack */
-#define LP_NO_PRIME 0x10 /* don't prime the printer at all */
-#define LP_PRIMEOPEN 0x20 /* prime on every open */
-#define LP_AUTOLF 0x40 /* tell printer to do an automatic lf */
-#define LP_BYPASS 0x80 /* bypass printer ready checks */
- struct buf *sc_inbuf;
- short sc_xfercnt ;
- char sc_primed;
- char *sc_cp ;
- u_char sc_irq ; /* IRQ status of port */
-#define LP_HAS_IRQ 0x01 /* we have an irq available */
-#define LP_USE_IRQ 0x02 /* we are using our irq */
-#define LP_ENABLE_IRQ 0x04 /* enable IRQ on open */
- u_char sc_backoff ; /* time to call lptout() again */
-
-#ifdef INET
- struct ifnet sc_if;
- u_char *sc_ifbuf;
- int sc_iferrs;
-#endif
-#ifdef DEVFS
- void *devfs_token;
- void *devfs_token_ctl;
-#endif
-} lpt_sc[NLPT] ;
-
-/* bits for state */
-#define OPEN (1<<0) /* device is open */
-#define ASLP (1<<1) /* awaiting draining of printer */
-#define ERROR (1<<2) /* error was received from printer */
-#define OBUSY (1<<3) /* printer is busy doing output */
-#define LPTOUT (1<<4) /* timeout while not selected */
-#define TOUT (1<<5) /* timeout while not selected */
-#define INIT (1<<6) /* waiting to initialize for open */
-#define INTERRUPTED (1<<7) /* write call was interrupted */
-
-
-/* status masks to interrogate printer status */
-#define RDY_MASK (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR) /* ready ? */
-#define LP_READY (LPS_SEL|LPS_NBSY|LPS_NERR)
-
-/* Printer Ready condition - from lpa.c */
-/* Only used in polling code */
-#define LPS_INVERT (LPS_NBSY | LPS_NACK | LPS_SEL | LPS_NERR)
-#define LPS_MASK (LPS_NBSY | LPS_NACK | LPS_OUT | LPS_SEL | LPS_NERR)
-#define NOT_READY(x) ((inb(x)^LPS_INVERT)&LPS_MASK)
-
-#define MAX_SLEEP (hz*5) /* Timeout while waiting for device ready */
-#define MAX_SPIN 20 /* Max delay for device ready in usecs */
-
-static timeout_t lptout;
-static int lptprobe (struct isa_device *dvp);
-static int lptattach (struct isa_device *isdp);
-static ointhand2_t lptintr;
-
-#ifdef INET
-
-/* Tables for the lp# interface */
-static u_char *txmith;
-#define txmitl (txmith+(1*LPIPTBLSIZE))
-#define trecvh (txmith+(2*LPIPTBLSIZE))
-#define trecvl (txmith+(3*LPIPTBLSIZE))
-
-static u_char *ctxmith;
-#define ctxmitl (ctxmith+(1*LPIPTBLSIZE))
-#define ctrecvh (ctxmith+(2*LPIPTBLSIZE))
-#define ctrecvl (ctxmith+(3*LPIPTBLSIZE))
-
-/* Functions for the lp# interface */
-static void lpattach(struct lpt_softc *,int);
-static int lpinittables(void);
-static int lpioctl(struct ifnet *, u_long, caddr_t);
-static int lpoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
- struct rtentry *);
-static void lpintr(int);
-#endif /* INET */
-
-struct isa_driver lptdriver = {
- lptprobe, lptattach, "lpt"
-};
-
-static d_open_t lptopen;
-static d_close_t lptclose;
-static d_write_t lptwrite;
-static d_ioctl_t lptioctl;
-
-#define CDEV_MAJOR 16
-static struct cdevsw lpt_cdevsw =
- { lptopen, lptclose, noread, lptwrite, /*16*/
- lptioctl, nullstop, nullreset, nodevtotty,/* lpt */
- seltrue, nommap, nostrat, "lpt", NULL, -1 };
-
-
-/*
- * Internal routine to lptprobe to do port tests of one byte value
- */
-static int
-lpt_port_test (int port, u_char data, u_char mask)
-{
- int temp, timeout;
-
- data = data & mask;
- outb(port, data);
- timeout = 10000;
- do {
- DELAY(10);
- temp = inb(port) & mask;
- }
- while (temp != data && --timeout);
- lprintf(("Port 0x%x\tout=%x\tin=%x\ttout=%d\n",
- port, data, temp, timeout));
- return (temp == data);
-}
-
-/*
- * New lpt port probe Geoff Rehmet - Rhodes University - 14/2/94
- * Based partially on Rod Grimes' printer probe
- *
- * Logic:
- * 1) If no port address was given, use the bios detected ports
- * and autodetect what ports the printers are on.
- * 2) Otherwise, probe the data port at the address given,
- * using the method in Rod Grimes' port probe.
- * (Much code ripped off directly from Rod's probe.)
- *
- * Comments from Rod's probe:
- * Logic:
- * 1) You should be able to write to and read back the same value
- * to the data port. Do an alternating zeros, alternating ones,
- * walking zero, and walking one test to check for stuck bits.
- *
- * 2) You should be able to write to and read back the same value
- * to the control port lower 5 bits, the upper 3 bits are reserved
- * per the IBM PC technical reference manauls and different boards
- * do different things with them. Do an alternating zeros, alternating
- * ones, walking zero, and walking one test to check for stuck bits.
- *
- * Some printers drag the strobe line down when the are powered off
- * so this bit has been masked out of the control port test.
- *
- * XXX Some printers may not like a fast pulse on init or strobe, I
- * don't know at this point, if that becomes a problem these bits
- * should be turned off in the mask byte for the control port test.
- *
- * We are finally left with a mask of 0x14, due to some printers
- * being adamant about holding other bits high ........
- *
- * Before probing the control port, we write a 0 to the data port -
- * If not, some printers chuck out garbage when the strobe line
- * gets toggled.
- *
- * 3) Set the data and control ports to a value of 0
- *
- * This probe routine has been tested on Epson Lx-800, HP LJ3P,
- * Epson FX-1170 and C.Itoh 8510RM
- * printers.
- * Quick exit on fail added.
- */
-int
-lptprobe(struct isa_device *dvp)
-{
- int port;
- static short next_bios_lpt = 0;
- int status;
- static u_char testbyte[18] = {
- 0x55, /* alternating zeros */
- 0xaa, /* alternating ones */
- 0xfe, 0xfd, 0xfb, 0xf7,
- 0xef, 0xdf, 0xbf, 0x7f, /* walking zero */
- 0x01, 0x02, 0x04, 0x08,
- 0x10, 0x20, 0x40, 0x80 /* walking one */
- };
- int i;
-
- /*
- * Make sure there is some way for lptopen to see that
- * the port is not configured
- * This 0 will remain if the port isn't attached
- */
- (lpt_sc + dvp->id_unit)->sc_port = 0;
-
- status = IO_LPTSIZE;
- /* If port not specified, use bios list */
- if(dvp->id_iobase < 0) { /* port? */
- if((next_bios_lpt < BIOS_MAX_LPT) &&
- (*(BIOS_PORTS+next_bios_lpt) != 0) ) {
- dvp->id_iobase = *(BIOS_PORTS+next_bios_lpt++);
- goto end_probe;
- } else
- return (0);
- }
-
- /* Port was explicitly specified */
- /* This allows probing of ports unknown to the BIOS */
- port = dvp->id_iobase + lpt_data;
- for (i = 0; i < 18; i++) {
- if (!lpt_port_test(port, testbyte[i], 0xff)) {
- status = 0;
- goto end_probe;
- }
- }
-
-end_probe:
- /* write 0's to control and data ports */
- outb(dvp->id_iobase+lpt_data, 0);
- outb(dvp->id_iobase+lpt_control, 0);
-
- return (status);
-}
-
-/* XXX Todo - try and detect if interrupt is working */
-int
-lptattach(struct isa_device *isdp)
-{
- struct lpt_softc *sc;
- int unit;
-
- isdp->id_ointr = lptintr;
- unit = isdp->id_unit;
- sc = lpt_sc + unit;
- sc->sc_port = isdp->id_iobase;
- sc->sc_primed = 0; /* not primed yet */
- outb(sc->sc_port+lpt_control, LPC_NINIT);
-
- /* check if we can use interrupt */
- lprintf(("oldirq %x\n", sc->sc_irq));
- if (isdp->id_irq) {
- sc->sc_irq = LP_HAS_IRQ | LP_USE_IRQ | LP_ENABLE_IRQ;
- printf("lpt%d: Interrupt-driven port\n", unit);
-#ifdef INET
- lpattach(sc, unit);
-#endif
- } else {
- sc->sc_irq = 0;
- lprintf(("lpt%d: Polled port\n", unit));
- }
- lprintf(("irq %x\n", sc->sc_irq));
-
-#ifdef DEVFS
- /* XXX what to do about the flags in the minor number? */
- sc->devfs_token = devfs_add_devswf(&lpt_cdevsw,
- unit, DV_CHR,
- UID_ROOT, GID_WHEEL, 0600, "lpt%d", unit);
- sc->devfs_token_ctl = devfs_add_devswf(&lpt_cdevsw,
- unit | LP_BYPASS, DV_CHR,
- UID_ROOT, GID_WHEEL, 0600, "lpctl%d", unit);
-#endif
- return (1);
-}
-
-/*
- * lptopen -- reset the printer, then wait until it's selected and not busy.
- * If LP_BYPASS flag is selected, then we do not try to select the
- * printer -- this is just used for passing ioctls.
- */
-
-static int
-lptopen (dev_t dev, int flags, int fmt, struct proc *p)
-{
- struct lpt_softc *sc;
- int s;
- int trys, port;
- u_int unit = LPTUNIT(minor(dev));
-
- sc = lpt_sc + unit;
- if ((unit >= NLPT) || (sc->sc_port == 0))
- return (ENXIO);
-
-#ifdef INET
- if (sc->sc_if.if_flags & IFF_UP)
- return(EBUSY);
-#endif
-
- if (sc->sc_state) {
- lprintf(("lp: still open %x\n", sc->sc_state));
- return(EBUSY);
- } else
- sc->sc_state |= INIT;
-
- sc->sc_flags = LPTFLAGS(minor(dev));
-
- /* Check for open with BYPASS flag set. */
- if (sc->sc_flags & LP_BYPASS) {
- sc->sc_state = OPEN;
- return(0);
- }
-
- s = spltty();
- lprintf(("lp flags 0x%x\n", sc->sc_flags));
- port = sc->sc_port;
-
- /* set IRQ status according to ENABLE_IRQ flag */
- if (sc->sc_irq & LP_ENABLE_IRQ)
- sc->sc_irq |= LP_USE_IRQ;
- else
- sc->sc_irq &= ~LP_USE_IRQ;
-
- /* init printer */
- if ((sc->sc_flags & LP_NO_PRIME) == 0) {
- if((sc->sc_flags & LP_PRIMEOPEN) || sc->sc_primed == 0) {
- outb(port+lpt_control, 0);
- sc->sc_primed++;
- DELAY(500);
- }
- }
-
- outb (port+lpt_control, LPC_SEL|LPC_NINIT);
-
- /* wait till ready (printer running diagnostics) */
- trys = 0;
- do {
- /* ran out of waiting for the printer */
- if (trys++ >= LPINITRDY*4) {
- splx(s);
- sc->sc_state = 0;
- lprintf(("status %x\n", inb(port+lpt_status)));
- return (EBUSY);
- }
-
- /* wait 1/4 second, give up if we get a signal */
- if (tsleep ((caddr_t)sc, LPPRI|PCATCH, "lptinit", hz/4) !=
- EWOULDBLOCK) {
- sc->sc_state = 0;
- splx(s);
- return (EBUSY);
- }
-
- /* is printer online and ready for output */
- } while ((inb(port+lpt_status) & (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)) !=
- (LPS_SEL|LPS_NBSY|LPS_NERR));
-
- sc->sc_control = LPC_SEL|LPC_NINIT;
- if (sc->sc_flags & LP_AUTOLF)
- sc->sc_control |= LPC_AUTOL;
-
- /* enable interrupt if interrupt-driven */
- if (sc->sc_irq & LP_USE_IRQ)
- sc->sc_control |= LPC_ENA;
-
- outb(port+lpt_control, sc->sc_control);
-
- sc->sc_state = OPEN;
- sc->sc_inbuf = geteblk(BUFSIZE);
- sc->sc_xfercnt = 0;
- splx(s);
-
- /* only use timeout if using interrupt */
- lprintf(("irq %x\n", sc->sc_irq));
- if (sc->sc_irq & LP_USE_IRQ) {
- sc->sc_state |= TOUT;
- timeout (lptout, (caddr_t)sc,
- (sc->sc_backoff = hz/LPTOUTINITIAL));
- }
-
- lprintf(("opened.\n"));
- return(0);
-}
-
-static void
-lptout (void *arg)
-{
- struct lpt_softc *sc = arg;
- int pl;
-
- lprintf(("T %x ", inb(sc->sc_port+lpt_status)));
- if (sc->sc_state & OPEN) {
- sc->sc_backoff++;
- if (sc->sc_backoff > hz/LPTOUTMAX)
- sc->sc_backoff = sc->sc_backoff > hz/LPTOUTMAX;
- timeout (lptout, (caddr_t)sc, sc->sc_backoff);
- } else
- sc->sc_state &= ~TOUT;
-
- if (sc->sc_state & ERROR)
- sc->sc_state &= ~ERROR;
-
- /*
- * Avoid possible hangs do to missed interrupts
- */
- if (sc->sc_xfercnt) {
- pl = spltty();
- lptintr(sc - lpt_sc);
- splx(pl);
- } else {
- sc->sc_state &= ~OBUSY;
- wakeup((caddr_t)sc);
- }
-}
-
-/*
- * lptclose -- close the device, free the local line buffer.
- *
- * Check for interrupted write call added.
- */
-
-static int
-lptclose(dev_t dev, int flags, int fmt, struct proc *p)
-{
- struct lpt_softc *sc = lpt_sc + LPTUNIT(minor(dev));
- int port = sc->sc_port;
-
- if(sc->sc_flags & LP_BYPASS)
- goto end_close;
-
- sc->sc_state &= ~OPEN;
-
- /* if the last write was interrupted, don't complete it */
- if((!(sc->sc_state & INTERRUPTED)) && (sc->sc_irq & LP_USE_IRQ))
- while ((inb(port+lpt_status) & (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)) !=
- (LPS_SEL|LPS_NBSY|LPS_NERR) || sc->sc_xfercnt)
- /* wait 1/4 second, give up if we get a signal */
- if (tsleep ((caddr_t)sc, LPPRI|PCATCH,
- "lpclose", hz) != EWOULDBLOCK)
- break;
-
- outb(sc->sc_port+lpt_control, LPC_NINIT);
- brelse(sc->sc_inbuf);
-
-end_close:
- sc->sc_state = 0;
- sc->sc_xfercnt = 0;
- lprintf(("closed.\n"));
- return(0);
-}
-
-/*
- * pushbytes()
- * Workhorse for actually spinning and writing bytes to printer
- * Derived from lpa.c
- * Originally by ?
- *
- * This code is only used when we are polling the port
- */
-static int
-pushbytes(struct lpt_softc * sc)
-{
- int spin, err, tic;
- char ch;
- int port = sc->sc_port;
-
- lprintf(("p"));
- /* loop for every character .. */
- while (sc->sc_xfercnt > 0) {
- /* printer data */
- ch = *(sc->sc_cp);
- sc->sc_cp++;
- sc->sc_xfercnt--;
-
- /*
- * Wait for printer ready.
- * Loop 20 usecs testing BUSY bit, then sleep
- * for exponentially increasing timeout. (vak)
- */
- for (spin=0; NOT_READY(port+lpt_status) && spin<MAX_SPIN; ++spin)
- DELAY(1); /* XXX delay is NOT this accurate! */
- if (spin >= MAX_SPIN) {
- tic = 0;
- while (NOT_READY(port+lpt_status)) {
- /*
- * Now sleep, every cycle a
- * little longer ..
- */
- tic = tic + tic + 1;
- /*
- * But no more than 10 seconds. (vak)
- */
- if (tic > MAX_SLEEP)
- tic = MAX_SLEEP;
- err = tsleep((caddr_t)sc, LPPRI,
- "lptpoll", tic);
- if (err != EWOULDBLOCK) {
- return (err);
- }
- }
- }
-
- /* output data */
- outb(port+lpt_data, ch);
- /* strobe */
- outb(port+lpt_control, sc->sc_control|LPC_STB);
- outb(port+lpt_control, sc->sc_control);
-
- }
- return(0);
-}
-
-/*
- * lptwrite --copy a line from user space to a local buffer, then call
- * putc to get the chars moved to the output queue.
- *
- * Flagging of interrupted write added.
- */
-
-static int
-lptwrite(dev_t dev, struct uio * uio, int ioflag)
-{
- register unsigned n;
- int pl, err;
- struct lpt_softc *sc = lpt_sc + LPTUNIT(minor(dev));
-
- if(sc->sc_flags & LP_BYPASS) {
- /* we can't do writes in bypass mode */
- return(EPERM);
- }
-
- sc->sc_state &= ~INTERRUPTED;
- while ((n = min(BUFSIZE, uio->uio_resid)) != 0) {
- sc->sc_cp = sc->sc_inbuf->b_data ;
- uiomove(sc->sc_cp, n, uio);
- sc->sc_xfercnt = n ;
- while ((sc->sc_xfercnt > 0)&&(sc->sc_irq & LP_USE_IRQ)) {
- lprintf(("i"));
- /* if the printer is ready for a char, */
- /* give it one */
- if ((sc->sc_state & OBUSY) == 0){
- lprintf(("\nC %d. ", sc->sc_xfercnt));
- pl = spltty();
- lptintr(sc - lpt_sc);
- (void) splx(pl);
- }
- lprintf(("W "));
- if (sc->sc_state & OBUSY)
- if ((err = tsleep ((caddr_t)sc,
- LPPRI|PCATCH, "lpwrite", 0))) {
- sc->sc_state |= INTERRUPTED;
- return(err);
- }
- }
- /* check to see if we must do a polled write */
- if(!(sc->sc_irq & LP_USE_IRQ) && (sc->sc_xfercnt)) {
- lprintf(("p"));
- if((err = pushbytes(sc)))
- return(err);
- }
- }
- return(0);
-}
-
-/*
- * lptintr -- handle printer interrupts which occur when the printer is
- * ready to accept another char.
- *
- * do checking for interrupted write call.
- */
-
-static void
-lptintr(int unit)
-{
- struct lpt_softc *sc = lpt_sc + unit;
- int port = sc->sc_port, sts;
- int i;
-
-#ifdef INET
- if(sc->sc_if.if_flags & IFF_UP) {
- lpintr(unit);
- return;
- }
-#endif /* INET */
-
- /*
- * Is printer online and ready for output?
- *
- * Avoid falling back to lptout() too quickly. First spin-loop
- * to see if the printer will become ready ``really soon now''.
- */
- for (i = 0;
- i < 100 &&
- ((sts=inb(port+lpt_status)) & RDY_MASK) != LP_READY;
- i++) ;
- if ((sts & RDY_MASK) == LP_READY) {
- sc->sc_state = (sc->sc_state | OBUSY) & ~ERROR;
- sc->sc_backoff = hz/LPTOUTINITIAL;
-
- if (sc->sc_xfercnt) {
- /* send char */
- /*lprintf(("%x ", *sc->sc_cp)); */
- outb(port+lpt_data, *sc->sc_cp++) ;
- outb(port+lpt_control, sc->sc_control|LPC_STB);
- /* DELAY(X) */
- outb(port+lpt_control, sc->sc_control);
-
- /* any more data for printer */
- if(--(sc->sc_xfercnt) > 0) return;
- }
-
- /*
- * No more data waiting for printer.
- * Wakeup is not done if write call was interrupted.
- */
- sc->sc_state &= ~OBUSY;
- if(!(sc->sc_state & INTERRUPTED))
- wakeup((caddr_t)sc);
- lprintf(("w "));
- return;
- } else { /* check for error */
- if(((sts & (LPS_NERR | LPS_OUT) ) != LPS_NERR) &&
- (sc->sc_state & OPEN))
- sc->sc_state |= ERROR;
- /* lptout() will jump in and try to restart. */
- }
- lprintf(("sts %x ", sts));
-}
-
-static int
-lptioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
-{
- int error = 0;
- struct lpt_softc *sc;
- u_int unit = LPTUNIT(minor(dev));
- u_char old_sc_irq; /* old printer IRQ status */
-
- sc = lpt_sc + unit;
-
- switch (cmd) {
- case LPT_IRQ :
- if(sc->sc_irq & LP_HAS_IRQ) {
- /*
- * NOTE:
- * If the IRQ status is changed,
- * this will only be visible on the
- * next open.
- *
- * If interrupt status changes,
- * this gets syslog'd.
- */
- old_sc_irq = sc->sc_irq;
- if(*(int*)data == 0)
- sc->sc_irq &= (~LP_ENABLE_IRQ);
- else
- sc->sc_irq |= LP_ENABLE_IRQ;
- if (old_sc_irq != sc->sc_irq )
- log(LOG_NOTICE, "lpt%c switched to %s mode\n",
- (char)unit+'0',
- (sc->sc_irq & LP_ENABLE_IRQ)?
- "interrupt-driven":"polled");
- } else /* polled port */
- error = EOPNOTSUPP;
- break;
- default:
- error = ENODEV;
- }
-
- return(error);
-}
-
-#ifdef INET
-
-static void
-lpattach (struct lpt_softc *sc, int unit)
-{
- struct ifnet *ifp = &sc->sc_if;
-
- ifp->if_softc = sc;
- ifp->if_name = "lp";
- ifp->if_unit = unit;
- ifp->if_mtu = LPMTU;
- ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST;
- ifp->if_ioctl = lpioctl;
- ifp->if_output = lpoutput;
- ifp->if_type = IFT_PARA;
- ifp->if_hdrlen = 0;
- ifp->if_addrlen = 0;
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
- if_attach(ifp);
- printf("lp%d: TCP/IP capable interface\n", unit);
-
-#if NBPFILTER > 0
- bpfattach(ifp, DLT_NULL, LPIPHDRLEN);
-#endif
-}
-/*
- * Build the translation tables for the LPIP (BSD unix) protocol.
- * We don't want to calculate these nasties in our tight loop, so we
- * precalculate them when we initialize.
- */
-static int
-lpinittables (void)
-{
- int i;
-
- if (!txmith)
- txmith = malloc(4*LPIPTBLSIZE, M_DEVBUF, M_NOWAIT);
-
- if (!txmith)
- return 1;
-
- if (!ctxmith)
- ctxmith = malloc(4*LPIPTBLSIZE, M_DEVBUF, M_NOWAIT);
-
- if (!ctxmith)
- return 1;
-
- for (i=0; i < LPIPTBLSIZE; i++) {
- ctxmith[i] = (i & 0xF0) >> 4;
- ctxmitl[i] = 0x10 | (i & 0x0F);
- ctrecvh[i] = (i & 0x78) << 1;
- ctrecvl[i] = (i & 0x78) >> 3;
- }
-
- for (i=0; i < LPIPTBLSIZE; i++) {
- txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08;
- txmitl[i] = ((i & 0x08) << 1) | (i & 0x07);
- trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1);
- trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3);
- }
-
- return 0;
-}
-
-/*
- * Process an ioctl request.
- */
-
-static int
-lpioctl (struct ifnet *ifp, u_long cmd, caddr_t data)
-{
- struct lpt_softc *sc = lpt_sc + ifp->if_unit;
- struct ifaddr *ifa = (struct ifaddr *)data;
- struct ifreq *ifr = (struct ifreq *)data;
- u_char *ptr;
-
- switch (cmd) {
-
- case SIOCSIFDSTADDR:
- case SIOCAIFADDR:
- case SIOCSIFADDR:
- if (ifa->ifa_addr->sa_family != AF_INET)
- return EAFNOSUPPORT;
- ifp->if_flags |= IFF_UP;
- /* FALLTHROUGH */
- case SIOCSIFFLAGS:
- if ((!(ifp->if_flags & IFF_UP)) && (ifp->if_flags & IFF_RUNNING)) {
- outb(sc->sc_port + lpt_control, 0x00);
- ifp->if_flags &= ~IFF_RUNNING;
- break;
- }
- if (((ifp->if_flags & IFF_UP)) && (!(ifp->if_flags & IFF_RUNNING))) {
- if (lpinittables())
- return ENOBUFS;
- sc->sc_ifbuf = malloc(sc->sc_if.if_mtu + MLPIPHDRLEN,
- M_DEVBUF, M_WAITOK);
- if (!sc->sc_ifbuf)
- return ENOBUFS;
-
- outb(sc->sc_port + lpt_control, LPC_ENA);
- ifp->if_flags |= IFF_RUNNING;
- }
- break;
-
- case SIOCSIFMTU:
- ptr = sc->sc_ifbuf;
- sc->sc_ifbuf = malloc(ifr->ifr_mtu+MLPIPHDRLEN, M_DEVBUF, M_NOWAIT);
- if (!sc->sc_ifbuf) {
- sc->sc_ifbuf = ptr;
- return ENOBUFS;
- }
- if (ptr)
- free(ptr,M_DEVBUF);
- sc->sc_if.if_mtu = ifr->ifr_mtu;
- break;
-
- case SIOCGIFMTU:
- ifr->ifr_mtu = sc->sc_if.if_mtu;
- break;
-
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- if (ifr == 0) {
- return EAFNOSUPPORT; /* XXX */
- }
- switch (ifr->ifr_addr.sa_family) {
-
-#ifdef INET
- case AF_INET:
- break;
-#endif
-
- default:
- return EAFNOSUPPORT;
- }
- break;
-
- default:
- lprintf(("LP:ioctl(0x%lx)\n", cmd));
- return EINVAL;
- }
- return 0;
-}
-
-static __inline int
-clpoutbyte (u_char byte, int spin, int data_port, int status_port)
-{
- outb(data_port, ctxmitl[byte]);
- while (inb(status_port) & CLPIP_SHAKE)
- if (--spin == 0) {
- return 1;
- }
- outb(data_port, ctxmith[byte]);
- while (!(inb(status_port) & CLPIP_SHAKE))
- if (--spin == 0) {
- return 1;
- }
- return 0;
-}
-
-static __inline int
-clpinbyte (int spin, int data_port, int status_port)
-{
- int c, cl;
-
- while((inb(status_port) & CLPIP_SHAKE))
- if(!--spin) {
- return -1;
- }
- cl = inb(status_port);
- outb(data_port, 0x10);
-
- while(!(inb(status_port) & CLPIP_SHAKE))
- if(!--spin) {
- return -1;
- }
- c = inb(status_port);
- outb(data_port, 0x00);
-
- return (ctrecvl[cl] | ctrecvh[c]);
-}
-
-static void
-lpintr (int unit)
-{
- struct lpt_softc *sc = lpt_sc + unit;
- register int lpt_data_port = sc->sc_port + lpt_data;
- register int lpt_stat_port = sc->sc_port + lpt_status;
- int lpt_ctrl_port = sc->sc_port + lpt_control;
- int len, s, j;
- u_char *bp;
- u_char c, cl;
- struct mbuf *top;
-
- s = splhigh();
-
- if (sc->sc_if.if_flags & IFF_LINK0) {
-
- /* Ack. the request */
- outb(lpt_data_port, 0x01);
-
- /* Get the packet length */
- j = clpinbyte(LPMAXSPIN2, lpt_data_port, lpt_stat_port);
- if (j == -1)
- goto err;
- len = j;
- j = clpinbyte(LPMAXSPIN2, lpt_data_port, lpt_stat_port);
- if (j == -1)
- goto err;
- len = len + (j << 8);
- if (len > sc->sc_if.if_mtu + MLPIPHDRLEN)
- goto err;
-
- bp = sc->sc_ifbuf;
-
- while (len--) {
- j = clpinbyte(LPMAXSPIN2, lpt_data_port, lpt_stat_port);
- if (j == -1) {
- goto err;
- }
- *bp++ = j;
- }
- /* Get and ignore checksum */
- j = clpinbyte(LPMAXSPIN2, lpt_data_port, lpt_stat_port);
- if (j == -1) {
- goto err;
- }
-
- len = bp - sc->sc_ifbuf;
- if (len <= CLPIPHDRLEN)
- goto err;
-
- sc->sc_iferrs = 0;
-
- if (IF_QFULL(&ipintrq)) {
- lprintf(("DROP"));
- IF_DROP(&ipintrq);
- goto done;
- }
- len -= CLPIPHDRLEN;
- sc->sc_if.if_ipackets++;
- sc->sc_if.if_ibytes += len;
- top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, &sc->sc_if, 0);
- if (top) {
- IF_ENQUEUE(&ipintrq, top);
- schednetisr(NETISR_IP);
- }
- goto done;
- }
- while ((inb(lpt_stat_port) & LPIP_SHAKE)) {
- len = sc->sc_if.if_mtu + LPIPHDRLEN;
- bp = sc->sc_ifbuf;
- while (len--) {
-
- cl = inb(lpt_stat_port);
- outb(lpt_data_port, 8);
-
- j = LPMAXSPIN2;
- while((inb(lpt_stat_port) & LPIP_SHAKE))
- if(!--j) goto err;
-
- c = inb(lpt_stat_port);
- outb(lpt_data_port, 0);
-
- *bp++= trecvh[cl] | trecvl[c];
-
- j = LPMAXSPIN2;
- while (!((cl=inb(lpt_stat_port)) & LPIP_SHAKE)) {
- if (cl != c &&
- (((cl = inb(lpt_stat_port)) ^ 0xb8) & 0xf8) ==
- (c & 0xf8))
- goto end;
- if (!--j) goto err;
- }
- }
-
- end:
- len = bp - sc->sc_ifbuf;
- if (len <= LPIPHDRLEN)
- goto err;
-
- sc->sc_iferrs = 0;
-
- if (IF_QFULL(&ipintrq)) {
- lprintf(("DROP"));
- IF_DROP(&ipintrq);
- goto done;
- }
-#if NBPFILTER > 0
- if (sc->sc_if.if_bpf) {
- bpf_tap(&sc->sc_if, sc->sc_ifbuf, len);
- }
-#endif
- len -= LPIPHDRLEN;
- sc->sc_if.if_ipackets++;
- sc->sc_if.if_ibytes += len;
- top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, &sc->sc_if, 0);
- if (top) {
- IF_ENQUEUE(&ipintrq, top);
- schednetisr(NETISR_IP);
- }
- }
- goto done;
-
- err:
- outb(lpt_data_port, 0);
- lprintf(("R"));
- sc->sc_if.if_ierrors++;
- sc->sc_iferrs++;
-
- /*
- * We are not able to send receive anything for now,
- * so stop wasting our time
- */
- if (sc->sc_iferrs > LPMAXERRS) {
- printf("lp%d: Too many errors, Going off-line.\n", unit);
- outb(lpt_ctrl_port, 0x00);
- sc->sc_if.if_flags &= ~IFF_RUNNING;
- sc->sc_iferrs=0;
- }
-
- done:
- splx(s);
- return;
-}
-
-static __inline int
-lpoutbyte (u_char byte, int spin, int data_port, int status_port)
-{
- outb(data_port, txmith[byte]);
- while (!(inb(status_port) & LPIP_SHAKE))
- if (--spin == 0)
- return 1;
- outb(data_port, txmitl[byte]);
- while (inb(status_port) & LPIP_SHAKE)
- if (--spin == 0)
- return 1;
- return 0;
-}
-
-static int
-lpoutput (struct ifnet *ifp, struct mbuf *m,
- struct sockaddr *dst, struct rtentry *rt)
-{
- register int lpt_data_port = lpt_sc[ifp->if_unit].sc_port + lpt_data;
- register int lpt_stat_port = lpt_sc[ifp->if_unit].sc_port + lpt_status;
- int lpt_ctrl_port = lpt_sc[ifp->if_unit].sc_port + lpt_control;
-
- int s, err;
- struct mbuf *mm;
- u_char *cp = "\0\0";
- u_char chksum = 0;
- int count = 0;
- int i;
- int spin;
-
- /* We need a sensible value if we abort */
- cp++;
- ifp->if_flags |= IFF_RUNNING;
-
- err = 1; /* assume we're aborting because of an error */
-
- s = splhigh();
-
- /* Suspend (on laptops) or receive-errors might have taken us offline */
- outb(lpt_ctrl_port, LPC_ENA);
-
- if (ifp->if_flags & IFF_LINK0) {
-
- if (!(inb(lpt_stat_port) & CLPIP_SHAKE)) {
- lprintf(("&"));
- lptintr(ifp->if_unit);
- }
-
- /* Alert other end to pending packet */
- spin = LPMAXSPIN1;
- outb(lpt_data_port, 0x08);
- while ((inb(lpt_stat_port) & 0x08) == 0)
- if (--spin == 0) {
- goto nend;
- }
-
- /* Calculate length of packet, then send that */
-
- count += 14; /* Ethernet header len */
-
- mm = m;
- for (mm = m; mm; mm = mm->m_next) {
- count += mm->m_len;
- }
- if (clpoutbyte(count & 0xFF, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
- goto nend;
- if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
- goto nend;
-
- /* Send dummy ethernet header */
- for (i = 0; i < 12; i++) {
- if (clpoutbyte(i, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
- goto nend;
- chksum += i;
- }
-
- if (clpoutbyte(0x08, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
- goto nend;
- if (clpoutbyte(0x00, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
- goto nend;
- chksum += 0x08 + 0x00; /* Add into checksum */
-
- mm = m;
- do {
- cp = mtod(mm, u_char *);
- while (mm->m_len--) {
- chksum += *cp;
- if (clpoutbyte(*cp++, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
- goto nend;
- }
- } while ((mm = mm->m_next));
-
- /* Send checksum */
- if (clpoutbyte(chksum, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
- goto nend;
-
- /* Go quiescent */
- outb(lpt_data_port, 0);
-
- err = 0; /* No errors */
-
- nend:
- if (err) { /* if we didn't timeout... */
- ifp->if_oerrors++;
- lprintf(("X"));
- } else {
- ifp->if_opackets++;
- ifp->if_obytes += m->m_pkthdr.len;
- }
-
- m_freem(m);
-
- if (!(inb(lpt_stat_port) & CLPIP_SHAKE)) {
- lprintf(("^"));
- lptintr(ifp->if_unit);
- }
- (void) splx(s);
- return 0;
- }
-
- if (inb(lpt_stat_port) & LPIP_SHAKE) {
- lprintf(("&"));
- lptintr(ifp->if_unit);
- }
-
- if (lpoutbyte(0x08, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
- goto end;
- if (lpoutbyte(0x00, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
- goto end;
-
- mm = m;
- do {
- cp = mtod(mm,u_char *);
- while (mm->m_len--)
- if (lpoutbyte(*cp++, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
- goto end;
- } while ((mm = mm->m_next));
-
- err = 0; /* no errors were encountered */
-
- end:
- --cp;
- outb(lpt_data_port, txmitl[*cp] ^ 0x17);
-
- if (err) { /* if we didn't timeout... */
- ifp->if_oerrors++;
- lprintf(("X"));
- } else {
- ifp->if_opackets++;
- ifp->if_obytes += m->m_pkthdr.len;
-#if NBPFILTER > 0
- if (ifp->if_bpf) {
- /*
- * We need to prepend the packet type as
- * a two byte field. Cons up a dummy header
- * to pacify bpf. This is safe because bpf
- * will only read from the mbuf (i.e., it won't
- * try to free it or keep a pointer to it).
- */
- struct mbuf m0;
- u_short hdr = 0x800;
-
- m0.m_next = m;
- m0.m_len = 2;
- m0.m_data = (char *)&hdr;
-
- bpf_mtap(ifp, &m0);
- }
-#endif
- }
-
- m_freem(m);
-
- if (inb(lpt_stat_port) & LPIP_SHAKE) {
- lprintf(("^"));
- lptintr(ifp->if_unit);
- }
-
- (void) splx(s);
- return 0;
-}
-
-#endif /* INET */
-
-static lpt_devsw_installed = 0;
-
-static void lpt_drvinit(void *unused)
-{
- dev_t dev;
-
- if( ! lpt_devsw_installed ) {
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev,&lpt_cdevsw, NULL);
- lpt_devsw_installed = 1;
- }
-}
-
-SYSINIT(lptdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,lpt_drvinit,NULL)
-
OpenPOWER on IntegriCloud