Index: head/sys/dev/etherswitch/e6000sw/e6000sw.c =================================================================== --- head/sys/dev/etherswitch/e6000sw/e6000sw.c +++ head/sys/dev/etherswitch/e6000sw/e6000sw.c @@ -89,7 +89,7 @@ char *ifname[E6000SW_MAX_PORTS]; device_t miibus[E6000SW_MAX_PORTS]; struct mii_data *mii[E6000SW_MAX_PORTS]; - struct callout tick_callout; + struct proc *kproc; uint32_t cpuports_mask; uint32_t fixed_mask; @@ -149,8 +149,6 @@ static __inline struct mii_data *e6000sw_miiforphy(e6000sw_softc_t *sc, unsigned int phy); -static struct proc *e6000sw_kproc; - static device_method_t e6000sw_methods[] = { /* device interface */ DEVMETHOD(device_identify, e6000sw_identify), @@ -419,8 +417,7 @@ bus_generic_probe(dev); bus_generic_attach(dev); - kproc_create(e6000sw_tick, sc, &e6000sw_kproc, 0, 0, - "e6000sw tick kproc"); + kproc_create(e6000sw_tick, sc, &sc->kproc, 0, 0, "e6000sw tick kproc"); return (0); @@ -1010,23 +1007,65 @@ return (0); } +/* + * Convert port status to ifmedia. + */ +static void +e6000sw_update_ifmedia(uint16_t portstatus, u_int *media_status, u_int *media_active) +{ + *media_active = IFM_ETHER; + *media_status = IFM_AVALID; + + if ((portstatus & PORT_STATUS_LINK_MASK) != 0) + *media_status |= IFM_ACTIVE; + else { + *media_active |= IFM_NONE; + return; + } + + switch (portstatus & PORT_STATUS_SPEED_MASK) { + case PORT_STATUS_SPEED_10: + *media_active |= IFM_10_T; + break; + case PORT_STATUS_SPEED_100: + *media_active |= IFM_100_TX; + break; + case PORT_STATUS_SPEED_1000: + *media_active |= IFM_1000_T; + break; + } + + if ((portstatus & PORT_STATUS_DUPLEX_MASK) == 0) + *media_active |= IFM_FDX; + else + *media_active |= IFM_HDX; +} + static void e6000sw_tick (void *arg) { e6000sw_softc_t *sc; struct mii_softc *miisc; + uint16_t portstatus; int port; sc = arg; E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); + for (;;) { E6000SW_LOCK(sc); for (port = 0; port < sc->num_ports; port++) { /* Tick only on PHY ports */ if (!e6000sw_is_phyport(sc, port)) continue; - mii_tick(sc->mii[port]); + + portstatus = e6000sw_readreg(sc, REG_PORT(port), PORT_STATUS); + + e6000sw_update_ifmedia(portstatus, + &sc->mii[port]->mii_media_status, + &sc->mii[port]->mii_media_active); + LIST_FOREACH(miisc, &sc->mii[port]->mii_phys, mii_list) { if (IFM_INST(sc->mii[port]->mii_media.ifm_cur->ifm_media) != miisc->mii_inst) Index: head/sys/dev/etherswitch/e6000sw/e6000swreg.h =================================================================== --- head/sys/dev/etherswitch/e6000sw/e6000swreg.h +++ head/sys/dev/etherswitch/e6000sw/e6000swreg.h @@ -55,6 +55,14 @@ * Per-Port Switch Registers */ #define PORT_STATUS 0x0 +#define PORT_STATUS_SPEED_MASK 0x300 +#define PORT_STATUS_SPEED_10 0 +#define PORT_STATUS_SPEED_100 1 +#define PORT_STATUS_SPEED_1000 2 +#define PORT_STATUS_DUPLEX_MASK (1 << 10) +#define PORT_STATUS_LINK_MASK (1 << 11) +#define PORT_STATUS_PHY_DETECT_MASK (1 << 12) + #define PSC_CONTROL 0x1 #define SWITCH_ID 0x3 #define PORT_CONTROL 0x4