xref: /csrg-svn/sys/luna68k/dev/if_le.c (revision 54000)
1*54000Sfujita /*
2*54000Sfujita  * Copyright (c) 1982, 1990, 1992 The Regents of the University of California.
3*54000Sfujita  * All rights reserved.
4*54000Sfujita  *
5*54000Sfujita  * %sccs.include.redist.c%
6*54000Sfujita  *
7*54000Sfujita  *	@(#)if_le.c	7.1 (Berkeley) 06/15/92
8*54000Sfujita  */
9*54000Sfujita 
10*54000Sfujita #include "le.h"
11*54000Sfujita #if NLE > 0
12*54000Sfujita 
13*54000Sfujita #include "bpfilter.h"
14*54000Sfujita 
15*54000Sfujita /*
16*54000Sfujita  * AMD 7990 LANCE
17*54000Sfujita  *
18*54000Sfujita  * This driver will generate and accept tailer encapsulated packets even
19*54000Sfujita  * though it buys us nothing.  The motivation was to avoid incompatibilities
20*54000Sfujita  * with VAXen, SUNs, and others that handle and benefit from them.
21*54000Sfujita  * This reasoning is dubious.
22*54000Sfujita  */
23*54000Sfujita #include "sys/param.h"
24*54000Sfujita #include "sys/proc.h"
25*54000Sfujita #include "sys/systm.h"
26*54000Sfujita #include "sys/mbuf.h"
27*54000Sfujita #include "sys/buf.h"
28*54000Sfujita #include "sys/protosw.h"
29*54000Sfujita #include "sys/socket.h"
30*54000Sfujita #include "sys/syslog.h"
31*54000Sfujita #include "sys/ioctl.h"
32*54000Sfujita #include "sys/errno.h"
33*54000Sfujita 
34*54000Sfujita #include "net/if.h"
35*54000Sfujita #include "net/netisr.h"
36*54000Sfujita #include "net/route.h"
37*54000Sfujita 
38*54000Sfujita #ifdef INET
39*54000Sfujita #include "netinet/in.h"
40*54000Sfujita #include "netinet/in_systm.h"
41*54000Sfujita #include "netinet/in_var.h"
42*54000Sfujita #include "netinet/ip.h"
43*54000Sfujita #include "netinet/if_ether.h"
44*54000Sfujita #endif
45*54000Sfujita 
46*54000Sfujita #ifdef NS
47*54000Sfujita #include "netns/ns.h"
48*54000Sfujita #include "netns/ns_if.h"
49*54000Sfujita #endif
50*54000Sfujita 
51*54000Sfujita #ifdef ISO
52*54000Sfujita extern	char all_es_snpa[], all_is_snpa[], all_l1is_snpa[], all_l2is_snpa[];
53*54000Sfujita #endif
54*54000Sfujita 
55*54000Sfujita #include "../include/cpu.h"
56*54000Sfujita #include "../include/mtpr.h"
57*54000Sfujita #include "device.h"
58*54000Sfujita #include "if_lereg.h"
59*54000Sfujita 
60*54000Sfujita #if NBPFILTER > 0
61*54000Sfujita #include "../net/bpf.h"
62*54000Sfujita #include "../net/bpfdesc.h"
63*54000Sfujita char hprmp_multi[] = { 9, 0, 9, 0, 0, 4};
64*54000Sfujita #endif
65*54000Sfujita 
66*54000Sfujita 
67*54000Sfujita int	leattach();
68*54000Sfujita struct	driver ledriver = {
69*54000Sfujita 	leattach, "le",
70*54000Sfujita };
71*54000Sfujita 
72*54000Sfujita int	ledebug = 0;		/* console error messages */
73*54000Sfujita 
74*54000Sfujita int	leintr(), leinit(), leioctl(), lestart(), ether_output();
75*54000Sfujita struct	mbuf *m_devget();
76*54000Sfujita extern	struct ifnet loif;
77*54000Sfujita 
78*54000Sfujita /*
79*54000Sfujita  * Ethernet software status per interface.
80*54000Sfujita  *
81*54000Sfujita  * Each interface is referenced by a network interface structure,
82*54000Sfujita  * le_if, which the routing code uses to locate the interface.
83*54000Sfujita  * This structure contains the output queue for the interface, its address, ...
84*54000Sfujita  */
85*54000Sfujita struct	le_softc {
86*54000Sfujita 	struct	arpcom sc_ac;	/* common Ethernet structures */
87*54000Sfujita #define	sc_if	sc_ac.ac_if	/* network-visible interface */
88*54000Sfujita #define	sc_addr	sc_ac.ac_enaddr	/* hardware Ethernet address */
89*54000Sfujita 	struct	lereg1 *sc_r1;	/* LANCE registers */
90*54000Sfujita 	struct	lereg2 *sc_r2;	/* dual-port RAM */
91*54000Sfujita 	int	sc_rmd;		/* predicted next rmd to process */
92*54000Sfujita 	int	sc_runt;
93*54000Sfujita 	int	sc_jab;
94*54000Sfujita 	int	sc_merr;
95*54000Sfujita 	int	sc_babl;
96*54000Sfujita 	int	sc_cerr;
97*54000Sfujita 	int	sc_miss;
98*54000Sfujita 	int	sc_xint;
99*54000Sfujita 	int	sc_xown;
100*54000Sfujita 	int	sc_uflo;
101*54000Sfujita 	int	sc_rxlen;
102*54000Sfujita 	int	sc_rxoff;
103*54000Sfujita 	int	sc_txoff;
104*54000Sfujita 	int	sc_busy;
105*54000Sfujita 	short	sc_iflags;
106*54000Sfujita 	caddr_t sc_bpf;
107*54000Sfujita 	int	sc_tmd;		/* predicted next tmd to process */
108*54000Sfujita 	int	sc_txcnt;	/* transmissions in progress */
109*54000Sfujita 	int	sc_txbad;
110*54000Sfujita 	int	sc_txbusy;
111*54000Sfujita } le_softc[NLE];
112*54000Sfujita 
113*54000Sfujita /* access LANCE registers */
114*54000Sfujita #define	LERDWR(cntl, src, dst)	(dst) = (src)
115*54000Sfujita 
116*54000Sfujita #define LE_IPL		3
117*54000Sfujita 
118*54000Sfujita /*
119*54000Sfujita  * Interface exists: make available by filling in network interface
120*54000Sfujita  * record.  System will initialize the interface when it is ready
121*54000Sfujita  * to accept packets.
122*54000Sfujita  */
123*54000Sfujita leattach(hd)
124*54000Sfujita 	struct hp_device *hd;
125*54000Sfujita {
126*54000Sfujita 	register struct lereg2 *ler2;
127*54000Sfujita 	struct lereg2 *lemem = (struct lereg2 *) 0;
128*54000Sfujita 	struct le_softc *le = &le_softc[hd->hp_unit];
129*54000Sfujita 	struct ifnet *ifp = &le->sc_if;
130*54000Sfujita 	char *cp;
131*54000Sfujita 	int i;
132*54000Sfujita 
133*54000Sfujita 	le->sc_r1 = (struct lereg1 *) hd->hp_addr;
134*54000Sfujita 	ler2 = le->sc_r2 = (struct lereg2 *) 0x71000000;
135*54000Sfujita 
136*54000Sfujita 	hd->hp_ipl = LE_IPL;
137*54000Sfujita 
138*54000Sfujita 	/*
139*54000Sfujita 	 * Read the ethernet address off the board, one nibble at a time.
140*54000Sfujita 	 */
141*54000Sfujita #ifdef NOROM
142*54000Sfujita 	cp = "00000a02456c";
143*54000Sfujita #else
144*54000Sfujita 	cp = (char *) 0x4101FFE0;
145*54000Sfujita #endif
146*54000Sfujita 	for (i = 0; i < sizeof(le->sc_addr); i++) {
147*54000Sfujita 		le->sc_addr[i]  = (*cp < 'A' ? (*cp & 0xF) : (*cp & 0xF) + 9) << 4;
148*54000Sfujita 		cp++;
149*54000Sfujita 		le->sc_addr[i] |= (*cp < 'A' ? (*cp & 0xF) : (*cp & 0xF) + 9);
150*54000Sfujita 		cp++;
151*54000Sfujita 	}
152*54000Sfujita 	printf("le%d: hardware address %s\n", hd->hp_unit,
153*54000Sfujita 		ether_sprintf(le->sc_addr));
154*54000Sfujita 
155*54000Sfujita 	/*
156*54000Sfujita 	 * Setup for transmit/receive
157*54000Sfujita 	 */
158*54000Sfujita 	ler2->ler2_mode = LE_MODE;
159*54000Sfujita #if defined(ISO) || NBPFILTER > 0
160*54000Sfujita 	ler2->ler2_ladrf0 = 0xffffffff;
161*54000Sfujita 	ler2->ler2_ladrf1 = 0xffffffff;
162*54000Sfujita #else
163*54000Sfujita 	ler2->ler2_ladrf0 = 0;
164*54000Sfujita 	ler2->ler2_ladrf1 = 0;
165*54000Sfujita #endif
166*54000Sfujita 	ler2->ler2_rlen = LE_RLEN;
167*54000Sfujita 	ler2->ler2_rdra = (int)lemem->ler2_rmd;
168*54000Sfujita 	ler2->ler2_tlen = LE_TLEN;
169*54000Sfujita 	ler2->ler2_tdra = (int)lemem->ler2_tmd;
170*54000Sfujita 
171*54000Sfujita 	ifp->if_unit = hd->hp_unit;
172*54000Sfujita 	ifp->if_name = "le";
173*54000Sfujita 	ifp->if_mtu = ETHERMTU;
174*54000Sfujita 	ifp->if_init = leinit;
175*54000Sfujita 	ifp->if_ioctl = leioctl;
176*54000Sfujita 	ifp->if_output = ether_output;
177*54000Sfujita 	ifp->if_start = lestart;
178*54000Sfujita 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
179*54000Sfujita #if NBPFILTER > 0
180*54000Sfujita 	bpfattach(&le->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
181*54000Sfujita #endif
182*54000Sfujita 	if_attach(ifp);
183*54000Sfujita 	return (1);
184*54000Sfujita }
185*54000Sfujita 
186*54000Sfujita ledrinit(ler2, le)
187*54000Sfujita 	register struct lereg2 *ler2;
188*54000Sfujita 	register struct le_softc *le;
189*54000Sfujita {
190*54000Sfujita 	register struct lereg2 *lemem = (struct lereg2 *) 0;
191*54000Sfujita 	register int i;
192*54000Sfujita 
193*54000Sfujita 	ler2->ler2_padr[0] = le->sc_addr[1];
194*54000Sfujita 	ler2->ler2_padr[1] = le->sc_addr[0];
195*54000Sfujita 	ler2->ler2_padr[2] = le->sc_addr[3];
196*54000Sfujita 	ler2->ler2_padr[3] = le->sc_addr[2];
197*54000Sfujita 	ler2->ler2_padr[4] = le->sc_addr[5];
198*54000Sfujita 	ler2->ler2_padr[5] = le->sc_addr[4];
199*54000Sfujita 	for (i = 0; i < LERBUF; i++) {
200*54000Sfujita 		ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i];
201*54000Sfujita 		ler2->ler2_rmd[i].rmd1 = LE_OWN;
202*54000Sfujita 		ler2->ler2_rmd[i].rmd2 = -LEMTU;
203*54000Sfujita 		ler2->ler2_rmd[i].rmd3 = 0;
204*54000Sfujita 	}
205*54000Sfujita 	for (i = 0; i < LETBUF; i++) {
206*54000Sfujita 		ler2->ler2_tmd[i].tmd0 = (int)lemem->ler2_tbuf[i];
207*54000Sfujita 		ler2->ler2_tmd[i].tmd1 = 0;
208*54000Sfujita 		ler2->ler2_tmd[i].tmd2 = 0;
209*54000Sfujita 		ler2->ler2_tmd[i].tmd3 = 0;
210*54000Sfujita 	}
211*54000Sfujita }
212*54000Sfujita 
213*54000Sfujita lereset(unit)
214*54000Sfujita 	register int unit;
215*54000Sfujita {
216*54000Sfujita 	register struct le_softc *le = &le_softc[unit];
217*54000Sfujita 	register struct lereg1 *ler1 = le->sc_r1;
218*54000Sfujita 	register struct lereg2 *lemem = (struct lereg2 *) 0;
219*54000Sfujita 	register int timo = 100000;
220*54000Sfujita 	register int stat;
221*54000Sfujita 
222*54000Sfujita #ifdef lint
223*54000Sfujita 	stat = unit;
224*54000Sfujita #endif
225*54000Sfujita #if NBPFILTER > 0
226*54000Sfujita 	if (le->sc_if.if_flags & IFF_PROMISC)
227*54000Sfujita 		/* set the promiscuous bit */
228*54000Sfujita 		le->sc_r2->ler2_mode = LE_MODE|0x8000;
229*54000Sfujita 	else
230*54000Sfujita 		le->sc_r2->ler2_mode = LE_MODE;
231*54000Sfujita #endif
232*54000Sfujita 	LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
233*54000Sfujita 	LERDWR(ler0, LE_STOP, ler1->ler1_rdp);
234*54000Sfujita 	ledrinit(le->sc_r2, le);
235*54000Sfujita 	le->sc_txcnt = le->sc_tmd = le->sc_rmd = 0;
236*54000Sfujita 	LERDWR(ler0, LE_CSR1, ler1->ler1_rap);
237*54000Sfujita 	LERDWR(ler0, (int)&lemem->ler2_mode, ler1->ler1_rdp);
238*54000Sfujita 	LERDWR(ler0, LE_CSR2, ler1->ler1_rap);
239*54000Sfujita 	LERDWR(ler0, 0, ler1->ler1_rdp);
240*54000Sfujita 	LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
241*54000Sfujita 	LERDWR(ler0, LE_INIT, ler1->ler1_rdp);
242*54000Sfujita 	do {
243*54000Sfujita 		if (--timo == 0) {
244*54000Sfujita 			printf("le%d: init timeout, stat = 0x%x\n",
245*54000Sfujita 			       unit, stat);
246*54000Sfujita 			break;
247*54000Sfujita 		}
248*54000Sfujita 		LERDWR(ler0, ler1->ler1_rdp, stat);
249*54000Sfujita 	} while ((stat & LE_IDON) == 0);
250*54000Sfujita 	LERDWR(ler0, LE_STOP, ler1->ler1_rdp);
251*54000Sfujita 	LERDWR(ler0, LE_CSR3, ler1->ler1_rap);
252*54000Sfujita 	LERDWR(ler0, LE_BSWP, ler1->ler1_rdp);
253*54000Sfujita 	LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
254*54000Sfujita 	LERDWR(ler0, LE_STRT | LE_INEA, ler1->ler1_rdp);
255*54000Sfujita 	le->sc_if.if_flags &= ~IFF_OACTIVE;
256*54000Sfujita }
257*54000Sfujita 
258*54000Sfujita /*
259*54000Sfujita  * Initialization of interface
260*54000Sfujita  */
261*54000Sfujita leinit(unit)
262*54000Sfujita 	int unit;
263*54000Sfujita {
264*54000Sfujita 	register struct ifnet *ifp = &le_softc[unit].sc_if;
265*54000Sfujita 	register struct ifaddr *ifa;
266*54000Sfujita 	int s;
267*54000Sfujita 
268*54000Sfujita 	/* not yet, if address still unknown */
269*54000Sfujita 	for (ifa = ifp->if_addrlist;; ifa = ifa->ifa_next)
270*54000Sfujita 		if (ifa == 0)
271*54000Sfujita 			return;
272*54000Sfujita 		else if (ifa->ifa_addr && ifa->ifa_addr->sa_family != AF_LINK)
273*54000Sfujita 			break;
274*54000Sfujita 	if ((ifp->if_flags & IFF_RUNNING) == 0) {
275*54000Sfujita 		s = splimp();
276*54000Sfujita 		ifp->if_flags |= IFF_RUNNING;
277*54000Sfujita 		lereset(unit);
278*54000Sfujita 	        (void) lestart(ifp);
279*54000Sfujita 		splx(s);
280*54000Sfujita 	}
281*54000Sfujita }
282*54000Sfujita 
283*54000Sfujita /*
284*54000Sfujita  * Start output on interface.  Get another datagram to send
285*54000Sfujita  * off of the interface queue, and copy it to the interface
286*54000Sfujita  * before starting the output.
287*54000Sfujita  */
288*54000Sfujita lestart(ifp)
289*54000Sfujita 	struct ifnet *ifp;
290*54000Sfujita {
291*54000Sfujita 	register struct le_softc *le = &le_softc[ifp->if_unit];
292*54000Sfujita 	register struct letmd *tmd;
293*54000Sfujita 	register struct mbuf *m;
294*54000Sfujita 	int len;
295*54000Sfujita 
296*54000Sfujita again:
297*54000Sfujita 	if ((le->sc_if.if_flags & IFF_RUNNING) == 0)
298*54000Sfujita 		return (0);
299*54000Sfujita 	IF_DEQUEUE(&le->sc_if.if_snd, m);
300*54000Sfujita 	if (m == 0)
301*54000Sfujita 		return (0);
302*54000Sfujita 	tmd = le->sc_r2->ler2_tmd + le->sc_tmd;
303*54000Sfujita 	if (tmd->tmd1 & LE_OWN)
304*54000Sfujita 		return (le->sc_txbusy++, 0);
305*54000Sfujita 	len = leput(le->sc_r2->ler2_tbuf[le->sc_tmd], m);
306*54000Sfujita #if NBPFILTER > 0
307*54000Sfujita 	/*
308*54000Sfujita 	 * If bpf is listening on this interface, let it
309*54000Sfujita 	 * see the packet before we commit it to the wire.
310*54000Sfujita 	 */
311*54000Sfujita 	if (le->sc_bpf)
312*54000Sfujita                 bpf_tap(le->sc_bpf, le->sc_r2->ler2_tbuf[le->sc_tmd], len);
313*54000Sfujita #endif
314*54000Sfujita 	tmd->tmd3 = 0;
315*54000Sfujita 	tmd->tmd2 = -len;
316*54000Sfujita 	if (++le->sc_tmd >= LETBUF)
317*54000Sfujita 		le->sc_tmd = 0;
318*54000Sfujita 	if (++le->sc_txcnt >= LETBUF) {
319*54000Sfujita 		le->sc_txcnt = LETBUF;
320*54000Sfujita 		le->sc_if.if_flags |= IFF_OACTIVE;
321*54000Sfujita 		tmd->tmd1 = LE_OWN | LE_STP | LE_ENP;
322*54000Sfujita 	} else {
323*54000Sfujita 		tmd->tmd1 = LE_OWN | LE_STP | LE_ENP;
324*54000Sfujita 		goto again;
325*54000Sfujita 	}
326*54000Sfujita 	return (0);
327*54000Sfujita }
328*54000Sfujita 
329*54000Sfujita void
330*54000Sfujita _leintr()
331*54000Sfujita {
332*54000Sfujita 	register int i;
333*54000Sfujita 
334*54000Sfujita 	for (i = 0; i < NLE; i++) {
335*54000Sfujita 		leintr(i);
336*54000Sfujita 	}
337*54000Sfujita }
338*54000Sfujita 
339*54000Sfujita int
340*54000Sfujita leintr(unit)
341*54000Sfujita 	register int unit;
342*54000Sfujita {
343*54000Sfujita 	register struct le_softc *le = &le_softc[unit];
344*54000Sfujita 	register struct lereg1 *ler1;
345*54000Sfujita 	register int stat;
346*54000Sfujita 
347*54000Sfujita 	ler1 = le->sc_r1;
348*54000Sfujita 	LERDWR(ler0, ler1->ler1_rdp, stat);
349*54000Sfujita 	if (stat & LE_SERR) {
350*54000Sfujita 		leerror(unit, stat);
351*54000Sfujita 		if (stat & LE_MERR) {
352*54000Sfujita 			le->sc_merr++;
353*54000Sfujita 			lereset(unit);
354*54000Sfujita 			return(1);
355*54000Sfujita 		}
356*54000Sfujita 		if (stat & LE_BABL)
357*54000Sfujita 			le->sc_babl++;
358*54000Sfujita 		if (stat & LE_CERR)
359*54000Sfujita 			le->sc_cerr++;
360*54000Sfujita 		if (stat & LE_MISS)
361*54000Sfujita 			le->sc_miss++;
362*54000Sfujita 		LERDWR(ler0, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp);
363*54000Sfujita 	}
364*54000Sfujita 	if ((stat & LE_RXON) == 0) {
365*54000Sfujita 		le->sc_rxoff++;
366*54000Sfujita 		lereset(unit);
367*54000Sfujita 		return(1);
368*54000Sfujita 	}
369*54000Sfujita 	if ((stat & LE_TXON) == 0) {
370*54000Sfujita 		le->sc_txoff++;
371*54000Sfujita 		lereset(unit);
372*54000Sfujita 		return(1);
373*54000Sfujita 	}
374*54000Sfujita 	if (stat & LE_RINT) {
375*54000Sfujita 		/* interrupt is cleared in lerint */
376*54000Sfujita 		lerint(unit);
377*54000Sfujita 	}
378*54000Sfujita 	if (stat & LE_TINT) {
379*54000Sfujita 		LERDWR(ler0, LE_TINT|LE_INEA, ler1->ler1_rdp);
380*54000Sfujita 		lexint(unit);
381*54000Sfujita 	}
382*54000Sfujita 	return(1);
383*54000Sfujita }
384*54000Sfujita 
385*54000Sfujita /*
386*54000Sfujita  * Ethernet interface transmitter interrupt.
387*54000Sfujita  * Start another output if more data to send.
388*54000Sfujita  */
389*54000Sfujita lexint(unit)
390*54000Sfujita 	register int unit;
391*54000Sfujita {
392*54000Sfujita 	register struct le_softc *le = &le_softc[unit];
393*54000Sfujita 	register struct letmd *tmd;
394*54000Sfujita 	int i, loopcount = 0;
395*54000Sfujita 
396*54000Sfujita 	if (le->sc_txcnt == 0) {
397*54000Sfujita 		le->sc_xint++;
398*54000Sfujita 		return;
399*54000Sfujita 	}
400*54000Sfujita again:
401*54000Sfujita 	if ((i = le->sc_tmd - le->sc_txcnt) < 0) i += LETBUF;
402*54000Sfujita 	tmd = le->sc_r2->ler2_tmd + i;
403*54000Sfujita 	if (tmd->tmd1 & LE_OWN) {
404*54000Sfujita 		if (loopcount)
405*54000Sfujita 			goto out;
406*54000Sfujita 		le->sc_xown++;
407*54000Sfujita 		return;
408*54000Sfujita 	}
409*54000Sfujita 	if (tmd->tmd1 & LE_ERR) {
410*54000Sfujita err:
411*54000Sfujita 		lexerror(unit);
412*54000Sfujita 		le->sc_if.if_oerrors++;
413*54000Sfujita 		if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) {
414*54000Sfujita 			le->sc_uflo++;
415*54000Sfujita 			lereset(unit);
416*54000Sfujita 		}
417*54000Sfujita 		else if (tmd->tmd3 & LE_LCOL)
418*54000Sfujita 			le->sc_if.if_collisions++;
419*54000Sfujita 		else if (tmd->tmd3 & LE_RTRY)
420*54000Sfujita 			le->sc_if.if_collisions += 16;
421*54000Sfujita 	}
422*54000Sfujita 	else if (tmd->tmd3 & LE_TBUFF)
423*54000Sfujita 		/* XXX documentation says BUFF not included in ERR */
424*54000Sfujita 		goto err;
425*54000Sfujita 	else if (tmd->tmd1 & LE_ONE)
426*54000Sfujita 		le->sc_if.if_collisions++;
427*54000Sfujita 	else if (tmd->tmd1 & LE_MORE)
428*54000Sfujita 		/* what is the real number? */
429*54000Sfujita 		le->sc_if.if_collisions += 2;
430*54000Sfujita 	else
431*54000Sfujita 		le->sc_if.if_opackets++;
432*54000Sfujita 	loopcount++;
433*54000Sfujita 	if (--le->sc_txcnt > 0)
434*54000Sfujita 		goto again;
435*54000Sfujita 	if (le->sc_txcnt < 0) {
436*54000Sfujita 		le->sc_txbad++;
437*54000Sfujita 		le->sc_txcnt = 0;
438*54000Sfujita 	}
439*54000Sfujita out:
440*54000Sfujita 	le->sc_if.if_flags &= ~IFF_OACTIVE;
441*54000Sfujita 	(void) lestart(&le->sc_if);
442*54000Sfujita }
443*54000Sfujita 
444*54000Sfujita #define	LENEXTRMP \
445*54000Sfujita 	if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd
446*54000Sfujita 
447*54000Sfujita /*
448*54000Sfujita  * Ethernet interface receiver interrupt.
449*54000Sfujita  * If input error just drop packet.
450*54000Sfujita  * Decapsulate packet based on type and pass to type specific
451*54000Sfujita  * higher-level input routine.
452*54000Sfujita  */
453*54000Sfujita lerint(unit)
454*54000Sfujita 	int unit;
455*54000Sfujita {
456*54000Sfujita 	register struct le_softc *le = &le_softc[unit];
457*54000Sfujita 	register int bix = le->sc_rmd;
458*54000Sfujita 	register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix];
459*54000Sfujita 
460*54000Sfujita 	/*
461*54000Sfujita 	 * Out of sync with hardware, should never happen?
462*54000Sfujita 	 */
463*54000Sfujita 	if (rmd->rmd1 & LE_OWN) {
464*54000Sfujita 		LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);
465*54000Sfujita 		return;
466*54000Sfujita 	}
467*54000Sfujita 
468*54000Sfujita 	/*
469*54000Sfujita 	 * Process all buffers with valid data
470*54000Sfujita 	 */
471*54000Sfujita 	while ((rmd->rmd1 & LE_OWN) == 0) {
472*54000Sfujita 		int len = rmd->rmd3;
473*54000Sfujita 
474*54000Sfujita 		/* Clear interrupt to avoid race condition */
475*54000Sfujita 		LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);
476*54000Sfujita 
477*54000Sfujita 		if (rmd->rmd1 & LE_ERR) {
478*54000Sfujita 			le->sc_rmd = bix;
479*54000Sfujita 			lererror(unit, "bad packet");
480*54000Sfujita 			le->sc_if.if_ierrors++;
481*54000Sfujita 		} else if ((rmd->rmd1 & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) {
482*54000Sfujita 			/*
483*54000Sfujita 			 * Find the end of the packet so we can see how long
484*54000Sfujita 			 * it was.  We still throw it away.
485*54000Sfujita 			 */
486*54000Sfujita 			do {
487*54000Sfujita 				LERDWR(le->sc_r0, LE_RINT|LE_INEA,
488*54000Sfujita 				       le->sc_r1->ler1_rdp);
489*54000Sfujita 				rmd->rmd3 = 0;
490*54000Sfujita 				rmd->rmd1 = LE_OWN;
491*54000Sfujita 				LENEXTRMP;
492*54000Sfujita 			} while (!(rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)));
493*54000Sfujita 			le->sc_rmd = bix;
494*54000Sfujita 			lererror(unit, "chained buffer");
495*54000Sfujita 			le->sc_rxlen++;
496*54000Sfujita 			/*
497*54000Sfujita 			 * If search terminated without successful completion
498*54000Sfujita 			 * we reset the hardware (conservative).
499*54000Sfujita 			 */
500*54000Sfujita 			if ((rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) !=
501*54000Sfujita 			    LE_ENP) {
502*54000Sfujita 				lereset(unit);
503*54000Sfujita 				return;
504*54000Sfujita 			}
505*54000Sfujita 		} else
506*54000Sfujita 			leread(unit, le->sc_r2->ler2_rbuf[bix], len);
507*54000Sfujita 		rmd->rmd3 = 0;
508*54000Sfujita 		rmd->rmd1 = LE_OWN;
509*54000Sfujita 		LENEXTRMP;
510*54000Sfujita 	}
511*54000Sfujita 	le->sc_rmd = bix;
512*54000Sfujita }
513*54000Sfujita 
514*54000Sfujita leread(unit, buf, len)
515*54000Sfujita 	int unit;
516*54000Sfujita 	char *buf;
517*54000Sfujita 	int len;
518*54000Sfujita {
519*54000Sfujita 	register struct le_softc *le = &le_softc[unit];
520*54000Sfujita 	register struct ether_header *et;
521*54000Sfujita     	struct mbuf *m;
522*54000Sfujita 	int off, resid;
523*54000Sfujita 
524*54000Sfujita 	le->sc_if.if_ipackets++;
525*54000Sfujita 	et = (struct ether_header *)buf;
526*54000Sfujita 	et->ether_type = ntohs((u_short)et->ether_type);
527*54000Sfujita 	/* adjust input length to account for header and CRC */
528*54000Sfujita 	len = len - sizeof(struct ether_header) - 4;
529*54000Sfujita 
530*54000Sfujita #define	ledataaddr(et, off, type)	((type)(((caddr_t)((et)+1)+(off))))
531*54000Sfujita 	if (et->ether_type >= ETHERTYPE_TRAIL &&
532*54000Sfujita 	    et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
533*54000Sfujita 		off = (et->ether_type - ETHERTYPE_TRAIL) * 512;
534*54000Sfujita 		if (off >= ETHERMTU)
535*54000Sfujita 			return;		/* sanity */
536*54000Sfujita 		et->ether_type = ntohs(*ledataaddr(et, off, u_short *));
537*54000Sfujita 		resid = ntohs(*(ledataaddr(et, off+2, u_short *)));
538*54000Sfujita 		if (off + resid > len)
539*54000Sfujita 			return;		/* sanity */
540*54000Sfujita 		len = off + resid;
541*54000Sfujita 	} else
542*54000Sfujita 		off = 0;
543*54000Sfujita 
544*54000Sfujita 	if (len <= 0) {
545*54000Sfujita 		if (ledebug)
546*54000Sfujita 			log(LOG_WARNING,
547*54000Sfujita 			    "le%d: ierror(runt packet): from %s: len=%d\n",
548*54000Sfujita 			    unit, ether_sprintf(et->ether_shost), len);
549*54000Sfujita 		le->sc_runt++;
550*54000Sfujita 		le->sc_if.if_ierrors++;
551*54000Sfujita 		return;
552*54000Sfujita 	}
553*54000Sfujita #if NBPFILTER > 0
554*54000Sfujita 	/*
555*54000Sfujita 	 * Check if there's a bpf filter listening on this interface.
556*54000Sfujita 	 * If so, hand off the raw packet to bpf, which must deal with
557*54000Sfujita 	 * trailers in its own way.
558*54000Sfujita 	 */
559*54000Sfujita 	if (le->sc_bpf)
560*54000Sfujita 		bpf_tap(le->sc_bpf, buf, len + sizeof(struct ether_header));
561*54000Sfujita #endif
562*54000Sfujita #if defined(ISO) || NBPFILTER > 0
563*54000Sfujita 	/*
564*54000Sfujita 	 * Note that the interface cannot be in promiscuous mode if
565*54000Sfujita 	 * there are no bpf listeners.  If we are in promiscuous
566*54000Sfujita 	 * mode, we have to check if this packet is really ours.
567*54000Sfujita 	 * However, there may be appropriate multicate addresses involved
568*54000Sfujita 	 */
569*54000Sfujita #define NOT_TO(p) (bcmp(et->ether_dhost, p, sizeof(et->ether_dhost)) != 0)
570*54000Sfujita 	if (et->ether_dhost[0] & 1) {
571*54000Sfujita 		if (NOT_TO(etherbroadcastaddr) && NOT_TO(hprmp_multi)
572*54000Sfujita #ifdef ISO
573*54000Sfujita 		    && NOT_TO(all_es_snpa) && NOT_TO(all_is_snpa)
574*54000Sfujita 		    && NOT_TO(all_l1is_snpa) && NOT_TO(all_l2is_snpa)
575*54000Sfujita #endif
576*54000Sfujita 		     ) return;
577*54000Sfujita 	} else if ((le->sc_if.if_flags & IFF_PROMISC) && NOT_TO(le->sc_addr))
578*54000Sfujita 		return;
579*54000Sfujita #endif
580*54000Sfujita 	/*
581*54000Sfujita 	 * Pull packet off interface.  Off is nonzero if packet
582*54000Sfujita 	 * has trailing header; m_devget will then force this header
583*54000Sfujita 	 * information to be at the front, but we still have to drop
584*54000Sfujita 	 * the type and length which are at the front of any trailer data.
585*54000Sfujita 	 */
586*54000Sfujita 	m = m_devget((char *)(et + 1), len, off, &le->sc_if, 0);
587*54000Sfujita 	if (m == 0)
588*54000Sfujita 		return;
589*54000Sfujita 	ether_input(&le->sc_if, et, m);
590*54000Sfujita }
591*54000Sfujita 
592*54000Sfujita /*
593*54000Sfujita  * Routine to copy from mbuf chain to transmit
594*54000Sfujita  * buffer in board local memory.
595*54000Sfujita  */
596*54000Sfujita leput(lebuf, m)
597*54000Sfujita 	register char *lebuf;
598*54000Sfujita 	register struct mbuf *m;
599*54000Sfujita {
600*54000Sfujita 	register struct mbuf *mp;
601*54000Sfujita 	register int len, tlen = 0;
602*54000Sfujita 
603*54000Sfujita 	for (mp = m; mp; mp = mp->m_next) {
604*54000Sfujita 		len = mp->m_len;
605*54000Sfujita 		if (len == 0)
606*54000Sfujita 			continue;
607*54000Sfujita 		tlen += len;
608*54000Sfujita 		bcopy(mtod(mp, char *), lebuf, len);
609*54000Sfujita 		lebuf += len;
610*54000Sfujita 	}
611*54000Sfujita 	m_freem(m);
612*54000Sfujita 	if (tlen < LEMINSIZE) {
613*54000Sfujita 		bzero(lebuf, LEMINSIZE - tlen);
614*54000Sfujita 		tlen = LEMINSIZE;
615*54000Sfujita 	}
616*54000Sfujita 	return(tlen);
617*54000Sfujita }
618*54000Sfujita 
619*54000Sfujita /*
620*54000Sfujita  * Process an ioctl request.
621*54000Sfujita  */
622*54000Sfujita leioctl(ifp, cmd, data)
623*54000Sfujita 	register struct ifnet *ifp;
624*54000Sfujita 	int cmd;
625*54000Sfujita 	caddr_t data;
626*54000Sfujita {
627*54000Sfujita 	register struct ifaddr *ifa = (struct ifaddr *)data;
628*54000Sfujita 	struct le_softc *le = &le_softc[ifp->if_unit];
629*54000Sfujita 	struct lereg1 *ler1 = le->sc_r1;
630*54000Sfujita 	int s = splimp(), error = 0;
631*54000Sfujita 
632*54000Sfujita 	switch (cmd) {
633*54000Sfujita 
634*54000Sfujita 	case SIOCSIFADDR:
635*54000Sfujita 		ifp->if_flags |= IFF_UP;
636*54000Sfujita 		switch (ifa->ifa_addr->sa_family) {
637*54000Sfujita #ifdef INET
638*54000Sfujita 		case AF_INET:
639*54000Sfujita 			leinit(ifp->if_unit);	/* before arpwhohas */
640*54000Sfujita 			((struct arpcom *)ifp)->ac_ipaddr =
641*54000Sfujita 				IA_SIN(ifa)->sin_addr;
642*54000Sfujita 			arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
643*54000Sfujita 			break;
644*54000Sfujita #endif
645*54000Sfujita #ifdef NS
646*54000Sfujita 		case AF_NS:
647*54000Sfujita 		    {
648*54000Sfujita 			register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
649*54000Sfujita 
650*54000Sfujita 			if (ns_nullhost(*ina))
651*54000Sfujita 				ina->x_host = *(union ns_host *)(le->sc_addr);
652*54000Sfujita 			else {
653*54000Sfujita 				/*
654*54000Sfujita 				 * The manual says we can't change the address
655*54000Sfujita 				 * while the receiver is armed,
656*54000Sfujita 				 * so reset everything
657*54000Sfujita 				 */
658*54000Sfujita 				ifp->if_flags &= ~IFF_RUNNING;
659*54000Sfujita 				LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp);
660*54000Sfujita 				bcopy((caddr_t)ina->x_host.c_host,
661*54000Sfujita 				    (caddr_t)le->sc_addr, sizeof(le->sc_addr));
662*54000Sfujita 			}
663*54000Sfujita 			leinit(ifp->if_unit); /* does le_setaddr() */
664*54000Sfujita 			break;
665*54000Sfujita 		    }
666*54000Sfujita #endif
667*54000Sfujita 		default:
668*54000Sfujita 			leinit(ifp->if_unit);
669*54000Sfujita 			break;
670*54000Sfujita 		}
671*54000Sfujita 		break;
672*54000Sfujita 
673*54000Sfujita 	case SIOCSIFFLAGS:
674*54000Sfujita 		if ((ifp->if_flags & IFF_UP) == 0 &&
675*54000Sfujita 		    ifp->if_flags & IFF_RUNNING) {
676*54000Sfujita 			LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp);
677*54000Sfujita 			ifp->if_flags &= ~IFF_RUNNING;
678*54000Sfujita 		} else if (ifp->if_flags & IFF_UP &&
679*54000Sfujita 		    (ifp->if_flags & IFF_RUNNING) == 0)
680*54000Sfujita 			leinit(ifp->if_unit);
681*54000Sfujita 		/*
682*54000Sfujita 		 * If the state of the promiscuous bit changes, the interface
683*54000Sfujita 		 * must be reset to effect the change.
684*54000Sfujita 		 */
685*54000Sfujita 		if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) &&
686*54000Sfujita 		    (ifp->if_flags & IFF_RUNNING)) {
687*54000Sfujita 			le->sc_iflags = ifp->if_flags;
688*54000Sfujita 			lereset(ifp->if_unit);
689*54000Sfujita 			lestart(ifp);
690*54000Sfujita 		}
691*54000Sfujita 		break;
692*54000Sfujita 
693*54000Sfujita 	default:
694*54000Sfujita 		error = EINVAL;
695*54000Sfujita 	}
696*54000Sfujita 	splx(s);
697*54000Sfujita 	return (error);
698*54000Sfujita }
699*54000Sfujita 
700*54000Sfujita leerror(unit, stat)
701*54000Sfujita 	int unit;
702*54000Sfujita 	int stat;
703*54000Sfujita {
704*54000Sfujita 	if (!ledebug)
705*54000Sfujita 		return;
706*54000Sfujita 
707*54000Sfujita 	/*
708*54000Sfujita 	 * Not all transceivers implement heartbeat
709*54000Sfujita 	 * so we only log CERR once.
710*54000Sfujita 	 */
711*54000Sfujita 	if ((stat & LE_CERR) && le_softc[unit].sc_cerr)
712*54000Sfujita 		return;
713*54000Sfujita 	log(LOG_WARNING,
714*54000Sfujita 	    "le%d: error: stat=%b\n", unit,
715*54000Sfujita 	    stat,
716*54000Sfujita 	    "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT");
717*54000Sfujita }
718*54000Sfujita 
719*54000Sfujita lererror(unit, msg)
720*54000Sfujita 	int unit;
721*54000Sfujita 	char *msg;
722*54000Sfujita {
723*54000Sfujita 	register struct le_softc *le = &le_softc[unit];
724*54000Sfujita 	register struct lermd *rmd;
725*54000Sfujita 	int len;
726*54000Sfujita 
727*54000Sfujita 	if (!ledebug)
728*54000Sfujita 		return;
729*54000Sfujita 
730*54000Sfujita 	rmd = &le->sc_r2->ler2_rmd[le->sc_rmd];
731*54000Sfujita 	len = rmd->rmd3;
732*54000Sfujita 	log(LOG_WARNING,
733*54000Sfujita 	    "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
734*54000Sfujita 	    unit, msg,
735*54000Sfujita 	    len > 11 ?
736*54000Sfujita 		ether_sprintf((u_char *)&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) :
737*54000Sfujita 		"unknown",
738*54000Sfujita 	    le->sc_rmd, len,
739*54000Sfujita 	    rmd->rmd1,
740*54000Sfujita 	    "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP");
741*54000Sfujita }
742*54000Sfujita 
743*54000Sfujita lexerror(unit)
744*54000Sfujita 	int unit;
745*54000Sfujita {
746*54000Sfujita 	register struct le_softc *le = &le_softc[unit];
747*54000Sfujita 	register struct letmd *tmd;
748*54000Sfujita 	int len;
749*54000Sfujita 
750*54000Sfujita 	if (!ledebug)
751*54000Sfujita 		return;
752*54000Sfujita 
753*54000Sfujita 	tmd = le->sc_r2->ler2_tmd;
754*54000Sfujita 	len = -tmd->tmd2;
755*54000Sfujita 	log(LOG_WARNING,
756*54000Sfujita 	    "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n",
757*54000Sfujita 	    unit,
758*54000Sfujita 	    len > 5 ?
759*54000Sfujita 		ether_sprintf((u_char *)&le->sc_r2->ler2_tbuf[0][0]) :
760*54000Sfujita 		"unknown",
761*54000Sfujita 	    0, len,
762*54000Sfujita 	    tmd->tmd1,
763*54000Sfujita 	    "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP",
764*54000Sfujita 	    tmd->tmd3,
765*54000Sfujita 	    "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY");
766*54000Sfujita }
767*54000Sfujita #endif
768