Home | History | Annotate | Line # | Download | only in dev
if_bm.c revision 1.31.10.3
      1  1.31.10.3  macallan /*	$NetBSD: if_bm.c,v 1.31.10.3 2007/08/02 05:34:32 macallan Exp $	*/
      2        1.1    tsubai 
      3        1.1    tsubai /*-
      4        1.4    tsubai  * Copyright (C) 1998, 1999, 2000 Tsubai Masanari.  All rights reserved.
      5        1.1    tsubai  *
      6        1.1    tsubai  * Redistribution and use in source and binary forms, with or without
      7        1.1    tsubai  * modification, are permitted provided that the following conditions
      8        1.1    tsubai  * are met:
      9        1.1    tsubai  * 1. Redistributions of source code must retain the above copyright
     10        1.1    tsubai  *    notice, this list of conditions and the following disclaimer.
     11        1.1    tsubai  * 2. Redistributions in binary form must reproduce the above copyright
     12        1.1    tsubai  *    notice, this list of conditions and the following disclaimer in the
     13        1.1    tsubai  *    documentation and/or other materials provided with the distribution.
     14        1.1    tsubai  * 3. The name of the author may not be used to endorse or promote products
     15        1.1    tsubai  *    derived from this software without specific prior written permission.
     16        1.1    tsubai  *
     17        1.1    tsubai  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18        1.1    tsubai  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19        1.1    tsubai  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20        1.1    tsubai  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21        1.1    tsubai  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22        1.1    tsubai  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23        1.1    tsubai  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24        1.1    tsubai  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25        1.1    tsubai  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26        1.1    tsubai  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27        1.1    tsubai  */
     28       1.21     lukem 
     29       1.21     lukem #include <sys/cdefs.h>
     30  1.31.10.3  macallan __KERNEL_RCSID(0, "$NetBSD: if_bm.c,v 1.31.10.3 2007/08/02 05:34:32 macallan Exp $");
     31        1.1    tsubai 
     32        1.1    tsubai #include "opt_inet.h"
     33        1.1    tsubai #include "bpfilter.h"
     34        1.1    tsubai 
     35        1.1    tsubai #include <sys/param.h>
     36        1.1    tsubai #include <sys/device.h>
     37        1.1    tsubai #include <sys/ioctl.h>
     38        1.4    tsubai #include <sys/kernel.h>
     39        1.1    tsubai #include <sys/mbuf.h>
     40        1.1    tsubai #include <sys/socket.h>
     41        1.1    tsubai #include <sys/systm.h>
     42        1.7   thorpej #include <sys/callout.h>
     43        1.1    tsubai 
     44       1.10       mrg #include <uvm/uvm_extern.h>
     45        1.4    tsubai 
     46        1.1    tsubai #include <net/if.h>
     47       1.22      matt #include <net/if_dl.h>
     48        1.1    tsubai #include <net/if_ether.h>
     49        1.1    tsubai #include <net/if_media.h>
     50        1.1    tsubai 
     51        1.1    tsubai #if NBPFILTER > 0
     52        1.1    tsubai #include <net/bpf.h>
     53        1.1    tsubai #endif
     54        1.1    tsubai 
     55        1.4    tsubai #ifdef INET
     56        1.4    tsubai #include <netinet/in.h>
     57        1.4    tsubai #include <netinet/if_inarp.h>
     58        1.4    tsubai #endif
     59        1.1    tsubai 
     60       1.22      matt 
     61        1.1    tsubai #include <dev/ofw/openfirm.h>
     62        1.1    tsubai 
     63        1.4    tsubai #include <dev/mii/mii.h>
     64        1.4    tsubai #include <dev/mii/miivar.h>
     65        1.4    tsubai #include <dev/mii/mii_bitbang.h>
     66        1.4    tsubai 
     67       1.24    kleink #include <powerpc/spr.h>
     68       1.24    kleink 
     69        1.1    tsubai #include <machine/autoconf.h>
     70        1.1    tsubai #include <machine/pio.h>
     71        1.1    tsubai 
     72        1.1    tsubai #include <macppc/dev/dbdma.h>
     73        1.1    tsubai #include <macppc/dev/if_bmreg.h>
     74        1.1    tsubai 
     75        1.1    tsubai #define BMAC_TXBUFS 2
     76        1.1    tsubai #define BMAC_RXBUFS 16
     77        1.1    tsubai #define BMAC_BUFLEN 2048
     78        1.1    tsubai 
     79        1.1    tsubai struct bmac_softc {
     80        1.1    tsubai 	struct device sc_dev;
     81        1.1    tsubai 	struct ethercom sc_ethercom;
     82        1.1    tsubai #define sc_if sc_ethercom.ec_if
     83        1.7   thorpej 	struct callout sc_tick_ch;
     84  1.31.10.2   garbled 	bus_space_tag_t sc_iot;
     85  1.31.10.2   garbled 	bus_space_handle_t sc_ioh;
     86        1.1    tsubai 	dbdma_regmap_t *sc_txdma;
     87        1.1    tsubai 	dbdma_regmap_t *sc_rxdma;
     88        1.1    tsubai 	dbdma_command_t *sc_txcmd;
     89        1.1    tsubai 	dbdma_command_t *sc_rxcmd;
     90       1.30  christos 	void *sc_txbuf;
     91       1.30  christos 	void *sc_rxbuf;
     92        1.1    tsubai 	int sc_rxlast;
     93        1.1    tsubai 	int sc_flags;
     94        1.4    tsubai 	struct mii_data sc_mii;
     95        1.1    tsubai 	u_char sc_enaddr[6];
     96        1.1    tsubai };
     97        1.1    tsubai 
     98        1.1    tsubai #define BMAC_BMACPLUS	0x01
     99        1.4    tsubai #define BMAC_DEBUGFLAG	0x02
    100        1.1    tsubai 
    101  1.31.10.2   garbled extern volatile uint32_t *heathrow_FCR;
    102        1.1    tsubai 
    103        1.4    tsubai int bmac_match __P((struct device *, struct cfdata *, void *));
    104        1.4    tsubai void bmac_attach __P((struct device *, struct device *, void *));
    105        1.4    tsubai void bmac_reset_chip __P((struct bmac_softc *));
    106        1.4    tsubai void bmac_init __P((struct bmac_softc *));
    107        1.4    tsubai void bmac_init_dma __P((struct bmac_softc *));
    108        1.4    tsubai int bmac_intr __P((void *));
    109        1.4    tsubai int bmac_rint __P((void *));
    110        1.4    tsubai void bmac_reset __P((struct bmac_softc *));
    111        1.4    tsubai void bmac_stop __P((struct bmac_softc *));
    112        1.4    tsubai void bmac_start __P((struct ifnet *));
    113        1.4    tsubai void bmac_transmit_packet __P((struct bmac_softc *, void *, int));
    114       1.30  christos int bmac_put __P((struct bmac_softc *, void *, struct mbuf *));
    115       1.30  christos struct mbuf *bmac_get __P((struct bmac_softc *, void *, int));
    116        1.4    tsubai void bmac_watchdog __P((struct ifnet *));
    117       1.30  christos int bmac_ioctl __P((struct ifnet *, u_long, void *));
    118        1.4    tsubai int bmac_mediachange __P((struct ifnet *));
    119        1.4    tsubai void bmac_mediastatus __P((struct ifnet *, struct ifmediareq *));
    120        1.4    tsubai void bmac_setladrf __P((struct bmac_softc *));
    121        1.4    tsubai 
    122        1.4    tsubai int bmac_mii_readreg __P((struct device *, int, int));
    123        1.4    tsubai void bmac_mii_writereg __P((struct device *, int, int, int));
    124        1.4    tsubai void bmac_mii_statchg __P((struct device *));
    125        1.4    tsubai void bmac_mii_tick __P((void *));
    126        1.4    tsubai u_int32_t bmac_mbo_read __P((struct device *));
    127        1.4    tsubai void bmac_mbo_write __P((struct device *, u_int32_t));
    128        1.1    tsubai 
    129       1.19   thorpej CFATTACH_DECL(bm, sizeof(struct bmac_softc),
    130       1.19   thorpej     bmac_match, bmac_attach, NULL, NULL);
    131        1.1    tsubai 
    132  1.31.10.2   garbled const struct mii_bitbang_ops bmac_mbo = {
    133        1.4    tsubai 	bmac_mbo_read, bmac_mbo_write,
    134        1.4    tsubai 	{ MIFDO, MIFDI, MIFDC, MIFDIR, 0 }
    135        1.4    tsubai };
    136        1.4    tsubai 
    137  1.31.10.2   garbled static inline uint16_t
    138  1.31.10.2   garbled bmac_read_reg(struct bmac_softc *sc, bus_size_t off)
    139        1.1    tsubai {
    140  1.31.10.2   garbled 	return bus_space_read_2(sc->sc_iot, sc->sc_ioh, off);
    141        1.1    tsubai }
    142        1.1    tsubai 
    143  1.31.10.2   garbled static inline void
    144  1.31.10.2   garbled bmac_write_reg(struct bmac_softc *sc, bus_size_t off, uint16_t val)
    145        1.1    tsubai {
    146  1.31.10.2   garbled 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, off, val);
    147        1.1    tsubai }
    148        1.1    tsubai 
    149  1.31.10.2   garbled static inline void
    150  1.31.10.2   garbled bmac_set_bits(struct bmac_softc *sc, bus_size_t off, uint16_t val)
    151        1.1    tsubai {
    152        1.1    tsubai 	val |= bmac_read_reg(sc, off);
    153        1.1    tsubai 	bmac_write_reg(sc, off, val);
    154        1.1    tsubai }
    155        1.1    tsubai 
    156  1.31.10.2   garbled static inline void
    157  1.31.10.2   garbled bmac_reset_bits(struct bmac_softc *sc, bus_size_t off, uint16_t val)
    158        1.1    tsubai {
    159        1.1    tsubai 	bmac_write_reg(sc, off, bmac_read_reg(sc, off) & ~val);
    160        1.1    tsubai }
    161        1.1    tsubai 
    162        1.1    tsubai int
    163  1.31.10.2   garbled bmac_match(struct device *parent, struct cfdata *cf, void *aux)
    164        1.1    tsubai {
    165        1.1    tsubai 	struct confargs *ca = aux;
    166        1.1    tsubai 
    167        1.1    tsubai 	if (ca->ca_nreg < 24 || ca->ca_nintr < 12)
    168        1.1    tsubai 		return 0;
    169        1.1    tsubai 
    170        1.1    tsubai 	if (strcmp(ca->ca_name, "bmac") == 0)		/* bmac */
    171        1.1    tsubai 		return 1;
    172        1.1    tsubai 	if (strcmp(ca->ca_name, "ethernet") == 0)	/* bmac+ */
    173        1.1    tsubai 		return 1;
    174        1.1    tsubai 
    175        1.1    tsubai 	return 0;
    176        1.1    tsubai }
    177        1.1    tsubai 
    178        1.1    tsubai void
    179  1.31.10.2   garbled bmac_attach(struct device *parent, struct device *self, void *aux)
    180        1.1    tsubai {
    181        1.1    tsubai 	struct confargs *ca = aux;
    182        1.1    tsubai 	struct bmac_softc *sc = (void *)self;
    183        1.1    tsubai 	struct ifnet *ifp = &sc->sc_if;
    184        1.4    tsubai 	struct mii_data *mii = &sc->sc_mii;
    185        1.1    tsubai 	u_char laddr[6];
    186        1.1    tsubai 
    187  1.31.10.3  macallan 	callout_init(&sc->sc_tick_ch, 0);
    188        1.7   thorpej 
    189        1.1    tsubai 	sc->sc_flags =0;
    190        1.3    tsubai 	if (strcmp(ca->ca_name, "ethernet") == 0) {
    191        1.3    tsubai 		char name[64];
    192        1.3    tsubai 
    193       1.16       wiz 		memset(name, 0, 64);
    194        1.3    tsubai 		OF_package_to_path(ca->ca_node, name, sizeof(name));
    195        1.3    tsubai 		OF_open(name);
    196        1.1    tsubai 		sc->sc_flags |= BMAC_BMACPLUS;
    197        1.3    tsubai 	}
    198        1.1    tsubai 
    199        1.1    tsubai 	ca->ca_reg[0] += ca->ca_baseaddr;
    200        1.1    tsubai 	ca->ca_reg[2] += ca->ca_baseaddr;
    201        1.1    tsubai 	ca->ca_reg[4] += ca->ca_baseaddr;
    202        1.1    tsubai 
    203  1.31.10.2   garbled 	sc->sc_iot = ca->ca_tag;
    204  1.31.10.2   garbled 	if (!bus_space_map(sc->sc_iot, ca->ca_reg[0], PAGE_SIZE, 0,
    205  1.31.10.2   garbled 	    &sc->sc_ioh)) {
    206  1.31.10.2   garbled 		aprint_error(": couldn't map %#x", ca->ca_reg[0]);
    207  1.31.10.2   garbled 		return;
    208  1.31.10.2   garbled 	}
    209        1.1    tsubai 
    210        1.1    tsubai 	bmac_write_reg(sc, INTDISABLE, NoEventsMask);
    211        1.1    tsubai 
    212        1.1    tsubai 	if (OF_getprop(ca->ca_node, "local-mac-address", laddr, 6) == -1 &&
    213        1.1    tsubai 	    OF_getprop(ca->ca_node, "mac-address", laddr, 6) == -1) {
    214        1.1    tsubai 		printf(": cannot get mac-address\n");
    215        1.1    tsubai 		return;
    216        1.1    tsubai 	}
    217       1.16       wiz 	memcpy(sc->sc_enaddr, laddr, 6);
    218        1.1    tsubai 
    219       1.20   thorpej 	sc->sc_txdma = mapiodev(ca->ca_reg[2], PAGE_SIZE);
    220       1.20   thorpej 	sc->sc_rxdma = mapiodev(ca->ca_reg[4], PAGE_SIZE);
    221        1.1    tsubai 	sc->sc_txcmd = dbdma_alloc(BMAC_TXBUFS * sizeof(dbdma_command_t));
    222        1.1    tsubai 	sc->sc_rxcmd = dbdma_alloc((BMAC_RXBUFS + 1) * sizeof(dbdma_command_t));
    223        1.1    tsubai 	sc->sc_txbuf = malloc(BMAC_BUFLEN * BMAC_TXBUFS, M_DEVBUF, M_NOWAIT);
    224        1.1    tsubai 	sc->sc_rxbuf = malloc(BMAC_BUFLEN * BMAC_RXBUFS, M_DEVBUF, M_NOWAIT);
    225        1.1    tsubai 	if (sc->sc_txbuf == NULL || sc->sc_rxbuf == NULL ||
    226        1.1    tsubai 	    sc->sc_txcmd == NULL || sc->sc_rxcmd == NULL) {
    227        1.1    tsubai 		printf("cannot allocate memory\n");
    228        1.1    tsubai 		return;
    229        1.1    tsubai 	}
    230        1.1    tsubai 
    231        1.1    tsubai 	printf(" irq %d,%d: address %s\n", ca->ca_intr[0], ca->ca_intr[2],
    232        1.1    tsubai 		ether_sprintf(laddr));
    233        1.1    tsubai 
    234  1.31.10.1  macallan 	intr_establish(ca->ca_intr[0], IST_EDGE, IPL_NET, bmac_intr, sc);
    235  1.31.10.1  macallan 	intr_establish(ca->ca_intr[2], IST_EDGE, IPL_NET, bmac_rint, sc);
    236        1.1    tsubai 
    237       1.16       wiz 	memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
    238        1.1    tsubai 	ifp->if_softc = sc;
    239        1.1    tsubai 	ifp->if_ioctl = bmac_ioctl;
    240        1.1    tsubai 	ifp->if_start = bmac_start;
    241        1.1    tsubai 	ifp->if_flags =
    242        1.1    tsubai 		IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
    243        1.1    tsubai 	ifp->if_watchdog = bmac_watchdog;
    244       1.17    itojun 	IFQ_SET_READY(&ifp->if_snd);
    245        1.1    tsubai 
    246        1.4    tsubai 	mii->mii_ifp = ifp;
    247        1.4    tsubai 	mii->mii_readreg = bmac_mii_readreg;
    248        1.4    tsubai 	mii->mii_writereg = bmac_mii_writereg;
    249        1.4    tsubai 	mii->mii_statchg = bmac_mii_statchg;
    250        1.4    tsubai 
    251        1.4    tsubai 	ifmedia_init(&mii->mii_media, 0, bmac_mediachange, bmac_mediastatus);
    252        1.5   thorpej 	mii_attach(&sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY,
    253        1.6   thorpej 		      MII_OFFSET_ANY, 0);
    254        1.4    tsubai 
    255        1.4    tsubai 	/* Choose a default media. */
    256        1.4    tsubai 	if (LIST_FIRST(&mii->mii_phys) == NULL) {
    257        1.4    tsubai 		ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_10_T, 0, NULL);
    258        1.4    tsubai 		ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_10_T);
    259        1.4    tsubai 	} else
    260        1.4    tsubai 		ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO);
    261        1.1    tsubai 
    262        1.1    tsubai 	bmac_reset_chip(sc);
    263        1.1    tsubai 
    264        1.1    tsubai 	if_attach(ifp);
    265        1.1    tsubai 	ether_ifattach(ifp, sc->sc_enaddr);
    266        1.1    tsubai }
    267        1.1    tsubai 
    268        1.1    tsubai /*
    269        1.1    tsubai  * Reset and enable bmac by heathrow FCR.
    270        1.1    tsubai  */
    271        1.1    tsubai void
    272        1.1    tsubai bmac_reset_chip(sc)
    273        1.1    tsubai 	struct bmac_softc *sc;
    274        1.1    tsubai {
    275        1.1    tsubai 	u_int v;
    276        1.1    tsubai 
    277        1.1    tsubai 	dbdma_reset(sc->sc_txdma);
    278        1.1    tsubai 	dbdma_reset(sc->sc_rxdma);
    279        1.1    tsubai 
    280        1.1    tsubai 	v = in32rb(heathrow_FCR);
    281        1.1    tsubai 
    282        1.1    tsubai 	v |= EnetEnable;
    283        1.1    tsubai 	out32rb(heathrow_FCR, v);
    284        1.1    tsubai 	delay(50000);
    285        1.1    tsubai 
    286        1.1    tsubai 	v |= ResetEnetCell;
    287        1.1    tsubai 	out32rb(heathrow_FCR, v);
    288        1.1    tsubai 	delay(50000);
    289        1.1    tsubai 
    290        1.1    tsubai 	v &= ~ResetEnetCell;
    291        1.1    tsubai 	out32rb(heathrow_FCR, v);
    292        1.1    tsubai 	delay(50000);
    293        1.1    tsubai 
    294        1.1    tsubai 	out32rb(heathrow_FCR, v);
    295        1.1    tsubai }
    296        1.1    tsubai 
    297        1.1    tsubai void
    298        1.1    tsubai bmac_init(sc)
    299        1.1    tsubai 	struct bmac_softc *sc;
    300        1.1    tsubai {
    301        1.1    tsubai 	struct ifnet *ifp = &sc->sc_if;
    302        1.1    tsubai 	struct ether_header *eh;
    303       1.30  christos 	void *data;
    304        1.4    tsubai 	int i, tb, bmcr;
    305        1.1    tsubai 	u_short *p;
    306        1.1    tsubai 
    307        1.1    tsubai 	bmac_reset_chip(sc);
    308        1.1    tsubai 
    309        1.4    tsubai 	/* XXX */
    310        1.4    tsubai 	bmcr = bmac_mii_readreg((struct device *)sc, 0, MII_BMCR);
    311        1.4    tsubai 	bmcr &= ~BMCR_ISO;
    312        1.4    tsubai 	bmac_mii_writereg((struct device *)sc, 0, MII_BMCR, bmcr);
    313        1.4    tsubai 
    314        1.1    tsubai 	bmac_write_reg(sc, RXRST, RxResetValue);
    315        1.1    tsubai 	bmac_write_reg(sc, TXRST, TxResetBit);
    316        1.1    tsubai 
    317        1.1    tsubai 	/* Wait for reset completion. */
    318        1.4    tsubai 	for (i = 1000; i > 0; i -= 10) {
    319        1.4    tsubai 		if ((bmac_read_reg(sc, TXRST) & TxResetBit) == 0)
    320        1.4    tsubai 			break;
    321        1.4    tsubai 		delay(10);
    322        1.4    tsubai 	}
    323        1.4    tsubai 	if (i <= 0)
    324        1.4    tsubai 		printf("%s: reset timeout\n", ifp->if_xname);
    325        1.1    tsubai 
    326        1.1    tsubai 	if (! (sc->sc_flags & BMAC_BMACPLUS))
    327        1.1    tsubai 		bmac_set_bits(sc, XCVRIF, ClkBit|SerialMode|COLActiveLow);
    328        1.1    tsubai 
    329       1.24    kleink 	if ((mfpvr() >> 16) == MPC601)
    330       1.24    kleink 		tb = mfrtcl();
    331       1.24    kleink 	else
    332       1.24    kleink 		tb = mftbl();
    333        1.1    tsubai 	bmac_write_reg(sc, RSEED, tb);
    334        1.1    tsubai 	bmac_set_bits(sc, XIFC, TxOutputEnable);
    335        1.1    tsubai 	bmac_read_reg(sc, PAREG);
    336        1.1    tsubai 
    337        1.1    tsubai 	/* Reset various counters. */
    338        1.1    tsubai 	bmac_write_reg(sc, NCCNT, 0);
    339        1.1    tsubai 	bmac_write_reg(sc, NTCNT, 0);
    340        1.1    tsubai 	bmac_write_reg(sc, EXCNT, 0);
    341        1.1    tsubai 	bmac_write_reg(sc, LTCNT, 0);
    342        1.1    tsubai 	bmac_write_reg(sc, FRCNT, 0);
    343        1.1    tsubai 	bmac_write_reg(sc, LECNT, 0);
    344        1.1    tsubai 	bmac_write_reg(sc, AECNT, 0);
    345        1.1    tsubai 	bmac_write_reg(sc, FECNT, 0);
    346        1.1    tsubai 	bmac_write_reg(sc, RXCV, 0);
    347        1.1    tsubai 
    348        1.1    tsubai 	/* Set tx fifo information. */
    349        1.1    tsubai 	bmac_write_reg(sc, TXTH, 4);	/* 4 octets before tx starts */
    350        1.1    tsubai 
    351        1.1    tsubai 	bmac_write_reg(sc, TXFIFOCSR, 0);
    352        1.1    tsubai 	bmac_write_reg(sc, TXFIFOCSR, TxFIFOEnable);
    353        1.1    tsubai 
    354        1.1    tsubai 	/* Set rx fifo information. */
    355        1.1    tsubai 	bmac_write_reg(sc, RXFIFOCSR, 0);
    356        1.1    tsubai 	bmac_write_reg(sc, RXFIFOCSR, RxFIFOEnable);
    357        1.1    tsubai 
    358        1.1    tsubai 	/* Clear status register. */
    359        1.1    tsubai 	bmac_read_reg(sc, STATUS);
    360        1.1    tsubai 
    361        1.1    tsubai 	bmac_write_reg(sc, HASH3, 0);
    362        1.1    tsubai 	bmac_write_reg(sc, HASH2, 0);
    363        1.1    tsubai 	bmac_write_reg(sc, HASH1, 0);
    364        1.1    tsubai 	bmac_write_reg(sc, HASH0, 0);
    365        1.1    tsubai 
    366        1.1    tsubai 	/* Set MAC address. */
    367        1.1    tsubai 	p = (u_short *)sc->sc_enaddr;
    368        1.1    tsubai 	bmac_write_reg(sc, MADD0, *p++);
    369        1.1    tsubai 	bmac_write_reg(sc, MADD1, *p++);
    370        1.1    tsubai 	bmac_write_reg(sc, MADD2, *p);
    371        1.1    tsubai 
    372        1.1    tsubai 	bmac_write_reg(sc, RXCFG,
    373        1.1    tsubai 		RxCRCEnable | RxHashFilterEnable | RxRejectOwnPackets);
    374        1.1    tsubai 
    375        1.1    tsubai 	if (ifp->if_flags & IFF_PROMISC)
    376        1.1    tsubai 		bmac_set_bits(sc, RXCFG, RxPromiscEnable);
    377        1.1    tsubai 
    378        1.1    tsubai 	bmac_init_dma(sc);
    379        1.1    tsubai 
    380        1.1    tsubai 	/* Enable TX/RX */
    381        1.1    tsubai 	bmac_set_bits(sc, RXCFG, RxMACEnable);
    382        1.1    tsubai 	bmac_set_bits(sc, TXCFG, TxMACEnable);
    383        1.1    tsubai 
    384        1.1    tsubai 	bmac_write_reg(sc, INTDISABLE, NormalIntEvents);
    385        1.1    tsubai 
    386        1.1    tsubai 	ifp->if_flags |= IFF_RUNNING;
    387        1.1    tsubai 	ifp->if_flags &= ~IFF_OACTIVE;
    388        1.1    tsubai 	ifp->if_timer = 0;
    389        1.1    tsubai 
    390        1.1    tsubai 	data = sc->sc_txbuf;
    391        1.1    tsubai 	eh = (struct ether_header *)data;
    392        1.1    tsubai 
    393       1.16       wiz 	memset(data, 0, sizeof(eh) + ETHERMIN);
    394       1.16       wiz 	memcpy(eh->ether_dhost, sc->sc_enaddr, ETHER_ADDR_LEN);
    395       1.16       wiz 	memcpy(eh->ether_shost, sc->sc_enaddr, ETHER_ADDR_LEN);
    396        1.1    tsubai 	bmac_transmit_packet(sc, data, sizeof(eh) + ETHERMIN);
    397        1.1    tsubai 
    398        1.1    tsubai 	bmac_start(ifp);
    399        1.4    tsubai 
    400        1.7   thorpej 	callout_reset(&sc->sc_tick_ch, hz, bmac_mii_tick, sc);
    401        1.1    tsubai }
    402        1.1    tsubai 
    403        1.1    tsubai void
    404        1.1    tsubai bmac_init_dma(sc)
    405        1.1    tsubai 	struct bmac_softc *sc;
    406        1.1    tsubai {
    407        1.1    tsubai 	dbdma_command_t *cmd = sc->sc_rxcmd;
    408        1.1    tsubai 	int i;
    409        1.1    tsubai 
    410        1.1    tsubai 	dbdma_reset(sc->sc_txdma);
    411        1.1    tsubai 	dbdma_reset(sc->sc_rxdma);
    412        1.1    tsubai 
    413       1.16       wiz 	memset(sc->sc_txcmd, 0, BMAC_TXBUFS * sizeof(dbdma_command_t));
    414       1.16       wiz 	memset(sc->sc_rxcmd, 0, (BMAC_RXBUFS + 1) * sizeof(dbdma_command_t));
    415        1.1    tsubai 
    416        1.1    tsubai 	for (i = 0; i < BMAC_RXBUFS; i++) {
    417        1.1    tsubai 		DBDMA_BUILD(cmd, DBDMA_CMD_IN_LAST, 0, BMAC_BUFLEN,
    418        1.8    tsubai 			vtophys((vaddr_t)sc->sc_rxbuf + BMAC_BUFLEN * i),
    419        1.1    tsubai 			DBDMA_INT_ALWAYS, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
    420        1.1    tsubai 		cmd++;
    421        1.1    tsubai 	}
    422        1.1    tsubai 	DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 0,
    423        1.1    tsubai 		DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS);
    424  1.31.10.2   garbled 	out32rb(&cmd->d_cmddep, vtophys((vaddr_t)sc->sc_rxcmd));
    425        1.1    tsubai 
    426        1.1    tsubai 	sc->sc_rxlast = 0;
    427        1.1    tsubai 
    428        1.1    tsubai 	dbdma_start(sc->sc_rxdma, sc->sc_rxcmd);
    429        1.1    tsubai }
    430        1.1    tsubai 
    431        1.1    tsubai int
    432        1.1    tsubai bmac_intr(v)
    433        1.1    tsubai 	void *v;
    434        1.1    tsubai {
    435        1.1    tsubai 	struct bmac_softc *sc = v;
    436        1.1    tsubai 	int stat;
    437        1.1    tsubai 
    438        1.1    tsubai 	stat = bmac_read_reg(sc, STATUS);
    439        1.1    tsubai 	if (stat == 0)
    440        1.1    tsubai 		return 0;
    441        1.1    tsubai 
    442        1.1    tsubai #ifdef BMAC_DEBUG
    443        1.1    tsubai 	printf("bmac_intr status = 0x%x\n", stat);
    444        1.1    tsubai #endif
    445        1.1    tsubai 
    446        1.1    tsubai 	if (stat & IntFrameSent) {
    447        1.1    tsubai 		sc->sc_if.if_flags &= ~IFF_OACTIVE;
    448        1.1    tsubai 		sc->sc_if.if_timer = 0;
    449        1.1    tsubai 		sc->sc_if.if_opackets++;
    450        1.1    tsubai 		bmac_start(&sc->sc_if);
    451        1.1    tsubai 	}
    452        1.1    tsubai 
    453        1.1    tsubai 	/* XXX should do more! */
    454        1.1    tsubai 
    455        1.1    tsubai 	return 1;
    456        1.1    tsubai }
    457        1.1    tsubai 
    458        1.1    tsubai int
    459        1.1    tsubai bmac_rint(v)
    460        1.1    tsubai 	void *v;
    461        1.1    tsubai {
    462        1.1    tsubai 	struct bmac_softc *sc = v;
    463        1.1    tsubai 	struct ifnet *ifp = &sc->sc_if;
    464        1.1    tsubai 	struct mbuf *m;
    465        1.1    tsubai 	dbdma_command_t *cmd;
    466        1.1    tsubai 	int status, resid, count, datalen;
    467        1.1    tsubai 	int i, n;
    468        1.1    tsubai 	void *data;
    469        1.1    tsubai 
    470        1.1    tsubai 	i = sc->sc_rxlast;
    471        1.1    tsubai 	for (n = 0; n < BMAC_RXBUFS; n++, i++) {
    472        1.1    tsubai 		if (i == BMAC_RXBUFS)
    473        1.1    tsubai 			i = 0;
    474        1.1    tsubai 		cmd = &sc->sc_rxcmd[i];
    475  1.31.10.2   garbled 		status = in16rb(&cmd->d_status);
    476  1.31.10.2   garbled 		resid = in16rb(&cmd->d_resid);
    477        1.1    tsubai 
    478        1.1    tsubai #ifdef BMAC_DEBUG
    479        1.1    tsubai 		if (status != 0 && status != 0x8440 && status != 0x9440)
    480        1.1    tsubai 			printf("bmac_rint status = 0x%x\n", status);
    481        1.1    tsubai #endif
    482        1.1    tsubai 
    483        1.1    tsubai 		if ((status & DBDMA_CNTRL_ACTIVE) == 0)	/* 0x9440 | 0x8440 */
    484        1.1    tsubai 			continue;
    485  1.31.10.2   garbled 		count = in16rb(&cmd->d_count);
    486       1.12    tsubai 		datalen = count - resid - 2;		/* 2 == framelen */
    487        1.1    tsubai 		if (datalen < sizeof(struct ether_header)) {
    488        1.1    tsubai 			printf("%s: short packet len = %d\n",
    489        1.1    tsubai 				ifp->if_xname, datalen);
    490        1.1    tsubai 			goto next;
    491        1.1    tsubai 		}
    492        1.1    tsubai 		DBDMA_BUILD_CMD(cmd, DBDMA_CMD_STOP, 0, 0, 0, 0);
    493       1.31  macallan 		data = (char *)sc->sc_rxbuf + BMAC_BUFLEN * i;
    494       1.12    tsubai 
    495       1.12    tsubai 		/* XXX Sometimes bmac reads one extra byte. */
    496       1.12    tsubai 		if (datalen == ETHER_MAX_LEN + 1)
    497       1.12    tsubai 			datalen--;
    498       1.25   thorpej 
    499       1.25   thorpej 		/* Trim the CRC. */
    500       1.25   thorpej 		datalen -= ETHER_CRC_LEN;
    501       1.25   thorpej 
    502        1.1    tsubai 		m = bmac_get(sc, data, datalen);
    503        1.1    tsubai 		if (m == NULL) {
    504        1.1    tsubai 			ifp->if_ierrors++;
    505        1.1    tsubai 			goto next;
    506        1.1    tsubai 		}
    507        1.1    tsubai 
    508        1.1    tsubai #if NBPFILTER > 0
    509        1.1    tsubai 		/*
    510        1.1    tsubai 		 * Check if there's a BPF listener on this interface.
    511        1.1    tsubai 		 * If so, hand off the raw packet to BPF.
    512        1.1    tsubai 		 */
    513        1.1    tsubai 		if (ifp->if_bpf)
    514        1.1    tsubai 			bpf_mtap(ifp->if_bpf, m);
    515        1.1    tsubai #endif
    516        1.2   thorpej 		(*ifp->if_input)(ifp, m);
    517        1.1    tsubai 		ifp->if_ipackets++;
    518        1.1    tsubai 
    519        1.1    tsubai next:
    520        1.1    tsubai 		DBDMA_BUILD_CMD(cmd, DBDMA_CMD_IN_LAST, 0, DBDMA_INT_ALWAYS,
    521        1.1    tsubai 			DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
    522        1.1    tsubai 
    523        1.1    tsubai 		cmd->d_status = 0;
    524        1.1    tsubai 		cmd->d_resid = 0;
    525        1.1    tsubai 		sc->sc_rxlast = i + 1;
    526        1.1    tsubai 	}
    527       1.29     jklos 	bmac_mediachange(ifp);
    528       1.29     jklos 
    529        1.1    tsubai 	dbdma_continue(sc->sc_rxdma);
    530        1.1    tsubai 
    531        1.1    tsubai 	return 1;
    532        1.1    tsubai }
    533        1.1    tsubai 
    534        1.1    tsubai void
    535        1.1    tsubai bmac_reset(sc)
    536        1.1    tsubai 	struct bmac_softc *sc;
    537        1.1    tsubai {
    538        1.1    tsubai 	int s;
    539        1.1    tsubai 
    540        1.1    tsubai 	s = splnet();
    541        1.1    tsubai 	bmac_init(sc);
    542        1.1    tsubai 	splx(s);
    543        1.1    tsubai }
    544        1.1    tsubai 
    545        1.1    tsubai void
    546        1.1    tsubai bmac_stop(sc)
    547        1.1    tsubai 	struct bmac_softc *sc;
    548        1.1    tsubai {
    549        1.1    tsubai 	struct ifnet *ifp = &sc->sc_if;
    550        1.1    tsubai 	int s;
    551        1.1    tsubai 
    552        1.1    tsubai 	s = splnet();
    553        1.1    tsubai 
    554        1.7   thorpej 	callout_stop(&sc->sc_tick_ch);
    555        1.4    tsubai 	mii_down(&sc->sc_mii);
    556        1.4    tsubai 
    557        1.1    tsubai 	/* Disable TX/RX. */
    558        1.1    tsubai 	bmac_reset_bits(sc, TXCFG, TxMACEnable);
    559        1.1    tsubai 	bmac_reset_bits(sc, RXCFG, RxMACEnable);
    560        1.1    tsubai 
    561        1.1    tsubai 	/* Disable all interrupts. */
    562        1.1    tsubai 	bmac_write_reg(sc, INTDISABLE, NoEventsMask);
    563        1.1    tsubai 
    564        1.1    tsubai 	dbdma_stop(sc->sc_txdma);
    565        1.1    tsubai 	dbdma_stop(sc->sc_rxdma);
    566        1.1    tsubai 
    567        1.1    tsubai 	ifp->if_flags &= ~(IFF_UP | IFF_RUNNING);
    568        1.1    tsubai 	ifp->if_timer = 0;
    569        1.1    tsubai 
    570        1.1    tsubai 	splx(s);
    571        1.1    tsubai }
    572        1.1    tsubai 
    573        1.1    tsubai void
    574        1.1    tsubai bmac_start(ifp)
    575        1.1    tsubai 	struct ifnet *ifp;
    576        1.1    tsubai {
    577        1.1    tsubai 	struct bmac_softc *sc = ifp->if_softc;
    578        1.1    tsubai 	struct mbuf *m;
    579        1.1    tsubai 	int tlen;
    580        1.1    tsubai 
    581        1.1    tsubai 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
    582        1.1    tsubai 		return;
    583        1.1    tsubai 
    584        1.1    tsubai 	while (1) {
    585        1.1    tsubai 		if (ifp->if_flags & IFF_OACTIVE)
    586        1.1    tsubai 			return;
    587        1.1    tsubai 
    588       1.17    itojun 		IFQ_DEQUEUE(&ifp->if_snd, m);
    589        1.1    tsubai 		if (m == 0)
    590        1.1    tsubai 			break;
    591        1.1    tsubai #if NBPFILTER > 0
    592        1.1    tsubai 		/*
    593        1.1    tsubai 		 * If BPF is listening on this interface, let it see the
    594        1.1    tsubai 		 * packet before we commit it to the wire.
    595        1.1    tsubai 		 */
    596        1.1    tsubai 		if (ifp->if_bpf)
    597        1.1    tsubai 			bpf_mtap(ifp->if_bpf, m);
    598        1.1    tsubai #endif
    599        1.1    tsubai 
    600        1.1    tsubai 		ifp->if_flags |= IFF_OACTIVE;
    601        1.1    tsubai 		tlen = bmac_put(sc, sc->sc_txbuf, m);
    602        1.1    tsubai 
    603        1.1    tsubai 		/* 5 seconds to watch for failing to transmit */
    604        1.1    tsubai 		ifp->if_timer = 5;
    605        1.1    tsubai 		ifp->if_opackets++;		/* # of pkts */
    606        1.1    tsubai 
    607        1.1    tsubai 		bmac_transmit_packet(sc, sc->sc_txbuf, tlen);
    608        1.1    tsubai 	}
    609        1.1    tsubai }
    610        1.1    tsubai 
    611        1.1    tsubai void
    612        1.1    tsubai bmac_transmit_packet(sc, buff, len)
    613        1.1    tsubai 	struct bmac_softc *sc;
    614        1.1    tsubai 	void *buff;
    615        1.1    tsubai 	int len;
    616        1.1    tsubai {
    617        1.1    tsubai 	dbdma_command_t *cmd = sc->sc_txcmd;
    618        1.1    tsubai 	vaddr_t va = (vaddr_t)buff;
    619        1.1    tsubai 
    620        1.1    tsubai #ifdef BMAC_DEBUG
    621        1.1    tsubai 	if (vtophys(va) + len - 1 != vtophys(va + len - 1))
    622        1.1    tsubai 		panic("bmac_transmit_packet");
    623        1.1    tsubai #endif
    624        1.1    tsubai 
    625        1.1    tsubai 	DBDMA_BUILD(cmd, DBDMA_CMD_OUT_LAST, 0, len, vtophys(va),
    626        1.1    tsubai 		DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
    627        1.1    tsubai 	cmd++;
    628        1.1    tsubai 	DBDMA_BUILD(cmd, DBDMA_CMD_STOP, 0, 0, 0,
    629        1.1    tsubai 		DBDMA_INT_ALWAYS, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
    630        1.1    tsubai 
    631        1.1    tsubai 	dbdma_start(sc->sc_txdma, sc->sc_txcmd);
    632        1.1    tsubai }
    633        1.1    tsubai 
    634        1.1    tsubai int
    635        1.1    tsubai bmac_put(sc, buff, m)
    636        1.1    tsubai 	struct bmac_softc *sc;
    637       1.30  christos 	void *buff;
    638        1.1    tsubai 	struct mbuf *m;
    639        1.1    tsubai {
    640        1.1    tsubai 	struct mbuf *n;
    641        1.1    tsubai 	int len, tlen = 0;
    642        1.1    tsubai 
    643        1.1    tsubai 	for (; m; m = n) {
    644        1.1    tsubai 		len = m->m_len;
    645        1.1    tsubai 		if (len == 0) {
    646        1.1    tsubai 			MFREE(m, n);
    647        1.1    tsubai 			continue;
    648        1.1    tsubai 		}
    649       1.30  christos 		memcpy(buff, mtod(m, void *), len);
    650       1.31  macallan 		buff = (char *)buff + len;
    651        1.1    tsubai 		tlen += len;
    652        1.1    tsubai 		MFREE(m, n);
    653        1.1    tsubai 	}
    654       1.20   thorpej 	if (tlen > PAGE_SIZE)
    655        1.1    tsubai 		panic("%s: putpacket packet overflow", sc->sc_dev.dv_xname);
    656        1.1    tsubai 
    657        1.1    tsubai 	return tlen;
    658        1.1    tsubai }
    659        1.1    tsubai 
    660        1.1    tsubai struct mbuf *
    661        1.1    tsubai bmac_get(sc, pkt, totlen)
    662        1.1    tsubai 	struct bmac_softc *sc;
    663       1.30  christos 	void *pkt;
    664        1.1    tsubai 	int totlen;
    665        1.1    tsubai {
    666        1.1    tsubai 	struct mbuf *m;
    667        1.1    tsubai 	struct mbuf *top, **mp;
    668        1.1    tsubai 	int len;
    669        1.1    tsubai 
    670        1.1    tsubai 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    671        1.1    tsubai 	if (m == 0)
    672        1.1    tsubai 		return 0;
    673        1.1    tsubai 	m->m_pkthdr.rcvif = &sc->sc_if;
    674        1.1    tsubai 	m->m_pkthdr.len = totlen;
    675        1.1    tsubai 	len = MHLEN;
    676        1.1    tsubai 	top = 0;
    677        1.1    tsubai 	mp = &top;
    678        1.1    tsubai 
    679        1.1    tsubai 	while (totlen > 0) {
    680        1.1    tsubai 		if (top) {
    681        1.1    tsubai 			MGET(m, M_DONTWAIT, MT_DATA);
    682        1.1    tsubai 			if (m == 0) {
    683        1.1    tsubai 				m_freem(top);
    684        1.1    tsubai 				return 0;
    685        1.1    tsubai 			}
    686        1.1    tsubai 			len = MLEN;
    687        1.1    tsubai 		}
    688        1.1    tsubai 		if (totlen >= MINCLSIZE) {
    689        1.1    tsubai 			MCLGET(m, M_DONTWAIT);
    690        1.1    tsubai 			if ((m->m_flags & M_EXT) == 0) {
    691        1.1    tsubai 				m_free(m);
    692        1.1    tsubai 				m_freem(top);
    693        1.1    tsubai 				return 0;
    694        1.1    tsubai 			}
    695        1.1    tsubai 			len = MCLBYTES;
    696        1.1    tsubai 		}
    697        1.1    tsubai 		m->m_len = len = min(totlen, len);
    698       1.30  christos 		memcpy(mtod(m, void *), pkt, len);
    699       1.31  macallan 		pkt = (char *)pkt + len;
    700        1.1    tsubai 		totlen -= len;
    701        1.1    tsubai 		*mp = m;
    702        1.1    tsubai 		mp = &m->m_next;
    703        1.1    tsubai 	}
    704        1.1    tsubai 
    705        1.1    tsubai 	return top;
    706        1.1    tsubai }
    707        1.1    tsubai 
    708        1.1    tsubai void
    709        1.1    tsubai bmac_watchdog(ifp)
    710        1.1    tsubai 	struct ifnet *ifp;
    711        1.1    tsubai {
    712        1.1    tsubai 	struct bmac_softc *sc = ifp->if_softc;
    713        1.1    tsubai 
    714        1.1    tsubai 	bmac_reset_bits(sc, RXCFG, RxMACEnable);
    715        1.1    tsubai 	bmac_reset_bits(sc, TXCFG, TxMACEnable);
    716        1.1    tsubai 
    717        1.1    tsubai 	printf("%s: device timeout\n", ifp->if_xname);
    718        1.1    tsubai 	ifp->if_oerrors++;
    719        1.1    tsubai 
    720        1.1    tsubai 	bmac_reset(sc);
    721        1.1    tsubai }
    722        1.1    tsubai 
    723        1.1    tsubai int
    724        1.1    tsubai bmac_ioctl(ifp, cmd, data)
    725        1.1    tsubai 	struct ifnet *ifp;
    726        1.1    tsubai 	u_long cmd;
    727       1.30  christos 	void *data;
    728        1.1    tsubai {
    729        1.1    tsubai 	struct bmac_softc *sc = ifp->if_softc;
    730        1.1    tsubai 	struct ifaddr *ifa = (struct ifaddr *)data;
    731        1.1    tsubai 	struct ifreq *ifr = (struct ifreq *)data;
    732        1.1    tsubai 	int s, error = 0;
    733        1.1    tsubai 
    734        1.1    tsubai 	s = splnet();
    735        1.1    tsubai 
    736        1.1    tsubai 	switch (cmd) {
    737        1.1    tsubai 
    738        1.1    tsubai 	case SIOCSIFADDR:
    739        1.1    tsubai 		ifp->if_flags |= IFF_UP;
    740        1.1    tsubai 
    741        1.1    tsubai 		switch (ifa->ifa_addr->sa_family) {
    742        1.1    tsubai #ifdef INET
    743        1.1    tsubai 		case AF_INET:
    744        1.1    tsubai 			bmac_init(sc);
    745        1.1    tsubai 			arp_ifinit(ifp, ifa);
    746        1.1    tsubai 			break;
    747        1.1    tsubai #endif
    748        1.1    tsubai 		default:
    749        1.1    tsubai 			bmac_init(sc);
    750        1.1    tsubai 			break;
    751        1.1    tsubai 		}
    752        1.1    tsubai 		break;
    753        1.1    tsubai 
    754        1.1    tsubai 	case SIOCSIFFLAGS:
    755        1.1    tsubai 		if ((ifp->if_flags & IFF_UP) == 0 &&
    756        1.1    tsubai 		    (ifp->if_flags & IFF_RUNNING) != 0) {
    757        1.1    tsubai 			/*
    758        1.1    tsubai 			 * If interface is marked down and it is running, then
    759        1.1    tsubai 			 * stop it.
    760        1.1    tsubai 			 */
    761        1.1    tsubai 			bmac_stop(sc);
    762        1.1    tsubai 			ifp->if_flags &= ~IFF_RUNNING;
    763        1.1    tsubai 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
    764        1.1    tsubai 		    (ifp->if_flags & IFF_RUNNING) == 0) {
    765        1.1    tsubai 			/*
    766        1.1    tsubai 			 * If interface is marked up and it is stopped, then
    767        1.1    tsubai 			 * start it.
    768        1.1    tsubai 			 */
    769        1.1    tsubai 			bmac_init(sc);
    770        1.1    tsubai 		} else {
    771        1.1    tsubai 			/*
    772        1.1    tsubai 			 * Reset the interface to pick up changes in any other
    773        1.1    tsubai 			 * flags that affect hardware registers.
    774        1.1    tsubai 			 */
    775        1.1    tsubai 			/*bmac_stop(sc);*/
    776        1.1    tsubai 			bmac_init(sc);
    777        1.1    tsubai 		}
    778        1.1    tsubai #ifdef BMAC_DEBUG
    779        1.1    tsubai 		if (ifp->if_flags & IFF_DEBUG)
    780        1.4    tsubai 			sc->sc_flags |= BMAC_DEBUGFLAG;
    781        1.1    tsubai #endif
    782        1.1    tsubai 		break;
    783        1.1    tsubai 
    784        1.1    tsubai 	case SIOCADDMULTI:
    785        1.1    tsubai 	case SIOCDELMULTI:
    786        1.1    tsubai 		error = (cmd == SIOCADDMULTI) ?
    787        1.1    tsubai 		    ether_addmulti(ifr, &sc->sc_ethercom) :
    788        1.1    tsubai 		    ether_delmulti(ifr, &sc->sc_ethercom);
    789        1.1    tsubai 
    790        1.1    tsubai 		if (error == ENETRESET) {
    791        1.1    tsubai 			/*
    792        1.1    tsubai 			 * Multicast list has changed; set the hardware filter
    793        1.1    tsubai 			 * accordingly.
    794        1.1    tsubai 			 */
    795       1.23   thorpej 			if (ifp->if_flags & IFF_RUNNING) {
    796       1.23   thorpej 				bmac_init(sc);
    797       1.23   thorpej 				bmac_setladrf(sc);
    798       1.23   thorpej 			}
    799        1.1    tsubai 			error = 0;
    800        1.1    tsubai 		}
    801        1.1    tsubai 		break;
    802        1.1    tsubai 
    803        1.1    tsubai 	case SIOCGIFMEDIA:
    804        1.1    tsubai 	case SIOCSIFMEDIA:
    805        1.4    tsubai 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
    806        1.1    tsubai 		break;
    807        1.1    tsubai 
    808        1.1    tsubai 	default:
    809        1.1    tsubai 		error = EINVAL;
    810        1.1    tsubai 	}
    811        1.1    tsubai 
    812        1.1    tsubai 	splx(s);
    813        1.1    tsubai 	return error;
    814        1.1    tsubai }
    815        1.1    tsubai 
    816        1.1    tsubai int
    817        1.1    tsubai bmac_mediachange(ifp)
    818        1.1    tsubai 	struct ifnet *ifp;
    819        1.1    tsubai {
    820        1.4    tsubai 	struct bmac_softc *sc = ifp->if_softc;
    821        1.4    tsubai 
    822        1.4    tsubai 	return mii_mediachg(&sc->sc_mii);
    823        1.1    tsubai }
    824        1.1    tsubai 
    825        1.1    tsubai void
    826        1.1    tsubai bmac_mediastatus(ifp, ifmr)
    827        1.1    tsubai 	struct ifnet *ifp;
    828        1.1    tsubai 	struct ifmediareq *ifmr;
    829        1.1    tsubai {
    830        1.4    tsubai 	struct bmac_softc *sc = ifp->if_softc;
    831        1.4    tsubai 
    832        1.4    tsubai 	mii_pollstat(&sc->sc_mii);
    833        1.1    tsubai 
    834        1.4    tsubai 	ifmr->ifm_status = sc->sc_mii.mii_media_status;
    835        1.4    tsubai 	ifmr->ifm_active = sc->sc_mii.mii_media_active;
    836        1.1    tsubai }
    837        1.1    tsubai 
    838        1.1    tsubai /*
    839        1.1    tsubai  * Set up the logical address filter.
    840        1.1    tsubai  */
    841        1.1    tsubai void
    842        1.1    tsubai bmac_setladrf(sc)
    843        1.1    tsubai 	struct bmac_softc *sc;
    844        1.1    tsubai {
    845        1.1    tsubai 	struct ifnet *ifp = &sc->sc_if;
    846        1.1    tsubai 	struct ether_multi *enm;
    847        1.1    tsubai 	struct ether_multistep step;
    848        1.1    tsubai 	u_int32_t crc;
    849        1.1    tsubai 	u_int16_t hash[4];
    850       1.11    tsubai 	int x;
    851        1.1    tsubai 
    852        1.1    tsubai 	/*
    853        1.1    tsubai 	 * Set up multicast address filter by passing all multicast addresses
    854        1.1    tsubai 	 * through a crc generator, and then using the high order 6 bits as an
    855        1.1    tsubai 	 * index into the 64 bit logical address filter.  The high order bit
    856        1.1    tsubai 	 * selects the word, while the rest of the bits select the bit within
    857        1.1    tsubai 	 * the word.
    858        1.1    tsubai 	 */
    859        1.1    tsubai 
    860        1.1    tsubai 	if (ifp->if_flags & IFF_PROMISC) {
    861        1.1    tsubai 		bmac_set_bits(sc, RXCFG, RxPromiscEnable);
    862        1.9    tsubai 		return;
    863        1.9    tsubai 	}
    864        1.9    tsubai 
    865        1.9    tsubai 	if (ifp->if_flags & IFF_ALLMULTI) {
    866        1.9    tsubai 		hash[3] = hash[2] = hash[1] = hash[0] = 0xffff;
    867        1.9    tsubai 		goto chipit;
    868        1.1    tsubai 	}
    869        1.1    tsubai 
    870        1.1    tsubai 	hash[3] = hash[2] = hash[1] = hash[0] = 0;
    871        1.9    tsubai 
    872        1.1    tsubai 	ETHER_FIRST_MULTI(step, &sc->sc_ethercom, enm);
    873        1.1    tsubai 	while (enm != NULL) {
    874       1.16       wiz 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
    875        1.1    tsubai 			/*
    876        1.1    tsubai 			 * We must listen to a range of multicast addresses.
    877        1.1    tsubai 			 * For now, just accept all multicasts, rather than
    878        1.1    tsubai 			 * trying to set only those filter bits needed to match
    879        1.1    tsubai 			 * the range.  (At this time, the only use of address
    880        1.1    tsubai 			 * ranges is for IP multicast routing, for which the
    881        1.1    tsubai 			 * range is big enough to require all bits set.)
    882        1.1    tsubai 			 */
    883        1.9    tsubai 			hash[3] = hash[2] = hash[1] = hash[0] = 0xffff;
    884        1.9    tsubai 			ifp->if_flags |= IFF_ALLMULTI;
    885        1.9    tsubai 			goto chipit;
    886        1.1    tsubai 		}
    887        1.1    tsubai 
    888        1.9    tsubai 		crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
    889        1.1    tsubai 
    890        1.1    tsubai 		/* Just want the 6 most significant bits. */
    891        1.1    tsubai 		crc >>= 26;
    892        1.1    tsubai 
    893        1.1    tsubai 		/* Set the corresponding bit in the filter. */
    894        1.1    tsubai 		hash[crc >> 4] |= 1 << (crc & 0xf);
    895        1.1    tsubai 
    896        1.1    tsubai 		ETHER_NEXT_MULTI(step, enm);
    897        1.1    tsubai 	}
    898        1.9    tsubai 
    899        1.1    tsubai 	ifp->if_flags &= ~IFF_ALLMULTI;
    900        1.1    tsubai 
    901        1.9    tsubai chipit:
    902        1.9    tsubai 	bmac_write_reg(sc, HASH0, hash[0]);
    903        1.9    tsubai 	bmac_write_reg(sc, HASH1, hash[1]);
    904        1.9    tsubai 	bmac_write_reg(sc, HASH2, hash[2]);
    905        1.9    tsubai 	bmac_write_reg(sc, HASH3, hash[3]);
    906       1.11    tsubai 	x = bmac_read_reg(sc, RXCFG);
    907       1.11    tsubai 	x &= ~RxPromiscEnable;
    908       1.11    tsubai 	x |= RxHashFilterEnable;
    909       1.11    tsubai 	bmac_write_reg(sc, RXCFG, x);
    910        1.4    tsubai }
    911        1.4    tsubai 
    912        1.4    tsubai int
    913        1.4    tsubai bmac_mii_readreg(dev, phy, reg)
    914        1.4    tsubai 	struct device *dev;
    915        1.4    tsubai 	int phy, reg;
    916        1.4    tsubai {
    917        1.4    tsubai 	return mii_bitbang_readreg(dev, &bmac_mbo, phy, reg);
    918        1.4    tsubai }
    919        1.4    tsubai 
    920        1.4    tsubai void
    921        1.4    tsubai bmac_mii_writereg(dev, phy, reg, val)
    922        1.4    tsubai 	struct device *dev;
    923        1.4    tsubai 	int phy, reg, val;
    924        1.4    tsubai {
    925        1.4    tsubai 	mii_bitbang_writereg(dev, &bmac_mbo, phy, reg, val);
    926        1.4    tsubai }
    927        1.4    tsubai 
    928        1.4    tsubai u_int32_t
    929        1.4    tsubai bmac_mbo_read(dev)
    930        1.4    tsubai 	struct device *dev;
    931        1.4    tsubai {
    932        1.4    tsubai 	struct bmac_softc *sc = (void *)dev;
    933        1.4    tsubai 
    934        1.4    tsubai 	return bmac_read_reg(sc, MIFCSR);
    935        1.4    tsubai }
    936        1.4    tsubai 
    937        1.4    tsubai void
    938        1.4    tsubai bmac_mbo_write(dev, val)
    939        1.4    tsubai 	struct device *dev;
    940        1.4    tsubai 	u_int32_t val;
    941        1.4    tsubai {
    942        1.4    tsubai 	struct bmac_softc *sc = (void *)dev;
    943        1.4    tsubai 
    944        1.4    tsubai 	bmac_write_reg(sc, MIFCSR, val);
    945        1.4    tsubai }
    946        1.4    tsubai 
    947        1.4    tsubai void
    948        1.4    tsubai bmac_mii_statchg(dev)
    949        1.4    tsubai 	struct device *dev;
    950        1.4    tsubai {
    951        1.4    tsubai 	struct bmac_softc *sc = (void *)dev;
    952        1.4    tsubai 	int x;
    953        1.4    tsubai 
    954        1.4    tsubai 	/* Update duplex mode in TX configuration */
    955        1.4    tsubai 	x = bmac_read_reg(sc, TXCFG);
    956        1.4    tsubai 	if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0)
    957        1.4    tsubai 		x |= TxFullDuplex;
    958        1.4    tsubai 	else
    959        1.4    tsubai 		x &= ~TxFullDuplex;
    960        1.4    tsubai 	bmac_write_reg(sc, TXCFG, x);
    961        1.4    tsubai 
    962        1.4    tsubai #ifdef BMAC_DEBUG
    963        1.4    tsubai 	printf("bmac_mii_statchg 0x%x\n",
    964        1.4    tsubai 		IFM_OPTIONS(sc->sc_mii.mii_media_active));
    965        1.4    tsubai #endif
    966        1.4    tsubai }
    967        1.4    tsubai 
    968        1.4    tsubai void
    969        1.4    tsubai bmac_mii_tick(v)
    970        1.4    tsubai 	void *v;
    971        1.4    tsubai {
    972        1.4    tsubai 	struct bmac_softc *sc = v;
    973        1.4    tsubai 	int s;
    974        1.4    tsubai 
    975        1.4    tsubai 	s = splnet();
    976        1.4    tsubai 	mii_tick(&sc->sc_mii);
    977        1.4    tsubai 	splx(s);
    978        1.4    tsubai 
    979        1.7   thorpej 	callout_reset(&sc->sc_tick_ch, hz, bmac_mii_tick, sc);
    980        1.1    tsubai }
    981