xref: /csrg-svn/sys/sparc/sbus/if_le.c (revision 64777)
155139Storek /*-
263322Sbostic  * Copyright (c) 1982, 1992, 1993
363322Sbostic  *	The Regents of the University of California.  All rights reserved.
455139Storek  *
555139Storek  * %sccs.include.redist.c%
655139Storek  *
7*64777Storek  *	@(#)if_le.c	8.2 (Berkeley) 10/30/93
855139Storek  *
9*64777Storek  * from: $Header: if_le.c,v 1.25 93/10/31 04:47:50 leres Locked $
1055139Storek  */
1155139Storek 
1255139Storek #include "bpfilter.h"
1355139Storek 
1455139Storek /*
1555139Storek  * AMD 7990 LANCE
1655139Storek  */
1756540Sbostic #include <sys/param.h>
1856540Sbostic #include <sys/device.h>
1956540Sbostic #include <sys/systm.h>
2056540Sbostic #include <sys/kernel.h>
2156540Sbostic #include <sys/mbuf.h>
2256540Sbostic #include <sys/buf.h>
2356540Sbostic #include <sys/socket.h>
2456540Sbostic #include <sys/syslog.h>
2556540Sbostic #include <sys/ioctl.h>
2656540Sbostic #include <sys/malloc.h>
2756540Sbostic #include <sys/errno.h>
2855139Storek 
2956540Sbostic #include <net/if.h>
3056540Sbostic #include <net/netisr.h>
3156540Sbostic #include <net/route.h>
3255139Storek #if NBPFILTER > 0
3356540Sbostic #include <sys/select.h>
3456540Sbostic #include <net/bpf.h>
3556540Sbostic #include <net/bpfdesc.h>
3655139Storek #endif
3755139Storek 
3855139Storek #ifdef INET
3956540Sbostic #include <netinet/in.h>
4056540Sbostic #include <netinet/in_systm.h>
4156540Sbostic #include <netinet/in_var.h>
4256540Sbostic #include <netinet/ip.h>
4356540Sbostic #include <netinet/if_ether.h>
4455139Storek #endif
4555139Storek 
4655139Storek #ifdef NS
4756540Sbostic #include <netns/ns.h>
4856540Sbostic #include <netns/ns_if.h>
4955139Storek #endif
5055139Storek 
5155139Storek #ifdef APPLETALK
5256540Sbostic #include <netddp/atalk.h>
5355139Storek #endif
5455139Storek 
5556540Sbostic #include <machine/autoconf.h>
5656540Sbostic #include <machine/cpu.h>
5756540Sbostic #include <machine/pmap.h>
5855139Storek 
5956540Sbostic #include <sparc/sbus/if_lereg.h>
6056540Sbostic #include <sparc/sbus/sbusvar.h>
6155139Storek 
6255139Storek /* DVMA address to LANCE address -- the Sbus/MMU will resupply the 0xff */
6355139Storek #define	LANCE_ADDR(x)	((int)(x) & ~0xff000000)
6455139Storek 
6555139Storek int	ledebug = 0;		/* console error messages */
6655139Storek 
6755139Storek #ifdef PACKETSTATS
6855139Storek long	lexpacketsizes[LEMTU+1];
6955139Storek long	lerpacketsizes[LEMTU+1];
7055139Storek #endif
7155139Storek 
7255139Storek /* Per interface statistics */
7355139Storek /* XXX this should go in something like if_levar.h */
7455139Storek struct	lestats {
7555139Storek 	long	lexints;	/* transmitter interrupts */
7655139Storek 	long	lerints;	/* receiver interrupts */
7755139Storek 	long	lerbufs;	/* total buffers received during interrupts */
7855139Storek 	long	lerhits;	/* times current rbuf was full */
7955139Storek 	long	lerscans;	/* rbufs scanned before finding first full */
8055139Storek };
8155139Storek 
8255139Storek /*
8355139Storek  * Ethernet software status per interface.
8455139Storek  *
8555139Storek  * Each interface is referenced by a network interface structure,
8655139Storek  * le_if, which the routing code uses to locate the interface.
8755139Storek  * This structure contains the output queue for the interface, its address, ...
8855139Storek  */
8955139Storek struct le_softc {
9055139Storek 	struct	device sc_dev;		/* base device */
9155139Storek 	struct	sbusdev sc_sd;		/* sbus device */
9255139Storek 	struct	intrhand sc_ih;		/* interrupt vectoring */
9359215Storek 	struct	evcnt sc_intrcnt;	/* # of interrupts, per le */
9459215Storek 	struct	evcnt sc_errcnt;	/* # of errors, per le */
9555139Storek 
9655139Storek 	struct	arpcom sc_ac;		/* common Ethernet structures */
9755139Storek #define	sc_if	sc_ac.ac_if		/* network-visible interface */
9855139Storek #define	sc_addr	sc_ac.ac_enaddr		/* hardware Ethernet address */
9955139Storek 	volatile struct	lereg1 *sc_r1;	/* LANCE registers */
10055139Storek 	volatile struct	lereg2 *sc_r2;	/* dual-port RAM */
10155139Storek 	int	sc_rmd;			/* predicted next rmd to process */
10255139Storek 	int	sc_runt;
10355139Storek 	int	sc_jab;
10455139Storek 	int	sc_merr;
10555139Storek 	int	sc_babl;
10655139Storek 	int	sc_cerr;
10755139Storek 	int	sc_miss;
10855139Storek 	int	sc_xint;
10955139Storek 	int	sc_xown;
11055139Storek 	int	sc_uflo;
11155139Storek 	int	sc_rxlen;
11255139Storek 	int	sc_rxoff;
11355139Storek 	int	sc_txoff;
11455139Storek 	int	sc_busy;
11555139Storek 	short	sc_iflags;
11655139Storek 	struct	lestats sc_lestats;	/* per interface statistics */
11755139Storek #if NBPFILTER > 0
11855139Storek 	caddr_t	sc_bpf;
11955139Storek #endif
12055139Storek };
12155139Storek 
12255139Storek 
12355139Storek /* autoconfiguration driver */
12455139Storek void	leattach(struct device *, struct device *, void *);
12555139Storek struct	cfdriver lecd =
12655139Storek     { NULL, "le", matchbyname, leattach, DV_IFNET, sizeof(struct le_softc) };
12755139Storek 
12855139Storek /* Forwards */
12955139Storek void	leattach(struct device *, struct device *, void *);
13055139Storek void	lesetladrf(struct le_softc *);
13155139Storek void	lereset(struct device *);
13255139Storek int	leinit(int);
13355139Storek int	lestart(struct ifnet *);
13455139Storek int	leintr(void *);
13555139Storek void	lexint(struct le_softc *);
13655139Storek void	lerint(struct le_softc *);
13755139Storek void	leread(struct le_softc *, char *, int);
13855139Storek int	leput(char *, struct mbuf *);
13955139Storek struct mbuf *leget(char *, int, int, struct ifnet *);
14055139Storek int	leioctl(struct ifnet *, int, caddr_t);
14155139Storek void	leerror(struct le_softc *, int);
14255139Storek void	lererror(struct le_softc *, char *);
14355139Storek void	lexerror(struct le_softc *);
14455139Storek 
14555139Storek /*
14655139Storek  * Interface exists: make available by filling in network interface
14755139Storek  * record.  System will initialize the interface when it is ready
14855139Storek  * to accept packets.
14955139Storek  */
15055139Storek void
leattach(parent,self,args)15155139Storek leattach(parent, self, args)
15255139Storek 	struct device *parent;
15355139Storek 	struct device *self;
15455139Storek 	void *args;
15555139Storek {
15655139Storek 	register struct le_softc *sc = (struct le_softc *)self;
15755139Storek 	register struct sbus_attach_args *sa = args;
15855139Storek 	register volatile struct lereg2 *ler2;
15955139Storek 	struct ifnet *ifp = &sc->sc_if;
16059215Storek 	register struct bootpath *bp;
16155139Storek 	register int a, pri;
16255139Storek 
16355139Storek 	/* XXX the following declarations should be elsewhere */
16455139Storek 	extern void myetheraddr(u_char *);
16555139Storek 	extern caddr_t dvma_malloc(size_t);
16655139Storek 
16755139Storek 	if (sa->sa_ra.ra_nintr != 1) {
16855139Storek 		printf(": expected 1 interrupt, got %d\n", sa->sa_ra.ra_nintr);
16955139Storek 		return;
17055139Storek 	}
17155139Storek 	pri = sa->sa_ra.ra_intr[0].int_pri;
17255139Storek 	printf(" pri %d", pri);
17355139Storek 	sc->sc_r1 = (volatile struct lereg1 *)
17455139Storek 	    mapiodev(sa->sa_ra.ra_paddr, sizeof(struct lereg1));
17555139Storek 	ler2 = sc->sc_r2 = (volatile struct lereg2 *)
17655139Storek 	    dvma_malloc(sizeof(struct lereg2));
17755139Storek 
17855139Storek 	myetheraddr(sc->sc_addr);
17955139Storek 	printf(": hardware address %s\n", ether_sprintf(sc->sc_addr));
18055139Storek 
18155139Storek 	/*
18255139Storek 	 * Setup for transmit/receive
18355139Storek 	 *
18455139Storek 	 * According to Van, some versions of the Lance only use this
18555139Storek 	 * address to receive packets; it doesn't put them in
18655139Storek 	 * output packets. We'll want to make sure that lestart()
18755139Storek 	 * installs the address.
18855139Storek 	 */
18955139Storek 	ler2->ler2_padr[0] = sc->sc_addr[1];
19055139Storek 	ler2->ler2_padr[1] = sc->sc_addr[0];
19155139Storek 	ler2->ler2_padr[2] = sc->sc_addr[3];
19255139Storek 	ler2->ler2_padr[3] = sc->sc_addr[2];
19355139Storek 	ler2->ler2_padr[4] = sc->sc_addr[5];
19455139Storek 	ler2->ler2_padr[5] = sc->sc_addr[4];
19555139Storek 	a = LANCE_ADDR(&ler2->ler2_rmd);
19655139Storek 	ler2->ler2_rlen = LE_RLEN | (a >> 16);
19755139Storek 	ler2->ler2_rdra = a;
19855139Storek 	a = LANCE_ADDR(&ler2->ler2_tmd);
19955139Storek 	ler2->ler2_tlen = LE_TLEN | (a >> 16);
20055139Storek 	ler2->ler2_tdra = a;
20155139Storek 
20255139Storek 	/*
20355139Storek 	 * Link into sbus, and establish interrupt handler.
20455139Storek 	 */
20555139Storek 	sc->sc_sd.sd_reset = lereset;
20655139Storek 	sbus_establish(&sc->sc_sd, &sc->sc_dev);
20755139Storek 	sc->sc_ih.ih_fun = leintr;
20855139Storek 	sc->sc_ih.ih_arg = sc;
20955139Storek 	intr_establish(pri, &sc->sc_ih);
21055139Storek 
21159215Storek 	/*
21259215Storek 	 * Set up event counters.
21359215Storek 	 */
21459215Storek 	evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt);
21559215Storek 	evcnt_attach(&sc->sc_dev, "errs", &sc->sc_errcnt);
21659215Storek 
21755139Storek 	ifp->if_unit = sc->sc_dev.dv_unit;
21855139Storek 	ifp->if_name = "le";
21955139Storek 	ifp->if_mtu = ETHERMTU;
22055139Storek 	ifp->if_init = leinit;
22155139Storek 	ifp->if_ioctl = leioctl;
22255139Storek 	ifp->if_output = ether_output;
22355139Storek 	ifp->if_start = lestart;
22455139Storek 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
22555139Storek #ifdef IFF_NOTRAILERS
22655139Storek 	/* XXX still compile when the blasted things are gone... */
22755139Storek 	ifp->if_flags |= IFF_NOTRAILERS;
22855139Storek #endif
22955139Storek #if NBPFILTER > 0
23055139Storek 	bpfattach(&sc->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
23155139Storek #endif
23255139Storek 	if_attach(ifp);
23359215Storek 
23459215Storek #define SAME_LANCE(bp, sa) \
23559215Storek 	((bp->val[0] == sa->sa_slot && bp->val[1] == sa->sa_offset) || \
23659215Storek 	 (bp->val[0] == -1 && bp->val[1] == sc->sc_dev.dv_unit))
23759215Storek 
23859215Storek 	bp = sa->sa_ra.ra_bp;
23959215Storek 	if (bp != NULL && strcmp(bp->name, "le") == 0 && SAME_LANCE(bp, sa))
24059215Storek 		bootdv = &sc->sc_dev;
24155139Storek }
24255139Storek 
24355139Storek /*
24455139Storek  * Setup the logical address filter
24555139Storek  */
24655139Storek void
lesetladrf(sc)24755139Storek lesetladrf(sc)
24855139Storek 	register struct le_softc *sc;
24955139Storek {
25055139Storek 	register volatile struct lereg2 *ler2 = sc->sc_r2;
25155139Storek 	register struct ifnet *ifp = &sc->sc_if;
25255139Storek 	register struct ether_multi *enm;
25359215Storek 	register u_char *cp, c;
25455139Storek 	register u_long crc;
25555139Storek 	register int i, len;
25655139Storek 	struct ether_multistep step;
25755139Storek 
25855139Storek 	/*
25955139Storek 	 * Set up multicast address filter by passing all multicast
26055139Storek 	 * addresses through a crc generator, and then using the high
26155139Storek 	 * order 6 bits as a index into the 64 bit logical address
26255139Storek 	 * filter. The high order two bits select the word, while the
26355139Storek 	 * rest of the bits select the bit within the word.
26455139Storek 	 */
26555139Storek 
26655139Storek 	ler2->ler2_ladrf[0] = 0;
26755139Storek 	ler2->ler2_ladrf[1] = 0;
268*64777Storek 	ler2->ler2_ladrf[2] = 0;
269*64777Storek 	ler2->ler2_ladrf[3] = 0;
27055139Storek 	ifp->if_flags &= ~IFF_ALLMULTI;
27155139Storek 	ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
27255139Storek 	while (enm != NULL) {
27355139Storek 		if (bcmp((caddr_t)&enm->enm_addrlo,
27459215Storek 		    (caddr_t)&enm->enm_addrhi, sizeof(enm->enm_addrlo)) != 0) {
27555139Storek 			/*
27655139Storek 			 * We must listen to a range of multicast
27755139Storek 			 * addresses. For now, just accept all
27855139Storek 			 * multicasts, rather than trying to set only
27955139Storek 			 * those filter bits needed to match the range.
28055139Storek 			 * (At this time, the only use of address
28155139Storek 			 * ranges is for IP multicast routing, for
28255139Storek 			 * which the range is big enough to require all
28355139Storek 			 * bits set.)
28455139Storek 			 */
285*64777Storek 			ler2->ler2_ladrf[0] = 0xffff;
286*64777Storek 			ler2->ler2_ladrf[1] = 0xffff;
287*64777Storek 			ler2->ler2_ladrf[2] = 0xffff;
288*64777Storek 			ler2->ler2_ladrf[3] = 0xffff;
28955139Storek 			ifp->if_flags |= IFF_ALLMULTI;
29055139Storek 			return;
29155139Storek 		}
29255139Storek 
29359215Storek 		/*
29459215Storek 		 * One would think, given the AM7990 document's polynomial
29559215Storek 		 * of 0x04c11db6, that this should be 0x6db88320 (the bit
29659215Storek 		 * reversal of the AMD value), but that is not right.  See
29759215Storek 		 * the BASIC listing: bit 0 (our bit 31) must then be set.
29859215Storek 		 */
29955139Storek 		cp = (unsigned char *)&enm->enm_addrlo;
30055139Storek 		crc = 0xffffffff;
30159215Storek 		for (len = 6; --len >= 0;) {
30259215Storek 			c = *cp++;
30355139Storek 			for (i = 0; i < 8; i++) {
30455139Storek 				if ((c & 0x01) ^ (crc & 0x01)) {
30555139Storek 					crc >>= 1;
30655139Storek 					crc = crc ^ 0xedb88320;
30759215Storek 				} else
30855139Storek 					crc >>= 1;
30955139Storek 				c >>= 1;
31055139Storek 			}
31155139Storek 		}
31255139Storek 		/* Just want the 6 most significant bits. */
31355139Storek 		crc = crc >> 26;
31455139Storek 
31555139Storek 		/* Turn on the corresponding bit in the filter. */
316*64777Storek 		ler2->ler2_ladrf[crc >> 4] |= 1 << (crc & 0xf);
31755139Storek 
31855139Storek 		ETHER_NEXT_MULTI(step, enm);
31955139Storek 	}
32055139Storek }
32155139Storek 
32255139Storek void
lereset(dev)32355139Storek lereset(dev)
32455139Storek 	struct device *dev;
32555139Storek {
32655139Storek 	register struct le_softc *sc = (struct le_softc *)dev;
32755139Storek 	register volatile struct lereg1 *ler1 = sc->sc_r1;
32855139Storek 	register volatile struct lereg2 *ler2 = sc->sc_r2;
32955139Storek 	register int i, a, timo, stat;
33055139Storek 
33155139Storek #if NBPFILTER > 0
33255139Storek 	if (sc->sc_if.if_flags & IFF_PROMISC)
33355139Storek 		ler2->ler2_mode = LE_MODE_NORMAL | LE_MODE_PROM;
33455139Storek 	else
33555139Storek #endif
33655139Storek 		ler2->ler2_mode = LE_MODE_NORMAL;
33755139Storek 	ler1->ler1_rap = LE_CSR0;
33855139Storek 	ler1->ler1_rdp = LE_C0_STOP;
33955139Storek 
34055139Storek 	/* Setup the logical address filter */
34155139Storek 	lesetladrf(sc);
34255139Storek 
34355139Storek 	/* init receive and transmit rings */
34455139Storek 	for (i = 0; i < LERBUF; i++) {
34555139Storek 		a = LANCE_ADDR(&ler2->ler2_rbuf[i][0]);
34655139Storek 		ler2->ler2_rmd[i].rmd0 = a;
34755139Storek 		ler2->ler2_rmd[i].rmd1_hadr = a >> 16;
34855139Storek 		ler2->ler2_rmd[i].rmd1_bits = LE_R1_OWN;
34955139Storek 		ler2->ler2_rmd[i].rmd2 = -LEMTU;
35055139Storek 		ler2->ler2_rmd[i].rmd3 = 0;
35155139Storek 	}
35255139Storek 	for (i = 0; i < LETBUF; i++) {
35355139Storek 		a = LANCE_ADDR(&ler2->ler2_tbuf[i][0]);
35455139Storek 		ler2->ler2_tmd[i].tmd0 = a;
35555139Storek 		ler2->ler2_tmd[i].tmd1_hadr = a >> 16;
35655139Storek 		ler2->ler2_tmd[i].tmd1_bits = 0;
35755139Storek 		ler2->ler2_tmd[i].tmd2 = 0;
35855139Storek 		ler2->ler2_tmd[i].tmd3 = 0;
35955139Storek 	}
36055139Storek 
36155139Storek bzero(&ler2->ler2_rbuf[0][0], (LERBUF + LETBUF) * LEMTU);
36255139Storek 	/* lance will stuff packet into receive buffer 0 next */
36355139Storek 	sc->sc_rmd = 0;
36455139Storek 
36555139Storek 	/* tell the chip where to find the initialization block */
36655139Storek 	a = LANCE_ADDR(&ler2->ler2_mode);
36755139Storek 	ler1->ler1_rap = LE_CSR1;
36855139Storek 	ler1->ler1_rdp = a;
36955139Storek 	ler1->ler1_rap = LE_CSR2;
37055139Storek 	ler1->ler1_rdp = a >> 16;
37155139Storek 	ler1->ler1_rap = LE_CSR3;
37255139Storek 	ler1->ler1_rdp = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON;
37355139Storek 	ler1->ler1_rap = LE_CSR0;
37455139Storek 	ler1->ler1_rdp = LE_C0_INIT;
37555139Storek 	timo = 100000;
37655139Storek 	while (((stat = ler1->ler1_rdp) & (LE_C0_ERR | LE_C0_IDON)) == 0) {
37755139Storek 		if (--timo == 0) {
37855139Storek 			printf("%s: init timeout, stat=%b\n",
37955139Storek 			    sc->sc_dev.dv_xname, stat, LE_C0_BITS);
38055139Storek 			break;
38155139Storek 		}
38255139Storek 	}
38355139Storek 	if (stat & LE_C0_ERR)
38455139Storek 		printf("%s: init failed, stat=%b\n",
38555139Storek 		    sc->sc_dev.dv_xname, stat, LE_C0_BITS);
38655139Storek 	else
38755139Storek 		ler1->ler1_rdp = LE_C0_IDON;	/* clear IDON */
38855139Storek 	ler1->ler1_rdp = LE_C0_STRT | LE_C0_INEA;
38955139Storek 	sc->sc_if.if_flags &= ~IFF_OACTIVE;
39055139Storek }
39155139Storek 
39255139Storek /*
39355139Storek  * Initialization of interface
39455139Storek  */
39555139Storek int
leinit(unit)39655139Storek leinit(unit)
39755139Storek 	int unit;
39855139Storek {
39955139Storek 	register struct le_softc *sc = lecd.cd_devs[unit];
40055139Storek 	register struct ifnet *ifp = &sc->sc_if;
40155139Storek 	register int s;
40255139Storek 
40355139Storek 	/* not yet, if address still unknown */
40455139Storek 	if (ifp->if_addrlist == (struct ifaddr *)0)
40555139Storek 		return (0);
40655139Storek 	if ((ifp->if_flags & IFF_RUNNING) == 0) {
40755139Storek 		s = splimp();
40855139Storek 		ifp->if_flags |= IFF_RUNNING;
409*64777Storek 		lereset(&sc->sc_dev);
41055139Storek 	        lestart(ifp);
41155139Storek 		splx(s);
41255139Storek 	}
41355139Storek 	return (0);
41455139Storek }
41555139Storek 
41655139Storek /*
41755139Storek  * Start output on interface.  Get another datagram to send
41855139Storek  * off of the interface queue, and copy it to the interface
41955139Storek  * before starting the output.
42055139Storek  */
42155139Storek int
lestart(ifp)42255139Storek lestart(ifp)
42355139Storek 	register struct ifnet *ifp;
42455139Storek {
42555139Storek 	register struct le_softc *sc = lecd.cd_devs[ifp->if_unit];
42655139Storek 	register volatile struct letmd *tmd;
42755139Storek 	register struct mbuf *m;
42855139Storek 	register int len;
42955139Storek 
43055139Storek 	if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
43155139Storek 		return (0);
43255139Storek 	IF_DEQUEUE(&sc->sc_if.if_snd, m);
43355139Storek 	if (m == 0)
43455139Storek 		return (0);
43555139Storek 	len = leput(sc->sc_r2->ler2_tbuf[0], m);
43655139Storek #if NBPFILTER > 0
43755139Storek 	/*
43855139Storek 	 * If bpf is listening on this interface, let it
43955139Storek 	 * see the packet before we commit it to the wire.
44055139Storek 	 */
44155139Storek 	if (sc->sc_bpf)
44255139Storek 		bpf_tap(sc->sc_bpf, sc->sc_r2->ler2_tbuf[0], len);
44355139Storek #endif
44455139Storek 
44555139Storek #ifdef PACKETSTATS
44655139Storek 	if (len <= LEMTU)
44755139Storek 		lexpacketsizes[len]++;
44855139Storek #endif
44955139Storek 	tmd = sc->sc_r2->ler2_tmd;
45055139Storek 	tmd->tmd3 = 0;
45155139Storek 	tmd->tmd2 = -len;
45255139Storek 	tmd->tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
45355139Storek 	sc->sc_if.if_flags |= IFF_OACTIVE;
45455139Storek 	return (0);
45555139Storek }
45655139Storek 
45755139Storek int
leintr(dev)45855139Storek leintr(dev)
45955139Storek 	register void *dev;
46055139Storek {
46155139Storek 	register struct le_softc *sc = dev;
46255139Storek 	register volatile struct lereg1 *ler1 = sc->sc_r1;
46355139Storek 	register int csr0;
46455139Storek 
46555139Storek 	csr0 = ler1->ler1_rdp;
46655139Storek 	if ((csr0 & LE_C0_INTR) == 0)
46755139Storek 		return (0);
46859215Storek 	sc->sc_intrcnt.ev_count++;
46955139Storek 
47055139Storek 	if (csr0 & LE_C0_ERR) {
47159215Storek 		sc->sc_errcnt.ev_count++;
47255139Storek 		leerror(sc, csr0);
47355139Storek 		if (csr0 & LE_C0_MERR) {
47455139Storek 			sc->sc_merr++;
475*64777Storek 			lereset(&sc->sc_dev);
47655139Storek 			return (1);
47755139Storek 		}
47855139Storek 		if (csr0 & LE_C0_BABL)
47955139Storek 			sc->sc_babl++;
48055139Storek 		if (csr0 & LE_C0_CERR)
48155139Storek 			sc->sc_cerr++;
48255139Storek 		if (csr0 & LE_C0_MISS)
48355139Storek 			sc->sc_miss++;
48455139Storek 		ler1->ler1_rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_INEA;
48555139Storek 	}
48655139Storek 	if ((csr0 & LE_C0_RXON) == 0) {
48755139Storek 		sc->sc_rxoff++;
488*64777Storek 		lereset(&sc->sc_dev);
48955139Storek 		return (1);
49055139Storek 	}
49155139Storek 	if ((csr0 & LE_C0_TXON) == 0) {
49255139Storek 		sc->sc_txoff++;
493*64777Storek 		lereset(&sc->sc_dev);
49455139Storek 		return (1);
49555139Storek 	}
49655139Storek 	if (csr0 & LE_C0_RINT) {
49755139Storek 		/* interrupt is cleared in lerint */
49855139Storek 		lerint(sc);
49955139Storek 	}
50055139Storek 	if (csr0 & LE_C0_TINT) {
50155139Storek 		ler1->ler1_rdp = LE_C0_TINT|LE_C0_INEA;
50255139Storek 		lexint(sc);
50355139Storek 	}
50455139Storek 	return (1);
50555139Storek }
50655139Storek 
50755139Storek /*
50855139Storek  * Ethernet interface transmitter interrupt.
50955139Storek  * Start another output if more data to send.
51055139Storek  */
51155139Storek void
lexint(sc)51255139Storek lexint(sc)
51355139Storek 	register struct le_softc *sc;
51455139Storek {
51555139Storek 	register volatile struct letmd *tmd = sc->sc_r2->ler2_tmd;
51655139Storek 
51755139Storek 	sc->sc_lestats.lexints++;
51855139Storek 	if ((sc->sc_if.if_flags & IFF_OACTIVE) == 0) {
51955139Storek 		sc->sc_xint++;
52055139Storek 		return;
52155139Storek 	}
52255139Storek 	if (tmd->tmd1_bits & LE_T1_OWN) {
52355139Storek 		sc->sc_xown++;
52455139Storek 		return;
52555139Storek 	}
52655139Storek 	if (tmd->tmd1_bits & LE_T1_ERR) {
52755139Storek err:
52855139Storek 		lexerror(sc);
52955139Storek 		sc->sc_if.if_oerrors++;
53055139Storek 		if (tmd->tmd3 & (LE_T3_BUFF|LE_T3_UFLO)) {
53155139Storek 			sc->sc_uflo++;
532*64777Storek 			lereset(&sc->sc_dev);
53355139Storek 		} else if (tmd->tmd3 & LE_T3_LCOL)
53455139Storek 			sc->sc_if.if_collisions++;
53555139Storek 		else if (tmd->tmd3 & LE_T3_RTRY)
53655139Storek 			sc->sc_if.if_collisions += 16;
53755139Storek 	}
53855139Storek 	else if (tmd->tmd3 & LE_T3_BUFF)
53955139Storek 		/* XXX documentation says BUFF not included in ERR */
54055139Storek 		goto err;
54155139Storek 	else if (tmd->tmd1_bits & LE_T1_ONE)
54255139Storek 		sc->sc_if.if_collisions++;
54355139Storek 	else if (tmd->tmd1_bits & LE_T1_MORE)
54455139Storek 		/* what is the real number? */
54555139Storek 		sc->sc_if.if_collisions += 2;
54655139Storek 	else
54755139Storek 		sc->sc_if.if_opackets++;
54855139Storek 	sc->sc_if.if_flags &= ~IFF_OACTIVE;
54955139Storek 	lestart(&sc->sc_if);
55055139Storek }
55155139Storek 
55255139Storek #define	LENEXTRMP \
55355139Storek 	if (++bix == LERBUF) bix = 0, rmd = sc->sc_r2->ler2_rmd; else ++rmd
55455139Storek 
55555139Storek /*
55655139Storek  * Ethernet interface receiver interrupt.
55755139Storek  * If input error just drop packet.
55855139Storek  * Decapsulate packet based on type and pass to type specific
55955139Storek  * higher-level input routine.
56055139Storek  */
56155139Storek void
lerint(sc)56255139Storek lerint(sc)
56355139Storek 	register struct le_softc *sc;
56455139Storek {
56555139Storek 	register int bix = sc->sc_rmd;
56655139Storek 	register volatile struct lermd *rmd = &sc->sc_r2->ler2_rmd[bix];
56755139Storek 
56855139Storek 	sc->sc_lestats.lerints++;
56955139Storek 	/*
57055139Storek 	 * Out of sync with hardware, should never happen?
57155139Storek 	 */
57255139Storek 	if (rmd->rmd1_bits & LE_R1_OWN) {
57355139Storek 		do {
57455139Storek 			sc->sc_lestats.lerscans++;
57555139Storek 			LENEXTRMP;
57655139Storek 		} while ((rmd->rmd1_bits & LE_R1_OWN) && bix != sc->sc_rmd);
57755139Storek 		if (bix == sc->sc_rmd)
57855139Storek 			printf("%s: RINT with no buffer\n",
57955139Storek 			    sc->sc_dev.dv_xname);
58055139Storek 	} else
58155139Storek 		sc->sc_lestats.lerhits++;
58255139Storek 
58355139Storek 	/*
58455139Storek 	 * Process all buffers with valid data
58555139Storek 	 */
58655139Storek 	while ((rmd->rmd1_bits & LE_R1_OWN) == 0) {
58755139Storek 		int len = rmd->rmd3;
58855139Storek 
58955139Storek 		/* Clear interrupt to avoid race condition */
59055139Storek 		sc->sc_r1->ler1_rdp = LE_C0_RINT|LE_C0_INEA;
59155139Storek 
59255139Storek 		if (rmd->rmd1_bits & LE_R1_ERR) {
59355139Storek 			sc->sc_rmd = bix;
59455139Storek 			lererror(sc, "bad packet");
59555139Storek 			sc->sc_if.if_ierrors++;
59655139Storek 		} else if ((rmd->rmd1_bits & (LE_R1_STP|LE_R1_ENP)) !=
59755139Storek 		    (LE_R1_STP|LE_R1_ENP)) {
59855139Storek 			/* XXX make a define for LE_R1_STP|LE_R1_ENP? */
59955139Storek 			/*
60055139Storek 			 * Find the end of the packet so we can see how long
60155139Storek 			 * it was.  We still throw it away.
60255139Storek 			 */
60355139Storek 			do {
60455139Storek 				sc->sc_r1->ler1_rdp = LE_C0_RINT|LE_C0_INEA;
60555139Storek 				rmd->rmd3 = 0;
60655139Storek 				rmd->rmd1_bits = LE_R1_OWN;
60755139Storek 				LENEXTRMP;
60855139Storek 			} while (!(rmd->rmd1_bits &
60955139Storek 			    (LE_R1_OWN|LE_R1_ERR|LE_R1_STP|LE_R1_ENP)));
61055139Storek 			sc->sc_rmd = bix;
61155139Storek 			lererror(sc, "chained buffer");
61255139Storek 			sc->sc_rxlen++;
61355139Storek 			/*
61455139Storek 			 * If search terminated without successful completion
61555139Storek 			 * we reset the hardware (conservative).
61655139Storek 			 */
61755139Storek 			if ((rmd->rmd1_bits &
61855139Storek 			    (LE_R1_OWN|LE_R1_ERR|LE_R1_STP|LE_R1_ENP)) !=
61955139Storek 			    LE_R1_ENP) {
620*64777Storek 				lereset(&sc->sc_dev);
62155139Storek 				return;
62255139Storek 			}
62355139Storek 		} else {
62455139Storek 			leread(sc, sc->sc_r2->ler2_rbuf[bix], len);
62555139Storek #ifdef PACKETSTATS
62655139Storek 			lerpacketsizes[len]++;
62755139Storek #endif
62855139Storek 			sc->sc_lestats.lerbufs++;
62955139Storek 		}
63055139Storek 		rmd->rmd3 = 0;
63155139Storek 		rmd->rmd1_bits = LE_R1_OWN;
63255139Storek 		LENEXTRMP;
63355139Storek 	}
63455139Storek 	sc->sc_rmd = bix;
63555139Storek }
63655139Storek 
63755139Storek void
leread(sc,pkt,len)63855139Storek leread(sc, pkt, len)
63955139Storek 	register struct le_softc *sc;
64055139Storek 	char *pkt;
64155139Storek 	int len;
64255139Storek {
64355139Storek 	register struct ether_header *et;
64455139Storek 	register struct ifnet *ifp = &sc->sc_if;
64555139Storek 	struct mbuf *m;
64655139Storek 	struct ifqueue *inq;
64755139Storek 	int flags;
64855139Storek 
64955139Storek 	ifp->if_ipackets++;
65055139Storek 	et = (struct ether_header *)pkt;
65155139Storek 	et->ether_type = ntohs((u_short)et->ether_type);
65255139Storek 	/* adjust input length to account for header and CRC */
65355139Storek 	len -= sizeof(struct ether_header) + 4;
65455139Storek 
65555139Storek 	if (len <= 0) {
65655139Storek 		if (ledebug)
65755139Storek 			log(LOG_WARNING,
65855139Storek 			    "%s: ierror(runt packet): from %s: len=%d\n",
65955139Storek 			    sc->sc_dev.dv_xname,
66055139Storek 			    ether_sprintf(et->ether_shost), len);
66155139Storek 		sc->sc_runt++;
66255139Storek 		ifp->if_ierrors++;
66355139Storek 		return;
66455139Storek 	}
66555139Storek 
66655139Storek 	/* Setup mbuf flags we'll need later */
66755139Storek 	flags = 0;
66855139Storek 	if (bcmp((caddr_t)etherbroadcastaddr,
66955139Storek 	    (caddr_t)et->ether_dhost, sizeof(etherbroadcastaddr)) == 0)
67055139Storek 		flags |= M_BCAST;
67155139Storek 	if (et->ether_dhost[0] & 1)
67255139Storek 		flags |= M_MCAST;
67355139Storek 
67455139Storek #if NBPFILTER > 0
67555139Storek 	/*
67655139Storek 	 * Check if there's a bpf filter listening on this interface.
67759215Storek 	 * If so, hand off the raw packet to enet, then discard things
67859215Storek 	 * not destined for us (but be sure to keep broadcast/multicast).
67955139Storek 	 */
68055139Storek 	if (sc->sc_bpf) {
68155139Storek 		bpf_tap(sc->sc_bpf, pkt, len + sizeof(struct ether_header));
68259215Storek 		if ((flags & (M_BCAST | M_MCAST)) == 0 &&
68355139Storek 		    bcmp(et->ether_dhost, sc->sc_addr,
68459215Storek 			    sizeof(et->ether_dhost)) != 0)
68555139Storek 			return;
68655139Storek 	}
68755139Storek #endif
68855139Storek 	m = leget(pkt, len, 0, ifp);
68955139Storek 	if (m == 0)
69055139Storek 		return;
69155139Storek 
69255139Storek 	/* XXX this code comes from ether_input() */
69355139Storek 	ifp->if_lastchange = time;
69455139Storek 	ifp->if_ibytes += m->m_pkthdr.len + sizeof (*et);
69555139Storek 	if (flags) {
69655139Storek 		m->m_flags |= flags;
69755139Storek 		ifp->if_imcasts++;
69855139Storek 	}
69955139Storek 	/* XXX end of code from ether_input() */
70055139Storek 
70155139Storek 	switch (et->ether_type) {
70255139Storek 
70355139Storek #ifdef INET
70455139Storek 	case ETHERTYPE_IP:
70555139Storek 		schednetisr(NETISR_IP);
70655139Storek 		inq = &ipintrq;
70755139Storek 		break;
70855139Storek 
70955139Storek 	case ETHERTYPE_ARP:
71055139Storek 		schednetisr(NETISR_ARP);
71155139Storek 		inq = &arpintrq;
71255139Storek 		break;
71355139Storek #endif
71455139Storek #ifdef NS
71555139Storek 	case ETHERTYPE_NS:
71655139Storek 		schednetisr(NETISR_NS);
71755139Storek 		inq = &nsintrq;
71855139Storek 		break;
71955139Storek #endif
72055139Storek 
72155139Storek #ifdef UTAHONLY
72255139Storek #ifdef APPLETALK
72355139Storek 	case ETHERTYPE_APPLETALK:
72455139Storek 		schednetisr(NETISR_DDP);
72555139Storek 		inq = &ddpintq;
72655139Storek 		break;
72755139Storek 
72855139Storek 	case ETHERTYPE_AARP:
72955139Storek 		aarpinput(&sc->sc_ac, m);
73055139Storek 		return;
73155139Storek #endif
73255139Storek #endif
73355139Storek 	default:
73455139Storek 		m_freem(m);
73555139Storek 		return;
73655139Storek 	}
73755139Storek 
73855139Storek 	if (IF_QFULL(inq)) {
73955139Storek 		IF_DROP(inq);
74055139Storek 		m_freem(m);
74155139Storek 		return;
74255139Storek 	}
74355139Storek 	IF_ENQUEUE(inq, m);
74455139Storek }
74555139Storek 
74655139Storek /*
74755139Storek  * Routine to copy from mbuf chain to transmit
74855139Storek  * buffer in board local memory.
74955139Storek  *
75055139Storek  * ### this can be done by remapping in some cases
75155139Storek  */
75255139Storek int
leput(lebuf,m)75355139Storek leput(lebuf, m)
75455139Storek 	register char *lebuf;
75555139Storek 	register struct mbuf *m;
75655139Storek {
75755139Storek 	register struct mbuf *mp;
75855139Storek 	register int len, tlen = 0;
75955139Storek 
76055139Storek 	for (mp = m; mp; mp = mp->m_next) {
76155139Storek 		len = mp->m_len;
76255139Storek 		if (len == 0)
76355139Storek 			continue;
76455139Storek 		tlen += len;
76555139Storek 		bcopy(mtod(mp, char *), lebuf, len);
76655139Storek 		lebuf += len;
76755139Storek 	}
76855139Storek 	m_freem(m);
76955139Storek 	if (tlen < LEMINSIZE) {
77055139Storek 		bzero(lebuf, LEMINSIZE - tlen);
77155139Storek 		tlen = LEMINSIZE;
77255139Storek 	}
77355139Storek 	return (tlen);
77455139Storek }
77555139Storek 
77655139Storek /*
77755139Storek  * Routine to copy from board local memory into mbufs.
77855139Storek  */
77955139Storek struct mbuf *
leget(lebuf,totlen,off0,ifp)78055139Storek leget(lebuf, totlen, off0, ifp)
78155139Storek 	char *lebuf;
78255139Storek 	int totlen, off0;
78355139Storek 	struct ifnet *ifp;
78455139Storek {
78555139Storek 	register struct mbuf *m;
78655139Storek 	struct mbuf *top = 0, **mp = &top;
78755139Storek 	register int off = off0, len;
78855139Storek 	register char *cp;
78955139Storek 	char *epkt;
79055139Storek 
79155139Storek 	lebuf += sizeof(struct ether_header);
79255139Storek 	cp = lebuf;
79355139Storek 	epkt = cp + totlen;
79455139Storek 	if (off) {
79555139Storek 		cp += off + 2 * sizeof(u_short);
79655139Storek 		totlen -= 2 * sizeof(u_short);
79755139Storek 	}
79855139Storek 
79955139Storek 	MGETHDR(m, M_DONTWAIT, MT_DATA);
80055139Storek 	if (m == 0)
80155139Storek 		return (0);
80255139Storek 	m->m_pkthdr.rcvif = ifp;
80355139Storek 	m->m_pkthdr.len = totlen;
80455139Storek 	m->m_len = MHLEN;
80555139Storek 
80655139Storek 	while (totlen > 0) {
80755139Storek 		if (top) {
80855139Storek 			MGET(m, M_DONTWAIT, MT_DATA);
80955139Storek 			if (m == 0) {
81055139Storek 				m_freem(top);
81155139Storek 				return (0);
81255139Storek 			}
81355139Storek 			m->m_len = MLEN;
81455139Storek 		}
81555139Storek 		len = min(totlen, epkt - cp);
81655139Storek 		if (len >= MINCLSIZE) {
81755139Storek 			MCLGET(m, M_DONTWAIT);
81855139Storek 			if (m->m_flags & M_EXT)
81955139Storek 				m->m_len = len = min(len, MCLBYTES);
82055139Storek 			else
82155139Storek 				len = m->m_len;
82255139Storek 		} else {
82355139Storek 			/*
82455139Storek 			 * Place initial small packet/header at end of mbuf.
82555139Storek 			 */
82655139Storek 			if (len < m->m_len) {
82755139Storek 				if (top == 0 && len + max_linkhdr <= m->m_len)
82855139Storek 					m->m_data += max_linkhdr;
82955139Storek 				m->m_len = len;
83055139Storek 			} else
83155139Storek 				len = m->m_len;
83255139Storek 		}
83355139Storek 		bcopy(cp, mtod(m, caddr_t), (unsigned)len);
83455139Storek 		cp += len;
83555139Storek 		*mp = m;
83655139Storek 		mp = &m->m_next;
83755139Storek 		totlen -= len;
83855139Storek 		if (cp == epkt)
83955139Storek 			cp = lebuf;
84055139Storek 	}
84155139Storek 	return (top);
84255139Storek }
84355139Storek 
84455139Storek /*
84555139Storek  * Process an ioctl request.
84655139Storek  */
84755139Storek int
leioctl(ifp,cmd,data)84855139Storek leioctl(ifp, cmd, data)
84955139Storek 	register struct ifnet *ifp;
85055139Storek 	int cmd;
85155139Storek 	caddr_t data;
85255139Storek {
85355139Storek 	register struct ifaddr *ifa;
85455139Storek 	register struct le_softc *sc = lecd.cd_devs[ifp->if_unit];
85555139Storek 	register volatile struct lereg1 *ler1;
85655139Storek 	int s = splimp(), error = 0;
85755139Storek 
85855139Storek 	switch (cmd) {
85955139Storek 
86055139Storek 	case SIOCSIFADDR:
86155139Storek 		ifa = (struct ifaddr *)data;
86255139Storek 		ifp->if_flags |= IFF_UP;
86355139Storek 		switch (ifa->ifa_addr->sa_family) {
86455139Storek #ifdef INET
86555139Storek 		case AF_INET:
86655139Storek 			(void)leinit(ifp->if_unit);	/* before arpwhohas */
86755139Storek 			((struct arpcom *)ifp)->ac_ipaddr =
86855139Storek 				IA_SIN(ifa)->sin_addr;
86955139Storek 			arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
87055139Storek 			break;
87155139Storek #endif
87255139Storek #ifdef NS
87355139Storek 		case AF_NS:
87455139Storek 		    {
87555139Storek 			register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
87655139Storek 
87755139Storek 			if (ns_nullhost(*ina))
87855139Storek 				ina->x_host = *(union ns_host *)(sc->sc_addr);
87955139Storek 			else {
88055139Storek 				/*
88155139Storek 				 * The manual says we can't change the address
88255139Storek 				 * while the receiver is armed,
88355139Storek 				 * so reset everything
88455139Storek 				 */
88555139Storek 				ifp->if_flags &= ~IFF_RUNNING;
88655139Storek 				bcopy((caddr_t)ina->x_host.c_host,
88755139Storek 				    (caddr_t)sc->sc_addr, sizeof(sc->sc_addr));
88855139Storek 			}
88955139Storek 			(void)leinit(ifp->if_unit);	/* does le_setaddr() */
89055139Storek 			break;
89155139Storek 		    }
89255139Storek #endif
89355139Storek 		default:
89455139Storek 			(void)leinit(ifp->if_unit);
89555139Storek 			break;
89655139Storek 		}
89755139Storek 		break;
89855139Storek 
89955139Storek 	case SIOCSIFFLAGS:
90055139Storek 		ler1 = sc->sc_r1;
90155139Storek 		if ((ifp->if_flags & IFF_UP) == 0 &&
90255139Storek 		    ifp->if_flags & IFF_RUNNING) {
90355139Storek 			ler1->ler1_rdp = LE_C0_STOP;
90455139Storek 			ifp->if_flags &= ~IFF_RUNNING;
90555139Storek 		} else if (ifp->if_flags & IFF_UP &&
90655139Storek 		    (ifp->if_flags & IFF_RUNNING) == 0)
90755139Storek 			(void)leinit(ifp->if_unit);
90855139Storek 		/*
90955139Storek 		 * If the state of the promiscuous bit changes, the interface
91055139Storek 		 * must be reset to effect the change.
91155139Storek 		 */
91255139Storek 		if (((ifp->if_flags ^ sc->sc_iflags) & IFF_PROMISC) &&
91355139Storek 		    (ifp->if_flags & IFF_RUNNING)) {
91455139Storek 			sc->sc_iflags = ifp->if_flags;
915*64777Storek 			lereset(&sc->sc_dev);
91655139Storek 			lestart(ifp);
91755139Storek 		}
91855139Storek 		break;
91955139Storek 
92055139Storek 	case SIOCADDMULTI:
92159215Storek 		error = ether_addmulti((struct ifreq *)data, &sc->sc_ac);
92259215Storek 		goto update_multicast;
92359215Storek 
92455139Storek 	case SIOCDELMULTI:
92559215Storek 		error = ether_delmulti((struct ifreq *)data, &sc->sc_ac);
92659215Storek 	update_multicast:
92755139Storek 		if (error == ENETRESET) {
92855139Storek 			/*
92955139Storek 			 * Multicast list has changed; set the hardware
93055139Storek 			 * filter accordingly.
93155139Storek 			 */
932*64777Storek 			lereset(&sc->sc_dev);
93355139Storek 			error = 0;
93455139Storek 		}
93555139Storek 		break;
93655139Storek 
93755139Storek 	default:
93855139Storek 		error = EINVAL;
93955139Storek 	}
94055139Storek 	splx(s);
94155139Storek 	return (error);
94255139Storek }
94355139Storek 
94455139Storek void
leerror(sc,stat)94555139Storek leerror(sc, stat)
94655139Storek 	register struct le_softc *sc;
94755139Storek 	int stat;
94855139Storek {
94955139Storek 	if (!ledebug)
95055139Storek 		return;
95155139Storek 
95255139Storek 	/*
95355139Storek 	 * Not all transceivers implement heartbeat
95455139Storek 	 * so we only log CERR once.
95555139Storek 	 */
95655139Storek 	if ((stat & LE_C0_CERR) && sc->sc_cerr)
95755139Storek 		return;
95855139Storek 	log(LOG_WARNING, "%s: error: stat=%b\n",
95955139Storek 	    sc->sc_dev.dv_xname, stat, LE_C0_BITS);
96055139Storek }
96155139Storek 
96255139Storek void
lererror(sc,msg)96355139Storek lererror(sc, msg)
96455139Storek 	register struct le_softc *sc;
96555139Storek 	char *msg;
96655139Storek {
96755139Storek 	register volatile struct lermd *rmd;
96855139Storek 	int len;
96955139Storek 
97055139Storek 	if (!ledebug)
97155139Storek 		return;
97255139Storek 
97355139Storek 	rmd = &sc->sc_r2->ler2_rmd[sc->sc_rmd];
97455139Storek 	len = rmd->rmd3;
97555139Storek 	log(LOG_WARNING, "%s: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
97655139Storek 	    sc->sc_dev.dv_xname, msg, len > 11 ?
97755139Storek 	    ether_sprintf((u_char *)&sc->sc_r2->ler2_rbuf[sc->sc_rmd][6]) :
97855139Storek 	    "unknown",
97955139Storek 	    sc->sc_rmd, len, rmd->rmd1_bits, LE_R1_BITS);
98055139Storek }
98155139Storek 
98255139Storek void
lexerror(sc)98355139Storek lexerror(sc)
98455139Storek 	register struct le_softc *sc;
98555139Storek {
98655139Storek 	register volatile struct letmd *tmd;
98755139Storek 	register int len, tmd3, tdr;
98855139Storek 
98955139Storek 	if (!ledebug)
99055139Storek 		return;
99155139Storek 
99255139Storek 	tmd = sc->sc_r2->ler2_tmd;
99355139Storek 	tmd3 = tmd->tmd3;
99455139Storek 	tdr = tmd3 & LE_T3_TDR_MASK;
99555139Storek 	len = -tmd->tmd2;
99655139Storek 	log(LOG_WARNING,
99755139Storek     "%s: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b, tdr=%d (%d nsecs)\n",
99855139Storek 	    sc->sc_dev.dv_xname, len > 5 ?
99955139Storek 	    ether_sprintf((u_char *)&sc->sc_r2->ler2_tbuf[0][0]) : "unknown",
100055139Storek 	    0, len,
100155139Storek 	    tmd->tmd1_bits, LE_T1_BITS,
100255139Storek 	    tmd3, LE_T3_BITS, tdr, tdr * 100);
100355139Storek }
1004