Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/dc/if_dc.c
Show First 20 Lines • Show All 240 Lines • ▼ Show 20 Lines | |||||
static int dc_encap(struct dc_softc *, struct mbuf **); | static int dc_encap(struct dc_softc *, struct mbuf **); | ||||
static void dc_pnic_rx_bug_war(struct dc_softc *, int); | static void dc_pnic_rx_bug_war(struct dc_softc *, int); | ||||
static int dc_rx_resync(struct dc_softc *); | static int dc_rx_resync(struct dc_softc *); | ||||
static int dc_rxeof(struct dc_softc *); | static int dc_rxeof(struct dc_softc *); | ||||
static void dc_txeof(struct dc_softc *); | static void dc_txeof(struct dc_softc *); | ||||
static void dc_tick(void *); | static void dc_tick(void *); | ||||
static void dc_tx_underrun(struct dc_softc *); | static void dc_tx_underrun(struct dc_softc *); | ||||
static void dc_intr(void *); | static void dc_intr(void *); | ||||
static void dc_start(struct ifnet *); | static void dc_start(if_t); | ||||
static void dc_start_locked(struct ifnet *); | static void dc_start_locked(if_t); | ||||
static int dc_ioctl(struct ifnet *, u_long, caddr_t); | static int dc_ioctl(if_t, u_long, caddr_t); | ||||
static void dc_init(void *); | static void dc_init(void *); | ||||
static void dc_init_locked(struct dc_softc *); | static void dc_init_locked(struct dc_softc *); | ||||
static void dc_stop(struct dc_softc *); | static void dc_stop(struct dc_softc *); | ||||
static void dc_watchdog(void *); | static void dc_watchdog(void *); | ||||
static int dc_shutdown(device_t); | static int dc_shutdown(device_t); | ||||
static int dc_ifmedia_upd(struct ifnet *); | static int dc_ifmedia_upd(if_t); | ||||
static int dc_ifmedia_upd_locked(struct dc_softc *); | static int dc_ifmedia_upd_locked(struct dc_softc *); | ||||
static void dc_ifmedia_sts(struct ifnet *, struct ifmediareq *); | static void dc_ifmedia_sts(if_t, struct ifmediareq *); | ||||
static int dc_dma_alloc(struct dc_softc *); | static int dc_dma_alloc(struct dc_softc *); | ||||
static void dc_dma_free(struct dc_softc *); | static void dc_dma_free(struct dc_softc *); | ||||
static void dc_dma_map_addr(void *, bus_dma_segment_t *, int, int); | static void dc_dma_map_addr(void *, bus_dma_segment_t *, int, int); | ||||
static void dc_delay(struct dc_softc *); | static void dc_delay(struct dc_softc *); | ||||
static void dc_eeprom_idle(struct dc_softc *); | static void dc_eeprom_idle(struct dc_softc *); | ||||
static void dc_eeprom_putbyte(struct dc_softc *, int); | static void dc_eeprom_putbyte(struct dc_softc *, int); | ||||
▲ Show 20 Lines • Show All 563 Lines • ▼ Show 20 Lines | dc_miibus_writereg(device_t dev, int phy, int reg, int data) | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
dc_miibus_statchg(device_t dev) | dc_miibus_statchg(device_t dev) | ||||
{ | { | ||||
struct dc_softc *sc; | struct dc_softc *sc; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
struct mii_data *mii; | struct mii_data *mii; | ||||
struct ifmedia *ifm; | struct ifmedia *ifm; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
mii = device_get_softc(sc->dc_miibus); | mii = device_get_softc(sc->dc_miibus); | ||||
ifp = sc->dc_ifp; | ifp = sc->dc_ifp; | ||||
if (mii == NULL || ifp == NULL || | if (mii == NULL || ifp == NULL || | ||||
(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) | (if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) | ||||
return; | return; | ||||
ifm = &mii->mii_media; | ifm = &mii->mii_media; | ||||
if (DC_IS_DAVICOM(sc) && IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) { | if (DC_IS_DAVICOM(sc) && IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) { | ||||
dc_setcfg(sc, ifm->ifm_media); | dc_setcfg(sc, ifm->ifm_media); | ||||
return; | return; | ||||
} else if (!DC_IS_ADMTEK(sc)) | } else if (!DC_IS_ADMTEK(sc)) | ||||
dc_setcfg(sc, mii->mii_media_active); | dc_setcfg(sc, mii->mii_media_active); | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static void | static void | ||||
dc_setfilt_21143(struct dc_softc *sc) | dc_setfilt_21143(struct dc_softc *sc) | ||||
{ | { | ||||
uint16_t eaddr[(ETHER_ADDR_LEN+1)/2]; | uint16_t eaddr[(ETHER_ADDR_LEN+1)/2]; | ||||
struct dc_desc *sframe; | struct dc_desc *sframe; | ||||
uint32_t h, *sp; | uint32_t h, *sp; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
int i; | int i; | ||||
ifp = sc->dc_ifp; | ifp = sc->dc_ifp; | ||||
i = sc->dc_cdata.dc_tx_prod; | i = sc->dc_cdata.dc_tx_prod; | ||||
DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT); | DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT); | ||||
sc->dc_cdata.dc_tx_cnt++; | sc->dc_cdata.dc_tx_cnt++; | ||||
sframe = &sc->dc_ldata.dc_tx_list[i]; | sframe = &sc->dc_ldata.dc_tx_list[i]; | ||||
sp = sc->dc_cdata.dc_sbuf; | sp = sc->dc_cdata.dc_sbuf; | ||||
bzero(sp, DC_SFRAME_LEN); | bzero(sp, DC_SFRAME_LEN); | ||||
sframe->dc_data = htole32(DC_ADDR_LO(sc->dc_saddr)); | sframe->dc_data = htole32(DC_ADDR_LO(sc->dc_saddr)); | ||||
sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP | | sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP | | ||||
DC_TXCTL_TLINK | DC_FILTER_HASHPERF | DC_TXCTL_FINT); | DC_TXCTL_TLINK | DC_FILTER_HASHPERF | DC_TXCTL_FINT); | ||||
sc->dc_cdata.dc_tx_chain[i] = (struct mbuf *)sc->dc_cdata.dc_sbuf; | sc->dc_cdata.dc_tx_chain[i] = (struct mbuf *)sc->dc_cdata.dc_sbuf; | ||||
/* If we want promiscuous mode, set the allframes bit. */ | /* If we want promiscuous mode, set the allframes bit. */ | ||||
if (ifp->if_flags & IFF_PROMISC) | if (if_getflags(ifp) & IFF_PROMISC) | ||||
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | ||||
else | else | ||||
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | ||||
if (ifp->if_flags & IFF_ALLMULTI) | if (if_getflags(ifp) & IFF_ALLMULTI) | ||||
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | ||||
else | else | ||||
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | ||||
if_foreach_llmaddr(ifp, dc_hash_maddr_21143, sp); | if_foreach_llmaddr(ifp, dc_hash_maddr_21143, sp); | ||||
if (ifp->if_flags & IFF_BROADCAST) { | if (if_getflags(ifp) & IFF_BROADCAST) { | ||||
h = dc_mchash_le(sc, ifp->if_broadcastaddr); | h = dc_mchash_le(sc, if_getbroadcastaddr(ifp)); | ||||
sp[h >> 4] |= htole32(1 << (h & 0xF)); | sp[h >> 4] |= htole32(1 << (h & 0xF)); | ||||
} | } | ||||
/* Set our MAC address. */ | /* Set our MAC address. */ | ||||
bcopy(IF_LLADDR(sc->dc_ifp), eaddr, ETHER_ADDR_LEN); | bcopy(if_getlladdr(sc->dc_ifp), eaddr, ETHER_ADDR_LEN); | ||||
sp[39] = DC_SP_MAC(eaddr[0]); | sp[39] = DC_SP_MAC(eaddr[0]); | ||||
sp[40] = DC_SP_MAC(eaddr[1]); | sp[40] = DC_SP_MAC(eaddr[1]); | ||||
sp[41] = DC_SP_MAC(eaddr[2]); | sp[41] = DC_SP_MAC(eaddr[2]); | ||||
sframe->dc_status = htole32(DC_TXSTAT_OWN); | sframe->dc_status = htole32(DC_TXSTAT_OWN); | ||||
bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap, BUS_DMASYNC_PREREAD | | bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap, BUS_DMASYNC_PREREAD | | ||||
BUS_DMASYNC_PREWRITE); | BUS_DMASYNC_PREWRITE); | ||||
bus_dmamap_sync(sc->dc_stag, sc->dc_smap, BUS_DMASYNC_PREWRITE); | bus_dmamap_sync(sc->dc_stag, sc->dc_smap, BUS_DMASYNC_PREWRITE); | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | dc_hash_maddr_admtek_le(void *arg, struct sockaddr_dl *sdl, u_int cnt) | ||||
return (1); | return (1); | ||||
} | } | ||||
static void | static void | ||||
dc_setfilt_admtek(struct dc_softc *sc) | dc_setfilt_admtek(struct dc_softc *sc) | ||||
{ | { | ||||
uint8_t eaddr[ETHER_ADDR_LEN]; | uint8_t eaddr[ETHER_ADDR_LEN]; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
struct dc_hash_maddr_admtek_le_ctx ctx = { sc, { 0, 0 }}; | struct dc_hash_maddr_admtek_le_ctx ctx = { sc, { 0, 0 }}; | ||||
ifp = sc->dc_ifp; | ifp = sc->dc_ifp; | ||||
/* Init our MAC address. */ | /* Init our MAC address. */ | ||||
bcopy(IF_LLADDR(sc->dc_ifp), eaddr, ETHER_ADDR_LEN); | bcopy(if_getlladdr(sc->dc_ifp), eaddr, ETHER_ADDR_LEN); | ||||
CSR_WRITE_4(sc, DC_AL_PAR0, eaddr[3] << 24 | eaddr[2] << 16 | | CSR_WRITE_4(sc, DC_AL_PAR0, eaddr[3] << 24 | eaddr[2] << 16 | | ||||
eaddr[1] << 8 | eaddr[0]); | eaddr[1] << 8 | eaddr[0]); | ||||
CSR_WRITE_4(sc, DC_AL_PAR1, eaddr[5] << 8 | eaddr[4]); | CSR_WRITE_4(sc, DC_AL_PAR1, eaddr[5] << 8 | eaddr[4]); | ||||
/* If we want promiscuous mode, set the allframes bit. */ | /* If we want promiscuous mode, set the allframes bit. */ | ||||
if (ifp->if_flags & IFF_PROMISC) | if (if_getflags(ifp) & IFF_PROMISC) | ||||
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | ||||
else | else | ||||
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | ||||
if (ifp->if_flags & IFF_ALLMULTI) | if (if_getflags(ifp) & IFF_ALLMULTI) | ||||
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | ||||
else | else | ||||
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | ||||
/* First, zot all the existing hash bits. */ | /* First, zot all the existing hash bits. */ | ||||
CSR_WRITE_4(sc, DC_AL_MAR0, 0); | CSR_WRITE_4(sc, DC_AL_MAR0, 0); | ||||
CSR_WRITE_4(sc, DC_AL_MAR1, 0); | CSR_WRITE_4(sc, DC_AL_MAR1, 0); | ||||
/* | /* | ||||
* If we're already in promisc or allmulti mode, we | * If we're already in promisc or allmulti mode, we | ||||
* don't have to bother programming the multicast filter. | * don't have to bother programming the multicast filter. | ||||
*/ | */ | ||||
if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) | if (if_getflags(ifp) & (IFF_PROMISC | IFF_ALLMULTI)) | ||||
return; | return; | ||||
/* Now program new ones. */ | /* Now program new ones. */ | ||||
if (DC_IS_CENTAUR(sc)) | if (DC_IS_CENTAUR(sc)) | ||||
if_foreach_llmaddr(ifp, dc_hash_maddr_admtek_le, &ctx); | if_foreach_llmaddr(ifp, dc_hash_maddr_admtek_le, &ctx); | ||||
else | else | ||||
if_foreach_llmaddr(ifp, dc_hash_maddr_admtek_be, &ctx.hashes); | if_foreach_llmaddr(ifp, dc_hash_maddr_admtek_be, &ctx.hashes); | ||||
CSR_WRITE_4(sc, DC_AL_MAR0, ctx.hashes[0]); | CSR_WRITE_4(sc, DC_AL_MAR0, ctx.hashes[0]); | ||||
CSR_WRITE_4(sc, DC_AL_MAR1, ctx.hashes[1]); | CSR_WRITE_4(sc, DC_AL_MAR1, ctx.hashes[1]); | ||||
} | } | ||||
static void | static void | ||||
dc_setfilt_asix(struct dc_softc *sc) | dc_setfilt_asix(struct dc_softc *sc) | ||||
{ | { | ||||
uint32_t eaddr[(ETHER_ADDR_LEN+3)/4]; | uint32_t eaddr[(ETHER_ADDR_LEN+3)/4]; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
uint32_t hashes[2] = { 0, 0 }; | uint32_t hashes[2] = { 0, 0 }; | ||||
ifp = sc->dc_ifp; | ifp = sc->dc_ifp; | ||||
/* Init our MAC address. */ | /* Init our MAC address. */ | ||||
bcopy(IF_LLADDR(sc->dc_ifp), eaddr, ETHER_ADDR_LEN); | bcopy(if_getlladdr(sc->dc_ifp), eaddr, ETHER_ADDR_LEN); | ||||
CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR0); | CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR0); | ||||
CSR_WRITE_4(sc, DC_AX_FILTDATA, eaddr[0]); | CSR_WRITE_4(sc, DC_AX_FILTDATA, eaddr[0]); | ||||
CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR1); | CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR1); | ||||
CSR_WRITE_4(sc, DC_AX_FILTDATA, eaddr[1]); | CSR_WRITE_4(sc, DC_AX_FILTDATA, eaddr[1]); | ||||
/* If we want promiscuous mode, set the allframes bit. */ | /* If we want promiscuous mode, set the allframes bit. */ | ||||
if (ifp->if_flags & IFF_PROMISC) | if (if_getflags(ifp) & IFF_PROMISC) | ||||
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | ||||
else | else | ||||
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | ||||
if (ifp->if_flags & IFF_ALLMULTI) | if (if_getflags(ifp) & IFF_ALLMULTI) | ||||
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | ||||
else | else | ||||
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | ||||
/* | /* | ||||
* The ASIX chip has a special bit to enable reception | * The ASIX chip has a special bit to enable reception | ||||
* of broadcast frames. | * of broadcast frames. | ||||
*/ | */ | ||||
if (ifp->if_flags & IFF_BROADCAST) | if (if_getflags(ifp) & IFF_BROADCAST) | ||||
DC_SETBIT(sc, DC_NETCFG, DC_AX_NETCFG_RX_BROAD); | DC_SETBIT(sc, DC_NETCFG, DC_AX_NETCFG_RX_BROAD); | ||||
else | else | ||||
DC_CLRBIT(sc, DC_NETCFG, DC_AX_NETCFG_RX_BROAD); | DC_CLRBIT(sc, DC_NETCFG, DC_AX_NETCFG_RX_BROAD); | ||||
/* first, zot all the existing hash bits */ | /* first, zot all the existing hash bits */ | ||||
CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0); | CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0); | ||||
CSR_WRITE_4(sc, DC_AX_FILTDATA, 0); | CSR_WRITE_4(sc, DC_AX_FILTDATA, 0); | ||||
CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR1); | CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR1); | ||||
CSR_WRITE_4(sc, DC_AX_FILTDATA, 0); | CSR_WRITE_4(sc, DC_AX_FILTDATA, 0); | ||||
/* | /* | ||||
* If we're already in promisc or allmulti mode, we | * If we're already in promisc or allmulti mode, we | ||||
* don't have to bother programming the multicast filter. | * don't have to bother programming the multicast filter. | ||||
*/ | */ | ||||
if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) | if (if_getflags(ifp) & (IFF_PROMISC | IFF_ALLMULTI)) | ||||
return; | return; | ||||
/* now program new ones */ | /* now program new ones */ | ||||
if_foreach_llmaddr(ifp, dc_hash_maddr_admtek_be, hashes); | if_foreach_llmaddr(ifp, dc_hash_maddr_admtek_be, hashes); | ||||
CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0); | CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0); | ||||
CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[0]); | CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[0]); | ||||
CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR1); | CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR1); | ||||
Show All 15 Lines | dc_hash_maddr_uli(void *arg, struct sockaddr_dl *sdl, u_int mcnt) | ||||
return (1); | return (1); | ||||
} | } | ||||
static void | static void | ||||
dc_setfilt_uli(struct dc_softc *sc) | dc_setfilt_uli(struct dc_softc *sc) | ||||
{ | { | ||||
uint8_t eaddr[ETHER_ADDR_LEN]; | uint8_t eaddr[ETHER_ADDR_LEN]; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
struct dc_desc *sframe; | struct dc_desc *sframe; | ||||
uint32_t filter, *sp; | uint32_t filter, *sp; | ||||
int i, mcnt; | int i, mcnt; | ||||
ifp = sc->dc_ifp; | ifp = sc->dc_ifp; | ||||
i = sc->dc_cdata.dc_tx_prod; | i = sc->dc_cdata.dc_tx_prod; | ||||
DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT); | DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT); | ||||
sc->dc_cdata.dc_tx_cnt++; | sc->dc_cdata.dc_tx_cnt++; | ||||
sframe = &sc->dc_ldata.dc_tx_list[i]; | sframe = &sc->dc_ldata.dc_tx_list[i]; | ||||
sp = sc->dc_cdata.dc_sbuf; | sp = sc->dc_cdata.dc_sbuf; | ||||
bzero(sp, DC_SFRAME_LEN); | bzero(sp, DC_SFRAME_LEN); | ||||
sframe->dc_data = htole32(DC_ADDR_LO(sc->dc_saddr)); | sframe->dc_data = htole32(DC_ADDR_LO(sc->dc_saddr)); | ||||
sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP | | sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP | | ||||
DC_TXCTL_TLINK | DC_FILTER_PERFECT | DC_TXCTL_FINT); | DC_TXCTL_TLINK | DC_FILTER_PERFECT | DC_TXCTL_FINT); | ||||
sc->dc_cdata.dc_tx_chain[i] = (struct mbuf *)sc->dc_cdata.dc_sbuf; | sc->dc_cdata.dc_tx_chain[i] = (struct mbuf *)sc->dc_cdata.dc_sbuf; | ||||
/* Set station address. */ | /* Set station address. */ | ||||
bcopy(IF_LLADDR(sc->dc_ifp), eaddr, ETHER_ADDR_LEN); | bcopy(if_getlladdr(sc->dc_ifp), eaddr, ETHER_ADDR_LEN); | ||||
*sp++ = DC_SP_MAC(eaddr[1] << 8 | eaddr[0]); | *sp++ = DC_SP_MAC(eaddr[1] << 8 | eaddr[0]); | ||||
*sp++ = DC_SP_MAC(eaddr[3] << 8 | eaddr[2]); | *sp++ = DC_SP_MAC(eaddr[3] << 8 | eaddr[2]); | ||||
*sp++ = DC_SP_MAC(eaddr[5] << 8 | eaddr[4]); | *sp++ = DC_SP_MAC(eaddr[5] << 8 | eaddr[4]); | ||||
/* Set broadcast address. */ | /* Set broadcast address. */ | ||||
*sp++ = DC_SP_MAC(0xFFFF); | *sp++ = DC_SP_MAC(0xFFFF); | ||||
*sp++ = DC_SP_MAC(0xFFFF); | *sp++ = DC_SP_MAC(0xFFFF); | ||||
*sp++ = DC_SP_MAC(0xFFFF); | *sp++ = DC_SP_MAC(0xFFFF); | ||||
Show All 12 Lines | for (; mcnt < DC_ULI_FILTER_NPERF; mcnt++) { | ||||
*sp++ = DC_SP_MAC(0xFFFF); | *sp++ = DC_SP_MAC(0xFFFF); | ||||
*sp++ = DC_SP_MAC(0xFFFF); | *sp++ = DC_SP_MAC(0xFFFF); | ||||
*sp++ = DC_SP_MAC(0xFFFF); | *sp++ = DC_SP_MAC(0xFFFF); | ||||
} | } | ||||
if (filter & (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)) | if (filter & (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)) | ||||
CSR_WRITE_4(sc, DC_NETCFG, | CSR_WRITE_4(sc, DC_NETCFG, | ||||
filter & ~(DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)); | filter & ~(DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)); | ||||
if (ifp->if_flags & IFF_PROMISC) | if (if_getflags(ifp) & IFF_PROMISC) | ||||
filter |= DC_NETCFG_RX_PROMISC | DC_NETCFG_RX_ALLMULTI; | filter |= DC_NETCFG_RX_PROMISC | DC_NETCFG_RX_ALLMULTI; | ||||
if (ifp->if_flags & IFF_ALLMULTI) | if (if_getflags(ifp) & IFF_ALLMULTI) | ||||
filter |= DC_NETCFG_RX_ALLMULTI; | filter |= DC_NETCFG_RX_ALLMULTI; | ||||
CSR_WRITE_4(sc, DC_NETCFG, | CSR_WRITE_4(sc, DC_NETCFG, | ||||
filter & ~(DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)); | filter & ~(DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)); | ||||
if (filter & (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)) | if (filter & (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)) | ||||
CSR_WRITE_4(sc, DC_NETCFG, filter); | CSR_WRITE_4(sc, DC_NETCFG, filter); | ||||
sframe->dc_status = htole32(DC_TXSTAT_OWN); | sframe->dc_status = htole32(DC_TXSTAT_OWN); | ||||
bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap, BUS_DMASYNC_PREREAD | | bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap, BUS_DMASYNC_PREREAD | | ||||
Show All 19 Lines | dc_hash_maddr_xircom(void *arg, struct sockaddr_dl *sdl, u_int cnt) | ||||
sc->dc_cdata.dc_sbuf[h >> 4] |= htole32(1 << (h & 0xF)); | sc->dc_cdata.dc_sbuf[h >> 4] |= htole32(1 << (h & 0xF)); | ||||
return (1); | return (1); | ||||
} | } | ||||
static void | static void | ||||
dc_setfilt_xircom(struct dc_softc *sc) | dc_setfilt_xircom(struct dc_softc *sc) | ||||
{ | { | ||||
uint16_t eaddr[(ETHER_ADDR_LEN+1)/2]; | uint16_t eaddr[(ETHER_ADDR_LEN+1)/2]; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
struct dc_desc *sframe; | struct dc_desc *sframe; | ||||
uint32_t h, *sp; | uint32_t h, *sp; | ||||
int i; | int i; | ||||
ifp = sc->dc_ifp; | ifp = sc->dc_ifp; | ||||
DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)); | DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)); | ||||
i = sc->dc_cdata.dc_tx_prod; | i = sc->dc_cdata.dc_tx_prod; | ||||
DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT); | DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT); | ||||
sc->dc_cdata.dc_tx_cnt++; | sc->dc_cdata.dc_tx_cnt++; | ||||
sframe = &sc->dc_ldata.dc_tx_list[i]; | sframe = &sc->dc_ldata.dc_tx_list[i]; | ||||
sp = sc->dc_cdata.dc_sbuf; | sp = sc->dc_cdata.dc_sbuf; | ||||
bzero(sp, DC_SFRAME_LEN); | bzero(sp, DC_SFRAME_LEN); | ||||
sframe->dc_data = htole32(DC_ADDR_LO(sc->dc_saddr)); | sframe->dc_data = htole32(DC_ADDR_LO(sc->dc_saddr)); | ||||
sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP | | sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP | | ||||
DC_TXCTL_TLINK | DC_FILTER_HASHPERF | DC_TXCTL_FINT); | DC_TXCTL_TLINK | DC_FILTER_HASHPERF | DC_TXCTL_FINT); | ||||
sc->dc_cdata.dc_tx_chain[i] = (struct mbuf *)sc->dc_cdata.dc_sbuf; | sc->dc_cdata.dc_tx_chain[i] = (struct mbuf *)sc->dc_cdata.dc_sbuf; | ||||
/* If we want promiscuous mode, set the allframes bit. */ | /* If we want promiscuous mode, set the allframes bit. */ | ||||
if (ifp->if_flags & IFF_PROMISC) | if (if_getflags(ifp) & IFF_PROMISC) | ||||
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | ||||
else | else | ||||
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); | ||||
if (ifp->if_flags & IFF_ALLMULTI) | if (if_getflags(ifp) & IFF_ALLMULTI) | ||||
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | ||||
else | else | ||||
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); | ||||
if_foreach_llmaddr(ifp, dc_hash_maddr_xircom, &sp); | if_foreach_llmaddr(ifp, dc_hash_maddr_xircom, &sp); | ||||
if (ifp->if_flags & IFF_BROADCAST) { | if (if_getflags(ifp) & IFF_BROADCAST) { | ||||
h = dc_mchash_le(sc, ifp->if_broadcastaddr); | h = dc_mchash_le(sc, if_getbroadcastaddr(ifp)); | ||||
sp[h >> 4] |= htole32(1 << (h & 0xF)); | sp[h >> 4] |= htole32(1 << (h & 0xF)); | ||||
} | } | ||||
/* Set our MAC address. */ | /* Set our MAC address. */ | ||||
bcopy(IF_LLADDR(sc->dc_ifp), eaddr, ETHER_ADDR_LEN); | bcopy(if_getlladdr(sc->dc_ifp), eaddr, ETHER_ADDR_LEN); | ||||
sp[0] = DC_SP_MAC(eaddr[0]); | sp[0] = DC_SP_MAC(eaddr[0]); | ||||
sp[1] = DC_SP_MAC(eaddr[1]); | sp[1] = DC_SP_MAC(eaddr[1]); | ||||
sp[2] = DC_SP_MAC(eaddr[2]); | sp[2] = DC_SP_MAC(eaddr[2]); | ||||
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON); | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON); | ||||
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON); | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON); | ||||
sframe->dc_status = htole32(DC_TXSTAT_OWN); | sframe->dc_status = htole32(DC_TXSTAT_OWN); | ||||
bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap, BUS_DMASYNC_PREREAD | | bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap, BUS_DMASYNC_PREREAD | | ||||
▲ Show 20 Lines • Show All 692 Lines • ▼ Show 20 Lines | |||||
* setup and ethernet/BPF attach. | * setup and ethernet/BPF attach. | ||||
*/ | */ | ||||
static int | static int | ||||
dc_attach(device_t dev) | dc_attach(device_t dev) | ||||
{ | { | ||||
uint32_t eaddr[(ETHER_ADDR_LEN+3)/4]; | uint32_t eaddr[(ETHER_ADDR_LEN+3)/4]; | ||||
uint32_t command; | uint32_t command; | ||||
struct dc_softc *sc; | struct dc_softc *sc; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
struct dc_mediainfo *m; | struct dc_mediainfo *m; | ||||
uint32_t reg, revision; | uint32_t reg, revision; | ||||
uint16_t *srom; | uint16_t *srom; | ||||
int error, mac_offset, n, phy, rid, tmp; | int error, mac_offset, n, phy, rid, tmp; | ||||
uint8_t *mac; | uint8_t *mac; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
sc->dc_dev = dev; | sc->dc_dev = dev; | ||||
▲ Show 20 Lines • Show All 342 Lines • ▼ Show 20 Lines | if ((error = dc_dma_alloc(sc)) != 0) | ||||
goto fail; | goto fail; | ||||
ifp = sc->dc_ifp = if_alloc(IFT_ETHER); | ifp = sc->dc_ifp = if_alloc(IFT_ETHER); | ||||
if (ifp == NULL) { | if (ifp == NULL) { | ||||
device_printf(dev, "can not if_alloc()\n"); | device_printf(dev, "can not if_alloc()\n"); | ||||
error = ENOSPC; | error = ENOSPC; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
ifp->if_softc = sc; | if_setsoftc(ifp, sc); | ||||
if_initname(ifp, device_get_name(dev), device_get_unit(dev)); | if_initname(ifp, device_get_name(dev), device_get_unit(dev)); | ||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); | ||||
ifp->if_ioctl = dc_ioctl; | if_setioctlfn(ifp, dc_ioctl); | ||||
ifp->if_start = dc_start; | if_setstartfn(ifp, dc_start); | ||||
ifp->if_init = dc_init; | if_setinitfn(ifp, dc_init); | ||||
IFQ_SET_MAXLEN(&ifp->if_snd, DC_TX_LIST_CNT - 1); | if_setsendqlen(ifp, DC_TX_LIST_CNT - 1); | ||||
ifp->if_snd.ifq_drv_maxlen = DC_TX_LIST_CNT - 1; | if_setsendqready(ifp); | ||||
IFQ_SET_READY(&ifp->if_snd); | |||||
/* | /* | ||||
* Do MII setup. If this is a 21143, check for a PHY on the | * Do MII setup. If this is a 21143, check for a PHY on the | ||||
* MII bus after applying any necessary fixups to twiddle the | * MII bus after applying any necessary fixups to twiddle the | ||||
* GPIO bits. If we don't end up finding a PHY, restore the | * GPIO bits. If we don't end up finding a PHY, restore the | ||||
* old selection (SIA only or SIA/SYM) and attach the dcphy | * old selection (SIA only or SIA/SYM) and attach the dcphy | ||||
* driver instead. | * driver instead. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | if (DC_IS_ADMTEK(sc)) { | ||||
* Set automatic TX underrun recovery for the ADMtek chips | * Set automatic TX underrun recovery for the ADMtek chips | ||||
*/ | */ | ||||
DC_SETBIT(sc, DC_AL_CR, DC_AL_CR_ATUR); | DC_SETBIT(sc, DC_AL_CR, DC_AL_CR_ATUR); | ||||
} | } | ||||
/* | /* | ||||
* Tell the upper layer(s) we support long frames. | * Tell the upper layer(s) we support long frames. | ||||
*/ | */ | ||||
ifp->if_hdrlen = sizeof(struct ether_vlan_header); | if_setifheaderlen(ifp, sizeof(struct ether_vlan_header)); | ||||
ifp->if_capabilities |= IFCAP_VLAN_MTU; | if_setcapabilitiesbit(ifp, IFCAP_VLAN_MTU, 0); | ||||
ifp->if_capenable = ifp->if_capabilities; | if_setcapenable(ifp, if_getcapabilities(ifp)); | ||||
#ifdef DEVICE_POLLING | #ifdef DEVICE_POLLING | ||||
ifp->if_capabilities |= IFCAP_POLLING; | if_setcapabilitiesbit(ifp, IFCAP_POLLING, 0); | ||||
#endif | #endif | ||||
callout_init_mtx(&sc->dc_stat_ch, &sc->dc_mtx, 0); | callout_init_mtx(&sc->dc_stat_ch, &sc->dc_mtx, 0); | ||||
callout_init_mtx(&sc->dc_wdog_ch, &sc->dc_mtx, 0); | callout_init_mtx(&sc->dc_wdog_ch, &sc->dc_mtx, 0); | ||||
/* | /* | ||||
* Call MI attach routine. | * Call MI attach routine. | ||||
*/ | */ | ||||
Show All 21 Lines | |||||
* the error case in attach and the normal detach case so it needs | * the error case in attach and the normal detach case so it needs | ||||
* to be careful about only freeing resources that have actually been | * to be careful about only freeing resources that have actually been | ||||
* allocated. | * allocated. | ||||
*/ | */ | ||||
static int | static int | ||||
dc_detach(device_t dev) | dc_detach(device_t dev) | ||||
{ | { | ||||
struct dc_softc *sc; | struct dc_softc *sc; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
struct dc_mediainfo *m; | struct dc_mediainfo *m; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
KASSERT(mtx_initialized(&sc->dc_mtx), ("dc mutex not initialized")); | KASSERT(mtx_initialized(&sc->dc_mtx), ("dc mutex not initialized")); | ||||
ifp = sc->dc_ifp; | ifp = sc->dc_ifp; | ||||
#ifdef DEVICE_POLLING | #ifdef DEVICE_POLLING | ||||
if (ifp != NULL && ifp->if_capenable & IFCAP_POLLING) | if (ifp != NULL && if_getcapenable(ifp) & IFCAP_POLLING) | ||||
ether_poll_deregister(ifp); | ether_poll_deregister(ifp); | ||||
#endif | #endif | ||||
/* These should only be active if attach succeeded */ | /* These should only be active if attach succeeded */ | ||||
if (device_is_attached(dev)) { | if (device_is_attached(dev)) { | ||||
DC_LOCK(sc); | DC_LOCK(sc); | ||||
dc_stop(sc); | dc_stop(sc); | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
▲ Show 20 Lines • Show All 307 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* A frame has been uploaded: pass the resulting mbuf chain up to | * A frame has been uploaded: pass the resulting mbuf chain up to | ||||
* the higher level protocols. | * the higher level protocols. | ||||
*/ | */ | ||||
static int | static int | ||||
dc_rxeof(struct dc_softc *sc) | dc_rxeof(struct dc_softc *sc) | ||||
{ | { | ||||
struct mbuf *m; | struct mbuf *m; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
struct dc_desc *cur_rx; | struct dc_desc *cur_rx; | ||||
int i, total_len, rx_npkts; | int i, total_len, rx_npkts; | ||||
uint32_t rxstat; | uint32_t rxstat; | ||||
DC_LOCK_ASSERT(sc); | DC_LOCK_ASSERT(sc); | ||||
ifp = sc->dc_ifp; | ifp = sc->dc_ifp; | ||||
rx_npkts = 0; | rx_npkts = 0; | ||||
bus_dmamap_sync(sc->dc_rx_ltag, sc->dc_rx_lmap, BUS_DMASYNC_POSTREAD | | bus_dmamap_sync(sc->dc_rx_ltag, sc->dc_rx_lmap, BUS_DMASYNC_POSTREAD | | ||||
BUS_DMASYNC_POSTWRITE); | BUS_DMASYNC_POSTWRITE); | ||||
for (i = sc->dc_cdata.dc_rx_prod; | for (i = sc->dc_cdata.dc_rx_prod; | ||||
(ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; | (if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0; | ||||
DC_INC(i, DC_RX_LIST_CNT)) { | DC_INC(i, DC_RX_LIST_CNT)) { | ||||
#ifdef DEVICE_POLLING | #ifdef DEVICE_POLLING | ||||
if (ifp->if_capenable & IFCAP_POLLING) { | if (if_getcapenable(ifp) & IFCAP_POLLING) { | ||||
if (sc->rxcycles <= 0) | if (sc->rxcycles <= 0) | ||||
break; | break; | ||||
sc->rxcycles--; | sc->rxcycles--; | ||||
} | } | ||||
#endif | #endif | ||||
cur_rx = &sc->dc_ldata.dc_rx_list[i]; | cur_rx = &sc->dc_ldata.dc_rx_list[i]; | ||||
rxstat = le32toh(cur_rx->dc_status); | rxstat = le32toh(cur_rx->dc_status); | ||||
if ((rxstat & DC_RXSTAT_OWN) != 0) | if ((rxstat & DC_RXSTAT_OWN) != 0) | ||||
Show All 30 Lines | if ((rxstat & DC_RXSTAT_RXERR)) { | ||||
DC_RXSTAT_RUNT | DC_RXSTAT_DE))) { | DC_RXSTAT_RUNT | DC_RXSTAT_DE))) { | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | ||||
if (rxstat & DC_RXSTAT_COLLSEEN) | if (rxstat & DC_RXSTAT_COLLSEEN) | ||||
if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); | if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); | ||||
dc_discard_rxbuf(sc, i); | dc_discard_rxbuf(sc, i); | ||||
if (rxstat & DC_RXSTAT_CRCERR) | if (rxstat & DC_RXSTAT_CRCERR) | ||||
continue; | continue; | ||||
else { | else { | ||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING; | if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING); | ||||
dc_init_locked(sc); | dc_init_locked(sc); | ||||
return (rx_npkts); | return (rx_npkts); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/* No errors; receive the packet. */ | /* No errors; receive the packet. */ | ||||
total_len -= ETHER_CRC_LEN; | total_len -= ETHER_CRC_LEN; | ||||
Show All 26 Lines | #else | ||||
continue; | continue; | ||||
} | } | ||||
m = m0; | m = m0; | ||||
} | } | ||||
#endif | #endif | ||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); | if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
(*ifp->if_input)(ifp, m); | if_input(ifp, m); | ||||
DC_LOCK(sc); | DC_LOCK(sc); | ||||
} | } | ||||
sc->dc_cdata.dc_rx_prod = i; | sc->dc_cdata.dc_rx_prod = i; | ||||
return (rx_npkts); | return (rx_npkts); | ||||
} | } | ||||
/* | /* | ||||
* A frame was downloaded to the chip. It's safe for us to clean up | * A frame was downloaded to the chip. It's safe for us to clean up | ||||
* the list buffers. | * the list buffers. | ||||
*/ | */ | ||||
static void | static void | ||||
dc_txeof(struct dc_softc *sc) | dc_txeof(struct dc_softc *sc) | ||||
{ | { | ||||
struct dc_desc *cur_tx; | struct dc_desc *cur_tx; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
int idx, setup; | int idx, setup; | ||||
uint32_t ctl, txstat; | uint32_t ctl, txstat; | ||||
if (sc->dc_cdata.dc_tx_cnt == 0) | if (sc->dc_cdata.dc_tx_cnt == 0) | ||||
return; | return; | ||||
ifp = sc->dc_ifp; | ifp = sc->dc_ifp; | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | for (idx = sc->dc_cdata.dc_tx_cons; idx != sc->dc_cdata.dc_tx_prod; | ||||
if (txstat & DC_TXSTAT_ERRSUM) { | if (txstat & DC_TXSTAT_ERRSUM) { | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | ||||
if (txstat & DC_TXSTAT_EXCESSCOLL) | if (txstat & DC_TXSTAT_EXCESSCOLL) | ||||
if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); | if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); | ||||
if (txstat & DC_TXSTAT_LATECOLL) | if (txstat & DC_TXSTAT_LATECOLL) | ||||
if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); | if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); | ||||
if (!(txstat & DC_TXSTAT_UNDERRUN)) { | if (!(txstat & DC_TXSTAT_UNDERRUN)) { | ||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING; | if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING); | ||||
dc_init_locked(sc); | dc_init_locked(sc); | ||||
return; | return; | ||||
} | } | ||||
} else | } else | ||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | ||||
if_inc_counter(ifp, IFCOUNTER_COLLISIONS, (txstat & DC_TXSTAT_COLLCNT) >> 3); | if_inc_counter(ifp, IFCOUNTER_COLLISIONS, (txstat & DC_TXSTAT_COLLCNT) >> 3); | ||||
bus_dmamap_sync(sc->dc_tx_mtag, sc->dc_cdata.dc_tx_map[idx], | bus_dmamap_sync(sc->dc_tx_mtag, sc->dc_cdata.dc_tx_map[idx], | ||||
BUS_DMASYNC_POSTWRITE); | BUS_DMASYNC_POSTWRITE); | ||||
bus_dmamap_unload(sc->dc_tx_mtag, sc->dc_cdata.dc_tx_map[idx]); | bus_dmamap_unload(sc->dc_tx_mtag, sc->dc_cdata.dc_tx_map[idx]); | ||||
m_freem(sc->dc_cdata.dc_tx_chain[idx]); | m_freem(sc->dc_cdata.dc_tx_chain[idx]); | ||||
sc->dc_cdata.dc_tx_chain[idx] = NULL; | sc->dc_cdata.dc_tx_chain[idx] = NULL; | ||||
} | } | ||||
sc->dc_cdata.dc_tx_cons = idx; | sc->dc_cdata.dc_tx_cons = idx; | ||||
if (sc->dc_cdata.dc_tx_cnt <= DC_TX_LIST_CNT - DC_TX_LIST_RSVD) { | if (sc->dc_cdata.dc_tx_cnt <= DC_TX_LIST_CNT - DC_TX_LIST_RSVD) { | ||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); | ||||
if (sc->dc_cdata.dc_tx_cnt == 0) | if (sc->dc_cdata.dc_tx_cnt == 0) | ||||
sc->dc_wdog_timer = 0; | sc->dc_wdog_timer = 0; | ||||
} | } | ||||
if (setup > 0) | if (setup > 0) | ||||
bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap, | bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap, | ||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | ||||
} | } | ||||
static void | static void | ||||
dc_tick(void *xsc) | dc_tick(void *xsc) | ||||
{ | { | ||||
struct dc_softc *sc; | struct dc_softc *sc; | ||||
struct mii_data *mii; | struct mii_data *mii; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
uint32_t r; | uint32_t r; | ||||
sc = xsc; | sc = xsc; | ||||
DC_LOCK_ASSERT(sc); | DC_LOCK_ASSERT(sc); | ||||
ifp = sc->dc_ifp; | ifp = sc->dc_ifp; | ||||
mii = device_get_softc(sc->dc_miibus); | mii = device_get_softc(sc->dc_miibus); | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | dc_tick(void *xsc) | ||||
* | * | ||||
* What we do here is prevent the TX start routine from sending | * What we do here is prevent the TX start routine from sending | ||||
* any packets until a link has been established. After the | * any packets until a link has been established. After the | ||||
* interface has been initialized, the tick routine will poll | * interface has been initialized, the tick routine will poll | ||||
* the state of the PHY until the IFM_ACTIVE flag is set. Until | * the state of the PHY until the IFM_ACTIVE flag is set. Until | ||||
* that time, packets will stay in the send queue, and once the | * that time, packets will stay in the send queue, and once the | ||||
* link comes up, they will be flushed out to the wire. | * link comes up, they will be flushed out to the wire. | ||||
*/ | */ | ||||
if (sc->dc_link != 0 && !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) | if (sc->dc_link != 0 && !if_sendq_empty(ifp)) | ||||
dc_start_locked(ifp); | dc_start_locked(ifp); | ||||
if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link) | if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link) | ||||
callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc); | callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc); | ||||
else | else | ||||
callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc); | callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | if ((sc->dc_flags & DC_TX_STORENFWD) == 0) { | ||||
reinit++; | reinit++; | ||||
} | } | ||||
if (reinit == 0) { | if (reinit == 0) { | ||||
CSR_WRITE_4(sc, DC_NETCFG, netcfg); | CSR_WRITE_4(sc, DC_NETCFG, netcfg); | ||||
if (DC_IS_INTEL(sc)) | if (DC_IS_INTEL(sc)) | ||||
CSR_WRITE_4(sc, DC_NETCFG, netcfg | DC_NETCFG_TX_ON); | CSR_WRITE_4(sc, DC_NETCFG, netcfg | DC_NETCFG_TX_ON); | ||||
} else { | } else { | ||||
sc->dc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; | if_setdrvflagbits(sc->dc_ifp, 0, IFF_DRV_RUNNING); | ||||
dc_init_locked(sc); | dc_init_locked(sc); | ||||
} | } | ||||
} | } | ||||
#ifdef DEVICE_POLLING | #ifdef DEVICE_POLLING | ||||
static poll_handler_t dc_poll; | static poll_handler_t dc_poll; | ||||
static int | static int | ||||
dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) | dc_poll(if_t ifp, enum poll_cmd cmd, int count) | ||||
{ | { | ||||
struct dc_softc *sc = ifp->if_softc; | struct dc_softc *sc = if_getsoftc(ifp); | ||||
int rx_npkts = 0; | int rx_npkts = 0; | ||||
DC_LOCK(sc); | DC_LOCK(sc); | ||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { | if (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) { | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
return (rx_npkts); | return (rx_npkts); | ||||
} | } | ||||
sc->rxcycles = count; | sc->rxcycles = count; | ||||
rx_npkts = dc_rxeof(sc); | rx_npkts = dc_rxeof(sc); | ||||
dc_txeof(sc); | dc_txeof(sc); | ||||
if (!IFQ_IS_EMPTY(&ifp->if_snd) && | if (!if_sendq_empty(ifp) && | ||||
!(ifp->if_drv_flags & IFF_DRV_OACTIVE)) | !(if_getdrvflags(ifp) & IFF_DRV_OACTIVE)) | ||||
dc_start_locked(ifp); | dc_start_locked(ifp); | ||||
if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */ | if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */ | ||||
uint32_t status; | uint32_t status; | ||||
status = CSR_READ_4(sc, DC_ISR); | status = CSR_READ_4(sc, DC_ISR); | ||||
status &= (DC_ISR_RX_WATDOGTIMEO | DC_ISR_RX_NOBUF | | status &= (DC_ISR_RX_WATDOGTIMEO | DC_ISR_RX_NOBUF | | ||||
DC_ISR_TX_NOBUF | DC_ISR_TX_IDLE | DC_ISR_TX_UNDERRUN | | DC_ISR_TX_NOBUF | DC_ISR_TX_IDLE | DC_ISR_TX_UNDERRUN | | ||||
Show All 16 Lines | if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */ | ||||
if (status & DC_ISR_TX_IDLE && sc->dc_cdata.dc_tx_cnt) | if (status & DC_ISR_TX_IDLE && sc->dc_cdata.dc_tx_cnt) | ||||
CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF); | CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF); | ||||
if (status & DC_ISR_TX_UNDERRUN) | if (status & DC_ISR_TX_UNDERRUN) | ||||
dc_tx_underrun(sc); | dc_tx_underrun(sc); | ||||
if (status & DC_ISR_BUS_ERR) { | if (status & DC_ISR_BUS_ERR) { | ||||
if_printf(ifp, "%s: bus error\n", __func__); | if_printf(ifp, "%s: bus error\n", __func__); | ||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING; | if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING); | ||||
dc_init_locked(sc); | dc_init_locked(sc); | ||||
} | } | ||||
} | } | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
return (rx_npkts); | return (rx_npkts); | ||||
} | } | ||||
#endif /* DEVICE_POLLING */ | #endif /* DEVICE_POLLING */ | ||||
static void | static void | ||||
dc_intr(void *arg) | dc_intr(void *arg) | ||||
{ | { | ||||
struct dc_softc *sc; | struct dc_softc *sc; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
uint32_t r, status; | uint32_t r, status; | ||||
int n; | int n; | ||||
sc = arg; | sc = arg; | ||||
if (sc->suspended) | if (sc->suspended) | ||||
return; | return; | ||||
DC_LOCK(sc); | DC_LOCK(sc); | ||||
status = CSR_READ_4(sc, DC_ISR); | status = CSR_READ_4(sc, DC_ISR); | ||||
if (status == 0xFFFFFFFF || (status & DC_INTRS) == 0) { | if (status == 0xFFFFFFFF || (status & DC_INTRS) == 0) { | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
return; | return; | ||||
} | } | ||||
ifp = sc->dc_ifp; | ifp = sc->dc_ifp; | ||||
#ifdef DEVICE_POLLING | #ifdef DEVICE_POLLING | ||||
if (ifp->if_capenable & IFCAP_POLLING) { | if (if_getcapenable(ifp) & IFCAP_POLLING) { | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
return; | return; | ||||
} | } | ||||
#endif | #endif | ||||
/* Disable interrupts. */ | /* Disable interrupts. */ | ||||
CSR_WRITE_4(sc, DC_IMR, 0x00000000); | CSR_WRITE_4(sc, DC_IMR, 0x00000000); | ||||
for (n = 16; n > 0; n--) { | for (n = 16; n > 0; n--) { | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) | if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) | ||||
break; | break; | ||||
/* Ack interrupts. */ | /* Ack interrupts. */ | ||||
CSR_WRITE_4(sc, DC_ISR, status); | CSR_WRITE_4(sc, DC_ISR, status); | ||||
if (status & DC_ISR_RX_OK) { | if (status & DC_ISR_RX_OK) { | ||||
if (dc_rxeof(sc) == 0) { | if (dc_rxeof(sc) == 0) { | ||||
while (dc_rx_resync(sc)) | while (dc_rx_resync(sc)) | ||||
dc_rxeof(sc); | dc_rxeof(sc); | ||||
Show All 19 Lines | if ((status & DC_ISR_RX_WATDOGTIMEO) | ||||
r = CSR_READ_4(sc, DC_FRAMESDISCARDED); | r = CSR_READ_4(sc, DC_FRAMESDISCARDED); | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, (r & 0xffff) + ((r >> 17) & 0x7ff)); | if_inc_counter(ifp, IFCOUNTER_IERRORS, (r & 0xffff) + ((r >> 17) & 0x7ff)); | ||||
if (dc_rxeof(sc) == 0) { | if (dc_rxeof(sc) == 0) { | ||||
while (dc_rx_resync(sc)) | while (dc_rx_resync(sc)) | ||||
dc_rxeof(sc); | dc_rxeof(sc); | ||||
} | } | ||||
} | } | ||||
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) | if (!if_sendq_empty(ifp)) | ||||
dc_start_locked(ifp); | dc_start_locked(ifp); | ||||
if (status & DC_ISR_BUS_ERR) { | if (status & DC_ISR_BUS_ERR) { | ||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING; | if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING); | ||||
dc_init_locked(sc); | dc_init_locked(sc); | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
return; | return; | ||||
} | } | ||||
status = CSR_READ_4(sc, DC_ISR); | status = CSR_READ_4(sc, DC_ISR); | ||||
if (status == 0xFFFFFFFF || (status & DC_INTRS) == 0) | if (status == 0xFFFFFFFF || (status & DC_INTRS) == 0) | ||||
break; | break; | ||||
} | } | ||||
/* Re-enable interrupts. */ | /* Re-enable interrupts. */ | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) | ||||
CSR_WRITE_4(sc, DC_IMR, DC_INTRS); | CSR_WRITE_4(sc, DC_IMR, DC_INTRS); | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
} | } | ||||
/* | /* | ||||
* Encapsulate an mbuf chain in a descriptor by coupling the mbuf data | * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data | ||||
* pointers to the fragment pointers. | * pointers to the fragment pointers. | ||||
▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | dc_encap(struct dc_softc *sc, struct mbuf **m_head) | ||||
map = sc->dc_cdata.dc_tx_map[cur]; | map = sc->dc_cdata.dc_tx_map[cur]; | ||||
sc->dc_cdata.dc_tx_map[cur] = sc->dc_cdata.dc_tx_map[first]; | sc->dc_cdata.dc_tx_map[cur] = sc->dc_cdata.dc_tx_map[first]; | ||||
sc->dc_cdata.dc_tx_map[first] = map; | sc->dc_cdata.dc_tx_map[first] = map; | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
dc_start(struct ifnet *ifp) | dc_start(if_t ifp) | ||||
{ | { | ||||
struct dc_softc *sc; | struct dc_softc *sc; | ||||
sc = ifp->if_softc; | sc = if_getsoftc(ifp); | ||||
DC_LOCK(sc); | DC_LOCK(sc); | ||||
dc_start_locked(ifp); | dc_start_locked(ifp); | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
} | } | ||||
/* | /* | ||||
* Main transmit routine | * Main transmit routine | ||||
* To avoid having to do mbuf copies, we put pointers to the mbuf data | * To avoid having to do mbuf copies, we put pointers to the mbuf data | ||||
* regions directly in the transmit lists. We also save a copy of the | * regions directly in the transmit lists. We also save a copy of the | ||||
* pointers since the transmit list fragment pointers are physical | * pointers since the transmit list fragment pointers are physical | ||||
* addresses. | * addresses. | ||||
*/ | */ | ||||
static void | static void | ||||
dc_start_locked(struct ifnet *ifp) | dc_start_locked(if_t ifp) | ||||
{ | { | ||||
struct dc_softc *sc; | struct dc_softc *sc; | ||||
struct mbuf *m_head; | struct mbuf *m_head; | ||||
int queued; | int queued; | ||||
sc = ifp->if_softc; | sc = if_getsoftc(ifp); | ||||
DC_LOCK_ASSERT(sc); | DC_LOCK_ASSERT(sc); | ||||
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->dc_link == 0) | IFF_DRV_RUNNING || sc->dc_link == 0) | ||||
return; | return; | ||||
sc->dc_cdata.dc_tx_first = sc->dc_cdata.dc_tx_prod; | sc->dc_cdata.dc_tx_first = sc->dc_cdata.dc_tx_prod; | ||||
for (queued = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) { | for (queued = 0; !if_sendq_empty(ifp); ) { | ||||
/* | /* | ||||
* If there's no way we can send any packets, return now. | * If there's no way we can send any packets, return now. | ||||
*/ | */ | ||||
if (sc->dc_cdata.dc_tx_cnt > DC_TX_LIST_CNT - DC_TX_LIST_RSVD) { | if (sc->dc_cdata.dc_tx_cnt > DC_TX_LIST_CNT - DC_TX_LIST_RSVD) { | ||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); | ||||
break; | break; | ||||
} | } | ||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); | m_head = if_dequeue(ifp); | ||||
if (m_head == NULL) | if (m_head == NULL) | ||||
break; | break; | ||||
if (dc_encap(sc, &m_head)) { | if (dc_encap(sc, &m_head)) { | ||||
if (m_head == NULL) | if (m_head == NULL) | ||||
break; | break; | ||||
IFQ_DRV_PREPEND(&ifp->if_snd, m_head); | if_sendq_prepend(ifp, m_head); | ||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); | ||||
break; | break; | ||||
} | } | ||||
queued++; | queued++; | ||||
/* | /* | ||||
* If there's a BPF listener, bounce a copy of this frame | * If there's a BPF listener, bounce a copy of this frame | ||||
* to him. | * to him. | ||||
*/ | */ | ||||
Show All 20 Lines | dc_init(void *xsc) | ||||
DC_LOCK(sc); | DC_LOCK(sc); | ||||
dc_init_locked(sc); | dc_init_locked(sc); | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
} | } | ||||
static void | static void | ||||
dc_init_locked(struct dc_softc *sc) | dc_init_locked(struct dc_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->dc_ifp; | if_t ifp = sc->dc_ifp; | ||||
struct mii_data *mii; | struct mii_data *mii; | ||||
struct ifmedia *ifm; | struct ifmedia *ifm; | ||||
DC_LOCK_ASSERT(sc); | DC_LOCK_ASSERT(sc); | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) | if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) | ||||
return; | return; | ||||
mii = device_get_softc(sc->dc_miibus); | mii = device_get_softc(sc->dc_miibus); | ||||
/* | /* | ||||
* Cancel pending I/O and free all RX/TX buffers. | * Cancel pending I/O and free all RX/TX buffers. | ||||
*/ | */ | ||||
dc_stop(sc); | dc_stop(sc); | ||||
▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | dc_init_locked(struct dc_softc *sc) | ||||
* Enable interrupts. | * Enable interrupts. | ||||
*/ | */ | ||||
#ifdef DEVICE_POLLING | #ifdef DEVICE_POLLING | ||||
/* | /* | ||||
* ... but only if we are not polling, and make sure they are off in | * ... but only if we are not polling, and make sure they are off in | ||||
* the case of polling. Some cards (e.g. fxp) turn interrupts on | * the case of polling. Some cards (e.g. fxp) turn interrupts on | ||||
* after a reset. | * after a reset. | ||||
*/ | */ | ||||
if (ifp->if_capenable & IFCAP_POLLING) | if (if_getcapenable(ifp) & IFCAP_POLLING) | ||||
CSR_WRITE_4(sc, DC_IMR, 0x00000000); | CSR_WRITE_4(sc, DC_IMR, 0x00000000); | ||||
else | else | ||||
#endif | #endif | ||||
CSR_WRITE_4(sc, DC_IMR, DC_INTRS); | CSR_WRITE_4(sc, DC_IMR, DC_INTRS); | ||||
CSR_WRITE_4(sc, DC_ISR, 0xFFFFFFFF); | CSR_WRITE_4(sc, DC_ISR, 0xFFFFFFFF); | ||||
/* Initialize TX jabber and RX watchdog timer. */ | /* Initialize TX jabber and RX watchdog timer. */ | ||||
if (DC_IS_ULI(sc)) | if (DC_IS_ULI(sc)) | ||||
Show All 21 Lines | #endif | ||||
* engine, and we need the transmitter enabled for that. | * engine, and we need the transmitter enabled for that. | ||||
*/ | */ | ||||
dc_setfilt(sc); | dc_setfilt(sc); | ||||
/* Enable receiver. */ | /* Enable receiver. */ | ||||
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON); | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON); | ||||
CSR_WRITE_4(sc, DC_RXSTART, 0xFFFFFFFF); | CSR_WRITE_4(sc, DC_RXSTART, 0xFFFFFFFF); | ||||
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); | ||||
dc_ifmedia_upd_locked(sc); | dc_ifmedia_upd_locked(sc); | ||||
/* Clear missed frames and overflow counter. */ | /* Clear missed frames and overflow counter. */ | ||||
CSR_READ_4(sc, DC_FRAMESDISCARDED); | CSR_READ_4(sc, DC_FRAMESDISCARDED); | ||||
/* Don't start the ticker if this is a homePNA link. */ | /* Don't start the ticker if this is a homePNA link. */ | ||||
if (IFM_SUBTYPE(mii->mii_media.ifm_media) == IFM_HPNA_1) | if (IFM_SUBTYPE(mii->mii_media.ifm_media) == IFM_HPNA_1) | ||||
sc->dc_link = 1; | sc->dc_link = 1; | ||||
else { | else { | ||||
if (sc->dc_flags & DC_21143_NWAY) | if (sc->dc_flags & DC_21143_NWAY) | ||||
callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc); | callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc); | ||||
else | else | ||||
callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc); | callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc); | ||||
} | } | ||||
sc->dc_wdog_timer = 0; | sc->dc_wdog_timer = 0; | ||||
callout_reset(&sc->dc_wdog_ch, hz, dc_watchdog, sc); | callout_reset(&sc->dc_wdog_ch, hz, dc_watchdog, sc); | ||||
} | } | ||||
/* | /* | ||||
* Set media options. | * Set media options. | ||||
*/ | */ | ||||
static int | static int | ||||
dc_ifmedia_upd(struct ifnet *ifp) | dc_ifmedia_upd(if_t ifp) | ||||
{ | { | ||||
struct dc_softc *sc; | struct dc_softc *sc; | ||||
int error; | int error; | ||||
sc = ifp->if_softc; | sc = if_getsoftc(ifp); | ||||
DC_LOCK(sc); | DC_LOCK(sc); | ||||
error = dc_ifmedia_upd_locked(sc); | error = dc_ifmedia_upd_locked(sc); | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
dc_ifmedia_upd_locked(struct dc_softc *sc) | dc_ifmedia_upd_locked(struct dc_softc *sc) | ||||
Show All 18 Lines | dc_ifmedia_upd_locked(struct dc_softc *sc) | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Report current media status. | * Report current media status. | ||||
*/ | */ | ||||
static void | static void | ||||
dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) | dc_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr) | ||||
{ | { | ||||
struct dc_softc *sc; | struct dc_softc *sc; | ||||
struct mii_data *mii; | struct mii_data *mii; | ||||
struct ifmedia *ifm; | struct ifmedia *ifm; | ||||
sc = ifp->if_softc; | sc = if_getsoftc(ifp); | ||||
mii = device_get_softc(sc->dc_miibus); | mii = device_get_softc(sc->dc_miibus); | ||||
DC_LOCK(sc); | DC_LOCK(sc); | ||||
mii_pollstat(mii); | mii_pollstat(mii); | ||||
ifm = &mii->mii_media; | ifm = &mii->mii_media; | ||||
if (DC_IS_DAVICOM(sc)) { | if (DC_IS_DAVICOM(sc)) { | ||||
if (IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) { | if (IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) { | ||||
ifmr->ifm_active = ifm->ifm_media; | ifmr->ifm_active = ifm->ifm_media; | ||||
ifmr->ifm_status = 0; | ifmr->ifm_status = 0; | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
ifmr->ifm_active = mii->mii_media_active; | ifmr->ifm_active = mii->mii_media_active; | ||||
ifmr->ifm_status = mii->mii_media_status; | ifmr->ifm_status = mii->mii_media_status; | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
} | } | ||||
static int | static int | ||||
dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) | dc_ioctl(if_t ifp, u_long command, caddr_t data) | ||||
{ | { | ||||
struct dc_softc *sc = ifp->if_softc; | struct dc_softc *sc = if_getsoftc(ifp); | ||||
struct ifreq *ifr = (struct ifreq *)data; | struct ifreq *ifr = (struct ifreq *)data; | ||||
struct mii_data *mii; | struct mii_data *mii; | ||||
int error = 0; | int error = 0; | ||||
switch (command) { | switch (command) { | ||||
case SIOCSIFFLAGS: | case SIOCSIFFLAGS: | ||||
DC_LOCK(sc); | DC_LOCK(sc); | ||||
if (ifp->if_flags & IFF_UP) { | if (if_getflags(ifp) & IFF_UP) { | ||||
int need_setfilt = (ifp->if_flags ^ sc->dc_if_flags) & | int need_setfilt = (if_getflags(ifp) ^ sc->dc_if_flags) & | ||||
(IFF_PROMISC | IFF_ALLMULTI); | (IFF_PROMISC | IFF_ALLMULTI); | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) { | if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { | ||||
if (need_setfilt) | if (need_setfilt) | ||||
dc_setfilt(sc); | dc_setfilt(sc); | ||||
} else { | } else { | ||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING; | if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING); | ||||
dc_init_locked(sc); | dc_init_locked(sc); | ||||
} | } | ||||
} else { | } else { | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) | ||||
dc_stop(sc); | dc_stop(sc); | ||||
} | } | ||||
sc->dc_if_flags = ifp->if_flags; | sc->dc_if_flags = if_getflags(ifp); | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
break; | break; | ||||
case SIOCADDMULTI: | case SIOCADDMULTI: | ||||
case SIOCDELMULTI: | case SIOCDELMULTI: | ||||
DC_LOCK(sc); | DC_LOCK(sc); | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) | ||||
dc_setfilt(sc); | dc_setfilt(sc); | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
break; | break; | ||||
case SIOCGIFMEDIA: | case SIOCGIFMEDIA: | ||||
case SIOCSIFMEDIA: | case SIOCSIFMEDIA: | ||||
mii = device_get_softc(sc->dc_miibus); | mii = device_get_softc(sc->dc_miibus); | ||||
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); | error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); | ||||
break; | break; | ||||
case SIOCSIFCAP: | case SIOCSIFCAP: | ||||
#ifdef DEVICE_POLLING | #ifdef DEVICE_POLLING | ||||
if (ifr->ifr_reqcap & IFCAP_POLLING && | if (ifr->ifr_reqcap & IFCAP_POLLING && | ||||
!(ifp->if_capenable & IFCAP_POLLING)) { | !(if_getcapenable(ifp) & IFCAP_POLLING)) { | ||||
error = ether_poll_register(dc_poll, ifp); | error = ether_poll_register(dc_poll, ifp); | ||||
if (error) | if (error) | ||||
return(error); | return(error); | ||||
DC_LOCK(sc); | DC_LOCK(sc); | ||||
/* Disable interrupts */ | /* Disable interrupts */ | ||||
CSR_WRITE_4(sc, DC_IMR, 0x00000000); | CSR_WRITE_4(sc, DC_IMR, 0x00000000); | ||||
ifp->if_capenable |= IFCAP_POLLING; | if_setcapenablebit(ifp, IFCAP_POLLING, 0); | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
return (error); | return (error); | ||||
} | } | ||||
if (!(ifr->ifr_reqcap & IFCAP_POLLING) && | if (!(ifr->ifr_reqcap & IFCAP_POLLING) && | ||||
ifp->if_capenable & IFCAP_POLLING) { | if_getcapenable(ifp) & IFCAP_POLLING) { | ||||
error = ether_poll_deregister(ifp); | error = ether_poll_deregister(ifp); | ||||
/* Enable interrupts. */ | /* Enable interrupts. */ | ||||
DC_LOCK(sc); | DC_LOCK(sc); | ||||
CSR_WRITE_4(sc, DC_IMR, DC_INTRS); | CSR_WRITE_4(sc, DC_IMR, DC_INTRS); | ||||
ifp->if_capenable &= ~IFCAP_POLLING; | if_setcapenablebit(ifp, 0, IFCAP_POLLING); | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
return (error); | return (error); | ||||
} | } | ||||
#endif /* DEVICE_POLLING */ | #endif /* DEVICE_POLLING */ | ||||
break; | break; | ||||
default: | default: | ||||
error = ether_ioctl(ifp, command, data); | error = ether_ioctl(ifp, command, data); | ||||
break; | break; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
static void | static void | ||||
dc_watchdog(void *xsc) | dc_watchdog(void *xsc) | ||||
{ | { | ||||
struct dc_softc *sc = xsc; | struct dc_softc *sc = xsc; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
DC_LOCK_ASSERT(sc); | DC_LOCK_ASSERT(sc); | ||||
if (sc->dc_wdog_timer == 0 || --sc->dc_wdog_timer != 0) { | if (sc->dc_wdog_timer == 0 || --sc->dc_wdog_timer != 0) { | ||||
callout_reset(&sc->dc_wdog_ch, hz, dc_watchdog, sc); | callout_reset(&sc->dc_wdog_ch, hz, dc_watchdog, sc); | ||||
return; | return; | ||||
} | } | ||||
ifp = sc->dc_ifp; | ifp = sc->dc_ifp; | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | ||||
device_printf(sc->dc_dev, "watchdog timeout\n"); | device_printf(sc->dc_dev, "watchdog timeout\n"); | ||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING; | if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING); | ||||
dc_init_locked(sc); | dc_init_locked(sc); | ||||
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) | if (!if_sendq_empty(ifp)) | ||||
dc_start_locked(ifp); | dc_start_locked(ifp); | ||||
} | } | ||||
/* | /* | ||||
* Stop the adapter and free any mbufs allocated to the | * Stop the adapter and free any mbufs allocated to the | ||||
* RX and TX lists. | * RX and TX lists. | ||||
*/ | */ | ||||
static void | static void | ||||
dc_stop(struct dc_softc *sc) | dc_stop(struct dc_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp; | if_t ifp; | ||||
struct dc_list_data *ld; | struct dc_list_data *ld; | ||||
struct dc_chain_data *cd; | struct dc_chain_data *cd; | ||||
int i; | int i; | ||||
uint32_t ctl, netcfg; | uint32_t ctl, netcfg; | ||||
DC_LOCK_ASSERT(sc); | DC_LOCK_ASSERT(sc); | ||||
ifp = sc->dc_ifp; | ifp = sc->dc_ifp; | ||||
ld = &sc->dc_ldata; | ld = &sc->dc_ldata; | ||||
cd = &sc->dc_cdata; | cd = &sc->dc_cdata; | ||||
callout_stop(&sc->dc_stat_ch); | callout_stop(&sc->dc_stat_ch); | ||||
callout_stop(&sc->dc_wdog_ch); | callout_stop(&sc->dc_wdog_ch); | ||||
sc->dc_wdog_timer = 0; | sc->dc_wdog_timer = 0; | ||||
sc->dc_link = 0; | sc->dc_link = 0; | ||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); | if_setdrvflagbits(ifp, 0, (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)); | ||||
netcfg = CSR_READ_4(sc, DC_NETCFG); | netcfg = CSR_READ_4(sc, DC_NETCFG); | ||||
if (netcfg & (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON)) | if (netcfg & (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON)) | ||||
CSR_WRITE_4(sc, DC_NETCFG, | CSR_WRITE_4(sc, DC_NETCFG, | ||||
netcfg & ~(DC_NETCFG_RX_ON | DC_NETCFG_TX_ON)); | netcfg & ~(DC_NETCFG_RX_ON | DC_NETCFG_TX_ON)); | ||||
CSR_WRITE_4(sc, DC_IMR, 0x00000000); | CSR_WRITE_4(sc, DC_IMR, 0x00000000); | ||||
/* Wait the completion of TX/RX SM. */ | /* Wait the completion of TX/RX SM. */ | ||||
if (netcfg & (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON)) | if (netcfg & (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON)) | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | |||||
* Device resume routine. Restore some PCI settings in case the BIOS | * Device resume routine. Restore some PCI settings in case the BIOS | ||||
* doesn't, re-enable busmastering, and restart the interface if | * doesn't, re-enable busmastering, and restart the interface if | ||||
* appropriate. | * appropriate. | ||||
*/ | */ | ||||
static int | static int | ||||
dc_resume(device_t dev) | dc_resume(device_t dev) | ||||
{ | { | ||||
struct dc_softc *sc; | struct dc_softc *sc; | ||||
struct ifnet *ifp; | if_t ifp; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
ifp = sc->dc_ifp; | ifp = sc->dc_ifp; | ||||
/* reinitialize interface if necessary */ | /* reinitialize interface if necessary */ | ||||
DC_LOCK(sc); | DC_LOCK(sc); | ||||
if (ifp->if_flags & IFF_UP) | if (if_getflags(ifp) & IFF_UP) | ||||
dc_init_locked(sc); | dc_init_locked(sc); | ||||
sc->suspended = 0; | sc->suspended = 0; | ||||
DC_UNLOCK(sc); | DC_UNLOCK(sc); | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 66 Lines • Show Last 20 Lines |