Example #1
0
int
nsgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
	int reg;

	if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
		return (ENXIO);

	switch (cmd) {
	case MII_POLLSTAT:
		/*
		 * If we're not polling our PHY instance, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);
		break;

	case MII_MEDIACHG:
		/*
		 * If the media indicates a different PHY instance,
		 * isolate ourselves.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
			reg = PHY_READ(sc, MII_BMCR);
			PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
			return (0);
		}

		/*
		 * If the interface is not up, don't do anything.
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			break;

		mii_phy_setmedia(sc);
		break;

	case MII_TICK:
		/*
		 * If we're not currently selected, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);

		if (mii_phy_tick(sc) == EJUSTRETURN)
			return (0);
		break;
	case MII_DOWN:
		mii_phy_down(sc);
		return (0);
	}

	/* Update the media status. */
	mii_phy_status(sc);

	/* Callback if something changed. */
	mii_phy_update(sc, cmd);
	return (0);
}
Example #2
0
int
rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;

	/*
	 * Can't isolate the RTL8139 phy, so it has to be the only one.
	 */
	if (IFM_INST(ife->ifm_media) != sc->mii_inst)
		panic("rlphy_service: attempt to isolate phy");

	switch (cmd) {
	case MII_POLLSTAT:
		break;

	case MII_MEDIACHG:
		/*
		 * If the interface is not up, don't do anything.
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			break;

		mii_phy_setmedia(sc);
		break;

	case MII_TICK:
		/*
		 * Is the interface even up?
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			return (0);

		/*
		 * Only used for autonegotiation.
		 */
		if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
			break;

		/*
		 * The RealTek PHY's autonegotiation doesn't need to be
		 * kicked; it continues in the background.
		 */
		break;

	case MII_DOWN:
		mii_phy_down(sc);
		return (0);
	}

	/* Update the media status. */
	mii_phy_status(sc);

	/* Callback if something changed. */
	mii_phy_update(sc, cmd);
	return (0);
}
Example #3
0
int
mii_phy_detach(device_t dev)
{
	struct mii_softc *sc;

	sc = device_get_softc(dev);
	mii_phy_down(sc);
	sc->mii_dev = NULL;
	LIST_REMOVE(sc, mii_list);
	return (0);
}
Example #4
0
int
exphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;

	if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
		return (ENXIO);

	/*
	 * We can't isolate the 3Com PHY, so it has to be the only one!
	 */
	if (IFM_INST(ife->ifm_media) != sc->mii_inst)
		panic("exphy_service: can't isolate 3Com PHY");

	switch (cmd) {
	case MII_POLLSTAT:
		break;

	case MII_MEDIACHG:
		/*
		 * If the interface is not up, don't do anything.
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			break;

		mii_phy_setmedia(sc);
		break;

	case MII_TICK:
		if (mii_phy_tick(sc) == EJUSTRETURN)
			return (0);

		break;

	case MII_DOWN:
		mii_phy_down(sc);
		return (0);
	}

	/* Update the media status. */
	mii_phy_status(sc);

	/* Callback if something changed. */
	mii_phy_update(sc, cmd);
	return (0);
}
Example #5
0
static int
igphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
	uint16_t reg;

	switch (cmd) {
	case MII_POLLSTAT:
		/*
		 * If we're not polling our PHY instance, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);
		break;

	case MII_MEDIACHG:
		/*
		 * If the media indicates a different PHY instance,
		 * isolate ourselves.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
			reg = PHY_READ(sc, MII_BMCR);
			PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
			return (0);
		}

		/*
		 * If the interface is not up, don't do anything.
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			break;

		reg = PHY_READ(sc, MII_IGPHY_PORT_CTRL);
		if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
			reg |= PSCR_AUTO_MDIX;
			reg &= ~PSCR_FORCE_MDI_MDIX;
			PHY_WRITE(sc, MII_IGPHY_PORT_CTRL, reg);
		} else {
			reg &= ~(PSCR_AUTO_MDIX | PSCR_FORCE_MDI_MDIX);
			PHY_WRITE(sc, MII_IGPHY_PORT_CTRL, reg);
		}

		mii_phy_setmedia(sc);
		break;

	case MII_TICK:
		/*
		 * If we're not currently selected, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);

		igphy_smartspeed_workaround(sc);

		if (mii_phy_tick(sc) == EJUSTRETURN)
			return (0);
		break;

	case MII_DOWN:
		mii_phy_down(sc);
		return (0);
	}

	/* Update the media status. */
	mii_phy_status(sc);

	/* Callback if something changed. */
	mii_phy_update(sc, cmd);
	return (0);
}
static int
makphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
	int reg;

	switch (cmd) {
	case MII_POLLSTAT:
		/*
		 * If we're not polling our PHY instance, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);
		break;

	case MII_MEDIACHG:
		/*
		 * If the media indicates a different PHY instance,
		 * isolate ourselves.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
			reg = PHY_READ(sc, MII_BMCR);
			PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
			return (0);
		}

		/*
		 * If the interface is not up, don't do anything.
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			break;

		mii_phy_setmedia(sc);
		if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
			/*
			 * when not in auto mode, we need to restart nego
			 * anyway, or a switch from a fixed mode to another
			 * fixed mode may not be seen by the switch.
			 */
			PHY_WRITE(sc, MII_BMCR,
			    PHY_READ(sc, MII_BMCR) | BMCR_STARTNEG);
		}
		break;

	case MII_TICK:
		/*
		 * If we're not currently selected, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);

		if (mii_phy_tick(sc) == EJUSTRETURN)
			return (0);
		break;

	case MII_DOWN:
		mii_phy_down(sc);
		return (0);
	}

	/* Update the media status. */
	mii_phy_status(sc);

	/* Callback if something changed. */
	mii_phy_update(sc, cmd);
	return (0);
}
Example #7
0
static int
ihphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
	int reg;

	switch (cmd) {
	case MII_POLLSTAT:
		/*
		 * If we're not polling our PHY instance, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return 0;
		break;

	case MII_MEDIACHG:
		/*
		 * If the media indicates a different PHY instance,
		 * isolate ourselves.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
			reg = PHY_READ(sc, MII_BMCR);
			PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
			return 0;
		}

		/*
		 * If the interface is not up, don't do anything.
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			break;

		/*
		 * If media is deselected, disable link (standby).
		 */
		reg = PHY_READ(sc, IHPHY_MII_ECR);
		if (IFM_SUBTYPE(ife->ifm_media) == IFM_NONE)
			reg &= ~IHPHY_ECR_LNK_EN;
		else
			reg |= IHPHY_ECR_LNK_EN;
		PHY_WRITE(sc, IHPHY_MII_ECR, reg);

		/*
		 * XXX Adjust MDI/MDIX configuration?  Other settings?
		 */

		mii_phy_setmedia(sc);
		break;

	case MII_TICK:
		/*
		 * If we're not currently selected, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return 0;

		if (mii_phy_tick(sc) == EJUSTRETURN)
			return 0;
		break;

	case MII_DOWN:
		mii_phy_down(sc);
		PHY_WRITE(sc, MII_BMCR, BMCR_PDOWN);
		return 0;
	}

	/* Update the media status. */
	mii_phy_status(sc);

	/* Callback if something changed. */
	mii_phy_update(sc, cmd);
	return 0;
}
Example #8
0
int
urlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
	int reg;

	DPRINTF(("%s: %s: enter\n", sc->mii_dev.dv_xname, __func__));

	if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
		return (ENXIO);

	switch (cmd) {
	case MII_POLLSTAT:
		/*
		 * If we're not polling our PHY instance, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);
		break;

	case MII_MEDIACHG:
		/*
		 * If we're not currently selected, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);

		/* If the interface is not up, don't do anything. */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			break;

		mii_phy_setmedia(sc);
		break;

	case MII_TICK:
		/*
		 * If we're not currently selected, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);

		/* Just bail now if the interface is down. */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			return (0);

		/*
		 * If we're not doing autonegotiation, we don't need to do
		 * any extra work here.  However, we need to check the link
		 * status so we can generate an announcement if the status
		 * changes.
		 */
		if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
			return (0);

		/* Read the status register twice; MSR_LINK is latch-low. */
		reg = PHY_READ(sc, URLPHY_MSR) | PHY_READ(sc, URLPHY_MSR);
		if (reg & URLPHY_MSR_LINK) {
			sc->mii_ticks = 0;
			break;
		}

		/*
	 	 * Only retry autonegotiation every mii_anegticks seconds.
		 */
		if (++sc->mii_ticks <= sc->mii_anegticks)
			return (0);

		sc->mii_ticks = 0;
		PHY_RESET(sc);

		if (mii_phy_auto(sc, 0) == EJUSTRETURN)
			return (0);

		break;

	case MII_DOWN:
		mii_phy_down(sc);
		return (0);
	}

	/* Update the media status. */
	mii_phy_status(sc);

	/* Callback if something changed. */
	mii_phy_update(sc, cmd);

	return (0);
}
Example #9
0
static int
tlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
	struct tlphy_softc *tsc = (struct tlphy_softc *)sc;
	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
	int reg;

	if ((sc->mii_flags & MIIF_DOINGAUTO) == 0 && tsc->sc_need_acomp)
		tlphy_acomp(tsc);

	switch (cmd) {
	case MII_POLLSTAT:
		/*
		 * If we're not polling our PHY instance, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);
		break;

	case MII_MEDIACHG:
		/*
		 * If the media indicates a different PHY instance,
		 * isolate ourselves.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
			reg = PHY_READ(sc, MII_BMCR);
			PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
			return (0);
		}

		/*
		 * If the interface is not up, don't do anything.
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			break;

		switch (IFM_SUBTYPE(ife->ifm_media)) {
		case IFM_AUTO:
			/*
			 * The ThunderLAN PHY doesn't self-configure after
			 * an autonegotiation cycle, so there's no such
			 * thing as "already in auto mode".
			 */
			(void) tlphy_auto(tsc, 1);
			break;
		case IFM_10_2:
		case IFM_10_5:
			PHY_WRITE(sc, MII_BMCR, 0);
			PHY_WRITE(sc, MII_TLPHY_CTRL, CTRL_AUISEL);
			delay(100000);
			break;
		default:
			PHY_WRITE(sc, MII_TLPHY_CTRL, 0);
			delay(100000);
			mii_phy_setmedia(sc);
		}
		break;

	case MII_TICK:
		/*
		 * If we're not currently selected, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);

		/*
		 * Only used for autonegotiation.
		 */
		if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
			return (0);

		/*
		 * Is the interface even up?
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			return (0);

		/*
		 * XXX WHAT ABOUT CHECKING LINK ON THE BNC/AUI?!
		 */

		if (mii_phy_tick(sc) == EJUSTRETURN)
			return (0);
		break;

	case MII_DOWN:
		mii_phy_down(sc);
		return (0);
	}

	/* Update the media status. */
	mii_phy_status(sc);

	/* Callback if something changed. */
	mii_phy_update(sc, cmd);
	return (0);
}
Example #10
0
static int
urlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
	int reg;

	DPRINTF(("%s: %s: enter\n", device_xname(sc->mii_dev), __func__));

	switch (cmd) {
	case MII_POLLSTAT:
		/*
		 * If we're not polling our PHY instance, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);
		break;

	case MII_MEDIACHG:
		/*
		 * If we're not currently selected, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);

		/* If the interface is not up, don't do anything. */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			break;

		mii_phy_setmedia(sc);
		break;

	case MII_TICK:
		/*
		 * If we're not currently selected, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);

		/* Just bail now if the interface is down. */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			return (0);

		/*
		 * If we're not doing autonegotiation, we don't need to do
		 * any extra work here.  However, we need to check the link
		 * status so we can generate an announcement if the status
		 * changes.
		 */
		if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
			break;

		/* Read the status register twice; MSR_LINK is latch-low. */
		reg = PHY_READ(sc, URLPHY_MSR) | PHY_READ(sc, URLPHY_MSR);
		if (reg & URLPHY_MSR_LINK) {
			/*
			 * Reset autonegotiation timer to 0 in case the link
			 * goes down in the next tick.
			 */
			sc->mii_ticks = 0;
			/* See above. */
			break;
		}

		/*
		 * mii_ticks == 0 means it's the first tick after changing the
		 * media or the link became down since the last tick (see
		 * above), so break to update the status.
		 */
		if (sc->mii_ticks++ == 0)
			break;

		/*
		 * Only retry autonegotiation every N seconds.
		 */
		KASSERT(sc->mii_anegticks != 0);
		if (sc->mii_ticks <= sc->mii_anegticks)
			return (0);

		PHY_RESET(sc);

		if (mii_phy_auto(sc, 0) == EJUSTRETURN)
			return (0);

		break;

	case MII_DOWN:
		mii_phy_down(sc);
		return (0);
	}

	/* Update the media status. */
	mii_phy_status(sc);

	/* Callback if something changed. */
	mii_phy_update(sc, cmd);

	return (0);
}
Example #11
0
int
eephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
	int bmcr;

	if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
		return (ENXIO);

	switch (cmd) {
	case MII_POLLSTAT:
		/*
		 * If we're not polling our PHY instance, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);
		break;

	case MII_MEDIACHG:
		/*
		 * If the media indicates a different PHY instance,
		 * isolate ourselves.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
			bmcr = PHY_READ(sc, E1000_CR);
			PHY_WRITE(sc, E1000_CR, bmcr | E1000_CR_ISOLATE);
			return (0);
		}

		/*
		 * If the interface is not up, don't do anything.
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			break;

		mii_phy_setmedia(sc);

		/*
		 * If autonegitation is not enabled, we need a
		 * software reset for the settings to take effect.
		 */
		if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
			bmcr = PHY_READ(sc, E1000_CR);
			PHY_WRITE(sc, E1000_CR, bmcr | E1000_CR_RESET);
		}
		break;

	case MII_TICK:
		/*
		 * If we're not currently selected, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);

		if (mii_phy_tick(sc) == EJUSTRETURN)
                        return (0);
		break;

	case MII_DOWN:
		mii_phy_down(sc);
                return (0);
	}

	/* Update the media status. */
	mii_phy_status(sc);

	/* Callback if something changed. */
	mii_phy_update(sc, cmd);
	return (0);
}
Example #12
0
static int
brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
	int reg, speed, gig;

	switch (cmd) {
	case MII_POLLSTAT:
		/*
		 * If we're not polling our PHY instance, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);
		break;

	case MII_MEDIACHG:
		/*
		 * If the media indicates a different PHY instance,
		 * isolate ourselves.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
			reg = PHY_READ(sc, MII_BMCR);
			PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
			return (0);
		}

		/*
		 * If the interface is not up, don't do anything.
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			break;

		PHY_RESET(sc); /* XXX hardware bug work-around */

		switch (IFM_SUBTYPE(ife->ifm_media)) {
		case IFM_AUTO:
			(void) brgphy_mii_phy_auto(sc);
			break;
		case IFM_1000_T:
			speed = BMCR_S1000;
			goto setit;
		case IFM_100_TX:
			speed = BMCR_S100;
			goto setit;
		case IFM_10_T:
			speed = BMCR_S10;
setit:
			brgphy_loop(sc);
			if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
				speed |= BMCR_FDX;
				gig = GTCR_ADV_1000TFDX;
			} else {
				gig = GTCR_ADV_1000THDX;
			}

			PHY_WRITE(sc, MII_100T2CR, 0);
			PHY_WRITE(sc, MII_ANAR, ANAR_CSMA);
			PHY_WRITE(sc, MII_BMCR, speed);

			if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)
				break;

			PHY_WRITE(sc, MII_100T2CR, gig);
			PHY_WRITE(sc, MII_BMCR,
			    speed | BMCR_AUTOEN | BMCR_STARTNEG);

			if ((sc->mii_mpd_oui != MII_OUI_BROADCOM)
			    || (sc->mii_mpd_model != MII_MODEL_BROADCOM_BCM5701))
				break;

			if (mii->mii_media.ifm_media & IFM_ETH_MASTER)
				gig |= GTCR_MAN_MS | GTCR_ADV_MS;
			PHY_WRITE(sc, MII_100T2CR, gig);
			break;
		default:
			return (EINVAL);
		}
		break;

	case MII_TICK:
		/*
		 * If we're not currently selected, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);

		/*
		 * Is the interface even up?
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			return 0;

		/*
		 * Only used for autonegotiation.
		 */
		if ((IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) &&
		    (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)) {
			sc->mii_ticks = 0;
			break;
		}

		/*
		 * Check for link.
		 * Read the status register twice; BMSR_LINK is latch-low.
		 */
		reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
		if (reg & BMSR_LINK) {
			sc->mii_ticks = 0;
			break;
		}

		/*
		 * mii_ticks == 0 means it's the first tick after changing the
		 * media or the link became down since the last tick
		 * (see above), so break to update the status.
		 */
		if (sc->mii_ticks++ == 0)
			break;

		/*
		 * Only retry autonegotiation every mii_anegticks seconds.
		 */
		KASSERT(sc->mii_anegticks != 0);
		if (sc->mii_ticks <= sc->mii_anegticks)
			break;

		brgphy_mii_phy_auto(sc);
		break;

	case MII_DOWN:
		mii_phy_down(sc);
		return (0);
	}

	/* Update the media status. */
	mii_phy_status(sc);

	/*
	 * Callback if something changed. Note that we need to poke the DSP on
	 * the Broadcom PHYs if the media changes.
	 */
	if (sc->mii_media_active != mii->mii_media_active ||
	    sc->mii_media_status != mii->mii_media_status ||
	    cmd == MII_MEDIACHG) {
		switch (sc->mii_mpd_oui) {
		case MII_OUI_BROADCOM:
			switch (sc->mii_mpd_model) {
			case MII_MODEL_BROADCOM_BCM5400:
				brgphy_bcm5401_dspcode(sc);
				break;
			case MII_MODEL_BROADCOM_BCM5401:
				if (sc->mii_mpd_rev == 1 || sc->mii_mpd_rev == 3)
					brgphy_bcm5401_dspcode(sc);
				break;
			case MII_MODEL_BROADCOM_BCM5411:
				brgphy_bcm5411_dspcode(sc);
				break;
			}
			break;
		}
	}

	/* Callback if something changed. */
	mii_phy_update(sc, cmd);
	return (0);
}
Example #13
0
static int
nsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
	int reg;

	switch (cmd) {
	case MII_POLLSTAT:
		/*
		 * If we're not polling our PHY instance, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);
		break;

	case MII_MEDIACHG:
		/*
		 * If the media indicates a different PHY instance,
		 * isolate ourselves.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
			reg = PHY_READ(sc, MII_BMCR);
			PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
			return (0);
		}

		/*
		 * If the interface is not up, don't do anything.
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			break;

		reg = PHY_READ(sc, MII_NSPHY_PCR);

		/*
		 * Set up the PCR to use LED4 to indicate full-duplex
		 * in both 10baseT and 100baseTX modes.
		 */
		reg |= PCR_LED4MODE;

		/*
		 * Make sure Carrier Integrity Monitor function is
		 * disabled (normal for Node operation, but sometimes
		 * it's not set?!)
		 */
		reg |= PCR_CIMDIS;

		/*
		 * Make sure "force link good" is set to normal mode.
		 * It's only intended for debugging.
		 */
		reg |= PCR_FLINK100;

		/*
		 * Mystery bits which are supposedly `reserved',
		 * but we seem to need to set them when the PHY
		 * is connected to some interfaces:
		 *
		 * 0x0400 is needed for fxp
		 *        (Intel EtherExpress Pro 10+/100B, 82557 chip)
		 *        (nsphy with a DP83840 chip)
		 * 0x0100 may be needed for some other card
		 */
		reg |= 0x0100 | 0x0400;

		PHY_WRITE(sc, MII_NSPHY_PCR, reg);

		mii_phy_setmedia(sc);
		break;

	case MII_TICK:
		/*
		 * If we're not currently selected, just return.
		 */
		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
			return (0);

		if (mii_phy_tick(sc) == EJUSTRETURN)
			return (0);
		break;

	case MII_DOWN:
		mii_phy_down(sc);
		return (0);
	}

	/* Update the media status. */
	mii_phy_status(sc);

	/* Callback if something changed. */
	mii_phy_update(sc, cmd);
	return (0);
}
Example #14
0
int
mlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
    struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
    struct mii_softc *other = NULL;
    struct mlphy_softc *msc = (struct mlphy_softc *)sc;
    int other_inst, reg;

    LIST_FOREACH(other, &mii->mii_phys, mii_list)
    if (other != sc)
        break;

    if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
        return (ENXIO);

    switch (cmd) {
    case MII_POLLSTAT:
        /*
         * If we're not polling our PHY instance, just return.
         */
        if (IFM_INST(ife->ifm_media) != sc->mii_inst)
            return (0);
        break;

    case MII_MEDIACHG:
        /*
         * If the interface is not up, don't do anything.
         */
        if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
            break;

        switch (IFM_SUBTYPE(ife->ifm_media)) {
        case IFM_AUTO:
            msc->ml_state = ML_STATE_AUTO_SELF;
            if (other != NULL) {
                mii_phy_reset(other);
                PHY_WRITE(other, MII_BMCR, BMCR_ISO);
            }
            (void)mii_phy_auto(sc, 0);
            msc->ml_linked = 0;
            break;
        case IFM_10_T:
            /*
             * For 10baseT modes, reset and program the
             * companion PHY (of any), then setup ourselves
             * to match. This will put us in pass-through
             * mode and let the companion PHY do all the
             * work.
             * BMCR data is stored in the ifmedia entry.
             */
            if (other != NULL) {
                mii_phy_reset(other);
                PHY_WRITE(other, MII_BMCR, ife->ifm_data);
            }
            mii_phy_setmedia(sc);
            msc->ml_state = 0;
            break;
        case IFM_100_TX:
            /*
             * For 100baseTX modes, reset and isolate the
             * companion PHY (if any), then setup ourselves
             * accordingly.
             *
             * BMCR data is stored in the ifmedia entry.
             */
            if (other != NULL) {
                mii_phy_reset(other);
                PHY_WRITE(other, MII_BMCR, BMCR_ISO);
            }
            mii_phy_setmedia(sc);
            msc->ml_state = 0;
            break;
        default:
            return (EINVAL);
        }
        break;
    case MII_TICK:
        /*
         * If interface is not up, don't do anything
         */
        if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
            return (0);
        /*
         * Only used for autonegotiation.
         */
        if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
            break;
        /*
         * Check to see if we have link.  If we do, we don't
         * need to restart the autonegotiation process.  Read
         * the BMSR twice in case it's latched.
         * If we're in a 10Mbps mode, check the link of the
         * 10Mbps PHY. Sometimes the Micro Linear PHY's
         * linkstat bit will clear while the linkstat bit of
         * the companion PHY will remain set.
         */
        if (msc->ml_state == ML_STATE_AUTO_OTHER) {
            reg = PHY_READ(other, MII_BMSR) |
                  PHY_READ(other, MII_BMSR);
        } else {
            reg = PHY_READ(sc, MII_BMSR) |
                  PHY_READ(sc, MII_BMSR);
        }

        if (reg & BMSR_LINK) {
            if (!msc->ml_linked) {
                msc->ml_linked = 1;
                mlphy_status(sc);
            }
            sc->mii_ticks = 0;
            break;
        }
        /*
         * Only retry autonegotiation every 5 seconds.
         */
        if (++sc->mii_ticks <= MII_ANEGTICKS)
            break;

        sc->mii_ticks = 0;
        msc->ml_linked = 0;
        mii->mii_media_active = IFM_NONE;
        mii_phy_reset(sc);
        msc->ml_state = ML_STATE_AUTO_SELF;
        if (other != NULL) {
            mii_phy_reset(other);
            PHY_WRITE(other, MII_BMCR, BMCR_ISO);
        }
        mii_phy_auto(sc, 0);
        break;

    case MII_DOWN:
        mii_phy_down(sc);
        return (0);
    }

    /* Update the media status. */
    if (msc->ml_state == ML_STATE_AUTO_OTHER && other != NULL) {
        other_inst = other->mii_inst;
        other->mii_inst = sc->mii_inst;
        if (IFM_INST(ife->ifm_media) == other->mii_inst)
            (void) PHY_SERVICE(other, mii, MII_POLLSTAT);
        other->mii_inst = other_inst;
        sc->mii_media_active = other->mii_media_active;
        sc->mii_media_status = other->mii_media_status;
    } else
        ukphy_status(sc);

    /* Callback if something changed. */
    mii_phy_update(sc, cmd);
    return (0);
}
Example #15
0
int
rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;

	int rv;

	/*
	 * Can't isolate the RTL8139 phy, so it has to be the only one.
	 */
	if (IFM_INST(ife->ifm_media) != sc->mii_inst)
		panic("rlphy_service: attempt to isolate phy");

	switch (cmd) {
	case MII_POLLSTAT:
		break;

	case MII_MEDIACHG:
		/*
		 * If the interface is not up, don't do anything.
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			break;

		switch (IFM_SUBTYPE(ife->ifm_media)) {
		case IFM_AUTO:
			/*
			 * If we're already in auto mode, just return.
			 */
			if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
				return (0);
			(void) mii_phy_auto(sc, 0);
			break;
		case IFM_100_T4:
			/*
			 * XXX Not supported as a manual setting right now.
			 */
			return (EINVAL);
		default:
			/*
			 * BMCR data is stored in the ifmedia entry.
			 */
			switch (ife->ifm_media &
			    (IFM_TMASK|IFM_NMASK|IFM_FDX)) {
				case IFM_ETHER|IFM_10_T:
					rv = ANAR_10|ANAR_CSMA;
					break;
				case IFM_ETHER|IFM_10_T|IFM_FDX:
					rv = ANAR_10_FD|ANAR_CSMA;
					break;
				case IFM_ETHER|IFM_100_TX:
					rv = ANAR_TX|ANAR_CSMA;
					break;
				case IFM_ETHER|IFM_100_TX|IFM_FDX:
					rv = ANAR_TX_FD|ANAR_CSMA;
					break;
				case IFM_ETHER|IFM_100_T4:
					rv = ANAR_T4|ANAR_CSMA;
					break;
				default:
					rv = 0;
					break;
			}

			PHY_WRITE(sc, MII_ANAR, rv);
			PHY_WRITE(sc, MII_BMCR, ife->ifm_data);
		}
		break;

	case MII_TICK:
		/*
		 * Is the interface even up?
		 */
		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
			return (0);

		/*
		 * Only used for autonegotiation.
		 */
		if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
			break;

		/*
		 * The RealTek PHY's autonegotiation doesn't need to be
		 * kicked; it continues in the background.
		 */
		break;

	case MII_DOWN:
		mii_phy_down(sc);
		return (0);
	}

	/* Update the media status. */
	mii_phy_status(sc);

	/* Callback if something changed. */
	mii_phy_update(sc, cmd);
	return (0);
}