xref: /csrg-svn/sys/sparc/sbus/if_le.c (revision 55139)
1*55139Storek /*-
2*55139Storek  * Copyright (c) 1982, 1992 The Regents of the University of California.
3*55139Storek  * All rights reserved.
4*55139Storek  *
5*55139Storek  * %sccs.include.redist.c%
6*55139Storek  *
7*55139Storek  *	@(#)if_le.c	7.1 (Berkeley) 07/13/92
8*55139Storek  *
9*55139Storek  * from: $Header: if_le.c,v 1.17 92/07/10 06:45:17 torek Exp $
10*55139Storek  */
11*55139Storek 
12*55139Storek #include "bpfilter.h"
13*55139Storek 
14*55139Storek /*
15*55139Storek  * AMD 7990 LANCE
16*55139Storek  *
17*55139Storek  * This driver will generate and accept tailer encapsulated packets even
18*55139Storek  * though it buys us nothing.  The motivation was to avoid incompatibilities
19*55139Storek  * with VAXen, SUNs, and others that handle and benefit from them.
20*55139Storek  * This reasoning is dubious.
21*55139Storek  */
22*55139Storek #include "sys/param.h"
23*55139Storek #include "sys/device.h"
24*55139Storek #include "sys/systm.h"
25*55139Storek #include "sys/kernel.h"
26*55139Storek #include "sys/mbuf.h"
27*55139Storek #include "sys/buf.h"
28*55139Storek #include "sys/socket.h"
29*55139Storek #include "sys/syslog.h"
30*55139Storek #include "sys/ioctl.h"
31*55139Storek #include "sys/malloc.h"
32*55139Storek #include "sys/errno.h"
33*55139Storek 
34*55139Storek #include "../net/if.h"
35*55139Storek #include "../net/netisr.h"
36*55139Storek #include "../net/route.h"
37*55139Storek #if NBPFILTER > 0
38*55139Storek #include "sys/select.h"
39*55139Storek #include "../net/bpf.h"
40*55139Storek #include "../net/bpfdesc.h"
41*55139Storek #endif
42*55139Storek 
43*55139Storek #ifdef INET
44*55139Storek #include "../netinet/in.h"
45*55139Storek #include "../netinet/in_systm.h"
46*55139Storek #include "../netinet/in_var.h"
47*55139Storek #include "../netinet/ip.h"
48*55139Storek #include "../netinet/if_ether.h"
49*55139Storek #endif
50*55139Storek 
51*55139Storek #ifdef NS
52*55139Storek #include "../netns/ns.h"
53*55139Storek #include "../netns/ns_if.h"
54*55139Storek #endif
55*55139Storek 
56*55139Storek #ifdef APPLETALK
57*55139Storek #include "../netddp/atalk.h"
58*55139Storek #endif
59*55139Storek 
60*55139Storek #include "machine/autoconf.h"
61*55139Storek #include "machine/cpu.h"
62*55139Storek #include "machine/pmap.h"
63*55139Storek 
64*55139Storek #include "if_lereg.h"
65*55139Storek #include "sbusvar.h"
66*55139Storek 
67*55139Storek /* DVMA address to LANCE address -- the Sbus/MMU will resupply the 0xff */
68*55139Storek #define	LANCE_ADDR(x)	((int)(x) & ~0xff000000)
69*55139Storek 
70*55139Storek int	ledebug = 0;		/* console error messages */
71*55139Storek 
72*55139Storek #ifdef PACKETSTATS
73*55139Storek long	lexpacketsizes[LEMTU+1];
74*55139Storek long	lerpacketsizes[LEMTU+1];
75*55139Storek #endif
76*55139Storek 
77*55139Storek /* Per interface statistics */
78*55139Storek /* XXX this should go in something like if_levar.h */
79*55139Storek struct	lestats {
80*55139Storek 	long	lexints;	/* transmitter interrupts */
81*55139Storek 	long	lerints;	/* receiver interrupts */
82*55139Storek 	long	lerbufs;	/* total buffers received during interrupts */
83*55139Storek 	long	lerhits;	/* times current rbuf was full */
84*55139Storek 	long	lerscans;	/* rbufs scanned before finding first full */
85*55139Storek };
86*55139Storek 
87*55139Storek /*
88*55139Storek  * Ethernet software status per interface.
89*55139Storek  *
90*55139Storek  * Each interface is referenced by a network interface structure,
91*55139Storek  * le_if, which the routing code uses to locate the interface.
92*55139Storek  * This structure contains the output queue for the interface, its address, ...
93*55139Storek  */
94*55139Storek struct le_softc {
95*55139Storek 	struct	device sc_dev;		/* base device */
96*55139Storek 	struct	sbusdev sc_sd;		/* sbus device */
97*55139Storek 	struct	intrhand sc_ih;		/* interrupt vectoring */
98*55139Storek 	int	sc_interrupts;		/* number of interrupts taken */
99*55139Storek 
100*55139Storek 	struct	arpcom sc_ac;		/* common Ethernet structures */
101*55139Storek #define	sc_if	sc_ac.ac_if		/* network-visible interface */
102*55139Storek #define	sc_addr	sc_ac.ac_enaddr		/* hardware Ethernet address */
103*55139Storek 	volatile struct	lereg1 *sc_r1;	/* LANCE registers */
104*55139Storek 	volatile struct	lereg2 *sc_r2;	/* dual-port RAM */
105*55139Storek 	int	sc_rmd;			/* predicted next rmd to process */
106*55139Storek 	int	sc_runt;
107*55139Storek 	int	sc_jab;
108*55139Storek 	int	sc_merr;
109*55139Storek 	int	sc_babl;
110*55139Storek 	int	sc_cerr;
111*55139Storek 	int	sc_miss;
112*55139Storek 	int	sc_xint;
113*55139Storek 	int	sc_xown;
114*55139Storek 	int	sc_uflo;
115*55139Storek 	int	sc_rxlen;
116*55139Storek 	int	sc_rxoff;
117*55139Storek 	int	sc_txoff;
118*55139Storek 	int	sc_busy;
119*55139Storek 	short	sc_iflags;
120*55139Storek 	struct	lestats sc_lestats;	/* per interface statistics */
121*55139Storek #if NBPFILTER > 0
122*55139Storek 	caddr_t	sc_bpf;
123*55139Storek #endif
124*55139Storek };
125*55139Storek 
126*55139Storek 
127*55139Storek /* autoconfiguration driver */
128*55139Storek void	leattach(struct device *, struct device *, void *);
129*55139Storek struct	cfdriver lecd =
130*55139Storek     { NULL, "le", matchbyname, leattach, DV_IFNET, sizeof(struct le_softc) };
131*55139Storek 
132*55139Storek /* Forwards */
133*55139Storek void	leattach(struct device *, struct device *, void *);
134*55139Storek #ifdef MULTICAST
135*55139Storek void	lesetladrf(struct le_softc *);
136*55139Storek #endif
137*55139Storek void	lereset(struct device *);
138*55139Storek int	leinit(int);
139*55139Storek int	lestart(struct ifnet *);
140*55139Storek int	leintr(void *);
141*55139Storek void	lexint(struct le_softc *);
142*55139Storek void	lerint(struct le_softc *);
143*55139Storek void	leread(struct le_softc *, char *, int);
144*55139Storek int	leput(char *, struct mbuf *);
145*55139Storek struct mbuf *leget(char *, int, int, struct ifnet *);
146*55139Storek int	leioctl(struct ifnet *, int, caddr_t);
147*55139Storek void	leerror(struct le_softc *, int);
148*55139Storek void	lererror(struct le_softc *, char *);
149*55139Storek void	lexerror(struct le_softc *);
150*55139Storek 
151*55139Storek /*
152*55139Storek  * Interface exists: make available by filling in network interface
153*55139Storek  * record.  System will initialize the interface when it is ready
154*55139Storek  * to accept packets.
155*55139Storek  */
156*55139Storek void
157*55139Storek leattach(parent, self, args)
158*55139Storek 	struct device *parent;
159*55139Storek 	struct device *self;
160*55139Storek 	void *args;
161*55139Storek {
162*55139Storek 	register struct le_softc *sc = (struct le_softc *)self;
163*55139Storek 	register struct sbus_attach_args *sa = args;
164*55139Storek 	register volatile struct lereg2 *ler2;
165*55139Storek 	struct ifnet *ifp = &sc->sc_if;
166*55139Storek 	register int a, pri;
167*55139Storek #define	ISQUADALIGN(a) ((((long) a) & 0x3) == 0)
168*55139Storek 
169*55139Storek 	/* XXX the following declarations should be elsewhere */
170*55139Storek 	extern void myetheraddr(u_char *);
171*55139Storek 	extern caddr_t dvma_malloc(size_t);
172*55139Storek 
173*55139Storek 	if (sa->sa_ra.ra_nintr != 1) {
174*55139Storek 		printf(": expected 1 interrupt, got %d\n", sa->sa_ra.ra_nintr);
175*55139Storek 		return;
176*55139Storek 	}
177*55139Storek 	pri = sa->sa_ra.ra_intr[0].int_pri;
178*55139Storek 	printf(" pri %d", pri);
179*55139Storek 	sc->sc_r1 = (volatile struct lereg1 *)
180*55139Storek 	    mapiodev(sa->sa_ra.ra_paddr, sizeof(struct lereg1));
181*55139Storek 	ler2 = sc->sc_r2 = (volatile struct lereg2 *)
182*55139Storek 	    dvma_malloc(sizeof(struct lereg2));
183*55139Storek if (!ISQUADALIGN(ler2))
184*55139Storek 	printf("? not quad aligned (0x%x)\n", ler2);
185*55139Storek 
186*55139Storek 	myetheraddr(sc->sc_addr);
187*55139Storek 	printf(": hardware address %s\n", ether_sprintf(sc->sc_addr));
188*55139Storek 
189*55139Storek 	/*
190*55139Storek 	 * Setup for transmit/receive
191*55139Storek 	 *
192*55139Storek 	 * According to Van, some versions of the Lance only use this
193*55139Storek 	 * address to receive packets; it doesn't put them in
194*55139Storek 	 * output packets. We'll want to make sure that lestart()
195*55139Storek 	 * installs the address.
196*55139Storek 	 */
197*55139Storek 	ler2->ler2_padr[0] = sc->sc_addr[1];
198*55139Storek 	ler2->ler2_padr[1] = sc->sc_addr[0];
199*55139Storek 	ler2->ler2_padr[2] = sc->sc_addr[3];
200*55139Storek 	ler2->ler2_padr[3] = sc->sc_addr[2];
201*55139Storek 	ler2->ler2_padr[4] = sc->sc_addr[5];
202*55139Storek 	ler2->ler2_padr[5] = sc->sc_addr[4];
203*55139Storek 	a = LANCE_ADDR(&ler2->ler2_rmd);
204*55139Storek if (!ISQUADALIGN(a))
205*55139Storek 	printf("rdra not quad aligned (0x%x)\n", a);
206*55139Storek 	ler2->ler2_rlen = LE_RLEN | (a >> 16);
207*55139Storek 	ler2->ler2_rdra = a;
208*55139Storek 	a = LANCE_ADDR(&ler2->ler2_tmd);
209*55139Storek if (!ISQUADALIGN(a))
210*55139Storek 	printf("tdra not quad aligned (0x%x)\n", a);
211*55139Storek 	ler2->ler2_tlen = LE_TLEN | (a >> 16);
212*55139Storek 	ler2->ler2_tdra = a;
213*55139Storek 
214*55139Storek 	/*
215*55139Storek 	 * Link into sbus, and establish interrupt handler.
216*55139Storek 	 */
217*55139Storek 	sc->sc_sd.sd_reset = lereset;
218*55139Storek 	sbus_establish(&sc->sc_sd, &sc->sc_dev);
219*55139Storek 	sc->sc_ih.ih_fun = leintr;
220*55139Storek 	sc->sc_ih.ih_arg = sc;
221*55139Storek 	intr_establish(pri, &sc->sc_ih);
222*55139Storek 
223*55139Storek 	ifp->if_unit = sc->sc_dev.dv_unit;
224*55139Storek 	ifp->if_name = "le";
225*55139Storek 	ifp->if_mtu = ETHERMTU;
226*55139Storek 	ifp->if_init = leinit;
227*55139Storek 	ifp->if_ioctl = leioctl;
228*55139Storek 	ifp->if_output = ether_output;
229*55139Storek 	ifp->if_start = lestart;
230*55139Storek #ifdef MULTICAST
231*55139Storek 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
232*55139Storek #else
233*55139Storek 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
234*55139Storek #endif
235*55139Storek #ifdef IFF_NOTRAILERS
236*55139Storek 	/* XXX still compile when the blasted things are gone... */
237*55139Storek 	ifp->if_flags |= IFF_NOTRAILERS;
238*55139Storek #endif
239*55139Storek #if NBPFILTER > 0
240*55139Storek 	bpfattach(&sc->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
241*55139Storek #endif
242*55139Storek 	if_attach(ifp);
243*55139Storek }
244*55139Storek 
245*55139Storek #ifdef MULTICAST
246*55139Storek /*
247*55139Storek  * Setup the logical address filter
248*55139Storek  */
249*55139Storek void
250*55139Storek lesetladrf(sc)
251*55139Storek 	register struct le_softc *sc;
252*55139Storek {
253*55139Storek 	register volatile struct lereg2 *ler2 = sc->sc_r2;
254*55139Storek 	register struct ifnet *ifp = &sc->sc_if;
255*55139Storek 	register struct ether_multi *enm;
256*55139Storek 	register u_char *cp;
257*55139Storek 	register u_long crc;
258*55139Storek 	register u_long c;
259*55139Storek 	register int i, len;
260*55139Storek 	struct ether_multistep step;
261*55139Storek 
262*55139Storek 	/*
263*55139Storek 	 * Set up multicast address filter by passing all multicast
264*55139Storek 	 * addresses through a crc generator, and then using the high
265*55139Storek 	 * order 6 bits as a index into the 64 bit logical address
266*55139Storek 	 * filter. The high order two bits select the word, while the
267*55139Storek 	 * rest of the bits select the bit within the word.
268*55139Storek 	 */
269*55139Storek 
270*55139Storek 	ler2->ler2_ladrf[0] = 0;
271*55139Storek 	ler2->ler2_ladrf[1] = 0;
272*55139Storek 	ifp->if_flags &= ~IFF_ALLMULTI;
273*55139Storek 	ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
274*55139Storek 	while (enm != NULL) {
275*55139Storek 		if (bcmp((caddr_t)&enm->enm_addrlo,
276*55139Storek 		    (caddr_t)&enm->enm_addrhi, sizeof(enm->enm_addrlo)) == 0) {
277*55139Storek 			/*
278*55139Storek 			 * We must listen to a range of multicast
279*55139Storek 			 * addresses. For now, just accept all
280*55139Storek 			 * multicasts, rather than trying to set only
281*55139Storek 			 * those filter bits needed to match the range.
282*55139Storek 			 * (At this time, the only use of address
283*55139Storek 			 * ranges is for IP multicast routing, for
284*55139Storek 			 * which the range is big enough to require all
285*55139Storek 			 * bits set.)
286*55139Storek 			 */
287*55139Storek 			ler2->ler2_ladrf[0] = 0xffffffff;
288*55139Storek 			ler2->ler2_ladrf[1] = 0xffffffff;
289*55139Storek 			ifp->if_flags |= IFF_ALLMULTI;
290*55139Storek 			return;
291*55139Storek 		}
292*55139Storek 
293*55139Storek 		cp = (unsigned char *)&enm->enm_addrlo;
294*55139Storek 		c = *cp;
295*55139Storek 		crc = 0xffffffff;
296*55139Storek 		len = 6;
297*55139Storek 		while (len-- > 0) {
298*55139Storek 			c = *cp;
299*55139Storek 			for (i = 0; i < 8; i++) {
300*55139Storek 				if ((c & 0x01) ^ (crc & 0x01)) {
301*55139Storek 					crc >>= 1;
302*55139Storek 					crc = crc ^ 0xedb88320;
303*55139Storek 				}
304*55139Storek 				else
305*55139Storek 					crc >>= 1;
306*55139Storek 				c >>= 1;
307*55139Storek 			}
308*55139Storek 			cp++;
309*55139Storek 		}
310*55139Storek 		/* Just want the 6 most significant bits. */
311*55139Storek 		crc = crc >> 26;
312*55139Storek 
313*55139Storek 		/* Turn on the corresponding bit in the filter. */
314*55139Storek 		ler2->ler2_ladrf[crc >> 5] |= 1 << (crc & 0x1f);
315*55139Storek 
316*55139Storek 		ETHER_NEXT_MULTI(step, enm);
317*55139Storek 	}
318*55139Storek }
319*55139Storek #endif
320*55139Storek 
321*55139Storek void
322*55139Storek lereset(dev)
323*55139Storek 	struct device *dev;
324*55139Storek {
325*55139Storek 	register struct le_softc *sc = (struct le_softc *)dev;
326*55139Storek 	register volatile struct lereg1 *ler1 = sc->sc_r1;
327*55139Storek 	register volatile struct lereg2 *ler2 = sc->sc_r2;
328*55139Storek 	register int i, a, timo, stat;
329*55139Storek 
330*55139Storek #if NBPFILTER > 0
331*55139Storek 	if (sc->sc_if.if_flags & IFF_PROMISC)
332*55139Storek 		ler2->ler2_mode = LE_MODE_NORMAL | LE_MODE_PROM;
333*55139Storek 	else
334*55139Storek #endif
335*55139Storek 		ler2->ler2_mode = LE_MODE_NORMAL;
336*55139Storek 	ler1->ler1_rap = LE_CSR0;
337*55139Storek 	ler1->ler1_rdp = LE_C0_STOP;
338*55139Storek 
339*55139Storek 	/* Setup the logical address filter */
340*55139Storek #ifdef MULTICAST
341*55139Storek 	lesetladrf(sc);
342*55139Storek #else
343*55139Storek 	ler2->ler2_ladrf[0] = 0;
344*55139Storek 	ler2->ler2_ladrf[1] = 0;
345*55139Storek #endif
346*55139Storek 
347*55139Storek 	/* init receive and transmit rings */
348*55139Storek a = LANCE_ADDR(&ler2->ler2_rbuf[0][0]);
349*55139Storek if (!ISQUADALIGN(a))
350*55139Storek 	printf("rbuf not quad aligned (0x%x)\n", a);
351*55139Storek 	for (i = 0; i < LERBUF; i++) {
352*55139Storek 		a = LANCE_ADDR(&ler2->ler2_rbuf[i][0]);
353*55139Storek 		ler2->ler2_rmd[i].rmd0 = a;
354*55139Storek 		ler2->ler2_rmd[i].rmd1_hadr = a >> 16;
355*55139Storek 		ler2->ler2_rmd[i].rmd1_bits = LE_R1_OWN;
356*55139Storek 		ler2->ler2_rmd[i].rmd2 = -LEMTU;
357*55139Storek 		ler2->ler2_rmd[i].rmd3 = 0;
358*55139Storek 	}
359*55139Storek a = LANCE_ADDR(&ler2->ler2_tbuf[0][0]);
360*55139Storek if (!ISQUADALIGN(a))
361*55139Storek 	printf("tbuf not quad aligned (0x%x)\n", a);
362*55139Storek 	for (i = 0; i < LETBUF; i++) {
363*55139Storek 		a = LANCE_ADDR(&ler2->ler2_tbuf[i][0]);
364*55139Storek 		ler2->ler2_tmd[i].tmd0 = a;
365*55139Storek 		ler2->ler2_tmd[i].tmd1_hadr = a >> 16;
366*55139Storek 		ler2->ler2_tmd[i].tmd1_bits = 0;
367*55139Storek 		ler2->ler2_tmd[i].tmd2 = 0;
368*55139Storek 		ler2->ler2_tmd[i].tmd3 = 0;
369*55139Storek 	}
370*55139Storek 
371*55139Storek bzero(&ler2->ler2_rbuf[0][0], (LERBUF + LETBUF) * LEMTU);
372*55139Storek 	/* lance will stuff packet into receive buffer 0 next */
373*55139Storek 	sc->sc_rmd = 0;
374*55139Storek 
375*55139Storek 	/* tell the chip where to find the initialization block */
376*55139Storek 	a = LANCE_ADDR(&ler2->ler2_mode);
377*55139Storek 	ler1->ler1_rap = LE_CSR1;
378*55139Storek 	ler1->ler1_rdp = a;
379*55139Storek 	ler1->ler1_rap = LE_CSR2;
380*55139Storek 	ler1->ler1_rdp = a >> 16;
381*55139Storek 	ler1->ler1_rap = LE_CSR3;
382*55139Storek 	ler1->ler1_rdp = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON;
383*55139Storek 	ler1->ler1_rap = LE_CSR0;
384*55139Storek 	ler1->ler1_rdp = LE_C0_INIT;
385*55139Storek 	timo = 100000;
386*55139Storek 	while (((stat = ler1->ler1_rdp) & (LE_C0_ERR | LE_C0_IDON)) == 0) {
387*55139Storek 		if (--timo == 0) {
388*55139Storek 			printf("%s: init timeout, stat=%b\n",
389*55139Storek 			    sc->sc_dev.dv_xname, stat, LE_C0_BITS);
390*55139Storek 			break;
391*55139Storek 		}
392*55139Storek 	}
393*55139Storek 	if (stat & LE_C0_ERR)
394*55139Storek 		printf("%s: init failed, stat=%b\n",
395*55139Storek 		    sc->sc_dev.dv_xname, stat, LE_C0_BITS);
396*55139Storek 	else
397*55139Storek 		ler1->ler1_rdp = LE_C0_IDON;	/* clear IDON */
398*55139Storek 	ler1->ler1_rdp = LE_C0_STRT | LE_C0_INEA;
399*55139Storek 	sc->sc_if.if_flags &= ~IFF_OACTIVE;
400*55139Storek }
401*55139Storek 
402*55139Storek /*
403*55139Storek  * Initialization of interface
404*55139Storek  */
405*55139Storek int
406*55139Storek leinit(unit)
407*55139Storek 	int unit;
408*55139Storek {
409*55139Storek 	register struct le_softc *sc = lecd.cd_devs[unit];
410*55139Storek 	register struct ifnet *ifp = &sc->sc_if;
411*55139Storek 	register int s;
412*55139Storek 
413*55139Storek 	/* not yet, if address still unknown */
414*55139Storek 	if (ifp->if_addrlist == (struct ifaddr *)0)
415*55139Storek 		return (0);
416*55139Storek 	if ((ifp->if_flags & IFF_RUNNING) == 0) {
417*55139Storek 		s = splimp();
418*55139Storek 		ifp->if_flags |= IFF_RUNNING;
419*55139Storek 		lereset((struct device *)sc);
420*55139Storek 	        lestart(ifp);
421*55139Storek 		splx(s);
422*55139Storek 	}
423*55139Storek 	return (0);
424*55139Storek }
425*55139Storek 
426*55139Storek /*
427*55139Storek  * Start output on interface.  Get another datagram to send
428*55139Storek  * off of the interface queue, and copy it to the interface
429*55139Storek  * before starting the output.
430*55139Storek  */
431*55139Storek int
432*55139Storek lestart(ifp)
433*55139Storek 	register struct ifnet *ifp;
434*55139Storek {
435*55139Storek 	register struct le_softc *sc = lecd.cd_devs[ifp->if_unit];
436*55139Storek 	register volatile struct letmd *tmd;
437*55139Storek 	register struct mbuf *m;
438*55139Storek 	register int len;
439*55139Storek 
440*55139Storek 	if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
441*55139Storek 		return (0);
442*55139Storek 	IF_DEQUEUE(&sc->sc_if.if_snd, m);
443*55139Storek 	if (m == 0)
444*55139Storek 		return (0);
445*55139Storek 	len = leput(sc->sc_r2->ler2_tbuf[0], m);
446*55139Storek #if NBPFILTER > 0
447*55139Storek 	/*
448*55139Storek 	 * If bpf is listening on this interface, let it
449*55139Storek 	 * see the packet before we commit it to the wire.
450*55139Storek 	 */
451*55139Storek 	if (sc->sc_bpf)
452*55139Storek 		bpf_tap(sc->sc_bpf, sc->sc_r2->ler2_tbuf[0], len);
453*55139Storek #endif
454*55139Storek 
455*55139Storek #ifdef PACKETSTATS
456*55139Storek 	if (len <= LEMTU)
457*55139Storek 		lexpacketsizes[len]++;
458*55139Storek #endif
459*55139Storek 	tmd = sc->sc_r2->ler2_tmd;
460*55139Storek 	tmd->tmd3 = 0;
461*55139Storek 	tmd->tmd2 = -len;
462*55139Storek 	tmd->tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
463*55139Storek 	sc->sc_if.if_flags |= IFF_OACTIVE;
464*55139Storek 	return (0);
465*55139Storek }
466*55139Storek 
467*55139Storek int
468*55139Storek leintr(dev)
469*55139Storek 	register void *dev;
470*55139Storek {
471*55139Storek 	register struct le_softc *sc = dev;
472*55139Storek 	register volatile struct lereg1 *ler1 = sc->sc_r1;
473*55139Storek 	register int csr0;
474*55139Storek 
475*55139Storek 	csr0 = ler1->ler1_rdp;
476*55139Storek 	if ((csr0 & LE_C0_INTR) == 0)
477*55139Storek 		return (0);
478*55139Storek 	sc->sc_interrupts++;
479*55139Storek 
480*55139Storek 	if (csr0 & LE_C0_ERR) {
481*55139Storek 		leerror(sc, csr0);
482*55139Storek 		if (csr0 & LE_C0_MERR) {
483*55139Storek 			sc->sc_merr++;
484*55139Storek 			lereset((struct device *)sc);
485*55139Storek 			return (1);
486*55139Storek 		}
487*55139Storek 		if (csr0 & LE_C0_BABL)
488*55139Storek 			sc->sc_babl++;
489*55139Storek 		if (csr0 & LE_C0_CERR)
490*55139Storek 			sc->sc_cerr++;
491*55139Storek 		if (csr0 & LE_C0_MISS)
492*55139Storek 			sc->sc_miss++;
493*55139Storek 		ler1->ler1_rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_INEA;
494*55139Storek 	}
495*55139Storek 	if ((csr0 & LE_C0_RXON) == 0) {
496*55139Storek 		sc->sc_rxoff++;
497*55139Storek 		lereset((struct device *)sc);
498*55139Storek 		return (1);
499*55139Storek 	}
500*55139Storek 	if ((csr0 & LE_C0_TXON) == 0) {
501*55139Storek 		sc->sc_txoff++;
502*55139Storek 		lereset((struct device *)sc);
503*55139Storek 		return (1);
504*55139Storek 	}
505*55139Storek 	if (csr0 & LE_C0_RINT) {
506*55139Storek 		/* interrupt is cleared in lerint */
507*55139Storek 		lerint(sc);
508*55139Storek 	}
509*55139Storek 	if (csr0 & LE_C0_TINT) {
510*55139Storek 		ler1->ler1_rdp = LE_C0_TINT|LE_C0_INEA;
511*55139Storek 		lexint(sc);
512*55139Storek 	}
513*55139Storek 	return (1);
514*55139Storek }
515*55139Storek 
516*55139Storek /*
517*55139Storek  * Ethernet interface transmitter interrupt.
518*55139Storek  * Start another output if more data to send.
519*55139Storek  */
520*55139Storek void
521*55139Storek lexint(sc)
522*55139Storek 	register struct le_softc *sc;
523*55139Storek {
524*55139Storek 	register volatile struct letmd *tmd = sc->sc_r2->ler2_tmd;
525*55139Storek 
526*55139Storek 	sc->sc_lestats.lexints++;
527*55139Storek 	if ((sc->sc_if.if_flags & IFF_OACTIVE) == 0) {
528*55139Storek 		sc->sc_xint++;
529*55139Storek 		return;
530*55139Storek 	}
531*55139Storek 	if (tmd->tmd1_bits & LE_T1_OWN) {
532*55139Storek 		sc->sc_xown++;
533*55139Storek 		return;
534*55139Storek 	}
535*55139Storek 	if (tmd->tmd1_bits & LE_T1_ERR) {
536*55139Storek err:
537*55139Storek 		lexerror(sc);
538*55139Storek 		sc->sc_if.if_oerrors++;
539*55139Storek 		if (tmd->tmd3 & (LE_T3_BUFF|LE_T3_UFLO)) {
540*55139Storek 			sc->sc_uflo++;
541*55139Storek 			lereset((struct device *)sc);
542*55139Storek 		} else if (tmd->tmd3 & LE_T3_LCOL)
543*55139Storek 			sc->sc_if.if_collisions++;
544*55139Storek 		else if (tmd->tmd3 & LE_T3_RTRY)
545*55139Storek 			sc->sc_if.if_collisions += 16;
546*55139Storek 	}
547*55139Storek 	else if (tmd->tmd3 & LE_T3_BUFF)
548*55139Storek 		/* XXX documentation says BUFF not included in ERR */
549*55139Storek 		goto err;
550*55139Storek 	else if (tmd->tmd1_bits & LE_T1_ONE)
551*55139Storek 		sc->sc_if.if_collisions++;
552*55139Storek 	else if (tmd->tmd1_bits & LE_T1_MORE)
553*55139Storek 		/* what is the real number? */
554*55139Storek 		sc->sc_if.if_collisions += 2;
555*55139Storek 	else
556*55139Storek 		sc->sc_if.if_opackets++;
557*55139Storek 	sc->sc_if.if_flags &= ~IFF_OACTIVE;
558*55139Storek 	lestart(&sc->sc_if);
559*55139Storek }
560*55139Storek 
561*55139Storek #define	LENEXTRMP \
562*55139Storek 	if (++bix == LERBUF) bix = 0, rmd = sc->sc_r2->ler2_rmd; else ++rmd
563*55139Storek 
564*55139Storek /*
565*55139Storek  * Ethernet interface receiver interrupt.
566*55139Storek  * If input error just drop packet.
567*55139Storek  * Decapsulate packet based on type and pass to type specific
568*55139Storek  * higher-level input routine.
569*55139Storek  */
570*55139Storek void
571*55139Storek lerint(sc)
572*55139Storek 	register struct le_softc *sc;
573*55139Storek {
574*55139Storek 	register int bix = sc->sc_rmd;
575*55139Storek 	register volatile struct lermd *rmd = &sc->sc_r2->ler2_rmd[bix];
576*55139Storek 
577*55139Storek 	sc->sc_lestats.lerints++;
578*55139Storek 	/*
579*55139Storek 	 * Out of sync with hardware, should never happen?
580*55139Storek 	 */
581*55139Storek 	if (rmd->rmd1_bits & LE_R1_OWN) {
582*55139Storek 		do {
583*55139Storek 			sc->sc_lestats.lerscans++;
584*55139Storek 			LENEXTRMP;
585*55139Storek 		} while ((rmd->rmd1_bits & LE_R1_OWN) && bix != sc->sc_rmd);
586*55139Storek 		if (bix == sc->sc_rmd)
587*55139Storek 			printf("%s: RINT with no buffer\n",
588*55139Storek 			    sc->sc_dev.dv_xname);
589*55139Storek 	} else
590*55139Storek 		sc->sc_lestats.lerhits++;
591*55139Storek 
592*55139Storek 	/*
593*55139Storek 	 * Process all buffers with valid data
594*55139Storek 	 */
595*55139Storek 	while ((rmd->rmd1_bits & LE_R1_OWN) == 0) {
596*55139Storek 		int len = rmd->rmd3;
597*55139Storek 
598*55139Storek 		/* Clear interrupt to avoid race condition */
599*55139Storek 		sc->sc_r1->ler1_rdp = LE_C0_RINT|LE_C0_INEA;
600*55139Storek 
601*55139Storek 		if (rmd->rmd1_bits & LE_R1_ERR) {
602*55139Storek 			sc->sc_rmd = bix;
603*55139Storek 			lererror(sc, "bad packet");
604*55139Storek 			sc->sc_if.if_ierrors++;
605*55139Storek 		} else if ((rmd->rmd1_bits & (LE_R1_STP|LE_R1_ENP)) !=
606*55139Storek 		    (LE_R1_STP|LE_R1_ENP)) {
607*55139Storek 			/* XXX make a define for LE_R1_STP|LE_R1_ENP? */
608*55139Storek 			/*
609*55139Storek 			 * Find the end of the packet so we can see how long
610*55139Storek 			 * it was.  We still throw it away.
611*55139Storek 			 */
612*55139Storek 			do {
613*55139Storek 				sc->sc_r1->ler1_rdp = LE_C0_RINT|LE_C0_INEA;
614*55139Storek 				rmd->rmd3 = 0;
615*55139Storek 				rmd->rmd1_bits = LE_R1_OWN;
616*55139Storek 				LENEXTRMP;
617*55139Storek 			} while (!(rmd->rmd1_bits &
618*55139Storek 			    (LE_R1_OWN|LE_R1_ERR|LE_R1_STP|LE_R1_ENP)));
619*55139Storek 			sc->sc_rmd = bix;
620*55139Storek 			lererror(sc, "chained buffer");
621*55139Storek 			sc->sc_rxlen++;
622*55139Storek 			/*
623*55139Storek 			 * If search terminated without successful completion
624*55139Storek 			 * we reset the hardware (conservative).
625*55139Storek 			 */
626*55139Storek 			if ((rmd->rmd1_bits &
627*55139Storek 			    (LE_R1_OWN|LE_R1_ERR|LE_R1_STP|LE_R1_ENP)) !=
628*55139Storek 			    LE_R1_ENP) {
629*55139Storek 				lereset((struct device *)sc);
630*55139Storek 				return;
631*55139Storek 			}
632*55139Storek 		} else {
633*55139Storek 			leread(sc, sc->sc_r2->ler2_rbuf[bix], len);
634*55139Storek #ifdef PACKETSTATS
635*55139Storek 			lerpacketsizes[len]++;
636*55139Storek #endif
637*55139Storek 			sc->sc_lestats.lerbufs++;
638*55139Storek 		}
639*55139Storek 		rmd->rmd3 = 0;
640*55139Storek 		rmd->rmd1_bits = LE_R1_OWN;
641*55139Storek 		LENEXTRMP;
642*55139Storek 	}
643*55139Storek 	sc->sc_rmd = bix;
644*55139Storek }
645*55139Storek 
646*55139Storek void
647*55139Storek leread(sc, pkt, len)
648*55139Storek 	register struct le_softc *sc;
649*55139Storek 	char *pkt;
650*55139Storek 	int len;
651*55139Storek {
652*55139Storek 	register struct ether_header *et;
653*55139Storek 	register struct ifnet *ifp = &sc->sc_if;
654*55139Storek 	struct mbuf *m;
655*55139Storek 	struct ifqueue *inq;
656*55139Storek 	int flags;
657*55139Storek 
658*55139Storek 	ifp->if_ipackets++;
659*55139Storek 	et = (struct ether_header *)pkt;
660*55139Storek 	et->ether_type = ntohs((u_short)et->ether_type);
661*55139Storek 	/* adjust input length to account for header and CRC */
662*55139Storek 	len -= sizeof(struct ether_header) + 4;
663*55139Storek 
664*55139Storek 	if (len <= 0) {
665*55139Storek 		if (ledebug)
666*55139Storek 			log(LOG_WARNING,
667*55139Storek 			    "%s: ierror(runt packet): from %s: len=%d\n",
668*55139Storek 			    sc->sc_dev.dv_xname,
669*55139Storek 			    ether_sprintf(et->ether_shost), len);
670*55139Storek 		sc->sc_runt++;
671*55139Storek 		ifp->if_ierrors++;
672*55139Storek 		return;
673*55139Storek 	}
674*55139Storek 
675*55139Storek 	/* Setup mbuf flags we'll need later */
676*55139Storek 	flags = 0;
677*55139Storek 	if (bcmp((caddr_t)etherbroadcastaddr,
678*55139Storek 	    (caddr_t)et->ether_dhost, sizeof(etherbroadcastaddr)) == 0)
679*55139Storek 		flags |= M_BCAST;
680*55139Storek 	if (et->ether_dhost[0] & 1)
681*55139Storek 		flags |= M_MCAST;
682*55139Storek 
683*55139Storek #if NBPFILTER > 0
684*55139Storek 	/*
685*55139Storek 	 * Check if there's a bpf filter listening on this interface.
686*55139Storek 	 * If so, hand off the raw packet to enet.
687*55139Storek 	 */
688*55139Storek 	if (sc->sc_bpf) {
689*55139Storek 		bpf_tap(sc->sc_bpf, pkt, len + sizeof(struct ether_header));
690*55139Storek 
691*55139Storek 		/*
692*55139Storek 		 * Keep the packet if it's a broadcast or has our
693*55139Storek 		 * physical ethernet address (or if we support
694*55139Storek 		 * multicast and it's one).
695*55139Storek 		 */
696*55139Storek 		if (
697*55139Storek #ifdef MULTICAST
698*55139Storek 		    (flags & (M_BCAST | M_MCAST)) == 0 &&
699*55139Storek #else
700*55139Storek 		    (flags & M_BCAST) == 0 &&
701*55139Storek #endif
702*55139Storek 		    bcmp(et->ether_dhost, sc->sc_addr,
703*55139Storek 			sizeof(et->ether_dhost)) != 0)
704*55139Storek 			return;
705*55139Storek 	}
706*55139Storek #endif
707*55139Storek 	m = leget(pkt, len, 0, ifp);
708*55139Storek 	if (m == 0)
709*55139Storek 		return;
710*55139Storek 
711*55139Storek 	/* XXX this code comes from ether_input() */
712*55139Storek 	ifp->if_lastchange = time;
713*55139Storek 	ifp->if_ibytes += m->m_pkthdr.len + sizeof (*et);
714*55139Storek 	if (flags) {
715*55139Storek 		m->m_flags |= flags;
716*55139Storek 		ifp->if_imcasts++;
717*55139Storek 	}
718*55139Storek 	/* XXX end of code from ether_input() */
719*55139Storek 
720*55139Storek 	switch (et->ether_type) {
721*55139Storek 
722*55139Storek #ifdef INET
723*55139Storek 	case ETHERTYPE_IP:
724*55139Storek 		schednetisr(NETISR_IP);
725*55139Storek 		inq = &ipintrq;
726*55139Storek 		break;
727*55139Storek 
728*55139Storek 	case ETHERTYPE_ARP:
729*55139Storek 		schednetisr(NETISR_ARP);
730*55139Storek 		inq = &arpintrq;
731*55139Storek 		break;
732*55139Storek #endif
733*55139Storek #ifdef NS
734*55139Storek 	case ETHERTYPE_NS:
735*55139Storek 		schednetisr(NETISR_NS);
736*55139Storek 		inq = &nsintrq;
737*55139Storek 		break;
738*55139Storek #endif
739*55139Storek 
740*55139Storek #ifdef UTAHONLY
741*55139Storek #ifdef APPLETALK
742*55139Storek 	case ETHERTYPE_APPLETALK:
743*55139Storek 		schednetisr(NETISR_DDP);
744*55139Storek 		inq = &ddpintq;
745*55139Storek 		break;
746*55139Storek 
747*55139Storek 	case ETHERTYPE_AARP:
748*55139Storek 		aarpinput(&sc->sc_ac, m);
749*55139Storek 		return;
750*55139Storek #endif
751*55139Storek #endif
752*55139Storek 	default:
753*55139Storek 		m_freem(m);
754*55139Storek 		return;
755*55139Storek 	}
756*55139Storek 
757*55139Storek 	if (IF_QFULL(inq)) {
758*55139Storek 		IF_DROP(inq);
759*55139Storek 		m_freem(m);
760*55139Storek 		return;
761*55139Storek 	}
762*55139Storek 	IF_ENQUEUE(inq, m);
763*55139Storek }
764*55139Storek 
765*55139Storek /*
766*55139Storek  * Routine to copy from mbuf chain to transmit
767*55139Storek  * buffer in board local memory.
768*55139Storek  *
769*55139Storek  * ### this can be done by remapping in some cases
770*55139Storek  */
771*55139Storek int
772*55139Storek leput(lebuf, m)
773*55139Storek 	register char *lebuf;
774*55139Storek 	register struct mbuf *m;
775*55139Storek {
776*55139Storek 	register struct mbuf *mp;
777*55139Storek 	register int len, tlen = 0;
778*55139Storek 
779*55139Storek 	for (mp = m; mp; mp = mp->m_next) {
780*55139Storek 		len = mp->m_len;
781*55139Storek 		if (len == 0)
782*55139Storek 			continue;
783*55139Storek 		tlen += len;
784*55139Storek 		bcopy(mtod(mp, char *), lebuf, len);
785*55139Storek 		lebuf += len;
786*55139Storek 	}
787*55139Storek 	m_freem(m);
788*55139Storek 	if (tlen < LEMINSIZE) {
789*55139Storek 		bzero(lebuf, LEMINSIZE - tlen);
790*55139Storek 		tlen = LEMINSIZE;
791*55139Storek 	}
792*55139Storek 	return (tlen);
793*55139Storek }
794*55139Storek 
795*55139Storek /*
796*55139Storek  * Routine to copy from board local memory into mbufs.
797*55139Storek  */
798*55139Storek struct mbuf *
799*55139Storek leget(lebuf, totlen, off0, ifp)
800*55139Storek 	char *lebuf;
801*55139Storek 	int totlen, off0;
802*55139Storek 	struct ifnet *ifp;
803*55139Storek {
804*55139Storek 	register struct mbuf *m;
805*55139Storek 	struct mbuf *top = 0, **mp = &top;
806*55139Storek 	register int off = off0, len;
807*55139Storek 	register char *cp;
808*55139Storek 	char *epkt;
809*55139Storek 
810*55139Storek 	lebuf += sizeof(struct ether_header);
811*55139Storek 	cp = lebuf;
812*55139Storek 	epkt = cp + totlen;
813*55139Storek 	if (off) {
814*55139Storek 		cp += off + 2 * sizeof(u_short);
815*55139Storek 		totlen -= 2 * sizeof(u_short);
816*55139Storek 	}
817*55139Storek 
818*55139Storek 	MGETHDR(m, M_DONTWAIT, MT_DATA);
819*55139Storek 	if (m == 0)
820*55139Storek 		return (0);
821*55139Storek 	m->m_pkthdr.rcvif = ifp;
822*55139Storek 	m->m_pkthdr.len = totlen;
823*55139Storek 	m->m_len = MHLEN;
824*55139Storek 
825*55139Storek 	while (totlen > 0) {
826*55139Storek 		if (top) {
827*55139Storek 			MGET(m, M_DONTWAIT, MT_DATA);
828*55139Storek 			if (m == 0) {
829*55139Storek 				m_freem(top);
830*55139Storek 				return (0);
831*55139Storek 			}
832*55139Storek 			m->m_len = MLEN;
833*55139Storek 		}
834*55139Storek 		len = min(totlen, epkt - cp);
835*55139Storek 		if (len >= MINCLSIZE) {
836*55139Storek 			MCLGET(m, M_DONTWAIT);
837*55139Storek 			if (m->m_flags & M_EXT)
838*55139Storek 				m->m_len = len = min(len, MCLBYTES);
839*55139Storek 			else
840*55139Storek 				len = m->m_len;
841*55139Storek 		} else {
842*55139Storek 			/*
843*55139Storek 			 * Place initial small packet/header at end of mbuf.
844*55139Storek 			 */
845*55139Storek 			if (len < m->m_len) {
846*55139Storek 				if (top == 0 && len + max_linkhdr <= m->m_len)
847*55139Storek 					m->m_data += max_linkhdr;
848*55139Storek 				m->m_len = len;
849*55139Storek 			} else
850*55139Storek 				len = m->m_len;
851*55139Storek 		}
852*55139Storek 		bcopy(cp, mtod(m, caddr_t), (unsigned)len);
853*55139Storek 		cp += len;
854*55139Storek 		*mp = m;
855*55139Storek 		mp = &m->m_next;
856*55139Storek 		totlen -= len;
857*55139Storek 		if (cp == epkt)
858*55139Storek 			cp = lebuf;
859*55139Storek 	}
860*55139Storek 	return (top);
861*55139Storek }
862*55139Storek 
863*55139Storek /*
864*55139Storek  * Process an ioctl request.
865*55139Storek  */
866*55139Storek int
867*55139Storek leioctl(ifp, cmd, data)
868*55139Storek 	register struct ifnet *ifp;
869*55139Storek 	int cmd;
870*55139Storek 	caddr_t data;
871*55139Storek {
872*55139Storek 	register struct ifaddr *ifa;
873*55139Storek 	register struct le_softc *sc = lecd.cd_devs[ifp->if_unit];
874*55139Storek 	register volatile struct lereg1 *ler1;
875*55139Storek 	int s = splimp(), error = 0;
876*55139Storek 
877*55139Storek 	switch (cmd) {
878*55139Storek 
879*55139Storek 	case SIOCSIFADDR:
880*55139Storek 		ifa = (struct ifaddr *)data;
881*55139Storek 		ifp->if_flags |= IFF_UP;
882*55139Storek 		switch (ifa->ifa_addr->sa_family) {
883*55139Storek #ifdef INET
884*55139Storek 		case AF_INET:
885*55139Storek 			(void)leinit(ifp->if_unit);	/* before arpwhohas */
886*55139Storek 			((struct arpcom *)ifp)->ac_ipaddr =
887*55139Storek 				IA_SIN(ifa)->sin_addr;
888*55139Storek 			arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
889*55139Storek 			break;
890*55139Storek #endif
891*55139Storek #ifdef NS
892*55139Storek 		case AF_NS:
893*55139Storek 		    {
894*55139Storek 			register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
895*55139Storek 
896*55139Storek 			if (ns_nullhost(*ina))
897*55139Storek 				ina->x_host = *(union ns_host *)(sc->sc_addr);
898*55139Storek 			else {
899*55139Storek 				/*
900*55139Storek 				 * The manual says we can't change the address
901*55139Storek 				 * while the receiver is armed,
902*55139Storek 				 * so reset everything
903*55139Storek 				 */
904*55139Storek 				ifp->if_flags &= ~IFF_RUNNING;
905*55139Storek 				bcopy((caddr_t)ina->x_host.c_host,
906*55139Storek 				    (caddr_t)sc->sc_addr, sizeof(sc->sc_addr));
907*55139Storek 			}
908*55139Storek 			(void)leinit(ifp->if_unit);	/* does le_setaddr() */
909*55139Storek 			break;
910*55139Storek 		    }
911*55139Storek #endif
912*55139Storek 		default:
913*55139Storek 			(void)leinit(ifp->if_unit);
914*55139Storek 			break;
915*55139Storek 		}
916*55139Storek 		break;
917*55139Storek 
918*55139Storek 	case SIOCSIFFLAGS:
919*55139Storek 		ler1 = sc->sc_r1;
920*55139Storek 		if ((ifp->if_flags & IFF_UP) == 0 &&
921*55139Storek 		    ifp->if_flags & IFF_RUNNING) {
922*55139Storek 			ler1->ler1_rdp = LE_C0_STOP;
923*55139Storek 			ifp->if_flags &= ~IFF_RUNNING;
924*55139Storek 		} else if (ifp->if_flags & IFF_UP &&
925*55139Storek 		    (ifp->if_flags & IFF_RUNNING) == 0)
926*55139Storek 			(void)leinit(ifp->if_unit);
927*55139Storek 		/*
928*55139Storek 		 * If the state of the promiscuous bit changes, the interface
929*55139Storek 		 * must be reset to effect the change.
930*55139Storek 		 */
931*55139Storek 		if (((ifp->if_flags ^ sc->sc_iflags) & IFF_PROMISC) &&
932*55139Storek 		    (ifp->if_flags & IFF_RUNNING)) {
933*55139Storek 			sc->sc_iflags = ifp->if_flags;
934*55139Storek 			lereset((struct device *)sc);
935*55139Storek 			lestart(ifp);
936*55139Storek 		}
937*55139Storek 		break;
938*55139Storek 
939*55139Storek #ifdef MULTICAST
940*55139Storek 	case SIOCADDMULTI:
941*55139Storek 	case SIOCDELMULTI:
942*55139Storek 		/* Update our multicast list  */
943*55139Storek 		error = (cmd == SIOCADDMULTI) ?
944*55139Storek 		    ether_addmulti((struct ifreq *)data, &sc->sc_ac) :
945*55139Storek 		    ether_delmulti((struct ifreq *)data, &sc->sc_ac);
946*55139Storek 
947*55139Storek 		if (error == ENETRESET) {
948*55139Storek 			/*
949*55139Storek 			 * Multicast list has changed; set the hardware
950*55139Storek 			 * filter accordingly.
951*55139Storek 			 */
952*55139Storek 			lereset((struct device *)sc);
953*55139Storek 			error = 0;
954*55139Storek 		}
955*55139Storek 		break;
956*55139Storek #endif
957*55139Storek 
958*55139Storek 	default:
959*55139Storek 		error = EINVAL;
960*55139Storek 	}
961*55139Storek 	splx(s);
962*55139Storek 	return (error);
963*55139Storek }
964*55139Storek 
965*55139Storek void
966*55139Storek leerror(sc, stat)
967*55139Storek 	register struct le_softc *sc;
968*55139Storek 	int stat;
969*55139Storek {
970*55139Storek 	if (!ledebug)
971*55139Storek 		return;
972*55139Storek 
973*55139Storek 	/*
974*55139Storek 	 * Not all transceivers implement heartbeat
975*55139Storek 	 * so we only log CERR once.
976*55139Storek 	 */
977*55139Storek 	if ((stat & LE_C0_CERR) && sc->sc_cerr)
978*55139Storek 		return;
979*55139Storek 	log(LOG_WARNING, "%s: error: stat=%b\n",
980*55139Storek 	    sc->sc_dev.dv_xname, stat, LE_C0_BITS);
981*55139Storek }
982*55139Storek 
983*55139Storek void
984*55139Storek lererror(sc, msg)
985*55139Storek 	register struct le_softc *sc;
986*55139Storek 	char *msg;
987*55139Storek {
988*55139Storek 	register volatile struct lermd *rmd;
989*55139Storek 	int len;
990*55139Storek 
991*55139Storek 	if (!ledebug)
992*55139Storek 		return;
993*55139Storek 
994*55139Storek 	rmd = &sc->sc_r2->ler2_rmd[sc->sc_rmd];
995*55139Storek 	len = rmd->rmd3;
996*55139Storek 	log(LOG_WARNING, "%s: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
997*55139Storek 	    sc->sc_dev.dv_xname, msg, len > 11 ?
998*55139Storek 	    ether_sprintf((u_char *)&sc->sc_r2->ler2_rbuf[sc->sc_rmd][6]) :
999*55139Storek 	    "unknown",
1000*55139Storek 	    sc->sc_rmd, len, rmd->rmd1_bits, LE_R1_BITS);
1001*55139Storek }
1002*55139Storek 
1003*55139Storek void
1004*55139Storek lexerror(sc)
1005*55139Storek 	register struct le_softc *sc;
1006*55139Storek {
1007*55139Storek 	register volatile struct letmd *tmd;
1008*55139Storek 	register int len, tmd3, tdr;
1009*55139Storek 
1010*55139Storek 	if (!ledebug)
1011*55139Storek 		return;
1012*55139Storek 
1013*55139Storek 	tmd = sc->sc_r2->ler2_tmd;
1014*55139Storek 	tmd3 = tmd->tmd3;
1015*55139Storek 	tdr = tmd3 & LE_T3_TDR_MASK;
1016*55139Storek 	len = -tmd->tmd2;
1017*55139Storek 	log(LOG_WARNING,
1018*55139Storek     "%s: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b, tdr=%d (%d nsecs)\n",
1019*55139Storek 	    sc->sc_dev.dv_xname, len > 5 ?
1020*55139Storek 	    ether_sprintf((u_char *)&sc->sc_r2->ler2_tbuf[0][0]) : "unknown",
1021*55139Storek 	    0, len,
1022*55139Storek 	    tmd->tmd1_bits, LE_T1_BITS,
1023*55139Storek 	    tmd3, LE_T3_BITS, tdr, tdr * 100);
1024*55139Storek }
1025