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