Home | History | Annotate | Line # | Download | only in ic
am7990.c revision 1.5
      1 /*	$NetBSD: am7990.c,v 1.5 1995/12/10 08:55:07 mycroft Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
      5  * Copyright (c) 1992, 1993
      6  *	The Regents of the University of California.  All rights reserved.
      7  *
      8  * This code is derived from software contributed to Berkeley by
      9  * Ralph Campbell and Rick Macklem.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. All advertising materials mentioning features or use of this software
     20  *    must display the following acknowledgement:
     21  *	This product includes software developed by the University of
     22  *	California, Berkeley and its contributors.
     23  * 4. Neither the name of the University nor the names of its contributors
     24  *    may be used to endorse or promote products derived from this software
     25  *    without specific prior written permission.
     26  *
     27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     37  * SUCH DAMAGE.
     38  *
     39  *	@(#)if_le.c	8.2 (Berkeley) 11/16/93
     40  */
     41 
     42 #include <sys/ioctl.h>
     43 #include <sys/errno.h>
     44 
     45 #ifdef INET
     46 #include <netinet/in_systm.h>
     47 #include <netinet/in_var.h>
     48 #include <netinet/ip.h>
     49 #endif
     50 
     51 #ifdef NS
     52 #include <netns/ns.h>
     53 #include <netns/ns_if.h>
     54 #endif
     55 
     56 #if defined(CCITT) && defined(LLC)
     57 #include <sys/socketvar.h>
     58 #include <netccitt/x25.h>
     59 extern llc_ctlinput(), cons_rtrequest();
     60 #endif
     61 
     62 #if NBPFILTER > 0
     63 #include <net/bpf.h>
     64 #include <net/bpfdesc.h>
     65 #endif
     66 
     67 #ifdef LEDEBUG
     68 void recv_print __P((struct le_softc *, int));
     69 void xmit_print __P((struct le_softc *, int));
     70 #endif
     71 
     72 void
     73 leconfig(sc)
     74 	struct le_softc *sc;
     75 {
     76 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
     77 	int mem;
     78 
     79 	/* Make sure the chip is stopped. */
     80 	lestop(sc);
     81 
     82 	/* Initialize ifnet structure. */
     83 	ifp->if_unit = sc->sc_dev.dv_unit;
     84 	ifp->if_start = lestart;
     85 	ifp->if_ioctl = leioctl;
     86 	ifp->if_watchdog = lewatchdog;
     87 	ifp->if_flags =
     88 	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
     89 #ifdef LANCE_REVC_BUG
     90 	ifp->if_flags &= ~IFF_MULTICAST;
     91 #endif
     92 
     93 	/* Attach the interface. */
     94 	if_attach(ifp);
     95 	ether_ifattach(ifp);
     96 
     97 #if NBPFILTER > 0
     98 	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
     99 #endif
    100 
    101 	switch (sc->sc_memsize) {
    102 	case 8192:
    103 		sc->sc_nrbuf = 4;
    104 		sc->sc_ntbuf = 1;
    105 		break;
    106 	case 16384:
    107 		sc->sc_nrbuf = 8;
    108 		sc->sc_ntbuf = 2;
    109 		break;
    110 	case 32768:
    111 		sc->sc_nrbuf = 16;
    112 		sc->sc_ntbuf = 4;
    113 		break;
    114 	case 65536:
    115 		sc->sc_nrbuf = 32;
    116 		sc->sc_ntbuf = 8;
    117 		break;
    118 	default:
    119 		panic("leconfig: weird memory size");
    120 	}
    121 
    122 	printf(": address %s\n%s: %d receive buffers, %d transmit buffers\n",
    123 	    ether_sprintf(sc->sc_arpcom.ac_enaddr),
    124 	    sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf);
    125 
    126 	mem = 0;
    127 	sc->sc_initaddr = mem;
    128 	mem += sizeof(struct leinit);
    129 	sc->sc_rmdaddr = mem;
    130 	mem += sizeof(struct lermd) * sc->sc_nrbuf;
    131 	sc->sc_tmdaddr = mem;
    132 	mem += sizeof(struct letmd) * sc->sc_ntbuf;
    133 	sc->sc_rbufaddr = mem;
    134 	mem += LEBLEN * sc->sc_nrbuf;
    135 	sc->sc_tbufaddr = mem;
    136 	mem += LEBLEN * sc->sc_ntbuf;
    137 #ifdef notyet
    138 	if (mem > ...)
    139 		panic(...);
    140 #endif
    141 }
    142 
    143 void
    144 lereset(sc)
    145 	struct le_softc *sc;
    146 {
    147 	int s;
    148 
    149 	s = splimp();
    150 	leinit(sc);
    151 	splx(s);
    152 }
    153 
    154 void
    155 lewatchdog(unit)
    156 	short unit;
    157 {
    158 	struct le_softc *sc = LE_SOFTC(unit);
    159 
    160 	log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
    161 	++sc->sc_arpcom.ac_if.if_oerrors;
    162 
    163 	lereset(sc);
    164 }
    165 
    166 /*
    167  * Set up the initialization block and the descriptor rings.
    168  */
    169 void
    170 lememinit(sc)
    171 	register struct le_softc *sc;
    172 {
    173 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    174 	u_long a;
    175 	int bix;
    176 	struct leinit init;
    177 	struct lermd rmd;
    178 	struct letmd tmd;
    179 
    180 #if NBPFILTER > 0
    181 	if (ifp->if_flags & IFF_PROMISC)
    182 		init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM;
    183 	else
    184 #endif
    185 		init.init_mode = LE_MODE_NORMAL;
    186 	init.init_padr[0] =
    187 	    (sc->sc_arpcom.ac_enaddr[1] << 8) | sc->sc_arpcom.ac_enaddr[0];
    188 	init.init_padr[1] =
    189 	    (sc->sc_arpcom.ac_enaddr[3] << 8) | sc->sc_arpcom.ac_enaddr[2];
    190 	init.init_padr[2] =
    191 	    (sc->sc_arpcom.ac_enaddr[5] << 8) | sc->sc_arpcom.ac_enaddr[4];
    192 	lesetladrf(&sc->sc_arpcom, init.init_ladrf);
    193 
    194 	sc->sc_last_rd = 0;
    195 	sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
    196 
    197 	a = sc->sc_addr + LE_RMDADDR(sc, 0);
    198 	init.init_rdra = a;
    199 	init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13);
    200 
    201 	a = sc->sc_addr + LE_TMDADDR(sc, 0);
    202 	init.init_tdra = a;
    203 	init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13);
    204 
    205 	(*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
    206 
    207 	/*
    208 	 * Set up receive ring descriptors.
    209 	 */
    210 	for (bix = 0; bix < sc->sc_nrbuf; bix++) {
    211 		a = sc->sc_addr + LE_RBUFADDR(sc, bix);
    212 		rmd.rmd0 = a;
    213 		rmd.rmd1_hadr = a >> 16;
    214 		rmd.rmd1_bits = LE_R1_OWN;
    215 		rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
    216 		rmd.rmd3 = 0;
    217 		(*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
    218 		    sizeof(rmd));
    219 	}
    220 
    221 	/*
    222 	 * Set up transmit ring descriptors.
    223 	 */
    224 	for (bix = 0; bix < sc->sc_ntbuf; bix++) {
    225 		a = sc->sc_addr + LE_TBUFADDR(sc, bix);
    226 		tmd.tmd0 = a;
    227 		tmd.tmd1_hadr = a >> 16;
    228 		tmd.tmd1_bits = 0;
    229 		tmd.tmd2 = 0 | LE_XMD2_ONES;
    230 		tmd.tmd3 = 0;
    231 		(*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
    232 		    sizeof(tmd));
    233 	}
    234 }
    235 
    236 void
    237 lestop(sc)
    238 	struct le_softc *sc;
    239 {
    240 
    241 	lewrcsr(sc, LE_CSR0, LE_C0_STOP);
    242 }
    243 
    244 /*
    245  * Initialization of interface; set up initialization block
    246  * and transmit/receive descriptor rings.
    247  */
    248 void
    249 leinit(sc)
    250 	register struct le_softc *sc;
    251 {
    252 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    253 	register int timo;
    254 	u_long a;
    255 
    256 	lewrcsr(sc, LE_CSR0, LE_C0_STOP);
    257 	LE_DELAY(100);
    258 
    259 	/* Set the correct byte swapping mode, etc. */
    260 	lewrcsr(sc, LE_CSR3, sc->sc_conf3);
    261 
    262 	/* Set up LANCE init block. */
    263 	lememinit(sc);
    264 
    265 	/* Give LANCE the physical address of its init block. */
    266 	a = sc->sc_addr + LE_INITADDR(sc);
    267 	lewrcsr(sc, LE_CSR1, a);
    268 	lewrcsr(sc, LE_CSR2, a >> 16);
    269 
    270 	/* Try to initialize the LANCE. */
    271 	LE_DELAY(100);
    272 	lewrcsr(sc, LE_CSR0, LE_C0_INIT);
    273 
    274 	/* Wait for initialization to finish. */
    275 	for (timo = 100000; timo; timo--)
    276 		if (lerdcsr(sc, LE_CSR0) & LE_C0_IDON)
    277 			break;
    278 
    279 	if (lerdcsr(sc, LE_CSR0) & LE_C0_IDON) {
    280 		/* Start the LANCE. */
    281 		lewrcsr(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT | LE_C0_IDON);
    282 		ifp->if_flags |= IFF_RUNNING;
    283 		ifp->if_flags &= ~IFF_OACTIVE;
    284 		ifp->if_timer = 0;
    285 		lestart(ifp);
    286 	} else
    287 		printf("%s: card failed to initialize\n", sc->sc_dev.dv_xname);
    288 }
    289 
    290 /*
    291  * Routine to copy from mbuf chain to transmit buffer in
    292  * network buffer memory.
    293  */
    294 integrate int
    295 leput(sc, boff, m)
    296 	struct le_softc *sc;
    297 	int boff;
    298 	register struct mbuf *m;
    299 {
    300 	register struct mbuf *n;
    301 	register int len, tlen = 0;
    302 
    303 	for (; m; m = n) {
    304 		len = m->m_len;
    305 		if (len == 0) {
    306 			MFREE(m, n);
    307 			continue;
    308 		}
    309 		(*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, len);
    310 		boff += len;
    311 		tlen += len;
    312 		MFREE(m, n);
    313 	}
    314 	if (tlen < LEMINSIZE) {
    315 		(*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen);
    316 		tlen = LEMINSIZE;
    317 	}
    318 	return (tlen);
    319 }
    320 
    321 /*
    322  * Pull data off an interface.
    323  * Len is length of data, with local net header stripped.
    324  * We copy the data into mbufs.  When full cluster sized units are present
    325  * we copy into clusters.
    326  */
    327 integrate struct mbuf *
    328 leget(sc, boff, totlen)
    329 	struct le_softc *sc;
    330 	int boff, totlen;
    331 {
    332 	register struct mbuf *m;
    333 	struct mbuf *top, **mp;
    334 	int len, pad;
    335 
    336 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    337 	if (m == 0)
    338 		return (0);
    339 	m->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if;
    340 	m->m_pkthdr.len = totlen;
    341 	pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
    342 	m->m_data += pad;
    343 	len = MHLEN - pad;
    344 	top = 0;
    345 	mp = &top;
    346 
    347 	while (totlen > 0) {
    348 		if (top) {
    349 			MGET(m, M_DONTWAIT, MT_DATA);
    350 			if (m == 0) {
    351 				m_freem(top);
    352 				return 0;
    353 			}
    354 			len = MLEN;
    355 		}
    356 		if (top && totlen >= MINCLSIZE) {
    357 			MCLGET(m, M_DONTWAIT);
    358 			if (m->m_flags & M_EXT)
    359 				len = MCLBYTES;
    360 		}
    361 		m->m_len = len = min(totlen, len);
    362 		(*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, len);
    363 		boff += len;
    364 		totlen -= len;
    365 		*mp = m;
    366 		mp = &m->m_next;
    367 	}
    368 
    369 	return (top);
    370 }
    371 
    372 /*
    373  * Pass a packet to the higher levels.
    374  */
    375 integrate void
    376 leread(sc, boff, len)
    377 	register struct le_softc *sc;
    378 	int boff, len;
    379 {
    380 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    381 	struct mbuf *m;
    382 	struct ether_header *eh;
    383 
    384 	if (len <= sizeof(struct ether_header) ||
    385 	    len > ETHERMTU + sizeof(struct ether_header)) {
    386 		printf("%s: invalid packet size %d; dropping\n",
    387 		    sc->sc_dev.dv_xname, len);
    388 		ifp->if_ierrors++;
    389 		return;
    390 	}
    391 
    392 	/* Pull packet off interface. */
    393 	m = leget(sc, boff, len);
    394 	if (m == 0) {
    395 		ifp->if_ierrors++;
    396 		return;
    397 	}
    398 
    399 	ifp->if_ipackets++;
    400 
    401 	/* We assume that the header fit entirely in one mbuf. */
    402 	eh = mtod(m, struct ether_header *);
    403 
    404 #if NBPFILTER > 0
    405 	/*
    406 	 * Check if there's a BPF listener on this interface.
    407 	 * If so, hand off the raw packet to BPF.
    408 	 */
    409 	if (ifp->if_bpf) {
    410 		bpf_mtap(ifp->if_bpf, m);
    411 
    412 #ifndef LANCE_REVC_BUG
    413 		/*
    414 		 * Note that the interface cannot be in promiscuous mode if
    415 		 * there are no BPF listeners.  And if we are in promiscuous
    416 		 * mode, we have to check if this packet is really ours.
    417 		 */
    418 		if ((ifp->if_flags & IFF_PROMISC) != 0 &&
    419 		    (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
    420 		    bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
    421 			    sizeof(eh->ether_dhost)) != 0) {
    422 			m_freem(m);
    423 			return;
    424 		}
    425 #endif
    426 	}
    427 #endif
    428 
    429 #ifdef LANCE_REVC_BUG
    430 	if (bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
    431 		    sizeof(eh->ether_dhost)) != 0 &&
    432 	    bcmp(eh->ether_dhost, etherbroadcastaddr,
    433 		    sizeof(eh->ether_dhost)) != 0) {
    434 		m_freem(m);
    435 		return;
    436 	}
    437 #endif
    438 
    439 	/* Pass the packet up, with the ether header sort-of removed. */
    440 	m_adj(m, sizeof(struct ether_header));
    441 	ether_input(ifp, eh, m);
    442 }
    443 
    444 integrate void
    445 lerint(sc)
    446 	struct le_softc *sc;
    447 {
    448 	register int bix;
    449 	int rp;
    450 	struct lermd rmd;
    451 
    452 	bix = sc->sc_last_rd;
    453 
    454 	/* Process all buffers with valid data. */
    455 	for (;;) {
    456 		rp = LE_RMDADDR(sc, bix);
    457 		(*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
    458 
    459 		if (rmd.rmd1_bits & LE_R1_OWN)
    460 			break;
    461 
    462 		if (rmd.rmd1_bits & LE_R1_ERR) {
    463 			if (rmd.rmd1_bits & LE_R1_ENP) {
    464 				if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) {
    465 					if (rmd.rmd1_bits & LE_R1_FRAM)
    466 						printf("%s: framing error\n",
    467 						    sc->sc_dev.dv_xname);
    468 					if (rmd.rmd1_bits & LE_R1_CRC)
    469 						printf("%s: crc mismatch\n",
    470 						    sc->sc_dev.dv_xname);
    471 				}
    472 			} else {
    473 				if (rmd.rmd1_bits & LE_R1_OFLO)
    474 					printf("%s: overflow\n",
    475 					    sc->sc_dev.dv_xname);
    476 			}
    477 			if (rmd.rmd1_bits & LE_R1_BUFF)
    478 				printf("%s: receive buffer error\n",
    479 				    sc->sc_dev.dv_xname);
    480 		} else if (rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP) !=
    481 		    (LE_R1_STP | LE_R1_ENP)) {
    482 			printf("%s: dropping chained buffer\n",
    483 			    sc->sc_dev.dv_xname);
    484 		} else {
    485 #ifdef LEDEBUG
    486 			if (sc->sc_debug)
    487 				recv_print(sc, sc->sc_last_rd);
    488 #endif
    489 			leread(sc, LE_RBUFADDR(sc, bix), (int)rmd.rmd3 - 4);
    490 		}
    491 
    492 		rmd.rmd1_bits = LE_R1_OWN;
    493 		rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
    494 		rmd.rmd3 = 0;
    495 		(*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
    496 
    497 #ifdef LEDEBUG
    498 		if (sc->sc_debug)
    499 			printf("sc->sc_last_rd = %x, rmd = %x\n",
    500 			    sc->sc_last_rd, rmd);
    501 #endif
    502 
    503 		if (++bix == sc->sc_nrbuf)
    504 			bix = 0;
    505 	}
    506 
    507 	sc->sc_last_rd = bix;
    508 }
    509 
    510 integrate void
    511 letint(sc)
    512 	register struct le_softc *sc;
    513 {
    514 	register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    515 	register int bix;
    516 	struct letmd tmd;
    517 
    518 	bix = sc->sc_first_td;
    519 
    520 	for (;;) {
    521 		if (sc->sc_no_td <= 0)
    522 			break;
    523 
    524 #ifdef LEDEBUG
    525 		if (sc->sc_debug)
    526 			printf("trans tmd = %x\n", tmd);
    527 #endif
    528 
    529 		(*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
    530 		    sizeof(tmd));
    531 
    532 		if (tmd.tmd1_bits & LE_T1_OWN)
    533 			break;
    534 
    535 		ifp->if_flags &= ~IFF_OACTIVE;
    536 
    537 		if (tmd.tmd1_bits & LE_T1_ERR) {
    538 			if (tmd.tmd3 & LE_T3_BUFF)
    539 				printf("%s: transmit buffer error\n", sc->sc_dev.dv_xname);
    540 			else if (tmd.tmd3 & LE_T3_UFLO)
    541 				printf("%s: underflow\n", sc->sc_dev.dv_xname);
    542 			if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
    543 				lereset(sc);
    544 				return;
    545 			}
    546 			if (tmd.tmd3 & LE_T3_LCAR)
    547 				printf("%s: lost carrier\n", sc->sc_dev.dv_xname);
    548 			if (tmd.tmd3 & LE_T3_LCOL)
    549 				ifp->if_collisions++;
    550 			if (tmd.tmd3 & LE_T3_RTRY) {
    551 				printf("%s: excessive collisions, tdr %d\n",
    552 				    sc->sc_dev.dv_xname, tmd.tmd3 & LE_T3_TDR_MASK);
    553 				ifp->if_collisions += 16;
    554 			}
    555 			ifp->if_oerrors++;
    556 		} else {
    557 			if (tmd.tmd1_bits & LE_T1_ONE)
    558 				ifp->if_collisions++;
    559 			else if (tmd.tmd1_bits & LE_T1_MORE)
    560 				/* Real number is unknown. */
    561 				ifp->if_collisions += 2;
    562 			ifp->if_opackets++;
    563 		}
    564 
    565 		if (++bix == sc->sc_ntbuf)
    566 			bix = 0;
    567 
    568 		--sc->sc_no_td;
    569 	}
    570 
    571 	sc->sc_first_td = bix;
    572 
    573 	lestart(ifp);
    574 
    575 	if (sc->sc_no_td == 0)
    576 		ifp->if_timer = 0;
    577 }
    578 
    579 /*
    580  * Controller interrupt.
    581  */
    582 #ifdef LEINTR_UNIT
    583 int
    584 leintr(unit)
    585 	int unit;
    586 {
    587 	register struct le_softc *sc = LE_SOFTC(unit);
    588 #else
    589 int
    590 leintr(arg)
    591 	register void *arg;
    592 {
    593 	register struct le_softc *sc = arg;
    594 #endif
    595 	register u_int16_t isr;
    596 
    597 	isr = lerdcsr(sc, LE_CSR0);
    598 #ifdef LEDEBUG
    599 	if (sc->sc_debug)
    600 		printf("%s: leintr entering with isr=%04x\n",
    601 		    sc->sc_dev.dv_xname, isr);
    602 #endif
    603 	if ((isr & LE_C0_INTR) == 0)
    604 		return (0);
    605 
    606 	lewrcsr(sc, LE_CSR0,
    607 	    isr & (LE_C0_INEA | LE_C0_BABL | LE_C0_MISS | LE_C0_MERR |
    608 		   LE_C0_RINT | LE_C0_TINT | LE_C0_IDON));
    609 	if (isr & LE_C0_ERR) {
    610 		if (isr & LE_C0_BABL) {
    611 			printf("%s: babble\n", sc->sc_dev.dv_xname);
    612 			sc->sc_arpcom.ac_if.if_oerrors++;
    613 		}
    614 #if 0
    615 		if (isr & LE_C0_CERR) {
    616 			printf("%s: collision error\n", sc->sc_dev.dv_xname);
    617 			sc->sc_arpcom.ac_if.if_collisions++;
    618 		}
    619 #endif
    620 		if (isr & LE_C0_MISS)
    621 			sc->sc_arpcom.ac_if.if_ierrors++;
    622 		if (isr & LE_C0_MERR) {
    623 			printf("%s: memory error\n", sc->sc_dev.dv_xname);
    624 			lereset(sc);
    625 			return (1);
    626 		}
    627 	}
    628 
    629 	if ((isr & LE_C0_RXON) == 0) {
    630 		printf("%s: receiver disabled\n", sc->sc_dev.dv_xname);
    631 		sc->sc_arpcom.ac_if.if_ierrors++;
    632 		lereset(sc);
    633 		return (1);
    634 	}
    635 	if ((isr & LE_C0_TXON) == 0) {
    636 		printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname);
    637 		sc->sc_arpcom.ac_if.if_oerrors++;
    638 		lereset(sc);
    639 		return (1);
    640 	}
    641 
    642 	if (isr & LE_C0_RINT)
    643 		lerint(sc);
    644 	if (isr & LE_C0_TINT)
    645 		letint(sc);
    646 
    647 	return (1);
    648 }
    649 
    650 /*
    651  * Setup output on interface.
    652  * Get another datagram to send off of the interface queue, and map it to the
    653  * interface before starting the output.
    654  * Called only at splimp or interrupt level.
    655  */
    656 void
    657 lestart(ifp)
    658 	register struct ifnet *ifp;
    659 {
    660 	register struct le_softc *sc = LE_SOFTC(ifp->if_unit);
    661 	register int bix;
    662 	register struct mbuf *m;
    663 	struct letmd tmd;
    664 	int rp;
    665 	int len;
    666 
    667 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
    668 		return;
    669 
    670 	bix = sc->sc_last_td;
    671 
    672 	for (;;) {
    673 		rp = LE_TMDADDR(sc, bix);
    674 		(*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
    675 
    676 		if (tmd.tmd1_bits & LE_T1_OWN) {
    677 			ifp->if_flags |= IFF_OACTIVE;
    678 			printf("missing buffer, no_td = %d, last_td = %d\n",
    679 			    sc->sc_no_td, sc->sc_last_td);
    680 		}
    681 
    682 		IF_DEQUEUE(&ifp->if_snd, m);
    683 		if (m == 0)
    684 			break;
    685 
    686 #if NBPFILTER > 0
    687 		/*
    688 		 * If BPF is listening on this interface, let it see the packet
    689 		 * before we commit it to the wire.
    690 		 */
    691 		if (ifp->if_bpf)
    692 			bpf_mtap(ifp->if_bpf, m);
    693 #endif
    694 
    695 		/*
    696 		 * Copy the mbuf chain into the transmit buffer.
    697 		 */
    698 		len = leput(sc, LE_TBUFADDR(sc, bix), m);
    699 
    700 #ifdef LEDEBUG
    701 		if (len > ETHERMTU + sizeof(struct ether_header))
    702 			printf("packet length %d\n", len);
    703 #endif
    704 
    705 		ifp->if_timer = 5;
    706 
    707 		/*
    708 		 * Init transmit registers, and set transmit start flag.
    709 		 */
    710 		tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
    711 		tmd.tmd2 = -len | LE_XMD2_ONES;
    712 		tmd.tmd3 = 0;
    713 
    714 		(*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
    715 
    716 #ifdef LEDEBUG
    717 		if (sc->sc_debug)
    718 			xmit_print(sc, sc->sc_last_td);
    719 #endif
    720 
    721 		lewrcsr(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
    722 
    723 		if (++bix == sc->sc_ntbuf)
    724 			bix = 0;
    725 
    726 		if (++sc->sc_no_td == sc->sc_ntbuf) {
    727 			ifp->if_flags |= IFF_OACTIVE;
    728 			break;
    729 		}
    730 
    731 	}
    732 
    733 	sc->sc_last_td = bix;
    734 }
    735 
    736 /*
    737  * Process an ioctl request.
    738  */
    739 int
    740 leioctl(ifp, cmd, data)
    741 	register struct ifnet *ifp;
    742 	u_long cmd;
    743 	caddr_t data;
    744 {
    745 	struct le_softc *sc = LE_SOFTC(ifp->if_unit);
    746 	struct ifaddr *ifa = (struct ifaddr *)data;
    747 	struct ifreq *ifr = (struct ifreq *)data;
    748 	int s, error = 0;
    749 
    750 	s = splimp();
    751 
    752 	switch (cmd) {
    753 
    754 	case SIOCSIFADDR:
    755 		ifp->if_flags |= IFF_UP;
    756 
    757 		switch (ifa->ifa_addr->sa_family) {
    758 #ifdef INET
    759 		case AF_INET:
    760 			leinit(sc);
    761 			arp_ifinit(&sc->sc_arpcom, ifa);
    762 			break;
    763 #endif
    764 #ifdef NS
    765 		case AF_NS:
    766 		    {
    767 			register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
    768 
    769 			if (ns_nullhost(*ina))
    770 				ina->x_host =
    771 				    *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
    772 			else
    773 				bcopy(ina->x_host.c_host,
    774 				    sc->sc_arpcom.ac_enaddr,
    775 				    sizeof(sc->sc_arpcom.ac_enaddr));
    776 			/* Set new address. */
    777 			leinit(sc);
    778 			break;
    779 		    }
    780 #endif
    781 		default:
    782 			leinit(sc);
    783 			break;
    784 		}
    785 		break;
    786 
    787 #if defined(CCITT) && defined(LLC)
    788 	case SIOCSIFCONF_X25:
    789 		ifp->if_flags |= IFF_UP;
    790 		ifa->ifa_rtrequest = (void (*)())cons_rtrequest; /* XXX */
    791 		error = x25_llcglue(PRC_IFUP, ifa->ifa_addr);
    792 		if (error == 0)
    793 			leinit(sc);
    794 		break;
    795 #endif /* CCITT && LLC */
    796 
    797 	case SIOCSIFFLAGS:
    798 		if ((ifp->if_flags & IFF_UP) == 0 &&
    799 		    (ifp->if_flags & IFF_RUNNING) != 0) {
    800 			/*
    801 			 * If interface is marked down and it is running, then
    802 			 * stop it.
    803 			 */
    804 			lestop(sc);
    805 			ifp->if_flags &= ~IFF_RUNNING;
    806 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
    807 		    	   (ifp->if_flags & IFF_RUNNING) == 0) {
    808 			/*
    809 			 * If interface is marked up and it is stopped, then
    810 			 * start it.
    811 			 */
    812 			leinit(sc);
    813 		} else {
    814 			/*
    815 			 * Reset the interface to pick up changes in any other
    816 			 * flags that affect hardware registers.
    817 			 */
    818 			/*lestop(sc);*/
    819 			leinit(sc);
    820 		}
    821 #ifdef LEDEBUG
    822 		if (ifp->if_flags & IFF_DEBUG)
    823 			sc->sc_debug = 1;
    824 		else
    825 			sc->sc_debug = 0;
    826 #endif
    827 		break;
    828 
    829 	case SIOCADDMULTI:
    830 	case SIOCDELMULTI:
    831 		error = (cmd == SIOCADDMULTI) ?
    832 		    ether_addmulti(ifr, &sc->sc_arpcom) :
    833 		    ether_delmulti(ifr, &sc->sc_arpcom);
    834 
    835 		if (error == ENETRESET) {
    836 			/*
    837 			 * Multicast list has changed; set the hardware filter
    838 			 * accordingly.
    839 			 */
    840 			lereset(sc);
    841 			error = 0;
    842 		}
    843 		break;
    844 
    845 	default:
    846 		error = EINVAL;
    847 		break;
    848 	}
    849 
    850 	splx(s);
    851 	return (error);
    852 }
    853 
    854 #ifdef LEDEBUG
    855 void
    856 recv_print(sc, no)
    857 	struct le_softc *sc;
    858 	int no;
    859 {
    860 	struct lermd rmd;
    861 	u_int16_t len;
    862 	struct ether_header eh;
    863 
    864 	(*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
    865 	len = rmd.rmd3;
    866 	printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
    867 	    len);
    868 	printf("%s: status %04x\n", sc->sc_dev.dv_xname, lerdcsr(sc, LE_CSR0));
    869 	printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
    870 	    sc->sc_dev.dv_xname,
    871 	    rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
    872 	if (len >= sizeof(eh)) {
    873 		(*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
    874 		printf("%s: dst %s", ether_sprintf(eh.ether_dhost));
    875 		printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
    876 		    ntohs(eh.ether_type));
    877 	}
    878 }
    879 
    880 void
    881 xmit_print(sc, no)
    882 	struct le_softc *sc;
    883 	int no;
    884 {
    885 	struct letmd tmd;
    886 	u_int16_t len;
    887 	struct ether_header eh;
    888 
    889 	(*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
    890 	len = -tmd.tmd2;
    891 	printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
    892 	    len);
    893 	printf("%s: status %04x\n", sc->sc_dev.dv_xname, lerdcsr(sc, LE_CSR0));
    894 	printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
    895 	    sc->sc_dev.dv_xname,
    896 	    tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
    897 	if (len >= sizeof(eh)) {
    898 		(*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
    899 		printf("%s: dst %s", ether_sprintf(eh.ether_dhost));
    900 		printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
    901 		    ntohs(eh.ether_type));
    902 	}
    903 }
    904 #endif /* LEDEBUG */
    905 
    906 /*
    907  * Set up the logical address filter.
    908  */
    909 void
    910 lesetladrf(ac, af)
    911 	struct arpcom *ac;
    912 	u_int16_t *af;
    913 {
    914 	struct ifnet *ifp = &ac->ac_if;
    915 	struct ether_multi *enm;
    916 	register u_char *cp, c;
    917 	register u_int32_t crc;
    918 	register int i, len;
    919 	struct ether_multistep step;
    920 
    921 	/*
    922 	 * Set up multicast address filter by passing all multicast addresses
    923 	 * through a crc generator, and then using the high order 6 bits as an
    924 	 * index into the 64 bit logical address filter.  The high order bit
    925 	 * selects the word, while the rest of the bits select the bit within
    926 	 * the word.
    927 	 */
    928 
    929 	if (ifp->if_flags & IFF_PROMISC)
    930 		goto allmulti;
    931 
    932 	af[0] = af[1] = af[2] = af[3] = 0x0000;
    933 	ETHER_FIRST_MULTI(step, ac, enm);
    934 	while (enm != NULL) {
    935 		if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
    936 		    sizeof(enm->enm_addrlo)) != 0) {
    937 			/*
    938 			 * We must listen to a range of multicast addresses.
    939 			 * For now, just accept all multicasts, rather than
    940 			 * trying to set only those filter bits needed to match
    941 			 * the range.  (At this time, the only use of address
    942 			 * ranges is for IP multicast routing, for which the
    943 			 * range is big enough to require all bits set.)
    944 			 */
    945 			goto allmulti;
    946 		}
    947 
    948 		cp = enm->enm_addrlo;
    949 		crc = 0xffffffff;
    950 		for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
    951 			c = *cp++;
    952 			for (i = 8; --i >= 0;) {
    953 				if ((crc & 0x01) ^ (c & 0x01)) {
    954 					crc >>= 1;
    955 					crc ^= 0xedb88320;
    956 				} else
    957 					crc >>= 1;
    958 				c >>= 1;
    959 			}
    960 		}
    961 		/* Just want the 6 most significant bits. */
    962 		crc >>= 26;
    963 
    964 		/* Set the corresponding bit in the filter. */
    965 		af[crc >> 4] |= 1 << (crc & 0xf);
    966 
    967 		ETHER_NEXT_MULTI(step, enm);
    968 	}
    969 	ifp->if_flags &= ~IFF_ALLMULTI;
    970 	return;
    971 
    972 allmulti:
    973 	ifp->if_flags |= IFF_ALLMULTI;
    974 	af[0] = af[1] = af[2] = af[3] = 0xffff;
    975 }
    976 
    977 
    978 /*
    979  * Routines for accessing the transmit and receive buffers.
    980  * The various CPU and adapter configurations supported by this
    981  * driver require three different access methods for buffers
    982  * and descriptors:
    983  *	(1) contig (contiguous data; no padding),
    984  *	(2) gap2 (two bytes of data followed by two bytes of padding),
    985  *	(3) gap16 (16 bytes of data followed by 16 bytes of padding).
    986  */
    987 
    988 #ifdef LE_NEED_BUF_CONTIG
    989 /*
    990  * contig: contiguous data with no padding.
    991  *
    992  * Buffers may have any alignment.
    993  */
    994 
    995 integrate void
    996 copytobuf_contig(sc, from, boff, len)
    997 	struct le_softc *sc;
    998 	void *from;
    999 	int boff, len;
   1000 {
   1001 	volatile caddr_t buf = sc->sc_mem;
   1002 
   1003 	/*
   1004 	 * Just call bcopy() to do the work.
   1005 	 */
   1006 	bcopy(from, buf + boff, len);
   1007 }
   1008 
   1009 integrate void
   1010 copyfrombuf_contig(sc, to, boff, len)
   1011 	struct le_softc *sc;
   1012 	void *to;
   1013 	int boff, len;
   1014 {
   1015 	volatile caddr_t buf = sc->sc_mem;
   1016 
   1017 	/*
   1018 	 * Just call bcopy() to do the work.
   1019 	 */
   1020 	bcopy(buf + boff, to, len);
   1021 }
   1022 
   1023 integrate void
   1024 zerobuf_contig(sc, boff, len)
   1025 	struct le_softc *sc;
   1026 	int boff, len;
   1027 {
   1028 	volatile caddr_t buf = sc->sc_mem;
   1029 
   1030 	/*
   1031 	 * Just let bzero() do the work
   1032 	 */
   1033 	bzero(buf + boff, len);
   1034 }
   1035 #endif /* LE_NEED_BUF_CONTIG */
   1036 
   1037 #ifdef LE_NEED_BUF_GAP2
   1038 /*
   1039  * gap2: two bytes of data followed by two bytes of pad.
   1040  *
   1041  * Buffers must be 4-byte aligned.  The code doesn't worry about
   1042  * doing an extra byte.
   1043  */
   1044 
   1045 integrate void
   1046 copytobuf_gap2(sc, fromv, boff, len)
   1047 	struct le_softc *sc;
   1048 	void *fromv;
   1049 	int boff;
   1050 	register int len;
   1051 {
   1052 	volatile caddr_t buf = sc->sc_mem;
   1053 	register caddr_t from = fromv;
   1054 	register volatile u_int16_t *bptr;
   1055 	register int xfer;
   1056 
   1057 	if (boff & 0x1) {
   1058 		/* handle unaligned first byte */
   1059 		bptr = ((volatile u_int16_t *)buf) + (boff - 1);
   1060 		*bptr = (*from++ << 8) | (*bptr & 0xff);
   1061 		bptr += 2;
   1062 		len--;
   1063 	} else
   1064 		bptr = ((volatile u_int16_t *)buf) + boff;
   1065 	while (len > 1) {
   1066 		*bptr = (from[1] << 8) | (from[0] & 0xff);
   1067 		bptr += 2;
   1068 		from += 2;
   1069 		len -= 2;
   1070 	}
   1071 	if (len == 1)
   1072 		*bptr = (u_int16_t)*from;
   1073 }
   1074 
   1075 integrate void
   1076 copyfrombuf_gap2(sc, tov, boff, len)
   1077 	struct le_softc *sc;
   1078 	void *tov;
   1079 	int boff, len;
   1080 {
   1081 	volatile caddr_t buf = sc->sc_mem;
   1082 	register caddr_t to = tov;
   1083 	register volatile u_int16_t *bptr;
   1084 	register u_int16_t tmp;
   1085 	register int xfer;
   1086 
   1087 	if (boff & 0x1) {
   1088 		/* handle unaligned first byte */
   1089 		bptr = ((volatile u_int16_t *)buf) + (boff - 1);
   1090 		*to++ = (*bptr >> 8) & 0xff;
   1091 		bptr += 2;
   1092 		len--;
   1093 	} else
   1094 		bptr = ((volatile u_int16_t *)buf) + boff;
   1095 	while (len > 1) {
   1096 		tmp = *bptr;
   1097 		*to++ = tmp & 0xff;
   1098 		*to++ = (tmp >> 8) & 0xff;
   1099 		bptr += 2;
   1100 		len -= 2;
   1101 	}
   1102 	if (len == 1)
   1103 		*to = *bptr & 0xff;
   1104 }
   1105 
   1106 integrate void
   1107 zerobuf_gap2(sc, boff, len)
   1108 	struct le_softc *sc;
   1109 	int boff, len;
   1110 {
   1111 	volatile caddr_t buf = sc->sc_mem;
   1112 	register volatile u_int16_t *bptr;
   1113 
   1114 	if ((unsigned)boff & 0x1) {
   1115 		bptr = ((volatile u_int16_t *)buf) + (boff - 1);
   1116 		*bptr &= 0xff;
   1117 		bptr += 2;
   1118 		len--;
   1119 	} else
   1120 		bptr = ((volatile u_int16_t *)buf) + boff;
   1121 	while (len > 0) {
   1122 		*bptr = 0;
   1123 		bptr += 2;
   1124 		len -= 2;
   1125 	}
   1126 }
   1127 #endif /* LE_NEED_BUF_GAP2 */
   1128 
   1129 #ifdef LE_NEED_BUF_GAP16
   1130 /*
   1131  * gap16: 16 bytes of data followed by 16 bytes of pad.
   1132  *
   1133  * Buffers must be 32-byte aligned.
   1134  */
   1135 
   1136 integrate void
   1137 copytobuf_gap16(sc, fromv, boff, len)
   1138 	struct le_softc *sc;
   1139 	void *fromv;
   1140 	int boff;
   1141 	register int len;
   1142 {
   1143 	volatile caddr_t buf = sc->sc_mem;
   1144 	register caddr_t from = fromv;
   1145 	register caddr_t bptr;
   1146 	register int xfer;
   1147 
   1148 	bptr = buf + ((boff << 1) & ~0x1f);
   1149 	boff &= 0xf;
   1150 	xfer = min(len, 16 - boff);
   1151 	while (len > 0) {
   1152 		bcopy(from, bptr + boff, xfer);
   1153 		from += xfer;
   1154 		bptr += 32;
   1155 		boff = 0;
   1156 		len -= xfer;
   1157 		xfer = min(len, 16);
   1158 	}
   1159 }
   1160 
   1161 integrate void
   1162 copyfrombuf_gap16(sc, tov, boff, len)
   1163 	struct le_softc *sc;
   1164 	void *tov;
   1165 	int boff, len;
   1166 {
   1167 	volatile caddr_t buf = sc->sc_mem;
   1168 	register caddr_t to = tov;
   1169 	register caddr_t bptr;
   1170 	register int xfer;
   1171 
   1172 	bptr = buf + ((boff << 1) & ~0x1f);
   1173 	boff &= 0xf;
   1174 	xfer = min(len, 16 - boff);
   1175 	while (len > 0) {
   1176 		bcopy(bptr + boff, to, xfer);
   1177 		to += xfer;
   1178 		bptr += 32;
   1179 		boff = 0;
   1180 		len -= xfer;
   1181 		xfer = min(len, 16);
   1182 	}
   1183 }
   1184 
   1185 integrate void
   1186 zerobuf_gap16(sc, boff, len)
   1187 	struct le_softc *sc;
   1188 	int boff, len;
   1189 {
   1190 	volatile caddr_t buf = sc->sc_mem;
   1191 	register caddr_t bptr;
   1192 	register int xfer;
   1193 
   1194 	bptr = buf + ((boff << 1) & ~0x1f);
   1195 	boff &= 0xf;
   1196 	xfer = min(len, 16 - boff);
   1197 	while (len > 0) {
   1198 		bzero(bptr + boff, xfer);
   1199 		bptr += 32;
   1200 		boff = 0;
   1201 		len -= xfer;
   1202 		xfer = min(len, 16);
   1203 	}
   1204 }
   1205 #endif /* LE_NEED_BUF_GAP16 */
   1206