FreeBSD/sys/dev/etherswitch/arswitch/arswitch.c
/*
 * Poll the status for all PHYs.  We're using the switch port status because
 * thats a lot quicker to read than talking to all the PHYs.  Care must be
 * taken that the resulting ifmedia_active is identical to what the PHY will
 * compute, or gratuitous link status changes will occur whenever the PHYs
 * update function is called.
 */
Poll the status for all PHYs.  We're using the switch port status because
thats a lot quicker to read than talking to all the PHYs.  Care must be
taken that the resulting ifmedia_active is identical to what the PHY will
compute, or gratuitous link status changes will occur whenever the PHYs
update function is called.
Poll the status for all PHYs . We ' re using the switch port status because thats a lot quicker to read than talking to all the PHYs . Care must be taken that the resulting ifmedia_active is identical to what the PHY will compute or gratuitous link status changes will occur whenever the PHYs update function is called .
static void
arswitch_miipollstat(struct arswitch_softc *sc)
{
	int i;
	struct mii_data *mii;
	struct mii_softc *miisc;
	int portstatus;
	int port_flap = 0;
	ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
	for (i = 0; i < sc->numphys; i++) {
		if (sc->miibus[i] == NULL)
			continue;
		mii = device_get_softc(sc->miibus[i]);
		if (AR8X16_IS_SWITCH(sc, AR8327))
			portstatus = arswitch_readreg(sc->sc_dev,
			    AR8327_REG_PORT_STATUS(arswitch_portforphy(i)));
		else
			portstatus = arswitch_readreg(sc->sc_dev,
			    AR8X16_REG_PORT_STS(arswitch_portforphy(i)));
#if 0
		DPRINTF(sc->sc_dev, "p[%d]=%b\n",
		    i,
		    portstatus,
		    "\20\3TXMAC\4RXMAC\5TXFLOW\6RXFLOW\7"
		    "DUPLEX\11LINK_UP\12LINK_AUTO\13LINK_PAUSE");
#endif
		if ((mii->mii_media_status & IFM_ACTIVE) == 0 &&
		    (portstatus & AR8X16_PORT_STS_LINK_UP) != 0) {
			device_printf(sc->sc_dev, "%s: port %d: port -> UP\n",
			    __func__,
			    i);
			port_flap = 1;
		}
		if ((mii->mii_media_status & IFM_ACTIVE) != 0 &&
		    (portstatus & AR8X16_PORT_STS_LINK_UP) == 0) {
			device_printf(sc->sc_dev, "%s: port %d: port -> DOWN\n",
			    __func__,
			    i);
			port_flap = 1;
		}
		arswitch_update_ifmedia(portstatus, &mii->mii_media_status,
		    &mii->mii_media_active);
		LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
			if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) !=
			    miisc->mii_inst)
				continue;
			mii_phy_update(miisc, MII_POLLSTAT);
		}
	}
	if (port_flap)
		sc->hal.arswitch_atu_flush(sc);
}
static void arswitch_miipollstat ( struct arswitch_softc * sc ) { int i ; struct mii_data * mii ; struct mii_softc * miisc ; int portstatus ; int port_flap = 0 ; ARSWITCH_LOCK_ASSERT ( sc , MA_OWNED ) ; for ( i = 0 ; i < sc -> numphys ; i ++ ) { if ( sc -> miibus [ i ] == NULL ) continue ; mii = device_get_softc ( sc -> miibus [ i ] ) ; if ( AR8X16_IS_SWITCH ( sc , AR8327 ) ) portstatus = arswitch_readreg ( sc -> sc_dev , AR8327_REG_PORT_STATUS ( arswitch_portforphy ( i ) ) ) ; else portstatus = arswitch_readreg ( sc -> sc_dev , AR8X16_REG_PORT_STS ( arswitch_portforphy ( i ) ) ) ; #if 0 DPRINTF ( sc -> sc_dev , " \n " , i , portstatus , " \20 \3 \4 \5 \6 \7 " " \11 \12 \13 " ) ; #endif if ( ( mii -> mii_media_status & IFM_ACTIVE ) == 0 && ( portstatus & AR8X16_PORT_STS_LINK_UP ) != 0 ) { device_printf ( sc -> sc_dev , " \n " , __func__ , i ) ; port_flap = 1 ; } if ( ( mii -> mii_media_status & IFM_ACTIVE ) != 0 && ( portstatus & AR8X16_PORT_STS_LINK_UP ) == 0 ) { device_printf ( sc -> sc_dev , " \n " , __func__ , i ) ; port_flap = 1 ; } arswitch_update_ifmedia ( portstatus , & mii -> mii_media_status , & mii -> mii_media_active ) ; LIST_FOREACH ( miisc , & mii -> mii_phys , mii_list ) { if ( IFM_INST ( mii -> mii_media . ifm_cur -> ifm_media ) != miisc -> mii_inst ) continue ; mii_phy_update ( miisc , MII_POLLSTAT ) ; } } if ( port_flap ) sc -> hal . arswitch_atu_flush ( sc ) ; }
Poll the status for all PHYs.
Poll the status for all PHYs .
/* XXX This would be nice to have abstracted out to be per-chip */ /* AR8327/AR8337 has a different register base */ /*
		 * If the current status is down, but we have a link
		 * status showing up, we need to do an ATU flush.
		 */ /*
		 * and maybe if a port goes up->down?
		 */ /* If a port went from down->up, flush the ATU */