Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/etherswitch/e6000sw/e6000sw.c
Show First 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | typedef struct e6000sw_softc { | ||||
device_t dev; | device_t dev; | ||||
phandle_t node; | phandle_t node; | ||||
struct sx sx; | struct sx sx; | ||||
struct ifnet *ifp[E6000SW_MAX_PORTS]; | struct ifnet *ifp[E6000SW_MAX_PORTS]; | ||||
char *ifname[E6000SW_MAX_PORTS]; | char *ifname[E6000SW_MAX_PORTS]; | ||||
device_t miibus[E6000SW_MAX_PORTS]; | device_t miibus[E6000SW_MAX_PORTS]; | ||||
struct mii_data *mii[E6000SW_MAX_PORTS]; | struct mii_data *mii[E6000SW_MAX_PORTS]; | ||||
struct callout tick_callout; | struct proc *kproc; | ||||
uint32_t cpuports_mask; | uint32_t cpuports_mask; | ||||
uint32_t fixed_mask; | uint32_t fixed_mask; | ||||
int sw_addr; | int sw_addr; | ||||
int num_ports; | int num_ports; | ||||
boolean_t multi_chip; | boolean_t multi_chip; | ||||
int vid[E6000SW_NUM_VGROUPS]; | int vid[E6000SW_NUM_VGROUPS]; | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
static int e6000sw_get_pvid(e6000sw_softc_t *sc, int port, int *pvid); | static int e6000sw_get_pvid(e6000sw_softc_t *sc, int port, int *pvid); | ||||
static int e6000sw_set_pvid(e6000sw_softc_t *sc, int port, int pvid); | static int e6000sw_set_pvid(e6000sw_softc_t *sc, int port, int pvid); | ||||
static __inline int e6000sw_is_cpuport(e6000sw_softc_t *sc, int port); | static __inline int e6000sw_is_cpuport(e6000sw_softc_t *sc, int port); | ||||
static __inline int e6000sw_is_fixedport(e6000sw_softc_t *sc, int port); | static __inline int e6000sw_is_fixedport(e6000sw_softc_t *sc, int port); | ||||
static __inline int e6000sw_is_phyport(e6000sw_softc_t *sc, int port); | static __inline int e6000sw_is_phyport(e6000sw_softc_t *sc, int port); | ||||
static __inline struct mii_data *e6000sw_miiforphy(e6000sw_softc_t *sc, | static __inline struct mii_data *e6000sw_miiforphy(e6000sw_softc_t *sc, | ||||
unsigned int phy); | unsigned int phy); | ||||
static struct proc *e6000sw_kproc; | |||||
static device_method_t e6000sw_methods[] = { | static device_method_t e6000sw_methods[] = { | ||||
/* device interface */ | /* device interface */ | ||||
DEVMETHOD(device_identify, e6000sw_identify), | DEVMETHOD(device_identify, e6000sw_identify), | ||||
DEVMETHOD(device_probe, e6000sw_probe), | DEVMETHOD(device_probe, e6000sw_probe), | ||||
DEVMETHOD(device_attach, e6000sw_attach), | DEVMETHOD(device_attach, e6000sw_attach), | ||||
DEVMETHOD(device_detach, e6000sw_detach), | DEVMETHOD(device_detach, e6000sw_detach), | ||||
/* bus interface */ | /* bus interface */ | ||||
▲ Show 20 Lines • Show All 252 Lines • ▼ Show 20 Lines | if (member_ports[vlangroup] != 0) { | ||||
e6000sw_setvgroup(dev, &vg); | e6000sw_setvgroup(dev, &vg); | ||||
} | } | ||||
E6000SW_UNLOCK(sc); | E6000SW_UNLOCK(sc); | ||||
bus_generic_probe(dev); | bus_generic_probe(dev); | ||||
bus_generic_attach(dev); | bus_generic_attach(dev); | ||||
kproc_create(e6000sw_tick, sc, &e6000sw_kproc, 0, 0, | kproc_create(e6000sw_tick, sc, &sc->kproc, 0, 0, "e6000sw tick kproc"); | ||||
"e6000sw tick kproc"); | |||||
return (0); | return (0); | ||||
out_fail: | out_fail: | ||||
E6000SW_UNLOCK(sc); | E6000SW_UNLOCK(sc); | ||||
e6000sw_detach(dev); | e6000sw_detach(dev); | ||||
return (err); | return (err); | ||||
▲ Show 20 Lines • Show All 573 Lines • ▼ Show 20 Lines | if (pvid == NULL) | ||||
return (ENXIO); | return (ENXIO); | ||||
*pvid = e6000sw_readreg(sc, REG_PORT(port), PORT_VID) & | *pvid = e6000sw_readreg(sc, REG_PORT(port), PORT_VID) & | ||||
PORT_VID_DEF_VID_MASK; | PORT_VID_DEF_VID_MASK; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | |||||
* Convert port status to ifmedia. | |||||
*/ | |||||
static void | 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_tick (void *arg) | ||||
{ | { | ||||
e6000sw_softc_t *sc; | e6000sw_softc_t *sc; | ||||
struct mii_softc *miisc; | struct mii_softc *miisc; | ||||
uint16_t portstatus; | |||||
int port; | int port; | ||||
sc = arg; | sc = arg; | ||||
E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); | E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED); | ||||
for (;;) { | for (;;) { | ||||
E6000SW_LOCK(sc); | E6000SW_LOCK(sc); | ||||
for (port = 0; port < sc->num_ports; port++) { | for (port = 0; port < sc->num_ports; port++) { | ||||
/* Tick only on PHY ports */ | /* Tick only on PHY ports */ | ||||
if (!e6000sw_is_phyport(sc, port)) | if (!e6000sw_is_phyport(sc, port)) | ||||
continue; | 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) { | LIST_FOREACH(miisc, &sc->mii[port]->mii_phys, mii_list) { | ||||
if (IFM_INST(sc->mii[port]->mii_media.ifm_cur->ifm_media) | if (IFM_INST(sc->mii[port]->mii_media.ifm_cur->ifm_media) | ||||
!= miisc->mii_inst) | != miisc->mii_inst) | ||||
continue; | continue; | ||||
mii_phy_update(miisc, MII_POLLSTAT); | mii_phy_update(miisc, MII_POLLSTAT); | ||||
} | } | ||||
} | } | ||||
E6000SW_UNLOCK(sc); | E6000SW_UNLOCK(sc); | ||||
▲ Show 20 Lines • Show All 173 Lines • Show Last 20 Lines |