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