xref: /netbsd-src/sys/arch/hp300/dev/if_le.c (revision ae1bfcddc410612bc8c58b807e1830becb69a24c)
1 /*
2  * Copyright (c) 1982, 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	from: @(#)if_le.c	7.6 (Berkeley) 5/8/91
34  *	$Id: if_le.c,v 1.12 1994/05/13 08:36:17 mycroft Exp $
35  */
36 
37 #include "le.h"
38 #if NLE > 0
39 
40 #include "bpfilter.h"
41 
42 /*
43  * AMD 7990 LANCE
44  */
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/mbuf.h>
49 #include <sys/buf.h>
50 #include <sys/socket.h>
51 #include <sys/syslog.h>
52 #include <sys/ioctl.h>
53 #include <sys/malloc.h>
54 #include <sys/errno.h>
55 
56 #include <net/if.h>
57 #include <net/netisr.h>
58 #include <net/route.h>
59 #if NBPFILTER > 0
60 #include <net/bpf.h>
61 #include <net/bpfdesc.h>
62 #endif
63 
64 #ifdef INET
65 #include <netinet/in.h>
66 #include <netinet/in_systm.h>
67 #include <netinet/in_var.h>
68 #include <netinet/ip.h>
69 #include <netinet/if_ether.h>
70 #endif
71 
72 #ifdef NS
73 #include <netns/ns.h>
74 #include <netns/ns_if.h>
75 #endif
76 
77 #include <machine/cpu.h>
78 #include <hp300/hp300/isr.h>
79 #include <machine/mtpr.h>
80 
81 #include <hp300/dev/device.h>
82 #include <hp300/dev/if_lereg.h>
83 
84 /* offsets for:	   ID,   REGS,    MEM,  NVRAM */
85 int	lestd[] = { 0, 0x4000, 0x8000, 0xC008 };
86 
87 struct	isr le_isr[NLE];
88 int	ledebug = 0;		/* console error messages */
89 
90 /*
91  * Ethernet software status per interface.
92  *
93  * Each interface is referenced by a network interface structure,
94  * le_if, which the routing code uses to locate the interface.
95  * This structure contains the output queue for the interface, its address, ...
96  */
97 struct	le_softc {
98 	struct	arpcom sc_ac;	/* common Ethernet structures */
99 #define	sc_if	sc_ac.ac_if	/* network-visible interface */
100 #define	sc_addr	sc_ac.ac_enaddr	/* hardware Ethernet address */
101 	struct	lereg0 *sc_r0;	/* DIO registers */
102 	struct	lereg1 *sc_r1;	/* LANCE registers */
103 	struct	lereg2 *sc_r2;	/* dual-port RAM */
104 	int	sc_rmd;		/* predicted next rmd to process */
105 	int	sc_tmd;		/* next available tmd */
106 	int	sc_txcnt;	/* # of transmit buffers in use */
107 	/* stats */
108 	int	sc_runt;
109 	int	sc_jab;
110 	int	sc_merr;
111 	int	sc_babl;
112 	int	sc_cerr;
113 	int	sc_miss;
114 	int	sc_rown;
115 	int	sc_xint;
116 	int	sc_xown;
117 	int	sc_xown2;
118 	int	sc_uflo;
119 	int	sc_rxlen;
120 	int	sc_rxoff;
121 	int	sc_txoff;
122 	int	sc_busy;
123 	short	sc_iflags;
124 } le_softc[NLE];
125 
126 /* access LANCE registers */
127 #define	LERDWR(cntl, src, dst) \
128 	do { \
129 		(dst) = (src); \
130 	} while (((cntl)->ler0_status & LE_ACK) == 0);
131 
132 int leattach __P((struct hp_device *));
133 void lesetladrf __P((struct arpcom *, u_long *));
134 void ledrinit __P((struct lereg2 *));
135 void lereset __P((struct le_softc *));
136 void leinit __P((int));
137 int lestart __P((struct ifnet *));
138 int leintr __P((int));
139 void lexint __P((struct le_softc *));
140 void lerint __P((struct le_softc *));
141 void leread __P((struct le_softc *, char *, int));
142 int leput __P((char *, struct mbuf *));
143 struct mbuf *leget __P((char *, int, int, struct ifnet *));
144 int leioctl __P((struct ifnet *, int, caddr_t));
145 void leerror __P((struct le_softc *, int));
146 void lererror __P((struct le_softc *, char *));
147 void lexerror __P((struct le_softc *));
148 int ether_output();
149 
150 struct	driver ledriver = {
151 	leattach, "le",
152 };
153 
154 /*
155  * Interface exists: make available by filling in network interface
156  * record.  System will initialize the interface when it is ready
157  * to accept packets.
158  */
159 int
160 leattach(hd)
161 	struct hp_device *hd;
162 {
163 	register struct lereg0 *ler0;
164 	register struct lereg2 *ler2;
165 	struct lereg2 *lemem = 0;
166 	struct le_softc *sc = &le_softc[hd->hp_unit];
167 	struct ifnet *ifp = &sc->sc_if;
168 	char *cp;
169 	int i;
170 
171 	ler0 = sc->sc_r0 = (struct lereg0 *)(lestd[0] + (int)hd->hp_addr);
172 	sc->sc_r1 = (struct lereg1 *)(lestd[1] + (int)hd->hp_addr);
173 	ler2 = sc->sc_r2 = (struct lereg2 *)(lestd[2] + (int)hd->hp_addr);
174 	if (ler0->ler0_id != LEID)
175 		return(0);
176 	le_isr[hd->hp_unit].isr_intr = leintr;
177 	hd->hp_ipl = le_isr[hd->hp_unit].isr_ipl = LE_IPL(ler0->ler0_status);
178 	le_isr[hd->hp_unit].isr_arg = hd->hp_unit;
179 	ler0->ler0_id = 0xFF;
180 	DELAY(100);
181 
182 	/*
183 	 * Read the ethernet address off the board, one nibble at a time.
184 	 */
185 	cp = (char *)(lestd[3] + (int)hd->hp_addr);
186 	for (i = 0; i < sizeof(sc->sc_addr); i++) {
187 		sc->sc_addr[i] = (*++cp & 0xF) << 4;
188 		cp++;
189 		sc->sc_addr[i] |= *++cp & 0xF;
190 		cp++;
191 	}
192 	printf("le%d: hardware address %s\n", hd->hp_unit,
193 		ether_sprintf(sc->sc_addr));
194 
195 	/*
196 	 * Setup for transmit/receive
197 	 */
198 	ler2->ler2_mode = LE_MODE;
199 	ler2->ler2_rlen = LE_RLEN;
200 	ler2->ler2_rdra = (int)lemem->ler2_rmd;
201 	ler2->ler2_tlen = LE_TLEN;
202 	ler2->ler2_tdra = (int)lemem->ler2_tmd;
203 	isrlink(&le_isr[hd->hp_unit]);
204 	ler0->ler0_status = LE_IE;
205 
206 	ifp->if_unit = hd->hp_unit;
207 	ifp->if_name = "le";
208 	ifp->if_ioctl = leioctl;
209 	ifp->if_output = ether_output;
210 	ifp->if_start = lestart;
211 	ifp->if_flags =
212 	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
213 	if_attach(ifp);
214 	ether_ifattach(ifp);
215 #if NBPFILTER > 0
216 	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
217 #endif
218 	return (1);
219 }
220 
221 /*
222  * Set up the logical address filter
223  */
224 void
225 lesetladrf(ac, af)
226 	struct arpcom *ac;
227 	u_long *af;
228 {
229 	struct ifnet *ifp = &ac->ac_if;
230 	struct ether_multi *enm;
231 	register u_char *cp, c;
232 	register u_long crc;
233 	register int i, len;
234 	struct ether_multistep step;
235 
236 	/*
237 	 * Set up multicast address filter by passing all multicast addresses
238 	 * through a crc generator, and then using the high order 6 bits as an
239 	 * index into the 64 bit logical address filter.  The high order bit
240 	 * selects the word, while the rest of the bits select the bit within
241 	 * the word.
242 	 */
243 
244 	if (ifp->if_flags & IFF_PROMISC) {
245 		ifp->if_flags |= IFF_ALLMULTI;
246 		af[0] = af[1] = 0xffffffff;
247 		return;
248 	}
249 
250 	af[0] = af[1] = 0;
251 	ETHER_FIRST_MULTI(step, ac, enm);
252 	while (enm != NULL) {
253 		if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
254 		    sizeof(enm->enm_addrlo)) != 0) {
255 			/*
256 			 * We must listen to a range of multicast addresses.
257 			 * For now, just accept all multicasts, rather than
258 			 * trying to set only those filter bits needed to match
259 			 * the range.  (At this time, the only use of address
260 			 * ranges is for IP multicast routing, for which the
261 			 * range is big enough to require all bits set.)
262 			 */
263 			ifp->if_flags |= IFF_ALLMULTI;
264 			af[0] = af[1] = 0xffffffff;
265 			return;
266 		}
267 
268 		cp = enm->enm_addrlo;
269 		crc = 0xffffffff;
270 		for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
271 			c = *cp++;
272 			for (i = 8; --i >= 0;) {
273 				if ((c & 0x01) ^ (crc & 0x01)) {
274 					crc >>= 1;
275 					crc ^= 0x6db88320 | 0x80000000;
276 				} else
277 					crc >>= 1;
278 				c >>= 1;
279 			}
280 		}
281 		/* Just want the 6 most significant bits. */
282 		crc >>= 26;
283 
284 		/* Turn on the corresponding bit in the filter. */
285 		af[crc >> 5] |= 1 << (crc & 0x1f);
286 
287 		ETHER_NEXT_MULTI(step, enm);
288 	}
289 	ifp->if_flags &= ~IFF_ALLMULTI;
290 }
291 
292 void
293 ledrinit(ler2)
294 	register struct lereg2 *ler2;
295 {
296 	register struct lereg2 *lemem = 0;
297 	register int i;
298 
299 	for (i = 0; i < LERBUF; i++) {
300 		ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i];
301 		ler2->ler2_rmd[i].rmd1 = LE_OWN;
302 		ler2->ler2_rmd[i].rmd2 = -LEMTU;
303 		ler2->ler2_rmd[i].rmd3 = 0;
304 	}
305 	for (i = 0; i < LETBUF; i++) {
306 		ler2->ler2_tmd[i].tmd0 = (int)lemem->ler2_tbuf[i];
307 		ler2->ler2_tmd[i].tmd1 = 0;
308 		ler2->ler2_tmd[i].tmd2 = 0;
309 		ler2->ler2_tmd[i].tmd3 = 0;
310 	}
311 }
312 
313 void
314 lereset(sc)
315 	register struct le_softc *sc;
316 {
317 	register struct lereg0 *ler0 = sc->sc_r0;
318 	register struct lereg1 *ler1 = sc->sc_r1;
319 	register struct lereg2 *ler2 = sc->sc_r2;
320 	struct lereg2 *lemem = 0;
321 	register int timo, stat;
322 
323 #if NBPFILTER > 0
324 	if (sc->sc_if.if_flags & IFF_PROMISC)
325 		/* set the promiscuous bit */
326 		ler2->ler2_mode = LE_MODE|0x8000;
327 	else
328 #endif
329 		ler2->ler2_mode = LE_MODE;
330 	LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
331 	LERDWR(ler0, LE_STOP, ler1->ler1_rdp);
332 
333 	ler2->ler2_padr[0] = sc->sc_addr[1];
334 	ler2->ler2_padr[1] = sc->sc_addr[0];
335 	ler2->ler2_padr[2] = sc->sc_addr[3];
336 	ler2->ler2_padr[3] = sc->sc_addr[2];
337 	ler2->ler2_padr[4] = sc->sc_addr[5];
338 	ler2->ler2_padr[5] = sc->sc_addr[4];
339 	lesetladrf(&sc->sc_ac, ler2->ler2_ladrf);
340 	ledrinit(ler2);
341 	sc->sc_rmd = sc->sc_tmd = sc->sc_txcnt = 0;
342 
343 	LERDWR(ler0, LE_CSR1, ler1->ler1_rap);
344 	LERDWR(ler0, (int)&lemem->ler2_mode, ler1->ler1_rdp);
345 	LERDWR(ler0, LE_CSR2, ler1->ler1_rap);
346 	LERDWR(ler0, 0, ler1->ler1_rdp);
347 	LERDWR(ler0, LE_CSR3, ler1->ler1_rap);
348 	LERDWR(ler0, LE_BSWP, ler1->ler1_rdp);
349 	LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
350 	LERDWR(ler0, LE_INIT, ler1->ler1_rdp);
351 	timo = 100000;
352 	do {
353 		if (--timo == 0) {
354 			printf("le%d: init timeout, stat=0x%x\n",
355 			    sc->sc_if.if_unit, stat);
356 			break;
357 		}
358 		LERDWR(ler0, ler1->ler1_rdp, stat);
359 	} while ((stat & (LE_IDON | LE_ERR)) == 0);
360 	if (stat & LE_ERR)
361 		printf("le%d: init failed, stat=0x%x\n",
362 		    sc->sc_if.if_unit, stat);
363 	else
364 		LERDWR(ler0, LE_IDON, ler1->ler1_rdp);
365 	sc->sc_if.if_flags &= ~IFF_OACTIVE;
366 	LERDWR(ler0, LE_STRT | LE_INEA, ler1->ler1_rdp);
367 }
368 
369 /*
370  * Initialization of interface
371  */
372 void
373 leinit(unit)
374 	int unit;
375 {
376 	struct le_softc *sc = &le_softc[unit];
377 	register struct ifnet *ifp = &sc->sc_if;
378 	int s;
379 
380 	/* not yet, if address still unknown */
381 	if (ifp->if_addrlist == (struct ifaddr *)0)
382 		return;
383 	if ((ifp->if_flags & IFF_RUNNING) == 0) {
384 		s = splimp();
385 		ifp->if_flags |= IFF_RUNNING;
386 		lereset(sc);
387 		(void) lestart(ifp);
388 		splx(s);
389 	}
390 }
391 
392 #define	LENEXTTMP \
393 	if (++bix == LETBUF) bix = 0, tmd = sc->sc_r2->ler2_tmd; else ++tmd
394 
395 /*
396  * Start output on interface.  Get another datagram to send
397  * off of the interface queue, and copy it to the interface
398  * before starting the output.
399  */
400 int
401 lestart(ifp)
402 	struct ifnet *ifp;
403 {
404 	register struct le_softc *sc = &le_softc[ifp->if_unit];
405 	register int bix;
406 	register struct letmd *tmd;
407 	register struct mbuf *m;
408 	int len, gotone = 0;
409 
410 	if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
411 		return (0);
412 	bix = sc->sc_tmd;
413 	tmd = &sc->sc_r2->ler2_tmd[bix];
414 	do {
415 		if (tmd->tmd1 & LE_OWN) {
416 			if (gotone)
417 				break;
418 			sc->sc_xown2++;
419 			return (0);
420 		}
421 		IF_DEQUEUE(&sc->sc_if.if_snd, m);
422 		if (m == 0) {
423 			if (gotone)
424 				break;
425 			return (0);
426 		}
427 		len = leput(sc->sc_r2->ler2_tbuf[bix], m);
428 #if NBPFILTER > 0
429 		/*
430 		 * If bpf is listening on this interface, let it
431 		 * see the packet before we commit it to the wire.
432 		 */
433 		if (ifp->if_bpf)
434 			bpf_tap(ifp->if_bpf, sc->sc_r2->ler2_tbuf[bix], len);
435 #endif
436 		tmd->tmd3 = 0;
437 		tmd->tmd2 = -len;
438 		tmd->tmd1 = LE_OWN | LE_STP | LE_ENP;
439 		LENEXTTMP;
440 		gotone++;
441 	} while (++sc->sc_txcnt < LETBUF);
442 	sc->sc_tmd = bix;
443 	sc->sc_if.if_flags |= IFF_OACTIVE;
444 	/* transmit as soon as possible */
445 	LERDWR(sc->sc_r0, LE_INEA|LE_TDMD, sc->sc_r1->ler1_rdp);
446 	return (0);
447 }
448 
449 int
450 leintr(unit)
451 	register int unit;
452 {
453 	register struct le_softc *sc = &le_softc[unit];
454 	register struct lereg0 *ler0 = sc->sc_r0;
455 	register struct lereg1 *ler1;
456 	register int stat;
457 
458 	if ((ler0->ler0_status & LE_IR) == 0)
459 		return(0);
460 	if (ler0->ler0_status & LE_JAB) {
461 		sc->sc_jab++;
462 		lereset(sc);
463 		return(1);
464 	}
465 	ler1 = sc->sc_r1;
466 	LERDWR(ler0, ler1->ler1_rdp, stat);
467 	if (stat & LE_SERR) {
468 		leerror(sc, stat);
469 		if (stat & LE_MERR) {
470 			sc->sc_merr++;
471 			lereset(sc);
472 			return(1);
473 		}
474 		if (stat & LE_BABL)
475 			sc->sc_babl++;
476 		if (stat & LE_CERR)
477 			sc->sc_cerr++;
478 		if (stat & LE_MISS)
479 			sc->sc_miss++;
480 		LERDWR(ler0, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp);
481 	}
482 	if ((stat & LE_RXON) == 0) {
483 		sc->sc_rxoff++;
484 		lereset(sc);
485 		return(1);
486 	}
487 	if ((stat & LE_TXON) == 0) {
488 		sc->sc_txoff++;
489 		lereset(sc);
490 		return(1);
491 	}
492 	if (stat & LE_RINT)
493 		lerint(sc);
494 	if (stat & LE_TINT)
495 		lexint(sc);
496 	return(1);
497 }
498 
499 /*
500  * Ethernet interface transmitter interrupt.
501  * Start another output if more data to send.
502  */
503 void
504 lexint(sc)
505 	register struct le_softc *sc;
506 {
507 	register struct letmd *tmd;
508 	int bix, gotone = 0;
509 
510 	if ((sc->sc_if.if_flags & IFF_OACTIVE) == 0) {
511 		sc->sc_xint++;
512 		return;
513 	}
514 	if ((bix = sc->sc_tmd - sc->sc_txcnt) < 0)
515 		bix += LETBUF;
516 	tmd = &sc->sc_r2->ler2_tmd[bix];
517 	do {
518 		if (tmd->tmd1 & LE_OWN) {
519 			if (gotone)
520 				break;
521 			sc->sc_xown++;
522 			return;
523 		}
524 
525 		/* clear interrupt */
526 		LERDWR(sc->sc_r0, LE_TINT|LE_INEA, sc->sc_r1->ler1_rdp);
527 
528 		/* XXX documentation says BUFF not included in ERR */
529 		if ((tmd->tmd1 & LE_ERR) || (tmd->tmd3 & LE_TBUFF)) {
530 			lexerror(sc);
531 			sc->sc_if.if_oerrors++;
532 			if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) {
533 				sc->sc_uflo++;
534 				lereset(sc);
535 			} else if (tmd->tmd3 & LE_LCOL)
536 				sc->sc_if.if_collisions++;
537 			else if (tmd->tmd3 & LE_RTRY)
538 				sc->sc_if.if_collisions += 16;
539 		}
540 		else if (tmd->tmd1 & LE_ONE)
541 			sc->sc_if.if_collisions++;
542 		else if (tmd->tmd1 & LE_MORE)
543 			/* what is the real number? */
544 			sc->sc_if.if_collisions += 2;
545 		else
546 			sc->sc_if.if_opackets++;
547 		LENEXTTMP;
548 		gotone++;
549 	} while (--sc->sc_txcnt > 0);
550 	sc->sc_if.if_flags &= ~IFF_OACTIVE;
551 	(void) lestart(&sc->sc_if);
552 }
553 
554 #define	LENEXTRMP \
555 	if (++bix == LERBUF) bix = 0, rmd = sc->sc_r2->ler2_rmd; else ++rmd
556 
557 /*
558  * Ethernet interface receiver interrupt.
559  * If input error just drop packet.
560  * Decapsulate packet based on type and pass to type specific
561  * higher-level input routine.
562  */
563 void
564 lerint(sc)
565 	register struct le_softc *sc;
566 {
567 	register int bix = sc->sc_rmd;
568 	register struct lermd *rmd = &sc->sc_r2->ler2_rmd[bix];
569 
570 	/*
571 	 * Out of sync with hardware, should never happen?
572 	 */
573 	if (rmd->rmd1 & LE_OWN) {
574 		sc->sc_rown++;
575 		do {
576 			LENEXTRMP;
577 		} while ((rmd->rmd1 & LE_OWN) && bix != sc->sc_rmd);
578 		if (bix == sc->sc_rmd) {
579 			printf("le%d: rint with no buffer\n",
580 			    sc->sc_if.if_unit);
581 			LERDWR(sc->sc_r0, LE_RINT|LE_INEA, sc->sc_r1->ler1_rdp);
582 			return;
583 		}
584 	}
585 
586 	/*
587 	 * Process all buffers with valid data
588 	 */
589 	while ((rmd->rmd1 & LE_OWN) == 0) {
590 		int len = rmd->rmd3;
591 
592 		/* Clear interrupt to avoid race condition */
593 		LERDWR(sc->sc_r0, LE_RINT|LE_INEA, sc->sc_r1->ler1_rdp);
594 
595 		if (rmd->rmd1 & LE_ERR) {
596 			sc->sc_rmd = bix;
597 			lererror(sc, "bad packet");
598 			sc->sc_if.if_ierrors++;
599 		} else if ((rmd->rmd1 & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) {
600 			/*
601 			 * Find the end of the packet so we can see how long
602 			 * it was.  We still throw it away.
603 			 */
604 			do {
605 				LERDWR(sc->sc_r0, LE_RINT|LE_INEA,
606 				       sc->sc_r1->ler1_rdp);
607 				rmd->rmd3 = 0;
608 				rmd->rmd1 = LE_OWN;
609 				LENEXTRMP;
610 			} while (!(rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)));
611 			sc->sc_rmd = bix;
612 			lererror(sc, "chained buffer");
613 			sc->sc_rxlen++;
614 			/*
615 			 * If search terminated without successful completion
616 			 * we reset the hardware (conservative).
617 			 */
618 			if ((rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) !=
619 			    LE_ENP) {
620 				lereset(sc);
621 				return;
622 			}
623 		} else
624 			leread(sc, sc->sc_r2->ler2_rbuf[bix], len);
625 		rmd->rmd3 = 0;
626 		rmd->rmd1 = LE_OWN;
627 		LENEXTRMP;
628 	}
629 	sc->sc_rmd = bix;
630 }
631 
632 void
633 leread(sc, buf, len)
634 	register struct le_softc *sc;
635 	char *buf;
636 	int len;
637 {
638 	register struct ether_header *et;
639 	register struct ifnet *ifp = &sc->sc_if;
640     	struct mbuf *m;
641 
642 	ifp->if_ipackets++;
643 	et = (struct ether_header *)buf;
644 	/* adjust input length to account for header and CRC */
645 	len -= sizeof(struct ether_header) + 4;
646 
647 	if (len <= 0) {
648 		if (ledebug)
649 			log(LOG_WARNING,
650 			    "le%d: ierror(runt packet): from %s: len=%d\n",
651 			    sc->sc_if.if_unit, ether_sprintf(et->ether_shost),
652 			    len);
653 		sc->sc_runt++;
654 		ifp->if_ierrors++;
655 		return;
656 	}
657 
658 #if NBPFILTER > 0
659 	/*
660 	 * Check if there's a bpf filter listening on this interface.
661 	 * If so, hand off the raw packet to bpf, then discard things
662 	 * not destined for us (but be sure to keep broadcast/multicast).
663 	 */
664 	if (ifp->if_bpf) {
665 		bpf_tap(ifp->if_bpf, buf, len + sizeof(struct ether_header));
666 		if ((ifp->if_flags & IFF_PROMISC) &&
667 		    (et->ether_dhost[0] & 1) == 0 &&
668 		    bcmp(et->ether_dhost, sc->sc_addr,
669 			    sizeof(et->ether_dhost)) != 0)
670 			return;
671 	}
672 #endif
673 
674 	m = leget(buf, len, 0, ifp);
675 	if (m == 0)
676 		return;
677 
678 	ether_input(ifp, et, m);
679 }
680 
681 /*
682  * Routine to copy from mbuf chain to transmit
683  * buffer in board local memory.
684  */
685 int
686 leput(lebuf, m)
687 	register char *lebuf;
688 	register struct mbuf *m;
689 {
690 	register struct mbuf *mp;
691 	register int len, tlen = 0;
692 
693 	for (mp = m; mp; mp = mp->m_next) {
694 		len = mp->m_len;
695 		if (len == 0)
696 			continue;
697 		tlen += len;
698 		bcopy(mtod(mp, char *), lebuf, len);
699 		lebuf += len;
700 	}
701 	m_freem(m);
702 	if (tlen < LEMINSIZE) {
703 		bzero(lebuf, LEMINSIZE - tlen);
704 		tlen = LEMINSIZE;
705 	}
706 	return(tlen);
707 }
708 
709 /*
710  * Routine to copy from board local memory into mbufs.
711  */
712 struct mbuf *
713 leget(lebuf, totlen, off0, ifp)
714 	char *lebuf;
715 	int totlen, off0;
716 	struct ifnet *ifp;
717 {
718 	register struct mbuf *m;
719 	struct mbuf *top = 0, **mp = &top;
720 	register int off = off0, len;
721 	register char *cp;
722 	char *epkt;
723 
724 	lebuf += sizeof (struct ether_header);
725 	cp = lebuf;
726 	epkt = cp + totlen;
727 	if (off) {
728 		cp += off + 2 * sizeof(u_short);
729 		totlen -= 2 * sizeof(u_short);
730 	}
731 
732 	MGETHDR(m, M_DONTWAIT, MT_DATA);
733 	if (m == 0)
734 		return (0);
735 	m->m_pkthdr.rcvif = ifp;
736 	m->m_pkthdr.len = totlen;
737 	m->m_len = MHLEN;
738 
739 	while (totlen > 0) {
740 		if (top) {
741 			MGET(m, M_DONTWAIT, MT_DATA);
742 			if (m == 0) {
743 				m_freem(top);
744 				return (0);
745 			}
746 			m->m_len = MLEN;
747 		}
748 		len = min(totlen, epkt - cp);
749 		if (len >= MINCLSIZE) {
750 			MCLGET(m, M_DONTWAIT);
751 			if (m->m_flags & M_EXT)
752 				m->m_len = len = min(len, MCLBYTES);
753 			else
754 				len = m->m_len;
755 		} else {
756 			/*
757 			 * Place initial small packet/header at end of mbuf.
758 			 */
759 			if (len < m->m_len) {
760 				if (top == 0 && len + max_linkhdr <= m->m_len)
761 					m->m_data += max_linkhdr;
762 				m->m_len = len;
763 			} else
764 				len = m->m_len;
765 		}
766 		bcopy(cp, mtod(m, caddr_t), (unsigned)len);
767 		cp += len;
768 		*mp = m;
769 		mp = &m->m_next;
770 		totlen -= len;
771 		if (cp == epkt)
772 			cp = lebuf;
773 	}
774 	return (top);
775 }
776 
777 /*
778  * Process an ioctl request.
779  */
780 int
781 leioctl(ifp, cmd, data)
782 	register struct ifnet *ifp;
783 	int cmd;
784 	caddr_t data;
785 {
786 	register struct ifaddr *ifa;
787 	struct le_softc *sc = &le_softc[ifp->if_unit];
788 	int s = splimp(), error = 0;
789 
790 	switch (cmd) {
791 
792 	case SIOCSIFADDR:
793 		ifa = (struct ifaddr *)data;
794 		ifp->if_flags |= IFF_UP;
795 		switch (ifa->ifa_addr->sa_family) {
796 #ifdef INET
797 		case AF_INET:
798 			leinit(ifp->if_unit);	/* before arpwhohas */
799 			((struct arpcom *)ifp)->ac_ipaddr =
800 				IA_SIN(ifa)->sin_addr;
801 			arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
802 			break;
803 #endif
804 #ifdef NS
805 		case AF_NS:
806 		    {
807 			register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
808 
809 			if (ns_nullhost(*ina))
810 				ina->x_host = *(union ns_host *)(sc->sc_addr);
811 			else {
812 				/*
813 				 * The manual says we can't change the address
814 				 * while the receiver is armed,
815 				 * so reset everything
816 				 */
817 				ifp->if_flags &= ~IFF_RUNNING;
818 				LERDWR(sc->sc_r0, LE_STOP, sc->sc_r1->ler1_rdp);
819 				bcopy((caddr_t)ina->x_host.c_host,
820 				    (caddr_t)sc->sc_addr, sizeof(sc->sc_addr));
821 			}
822 			leinit(ifp->if_unit); /* does le_setaddr() */
823 			break;
824 		    }
825 #endif
826 		default:
827 			leinit(ifp->if_unit);
828 			break;
829 		}
830 		break;
831 
832 	case SIOCSIFFLAGS:
833 		if ((ifp->if_flags & IFF_UP) == 0 &&
834 		    ifp->if_flags & IFF_RUNNING) {
835 			ifp->if_flags &= ~IFF_RUNNING;
836 			LERDWR(sc->sc_r0, LE_STOP, sc->sc_r1->ler1_rdp);
837 		} else if (ifp->if_flags & IFF_UP &&
838 		    (ifp->if_flags & IFF_RUNNING) == 0)
839 			leinit(ifp->if_unit);
840 		/*
841 		 * If the state of the promiscuous bit changes, the interface
842 		 * must be reset to effect the change.
843 		 */
844 		if (((ifp->if_flags ^ sc->sc_iflags) & IFF_PROMISC) &&
845 		    (ifp->if_flags & IFF_RUNNING)) {
846 			sc->sc_iflags = ifp->if_flags;
847 			lereset(sc);
848 			lestart(ifp);
849 		}
850 		break;
851 
852 	case SIOCADDMULTI:
853 		error = ether_addmulti((struct ifreq *)data, &sc->sc_ac);
854 		goto update_multicast;
855 
856 	case SIOCDELMULTI:
857 		error = ether_delmulti((struct ifreq *)data, &sc->sc_ac);
858 	update_multicast:
859 		if (error == ENETRESET) {
860 			/*
861 			 * Multicast list has changed; set the hardware
862 			 * filter accordingly.
863 			 */
864 			lereset(sc);
865 			error = 0;
866 		}
867 		break;
868 
869 	default:
870 		error = EINVAL;
871 	}
872 	splx(s);
873 	return (error);
874 }
875 
876 void
877 leerror(sc, stat)
878 	register struct le_softc *sc;
879 	int stat;
880 {
881 
882 	if (!ledebug)
883 		return;
884 
885 	/*
886 	 * Not all transceivers implement heartbeat
887 	 * so we only log CERR once.
888 	 */
889 	if ((stat & LE_CERR) && sc->sc_cerr)
890 		return;
891 	log(LOG_WARNING,
892 	    "le%d: error: stat=%b\n", sc->sc_if.if_unit, stat,
893 	    "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT");
894 }
895 
896 void
897 lererror(sc, msg)
898 	register struct le_softc *sc;
899 	char *msg;
900 {
901 	register struct lermd *rmd;
902 	int len;
903 
904 	if (!ledebug)
905 		return;
906 
907 	rmd = &sc->sc_r2->ler2_rmd[sc->sc_rmd];
908 	len = rmd->rmd3;
909 	log(LOG_WARNING,
910 	    "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
911 	    sc->sc_if.if_unit, msg,
912 	    len > 11 ? ether_sprintf(&sc->sc_r2->ler2_rbuf[sc->sc_rmd][6]) : "unknown",
913 	    sc->sc_rmd, len, rmd->rmd1,
914 	    "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP");
915 }
916 
917 void
918 lexerror(sc)
919 	register struct le_softc *sc;
920 {
921 	register struct letmd *tmd;
922 	register int len;
923 
924 	if (!ledebug)
925 		return;
926 
927 	tmd = sc->sc_r2->ler2_tmd;
928 	len = -tmd->tmd2;
929 	log(LOG_WARNING,
930 	    "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n",
931 	    sc->sc_if.if_unit,
932 	    len > 5 ? ether_sprintf(&sc->sc_r2->ler2_tbuf[0][0]) : "unknown",
933 	    0, len, tmd->tmd1,
934 	    "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP",
935 	    tmd->tmd3,
936 	    "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY");
937 }
938 #endif
939