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