1*cf96265bSbluhm /* $OpenBSD: aic6915.c,v 1.25 2023/11/10 15:51:20 bluhm Exp $ */
22f5860a2Smartin /* $NetBSD: aic6915.c,v 1.15 2005/12/24 20:27:29 perry Exp $ */
32f5860a2Smartin
42f5860a2Smartin /*-
52f5860a2Smartin * Copyright (c) 2001 The NetBSD Foundation, Inc.
62f5860a2Smartin * All rights reserved.
72f5860a2Smartin *
82f5860a2Smartin * This code is derived from software contributed to The NetBSD Foundation
92f5860a2Smartin * by Jason R. Thorpe.
102f5860a2Smartin *
112f5860a2Smartin * Redistribution and use in source and binary forms, with or without
122f5860a2Smartin * modification, are permitted provided that the following conditions
132f5860a2Smartin * are met:
142f5860a2Smartin * 1. Redistributions of source code must retain the above copyright
152f5860a2Smartin * notice, this list of conditions and the following disclaimer.
162f5860a2Smartin * 2. Redistributions in binary form must reproduce the above copyright
172f5860a2Smartin * notice, this list of conditions and the following disclaimer in the
182f5860a2Smartin * documentation and/or other materials provided with the distribution.
192f5860a2Smartin *
202f5860a2Smartin * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
212f5860a2Smartin * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
222f5860a2Smartin * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
232f5860a2Smartin * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
242f5860a2Smartin * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
252f5860a2Smartin * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
262f5860a2Smartin * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
272f5860a2Smartin * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
282f5860a2Smartin * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
292f5860a2Smartin * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
302f5860a2Smartin * POSSIBILITY OF SUCH DAMAGE.
312f5860a2Smartin */
322f5860a2Smartin
332f5860a2Smartin /*
342f5860a2Smartin * Device driver for the Adaptec AIC-6915 (``Starfire'')
352f5860a2Smartin * 10/100 Ethernet controller.
362f5860a2Smartin */
372f5860a2Smartin
382f5860a2Smartin #include "bpfilter.h"
392f5860a2Smartin
402f5860a2Smartin #include <sys/param.h>
41a4adbbcbSmartin #include <sys/endian.h>
422f5860a2Smartin #include <sys/systm.h>
432f5860a2Smartin #include <sys/timeout.h>
442f5860a2Smartin #include <sys/mbuf.h>
452f5860a2Smartin #include <sys/malloc.h>
462f5860a2Smartin #include <sys/kernel.h>
472f5860a2Smartin #include <sys/socket.h>
482f5860a2Smartin #include <sys/ioctl.h>
492f5860a2Smartin #include <sys/errno.h>
502f5860a2Smartin #include <sys/device.h>
512f5860a2Smartin
522f5860a2Smartin #include <net/if.h>
532f5860a2Smartin #include <net/if_dl.h>
542f5860a2Smartin
552f5860a2Smartin #include <netinet/in.h>
562f5860a2Smartin #include <netinet/if_ether.h>
572f5860a2Smartin
582f5860a2Smartin #include <net/if_media.h>
592f5860a2Smartin
602f5860a2Smartin #if NBPFILTER > 0
612f5860a2Smartin #include <net/bpf.h>
622f5860a2Smartin #endif
632f5860a2Smartin
642f5860a2Smartin #include <machine/bus.h>
652f5860a2Smartin #include <machine/intr.h>
662f5860a2Smartin
672f5860a2Smartin #include <dev/mii/miivar.h>
682f5860a2Smartin
692f5860a2Smartin #include <dev/ic/aic6915.h>
702f5860a2Smartin
712f5860a2Smartin void sf_start(struct ifnet *);
722f5860a2Smartin void sf_watchdog(struct ifnet *);
732f5860a2Smartin int sf_ioctl(struct ifnet *, u_long, caddr_t);
742f5860a2Smartin int sf_init(struct ifnet *);
752f5860a2Smartin void sf_stop(struct ifnet *, int);
762f5860a2Smartin
772f5860a2Smartin void sf_txintr(struct sf_softc *);
782f5860a2Smartin void sf_rxintr(struct sf_softc *);
792f5860a2Smartin void sf_stats_update(struct sf_softc *);
802f5860a2Smartin
812f5860a2Smartin void sf_reset(struct sf_softc *);
822f5860a2Smartin void sf_macreset(struct sf_softc *);
832f5860a2Smartin void sf_rxdrain(struct sf_softc *);
842f5860a2Smartin int sf_add_rxbuf(struct sf_softc *, int);
852f5860a2Smartin uint8_t sf_read_eeprom(struct sf_softc *, int);
862f5860a2Smartin void sf_set_filter(struct sf_softc *);
872f5860a2Smartin
882f5860a2Smartin int sf_mii_read(struct device *, int, int);
892f5860a2Smartin void sf_mii_write(struct device *, int, int, int);
902f5860a2Smartin void sf_mii_statchg(struct device *);
912f5860a2Smartin
922f5860a2Smartin void sf_tick(void *);
932f5860a2Smartin
942f5860a2Smartin int sf_mediachange(struct ifnet *);
952f5860a2Smartin void sf_mediastatus(struct ifnet *, struct ifmediareq *);
962f5860a2Smartin
972f5860a2Smartin uint32_t sf_reg_read(struct sf_softc *, bus_addr_t);
982f5860a2Smartin void sf_reg_write(struct sf_softc *, bus_addr_t , uint32_t);
992f5860a2Smartin
1002f5860a2Smartin void sf_set_filter_perfect(struct sf_softc *, int , uint8_t *);
1012f5860a2Smartin void sf_set_filter_hash(struct sf_softc *, uint8_t *);
1022f5860a2Smartin
1032f5860a2Smartin struct cfdriver sf_cd = {
1042f5860a2Smartin NULL, "sf", DV_IFNET
1052f5860a2Smartin };
1062f5860a2Smartin
1072f5860a2Smartin #define sf_funcreg_read(sc, reg) \
1082f5860a2Smartin bus_space_read_4((sc)->sc_st, (sc)->sc_sh_func, (reg))
1092f5860a2Smartin #define sf_funcreg_write(sc, reg, val) \
1102f5860a2Smartin bus_space_write_4((sc)->sc_st, (sc)->sc_sh_func, (reg), (val))
1112f5860a2Smartin
1122f5860a2Smartin uint32_t
sf_reg_read(struct sf_softc * sc,bus_addr_t reg)1132f5860a2Smartin sf_reg_read(struct sf_softc *sc, bus_addr_t reg)
1142f5860a2Smartin {
1152f5860a2Smartin
1162f5860a2Smartin if (__predict_false(sc->sc_iomapped)) {
1172f5860a2Smartin bus_space_write_4(sc->sc_st, sc->sc_sh, SF_IndirectIoAccess,
1182f5860a2Smartin reg);
1192f5860a2Smartin return (bus_space_read_4(sc->sc_st, sc->sc_sh,
1202f5860a2Smartin SF_IndirectIoDataPort));
1212f5860a2Smartin }
1222f5860a2Smartin
1232f5860a2Smartin return (bus_space_read_4(sc->sc_st, sc->sc_sh, reg));
1242f5860a2Smartin }
1252f5860a2Smartin
1262f5860a2Smartin void
sf_reg_write(struct sf_softc * sc,bus_addr_t reg,uint32_t val)1272f5860a2Smartin sf_reg_write(struct sf_softc *sc, bus_addr_t reg, uint32_t val)
1282f5860a2Smartin {
1292f5860a2Smartin
1302f5860a2Smartin if (__predict_false(sc->sc_iomapped)) {
1312f5860a2Smartin bus_space_write_4(sc->sc_st, sc->sc_sh, SF_IndirectIoAccess,
1322f5860a2Smartin reg);
1332f5860a2Smartin bus_space_write_4(sc->sc_st, sc->sc_sh, SF_IndirectIoDataPort,
1342f5860a2Smartin val);
1352f5860a2Smartin return;
1362f5860a2Smartin }
1372f5860a2Smartin
1382f5860a2Smartin bus_space_write_4(sc->sc_st, sc->sc_sh, reg, val);
1392f5860a2Smartin }
1402f5860a2Smartin
1412f5860a2Smartin #define sf_genreg_read(sc, reg) \
1422f5860a2Smartin sf_reg_read((sc), (reg) + SF_GENREG_OFFSET)
1432f5860a2Smartin #define sf_genreg_write(sc, reg, val) \
1442f5860a2Smartin sf_reg_write((sc), (reg) + SF_GENREG_OFFSET, (val))
1452f5860a2Smartin
1462f5860a2Smartin /*
1472f5860a2Smartin * sf_attach:
1482f5860a2Smartin *
1492f5860a2Smartin * Attach a Starfire interface to the system.
1502f5860a2Smartin */
1512f5860a2Smartin void
sf_attach(struct sf_softc * sc)1522f5860a2Smartin sf_attach(struct sf_softc *sc)
1532f5860a2Smartin {
1542f5860a2Smartin struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1552f5860a2Smartin int i, rseg, error;
1562f5860a2Smartin bus_dma_segment_t seg;
1572f5860a2Smartin u_int8_t enaddr[ETHER_ADDR_LEN];
1582f5860a2Smartin
1592f5860a2Smartin timeout_set(&sc->sc_mii_timeout, sf_tick, sc);
1602f5860a2Smartin
1612f5860a2Smartin /*
1622f5860a2Smartin * If we're I/O mapped, the functional register handle is
1632f5860a2Smartin * the same as the base handle. If we're memory mapped,
1642f5860a2Smartin * carve off a chunk of the register space for the functional
1652f5860a2Smartin * registers, to save on arithmetic later.
1662f5860a2Smartin */
1672f5860a2Smartin if (sc->sc_iomapped)
1682f5860a2Smartin sc->sc_sh_func = sc->sc_sh;
1692f5860a2Smartin else {
1702f5860a2Smartin if ((error = bus_space_subregion(sc->sc_st, sc->sc_sh,
1712f5860a2Smartin SF_GENREG_OFFSET, SF_FUNCREG_SIZE, &sc->sc_sh_func)) != 0) {
1722f5860a2Smartin printf("%s: unable to sub-region functional "
1732f5860a2Smartin "registers, error = %d\n", sc->sc_dev.dv_xname,
1742f5860a2Smartin error);
1752f5860a2Smartin return;
1762f5860a2Smartin }
1772f5860a2Smartin }
1782f5860a2Smartin
1792f5860a2Smartin /*
1802f5860a2Smartin * Initialize the transmit threshold for this interface. The
1812f5860a2Smartin * manual describes the default as 4 * 16 bytes. We start out
1822f5860a2Smartin * at 10 * 16 bytes, to avoid a bunch of initial underruns on
1832f5860a2Smartin * several platforms.
1842f5860a2Smartin */
1852f5860a2Smartin sc->sc_txthresh = 10;
1862f5860a2Smartin
1872f5860a2Smartin /*
1882f5860a2Smartin * Allocate the control data structures, and create and load the
1892f5860a2Smartin * DMA map for it.
1902f5860a2Smartin */
1912f5860a2Smartin if ((error = bus_dmamem_alloc(sc->sc_dmat,
1922f5860a2Smartin sizeof(struct sf_control_data), PAGE_SIZE, 0, &seg, 1, &rseg,
1932f5860a2Smartin BUS_DMA_NOWAIT)) != 0) {
1942f5860a2Smartin printf("%s: unable to allocate control data, error = %d\n",
1952f5860a2Smartin sc->sc_dev.dv_xname, error);
1962f5860a2Smartin goto fail_0;
1972f5860a2Smartin }
1982f5860a2Smartin
1992f5860a2Smartin if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
2002f5860a2Smartin sizeof(struct sf_control_data), (caddr_t *)&sc->sc_control_data,
2012f5860a2Smartin BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
2022f5860a2Smartin printf("%s: unable to map control data, error = %d\n",
2032f5860a2Smartin sc->sc_dev.dv_xname, error);
2042f5860a2Smartin goto fail_1;
2052f5860a2Smartin }
2062f5860a2Smartin
2072f5860a2Smartin if ((error = bus_dmamap_create(sc->sc_dmat,
2082f5860a2Smartin sizeof(struct sf_control_data), 1,
2092f5860a2Smartin sizeof(struct sf_control_data), 0, BUS_DMA_NOWAIT,
2102f5860a2Smartin &sc->sc_cddmamap)) != 0) {
2112f5860a2Smartin printf("%s: unable to create control data DMA map, "
2122f5860a2Smartin "error = %d\n", sc->sc_dev.dv_xname, error);
2132f5860a2Smartin goto fail_2;
2142f5860a2Smartin }
2152f5860a2Smartin
2162f5860a2Smartin if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
2172f5860a2Smartin sc->sc_control_data, sizeof(struct sf_control_data), NULL,
2182f5860a2Smartin BUS_DMA_NOWAIT)) != 0) {
2192f5860a2Smartin printf("%s: unable to load control data DMA map, error = %d\n",
2202f5860a2Smartin sc->sc_dev.dv_xname, error);
2212f5860a2Smartin goto fail_3;
2222f5860a2Smartin }
2232f5860a2Smartin
2242f5860a2Smartin /*
2252f5860a2Smartin * Create the transmit buffer DMA maps.
2262f5860a2Smartin */
2272f5860a2Smartin for (i = 0; i < SF_NTXDESC; i++) {
2282f5860a2Smartin if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
2292f5860a2Smartin SF_NTXFRAGS, MCLBYTES, 0, BUS_DMA_NOWAIT,
2302f5860a2Smartin &sc->sc_txsoft[i].ds_dmamap)) != 0) {
2312f5860a2Smartin printf("%s: unable to create tx DMA map %d, "
2322f5860a2Smartin "error = %d\n", sc->sc_dev.dv_xname, i, error);
2332f5860a2Smartin goto fail_4;
2342f5860a2Smartin }
2352f5860a2Smartin }
2362f5860a2Smartin
2372f5860a2Smartin /*
2382f5860a2Smartin * Create the receive buffer DMA maps.
2392f5860a2Smartin */
2402f5860a2Smartin for (i = 0; i < SF_NRXDESC; i++) {
2412f5860a2Smartin if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
2422f5860a2Smartin MCLBYTES, 0, BUS_DMA_NOWAIT,
2432f5860a2Smartin &sc->sc_rxsoft[i].ds_dmamap)) != 0) {
2442f5860a2Smartin printf("%s: unable to create rx DMA map %d, "
2452f5860a2Smartin "error = %d\n", sc->sc_dev.dv_xname, i, error);
2462f5860a2Smartin goto fail_5;
2472f5860a2Smartin }
2482f5860a2Smartin }
2492f5860a2Smartin
2502f5860a2Smartin /*
2512f5860a2Smartin * Reset the chip to a known state.
2522f5860a2Smartin */
2532f5860a2Smartin sf_reset(sc);
2542f5860a2Smartin
2552f5860a2Smartin /*
2562f5860a2Smartin * Read the Ethernet address from the EEPROM.
2572f5860a2Smartin */
2582f5860a2Smartin for (i = 0; i < ETHER_ADDR_LEN; i++)
2592f5860a2Smartin enaddr[i] = sf_read_eeprom(sc, (15 + (ETHER_ADDR_LEN - 1)) - i);
2602f5860a2Smartin
2612f5860a2Smartin printf(", address %s\n", ether_sprintf(enaddr));
2622f5860a2Smartin
2632f5860a2Smartin #ifdef DEBUG
2642f5860a2Smartin if (sf_funcreg_read(sc, SF_PciDeviceConfig) & PDC_System64)
2652f5860a2Smartin printf("%s: 64-bit PCI slot detected\n", sc->sc_dev.dv_xname);
2662f5860a2Smartin #endif
2672f5860a2Smartin
2682f5860a2Smartin /*
2692f5860a2Smartin * Initialize our media structures and probe the MII.
2702f5860a2Smartin */
2712f5860a2Smartin sc->sc_mii.mii_ifp = ifp;
2722f5860a2Smartin sc->sc_mii.mii_readreg = sf_mii_read;
2732f5860a2Smartin sc->sc_mii.mii_writereg = sf_mii_write;
2742f5860a2Smartin sc->sc_mii.mii_statchg = sf_mii_statchg;
2752f5860a2Smartin ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, sf_mediachange,
2762f5860a2Smartin sf_mediastatus);
2772f5860a2Smartin mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
2782f5860a2Smartin MII_OFFSET_ANY, 0);
2792f5860a2Smartin if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
2802f5860a2Smartin ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
2812f5860a2Smartin ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
2822f5860a2Smartin } else
2832f5860a2Smartin ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
2842f5860a2Smartin bcopy(enaddr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
2852f5860a2Smartin bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
2862f5860a2Smartin ifp = &sc->sc_arpcom.ac_if;
2872f5860a2Smartin ifp->if_softc = sc;
2882f5860a2Smartin ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
2892f5860a2Smartin ifp->if_ioctl = sf_ioctl;
2902f5860a2Smartin ifp->if_start = sf_start;
2912f5860a2Smartin ifp->if_watchdog = sf_watchdog;
292*cf96265bSbluhm ifq_init_maxlen(&ifp->if_snd, SF_NTXDESC_MASK);
2932f5860a2Smartin
2942f5860a2Smartin /*
2952f5860a2Smartin * Attach the interface.
2962f5860a2Smartin */
2972f5860a2Smartin if_attach(ifp);
2982f5860a2Smartin ether_ifattach(ifp);
2992f5860a2Smartin return;
3002f5860a2Smartin
3012f5860a2Smartin /*
3022f5860a2Smartin * Free any resources we've allocated during the failed attach
3032f5860a2Smartin * attempt. Do this in reverse order an fall through.
3042f5860a2Smartin */
3052f5860a2Smartin fail_5:
3062f5860a2Smartin for (i = 0; i < SF_NRXDESC; i++) {
3072f5860a2Smartin if (sc->sc_rxsoft[i].ds_dmamap != NULL)
3082f5860a2Smartin bus_dmamap_destroy(sc->sc_dmat,
3092f5860a2Smartin sc->sc_rxsoft[i].ds_dmamap);
3102f5860a2Smartin }
3112f5860a2Smartin fail_4:
3122f5860a2Smartin for (i = 0; i < SF_NTXDESC; i++) {
3132f5860a2Smartin if (sc->sc_txsoft[i].ds_dmamap != NULL)
3142f5860a2Smartin bus_dmamap_destroy(sc->sc_dmat,
3152f5860a2Smartin sc->sc_txsoft[i].ds_dmamap);
3162f5860a2Smartin }
3172f5860a2Smartin bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
3182f5860a2Smartin fail_3:
3192f5860a2Smartin bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
3202f5860a2Smartin fail_2:
3212f5860a2Smartin bus_dmamem_unmap(sc->sc_dmat, (caddr_t) sc->sc_control_data,
3222f5860a2Smartin sizeof(struct sf_control_data));
3232f5860a2Smartin fail_1:
3242f5860a2Smartin bus_dmamem_free(sc->sc_dmat, &seg, rseg);
3252f5860a2Smartin fail_0:
3262f5860a2Smartin return;
3272f5860a2Smartin }
3282f5860a2Smartin
3292f5860a2Smartin /*
3302f5860a2Smartin * sf_start: [ifnet interface function]
3312f5860a2Smartin *
3322f5860a2Smartin * Start packet transmission on the interface.
3332f5860a2Smartin */
3342f5860a2Smartin void
sf_start(struct ifnet * ifp)3352f5860a2Smartin sf_start(struct ifnet *ifp)
3362f5860a2Smartin {
3372f5860a2Smartin struct sf_softc *sc = ifp->if_softc;
3382f5860a2Smartin struct mbuf *m0, *m;
3392f5860a2Smartin struct sf_txdesc0 *txd;
3402f5860a2Smartin struct sf_descsoft *ds;
3412f5860a2Smartin bus_dmamap_t dmamap;
3422f5860a2Smartin int error, producer, last = -1, opending, seg;
3432f5860a2Smartin
3442f5860a2Smartin /*
3452f5860a2Smartin * Remember the previous number of pending transmits.
3462f5860a2Smartin */
3472f5860a2Smartin opending = sc->sc_txpending;
3482f5860a2Smartin
3492f5860a2Smartin /*
3502f5860a2Smartin * Find out where we're sitting.
3512f5860a2Smartin */
3522f5860a2Smartin producer = SF_TXDINDEX_TO_HOST(
3532f5860a2Smartin TDQPI_HiPrTxProducerIndex_get(
3542f5860a2Smartin sf_funcreg_read(sc, SF_TxDescQueueProducerIndex)));
3552f5860a2Smartin
3562f5860a2Smartin /*
3572f5860a2Smartin * Loop through the send queue, setting up transmit descriptors
3582f5860a2Smartin * until we drain the queue, or use up all available transmit
3592f5860a2Smartin * descriptors. Leave a blank one at the end for sanity's sake.
3602f5860a2Smartin */
3612f5860a2Smartin while (sc->sc_txpending < (SF_NTXDESC - 1)) {
3622f5860a2Smartin /*
3632f5860a2Smartin * Grab a packet off the queue.
3642f5860a2Smartin */
365b5d83b91Sdlg m0 = ifq_deq_begin(&ifp->if_snd);
3662f5860a2Smartin if (m0 == NULL)
3672f5860a2Smartin break;
3682f5860a2Smartin m = NULL;
3692f5860a2Smartin
3702f5860a2Smartin /*
3712f5860a2Smartin * Get the transmit descriptor.
3722f5860a2Smartin */
3732f5860a2Smartin txd = &sc->sc_txdescs[producer];
3742f5860a2Smartin ds = &sc->sc_txsoft[producer];
3752f5860a2Smartin dmamap = ds->ds_dmamap;
3762f5860a2Smartin
3772f5860a2Smartin /*
3782f5860a2Smartin * Load the DMA map. If this fails, the packet either
3792f5860a2Smartin * didn't fit in the allotted number of frags, or we were
3802f5860a2Smartin * short on resources. In this case, we'll copy and try
3812f5860a2Smartin * again.
3822f5860a2Smartin */
3832f5860a2Smartin if (bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
3842f5860a2Smartin BUS_DMA_WRITE|BUS_DMA_NOWAIT) != 0) {
3852f5860a2Smartin MGETHDR(m, M_DONTWAIT, MT_DATA);
3862f5860a2Smartin if (m == NULL) {
387b5d83b91Sdlg ifq_deq_rollback(&ifp->if_snd, m0);
3882f5860a2Smartin printf("%s: unable to allocate Tx mbuf\n",
3892f5860a2Smartin sc->sc_dev.dv_xname);
3902f5860a2Smartin break;
3912f5860a2Smartin }
3922f5860a2Smartin if (m0->m_pkthdr.len > MHLEN) {
3932f5860a2Smartin MCLGET(m, M_DONTWAIT);
3942f5860a2Smartin if ((m->m_flags & M_EXT) == 0) {
395b5d83b91Sdlg ifq_deq_rollback(&ifp->if_snd, m0);
3962f5860a2Smartin printf("%s: unable to allocate Tx "
3972f5860a2Smartin "cluster\n", sc->sc_dev.dv_xname);
3982f5860a2Smartin m_freem(m);
3992f5860a2Smartin break;
4002f5860a2Smartin }
4012f5860a2Smartin }
4022f5860a2Smartin m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
4032f5860a2Smartin m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
4042f5860a2Smartin error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap,
4052f5860a2Smartin m, BUS_DMA_WRITE|BUS_DMA_NOWAIT);
4062f5860a2Smartin if (error) {
407b5d83b91Sdlg ifq_deq_rollback(&ifp->if_snd, m0);
4082f5860a2Smartin printf("%s: unable to load Tx buffer, "
4092f5860a2Smartin "error = %d\n", sc->sc_dev.dv_xname, error);
410657454b1Sjsg m_freem(m);
4112f5860a2Smartin break;
4122f5860a2Smartin }
4132f5860a2Smartin }
4142f5860a2Smartin
4152f5860a2Smartin /*
4162f5860a2Smartin * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
4172f5860a2Smartin */
418b5d83b91Sdlg ifq_deq_commit(&ifp->if_snd, m0);
4192f5860a2Smartin if (m != NULL) {
4202f5860a2Smartin m_freem(m0);
4212f5860a2Smartin m0 = m;
4222f5860a2Smartin }
4232f5860a2Smartin
4242f5860a2Smartin /* Initialize the descriptor. */
4252f5860a2Smartin txd->td_word0 =
4262f5860a2Smartin htole32(TD_W0_ID | TD_W0_CRCEN | m0->m_pkthdr.len);
4272f5860a2Smartin if (producer == (SF_NTXDESC - 1))
4282f5860a2Smartin txd->td_word0 |= TD_W0_END;
4292f5860a2Smartin txd->td_word1 = htole32(dmamap->dm_nsegs);
4302f5860a2Smartin for (seg = 0; seg < dmamap->dm_nsegs; seg++) {
4312f5860a2Smartin txd->td_frags[seg].fr_addr =
4322f5860a2Smartin htole32(dmamap->dm_segs[seg].ds_addr);
4332f5860a2Smartin txd->td_frags[seg].fr_len =
4342f5860a2Smartin htole32(dmamap->dm_segs[seg].ds_len);
4352f5860a2Smartin }
4362f5860a2Smartin
4372f5860a2Smartin /* Sync the descriptor and the DMA map. */
4382f5860a2Smartin SF_CDTXDSYNC(sc, producer, BUS_DMASYNC_PREWRITE);
4392f5860a2Smartin bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
4402f5860a2Smartin BUS_DMASYNC_PREWRITE);
4412f5860a2Smartin
4422f5860a2Smartin /*
4432f5860a2Smartin * Store a pointer to the packet so we can free it later.
4442f5860a2Smartin */
4452f5860a2Smartin ds->ds_mbuf = m0;
4462f5860a2Smartin
4472f5860a2Smartin /* Advance the Tx pointer. */
4482f5860a2Smartin sc->sc_txpending++;
4492f5860a2Smartin last = producer;
4502f5860a2Smartin producer = SF_NEXTTX(producer);
4512f5860a2Smartin
4522f5860a2Smartin #if NBPFILTER > 0
4532f5860a2Smartin /*
4542f5860a2Smartin * Pass the packet to any BPF listeners.
4552f5860a2Smartin */
4562f5860a2Smartin if (ifp->if_bpf)
4572f5860a2Smartin bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
4582f5860a2Smartin #endif
4592f5860a2Smartin }
4602f5860a2Smartin
4612f5860a2Smartin if (sc->sc_txpending == (SF_NTXDESC - 1)) {
4622f5860a2Smartin /* No more slots left; notify upper layer. */
463de6cd8fbSdlg ifq_set_oactive(&ifp->if_snd);
4642f5860a2Smartin }
4652f5860a2Smartin
4662f5860a2Smartin if (sc->sc_txpending != opending) {
4672f5860a2Smartin KASSERT(last != -1);
4682f5860a2Smartin /*
4692f5860a2Smartin * We enqueued packets. Cause a transmit interrupt to
4702f5860a2Smartin * happen on the last packet we enqueued, and give the
4712f5860a2Smartin * new descriptors to the chip by writing the new
4722f5860a2Smartin * producer index.
4732f5860a2Smartin */
4742f5860a2Smartin sc->sc_txdescs[last].td_word0 |= TD_W0_INTR;
4752f5860a2Smartin SF_CDTXDSYNC(sc, last, BUS_DMASYNC_PREWRITE);
4762f5860a2Smartin
4772f5860a2Smartin sf_funcreg_write(sc, SF_TxDescQueueProducerIndex,
4782f5860a2Smartin TDQPI_HiPrTxProducerIndex(SF_TXDINDEX_TO_CHIP(producer)));
4792f5860a2Smartin
4802f5860a2Smartin /* Set a watchdog timer in case the chip flakes out. */
4812f5860a2Smartin ifp->if_timer = 5;
4822f5860a2Smartin }
4832f5860a2Smartin }
4842f5860a2Smartin
4852f5860a2Smartin /*
4862f5860a2Smartin * sf_watchdog: [ifnet interface function]
4872f5860a2Smartin *
4882f5860a2Smartin * Watchdog timer handler.
4892f5860a2Smartin */
4902f5860a2Smartin void
sf_watchdog(struct ifnet * ifp)4912f5860a2Smartin sf_watchdog(struct ifnet *ifp)
4922f5860a2Smartin {
4932f5860a2Smartin struct sf_softc *sc = ifp->if_softc;
4942f5860a2Smartin
4952f5860a2Smartin printf("%s: device timeout\n", sc->sc_dev.dv_xname);
4962f5860a2Smartin ifp->if_oerrors++;
4972f5860a2Smartin
4982f5860a2Smartin (void) sf_init(ifp);
4992f5860a2Smartin
5002f5860a2Smartin /* Try to get more packets going. */
5012f5860a2Smartin sf_start(ifp);
5022f5860a2Smartin }
5032f5860a2Smartin
5042f5860a2Smartin /*
5052f5860a2Smartin * sf_ioctl: [ifnet interface function]
5062f5860a2Smartin *
5072f5860a2Smartin * Handle control requests from the operator.
5082f5860a2Smartin */
5092f5860a2Smartin int
sf_ioctl(struct ifnet * ifp,u_long cmd,caddr_t data)5102f5860a2Smartin sf_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
5112f5860a2Smartin {
5122f5860a2Smartin struct sf_softc *sc = (struct sf_softc *)ifp->if_softc;
5132f5860a2Smartin struct ifreq *ifr = (struct ifreq *) data;
51462e5525bSmartin int s, error = 0;
5152f5860a2Smartin
5162f5860a2Smartin s = splnet();
51762e5525bSmartin
5182f5860a2Smartin switch (cmd) {
5192f5860a2Smartin case SIOCSIFADDR:
5202f5860a2Smartin ifp->if_flags |= IFF_UP;
52162e5525bSmartin if (!(ifp->if_flags & IFF_RUNNING))
52262e5525bSmartin sf_init(ifp);
52362e5525bSmartin break;
52462e5525bSmartin
5252f5860a2Smartin case SIOCSIFFLAGS:
5262f5860a2Smartin if (ifp->if_flags & IFF_UP) {
52762e5525bSmartin if (ifp->if_flags & IFF_RUNNING &&
52862e5525bSmartin ((ifp->if_flags ^ sc->sc_flags) &
52962e5525bSmartin IFF_PROMISC)) {
5302f5860a2Smartin sf_set_filter(sc);
53162e5525bSmartin } else {
53262e5525bSmartin if (!(ifp->if_flags & IFF_RUNNING))
5332f5860a2Smartin sf_init(ifp);
53462e5525bSmartin }
5352f5860a2Smartin } else {
5362f5860a2Smartin if (ifp->if_flags & IFF_RUNNING)
5372f5860a2Smartin sf_stop(ifp, 1);
5382f5860a2Smartin }
53962e5525bSmartin sc->sc_flags = ifp->if_flags;
5402f5860a2Smartin break;
5412f5860a2Smartin
5422f5860a2Smartin case SIOCGIFMEDIA:
5432f5860a2Smartin case SIOCSIFMEDIA:
5442f5860a2Smartin error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
5452f5860a2Smartin break;
5462f5860a2Smartin
5472f5860a2Smartin default:
548775775feSbrad error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data);
5492f5860a2Smartin }
5502f5860a2Smartin
55134f0f0fdSbrad if (error == ENETRESET) {
55234f0f0fdSbrad if (ifp->if_flags & IFF_RUNNING)
55334f0f0fdSbrad sf_set_filter(sc);
55434f0f0fdSbrad error = 0;
55534f0f0fdSbrad }
55634f0f0fdSbrad
5572f5860a2Smartin /* Try to get more packets going. */
5582f5860a2Smartin sf_start(ifp);
5592f5860a2Smartin
5602f5860a2Smartin splx(s);
5612f5860a2Smartin return (error);
5622f5860a2Smartin }
5632f5860a2Smartin
5642f5860a2Smartin /*
5652f5860a2Smartin * sf_intr:
5662f5860a2Smartin *
5672f5860a2Smartin * Interrupt service routine.
5682f5860a2Smartin */
5692f5860a2Smartin int
sf_intr(void * arg)5702f5860a2Smartin sf_intr(void *arg)
5712f5860a2Smartin {
5722f5860a2Smartin struct sf_softc *sc = arg;
5732f5860a2Smartin uint32_t isr;
5742f5860a2Smartin int handled = 0, wantinit = 0;
5752f5860a2Smartin
5762f5860a2Smartin for (;;) {
5772f5860a2Smartin /* Reading clears all interrupts we're interested in. */
5782f5860a2Smartin isr = sf_funcreg_read(sc, SF_InterruptStatus);
5792f5860a2Smartin if ((isr & IS_PCIPadInt) == 0)
5802f5860a2Smartin break;
5812f5860a2Smartin
5822f5860a2Smartin handled = 1;
5832f5860a2Smartin
5842f5860a2Smartin /* Handle receive interrupts. */
5852f5860a2Smartin if (isr & IS_RxQ1DoneInt)
5862f5860a2Smartin sf_rxintr(sc);
5872f5860a2Smartin
5882f5860a2Smartin /* Handle transmit completion interrupts. */
5892f5860a2Smartin if (isr & (IS_TxDmaDoneInt|IS_TxQueueDoneInt))
5902f5860a2Smartin sf_txintr(sc);
5912f5860a2Smartin
5922f5860a2Smartin /* Handle abnormal interrupts. */
5932f5860a2Smartin if (isr & IS_AbnormalInterrupt) {
5942f5860a2Smartin /* Statistics. */
5952f5860a2Smartin if (isr & IS_StatisticWrapInt)
5962f5860a2Smartin sf_stats_update(sc);
5972f5860a2Smartin
5982f5860a2Smartin /* DMA errors. */
5992f5860a2Smartin if (isr & IS_DmaErrInt) {
6002f5860a2Smartin wantinit = 1;
6012f5860a2Smartin printf("%s: WARNING: DMA error\n",
6022f5860a2Smartin sc->sc_dev.dv_xname);
6032f5860a2Smartin }
6042f5860a2Smartin
6052f5860a2Smartin /* Transmit FIFO underruns. */
6062f5860a2Smartin if (isr & IS_TxDataLowInt) {
6072f5860a2Smartin if (sc->sc_txthresh < 0xff)
6082f5860a2Smartin sc->sc_txthresh++;
6092f5860a2Smartin #ifdef DEBUG
6102f5860a2Smartin printf("%s: transmit FIFO underrun, new "
6112f5860a2Smartin "threshold: %d bytes\n",
6122f5860a2Smartin sc->sc_dev.dv_xname,
6132f5860a2Smartin sc->sc_txthresh * 16);
6142f5860a2Smartin #endif
6152f5860a2Smartin sf_funcreg_write(sc, SF_TransmitFrameCSR,
6162f5860a2Smartin sc->sc_TransmitFrameCSR |
6172f5860a2Smartin TFCSR_TransmitThreshold(sc->sc_txthresh));
6182f5860a2Smartin sf_funcreg_write(sc, SF_TxDescQueueCtrl,
6192f5860a2Smartin sc->sc_TxDescQueueCtrl |
6202f5860a2Smartin TDQC_TxHighPriorityFifoThreshold(
6212f5860a2Smartin sc->sc_txthresh));
6222f5860a2Smartin }
6232f5860a2Smartin }
6242f5860a2Smartin }
6252f5860a2Smartin
6262f5860a2Smartin if (handled) {
6272f5860a2Smartin /* Reset the interface, if necessary. */
6282f5860a2Smartin if (wantinit)
6292f5860a2Smartin sf_init(&sc->sc_arpcom.ac_if);
6302f5860a2Smartin
6312f5860a2Smartin /* Try and get more packets going. */
6322f5860a2Smartin sf_start(&sc->sc_arpcom.ac_if);
6332f5860a2Smartin }
6342f5860a2Smartin
6352f5860a2Smartin return (handled);
6362f5860a2Smartin }
6372f5860a2Smartin
6382f5860a2Smartin /*
6392f5860a2Smartin * sf_txintr:
6402f5860a2Smartin *
6412f5860a2Smartin * Helper -- handle transmit completion interrupts.
6422f5860a2Smartin */
6432f5860a2Smartin void
sf_txintr(struct sf_softc * sc)6442f5860a2Smartin sf_txintr(struct sf_softc *sc)
6452f5860a2Smartin {
6462f5860a2Smartin struct ifnet *ifp = &sc->sc_arpcom.ac_if;
6472f5860a2Smartin struct sf_descsoft *ds;
6482f5860a2Smartin uint32_t cqci, tcd;
6492f5860a2Smartin int consumer, producer, txidx;
6502f5860a2Smartin
6512f5860a2Smartin try_again:
6522f5860a2Smartin cqci = sf_funcreg_read(sc, SF_CompletionQueueConsumerIndex);
6532f5860a2Smartin
6542f5860a2Smartin consumer = CQCI_TxCompletionConsumerIndex_get(cqci);
6552f5860a2Smartin producer = CQPI_TxCompletionProducerIndex_get(
6562f5860a2Smartin sf_funcreg_read(sc, SF_CompletionQueueProducerIndex));
6572f5860a2Smartin
6582f5860a2Smartin if (consumer == producer)
6592f5860a2Smartin return;
6602f5860a2Smartin
661de6cd8fbSdlg ifq_clr_oactive(&ifp->if_snd);
6622f5860a2Smartin
6632f5860a2Smartin while (consumer != producer) {
6642f5860a2Smartin SF_CDTXCSYNC(sc, consumer, BUS_DMASYNC_POSTREAD);
6652f5860a2Smartin tcd = letoh32(sc->sc_txcomp[consumer].tcd_word0);
6662f5860a2Smartin
6672f5860a2Smartin txidx = SF_TCD_INDEX_TO_HOST(TCD_INDEX(tcd));
6682f5860a2Smartin #ifdef DIAGNOSTIC
6692f5860a2Smartin if ((tcd & TCD_PR) == 0)
6702f5860a2Smartin printf("%s: Tx queue mismatch, index %d\n",
6712f5860a2Smartin sc->sc_dev.dv_xname, txidx);
6722f5860a2Smartin #endif
6732f5860a2Smartin /*
6742f5860a2Smartin * NOTE: stats are updated later. We're just
6752f5860a2Smartin * releasing packets that have been DMA'd to
6762f5860a2Smartin * the chip.
6772f5860a2Smartin */
6782f5860a2Smartin ds = &sc->sc_txsoft[txidx];
6792f5860a2Smartin SF_CDTXDSYNC(sc, txidx, BUS_DMASYNC_POSTWRITE);
6802f5860a2Smartin bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap,
6812f5860a2Smartin 0, ds->ds_dmamap->dm_mapsize,
6822f5860a2Smartin BUS_DMASYNC_POSTWRITE);
6832f5860a2Smartin m_freem(ds->ds_mbuf);
6842f5860a2Smartin ds->ds_mbuf = NULL;
6852f5860a2Smartin
6862f5860a2Smartin consumer = SF_NEXTTCD(consumer);
6872f5860a2Smartin sc->sc_txpending--;
6882f5860a2Smartin }
6892f5860a2Smartin
6902f5860a2Smartin /* XXXJRT -- should be KDASSERT() */
6912f5860a2Smartin KASSERT(sc->sc_txpending >= 0);
6922f5860a2Smartin
6932f5860a2Smartin /* If all packets are done, cancel the watchdog timer. */
6942f5860a2Smartin if (sc->sc_txpending == 0)
6952f5860a2Smartin ifp->if_timer = 0;
6962f5860a2Smartin
6972f5860a2Smartin /* Update the consumer index. */
6982f5860a2Smartin sf_funcreg_write(sc, SF_CompletionQueueConsumerIndex,
6992f5860a2Smartin (cqci & ~CQCI_TxCompletionConsumerIndex(0x7ff)) |
7002f5860a2Smartin CQCI_TxCompletionConsumerIndex(consumer));
7012f5860a2Smartin
7022f5860a2Smartin /* Double check for new completions. */
7032f5860a2Smartin goto try_again;
7042f5860a2Smartin }
7052f5860a2Smartin
7062f5860a2Smartin /*
7072f5860a2Smartin * sf_rxintr:
7082f5860a2Smartin *
7092f5860a2Smartin * Helper -- handle receive interrupts.
7102f5860a2Smartin */
7112f5860a2Smartin void
sf_rxintr(struct sf_softc * sc)7122f5860a2Smartin sf_rxintr(struct sf_softc *sc)
7132f5860a2Smartin {
7142f5860a2Smartin struct ifnet *ifp = &sc->sc_arpcom.ac_if;
7152f5860a2Smartin struct sf_descsoft *ds;
7162f5860a2Smartin struct sf_rcd_full *rcd;
717cdea9bebSmpi struct mbuf_list ml = MBUF_LIST_INITIALIZER();
7182f5860a2Smartin struct mbuf *m;
7192f5860a2Smartin uint32_t cqci, word0;
7202f5860a2Smartin int consumer, producer, bufproducer, rxidx, len;
7212f5860a2Smartin
7222f5860a2Smartin cqci = sf_funcreg_read(sc, SF_CompletionQueueConsumerIndex);
7232f5860a2Smartin
7242f5860a2Smartin consumer = CQCI_RxCompletionQ1ConsumerIndex_get(cqci);
7252f5860a2Smartin producer = CQPI_RxCompletionQ1ProducerIndex_get(
7262f5860a2Smartin sf_funcreg_read(sc, SF_CompletionQueueProducerIndex));
7272f5860a2Smartin bufproducer = RXQ1P_RxDescQ1Producer_get(
7282f5860a2Smartin sf_funcreg_read(sc, SF_RxDescQueue1Ptrs));
7292f5860a2Smartin
7302f5860a2Smartin if (consumer == producer)
7312f5860a2Smartin return;
7322f5860a2Smartin
7332f5860a2Smartin while (consumer != producer) {
7342f5860a2Smartin rcd = &sc->sc_rxcomp[consumer];
7352f5860a2Smartin SF_CDRXCSYNC(sc, consumer,
7362f5860a2Smartin BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
7372f5860a2Smartin SF_CDRXCSYNC(sc, consumer,
7382f5860a2Smartin BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
7392f5860a2Smartin
7402f5860a2Smartin word0 = letoh32(rcd->rcd_word0);
7412f5860a2Smartin rxidx = RCD_W0_EndIndex(word0);
7422f5860a2Smartin
7432f5860a2Smartin ds = &sc->sc_rxsoft[rxidx];
7442f5860a2Smartin
7452f5860a2Smartin consumer = SF_NEXTRCD(consumer);
7462f5860a2Smartin bufproducer = SF_NEXTRX(bufproducer);
7472f5860a2Smartin
7482f5860a2Smartin if ((word0 & RCD_W0_OK) == 0) {
7492f5860a2Smartin SF_INIT_RXDESC(sc, rxidx);
7502f5860a2Smartin continue;
7512f5860a2Smartin }
7522f5860a2Smartin
7532f5860a2Smartin bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
7542f5860a2Smartin ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
7552f5860a2Smartin
7562f5860a2Smartin /*
7572f5860a2Smartin * No errors; receive the packet. Note that we have
7582f5860a2Smartin * configured the Starfire to NOT transfer the CRC
7592f5860a2Smartin * with the packet.
7602f5860a2Smartin */
7612f5860a2Smartin len = RCD_W0_Length(word0);
7622f5860a2Smartin
763a4adbbcbSmartin #ifndef __STRICT_ALIGNMENT
7642f5860a2Smartin /*
7652f5860a2Smartin * Allocate a new mbuf cluster. If that fails, we are
7662f5860a2Smartin * out of memory, and must drop the packet and recycle
7672f5860a2Smartin * the buffer that's already attached to this descriptor.
7682f5860a2Smartin */
7692f5860a2Smartin m = ds->ds_mbuf;
7702f5860a2Smartin if (sf_add_rxbuf(sc, rxidx) != 0) {
7712f5860a2Smartin ifp->if_ierrors++;
7722f5860a2Smartin SF_INIT_RXDESC(sc, rxidx);
7732f5860a2Smartin bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
7742f5860a2Smartin ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
7752f5860a2Smartin continue;
7762f5860a2Smartin }
7772f5860a2Smartin #else
7782f5860a2Smartin /*
7792f5860a2Smartin * The Starfire's receive buffer must be 4-byte aligned.
7802f5860a2Smartin * But this means that the data after the Ethernet header
7812f5860a2Smartin * is misaligned. We must allocate a new buffer and
7822f5860a2Smartin * copy the data, shifted forward 2 bytes.
7832f5860a2Smartin */
7842f5860a2Smartin MGETHDR(m, M_DONTWAIT, MT_DATA);
7852f5860a2Smartin if (m == NULL) {
7862f5860a2Smartin dropit:
7872f5860a2Smartin ifp->if_ierrors++;
7882f5860a2Smartin SF_INIT_RXDESC(sc, rxidx);
7892f5860a2Smartin bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
7902f5860a2Smartin ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
7912f5860a2Smartin continue;
7922f5860a2Smartin }
7932f5860a2Smartin if (len > (MHLEN - 2)) {
7942f5860a2Smartin MCLGET(m, M_DONTWAIT);
7952f5860a2Smartin if ((m->m_flags & M_EXT) == 0) {
7962f5860a2Smartin m_freem(m);
7972f5860a2Smartin goto dropit;
7982f5860a2Smartin }
7992f5860a2Smartin }
8002f5860a2Smartin m->m_data += 2;
8012f5860a2Smartin
8022f5860a2Smartin /*
8032f5860a2Smartin * Note that we use cluster for incoming frames, so the
8042f5860a2Smartin * buffer is virtually contiguous.
8052f5860a2Smartin */
8062f5860a2Smartin memcpy(mtod(m, caddr_t), mtod(ds->ds_mbuf, caddr_t), len);
8072f5860a2Smartin
8082f5860a2Smartin /* Allow the receive descriptor to continue using its mbuf. */
8092f5860a2Smartin SF_INIT_RXDESC(sc, rxidx);
8102f5860a2Smartin bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
8112f5860a2Smartin ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
812a4adbbcbSmartin #endif /* __STRICT_ALIGNMENT */
8132f5860a2Smartin
8142f5860a2Smartin m->m_pkthdr.len = m->m_len = len;
8152f5860a2Smartin
816cdea9bebSmpi ml_enqueue(&ml, m);
8172f5860a2Smartin }
8182f5860a2Smartin
819cdea9bebSmpi if_input(ifp, &ml);
820cdea9bebSmpi
8212f5860a2Smartin /* Update the chip's pointers. */
8222f5860a2Smartin sf_funcreg_write(sc, SF_CompletionQueueConsumerIndex,
8232f5860a2Smartin (cqci & ~CQCI_RxCompletionQ1ConsumerIndex(0x7ff)) |
8242f5860a2Smartin CQCI_RxCompletionQ1ConsumerIndex(consumer));
8252f5860a2Smartin sf_funcreg_write(sc, SF_RxDescQueue1Ptrs,
8262f5860a2Smartin RXQ1P_RxDescQ1Producer(bufproducer));
8272f5860a2Smartin }
8282f5860a2Smartin
8292f5860a2Smartin /*
8302f5860a2Smartin * sf_tick:
8312f5860a2Smartin *
8322f5860a2Smartin * One second timer, used to tick the MII and update stats.
8332f5860a2Smartin */
8342f5860a2Smartin void
sf_tick(void * arg)8352f5860a2Smartin sf_tick(void *arg)
8362f5860a2Smartin {
8372f5860a2Smartin struct sf_softc *sc = arg;
8382f5860a2Smartin int s;
8392f5860a2Smartin
8402f5860a2Smartin s = splnet();
8412f5860a2Smartin mii_tick(&sc->sc_mii);
8422f5860a2Smartin sf_stats_update(sc);
8432f5860a2Smartin splx(s);
8442f5860a2Smartin
845e15e1c8cSblambert timeout_add_sec(&sc->sc_mii_timeout, 1);
8462f5860a2Smartin }
8472f5860a2Smartin
8482f5860a2Smartin /*
8492f5860a2Smartin * sf_stats_update:
8502f5860a2Smartin *
8514b1a56afSjsg * Read the statistics counters.
8522f5860a2Smartin */
8532f5860a2Smartin void
sf_stats_update(struct sf_softc * sc)8542f5860a2Smartin sf_stats_update(struct sf_softc *sc)
8552f5860a2Smartin {
8562f5860a2Smartin struct sf_stats stats;
8572f5860a2Smartin struct ifnet *ifp = &sc->sc_arpcom.ac_if;
8582f5860a2Smartin uint32_t *p;
8592f5860a2Smartin u_int i;
8602f5860a2Smartin
8612f5860a2Smartin p = &stats.TransmitOKFrames;
8622f5860a2Smartin for (i = 0; i < (sizeof(stats) / sizeof(uint32_t)); i++) {
8632f5860a2Smartin *p++ = sf_genreg_read(sc,
8642f5860a2Smartin SF_STATS_BASE + (i * sizeof(uint32_t)));
8652f5860a2Smartin sf_genreg_write(sc, SF_STATS_BASE + (i * sizeof(uint32_t)), 0);
8662f5860a2Smartin }
8672f5860a2Smartin
8682f5860a2Smartin ifp->if_collisions += stats.SingleCollisionFrames +
8692f5860a2Smartin stats.MultipleCollisionFrames;
8702f5860a2Smartin
8712f5860a2Smartin ifp->if_oerrors += stats.TransmitAbortDueToExcessiveCollisions +
8722f5860a2Smartin stats.TransmitAbortDueToExcessingDeferral +
8732f5860a2Smartin stats.FramesLostDueToInternalTransmitErrors;
8742f5860a2Smartin
8752f5860a2Smartin ifp->if_ierrors += stats.ReceiveCRCErrors + stats.AlignmentErrors +
8762f5860a2Smartin stats.ReceiveFramesTooLong + stats.ReceiveFramesTooShort +
8772f5860a2Smartin stats.ReceiveFramesJabbersError +
8782f5860a2Smartin stats.FramesLostDueToInternalReceiveErrors;
8792f5860a2Smartin }
8802f5860a2Smartin
8812f5860a2Smartin /*
8822f5860a2Smartin * sf_reset:
8832f5860a2Smartin *
8842f5860a2Smartin * Perform a soft reset on the Starfire.
8852f5860a2Smartin */
8862f5860a2Smartin void
sf_reset(struct sf_softc * sc)8872f5860a2Smartin sf_reset(struct sf_softc *sc)
8882f5860a2Smartin {
8892f5860a2Smartin int i;
8902f5860a2Smartin
8912f5860a2Smartin sf_funcreg_write(sc, SF_GeneralEthernetCtrl, 0);
8922f5860a2Smartin
8932f5860a2Smartin sf_macreset(sc);
8942f5860a2Smartin
8952f5860a2Smartin sf_funcreg_write(sc, SF_PciDeviceConfig, PDC_SoftReset);
8962f5860a2Smartin for (i = 0; i < 1000; i++) {
8972f5860a2Smartin delay(10);
8982f5860a2Smartin if ((sf_funcreg_read(sc, SF_PciDeviceConfig) &
8992f5860a2Smartin PDC_SoftReset) == 0)
9002f5860a2Smartin break;
9012f5860a2Smartin }
9022f5860a2Smartin
9032f5860a2Smartin if (i == 1000) {
9042f5860a2Smartin printf("%s: reset failed to complete\n", sc->sc_dev.dv_xname);
9052f5860a2Smartin sf_funcreg_write(sc, SF_PciDeviceConfig, 0);
9062f5860a2Smartin }
9072f5860a2Smartin
9082f5860a2Smartin delay(1000);
9092f5860a2Smartin }
9102f5860a2Smartin
9112f5860a2Smartin /*
9122f5860a2Smartin * sf_macreset:
9132f5860a2Smartin *
9142f5860a2Smartin * Reset the MAC portion of the Starfire.
9152f5860a2Smartin */
9162f5860a2Smartin void
sf_macreset(struct sf_softc * sc)9172f5860a2Smartin sf_macreset(struct sf_softc *sc)
9182f5860a2Smartin {
9192f5860a2Smartin
9202f5860a2Smartin sf_genreg_write(sc, SF_MacConfig1, sc->sc_MacConfig1 | MC1_SoftRst);
9212f5860a2Smartin delay(1000);
9222f5860a2Smartin sf_genreg_write(sc, SF_MacConfig1, sc->sc_MacConfig1);
9232f5860a2Smartin }
9242f5860a2Smartin
9252f5860a2Smartin /*
9262f5860a2Smartin * sf_init: [ifnet interface function]
9272f5860a2Smartin *
9282f5860a2Smartin * Initialize the interface. Must be called at splnet().
9292f5860a2Smartin */
9302f5860a2Smartin int
sf_init(struct ifnet * ifp)9312f5860a2Smartin sf_init(struct ifnet *ifp)
9322f5860a2Smartin {
9332f5860a2Smartin struct sf_softc *sc = ifp->if_softc;
9342f5860a2Smartin struct sf_descsoft *ds;
9352f5860a2Smartin int error = 0;
9362f5860a2Smartin u_int i;
9372f5860a2Smartin
9382f5860a2Smartin /*
9392f5860a2Smartin * Cancel any pending I/O.
9402f5860a2Smartin */
9412f5860a2Smartin sf_stop(ifp, 0);
9422f5860a2Smartin
9432f5860a2Smartin /*
9442f5860a2Smartin * Reset the Starfire to a known state.
9452f5860a2Smartin */
9462f5860a2Smartin sf_reset(sc);
9472f5860a2Smartin
9482f5860a2Smartin /* Clear the stat counters. */
9492f5860a2Smartin for (i = 0; i < sizeof(struct sf_stats); i += sizeof(uint32_t))
9502f5860a2Smartin sf_genreg_write(sc, SF_STATS_BASE + i, 0);
9512f5860a2Smartin
9522f5860a2Smartin /*
9532f5860a2Smartin * Initialize the transmit descriptor ring.
9542f5860a2Smartin */
9552f5860a2Smartin memset(sc->sc_txdescs, 0, sizeof(sc->sc_txdescs));
9562f5860a2Smartin sf_funcreg_write(sc, SF_TxDescQueueHighAddr, 0);
9572f5860a2Smartin sf_funcreg_write(sc, SF_HiPrTxDescQueueBaseAddr, SF_CDTXDADDR(sc, 0));
9582f5860a2Smartin sf_funcreg_write(sc, SF_LoPrTxDescQueueBaseAddr, 0);
9592f5860a2Smartin
9602f5860a2Smartin /*
9612f5860a2Smartin * Initialize the transmit completion ring.
9622f5860a2Smartin */
9632f5860a2Smartin for (i = 0; i < SF_NTCD; i++) {
9642f5860a2Smartin sc->sc_txcomp[i].tcd_word0 = TCD_DMA_ID;
9652f5860a2Smartin SF_CDTXCSYNC(sc, i, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
9662f5860a2Smartin }
9672f5860a2Smartin sf_funcreg_write(sc, SF_CompletionQueueHighAddr, 0);
9682f5860a2Smartin sf_funcreg_write(sc, SF_TxCompletionQueueCtrl, SF_CDTXCADDR(sc, 0));
9692f5860a2Smartin
9702f5860a2Smartin /*
9712f5860a2Smartin * Initialize the receive descriptor ring.
9722f5860a2Smartin */
9732f5860a2Smartin for (i = 0; i < SF_NRXDESC; i++) {
9742f5860a2Smartin ds = &sc->sc_rxsoft[i];
9752f5860a2Smartin if (ds->ds_mbuf == NULL) {
9762f5860a2Smartin if ((error = sf_add_rxbuf(sc, i)) != 0) {
9772f5860a2Smartin printf("%s: unable to allocate or map rx "
9782f5860a2Smartin "buffer %d, error = %d\n",
9792f5860a2Smartin sc->sc_dev.dv_xname, i, error);
9802f5860a2Smartin /*
9812f5860a2Smartin * XXX Should attempt to run with fewer receive
9822f5860a2Smartin * XXX buffers instead of just failing.
9832f5860a2Smartin */
9842f5860a2Smartin sf_rxdrain(sc);
9852f5860a2Smartin goto out;
9862f5860a2Smartin }
9872f5860a2Smartin } else
9882f5860a2Smartin SF_INIT_RXDESC(sc, i);
9892f5860a2Smartin }
9902f5860a2Smartin sf_funcreg_write(sc, SF_RxDescQueueHighAddress, 0);
9912f5860a2Smartin sf_funcreg_write(sc, SF_RxDescQueue1LowAddress, SF_CDRXDADDR(sc, 0));
9922f5860a2Smartin sf_funcreg_write(sc, SF_RxDescQueue2LowAddress, 0);
9932f5860a2Smartin
9942f5860a2Smartin /*
9952f5860a2Smartin * Initialize the receive completion ring.
9962f5860a2Smartin */
9972f5860a2Smartin for (i = 0; i < SF_NRCD; i++) {
9982f5860a2Smartin sc->sc_rxcomp[i].rcd_word0 = RCD_W0_ID;
9992f5860a2Smartin sc->sc_rxcomp[i].rcd_word1 = 0;
10002f5860a2Smartin sc->sc_rxcomp[i].rcd_word2 = 0;
10012f5860a2Smartin sc->sc_rxcomp[i].rcd_timestamp = 0;
10022f5860a2Smartin SF_CDRXCSYNC(sc, i, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
10032f5860a2Smartin }
10042f5860a2Smartin sf_funcreg_write(sc, SF_RxCompletionQueue1Ctrl, SF_CDRXCADDR(sc, 0) |
10052f5860a2Smartin RCQ1C_RxCompletionQ1Type(3));
10062f5860a2Smartin sf_funcreg_write(sc, SF_RxCompletionQueue2Ctrl, 0);
10072f5860a2Smartin
10082f5860a2Smartin /*
10092f5860a2Smartin * Initialize the Tx CSR.
10102f5860a2Smartin */
10112f5860a2Smartin sc->sc_TransmitFrameCSR = 0;
10122f5860a2Smartin sf_funcreg_write(sc, SF_TransmitFrameCSR,
10132f5860a2Smartin sc->sc_TransmitFrameCSR |
10142f5860a2Smartin TFCSR_TransmitThreshold(sc->sc_txthresh));
10152f5860a2Smartin
10162f5860a2Smartin /*
10172f5860a2Smartin * Initialize the Tx descriptor control register.
10182f5860a2Smartin */
10192f5860a2Smartin sc->sc_TxDescQueueCtrl = TDQC_SkipLength(0) |
10202f5860a2Smartin TDQC_TxDmaBurstSize(4) | /* default */
10212f5860a2Smartin TDQC_MinFrameSpacing(3) | /* 128 bytes */
10222f5860a2Smartin TDQC_TxDescType(0);
10232f5860a2Smartin sf_funcreg_write(sc, SF_TxDescQueueCtrl,
10242f5860a2Smartin sc->sc_TxDescQueueCtrl |
10252f5860a2Smartin TDQC_TxHighPriorityFifoThreshold(sc->sc_txthresh));
10262f5860a2Smartin
10272f5860a2Smartin /*
10282f5860a2Smartin * Initialize the Rx descriptor control registers.
10292f5860a2Smartin */
10302f5860a2Smartin sf_funcreg_write(sc, SF_RxDescQueue1Ctrl,
10312f5860a2Smartin RDQ1C_RxQ1BufferLength(MCLBYTES) |
10322f5860a2Smartin RDQ1C_RxDescSpacing(0));
10332f5860a2Smartin sf_funcreg_write(sc, SF_RxDescQueue2Ctrl, 0);
10342f5860a2Smartin
10352f5860a2Smartin /*
10362f5860a2Smartin * Initialize the Tx descriptor producer indices.
10372f5860a2Smartin */
10382f5860a2Smartin sf_funcreg_write(sc, SF_TxDescQueueProducerIndex,
10392f5860a2Smartin TDQPI_HiPrTxProducerIndex(0) |
10402f5860a2Smartin TDQPI_LoPrTxProducerIndex(0));
10412f5860a2Smartin
10422f5860a2Smartin /*
10432f5860a2Smartin * Initialize the Rx descriptor producer indices.
10442f5860a2Smartin */
10452f5860a2Smartin sf_funcreg_write(sc, SF_RxDescQueue1Ptrs,
10462f5860a2Smartin RXQ1P_RxDescQ1Producer(SF_NRXDESC - 1));
10472f5860a2Smartin sf_funcreg_write(sc, SF_RxDescQueue2Ptrs,
10482f5860a2Smartin RXQ2P_RxDescQ2Producer(0));
10492f5860a2Smartin
10502f5860a2Smartin /*
10512f5860a2Smartin * Initialize the Tx and Rx completion queue consumer indices.
10522f5860a2Smartin */
10532f5860a2Smartin sf_funcreg_write(sc, SF_CompletionQueueConsumerIndex,
10542f5860a2Smartin CQCI_TxCompletionConsumerIndex(0) |
10552f5860a2Smartin CQCI_RxCompletionQ1ConsumerIndex(0));
10562f5860a2Smartin sf_funcreg_write(sc, SF_RxHiPrCompletionPtrs, 0);
10572f5860a2Smartin
10582f5860a2Smartin /*
10592f5860a2Smartin * Initialize the Rx DMA control register.
10602f5860a2Smartin */
10612f5860a2Smartin sf_funcreg_write(sc, SF_RxDmaCtrl,
10622f5860a2Smartin RDC_RxHighPriorityThreshold(6) | /* default */
10632f5860a2Smartin RDC_RxBurstSize(4)); /* default */
10642f5860a2Smartin
10652f5860a2Smartin /*
10662f5860a2Smartin * Set the receive filter.
10672f5860a2Smartin */
10682f5860a2Smartin sc->sc_RxAddressFilteringCtl = 0;
10692f5860a2Smartin sf_set_filter(sc);
10702f5860a2Smartin
10712f5860a2Smartin /*
10722f5860a2Smartin * Set MacConfig1. When we set the media, MacConfig1 will
10732f5860a2Smartin * actually be written and the MAC part reset.
10742f5860a2Smartin */
10752f5860a2Smartin sc->sc_MacConfig1 = MC1_PadEn;
10762f5860a2Smartin
10772f5860a2Smartin /*
10782f5860a2Smartin * Set the media.
10792f5860a2Smartin */
10802f5860a2Smartin mii_mediachg(&sc->sc_mii);
10812f5860a2Smartin
10822f5860a2Smartin /*
10832f5860a2Smartin * Initialize the interrupt register.
10842f5860a2Smartin */
10852f5860a2Smartin sc->sc_InterruptEn = IS_PCIPadInt | IS_RxQ1DoneInt |
10862f5860a2Smartin IS_TxQueueDoneInt | IS_TxDmaDoneInt | IS_DmaErrInt |
10872f5860a2Smartin IS_StatisticWrapInt;
10882f5860a2Smartin sf_funcreg_write(sc, SF_InterruptEn, sc->sc_InterruptEn);
10892f5860a2Smartin
10902f5860a2Smartin sf_funcreg_write(sc, SF_PciDeviceConfig, PDC_IntEnable |
10912f5860a2Smartin PDC_PCIMstDmaEn | (1 << PDC_FifoThreshold_SHIFT));
10922f5860a2Smartin
10932f5860a2Smartin /*
10942f5860a2Smartin * Start the transmit and receive processes.
10952f5860a2Smartin */
10962f5860a2Smartin sf_funcreg_write(sc, SF_GeneralEthernetCtrl,
10972f5860a2Smartin GEC_TxDmaEn|GEC_RxDmaEn|GEC_TransmitEn|GEC_ReceiveEn);
10982f5860a2Smartin
10992f5860a2Smartin /* Start the on second clock. */
1100e15e1c8cSblambert timeout_add_sec(&sc->sc_mii_timeout, 1);
11012f5860a2Smartin
11022f5860a2Smartin /*
11032f5860a2Smartin * Note that the interface is now running.
11042f5860a2Smartin */
11052f5860a2Smartin ifp->if_flags |= IFF_RUNNING;
1106de6cd8fbSdlg ifq_clr_oactive(&ifp->if_snd);
11072f5860a2Smartin
11082f5860a2Smartin out:
11092f5860a2Smartin if (error) {
1110de6cd8fbSdlg ifp->if_flags &= ~IFF_RUNNING;
1111de6cd8fbSdlg ifq_clr_oactive(&ifp->if_snd);
11122f5860a2Smartin ifp->if_timer = 0;
11132f5860a2Smartin printf("%s: interface not running\n", sc->sc_dev.dv_xname);
11142f5860a2Smartin }
11152f5860a2Smartin return (error);
11162f5860a2Smartin }
11172f5860a2Smartin
11182f5860a2Smartin /*
11192f5860a2Smartin * sf_rxdrain:
11202f5860a2Smartin *
11212f5860a2Smartin * Drain the receive queue.
11222f5860a2Smartin */
11232f5860a2Smartin void
sf_rxdrain(struct sf_softc * sc)11242f5860a2Smartin sf_rxdrain(struct sf_softc *sc)
11252f5860a2Smartin {
11262f5860a2Smartin struct sf_descsoft *ds;
11272f5860a2Smartin int i;
11282f5860a2Smartin
11292f5860a2Smartin for (i = 0; i < SF_NRXDESC; i++) {
11302f5860a2Smartin ds = &sc->sc_rxsoft[i];
11312f5860a2Smartin if (ds->ds_mbuf != NULL) {
11322f5860a2Smartin bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
11332f5860a2Smartin m_freem(ds->ds_mbuf);
11342f5860a2Smartin ds->ds_mbuf = NULL;
11352f5860a2Smartin }
11362f5860a2Smartin }
11372f5860a2Smartin }
11382f5860a2Smartin
11392f5860a2Smartin /*
11402f5860a2Smartin * sf_stop: [ifnet interface function]
11412f5860a2Smartin *
11422f5860a2Smartin * Stop transmission on the interface.
11432f5860a2Smartin */
11442f5860a2Smartin void
sf_stop(struct ifnet * ifp,int disable)11452f5860a2Smartin sf_stop(struct ifnet *ifp, int disable)
11462f5860a2Smartin {
11472f5860a2Smartin struct sf_softc *sc = ifp->if_softc;
11482f5860a2Smartin struct sf_descsoft *ds;
11492f5860a2Smartin int i;
11502f5860a2Smartin
11512f5860a2Smartin /* Stop the one second clock. */
11522f5860a2Smartin timeout_del(&sc->sc_mii_timeout);
11532f5860a2Smartin
11542f5860a2Smartin /* Down the MII. */
11552f5860a2Smartin mii_down(&sc->sc_mii);
11562f5860a2Smartin
11572f5860a2Smartin /* Disable interrupts. */
11582f5860a2Smartin sf_funcreg_write(sc, SF_InterruptEn, 0);
11592f5860a2Smartin
11602f5860a2Smartin /* Stop the transmit and receive processes. */
11612f5860a2Smartin sf_funcreg_write(sc, SF_GeneralEthernetCtrl, 0);
11622f5860a2Smartin
11632f5860a2Smartin /*
11642f5860a2Smartin * Release any queued transmit buffers.
11652f5860a2Smartin */
11662f5860a2Smartin for (i = 0; i < SF_NTXDESC; i++) {
11672f5860a2Smartin ds = &sc->sc_txsoft[i];
11682f5860a2Smartin if (ds->ds_mbuf != NULL) {
11692f5860a2Smartin bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
11702f5860a2Smartin m_freem(ds->ds_mbuf);
11712f5860a2Smartin ds->ds_mbuf = NULL;
11722f5860a2Smartin }
11732f5860a2Smartin }
11742c828e54Sbrad sc->sc_txpending = 0;
11752f5860a2Smartin
11762f5860a2Smartin if (disable)
11772f5860a2Smartin sf_rxdrain(sc);
11782f5860a2Smartin
11792f5860a2Smartin /*
11802f5860a2Smartin * Mark the interface down and cancel the watchdog timer.
11812f5860a2Smartin */
1182de6cd8fbSdlg ifp->if_flags &= ~IFF_RUNNING;
1183de6cd8fbSdlg ifq_clr_oactive(&ifp->if_snd);
11842f5860a2Smartin ifp->if_timer = 0;
11852f5860a2Smartin }
11862f5860a2Smartin
11872f5860a2Smartin /*
11882f5860a2Smartin * sf_read_eeprom:
11892f5860a2Smartin *
11902f5860a2Smartin * Read from the Starfire EEPROM.
11912f5860a2Smartin */
11922f5860a2Smartin uint8_t
sf_read_eeprom(struct sf_softc * sc,int offset)11932f5860a2Smartin sf_read_eeprom(struct sf_softc *sc, int offset)
11942f5860a2Smartin {
11952f5860a2Smartin uint32_t reg;
11962f5860a2Smartin
11972f5860a2Smartin reg = sf_genreg_read(sc, SF_EEPROM_BASE + (offset & ~3));
11982f5860a2Smartin
11992f5860a2Smartin return ((reg >> (8 * (offset & 3))) & 0xff);
12002f5860a2Smartin }
12012f5860a2Smartin
12022f5860a2Smartin /*
12032f5860a2Smartin * sf_add_rxbuf:
12042f5860a2Smartin *
12052f5860a2Smartin * Add a receive buffer to the indicated descriptor.
12062f5860a2Smartin */
12072f5860a2Smartin int
sf_add_rxbuf(struct sf_softc * sc,int idx)12082f5860a2Smartin sf_add_rxbuf(struct sf_softc *sc, int idx)
12092f5860a2Smartin {
12102f5860a2Smartin struct sf_descsoft *ds = &sc->sc_rxsoft[idx];
12112f5860a2Smartin struct mbuf *m;
12122f5860a2Smartin int error;
12132f5860a2Smartin
12142f5860a2Smartin MGETHDR(m, M_DONTWAIT, MT_DATA);
12152f5860a2Smartin if (m == NULL)
12162f5860a2Smartin return (ENOBUFS);
12172f5860a2Smartin
12182f5860a2Smartin MCLGET(m, M_DONTWAIT);
12192f5860a2Smartin if ((m->m_flags & M_EXT) == 0) {
12202f5860a2Smartin m_freem(m);
12212f5860a2Smartin return (ENOBUFS);
12222f5860a2Smartin }
12232f5860a2Smartin
12242f5860a2Smartin if (ds->ds_mbuf != NULL)
12252f5860a2Smartin bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
12262f5860a2Smartin
12272f5860a2Smartin ds->ds_mbuf = m;
12282f5860a2Smartin
12292f5860a2Smartin error = bus_dmamap_load(sc->sc_dmat, ds->ds_dmamap,
12302f5860a2Smartin m->m_ext.ext_buf, m->m_ext.ext_size, NULL,
12312f5860a2Smartin BUS_DMA_READ|BUS_DMA_NOWAIT);
12322f5860a2Smartin if (error) {
12332f5860a2Smartin printf("%s: can't load rx DMA map %d, error = %d\n",
12342f5860a2Smartin sc->sc_dev.dv_xname, idx, error);
12352f5860a2Smartin panic("sf_add_rxbuf"); /* XXX */
12362f5860a2Smartin }
12372f5860a2Smartin
12382f5860a2Smartin bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
12392f5860a2Smartin ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
12402f5860a2Smartin
12412f5860a2Smartin SF_INIT_RXDESC(sc, idx);
12422f5860a2Smartin
12432f5860a2Smartin return (0);
12442f5860a2Smartin }
12452f5860a2Smartin
12462f5860a2Smartin void
sf_set_filter_perfect(struct sf_softc * sc,int slot,uint8_t * enaddr)12472f5860a2Smartin sf_set_filter_perfect(struct sf_softc *sc, int slot, uint8_t *enaddr)
12482f5860a2Smartin {
12492f5860a2Smartin uint32_t reg0, reg1, reg2;
12502f5860a2Smartin
12512f5860a2Smartin reg0 = enaddr[5] | (enaddr[4] << 8);
12522f5860a2Smartin reg1 = enaddr[3] | (enaddr[2] << 8);
12532f5860a2Smartin reg2 = enaddr[1] | (enaddr[0] << 8);
12542f5860a2Smartin
12552f5860a2Smartin sf_genreg_write(sc, SF_PERFECT_BASE + (slot * 0x10) + 0, reg0);
12562f5860a2Smartin sf_genreg_write(sc, SF_PERFECT_BASE + (slot * 0x10) + 4, reg1);
12572f5860a2Smartin sf_genreg_write(sc, SF_PERFECT_BASE + (slot * 0x10) + 8, reg2);
12582f5860a2Smartin }
12592f5860a2Smartin
12602f5860a2Smartin void
sf_set_filter_hash(struct sf_softc * sc,uint8_t * enaddr)12612f5860a2Smartin sf_set_filter_hash(struct sf_softc *sc, uint8_t *enaddr)
12622f5860a2Smartin {
12632f5860a2Smartin uint32_t hash, slot, reg;
12642f5860a2Smartin
12652f5860a2Smartin hash = ether_crc32_be(enaddr, ETHER_ADDR_LEN) >> 23;
12662f5860a2Smartin slot = hash >> 4;
12672f5860a2Smartin
12682f5860a2Smartin reg = sf_genreg_read(sc, SF_HASH_BASE + (slot * 0x10));
12692f5860a2Smartin reg |= 1 << (hash & 0xf);
12702f5860a2Smartin sf_genreg_write(sc, SF_HASH_BASE + (slot * 0x10), reg);
12712f5860a2Smartin }
12722f5860a2Smartin
12732f5860a2Smartin /*
12742f5860a2Smartin * sf_set_filter:
12752f5860a2Smartin *
12762f5860a2Smartin * Set the Starfire receive filter.
12772f5860a2Smartin */
12782f5860a2Smartin void
sf_set_filter(struct sf_softc * sc)12792f5860a2Smartin sf_set_filter(struct sf_softc *sc)
12802f5860a2Smartin {
12812f5860a2Smartin struct arpcom *ac = &sc->sc_arpcom;
12822f5860a2Smartin struct ifnet *ifp = &sc->sc_arpcom.ac_if;
12832f5860a2Smartin struct ether_multi *enm;
12842f5860a2Smartin struct ether_multistep step;
12852f5860a2Smartin int i;
12862f5860a2Smartin
12872f5860a2Smartin /* Start by clearing the perfect and hash tables. */
12882f5860a2Smartin for (i = 0; i < SF_PERFECT_SIZE; i += sizeof(uint32_t))
12892f5860a2Smartin sf_genreg_write(sc, SF_PERFECT_BASE + i, 0);
12902f5860a2Smartin
12912f5860a2Smartin for (i = 0; i < SF_HASH_SIZE; i += sizeof(uint32_t))
12922f5860a2Smartin sf_genreg_write(sc, SF_HASH_BASE + i, 0);
12932f5860a2Smartin
12942f5860a2Smartin /*
12952f5860a2Smartin * Clear the perfect and hash mode bits.
12962f5860a2Smartin */
12972f5860a2Smartin sc->sc_RxAddressFilteringCtl &=
12982f5860a2Smartin ~(RAFC_PerfectFilteringMode(3) | RAFC_HashFilteringMode(3));
12992f5860a2Smartin
13002f5860a2Smartin if (ifp->if_flags & IFF_BROADCAST)
13012f5860a2Smartin sc->sc_RxAddressFilteringCtl |= RAFC_PassBroadcast;
13022f5860a2Smartin else
13032f5860a2Smartin sc->sc_RxAddressFilteringCtl &= ~RAFC_PassBroadcast;
13042f5860a2Smartin
13052f5860a2Smartin if (ifp->if_flags & IFF_PROMISC) {
13062f5860a2Smartin sc->sc_RxAddressFilteringCtl |= RAFC_PromiscuousMode;
13072f5860a2Smartin goto allmulti;
13082f5860a2Smartin } else
13092f5860a2Smartin sc->sc_RxAddressFilteringCtl &= ~RAFC_PromiscuousMode;
13102f5860a2Smartin
13112f5860a2Smartin /*
13122f5860a2Smartin * Set normal perfect filtering mode.
13132f5860a2Smartin */
13142f5860a2Smartin sc->sc_RxAddressFilteringCtl |= RAFC_PerfectFilteringMode(1);
13152f5860a2Smartin
13162f5860a2Smartin /*
13172f5860a2Smartin * First, write the station address to the perfect filter
13182f5860a2Smartin * table.
13192f5860a2Smartin */
13202f5860a2Smartin sf_set_filter_perfect(sc, 0, LLADDR(ifp->if_sadl));
13212f5860a2Smartin
1322f2e23e59Smpi if (ac->ac_multirangecnt > 0)
1323f2e23e59Smpi goto allmulti;
1324f2e23e59Smpi
13252f5860a2Smartin /*
13262f5860a2Smartin * Now set the hash bits for each multicast address in our
13272f5860a2Smartin * list.
13282f5860a2Smartin */
13292f5860a2Smartin ETHER_FIRST_MULTI(step, ac, enm);
13302f5860a2Smartin if (enm == NULL)
13312f5860a2Smartin goto done;
13322f5860a2Smartin while (enm != NULL) {
13332f5860a2Smartin sf_set_filter_hash(sc, enm->enm_addrlo);
13342f5860a2Smartin ETHER_NEXT_MULTI(step, enm);
13352f5860a2Smartin }
13362f5860a2Smartin
13372f5860a2Smartin /*
13382f5860a2Smartin * Set "hash only multicast dest, match regardless of VLAN ID".
13392f5860a2Smartin */
13402f5860a2Smartin sc->sc_RxAddressFilteringCtl |= RAFC_HashFilteringMode(2);
13412f5860a2Smartin goto done;
13422f5860a2Smartin
13432f5860a2Smartin allmulti:
13442f5860a2Smartin /*
13452f5860a2Smartin * XXX RAFC_PassMulticast is sub-optimal if using VLAN mode.
13462f5860a2Smartin */
13472f5860a2Smartin sc->sc_RxAddressFilteringCtl |= RAFC_PassMulticast;
13482f5860a2Smartin ifp->if_flags |= IFF_ALLMULTI;
13492f5860a2Smartin
13502f5860a2Smartin done:
13512f5860a2Smartin sf_funcreg_write(sc, SF_RxAddressFilteringCtl,
13522f5860a2Smartin sc->sc_RxAddressFilteringCtl);
13532f5860a2Smartin }
13542f5860a2Smartin
13552f5860a2Smartin /*
13562f5860a2Smartin * sf_mii_read: [mii interface function]
13572f5860a2Smartin *
13582f5860a2Smartin * Read from the MII.
13592f5860a2Smartin */
13602f5860a2Smartin int
sf_mii_read(struct device * self,int phy,int reg)13612f5860a2Smartin sf_mii_read(struct device *self, int phy, int reg)
13622f5860a2Smartin {
13632f5860a2Smartin struct sf_softc *sc = (void *) self;
13642f5860a2Smartin uint32_t v;
13652f5860a2Smartin int i;
13662f5860a2Smartin
13672f5860a2Smartin for (i = 0; i < 1000; i++) {
13682f5860a2Smartin v = sf_genreg_read(sc, SF_MII_PHY_REG(phy, reg));
13692f5860a2Smartin if (v & MiiDataValid)
13702f5860a2Smartin break;
13712f5860a2Smartin delay(1);
13722f5860a2Smartin }
13732f5860a2Smartin
13742f5860a2Smartin if ((v & MiiDataValid) == 0)
13752f5860a2Smartin return (0);
13762f5860a2Smartin
13772f5860a2Smartin if (MiiRegDataPort(v) == 0xffff)
13782f5860a2Smartin return (0);
13792f5860a2Smartin
13802f5860a2Smartin return (MiiRegDataPort(v));
13812f5860a2Smartin }
13822f5860a2Smartin
13832f5860a2Smartin /*
13842f5860a2Smartin * sf_mii_write: [mii interface function]
13852f5860a2Smartin *
13862f5860a2Smartin * Write to the MII.
13872f5860a2Smartin */
13882f5860a2Smartin void
sf_mii_write(struct device * self,int phy,int reg,int val)13892f5860a2Smartin sf_mii_write(struct device *self, int phy, int reg, int val)
13902f5860a2Smartin {
13912f5860a2Smartin struct sf_softc *sc = (void *) self;
13922f5860a2Smartin int i;
13932f5860a2Smartin
13942f5860a2Smartin sf_genreg_write(sc, SF_MII_PHY_REG(phy, reg), val);
13952f5860a2Smartin
13962f5860a2Smartin for (i = 0; i < 1000; i++) {
13972f5860a2Smartin if ((sf_genreg_read(sc, SF_MII_PHY_REG(phy, reg)) &
13982f5860a2Smartin MiiBusy) == 0)
13992f5860a2Smartin return;
14002f5860a2Smartin delay(1);
14012f5860a2Smartin }
14022f5860a2Smartin
14032f5860a2Smartin printf("%s: MII write timed out\n", sc->sc_dev.dv_xname);
14042f5860a2Smartin }
14052f5860a2Smartin
14062f5860a2Smartin /*
14072f5860a2Smartin * sf_mii_statchg: [mii interface function]
14082f5860a2Smartin *
14092f5860a2Smartin * Callback from the PHY when the media changes.
14102f5860a2Smartin */
14112f5860a2Smartin void
sf_mii_statchg(struct device * self)14122f5860a2Smartin sf_mii_statchg(struct device *self)
14132f5860a2Smartin {
14142f5860a2Smartin struct sf_softc *sc = (void *) self;
14152f5860a2Smartin uint32_t ipg;
14162f5860a2Smartin
14172f5860a2Smartin if (sc->sc_mii.mii_media_active & IFM_FDX) {
14182f5860a2Smartin sc->sc_MacConfig1 |= MC1_FullDuplex;
14192f5860a2Smartin ipg = 0x15;
14202f5860a2Smartin } else {
14212f5860a2Smartin sc->sc_MacConfig1 &= ~MC1_FullDuplex;
14222f5860a2Smartin ipg = 0x11;
14232f5860a2Smartin }
14242f5860a2Smartin
14252f5860a2Smartin sf_genreg_write(sc, SF_MacConfig1, sc->sc_MacConfig1);
14262f5860a2Smartin sf_macreset(sc);
14272f5860a2Smartin
14282f5860a2Smartin sf_genreg_write(sc, SF_BkToBkIPG, ipg);
14292f5860a2Smartin }
14302f5860a2Smartin
14312f5860a2Smartin /*
14322f5860a2Smartin * sf_mediastatus: [ifmedia interface function]
14332f5860a2Smartin *
14342f5860a2Smartin * Callback from ifmedia to request current media status.
14352f5860a2Smartin */
14362f5860a2Smartin void
sf_mediastatus(struct ifnet * ifp,struct ifmediareq * ifmr)14372f5860a2Smartin sf_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
14382f5860a2Smartin {
14392f5860a2Smartin struct sf_softc *sc = ifp->if_softc;
14402f5860a2Smartin
14412f5860a2Smartin mii_pollstat(&sc->sc_mii);
14422f5860a2Smartin ifmr->ifm_status = sc->sc_mii.mii_media_status;
14432f5860a2Smartin ifmr->ifm_active = sc->sc_mii.mii_media_active;
14442f5860a2Smartin }
14452f5860a2Smartin
14462f5860a2Smartin /*
14472f5860a2Smartin * sf_mediachange: [ifmedia interface function]
14482f5860a2Smartin *
14492f5860a2Smartin * Callback from ifmedia to request new media setting.
14502f5860a2Smartin */
14512f5860a2Smartin int
sf_mediachange(struct ifnet * ifp)14522f5860a2Smartin sf_mediachange(struct ifnet *ifp)
14532f5860a2Smartin {
14542f5860a2Smartin struct sf_softc *sc = ifp->if_softc;
14552f5860a2Smartin
14562f5860a2Smartin if (ifp->if_flags & IFF_UP)
14572f5860a2Smartin mii_mediachg(&sc->sc_mii);
14582f5860a2Smartin return (0);
14592f5860a2Smartin }
1460