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); }
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); }
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); }
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); }
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); }
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; }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }