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