Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/gem/if_gem.c
Show First 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | |||||
static void gem_cddma_callback(void *xsc, bus_dma_segment_t *segs, | static void gem_cddma_callback(void *xsc, bus_dma_segment_t *segs, | ||||
int nsegs, int error); | int nsegs, int error); | ||||
static int gem_disable_rx(struct gem_softc *sc); | static int gem_disable_rx(struct gem_softc *sc); | ||||
static int gem_disable_tx(struct gem_softc *sc); | static int gem_disable_tx(struct gem_softc *sc); | ||||
static void gem_eint(struct gem_softc *sc, u_int status); | static void gem_eint(struct gem_softc *sc, u_int status); | ||||
static void gem_init(void *xsc); | static void gem_init(void *xsc); | ||||
static void gem_init_locked(struct gem_softc *sc); | static void gem_init_locked(struct gem_softc *sc); | ||||
static void gem_init_regs(struct gem_softc *sc); | static void gem_init_regs(struct gem_softc *sc); | ||||
static int gem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data); | static int gem_ioctl(if_t ifp, u_long cmd, caddr_t data); | ||||
static int gem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head); | static int gem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head); | ||||
static int gem_meminit(struct gem_softc *sc); | static int gem_meminit(struct gem_softc *sc); | ||||
static void gem_mifinit(struct gem_softc *sc); | static void gem_mifinit(struct gem_softc *sc); | ||||
static void gem_reset(struct gem_softc *sc); | static void gem_reset(struct gem_softc *sc); | ||||
static int gem_reset_rx(struct gem_softc *sc); | static int gem_reset_rx(struct gem_softc *sc); | ||||
static void gem_reset_rxdma(struct gem_softc *sc); | static void gem_reset_rxdma(struct gem_softc *sc); | ||||
static int gem_reset_tx(struct gem_softc *sc); | static int gem_reset_tx(struct gem_softc *sc); | ||||
static u_int gem_ringsize(u_int sz); | static u_int gem_ringsize(u_int sz); | ||||
static void gem_rint(struct gem_softc *sc); | static void gem_rint(struct gem_softc *sc); | ||||
#ifdef GEM_RINT_TIMEOUT | #ifdef GEM_RINT_TIMEOUT | ||||
static void gem_rint_timeout(void *arg); | static void gem_rint_timeout(void *arg); | ||||
#endif | #endif | ||||
static inline void gem_rxcksum(struct mbuf *m, uint64_t flags); | static inline void gem_rxcksum(struct mbuf *m, uint64_t flags); | ||||
static void gem_rxdrain(struct gem_softc *sc); | static void gem_rxdrain(struct gem_softc *sc); | ||||
static void gem_setladrf(struct gem_softc *sc); | static void gem_setladrf(struct gem_softc *sc); | ||||
static void gem_start(struct ifnet *ifp); | static void gem_start(if_t ifp); | ||||
static void gem_start_locked(struct ifnet *ifp); | static void gem_start_locked(if_t ifp); | ||||
static void gem_stop(struct ifnet *ifp, int disable); | static void gem_stop(if_t ifp, int disable); | ||||
static void gem_tick(void *arg); | static void gem_tick(void *arg); | ||||
static void gem_tint(struct gem_softc *sc); | static void gem_tint(struct gem_softc *sc); | ||||
static inline void gem_txkick(struct gem_softc *sc); | static inline void gem_txkick(struct gem_softc *sc); | ||||
static int gem_watchdog(struct gem_softc *sc); | static int gem_watchdog(struct gem_softc *sc); | ||||
DRIVER_MODULE(miibus, gem, miibus_driver, 0, 0); | DRIVER_MODULE(miibus, gem, miibus_driver, 0, 0); | ||||
MODULE_DEPEND(gem, miibus, 1, 1, 1); | MODULE_DEPEND(gem, miibus, 1, 1, 1); | ||||
#ifdef GEM_DEBUG | #ifdef GEM_DEBUG | ||||
#include <sys/ktr.h> | #include <sys/ktr.h> | ||||
#define KTR_GEM KTR_SPARE2 | #define KTR_GEM KTR_SPARE2 | ||||
#endif | #endif | ||||
#define GEM_BANK1_BITWAIT(sc, r, clr, set) \ | #define GEM_BANK1_BITWAIT(sc, r, clr, set) \ | ||||
gem_bitwait((sc), GEM_RES_BANK1, (r), (clr), (set)) | gem_bitwait((sc), GEM_RES_BANK1, (r), (clr), (set)) | ||||
#define GEM_BANK2_BITWAIT(sc, r, clr, set) \ | #define GEM_BANK2_BITWAIT(sc, r, clr, set) \ | ||||
gem_bitwait((sc), GEM_RES_BANK2, (r), (clr), (set)) | gem_bitwait((sc), GEM_RES_BANK2, (r), (clr), (set)) | ||||
int | int | ||||
gem_attach(struct gem_softc *sc) | gem_attach(struct gem_softc *sc) | ||||
{ | { | ||||
struct gem_txsoft *txs; | struct gem_txsoft *txs; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
int error, i, phy; | int error, i, phy; | ||||
uint32_t v; | uint32_t v; | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(sc->sc_dev, "flags=0x%x\n", sc->sc_flags); | device_printf(sc->sc_dev, "flags=0x%x\n", sc->sc_flags); | ||||
/* Set up ifnet structure. */ | /* Set up ifnet structure. */ | ||||
ifp = sc->sc_ifp = if_alloc(IFT_ETHER); | ifp = sc->sc_ifp = if_alloc(IFT_ETHER); | ||||
if (ifp == NULL) | if (ifp == NULL) | ||||
return (ENOSPC); | return (ENOSPC); | ||||
sc->sc_csum_features = GEM_CSUM_FEATURES; | sc->sc_csum_features = GEM_CSUM_FEATURES; | ||||
ifp->if_softc = sc; | if_setsoftc(ifp, sc); | ||||
if_initname(ifp, device_get_name(sc->sc_dev), | if_initname(ifp, device_get_name(sc->sc_dev), | ||||
device_get_unit(sc->sc_dev)); | device_get_unit(sc->sc_dev)); | ||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); | ||||
ifp->if_start = gem_start; | if_setstartfn(ifp, gem_start); | ||||
ifp->if_ioctl = gem_ioctl; | if_setioctlfn(ifp, gem_ioctl); | ||||
ifp->if_init = gem_init; | if_setinitfn(ifp, gem_init); | ||||
IFQ_SET_MAXLEN(&ifp->if_snd, GEM_TXQUEUELEN); | if_setsendqlen(ifp, GEM_TXQUEUELEN); | ||||
ifp->if_snd.ifq_drv_maxlen = GEM_TXQUEUELEN; | if_setsendqready(ifp); | ||||
IFQ_SET_READY(&ifp->if_snd); | |||||
callout_init_mtx(&sc->sc_tick_ch, &sc->sc_mtx, 0); | callout_init_mtx(&sc->sc_tick_ch, &sc->sc_mtx, 0); | ||||
#ifdef GEM_RINT_TIMEOUT | #ifdef GEM_RINT_TIMEOUT | ||||
callout_init_mtx(&sc->sc_rx_ch, &sc->sc_mtx, 0); | callout_init_mtx(&sc->sc_rx_ch, &sc->sc_mtx, 0); | ||||
#endif | #endif | ||||
/* Make sure the chip is stopped. */ | /* Make sure the chip is stopped. */ | ||||
gem_reset(sc); | gem_reset(sc); | ||||
▲ Show 20 Lines • Show All 195 Lines • ▼ Show 20 Lines | device_printf(sc->sc_dev, "%ukB RX FIFO, %ukB TX FIFO\n", | ||||
sc->sc_rxfifosize / 1024, v / 16); | sc->sc_rxfifosize / 1024, v / 16); | ||||
/* Attach the interface. */ | /* Attach the interface. */ | ||||
ether_ifattach(ifp, sc->sc_enaddr); | ether_ifattach(ifp, sc->sc_enaddr); | ||||
/* | /* | ||||
* Tell the upper layer(s) we support long frames/checksum offloads. | * Tell the upper layer(s) we support long frames/checksum offloads. | ||||
*/ | */ | ||||
ifp->if_hdrlen = sizeof(struct ether_vlan_header); | if_setifheaderlen(ifp, sizeof(struct ether_vlan_header)); | ||||
ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; | if_setcapabilitiesbit(ifp, IFCAP_VLAN_MTU | IFCAP_HWCSUM, 0); | ||||
ifp->if_hwassist |= sc->sc_csum_features; | if_sethwassistbits(ifp, sc->sc_csum_features, 0); | ||||
ifp->if_capenable |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; | if_setcapenablebit(ifp, IFCAP_VLAN_MTU | IFCAP_HWCSUM, 0); | ||||
return (0); | return (0); | ||||
/* | /* | ||||
* Free any resources we've allocated during the failed attach | * Free any resources we've allocated during the failed attach | ||||
* attempt. Do this in reverse order and fall through. | * attempt. Do this in reverse order and fall through. | ||||
*/ | */ | ||||
fail_rxd: | fail_rxd: | ||||
Show All 21 Lines | |||||
fail_ifnet: | fail_ifnet: | ||||
if_free(ifp); | if_free(ifp); | ||||
return (error); | return (error); | ||||
} | } | ||||
void | void | ||||
gem_detach(struct gem_softc *sc) | gem_detach(struct gem_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | if_t ifp = sc->sc_ifp; | ||||
int i; | int i; | ||||
ether_ifdetach(ifp); | ether_ifdetach(ifp); | ||||
GEM_LOCK(sc); | GEM_LOCK(sc); | ||||
gem_stop(ifp, 1); | gem_stop(ifp, 1); | ||||
GEM_UNLOCK(sc); | GEM_UNLOCK(sc); | ||||
callout_drain(&sc->sc_tick_ch); | callout_drain(&sc->sc_tick_ch); | ||||
#ifdef GEM_RINT_TIMEOUT | #ifdef GEM_RINT_TIMEOUT | ||||
Show All 18 Lines | #endif | ||||
bus_dma_tag_destroy(sc->sc_tdmatag); | bus_dma_tag_destroy(sc->sc_tdmatag); | ||||
bus_dma_tag_destroy(sc->sc_rdmatag); | bus_dma_tag_destroy(sc->sc_rdmatag); | ||||
bus_dma_tag_destroy(sc->sc_pdmatag); | bus_dma_tag_destroy(sc->sc_pdmatag); | ||||
} | } | ||||
void | void | ||||
gem_suspend(struct gem_softc *sc) | gem_suspend(struct gem_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | if_t ifp = sc->sc_ifp; | ||||
GEM_LOCK(sc); | GEM_LOCK(sc); | ||||
gem_stop(ifp, 0); | gem_stop(ifp, 0); | ||||
GEM_UNLOCK(sc); | GEM_UNLOCK(sc); | ||||
} | } | ||||
void | void | ||||
gem_resume(struct gem_softc *sc) | gem_resume(struct gem_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | if_t ifp = sc->sc_ifp; | ||||
GEM_LOCK(sc); | GEM_LOCK(sc); | ||||
/* | /* | ||||
* On resume all registers have to be initialized again like | * On resume all registers have to be initialized again like | ||||
* after power-on. | * after power-on. | ||||
*/ | */ | ||||
sc->sc_flags &= ~GEM_INITED; | sc->sc_flags &= ~GEM_INITED; | ||||
if (ifp->if_flags & IFF_UP) | if (if_getflags(ifp) & IFF_UP) | ||||
gem_init_locked(sc); | gem_init_locked(sc); | ||||
GEM_UNLOCK(sc); | GEM_UNLOCK(sc); | ||||
} | } | ||||
static inline void | static inline void | ||||
gem_rxcksum(struct mbuf *m, uint64_t flags) | gem_rxcksum(struct mbuf *m, uint64_t flags) | ||||
{ | { | ||||
struct ether_header *eh; | struct ether_header *eh; | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | if (nsegs != 1) | ||||
panic("%s: bad control buffer segment count", __func__); | panic("%s: bad control buffer segment count", __func__); | ||||
sc->sc_cddma = segs[0].ds_addr; | sc->sc_cddma = segs[0].ds_addr; | ||||
} | } | ||||
static void | static void | ||||
gem_tick(void *arg) | gem_tick(void *arg) | ||||
{ | { | ||||
struct gem_softc *sc = arg; | struct gem_softc *sc = arg; | ||||
struct ifnet *ifp = sc->sc_ifp; | if_t ifp = sc->sc_ifp; | ||||
uint32_t v; | uint32_t v; | ||||
GEM_LOCK_ASSERT(sc, MA_OWNED); | GEM_LOCK_ASSERT(sc, MA_OWNED); | ||||
/* | /* | ||||
* Unload collision and error counters. | * Unload collision and error counters. | ||||
*/ | */ | ||||
if_inc_counter(ifp, IFCOUNTER_COLLISIONS, | if_inc_counter(ifp, IFCOUNTER_COLLISIONS, | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | if (rxs->rxs_mbuf != NULL) { | ||||
bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); | bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); | ||||
m_freem(rxs->rxs_mbuf); | m_freem(rxs->rxs_mbuf); | ||||
rxs->rxs_mbuf = NULL; | rxs->rxs_mbuf = NULL; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
gem_stop(struct ifnet *ifp, int disable) | gem_stop(if_t ifp, int disable) | ||||
{ | { | ||||
struct gem_softc *sc = ifp->if_softc; | struct gem_softc *sc = if_getsoftc(ifp); | ||||
struct gem_txsoft *txs; | struct gem_txsoft *txs; | ||||
#ifdef GEM_DEBUG | #ifdef GEM_DEBUG | ||||
CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); | CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); | ||||
#endif | #endif | ||||
callout_stop(&sc->sc_tick_ch); | callout_stop(&sc->sc_tick_ch); | ||||
#ifdef GEM_RINT_TIMEOUT | #ifdef GEM_RINT_TIMEOUT | ||||
Show All 21 Lines | #endif | ||||
} | } | ||||
if (disable) | if (disable) | ||||
gem_rxdrain(sc); | gem_rxdrain(sc); | ||||
/* | /* | ||||
* Mark the interface down and cancel the watchdog timer. | * Mark the interface down and cancel the watchdog timer. | ||||
*/ | */ | ||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); | if_setdrvflagbits(ifp, 0, (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)); | ||||
sc->sc_flags &= ~GEM_LINK; | sc->sc_flags &= ~GEM_LINK; | ||||
sc->sc_wdog_timer = 0; | sc->sc_wdog_timer = 0; | ||||
} | } | ||||
static int | static int | ||||
gem_reset_rx(struct gem_softc *sc) | gem_reset_rx(struct gem_softc *sc) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
* reset which amongst others also downs the link and clears the FIFOs. | * reset which amongst others also downs the link and clears the FIFOs. | ||||
*/ | */ | ||||
static void | static void | ||||
gem_reset_rxdma(struct gem_softc *sc) | gem_reset_rxdma(struct gem_softc *sc) | ||||
{ | { | ||||
int i; | int i; | ||||
if (gem_reset_rx(sc) != 0) { | if (gem_reset_rx(sc) != 0) { | ||||
sc->sc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; | if_setdrvflagbits(sc->sc_ifp, 0, IFF_DRV_RUNNING); | ||||
return (gem_init_locked(sc)); | return (gem_init_locked(sc)); | ||||
} | } | ||||
for (i = 0; i < GEM_NRXDESC; i++) | for (i = 0; i < GEM_NRXDESC; i++) | ||||
if (sc->sc_rxsoft[i].rxs_mbuf != NULL) | if (sc->sc_rxsoft[i].rxs_mbuf != NULL) | ||||
GEM_UPDATE_RXDESC(sc, i); | GEM_UPDATE_RXDESC(sc, i); | ||||
sc->sc_rxptr = 0; | sc->sc_rxptr = 0; | ||||
GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | ||||
▲ Show 20 Lines • Show All 172 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Initialization of interface; set up initialization block | * Initialization of interface; set up initialization block | ||||
* and transmit/receive descriptor rings. | * and transmit/receive descriptor rings. | ||||
*/ | */ | ||||
static void | static void | ||||
gem_init_locked(struct gem_softc *sc) | gem_init_locked(struct gem_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | if_t ifp = sc->sc_ifp; | ||||
uint32_t v; | uint32_t v; | ||||
GEM_LOCK_ASSERT(sc, MA_OWNED); | GEM_LOCK_ASSERT(sc, MA_OWNED); | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) | if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) | ||||
return; | return; | ||||
#ifdef GEM_DEBUG | #ifdef GEM_DEBUG | ||||
CTR2(KTR_GEM, "%s: %s: calling stop", device_get_name(sc->sc_dev), | CTR2(KTR_GEM, "%s: %s: calling stop", device_get_name(sc->sc_dev), | ||||
__func__); | __func__); | ||||
#endif | #endif | ||||
/* | /* | ||||
* Initialization sequence. The numbered steps below correspond | * Initialization sequence. The numbered steps below correspond | ||||
▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | #endif | ||||
(void)gem_disable_tx(sc); | (void)gem_disable_tx(sc); | ||||
GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, v); | GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, v); | ||||
/* step 14. Issue Transmit Pending command. */ | /* step 14. Issue Transmit Pending command. */ | ||||
/* step 15. Give the receiver a swift kick. */ | /* step 15. Give the receiver a swift kick. */ | ||||
GEM_BANK1_WRITE_4(sc, GEM_RX_KICK, GEM_NRXDESC - 4); | GEM_BANK1_WRITE_4(sc, GEM_RX_KICK, GEM_NRXDESC - 4); | ||||
ifp->if_drv_flags |= IFF_DRV_RUNNING; | if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); | ||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); | ||||
mii_mediachg(sc->sc_mii); | mii_mediachg(sc->sc_mii); | ||||
/* Start the one second timer. */ | /* Start the one second timer. */ | ||||
sc->sc_wdog_timer = 0; | sc->sc_wdog_timer = 0; | ||||
callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); | callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 139 Lines • ▼ Show 20 Lines | #endif | ||||
sc->sc_txfree -= txs->txs_ndescs; | sc->sc_txfree -= txs->txs_ndescs; | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
gem_init_regs(struct gem_softc *sc) | gem_init_regs(struct gem_softc *sc) | ||||
{ | { | ||||
const u_char *laddr = IF_LLADDR(sc->sc_ifp); | const u_char *laddr = if_getlladdr(sc->sc_ifp); | ||||
GEM_LOCK_ASSERT(sc, MA_OWNED); | GEM_LOCK_ASSERT(sc, MA_OWNED); | ||||
/* These registers are not cleared on reset. */ | /* These registers are not cleared on reset. */ | ||||
if ((sc->sc_flags & GEM_INITED) == 0) { | if ((sc->sc_flags & GEM_INITED) == 0) { | ||||
/* magic values */ | /* magic values */ | ||||
GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG0, 0); | GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG0, 0); | ||||
GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG1, 8); | GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG1, 8); | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | gem_init_regs(struct gem_softc *sc) | ||||
GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR1, (laddr[2] << 8) | laddr[3]); | GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR1, (laddr[2] << 8) | laddr[3]); | ||||
GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR2, (laddr[0] << 8) | laddr[1]); | GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR2, (laddr[0] << 8) | laddr[1]); | ||||
/* Enable MII outputs. */ | /* Enable MII outputs. */ | ||||
GEM_BANK1_WRITE_4(sc, GEM_MAC_XIF_CONFIG, GEM_MAC_XIF_TX_MII_ENA); | GEM_BANK1_WRITE_4(sc, GEM_MAC_XIF_CONFIG, GEM_MAC_XIF_TX_MII_ENA); | ||||
} | } | ||||
static void | static void | ||||
gem_start(struct ifnet *ifp) | gem_start(if_t ifp) | ||||
{ | { | ||||
struct gem_softc *sc = ifp->if_softc; | struct gem_softc *sc = if_getsoftc(ifp); | ||||
GEM_LOCK(sc); | GEM_LOCK(sc); | ||||
gem_start_locked(ifp); | gem_start_locked(ifp); | ||||
GEM_UNLOCK(sc); | GEM_UNLOCK(sc); | ||||
} | } | ||||
static inline void | static inline void | ||||
gem_txkick(struct gem_softc *sc) | gem_txkick(struct gem_softc *sc) | ||||
Show All 9 Lines | #ifdef GEM_DEBUG | ||||
CTR3(KTR_GEM, "%s: %s: kicking TX %d", | CTR3(KTR_GEM, "%s: %s: kicking TX %d", | ||||
device_get_name(sc->sc_dev), __func__, sc->sc_txnext); | device_get_name(sc->sc_dev), __func__, sc->sc_txnext); | ||||
#endif | #endif | ||||
GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | ||||
GEM_BANK1_WRITE_4(sc, GEM_TX_KICK, sc->sc_txnext); | GEM_BANK1_WRITE_4(sc, GEM_TX_KICK, sc->sc_txnext); | ||||
} | } | ||||
static void | static void | ||||
gem_start_locked(struct ifnet *ifp) | gem_start_locked(if_t ifp) | ||||
{ | { | ||||
struct gem_softc *sc = ifp->if_softc; | struct gem_softc *sc = if_getsoftc(ifp); | ||||
struct mbuf *m; | struct mbuf *m; | ||||
int kicked, ntx; | int kicked, ntx; | ||||
GEM_LOCK_ASSERT(sc, MA_OWNED); | GEM_LOCK_ASSERT(sc, MA_OWNED); | ||||
if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != | if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != | ||||
IFF_DRV_RUNNING || (sc->sc_flags & GEM_LINK) == 0) | IFF_DRV_RUNNING || (sc->sc_flags & GEM_LINK) == 0) | ||||
return; | return; | ||||
#ifdef GEM_DEBUG | #ifdef GEM_DEBUG | ||||
CTR4(KTR_GEM, "%s: %s: txfree %d, txnext %d", | CTR4(KTR_GEM, "%s: %s: txfree %d, txnext %d", | ||||
device_get_name(sc->sc_dev), __func__, sc->sc_txfree, | device_get_name(sc->sc_dev), __func__, sc->sc_txfree, | ||||
sc->sc_txnext); | sc->sc_txnext); | ||||
#endif | #endif | ||||
ntx = 0; | ntx = 0; | ||||
kicked = 0; | kicked = 0; | ||||
for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && sc->sc_txfree > 1;) { | for (; !if_sendq_empty(ifp) && sc->sc_txfree > 1;) { | ||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m); | m = if_dequeue(ifp); | ||||
if (m == NULL) | if (m == NULL) | ||||
break; | break; | ||||
if (gem_load_txmbuf(sc, &m) != 0) { | if (gem_load_txmbuf(sc, &m) != 0) { | ||||
if (m == NULL) | if (m == NULL) | ||||
break; | break; | ||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); | ||||
IFQ_DRV_PREPEND(&ifp->if_snd, m); | if_sendq_prepend(ifp, m); | ||||
break; | break; | ||||
} | } | ||||
if ((sc->sc_txnext % 4) == 0) { | if ((sc->sc_txnext % 4) == 0) { | ||||
gem_txkick(sc); | gem_txkick(sc); | ||||
kicked = 1; | kicked = 1; | ||||
} else | } else | ||||
kicked = 0; | kicked = 0; | ||||
ntx++; | ntx++; | ||||
Show All 16 Lines | CTR3(KTR_GEM, "%s: %s: watchdog %d", | ||||
sc->sc_wdog_timer); | sc->sc_wdog_timer); | ||||
#endif | #endif | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
gem_tint(struct gem_softc *sc) | gem_tint(struct gem_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | if_t ifp = sc->sc_ifp; | ||||
struct gem_txsoft *txs; | struct gem_txsoft *txs; | ||||
int progress; | int progress; | ||||
uint32_t txlast; | uint32_t txlast; | ||||
#ifdef GEM_DEBUG | #ifdef GEM_DEBUG | ||||
int i; | int i; | ||||
GEM_LOCK_ASSERT(sc, MA_OWNED); | GEM_LOCK_ASSERT(sc, MA_OWNED); | ||||
CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); | CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); | ||||
#endif | #endif | ||||
/* | /* | ||||
* Go through our TX list and free mbufs for those | * Go through our TX list and free mbufs for those | ||||
* frames that have been transmitted. | * frames that have been transmitted. | ||||
*/ | */ | ||||
progress = 0; | progress = 0; | ||||
GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); | GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); | ||||
while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { | while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { | ||||
#ifdef GEM_DEBUG | #ifdef GEM_DEBUG | ||||
if ((ifp->if_flags & IFF_DEBUG) != 0) { | if ((if_getflags(ifp) & IFF_DEBUG) != 0) { | ||||
printf(" txsoft %p transmit chain:\n", txs); | printf(" txsoft %p transmit chain:\n", txs); | ||||
for (i = txs->txs_firstdesc;; i = GEM_NEXTTX(i)) { | for (i = txs->txs_firstdesc;; i = GEM_NEXTTX(i)) { | ||||
printf("descriptor %d: ", i); | printf("descriptor %d: ", i); | ||||
printf("gd_flags: 0x%016llx\t", | printf("gd_flags: 0x%016llx\t", | ||||
(long long)GEM_DMA_READ(sc, | (long long)GEM_DMA_READ(sc, | ||||
sc->sc_txdescs[i].gd_flags)); | sc->sc_txdescs[i].gd_flags)); | ||||
printf("gd_addr: 0x%016llx\n", | printf("gd_addr: 0x%016llx\n", | ||||
(long long)GEM_DMA_READ(sc, | (long long)GEM_DMA_READ(sc, | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | #endif | ||||
if (progress) { | if (progress) { | ||||
if (sc->sc_txfree == GEM_NTXDESC - 1) | if (sc->sc_txfree == GEM_NTXDESC - 1) | ||||
sc->sc_txwin = 0; | sc->sc_txwin = 0; | ||||
/* | /* | ||||
* We freed some descriptors, so reset IFF_DRV_OACTIVE | * We freed some descriptors, so reset IFF_DRV_OACTIVE | ||||
* and restart. | * and restart. | ||||
*/ | */ | ||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); | ||||
if (STAILQ_EMPTY(&sc->sc_txdirtyq)) | if (STAILQ_EMPTY(&sc->sc_txdirtyq)) | ||||
sc->sc_wdog_timer = 0; | sc->sc_wdog_timer = 0; | ||||
gem_start_locked(ifp); | gem_start_locked(ifp); | ||||
} | } | ||||
#ifdef GEM_DEBUG | #ifdef GEM_DEBUG | ||||
CTR3(KTR_GEM, "%s: %s: watchdog %d", | CTR3(KTR_GEM, "%s: %s: watchdog %d", | ||||
device_get_name(sc->sc_dev), __func__, sc->sc_wdog_timer); | device_get_name(sc->sc_dev), __func__, sc->sc_wdog_timer); | ||||
Show All 10 Lines | gem_rint_timeout(void *arg) | ||||
gem_rint(sc); | gem_rint(sc); | ||||
} | } | ||||
#endif | #endif | ||||
static void | static void | ||||
gem_rint(struct gem_softc *sc) | gem_rint(struct gem_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | if_t ifp = sc->sc_ifp; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
uint64_t rxstat; | uint64_t rxstat; | ||||
uint32_t rxcomp; | uint32_t rxcomp; | ||||
GEM_LOCK_ASSERT(sc, MA_OWNED); | GEM_LOCK_ASSERT(sc, MA_OWNED); | ||||
#ifdef GEM_RINT_TIMEOUT | #ifdef GEM_RINT_TIMEOUT | ||||
callout_stop(&sc->sc_rx_ch); | callout_stop(&sc->sc_rx_ch); | ||||
Show All 38 Lines | if (rxstat & GEM_RD_BAD_CRC) { | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | ||||
device_printf(sc->sc_dev, "receive error: CRC error\n"); | device_printf(sc->sc_dev, "receive error: CRC error\n"); | ||||
GEM_INIT_RXDESC(sc, sc->sc_rxptr); | GEM_INIT_RXDESC(sc, sc->sc_rxptr); | ||||
m = NULL; | m = NULL; | ||||
goto kickit; | goto kickit; | ||||
} | } | ||||
#ifdef GEM_DEBUG | #ifdef GEM_DEBUG | ||||
if ((ifp->if_flags & IFF_DEBUG) != 0) { | if ((if_getflags(ifp) & IFF_DEBUG) != 0) { | ||||
printf(" rxsoft %p descriptor %d: ", | printf(" rxsoft %p descriptor %d: ", | ||||
&sc->sc_rxsoft[sc->sc_rxptr], sc->sc_rxptr); | &sc->sc_rxsoft[sc->sc_rxptr], sc->sc_rxptr); | ||||
printf("gd_flags: 0x%016llx\t", | printf("gd_flags: 0x%016llx\t", | ||||
(long long)GEM_DMA_READ(sc, | (long long)GEM_DMA_READ(sc, | ||||
sc->sc_rxdescs[sc->sc_rxptr].gd_flags)); | sc->sc_rxdescs[sc->sc_rxptr].gd_flags)); | ||||
printf("gd_addr: 0x%016llx\n", | printf("gd_addr: 0x%016llx\n", | ||||
(long long)GEM_DMA_READ(sc, | (long long)GEM_DMA_READ(sc, | ||||
sc->sc_rxdescs[sc->sc_rxptr].gd_addr)); | sc->sc_rxdescs[sc->sc_rxptr].gd_addr)); | ||||
Show All 34 Lines | if (m == NULL) { | ||||
continue; | continue; | ||||
} | } | ||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); | if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); | ||||
m->m_data += ETHER_ALIGN; /* first byte offset */ | m->m_data += ETHER_ALIGN; /* first byte offset */ | ||||
m->m_pkthdr.rcvif = ifp; | m->m_pkthdr.rcvif = ifp; | ||||
m->m_pkthdr.len = m->m_len = GEM_RD_BUFLEN(rxstat); | m->m_pkthdr.len = m->m_len = GEM_RD_BUFLEN(rxstat); | ||||
if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) | if ((if_getcapenable(ifp) & IFCAP_RXCSUM) != 0) | ||||
gem_rxcksum(m, rxstat); | gem_rxcksum(m, rxstat); | ||||
/* Pass it on. */ | /* Pass it on. */ | ||||
GEM_UNLOCK(sc); | GEM_UNLOCK(sc); | ||||
(*ifp->if_input)(ifp, m); | if_input(ifp, m); | ||||
GEM_LOCK(sc); | GEM_LOCK(sc); | ||||
} | } | ||||
#ifdef GEM_DEBUG | #ifdef GEM_DEBUG | ||||
CTR3(KTR_GEM, "%s: done sc->sc_rxptr %d, complete %d", __func__, | CTR3(KTR_GEM, "%s: done sc->sc_rxptr %d, complete %d", __func__, | ||||
sc->sc_rxptr, GEM_BANK1_READ_4(sc, GEM_RX_COMPLETION)); | sc->sc_rxptr, GEM_BANK1_READ_4(sc, GEM_RX_COMPLETION)); | ||||
#endif | #endif | ||||
} | } | ||||
▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | if (__predict_false((status & GEM_INTR_TX_MAC) != 0)) { | ||||
if ((status2 & | if ((status2 & | ||||
~(GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP | | ~(GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP | | ||||
GEM_MAC_TX_PEAK_EXP)) != 0) | GEM_MAC_TX_PEAK_EXP)) != 0) | ||||
device_printf(sc->sc_dev, | device_printf(sc->sc_dev, | ||||
"MAC TX fault, status %x\n", status2); | "MAC TX fault, status %x\n", status2); | ||||
if ((status2 & | if ((status2 & | ||||
(GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG)) != 0) { | (GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG)) != 0) { | ||||
if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1); | if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1); | ||||
sc->sc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; | if_setdrvflagbits(sc->sc_ifp, 0, IFF_DRV_RUNNING); | ||||
gem_init_locked(sc); | gem_init_locked(sc); | ||||
} | } | ||||
} | } | ||||
if (__predict_false((status & GEM_INTR_RX_MAC) != 0)) { | if (__predict_false((status & GEM_INTR_RX_MAC) != 0)) { | ||||
status2 = GEM_BANK1_READ_4(sc, GEM_MAC_RX_STATUS); | status2 = GEM_BANK1_READ_4(sc, GEM_MAC_RX_STATUS); | ||||
/* | /* | ||||
* At least with GEM_SUN_GEM and some GEM_SUN_ERI | * At least with GEM_SUN_GEM and some GEM_SUN_ERI | ||||
* revisions GEM_MAC_RX_OVERFLOW happen often due to a | * revisions GEM_MAC_RX_OVERFLOW happen often due to a | ||||
Show All 9 Lines | if ((status2 & GEM_MAC_RX_OVERFLOW) != 0) { | ||||
"MAC RX fault, status %x\n", status2); | "MAC RX fault, status %x\n", status2); | ||||
} | } | ||||
GEM_UNLOCK(sc); | GEM_UNLOCK(sc); | ||||
} | } | ||||
static int | static int | ||||
gem_watchdog(struct gem_softc *sc) | gem_watchdog(struct gem_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | if_t ifp = sc->sc_ifp; | ||||
GEM_LOCK_ASSERT(sc, MA_OWNED); | GEM_LOCK_ASSERT(sc, MA_OWNED); | ||||
#ifdef GEM_DEBUG | #ifdef GEM_DEBUG | ||||
CTR4(KTR_GEM, | CTR4(KTR_GEM, | ||||
"%s: GEM_RX_CONFIG %x GEM_MAC_RX_STATUS %x GEM_MAC_RX_CONFIG %x", | "%s: GEM_RX_CONFIG %x GEM_MAC_RX_STATUS %x GEM_MAC_RX_CONFIG %x", | ||||
__func__, GEM_BANK1_READ_4(sc, GEM_RX_CONFIG), | __func__, GEM_BANK1_READ_4(sc, GEM_RX_CONFIG), | ||||
GEM_BANK1_READ_4(sc, GEM_MAC_RX_STATUS), | GEM_BANK1_READ_4(sc, GEM_MAC_RX_STATUS), | ||||
Show All 10 Lines | #endif | ||||
if ((sc->sc_flags & GEM_LINK) != 0) | if ((sc->sc_flags & GEM_LINK) != 0) | ||||
device_printf(sc->sc_dev, "device timeout\n"); | device_printf(sc->sc_dev, "device timeout\n"); | ||||
else if (bootverbose) | else if (bootverbose) | ||||
device_printf(sc->sc_dev, "device timeout (no link)\n"); | device_printf(sc->sc_dev, "device timeout (no link)\n"); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | ||||
/* Try to get more packets going. */ | /* Try to get more packets going. */ | ||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING; | if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING); | ||||
gem_init_locked(sc); | gem_init_locked(sc); | ||||
gem_start_locked(ifp); | gem_start_locked(ifp); | ||||
return (EJUSTRETURN); | return (EJUSTRETURN); | ||||
} | } | ||||
static void | static void | ||||
gem_mifinit(struct gem_softc *sc) | gem_mifinit(struct gem_softc *sc) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 163 Lines • ▼ Show 20 Lines | gem_mii_statchg(device_t dev) | ||||
int gigabit; | int gigabit; | ||||
uint32_t rxcfg, txcfg, v; | uint32_t rxcfg, txcfg, v; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
GEM_LOCK_ASSERT(sc, MA_OWNED); | GEM_LOCK_ASSERT(sc, MA_OWNED); | ||||
#ifdef GEM_DEBUG | #ifdef GEM_DEBUG | ||||
if ((sc->sc_ifp->if_flags & IFF_DEBUG) != 0) | if ((sc->sc_if_getflags(ifp) & IFF_DEBUG) != 0) | ||||
device_printf(sc->sc_dev, "%s: status change\n", __func__); | device_printf(sc->sc_dev, "%s: status change\n", __func__); | ||||
#endif | #endif | ||||
if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) != 0 && | if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) != 0 && | ||||
IFM_SUBTYPE(sc->sc_mii->mii_media_active) != IFM_NONE) | IFM_SUBTYPE(sc->sc_mii->mii_media_active) != IFM_NONE) | ||||
sc->sc_flags |= GEM_LINK; | sc->sc_flags |= GEM_LINK; | ||||
else | else | ||||
sc->sc_flags &= ~GEM_LINK; | sc->sc_flags &= ~GEM_LINK; | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
if (gigabit != 0) | if (gigabit != 0) | ||||
v |= GEM_MAC_XIF_GMII_MODE; | v |= GEM_MAC_XIF_GMII_MODE; | ||||
if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) | if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) | ||||
v |= GEM_MAC_XIF_FDPLX_LED; | v |= GEM_MAC_XIF_FDPLX_LED; | ||||
GEM_BANK1_WRITE_4(sc, GEM_MAC_XIF_CONFIG, v); | GEM_BANK1_WRITE_4(sc, GEM_MAC_XIF_CONFIG, v); | ||||
sc->sc_mac_rxcfg = rxcfg; | sc->sc_mac_rxcfg = rxcfg; | ||||
if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && | if ((if_getdrvflags(sc->sc_ifp) & IFF_DRV_RUNNING) != 0 && | ||||
(sc->sc_flags & GEM_LINK) != 0) { | (sc->sc_flags & GEM_LINK) != 0) { | ||||
GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, | GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, | ||||
txcfg | GEM_MAC_TX_ENABLE); | txcfg | GEM_MAC_TX_ENABLE); | ||||
GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, | GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, | ||||
rxcfg | GEM_MAC_RX_ENABLE); | rxcfg | GEM_MAC_RX_ENABLE); | ||||
} | } | ||||
} | } | ||||
int | int | ||||
gem_mediachange(struct ifnet *ifp) | gem_mediachange(if_t ifp) | ||||
{ | { | ||||
struct gem_softc *sc = ifp->if_softc; | struct gem_softc *sc = if_getsoftc(ifp); | ||||
int error; | int error; | ||||
/* XXX add support for serial media. */ | /* XXX add support for serial media. */ | ||||
GEM_LOCK(sc); | GEM_LOCK(sc); | ||||
error = mii_mediachg(sc->sc_mii); | error = mii_mediachg(sc->sc_mii); | ||||
GEM_UNLOCK(sc); | GEM_UNLOCK(sc); | ||||
return (error); | return (error); | ||||
} | } | ||||
void | void | ||||
gem_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) | gem_mediastatus(if_t ifp, struct ifmediareq *ifmr) | ||||
{ | { | ||||
struct gem_softc *sc = ifp->if_softc; | struct gem_softc *sc = if_getsoftc(ifp); | ||||
GEM_LOCK(sc); | GEM_LOCK(sc); | ||||
if ((ifp->if_flags & IFF_UP) == 0) { | if ((if_getflags(ifp) & IFF_UP) == 0) { | ||||
GEM_UNLOCK(sc); | GEM_UNLOCK(sc); | ||||
return; | return; | ||||
} | } | ||||
mii_pollstat(sc->sc_mii); | mii_pollstat(sc->sc_mii); | ||||
ifmr->ifm_active = sc->sc_mii->mii_media_active; | ifmr->ifm_active = sc->sc_mii->mii_media_active; | ||||
ifmr->ifm_status = sc->sc_mii->mii_media_status; | ifmr->ifm_status = sc->sc_mii->mii_media_status; | ||||
GEM_UNLOCK(sc); | GEM_UNLOCK(sc); | ||||
} | } | ||||
static int | static int | ||||
gem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) | gem_ioctl(if_t ifp, u_long cmd, caddr_t data) | ||||
{ | { | ||||
struct gem_softc *sc = ifp->if_softc; | struct gem_softc *sc = if_getsoftc(ifp); | ||||
struct ifreq *ifr = (struct ifreq *)data; | struct ifreq *ifr = (struct ifreq *)data; | ||||
int error; | int error; | ||||
error = 0; | error = 0; | ||||
switch (cmd) { | switch (cmd) { | ||||
case SIOCSIFFLAGS: | case SIOCSIFFLAGS: | ||||
GEM_LOCK(sc); | GEM_LOCK(sc); | ||||
if ((ifp->if_flags & IFF_UP) != 0) { | if ((if_getflags(ifp) & IFF_UP) != 0) { | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && | if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0 && | ||||
((ifp->if_flags ^ sc->sc_ifflags) & | ((if_getflags(ifp) ^ sc->sc_ifflags) & | ||||
(IFF_ALLMULTI | IFF_PROMISC)) != 0) | (IFF_ALLMULTI | IFF_PROMISC)) != 0) | ||||
gem_setladrf(sc); | gem_setladrf(sc); | ||||
else | else | ||||
gem_init_locked(sc); | gem_init_locked(sc); | ||||
} else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) | } else if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) | ||||
gem_stop(ifp, 0); | gem_stop(ifp, 0); | ||||
if ((ifp->if_flags & IFF_LINK0) != 0) | if ((if_getflags(ifp) & IFF_LINK0) != 0) | ||||
sc->sc_csum_features |= CSUM_UDP; | sc->sc_csum_features |= CSUM_UDP; | ||||
else | else | ||||
sc->sc_csum_features &= ~CSUM_UDP; | sc->sc_csum_features &= ~CSUM_UDP; | ||||
if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) | if ((if_getcapenable(ifp) & IFCAP_TXCSUM) != 0) | ||||
ifp->if_hwassist = sc->sc_csum_features; | if_sethwassist(ifp, sc->sc_csum_features); | ||||
sc->sc_ifflags = ifp->if_flags; | sc->sc_ifflags = if_getflags(ifp); | ||||
GEM_UNLOCK(sc); | GEM_UNLOCK(sc); | ||||
break; | break; | ||||
case SIOCADDMULTI: | case SIOCADDMULTI: | ||||
case SIOCDELMULTI: | case SIOCDELMULTI: | ||||
GEM_LOCK(sc); | GEM_LOCK(sc); | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) | if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) | ||||
gem_setladrf(sc); | gem_setladrf(sc); | ||||
GEM_UNLOCK(sc); | GEM_UNLOCK(sc); | ||||
break; | break; | ||||
case SIOCGIFMEDIA: | case SIOCGIFMEDIA: | ||||
case SIOCSIFMEDIA: | case SIOCSIFMEDIA: | ||||
error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd); | error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd); | ||||
break; | break; | ||||
case SIOCSIFCAP: | case SIOCSIFCAP: | ||||
GEM_LOCK(sc); | GEM_LOCK(sc); | ||||
ifp->if_capenable = ifr->ifr_reqcap; | if_setcapenable(ifp, ifr->ifr_reqcap); | ||||
if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) | if ((if_getcapenable(ifp) & IFCAP_TXCSUM) != 0) | ||||
ifp->if_hwassist = sc->sc_csum_features; | if_sethwassist(ifp, sc->sc_csum_features); | ||||
else | else | ||||
ifp->if_hwassist = 0; | if_sethwassist(ifp, 0); | ||||
GEM_UNLOCK(sc); | GEM_UNLOCK(sc); | ||||
break; | break; | ||||
default: | default: | ||||
error = ether_ioctl(ifp, cmd, data); | error = ether_ioctl(ifp, cmd, data); | ||||
break; | break; | ||||
} | } | ||||
return (error); | return (error); | ||||
Show All 11 Lines | gem_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) | ||||
hash[crc >> 4] |= 1 << (15 - (crc & 15)); | hash[crc >> 4] |= 1 << (15 - (crc & 15)); | ||||
return (1); | return (1); | ||||
} | } | ||||
static void | static void | ||||
gem_setladrf(struct gem_softc *sc) | gem_setladrf(struct gem_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | if_t ifp = sc->sc_ifp; | ||||
int i; | int i; | ||||
uint32_t hash[16]; | uint32_t hash[16]; | ||||
uint32_t v; | uint32_t v; | ||||
GEM_LOCK_ASSERT(sc, MA_OWNED); | GEM_LOCK_ASSERT(sc, MA_OWNED); | ||||
/* | /* | ||||
* Turn off the RX MAC and the hash filter as required by the Sun GEM | * Turn off the RX MAC and the hash filter as required by the Sun GEM | ||||
* programming restrictions. | * programming restrictions. | ||||
*/ | */ | ||||
v = sc->sc_mac_rxcfg & ~GEM_MAC_RX_HASH_FILTER; | v = sc->sc_mac_rxcfg & ~GEM_MAC_RX_HASH_FILTER; | ||||
GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v); | GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v); | ||||
GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4, | GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4, | ||||
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); | BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); | ||||
if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_HASH_FILTER | | if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_HASH_FILTER | | ||||
GEM_MAC_RX_ENABLE, 0)) | GEM_MAC_RX_ENABLE, 0)) | ||||
device_printf(sc->sc_dev, | device_printf(sc->sc_dev, | ||||
"cannot disable RX MAC or hash filter\n"); | "cannot disable RX MAC or hash filter\n"); | ||||
v &= ~(GEM_MAC_RX_PROMISCUOUS | GEM_MAC_RX_PROMISC_GRP); | v &= ~(GEM_MAC_RX_PROMISCUOUS | GEM_MAC_RX_PROMISC_GRP); | ||||
if ((ifp->if_flags & IFF_PROMISC) != 0) { | if ((if_getflags(ifp) & IFF_PROMISC) != 0) { | ||||
v |= GEM_MAC_RX_PROMISCUOUS; | v |= GEM_MAC_RX_PROMISCUOUS; | ||||
goto chipit; | goto chipit; | ||||
} | } | ||||
if ((ifp->if_flags & IFF_ALLMULTI) != 0) { | if ((if_getflags(ifp) & IFF_ALLMULTI) != 0) { | ||||
v |= GEM_MAC_RX_PROMISC_GRP; | v |= GEM_MAC_RX_PROMISC_GRP; | ||||
goto chipit; | goto chipit; | ||||
} | } | ||||
/* | /* | ||||
* Set up multicast address filter by passing all multicast | * Set up multicast address filter by passing all multicast | ||||
* addresses through a crc generator, and then using the high | * addresses through a crc generator, and then using the high | ||||
* order 8 bits as an index into the 256 bit logical address | * order 8 bits as an index into the 256 bit logical address | ||||
Show All 20 Lines |