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