Home | History | Annotate | Line # | Download | only in ic
am7990.c revision 1.50
      1  1.50  drochner /*	$NetBSD: am7990.c,v 1.50 1998/07/07 14:13:51 drochner Exp $	*/
      2  1.36   thorpej 
      3  1.36   thorpej /*-
      4  1.36   thorpej  * Copyright (c) 1997 The NetBSD Foundation, Inc.
      5  1.36   thorpej  * All rights reserved.
      6  1.36   thorpej  *
      7  1.36   thorpej  * This code is derived from software contributed to The NetBSD Foundation
      8  1.36   thorpej  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  1.36   thorpej  * NASA Ames Research Center.
     10  1.36   thorpej  *
     11  1.36   thorpej  * Redistribution and use in source and binary forms, with or without
     12  1.36   thorpej  * modification, are permitted provided that the following conditions
     13  1.36   thorpej  * are met:
     14  1.36   thorpej  * 1. Redistributions of source code must retain the above copyright
     15  1.36   thorpej  *    notice, this list of conditions and the following disclaimer.
     16  1.36   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     17  1.36   thorpej  *    notice, this list of conditions and the following disclaimer in the
     18  1.36   thorpej  *    documentation and/or other materials provided with the distribution.
     19  1.36   thorpej  * 3. All advertising materials mentioning features or use of this software
     20  1.36   thorpej  *    must display the following acknowledgement:
     21  1.36   thorpej  *	This product includes software developed by the NetBSD
     22  1.36   thorpej  *	Foundation, Inc. and its contributors.
     23  1.36   thorpej  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24  1.36   thorpej  *    contributors may be used to endorse or promote products derived
     25  1.36   thorpej  *    from this software without specific prior written permission.
     26  1.36   thorpej  *
     27  1.36   thorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28  1.36   thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29  1.36   thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30  1.36   thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31  1.36   thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32  1.36   thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33  1.36   thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34  1.36   thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35  1.36   thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36  1.36   thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37  1.36   thorpej  * POSSIBILITY OF SUCH DAMAGE.
     38  1.36   thorpej  */
     39   1.1       cgd 
     40   1.1       cgd /*-
     41   1.1       cgd  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
     42   1.1       cgd  * Copyright (c) 1992, 1993
     43   1.1       cgd  *	The Regents of the University of California.  All rights reserved.
     44   1.1       cgd  *
     45   1.1       cgd  * This code is derived from software contributed to Berkeley by
     46   1.1       cgd  * Ralph Campbell and Rick Macklem.
     47   1.1       cgd  *
     48   1.1       cgd  * Redistribution and use in source and binary forms, with or without
     49   1.1       cgd  * modification, are permitted provided that the following conditions
     50   1.1       cgd  * are met:
     51   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     52   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     53   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     54   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     55   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     56   1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     57   1.1       cgd  *    must display the following acknowledgement:
     58   1.1       cgd  *	This product includes software developed by the University of
     59   1.1       cgd  *	California, Berkeley and its contributors.
     60   1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     61   1.1       cgd  *    may be used to endorse or promote products derived from this software
     62   1.1       cgd  *    without specific prior written permission.
     63   1.1       cgd  *
     64   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     65   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     66   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     67   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     68   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     69   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     70   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     71   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     72   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     73   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     74   1.1       cgd  * SUCH DAMAGE.
     75   1.1       cgd  *
     76   1.1       cgd  *	@(#)if_le.c	8.2 (Berkeley) 11/16/93
     77   1.1       cgd  */
     78   1.1       cgd 
     79  1.45  jonathan #include "opt_ddb.h"
     80  1.46  jonathan #include "opt_inet.h"
     81  1.47  jonathan #include "opt_ccitt.h"
     82  1.48  jonathan #include "opt_llc.h"
     83  1.49  jonathan #include "opt_ns.h"
     84  1.19   thorpej #include "bpfilter.h"
     85  1.38  explorer #include "rnd.h"
     86  1.19   thorpej 
     87  1.19   thorpej #include <sys/param.h>
     88  1.19   thorpej #include <sys/systm.h>
     89  1.19   thorpej #include <sys/mbuf.h>
     90  1.19   thorpej #include <sys/syslog.h>
     91  1.19   thorpej #include <sys/socket.h>
     92  1.19   thorpej #include <sys/device.h>
     93  1.19   thorpej #include <sys/malloc.h>
     94   1.1       cgd #include <sys/ioctl.h>
     95   1.1       cgd #include <sys/errno.h>
     96  1.38  explorer #if NRND > 0
     97  1.37  explorer #include <sys/rnd.h>
     98  1.38  explorer #endif
     99   1.1       cgd 
    100  1.19   thorpej #include <net/if.h>
    101  1.26        is #include <net/if_dl.h>
    102  1.26        is #include <net/if_ether.h>
    103  1.27   thorpej #include <net/if_media.h>
    104  1.19   thorpej 
    105   1.1       cgd #ifdef INET
    106  1.19   thorpej #include <netinet/in.h>
    107  1.26        is #include <netinet/if_inarp.h>
    108   1.1       cgd #include <netinet/in_systm.h>
    109   1.1       cgd #include <netinet/in_var.h>
    110   1.1       cgd #include <netinet/ip.h>
    111   1.1       cgd #endif
    112   1.1       cgd 
    113   1.1       cgd #ifdef NS
    114   1.1       cgd #include <netns/ns.h>
    115   1.1       cgd #include <netns/ns_if.h>
    116   1.1       cgd #endif
    117   1.1       cgd 
    118   1.1       cgd #if defined(CCITT) && defined(LLC)
    119   1.1       cgd #include <sys/socketvar.h>
    120   1.1       cgd #include <netccitt/x25.h>
    121  1.11  christos #include <netccitt/pk.h>
    122  1.11  christos #include <netccitt/pk_var.h>
    123  1.11  christos #include <netccitt/pk_extern.h>
    124   1.1       cgd #endif
    125   1.1       cgd 
    126   1.1       cgd #if NBPFILTER > 0
    127   1.1       cgd #include <net/bpf.h>
    128   1.1       cgd #include <net/bpfdesc.h>
    129   1.1       cgd #endif
    130   1.1       cgd 
    131  1.19   thorpej #include <dev/ic/am7990reg.h>
    132  1.19   thorpej #include <dev/ic/am7990var.h>
    133  1.19   thorpej 
    134   1.1       cgd #ifdef LEDEBUG
    135  1.19   thorpej void am7990_recv_print __P((struct am7990_softc *, int));
    136  1.19   thorpej void am7990_xmit_print __P((struct am7990_softc *, int));
    137   1.1       cgd #endif
    138   1.1       cgd 
    139  1.19   thorpej integrate void am7990_rint __P((struct am7990_softc *));
    140  1.19   thorpej integrate void am7990_tint __P((struct am7990_softc *));
    141  1.19   thorpej 
    142  1.19   thorpej integrate int am7990_put __P((struct am7990_softc *, int, struct mbuf *));
    143  1.19   thorpej integrate struct mbuf *am7990_get __P((struct am7990_softc *, int, int));
    144  1.19   thorpej integrate void am7990_read __P((struct am7990_softc *, int, int));
    145  1.19   thorpej 
    146  1.19   thorpej hide void am7990_shutdown __P((void *));
    147  1.19   thorpej 
    148  1.27   thorpej int am7990_mediachange __P((struct ifnet *));
    149  1.27   thorpej void am7990_mediastatus __P((struct ifnet *, struct ifmediareq *));
    150  1.27   thorpej 
    151  1.26        is #define	ifp	(&sc->sc_ethercom.ec_if)
    152   1.7   mycroft 
    153  1.39       gwr static inline u_int16_t ether_cmp __P((void *, void *));
    154  1.19   thorpej 
    155  1.19   thorpej /*
    156  1.19   thorpej  * Compare two Ether/802 addresses for equality, inlined and
    157  1.39       gwr  * unrolled for speed.  Use this like bcmp().
    158  1.39       gwr  *
    159  1.39       gwr  * XXX: Add <machine/inlines.h> for stuff like this?
    160  1.39       gwr  * XXX: or maybe add it to libkern.h instead?
    161  1.39       gwr  *
    162  1.39       gwr  * "I'd love to have an inline assembler version of this."
    163  1.39       gwr  * XXX: Who wanted that? mycroft?  I wrote one, but this
    164  1.39       gwr  * version in C is as good as hand-coded assembly. -gwr
    165  1.39       gwr  *
    166  1.39       gwr  * Please do NOT tweak this without looking at the actual
    167  1.39       gwr  * assembly code generated before and after your tweaks!
    168  1.19   thorpej  */
    169  1.39       gwr static inline u_int16_t
    170  1.39       gwr ether_cmp(one, two)
    171  1.39       gwr 	void *one, *two;
    172  1.19   thorpej {
    173  1.39       gwr 	register u_int16_t *a = (u_short *) one;
    174  1.39       gwr 	register u_int16_t *b = (u_short *) two;
    175  1.39       gwr 	register u_int16_t diff;
    176  1.19   thorpej 
    177  1.39       gwr #ifdef	m68k
    178  1.39       gwr 	/*
    179  1.39       gwr 	 * The post-increment-pointer form produces the best
    180  1.39       gwr 	 * machine code for m68k.  This was carefully tuned
    181  1.39       gwr 	 * so it compiles to just 8 short (2-byte) op-codes!
    182  1.39       gwr 	 */
    183  1.39       gwr 	diff  = *a++ - *b++;
    184  1.39       gwr 	diff |= *a++ - *b++;
    185  1.39       gwr 	diff |= *a++ - *b++;
    186  1.39       gwr #else
    187  1.39       gwr 	/*
    188  1.39       gwr 	 * Most modern CPUs do better with a single expresion.
    189  1.39       gwr 	 * Note that short-cut evaluation is NOT helpful here,
    190  1.39       gwr 	 * because it just makes the code longer, not faster!
    191  1.39       gwr 	 */
    192  1.39       gwr 	diff = (a[0] - b[0]) | (a[1] - b[1]) | (a[2] - b[2]);
    193  1.39       gwr #endif
    194  1.39       gwr 
    195  1.39       gwr 	return (diff);
    196  1.19   thorpej }
    197  1.19   thorpej 
    198  1.19   thorpej #define ETHER_CMP	ether_cmp
    199  1.13       gwr 
    200  1.39       gwr #ifdef LANCE_REVC_BUG
    201  1.39       gwr /* Make sure this is short-aligned, for ether_cmp(). */
    202  1.39       gwr static u_int16_t bcast_enaddr[3] = { ~0, ~0, ~0 };
    203  1.39       gwr #endif
    204  1.19   thorpej 
    205   1.1       cgd void
    206  1.19   thorpej am7990_config(sc)
    207  1.19   thorpej 	struct am7990_softc *sc;
    208   1.1       cgd {
    209  1.25       leo 	int mem, i;
    210   1.1       cgd 
    211   1.1       cgd 	/* Make sure the chip is stopped. */
    212  1.19   thorpej 	am7990_stop(sc);
    213   1.1       cgd 
    214   1.1       cgd 	/* Initialize ifnet structure. */
    215  1.19   thorpej 	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
    216  1.19   thorpej 	ifp->if_softc = sc;
    217  1.19   thorpej 	ifp->if_start = am7990_start;
    218  1.19   thorpej 	ifp->if_ioctl = am7990_ioctl;
    219  1.19   thorpej 	ifp->if_watchdog = am7990_watchdog;
    220   1.1       cgd 	ifp->if_flags =
    221   1.1       cgd 	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
    222   1.5   mycroft #ifdef LANCE_REVC_BUG
    223   1.5   mycroft 	ifp->if_flags &= ~IFF_MULTICAST;
    224   1.5   mycroft #endif
    225   1.1       cgd 
    226  1.27   thorpej 	/* Initialize ifmedia structures. */
    227  1.27   thorpej 	ifmedia_init(&sc->sc_media, 0, am7990_mediachange, am7990_mediastatus);
    228  1.27   thorpej 	if (sc->sc_supmedia != NULL) {
    229  1.27   thorpej 		for (i = 0; i < sc->sc_nsupmedia; i++)
    230  1.27   thorpej 			ifmedia_add(&sc->sc_media, sc->sc_supmedia[i],
    231  1.27   thorpej 			   0, NULL);
    232  1.27   thorpej 		ifmedia_set(&sc->sc_media, sc->sc_defaultmedia);
    233  1.27   thorpej 	} else {
    234  1.27   thorpej 		ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
    235  1.27   thorpej 		ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
    236  1.27   thorpej 	}
    237  1.27   thorpej 
    238   1.1       cgd 	/* Attach the interface. */
    239   1.1       cgd 	if_attach(ifp);
    240  1.26        is 	ether_ifattach(ifp, sc->sc_enaddr);
    241   1.1       cgd 
    242   1.1       cgd #if NBPFILTER > 0
    243   1.1       cgd 	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
    244   1.1       cgd #endif
    245   1.1       cgd 
    246   1.1       cgd 	switch (sc->sc_memsize) {
    247   1.1       cgd 	case 8192:
    248   1.1       cgd 		sc->sc_nrbuf = 4;
    249   1.1       cgd 		sc->sc_ntbuf = 1;
    250   1.1       cgd 		break;
    251   1.1       cgd 	case 16384:
    252   1.1       cgd 		sc->sc_nrbuf = 8;
    253   1.1       cgd 		sc->sc_ntbuf = 2;
    254   1.1       cgd 		break;
    255   1.1       cgd 	case 32768:
    256   1.1       cgd 		sc->sc_nrbuf = 16;
    257   1.1       cgd 		sc->sc_ntbuf = 4;
    258   1.1       cgd 		break;
    259   1.1       cgd 	case 65536:
    260   1.1       cgd 		sc->sc_nrbuf = 32;
    261   1.1       cgd 		sc->sc_ntbuf = 8;
    262  1.24        pk 		break;
    263  1.24        pk 	case 131072:
    264  1.24        pk 		sc->sc_nrbuf = 64;
    265  1.24        pk 		sc->sc_ntbuf = 16;
    266   1.1       cgd 		break;
    267   1.1       cgd 	default:
    268  1.19   thorpej 		panic("am7990_config: weird memory size");
    269   1.1       cgd 	}
    270   1.1       cgd 
    271  1.26        is 	printf(": address %s\n", ether_sprintf(sc->sc_enaddr));
    272  1.22  christos 	printf("%s: %d receive buffers, %d transmit buffers\n",
    273   1.5   mycroft 	    sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf);
    274   1.1       cgd 
    275  1.19   thorpej 	sc->sc_sh = shutdownhook_establish(am7990_shutdown, sc);
    276  1.19   thorpej 	if (sc->sc_sh == NULL)
    277  1.19   thorpej 		panic("am7990_config: can't establish shutdownhook");
    278  1.25       leo 	sc->sc_rbufaddr = malloc(sc->sc_nrbuf * sizeof(int), M_DEVBUF,
    279  1.25       leo 					M_WAITOK);
    280  1.25       leo 	sc->sc_tbufaddr = malloc(sc->sc_ntbuf * sizeof(int), M_DEVBUF,
    281  1.25       leo 					M_WAITOK);
    282  1.19   thorpej 
    283   1.1       cgd 	mem = 0;
    284   1.1       cgd 	sc->sc_initaddr = mem;
    285   1.1       cgd 	mem += sizeof(struct leinit);
    286   1.1       cgd 	sc->sc_rmdaddr = mem;
    287   1.1       cgd 	mem += sizeof(struct lermd) * sc->sc_nrbuf;
    288   1.1       cgd 	sc->sc_tmdaddr = mem;
    289   1.1       cgd 	mem += sizeof(struct letmd) * sc->sc_ntbuf;
    290  1.25       leo 	for (i = 0; i < sc->sc_nrbuf; i++, mem += LEBLEN)
    291  1.25       leo 		sc->sc_rbufaddr[i] = mem;
    292  1.25       leo 	for (i = 0; i < sc->sc_ntbuf; i++, mem += LEBLEN)
    293  1.25       leo 		sc->sc_tbufaddr[i] = mem;
    294   1.1       cgd #ifdef notyet
    295   1.1       cgd 	if (mem > ...)
    296   1.1       cgd 		panic(...);
    297   1.1       cgd #endif
    298  1.37  explorer 
    299  1.38  explorer #if NRND > 0
    300  1.37  explorer 	rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
    301  1.37  explorer 			  RND_TYPE_NET);
    302  1.38  explorer #endif
    303   1.1       cgd }
    304   1.1       cgd 
    305   1.1       cgd void
    306  1.19   thorpej am7990_reset(sc)
    307  1.19   thorpej 	struct am7990_softc *sc;
    308   1.1       cgd {
    309   1.2   mycroft 	int s;
    310   1.1       cgd 
    311   1.2   mycroft 	s = splimp();
    312  1.19   thorpej 	am7990_init(sc);
    313   1.2   mycroft 	splx(s);
    314   1.1       cgd }
    315   1.1       cgd 
    316   1.1       cgd /*
    317   1.1       cgd  * Set up the initialization block and the descriptor rings.
    318   1.1       cgd  */
    319   1.1       cgd void
    320  1.19   thorpej am7990_meminit(sc)
    321  1.19   thorpej 	register struct am7990_softc *sc;
    322   1.1       cgd {
    323   1.1       cgd 	u_long a;
    324   1.1       cgd 	int bix;
    325   1.1       cgd 	struct leinit init;
    326   1.1       cgd 	struct lermd rmd;
    327   1.1       cgd 	struct letmd tmd;
    328  1.28        is 	u_int8_t *myaddr;
    329   1.1       cgd 
    330   1.1       cgd #if NBPFILTER > 0
    331   1.1       cgd 	if (ifp->if_flags & IFF_PROMISC)
    332   1.1       cgd 		init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM;
    333   1.1       cgd 	else
    334   1.1       cgd #endif
    335   1.1       cgd 		init.init_mode = LE_MODE_NORMAL;
    336  1.29     veego 	if (sc->sc_initmodemedia == 1)
    337  1.29     veego 		init.init_mode |= LE_MODE_PSEL0;
    338  1.28        is 
    339  1.39       gwr 	/*
    340  1.39       gwr 	 * Update our private copy of the Ethernet address.
    341  1.39       gwr 	 * We NEED the copy so we can ensure its alignment!
    342  1.39       gwr 	 */
    343  1.39       gwr 	bcopy(LLADDR(ifp->if_sadl), sc->sc_enaddr, 6);
    344  1.39       gwr 	myaddr = sc->sc_enaddr;
    345  1.39       gwr 
    346  1.28        is 	init.init_padr[0] = (myaddr[1] << 8) | myaddr[0];
    347  1.28        is 	init.init_padr[1] = (myaddr[3] << 8) | myaddr[2];
    348  1.28        is 	init.init_padr[2] = (myaddr[5] << 8) | myaddr[4];
    349  1.26        is 	am7990_setladrf(&sc->sc_ethercom, init.init_ladrf);
    350   1.1       cgd 
    351   1.1       cgd 	sc->sc_last_rd = 0;
    352   1.1       cgd 	sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
    353   1.1       cgd 
    354   1.1       cgd 	a = sc->sc_addr + LE_RMDADDR(sc, 0);
    355   1.1       cgd 	init.init_rdra = a;
    356   1.1       cgd 	init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13);
    357   1.1       cgd 
    358   1.1       cgd 	a = sc->sc_addr + LE_TMDADDR(sc, 0);
    359   1.1       cgd 	init.init_tdra = a;
    360   1.1       cgd 	init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13);
    361   1.1       cgd 
    362   1.1       cgd 	(*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
    363   1.1       cgd 
    364   1.1       cgd 	/*
    365   1.1       cgd 	 * Set up receive ring descriptors.
    366   1.1       cgd 	 */
    367   1.1       cgd 	for (bix = 0; bix < sc->sc_nrbuf; bix++) {
    368   1.1       cgd 		a = sc->sc_addr + LE_RBUFADDR(sc, bix);
    369   1.1       cgd 		rmd.rmd0 = a;
    370   1.1       cgd 		rmd.rmd1_hadr = a >> 16;
    371   1.1       cgd 		rmd.rmd1_bits = LE_R1_OWN;
    372   1.1       cgd 		rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
    373   1.1       cgd 		rmd.rmd3 = 0;
    374   1.1       cgd 		(*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
    375   1.1       cgd 		    sizeof(rmd));
    376   1.1       cgd 	}
    377   1.1       cgd 
    378   1.1       cgd 	/*
    379   1.1       cgd 	 * Set up transmit ring descriptors.
    380   1.1       cgd 	 */
    381   1.1       cgd 	for (bix = 0; bix < sc->sc_ntbuf; bix++) {
    382   1.1       cgd 		a = sc->sc_addr + LE_TBUFADDR(sc, bix);
    383   1.1       cgd 		tmd.tmd0 = a;
    384   1.1       cgd 		tmd.tmd1_hadr = a >> 16;
    385   1.1       cgd 		tmd.tmd1_bits = 0;
    386   1.1       cgd 		tmd.tmd2 = 0 | LE_XMD2_ONES;
    387   1.1       cgd 		tmd.tmd3 = 0;
    388   1.1       cgd 		(*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
    389   1.1       cgd 		    sizeof(tmd));
    390   1.1       cgd 	}
    391   1.1       cgd }
    392   1.1       cgd 
    393   1.1       cgd void
    394  1.19   thorpej am7990_stop(sc)
    395  1.19   thorpej 	struct am7990_softc *sc;
    396   1.1       cgd {
    397   1.1       cgd 
    398  1.19   thorpej 	(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
    399   1.1       cgd }
    400   1.1       cgd 
    401   1.1       cgd /*
    402   1.1       cgd  * Initialization of interface; set up initialization block
    403   1.1       cgd  * and transmit/receive descriptor rings.
    404   1.1       cgd  */
    405   1.1       cgd void
    406  1.19   thorpej am7990_init(sc)
    407  1.19   thorpej 	register struct am7990_softc *sc;
    408   1.1       cgd {
    409   1.1       cgd 	register int timo;
    410   1.1       cgd 	u_long a;
    411   1.1       cgd 
    412  1.19   thorpej 	(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
    413  1.19   thorpej 	DELAY(100);
    414  1.29     veego 
    415  1.29     veego 	/* Newer LANCE chips have a reset register */
    416  1.29     veego 	if (sc->sc_hwreset)
    417  1.29     veego 		(*sc->sc_hwreset)(sc);
    418   1.1       cgd 
    419   1.1       cgd 	/* Set the correct byte swapping mode, etc. */
    420  1.19   thorpej 	(*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3);
    421   1.1       cgd 
    422   1.1       cgd 	/* Set up LANCE init block. */
    423  1.19   thorpej 	am7990_meminit(sc);
    424   1.1       cgd 
    425   1.1       cgd 	/* Give LANCE the physical address of its init block. */
    426   1.1       cgd 	a = sc->sc_addr + LE_INITADDR(sc);
    427  1.19   thorpej 	(*sc->sc_wrcsr)(sc, LE_CSR1, a);
    428  1.19   thorpej 	(*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16);
    429   1.1       cgd 
    430   1.1       cgd 	/* Try to initialize the LANCE. */
    431  1.19   thorpej 	DELAY(100);
    432  1.19   thorpej 	(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT);
    433   1.1       cgd 
    434   1.1       cgd 	/* Wait for initialization to finish. */
    435   1.1       cgd 	for (timo = 100000; timo; timo--)
    436  1.19   thorpej 		if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON)
    437   1.1       cgd 			break;
    438   1.1       cgd 
    439  1.19   thorpej 	if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) {
    440   1.1       cgd 		/* Start the LANCE. */
    441  1.19   thorpej 		(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT |
    442  1.19   thorpej 		    LE_C0_IDON);
    443   1.1       cgd 		ifp->if_flags |= IFF_RUNNING;
    444   1.1       cgd 		ifp->if_flags &= ~IFF_OACTIVE;
    445   1.1       cgd 		ifp->if_timer = 0;
    446  1.19   thorpej 		am7990_start(ifp);
    447   1.1       cgd 	} else
    448  1.44      fair 		printf("%s: controller failed to initialize\n",
    449  1.44      fair 			sc->sc_dev.dv_xname);
    450  1.19   thorpej 	if (sc->sc_hwinit)
    451  1.19   thorpej 		(*sc->sc_hwinit)(sc);
    452   1.1       cgd }
    453   1.1       cgd 
    454   1.1       cgd /*
    455   1.1       cgd  * Routine to copy from mbuf chain to transmit buffer in
    456   1.1       cgd  * network buffer memory.
    457   1.1       cgd  */
    458   1.1       cgd integrate int
    459  1.19   thorpej am7990_put(sc, boff, m)
    460  1.19   thorpej 	struct am7990_softc *sc;
    461   1.1       cgd 	int boff;
    462   1.1       cgd 	register struct mbuf *m;
    463   1.1       cgd {
    464   1.1       cgd 	register struct mbuf *n;
    465   1.1       cgd 	register int len, tlen = 0;
    466   1.1       cgd 
    467   1.1       cgd 	for (; m; m = n) {
    468   1.1       cgd 		len = m->m_len;
    469   1.1       cgd 		if (len == 0) {
    470   1.1       cgd 			MFREE(m, n);
    471   1.1       cgd 			continue;
    472   1.1       cgd 		}
    473   1.1       cgd 		(*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, len);
    474   1.1       cgd 		boff += len;
    475   1.1       cgd 		tlen += len;
    476   1.1       cgd 		MFREE(m, n);
    477   1.1       cgd 	}
    478   1.1       cgd 	if (tlen < LEMINSIZE) {
    479   1.1       cgd 		(*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen);
    480   1.1       cgd 		tlen = LEMINSIZE;
    481   1.1       cgd 	}
    482   1.1       cgd 	return (tlen);
    483   1.1       cgd }
    484   1.1       cgd 
    485   1.1       cgd /*
    486   1.1       cgd  * Pull data off an interface.
    487   1.1       cgd  * Len is length of data, with local net header stripped.
    488   1.1       cgd  * We copy the data into mbufs.  When full cluster sized units are present
    489   1.1       cgd  * we copy into clusters.
    490   1.1       cgd  */
    491   1.1       cgd integrate struct mbuf *
    492  1.19   thorpej am7990_get(sc, boff, totlen)
    493  1.19   thorpej 	struct am7990_softc *sc;
    494   1.1       cgd 	int boff, totlen;
    495   1.1       cgd {
    496   1.1       cgd 	register struct mbuf *m;
    497   1.1       cgd 	struct mbuf *top, **mp;
    498  1.34  jonathan 	int len;
    499   1.1       cgd 
    500   1.1       cgd 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    501   1.1       cgd 	if (m == 0)
    502   1.1       cgd 		return (0);
    503   1.7   mycroft 	m->m_pkthdr.rcvif = ifp;
    504   1.1       cgd 	m->m_pkthdr.len = totlen;
    505  1.34  jonathan 	len = MHLEN;
    506   1.1       cgd 	top = 0;
    507   1.1       cgd 	mp = &top;
    508   1.1       cgd 
    509   1.1       cgd 	while (totlen > 0) {
    510   1.1       cgd 		if (top) {
    511   1.1       cgd 			MGET(m, M_DONTWAIT, MT_DATA);
    512   1.1       cgd 			if (m == 0) {
    513   1.1       cgd 				m_freem(top);
    514   1.1       cgd 				return 0;
    515   1.1       cgd 			}
    516   1.1       cgd 			len = MLEN;
    517   1.1       cgd 		}
    518  1.32   mycroft 		if (totlen >= MINCLSIZE) {
    519   1.1       cgd 			MCLGET(m, M_DONTWAIT);
    520  1.33   mycroft 			if ((m->m_flags & M_EXT) == 0) {
    521  1.35   mycroft 				m_free(m);
    522  1.31   mycroft 				m_freem(top);
    523  1.31   mycroft 				return 0;
    524  1.31   mycroft 			}
    525  1.31   mycroft 			len = MCLBYTES;
    526  1.34  jonathan 		}
    527  1.34  jonathan 		if (!top) {
    528  1.34  jonathan 			register int pad =
    529  1.34  jonathan 			    ALIGN(sizeof(struct ether_header)) -
    530  1.34  jonathan 			        sizeof(struct ether_header);
    531  1.34  jonathan 			m->m_data += pad;
    532  1.34  jonathan 			len -= pad;
    533   1.1       cgd 		}
    534   1.1       cgd 		m->m_len = len = min(totlen, len);
    535   1.1       cgd 		(*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, len);
    536   1.1       cgd 		boff += len;
    537   1.1       cgd 		totlen -= len;
    538   1.1       cgd 		*mp = m;
    539   1.1       cgd 		mp = &m->m_next;
    540   1.1       cgd 	}
    541   1.1       cgd 
    542   1.1       cgd 	return (top);
    543   1.1       cgd }
    544   1.1       cgd 
    545   1.1       cgd /*
    546   1.1       cgd  * Pass a packet to the higher levels.
    547   1.1       cgd  */
    548   1.1       cgd integrate void
    549  1.19   thorpej am7990_read(sc, boff, len)
    550  1.19   thorpej 	register struct am7990_softc *sc;
    551   1.1       cgd 	int boff, len;
    552   1.1       cgd {
    553   1.1       cgd 	struct mbuf *m;
    554   1.1       cgd 	struct ether_header *eh;
    555   1.1       cgd 
    556   1.2   mycroft 	if (len <= sizeof(struct ether_header) ||
    557   1.3   mycroft 	    len > ETHERMTU + sizeof(struct ether_header)) {
    558   1.6   mycroft #ifdef LEDEBUG
    559  1.22  christos 		printf("%s: invalid packet size %d; dropping\n",
    560   1.2   mycroft 		    sc->sc_dev.dv_xname, len);
    561   1.6   mycroft #endif
    562   1.2   mycroft 		ifp->if_ierrors++;
    563   1.1       cgd 		return;
    564   1.2   mycroft 	}
    565   1.1       cgd 
    566   1.1       cgd 	/* Pull packet off interface. */
    567  1.19   thorpej 	m = am7990_get(sc, boff, len);
    568   1.2   mycroft 	if (m == 0) {
    569   1.2   mycroft 		ifp->if_ierrors++;
    570   1.1       cgd 		return;
    571   1.2   mycroft 	}
    572   1.2   mycroft 
    573   1.2   mycroft 	ifp->if_ipackets++;
    574   1.1       cgd 
    575   1.1       cgd 	/* We assume that the header fit entirely in one mbuf. */
    576   1.1       cgd 	eh = mtod(m, struct ether_header *);
    577   1.1       cgd 
    578   1.1       cgd #if NBPFILTER > 0
    579   1.1       cgd 	/*
    580   1.1       cgd 	 * Check if there's a BPF listener on this interface.
    581   1.1       cgd 	 * If so, hand off the raw packet to BPF.
    582   1.1       cgd 	 */
    583   1.1       cgd 	if (ifp->if_bpf) {
    584   1.1       cgd 		bpf_mtap(ifp->if_bpf, m);
    585   1.1       cgd 
    586   1.5   mycroft #ifndef LANCE_REVC_BUG
    587   1.1       cgd 		/*
    588   1.1       cgd 		 * Note that the interface cannot be in promiscuous mode if
    589   1.1       cgd 		 * there are no BPF listeners.  And if we are in promiscuous
    590   1.1       cgd 		 * mode, we have to check if this packet is really ours.
    591   1.1       cgd 		 */
    592   1.1       cgd 		if ((ifp->if_flags & IFF_PROMISC) != 0 &&
    593   1.1       cgd 		    (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
    594  1.39       gwr 		    ETHER_CMP(eh->ether_dhost, sc->sc_enaddr)) {
    595   1.1       cgd 			m_freem(m);
    596   1.1       cgd 			return;
    597   1.1       cgd 		}
    598   1.5   mycroft #endif
    599   1.5   mycroft 	}
    600   1.5   mycroft #endif
    601   1.5   mycroft 
    602   1.5   mycroft #ifdef LANCE_REVC_BUG
    603  1.13       gwr 	/*
    604  1.13       gwr 	 * The old LANCE (Rev. C) chips have a bug which causes
    605  1.13       gwr 	 * garbage to be inserted in front of the received packet.
    606  1.13       gwr 	 * The work-around is to ignore packets with an invalid
    607  1.13       gwr 	 * destination address (garbage will usually not match).
    608  1.13       gwr 	 * Of course, this precludes multicast support...
    609  1.13       gwr 	 */
    610  1.39       gwr 	if (ETHER_CMP(eh->ether_dhost, sc->sc_enaddr) &&
    611  1.39       gwr 	    ETHER_CMP(eh->ether_dhost, bcast_enaddr)) {
    612   1.5   mycroft 		m_freem(m);
    613   1.5   mycroft 		return;
    614   1.1       cgd 	}
    615   1.1       cgd #endif
    616   1.1       cgd 
    617   1.1       cgd 	/* Pass the packet up, with the ether header sort-of removed. */
    618   1.1       cgd 	m_adj(m, sizeof(struct ether_header));
    619   1.1       cgd 	ether_input(ifp, eh, m);
    620   1.1       cgd }
    621   1.1       cgd 
    622   1.1       cgd integrate void
    623  1.19   thorpej am7990_rint(sc)
    624  1.19   thorpej 	struct am7990_softc *sc;
    625   1.1       cgd {
    626   1.1       cgd 	register int bix;
    627   1.1       cgd 	int rp;
    628   1.1       cgd 	struct lermd rmd;
    629   1.1       cgd 
    630   1.1       cgd 	bix = sc->sc_last_rd;
    631   1.1       cgd 
    632   1.1       cgd 	/* Process all buffers with valid data. */
    633   1.1       cgd 	for (;;) {
    634   1.1       cgd 		rp = LE_RMDADDR(sc, bix);
    635   1.1       cgd 		(*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
    636   1.1       cgd 
    637   1.1       cgd 		if (rmd.rmd1_bits & LE_R1_OWN)
    638   1.1       cgd 			break;
    639   1.1       cgd 
    640   1.1       cgd 		if (rmd.rmd1_bits & LE_R1_ERR) {
    641   1.1       cgd 			if (rmd.rmd1_bits & LE_R1_ENP) {
    642   1.6   mycroft #ifdef LEDEBUG
    643   1.1       cgd 				if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) {
    644   1.1       cgd 					if (rmd.rmd1_bits & LE_R1_FRAM)
    645  1.22  christos 						printf("%s: framing error\n",
    646   1.1       cgd 						    sc->sc_dev.dv_xname);
    647   1.1       cgd 					if (rmd.rmd1_bits & LE_R1_CRC)
    648  1.22  christos 						printf("%s: crc mismatch\n",
    649   1.1       cgd 						    sc->sc_dev.dv_xname);
    650   1.1       cgd 				}
    651   1.6   mycroft #endif
    652   1.1       cgd 			} else {
    653   1.1       cgd 				if (rmd.rmd1_bits & LE_R1_OFLO)
    654  1.22  christos 					printf("%s: overflow\n",
    655   1.1       cgd 					    sc->sc_dev.dv_xname);
    656   1.1       cgd 			}
    657   1.1       cgd 			if (rmd.rmd1_bits & LE_R1_BUFF)
    658  1.22  christos 				printf("%s: receive buffer error\n",
    659   1.1       cgd 				    sc->sc_dev.dv_xname);
    660   1.7   mycroft 			ifp->if_ierrors++;
    661  1.12  christos 		} else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) !=
    662   1.1       cgd 		    (LE_R1_STP | LE_R1_ENP)) {
    663  1.22  christos 			printf("%s: dropping chained buffer\n",
    664   1.1       cgd 			    sc->sc_dev.dv_xname);
    665   1.7   mycroft 			ifp->if_ierrors++;
    666   1.1       cgd 		} else {
    667   1.1       cgd #ifdef LEDEBUG
    668   1.1       cgd 			if (sc->sc_debug)
    669  1.19   thorpej 				am7990_recv_print(sc, sc->sc_last_rd);
    670   1.1       cgd #endif
    671  1.19   thorpej 			am7990_read(sc, LE_RBUFADDR(sc, bix),
    672  1.19   thorpej 			    (int)rmd.rmd3 - 4);
    673   1.1       cgd 		}
    674   1.1       cgd 
    675   1.1       cgd 		rmd.rmd1_bits = LE_R1_OWN;
    676   1.1       cgd 		rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
    677   1.1       cgd 		rmd.rmd3 = 0;
    678   1.1       cgd 		(*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
    679   1.1       cgd 
    680   1.1       cgd #ifdef LEDEBUG
    681   1.1       cgd 		if (sc->sc_debug)
    682  1.22  christos 			printf("sc->sc_last_rd = %x, rmd: "
    683  1.16        pk 			       "ladr %04x, hadr %02x, flags %02x, "
    684  1.16        pk 			       "bcnt %04x, mcnt %04x\n",
    685  1.16        pk 				sc->sc_last_rd,
    686  1.16        pk 				rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits,
    687  1.16        pk 				rmd.rmd2, rmd.rmd3);
    688   1.1       cgd #endif
    689   1.1       cgd 
    690   1.1       cgd 		if (++bix == sc->sc_nrbuf)
    691   1.1       cgd 			bix = 0;
    692   1.1       cgd 	}
    693   1.1       cgd 
    694   1.1       cgd 	sc->sc_last_rd = bix;
    695   1.1       cgd }
    696   1.1       cgd 
    697   1.1       cgd integrate void
    698  1.19   thorpej am7990_tint(sc)
    699  1.19   thorpej 	register struct am7990_softc *sc;
    700   1.1       cgd {
    701   1.1       cgd 	register int bix;
    702   1.1       cgd 	struct letmd tmd;
    703   1.9   thorpej 
    704   1.1       cgd 	bix = sc->sc_first_td;
    705   1.1       cgd 
    706   1.1       cgd 	for (;;) {
    707   1.1       cgd 		if (sc->sc_no_td <= 0)
    708   1.1       cgd 			break;
    709   1.1       cgd 
    710  1.50  drochner 		(*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
    711  1.50  drochner 		    sizeof(tmd));
    712  1.50  drochner 
    713   1.1       cgd #ifdef LEDEBUG
    714   1.1       cgd 		if (sc->sc_debug)
    715  1.22  christos 			printf("trans tmd: "
    716  1.21  christos 			    "ladr %04x, hadr %02x, flags %02x, "
    717  1.21  christos 			    "bcnt %04x, mcnt %04x\n",
    718  1.21  christos 			    tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits,
    719  1.21  christos 			    tmd.tmd2, tmd.tmd3);
    720   1.1       cgd #endif
    721   1.1       cgd 
    722   1.1       cgd 		if (tmd.tmd1_bits & LE_T1_OWN)
    723   1.1       cgd 			break;
    724   1.1       cgd 
    725   1.1       cgd 		ifp->if_flags &= ~IFF_OACTIVE;
    726   1.1       cgd 
    727   1.1       cgd 		if (tmd.tmd1_bits & LE_T1_ERR) {
    728   1.1       cgd 			if (tmd.tmd3 & LE_T3_BUFF)
    729  1.22  christos 				printf("%s: transmit buffer error\n",
    730  1.19   thorpej 				    sc->sc_dev.dv_xname);
    731   1.1       cgd 			else if (tmd.tmd3 & LE_T3_UFLO)
    732  1.22  christos 				printf("%s: underflow\n", sc->sc_dev.dv_xname);
    733   1.1       cgd 			if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
    734  1.19   thorpej 				am7990_reset(sc);
    735   1.1       cgd 				return;
    736   1.1       cgd 			}
    737  1.20    abrown 			if (tmd.tmd3 & LE_T3_LCAR) {
    738  1.27   thorpej 				sc->sc_havecarrier = 0;
    739  1.20    abrown 				if (sc->sc_nocarrier)
    740  1.20    abrown 					(*sc->sc_nocarrier)(sc);
    741  1.20    abrown 				else
    742  1.22  christos 					printf("%s: lost carrier\n",
    743  1.20    abrown 					    sc->sc_dev.dv_xname);
    744  1.20    abrown 			}
    745   1.1       cgd 			if (tmd.tmd3 & LE_T3_LCOL)
    746   1.1       cgd 				ifp->if_collisions++;
    747   1.1       cgd 			if (tmd.tmd3 & LE_T3_RTRY) {
    748  1.22  christos 				printf("%s: excessive collisions, tdr %d\n",
    749  1.19   thorpej 				    sc->sc_dev.dv_xname,
    750  1.19   thorpej 				    tmd.tmd3 & LE_T3_TDR_MASK);
    751   1.1       cgd 				ifp->if_collisions += 16;
    752   1.1       cgd 			}
    753   1.1       cgd 			ifp->if_oerrors++;
    754   1.1       cgd 		} else {
    755   1.1       cgd 			if (tmd.tmd1_bits & LE_T1_ONE)
    756   1.1       cgd 				ifp->if_collisions++;
    757   1.1       cgd 			else if (tmd.tmd1_bits & LE_T1_MORE)
    758   1.1       cgd 				/* Real number is unknown. */
    759   1.1       cgd 				ifp->if_collisions += 2;
    760   1.1       cgd 			ifp->if_opackets++;
    761   1.1       cgd 		}
    762   1.1       cgd 
    763   1.1       cgd 		if (++bix == sc->sc_ntbuf)
    764   1.1       cgd 			bix = 0;
    765   1.1       cgd 
    766   1.1       cgd 		--sc->sc_no_td;
    767   1.1       cgd 	}
    768   1.1       cgd 
    769   1.1       cgd 	sc->sc_first_td = bix;
    770   1.1       cgd 
    771  1.19   thorpej 	am7990_start(ifp);
    772   1.1       cgd 
    773   1.1       cgd 	if (sc->sc_no_td == 0)
    774   1.1       cgd 		ifp->if_timer = 0;
    775   1.1       cgd }
    776   1.1       cgd 
    777   1.1       cgd /*
    778   1.1       cgd  * Controller interrupt.
    779   1.1       cgd  */
    780   1.1       cgd int
    781  1.19   thorpej am7990_intr(arg)
    782   1.1       cgd 	register void *arg;
    783   1.1       cgd {
    784  1.19   thorpej 	register struct am7990_softc *sc = arg;
    785   1.1       cgd 	register u_int16_t isr;
    786   1.1       cgd 
    787  1.25       leo 	isr = (*sc->sc_rdcsr)(sc, LE_CSR0) | sc->sc_saved_csr0;
    788  1.25       leo 	sc->sc_saved_csr0 = 0;
    789   1.1       cgd #ifdef LEDEBUG
    790   1.1       cgd 	if (sc->sc_debug)
    791  1.22  christos 		printf("%s: am7990_intr entering with isr=%04x\n",
    792   1.1       cgd 		    sc->sc_dev.dv_xname, isr);
    793   1.1       cgd #endif
    794   1.1       cgd 	if ((isr & LE_C0_INTR) == 0)
    795   1.1       cgd 		return (0);
    796   1.1       cgd 
    797  1.19   thorpej 	(*sc->sc_wrcsr)(sc, LE_CSR0,
    798   1.1       cgd 	    isr & (LE_C0_INEA | LE_C0_BABL | LE_C0_MISS | LE_C0_MERR |
    799   1.1       cgd 		   LE_C0_RINT | LE_C0_TINT | LE_C0_IDON));
    800   1.1       cgd 	if (isr & LE_C0_ERR) {
    801   1.1       cgd 		if (isr & LE_C0_BABL) {
    802   1.6   mycroft #ifdef LEDEBUG
    803  1.22  christos 			printf("%s: babble\n", sc->sc_dev.dv_xname);
    804   1.6   mycroft #endif
    805   1.7   mycroft 			ifp->if_oerrors++;
    806   1.1       cgd 		}
    807   1.1       cgd #if 0
    808   1.1       cgd 		if (isr & LE_C0_CERR) {
    809  1.22  christos 			printf("%s: collision error\n", sc->sc_dev.dv_xname);
    810   1.7   mycroft 			ifp->if_collisions++;
    811   1.1       cgd 		}
    812   1.1       cgd #endif
    813   1.6   mycroft 		if (isr & LE_C0_MISS) {
    814   1.6   mycroft #ifdef LEDEBUG
    815  1.22  christos 			printf("%s: missed packet\n", sc->sc_dev.dv_xname);
    816   1.6   mycroft #endif
    817   1.7   mycroft 			ifp->if_ierrors++;
    818   1.6   mycroft 		}
    819   1.1       cgd 		if (isr & LE_C0_MERR) {
    820  1.22  christos 			printf("%s: memory error\n", sc->sc_dev.dv_xname);
    821  1.19   thorpej 			am7990_reset(sc);
    822   1.1       cgd 			return (1);
    823   1.1       cgd 		}
    824   1.1       cgd 	}
    825   1.1       cgd 
    826   1.1       cgd 	if ((isr & LE_C0_RXON) == 0) {
    827  1.22  christos 		printf("%s: receiver disabled\n", sc->sc_dev.dv_xname);
    828   1.7   mycroft 		ifp->if_ierrors++;
    829  1.19   thorpej 		am7990_reset(sc);
    830   1.1       cgd 		return (1);
    831   1.1       cgd 	}
    832   1.1       cgd 	if ((isr & LE_C0_TXON) == 0) {
    833  1.22  christos 		printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname);
    834   1.7   mycroft 		ifp->if_oerrors++;
    835  1.19   thorpej 		am7990_reset(sc);
    836   1.1       cgd 		return (1);
    837   1.1       cgd 	}
    838   1.1       cgd 
    839  1.27   thorpej 	/*
    840  1.27   thorpej 	 * Pretend we have carrier; if we don't this will be cleared
    841  1.27   thorpej 	 * shortly.
    842  1.27   thorpej 	 */
    843  1.27   thorpej 	sc->sc_havecarrier = 1;
    844  1.27   thorpej 
    845   1.1       cgd 	if (isr & LE_C0_RINT)
    846  1.19   thorpej 		am7990_rint(sc);
    847   1.1       cgd 	if (isr & LE_C0_TINT)
    848  1.19   thorpej 		am7990_tint(sc);
    849  1.37  explorer 
    850  1.38  explorer #if NRND > 0
    851  1.37  explorer 	rnd_add_uint32(&sc->rnd_source, isr);
    852  1.38  explorer #endif
    853   1.1       cgd 
    854   1.1       cgd 	return (1);
    855   1.1       cgd }
    856   1.7   mycroft 
    857   1.7   mycroft #undef	ifp
    858   1.1       cgd 
    859  1.19   thorpej void
    860  1.19   thorpej am7990_watchdog(ifp)
    861  1.19   thorpej 	struct ifnet *ifp;
    862  1.19   thorpej {
    863  1.19   thorpej 	struct am7990_softc *sc = ifp->if_softc;
    864  1.19   thorpej 
    865  1.19   thorpej 	log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
    866  1.19   thorpej 	++ifp->if_oerrors;
    867  1.19   thorpej 
    868  1.19   thorpej 	am7990_reset(sc);
    869  1.19   thorpej }
    870  1.19   thorpej 
    871  1.27   thorpej int
    872  1.27   thorpej am7990_mediachange(ifp)
    873  1.27   thorpej 	struct ifnet *ifp;
    874  1.27   thorpej {
    875  1.27   thorpej 	struct am7990_softc *sc = ifp->if_softc;
    876  1.27   thorpej 
    877  1.27   thorpej 	if (sc->sc_mediachange)
    878  1.27   thorpej 		return ((*sc->sc_mediachange)(sc));
    879  1.27   thorpej 	return (EINVAL);
    880  1.27   thorpej }
    881  1.27   thorpej 
    882  1.27   thorpej void
    883  1.27   thorpej am7990_mediastatus(ifp, ifmr)
    884  1.27   thorpej 	struct ifnet *ifp;
    885  1.27   thorpej 	struct ifmediareq *ifmr;
    886  1.27   thorpej {
    887  1.27   thorpej 	struct am7990_softc *sc = ifp->if_softc;
    888  1.27   thorpej 
    889  1.27   thorpej 	if ((ifp->if_flags & IFF_UP) == 0)
    890  1.27   thorpej 		return;
    891  1.27   thorpej 
    892  1.27   thorpej 	ifmr->ifm_status = IFM_AVALID;
    893  1.27   thorpej 	if (sc->sc_havecarrier)
    894  1.27   thorpej 		ifmr->ifm_status |= IFM_ACTIVE;
    895  1.27   thorpej 
    896  1.27   thorpej 	if (sc->sc_mediastatus)
    897  1.27   thorpej 		(*sc->sc_mediastatus)(sc, ifmr);
    898  1.27   thorpej }
    899  1.27   thorpej 
    900   1.1       cgd /*
    901   1.1       cgd  * Setup output on interface.
    902   1.1       cgd  * Get another datagram to send off of the interface queue, and map it to the
    903   1.1       cgd  * interface before starting the output.
    904   1.1       cgd  * Called only at splimp or interrupt level.
    905   1.1       cgd  */
    906   1.1       cgd void
    907  1.19   thorpej am7990_start(ifp)
    908   1.1       cgd 	register struct ifnet *ifp;
    909   1.1       cgd {
    910  1.19   thorpej 	register struct am7990_softc *sc = ifp->if_softc;
    911   1.1       cgd 	register int bix;
    912   1.1       cgd 	register struct mbuf *m;
    913   1.1       cgd 	struct letmd tmd;
    914   1.1       cgd 	int rp;
    915   1.1       cgd 	int len;
    916   1.1       cgd 
    917   1.1       cgd 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
    918   1.1       cgd 		return;
    919   1.1       cgd 
    920   1.1       cgd 	bix = sc->sc_last_td;
    921   1.1       cgd 
    922   1.1       cgd 	for (;;) {
    923   1.1       cgd 		rp = LE_TMDADDR(sc, bix);
    924   1.1       cgd 		(*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
    925   1.1       cgd 
    926   1.1       cgd 		if (tmd.tmd1_bits & LE_T1_OWN) {
    927   1.1       cgd 			ifp->if_flags |= IFF_OACTIVE;
    928  1.22  christos 			printf("missing buffer, no_td = %d, last_td = %d\n",
    929   1.1       cgd 			    sc->sc_no_td, sc->sc_last_td);
    930   1.1       cgd 		}
    931   1.1       cgd 
    932   1.1       cgd 		IF_DEQUEUE(&ifp->if_snd, m);
    933   1.1       cgd 		if (m == 0)
    934   1.1       cgd 			break;
    935   1.1       cgd 
    936   1.1       cgd #if NBPFILTER > 0
    937   1.1       cgd 		/*
    938   1.1       cgd 		 * If BPF is listening on this interface, let it see the packet
    939   1.1       cgd 		 * before we commit it to the wire.
    940   1.1       cgd 		 */
    941   1.1       cgd 		if (ifp->if_bpf)
    942   1.1       cgd 			bpf_mtap(ifp->if_bpf, m);
    943   1.1       cgd #endif
    944   1.1       cgd 
    945   1.1       cgd 		/*
    946   1.1       cgd 		 * Copy the mbuf chain into the transmit buffer.
    947   1.1       cgd 		 */
    948  1.19   thorpej 		len = am7990_put(sc, LE_TBUFADDR(sc, bix), m);
    949   1.1       cgd 
    950   1.1       cgd #ifdef LEDEBUG
    951   1.3   mycroft 		if (len > ETHERMTU + sizeof(struct ether_header))
    952  1.22  christos 			printf("packet length %d\n", len);
    953   1.1       cgd #endif
    954   1.1       cgd 
    955   1.1       cgd 		ifp->if_timer = 5;
    956   1.1       cgd 
    957   1.1       cgd 		/*
    958   1.1       cgd 		 * Init transmit registers, and set transmit start flag.
    959   1.1       cgd 		 */
    960   1.1       cgd 		tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
    961   1.1       cgd 		tmd.tmd2 = -len | LE_XMD2_ONES;
    962   1.1       cgd 		tmd.tmd3 = 0;
    963   1.1       cgd 
    964   1.1       cgd 		(*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
    965   1.1       cgd 
    966   1.1       cgd #ifdef LEDEBUG
    967   1.1       cgd 		if (sc->sc_debug)
    968  1.19   thorpej 			am7990_xmit_print(sc, sc->sc_last_td);
    969   1.1       cgd #endif
    970   1.1       cgd 
    971  1.19   thorpej 		(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
    972   1.1       cgd 
    973   1.1       cgd 		if (++bix == sc->sc_ntbuf)
    974   1.1       cgd 			bix = 0;
    975   1.1       cgd 
    976   1.1       cgd 		if (++sc->sc_no_td == sc->sc_ntbuf) {
    977   1.1       cgd 			ifp->if_flags |= IFF_OACTIVE;
    978   1.1       cgd 			break;
    979   1.1       cgd 		}
    980   1.1       cgd 
    981   1.1       cgd 	}
    982   1.1       cgd 
    983   1.1       cgd 	sc->sc_last_td = bix;
    984   1.1       cgd }
    985   1.1       cgd 
    986   1.1       cgd /*
    987   1.1       cgd  * Process an ioctl request.
    988   1.1       cgd  */
    989   1.1       cgd int
    990  1.19   thorpej am7990_ioctl(ifp, cmd, data)
    991   1.1       cgd 	register struct ifnet *ifp;
    992   1.1       cgd 	u_long cmd;
    993   1.1       cgd 	caddr_t data;
    994   1.1       cgd {
    995  1.19   thorpej 	register struct am7990_softc *sc = ifp->if_softc;
    996   1.1       cgd 	struct ifaddr *ifa = (struct ifaddr *)data;
    997   1.1       cgd 	struct ifreq *ifr = (struct ifreq *)data;
    998   1.1       cgd 	int s, error = 0;
    999   1.1       cgd 
   1000   1.1       cgd 	s = splimp();
   1001   1.1       cgd 
   1002   1.1       cgd 	switch (cmd) {
   1003   1.1       cgd 
   1004   1.1       cgd 	case SIOCSIFADDR:
   1005   1.1       cgd 		ifp->if_flags |= IFF_UP;
   1006   1.1       cgd 
   1007   1.1       cgd 		switch (ifa->ifa_addr->sa_family) {
   1008   1.1       cgd #ifdef INET
   1009   1.1       cgd 		case AF_INET:
   1010  1.19   thorpej 			am7990_init(sc);
   1011  1.26        is 			arp_ifinit(ifp, ifa);
   1012   1.1       cgd 			break;
   1013   1.1       cgd #endif
   1014   1.1       cgd #ifdef NS
   1015   1.1       cgd 		case AF_NS:
   1016   1.1       cgd 		    {
   1017   1.1       cgd 			register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
   1018   1.1       cgd 
   1019   1.1       cgd 			if (ns_nullhost(*ina))
   1020   1.1       cgd 				ina->x_host =
   1021  1.26        is 				    *(union ns_host *)LLADDR(ifp->if_sadl);
   1022  1.26        is 			else {
   1023   1.1       cgd 				bcopy(ina->x_host.c_host,
   1024  1.26        is 				    LLADDR(ifp->if_sadl),
   1025  1.26        is 				    sizeof(sc->sc_enaddr));
   1026  1.26        is 			}
   1027   1.1       cgd 			/* Set new address. */
   1028  1.19   thorpej 			am7990_init(sc);
   1029   1.1       cgd 			break;
   1030   1.1       cgd 		    }
   1031   1.1       cgd #endif
   1032   1.1       cgd 		default:
   1033  1.19   thorpej 			am7990_init(sc);
   1034   1.1       cgd 			break;
   1035   1.1       cgd 		}
   1036   1.1       cgd 		break;
   1037   1.1       cgd 
   1038   1.1       cgd #if defined(CCITT) && defined(LLC)
   1039   1.1       cgd 	case SIOCSIFCONF_X25:
   1040   1.1       cgd 		ifp->if_flags |= IFF_UP;
   1041  1.11  christos 		ifa->ifa_rtrequest = cons_rtrequest; /* XXX */
   1042   1.1       cgd 		error = x25_llcglue(PRC_IFUP, ifa->ifa_addr);
   1043   1.1       cgd 		if (error == 0)
   1044  1.19   thorpej 			am7990_init(sc);
   1045   1.1       cgd 		break;
   1046   1.1       cgd #endif /* CCITT && LLC */
   1047   1.1       cgd 
   1048   1.1       cgd 	case SIOCSIFFLAGS:
   1049   1.1       cgd 		if ((ifp->if_flags & IFF_UP) == 0 &&
   1050   1.1       cgd 		    (ifp->if_flags & IFF_RUNNING) != 0) {
   1051   1.1       cgd 			/*
   1052   1.1       cgd 			 * If interface is marked down and it is running, then
   1053   1.1       cgd 			 * stop it.
   1054   1.1       cgd 			 */
   1055  1.19   thorpej 			am7990_stop(sc);
   1056   1.1       cgd 			ifp->if_flags &= ~IFF_RUNNING;
   1057   1.1       cgd 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
   1058   1.1       cgd 		    	   (ifp->if_flags & IFF_RUNNING) == 0) {
   1059   1.1       cgd 			/*
   1060   1.1       cgd 			 * If interface is marked up and it is stopped, then
   1061   1.1       cgd 			 * start it.
   1062   1.1       cgd 			 */
   1063  1.19   thorpej 			am7990_init(sc);
   1064   1.1       cgd 		} else {
   1065   1.1       cgd 			/*
   1066   1.1       cgd 			 * Reset the interface to pick up changes in any other
   1067   1.1       cgd 			 * flags that affect hardware registers.
   1068   1.1       cgd 			 */
   1069  1.19   thorpej 			/*am7990_stop(sc);*/
   1070  1.19   thorpej 			am7990_init(sc);
   1071   1.1       cgd 		}
   1072   1.1       cgd #ifdef LEDEBUG
   1073   1.1       cgd 		if (ifp->if_flags & IFF_DEBUG)
   1074   1.1       cgd 			sc->sc_debug = 1;
   1075   1.1       cgd 		else
   1076   1.1       cgd 			sc->sc_debug = 0;
   1077   1.1       cgd #endif
   1078   1.1       cgd 		break;
   1079   1.1       cgd 
   1080   1.1       cgd 	case SIOCADDMULTI:
   1081   1.1       cgd 	case SIOCDELMULTI:
   1082   1.1       cgd 		error = (cmd == SIOCADDMULTI) ?
   1083  1.26        is 		    ether_addmulti(ifr, &sc->sc_ethercom) :
   1084  1.26        is 		    ether_delmulti(ifr, &sc->sc_ethercom);
   1085   1.1       cgd 
   1086   1.1       cgd 		if (error == ENETRESET) {
   1087   1.1       cgd 			/*
   1088   1.1       cgd 			 * Multicast list has changed; set the hardware filter
   1089   1.1       cgd 			 * accordingly.
   1090   1.1       cgd 			 */
   1091  1.19   thorpej 			am7990_reset(sc);
   1092   1.1       cgd 			error = 0;
   1093   1.1       cgd 		}
   1094  1.27   thorpej 		break;
   1095  1.27   thorpej 
   1096  1.27   thorpej 	case SIOCGIFMEDIA:
   1097  1.27   thorpej 	case SIOCSIFMEDIA:
   1098  1.27   thorpej 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
   1099   1.1       cgd 		break;
   1100   1.1       cgd 
   1101   1.1       cgd 	default:
   1102   1.1       cgd 		error = EINVAL;
   1103   1.2   mycroft 		break;
   1104   1.1       cgd 	}
   1105   1.1       cgd 
   1106   1.1       cgd 	splx(s);
   1107   1.1       cgd 	return (error);
   1108   1.1       cgd }
   1109   1.1       cgd 
   1110  1.19   thorpej hide void
   1111  1.19   thorpej am7990_shutdown(arg)
   1112  1.19   thorpej 	void *arg;
   1113  1.19   thorpej {
   1114  1.19   thorpej 
   1115  1.19   thorpej 	am7990_stop((struct am7990_softc *)arg);
   1116  1.19   thorpej }
   1117  1.19   thorpej 
   1118   1.1       cgd #ifdef LEDEBUG
   1119   1.1       cgd void
   1120  1.19   thorpej am7990_recv_print(sc, no)
   1121  1.19   thorpej 	struct am7990_softc *sc;
   1122   1.1       cgd 	int no;
   1123   1.1       cgd {
   1124   1.1       cgd 	struct lermd rmd;
   1125   1.1       cgd 	u_int16_t len;
   1126   1.1       cgd 	struct ether_header eh;
   1127   1.1       cgd 
   1128   1.1       cgd 	(*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
   1129   1.1       cgd 	len = rmd.rmd3;
   1130  1.22  christos 	printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
   1131   1.1       cgd 	    len);
   1132  1.22  christos 	printf("%s: status %04x\n", sc->sc_dev.dv_xname,
   1133  1.19   thorpej 	    (*sc->sc_rdcsr)(sc, LE_CSR0));
   1134  1.22  christos 	printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
   1135   1.1       cgd 	    sc->sc_dev.dv_xname,
   1136   1.1       cgd 	    rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
   1137   1.1       cgd 	if (len >= sizeof(eh)) {
   1138   1.1       cgd 		(*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
   1139  1.22  christos 		printf("%s: dst %s", sc->sc_dev.dv_xname,
   1140  1.16        pk 			ether_sprintf(eh.ether_dhost));
   1141  1.22  christos 		printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
   1142  1.16        pk 			ntohs(eh.ether_type));
   1143   1.1       cgd 	}
   1144   1.1       cgd }
   1145   1.1       cgd 
   1146   1.1       cgd void
   1147  1.19   thorpej am7990_xmit_print(sc, no)
   1148  1.19   thorpej 	struct am7990_softc *sc;
   1149   1.1       cgd 	int no;
   1150   1.1       cgd {
   1151   1.1       cgd 	struct letmd tmd;
   1152   1.1       cgd 	u_int16_t len;
   1153   1.1       cgd 	struct ether_header eh;
   1154   1.1       cgd 
   1155   1.1       cgd 	(*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
   1156   1.1       cgd 	len = -tmd.tmd2;
   1157  1.22  christos 	printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
   1158   1.1       cgd 	    len);
   1159  1.22  christos 	printf("%s: status %04x\n", sc->sc_dev.dv_xname,
   1160  1.19   thorpej 	    (*sc->sc_rdcsr)(sc, LE_CSR0));
   1161  1.22  christos 	printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
   1162   1.1       cgd 	    sc->sc_dev.dv_xname,
   1163   1.1       cgd 	    tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
   1164   1.1       cgd 	if (len >= sizeof(eh)) {
   1165   1.1       cgd 		(*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
   1166  1.22  christos 		printf("%s: dst %s", sc->sc_dev.dv_xname,
   1167  1.16        pk 			ether_sprintf(eh.ether_dhost));
   1168  1.22  christos 		printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
   1169   1.1       cgd 		    ntohs(eh.ether_type));
   1170   1.1       cgd 	}
   1171   1.1       cgd }
   1172   1.1       cgd #endif /* LEDEBUG */
   1173   1.1       cgd 
   1174   1.1       cgd /*
   1175   1.1       cgd  * Set up the logical address filter.
   1176   1.1       cgd  */
   1177   1.1       cgd void
   1178  1.19   thorpej am7990_setladrf(ac, af)
   1179  1.26        is 	struct ethercom *ac;
   1180   1.1       cgd 	u_int16_t *af;
   1181   1.1       cgd {
   1182  1.26        is 	struct ifnet *ifp = &ac->ec_if;
   1183   1.1       cgd 	struct ether_multi *enm;
   1184  1.41   mycroft 	register u_char *cp;
   1185   1.1       cgd 	register u_int32_t crc;
   1186  1.43   mycroft 	static const u_int32_t crctab[] = {
   1187  1.42   mycroft 		0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
   1188  1.42   mycroft 		0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
   1189  1.42   mycroft 		0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
   1190  1.42   mycroft 		0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
   1191  1.42   mycroft 	};
   1192  1.42   mycroft 	register int len;
   1193   1.1       cgd 	struct ether_multistep step;
   1194   1.1       cgd 
   1195   1.1       cgd 	/*
   1196   1.1       cgd 	 * Set up multicast address filter by passing all multicast addresses
   1197   1.1       cgd 	 * through a crc generator, and then using the high order 6 bits as an
   1198   1.1       cgd 	 * index into the 64 bit logical address filter.  The high order bit
   1199   1.1       cgd 	 * selects the word, while the rest of the bits select the bit within
   1200   1.1       cgd 	 * the word.
   1201   1.1       cgd 	 */
   1202   1.1       cgd 
   1203   1.1       cgd 	if (ifp->if_flags & IFF_PROMISC)
   1204   1.1       cgd 		goto allmulti;
   1205   1.1       cgd 
   1206   1.1       cgd 	af[0] = af[1] = af[2] = af[3] = 0x0000;
   1207   1.1       cgd 	ETHER_FIRST_MULTI(step, ac, enm);
   1208   1.1       cgd 	while (enm != NULL) {
   1209  1.13       gwr 		if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) {
   1210   1.1       cgd 			/*
   1211   1.1       cgd 			 * We must listen to a range of multicast addresses.
   1212   1.1       cgd 			 * For now, just accept all multicasts, rather than
   1213   1.1       cgd 			 * trying to set only those filter bits needed to match
   1214   1.1       cgd 			 * the range.  (At this time, the only use of address
   1215   1.1       cgd 			 * ranges is for IP multicast routing, for which the
   1216   1.1       cgd 			 * range is big enough to require all bits set.)
   1217   1.1       cgd 			 */
   1218   1.1       cgd 			goto allmulti;
   1219   1.1       cgd 		}
   1220   1.1       cgd 
   1221   1.1       cgd 		cp = enm->enm_addrlo;
   1222   1.1       cgd 		crc = 0xffffffff;
   1223   1.1       cgd 		for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
   1224  1.42   mycroft 			crc ^= *cp++;
   1225  1.42   mycroft 			crc = (crc >> 4) ^ crctab[crc & 0xf];
   1226  1.42   mycroft 			crc = (crc >> 4) ^ crctab[crc & 0xf];
   1227   1.1       cgd 		}
   1228   1.1       cgd 		/* Just want the 6 most significant bits. */
   1229   1.1       cgd 		crc >>= 26;
   1230   1.1       cgd 
   1231   1.1       cgd 		/* Set the corresponding bit in the filter. */
   1232   1.1       cgd 		af[crc >> 4] |= 1 << (crc & 0xf);
   1233   1.1       cgd 
   1234   1.1       cgd 		ETHER_NEXT_MULTI(step, enm);
   1235   1.1       cgd 	}
   1236   1.1       cgd 	ifp->if_flags &= ~IFF_ALLMULTI;
   1237   1.1       cgd 	return;
   1238   1.1       cgd 
   1239   1.1       cgd allmulti:
   1240   1.1       cgd 	ifp->if_flags |= IFF_ALLMULTI;
   1241   1.1       cgd 	af[0] = af[1] = af[2] = af[3] = 0xffff;
   1242   1.1       cgd }
   1243   1.1       cgd 
   1244   1.1       cgd 
   1245   1.1       cgd /*
   1246   1.4       cgd  * Routines for accessing the transmit and receive buffers.
   1247   1.4       cgd  * The various CPU and adapter configurations supported by this
   1248   1.4       cgd  * driver require three different access methods for buffers
   1249   1.4       cgd  * and descriptors:
   1250   1.4       cgd  *	(1) contig (contiguous data; no padding),
   1251   1.4       cgd  *	(2) gap2 (two bytes of data followed by two bytes of padding),
   1252   1.4       cgd  *	(3) gap16 (16 bytes of data followed by 16 bytes of padding).
   1253   1.1       cgd  */
   1254   1.1       cgd 
   1255   1.4       cgd /*
   1256   1.4       cgd  * contig: contiguous data with no padding.
   1257   1.4       cgd  *
   1258   1.4       cgd  * Buffers may have any alignment.
   1259   1.4       cgd  */
   1260   1.1       cgd 
   1261  1.17       cgd void
   1262  1.17       cgd am7990_copytobuf_contig(sc, from, boff, len)
   1263  1.19   thorpej 	struct am7990_softc *sc;
   1264   1.4       cgd 	void *from;
   1265   1.1       cgd 	int boff, len;
   1266   1.1       cgd {
   1267   1.1       cgd 	volatile caddr_t buf = sc->sc_mem;
   1268   1.1       cgd 
   1269   1.1       cgd 	/*
   1270   1.1       cgd 	 * Just call bcopy() to do the work.
   1271   1.1       cgd 	 */
   1272   1.1       cgd 	bcopy(from, buf + boff, len);
   1273   1.1       cgd }
   1274   1.1       cgd 
   1275  1.17       cgd void
   1276  1.17       cgd am7990_copyfrombuf_contig(sc, to, boff, len)
   1277  1.19   thorpej 	struct am7990_softc *sc;
   1278   1.4       cgd 	void *to;
   1279   1.1       cgd 	int boff, len;
   1280   1.1       cgd {
   1281   1.1       cgd 	volatile caddr_t buf = sc->sc_mem;
   1282   1.1       cgd 
   1283   1.1       cgd 	/*
   1284   1.1       cgd 	 * Just call bcopy() to do the work.
   1285   1.1       cgd 	 */
   1286   1.1       cgd 	bcopy(buf + boff, to, len);
   1287   1.1       cgd }
   1288   1.1       cgd 
   1289  1.17       cgd void
   1290  1.17       cgd am7990_zerobuf_contig(sc, boff, len)
   1291  1.19   thorpej 	struct am7990_softc *sc;
   1292   1.1       cgd 	int boff, len;
   1293   1.1       cgd {
   1294   1.1       cgd 	volatile caddr_t buf = sc->sc_mem;
   1295   1.1       cgd 
   1296   1.1       cgd 	/*
   1297   1.1       cgd 	 * Just let bzero() do the work
   1298   1.1       cgd 	 */
   1299   1.1       cgd 	bzero(buf + boff, len);
   1300   1.1       cgd }
   1301   1.1       cgd 
   1302  1.19   thorpej #if 0
   1303  1.19   thorpej /*
   1304  1.19   thorpej  * Examples only; duplicate these and tweak (if necessary) in
   1305  1.19   thorpej  * machine-specific front-ends.
   1306  1.19   thorpej  */
   1307  1.19   thorpej 
   1308   1.1       cgd /*
   1309   1.4       cgd  * gap2: two bytes of data followed by two bytes of pad.
   1310   1.4       cgd  *
   1311   1.4       cgd  * Buffers must be 4-byte aligned.  The code doesn't worry about
   1312   1.4       cgd  * doing an extra byte.
   1313   1.1       cgd  */
   1314   1.4       cgd 
   1315  1.17       cgd void
   1316  1.17       cgd am7990_copytobuf_gap2(sc, fromv, boff, len)
   1317  1.19   thorpej 	struct am7990_softc *sc;
   1318   1.4       cgd 	void *fromv;
   1319   1.1       cgd 	int boff;
   1320   1.1       cgd 	register int len;
   1321   1.1       cgd {
   1322   1.1       cgd 	volatile caddr_t buf = sc->sc_mem;
   1323   1.4       cgd 	register caddr_t from = fromv;
   1324   1.4       cgd 	register volatile u_int16_t *bptr;
   1325   1.1       cgd 
   1326   1.1       cgd 	if (boff & 0x1) {
   1327   1.1       cgd 		/* handle unaligned first byte */
   1328   1.4       cgd 		bptr = ((volatile u_int16_t *)buf) + (boff - 1);
   1329   1.1       cgd 		*bptr = (*from++ << 8) | (*bptr & 0xff);
   1330   1.1       cgd 		bptr += 2;
   1331   1.1       cgd 		len--;
   1332   1.1       cgd 	} else
   1333   1.4       cgd 		bptr = ((volatile u_int16_t *)buf) + boff;
   1334   1.4       cgd 	while (len > 1) {
   1335   1.4       cgd 		*bptr = (from[1] << 8) | (from[0] & 0xff);
   1336   1.4       cgd 		bptr += 2;
   1337   1.4       cgd 		from += 2;
   1338   1.4       cgd 		len -= 2;
   1339   1.1       cgd 	}
   1340   1.1       cgd 	if (len == 1)
   1341   1.4       cgd 		*bptr = (u_int16_t)*from;
   1342   1.1       cgd }
   1343   1.1       cgd 
   1344  1.17       cgd void
   1345  1.17       cgd am7990_copyfrombuf_gap2(sc, tov, boff, len)
   1346  1.19   thorpej 	struct am7990_softc *sc;
   1347   1.4       cgd 	void *tov;
   1348   1.1       cgd 	int boff, len;
   1349   1.1       cgd {
   1350   1.1       cgd 	volatile caddr_t buf = sc->sc_mem;
   1351   1.4       cgd 	register caddr_t to = tov;
   1352   1.4       cgd 	register volatile u_int16_t *bptr;
   1353   1.4       cgd 	register u_int16_t tmp;
   1354   1.1       cgd 
   1355   1.1       cgd 	if (boff & 0x1) {
   1356   1.1       cgd 		/* handle unaligned first byte */
   1357   1.4       cgd 		bptr = ((volatile u_int16_t *)buf) + (boff - 1);
   1358   1.1       cgd 		*to++ = (*bptr >> 8) & 0xff;
   1359   1.1       cgd 		bptr += 2;
   1360   1.1       cgd 		len--;
   1361   1.1       cgd 	} else
   1362   1.4       cgd 		bptr = ((volatile u_int16_t *)buf) + boff;
   1363   1.4       cgd 	while (len > 1) {
   1364   1.4       cgd 		tmp = *bptr;
   1365   1.4       cgd 		*to++ = tmp & 0xff;
   1366   1.4       cgd 		*to++ = (tmp >> 8) & 0xff;
   1367   1.4       cgd 		bptr += 2;
   1368   1.4       cgd 		len -= 2;
   1369   1.1       cgd 	}
   1370   1.1       cgd 	if (len == 1)
   1371   1.1       cgd 		*to = *bptr & 0xff;
   1372   1.1       cgd }
   1373   1.1       cgd 
   1374  1.17       cgd void
   1375  1.17       cgd am7990_zerobuf_gap2(sc, boff, len)
   1376  1.19   thorpej 	struct am7990_softc *sc;
   1377   1.1       cgd 	int boff, len;
   1378   1.1       cgd {
   1379   1.1       cgd 	volatile caddr_t buf = sc->sc_mem;
   1380   1.4       cgd 	register volatile u_int16_t *bptr;
   1381   1.1       cgd 
   1382   1.1       cgd 	if ((unsigned)boff & 0x1) {
   1383   1.4       cgd 		bptr = ((volatile u_int16_t *)buf) + (boff - 1);
   1384   1.1       cgd 		*bptr &= 0xff;
   1385   1.1       cgd 		bptr += 2;
   1386   1.1       cgd 		len--;
   1387   1.1       cgd 	} else
   1388   1.4       cgd 		bptr = ((volatile u_int16_t *)buf) + boff;
   1389   1.1       cgd 	while (len > 0) {
   1390   1.1       cgd 		*bptr = 0;
   1391   1.1       cgd 		bptr += 2;
   1392   1.1       cgd 		len -= 2;
   1393   1.1       cgd 	}
   1394   1.1       cgd }
   1395   1.1       cgd 
   1396   1.1       cgd /*
   1397   1.4       cgd  * gap16: 16 bytes of data followed by 16 bytes of pad.
   1398   1.4       cgd  *
   1399   1.4       cgd  * Buffers must be 32-byte aligned.
   1400   1.1       cgd  */
   1401   1.4       cgd 
   1402  1.17       cgd void
   1403  1.17       cgd am7990_copytobuf_gap16(sc, fromv, boff, len)
   1404  1.19   thorpej 	struct am7990_softc *sc;
   1405   1.4       cgd 	void *fromv;
   1406   1.1       cgd 	int boff;
   1407   1.1       cgd 	register int len;
   1408   1.1       cgd {
   1409   1.1       cgd 	volatile caddr_t buf = sc->sc_mem;
   1410   1.4       cgd 	register caddr_t from = fromv;
   1411   1.1       cgd 	register caddr_t bptr;
   1412   1.1       cgd 	register int xfer;
   1413   1.1       cgd 
   1414   1.1       cgd 	bptr = buf + ((boff << 1) & ~0x1f);
   1415   1.1       cgd 	boff &= 0xf;
   1416   1.1       cgd 	xfer = min(len, 16 - boff);
   1417   1.1       cgd 	while (len > 0) {
   1418   1.1       cgd 		bcopy(from, bptr + boff, xfer);
   1419   1.1       cgd 		from += xfer;
   1420   1.1       cgd 		bptr += 32;
   1421   1.1       cgd 		boff = 0;
   1422   1.1       cgd 		len -= xfer;
   1423   1.1       cgd 		xfer = min(len, 16);
   1424   1.1       cgd 	}
   1425   1.1       cgd }
   1426   1.1       cgd 
   1427  1.17       cgd void
   1428  1.17       cgd am7990_copyfrombuf_gap16(sc, tov, boff, len)
   1429  1.19   thorpej 	struct am7990_softc *sc;
   1430   1.4       cgd 	void *tov;
   1431   1.1       cgd 	int boff, len;
   1432   1.1       cgd {
   1433   1.1       cgd 	volatile caddr_t buf = sc->sc_mem;
   1434   1.4       cgd 	register caddr_t to = tov;
   1435   1.1       cgd 	register caddr_t bptr;
   1436   1.1       cgd 	register int xfer;
   1437   1.1       cgd 
   1438   1.1       cgd 	bptr = buf + ((boff << 1) & ~0x1f);
   1439   1.1       cgd 	boff &= 0xf;
   1440   1.1       cgd 	xfer = min(len, 16 - boff);
   1441   1.1       cgd 	while (len > 0) {
   1442   1.1       cgd 		bcopy(bptr + boff, to, xfer);
   1443   1.1       cgd 		to += xfer;
   1444   1.1       cgd 		bptr += 32;
   1445   1.1       cgd 		boff = 0;
   1446   1.1       cgd 		len -= xfer;
   1447   1.1       cgd 		xfer = min(len, 16);
   1448   1.1       cgd 	}
   1449   1.1       cgd }
   1450   1.1       cgd 
   1451  1.17       cgd void
   1452  1.17       cgd am7990_zerobuf_gap16(sc, boff, len)
   1453  1.19   thorpej 	struct am7990_softc *sc;
   1454   1.1       cgd 	int boff, len;
   1455   1.1       cgd {
   1456   1.1       cgd 	volatile caddr_t buf = sc->sc_mem;
   1457   1.1       cgd 	register caddr_t bptr;
   1458   1.1       cgd 	register int xfer;
   1459   1.1       cgd 
   1460   1.1       cgd 	bptr = buf + ((boff << 1) & ~0x1f);
   1461   1.1       cgd 	boff &= 0xf;
   1462   1.1       cgd 	xfer = min(len, 16 - boff);
   1463   1.1       cgd 	while (len > 0) {
   1464   1.1       cgd 		bzero(bptr + boff, xfer);
   1465   1.1       cgd 		bptr += 32;
   1466   1.1       cgd 		boff = 0;
   1467   1.1       cgd 		len -= xfer;
   1468   1.1       cgd 		xfer = min(len, 16);
   1469   1.1       cgd 	}
   1470   1.1       cgd }
   1471  1.19   thorpej #endif /* Example only */
   1472