static int brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int val; 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; /* Todo: Why is this here? Is it really needed? */ PHY_RESET(sc); /* XXX hardware bug work-around */ switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_AUTO: brgphy_mii_phy_auto(sc, ife->ifm_media); break; case IFM_2500_SX: case IFM_1000_SX: case IFM_1000_T: case IFM_100_TX: case IFM_10_T: brgphy_setmedia(sc, ife->ifm_media); break; default: return (EINVAL); } break; case MII_TICK: /* Bail if the interface isn't up. */ if ((mii->mii_ifp->if_flags & IFF_UP) == 0) return (0); /* Bail if autoneg isn't in process. */ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { sc->mii_ticks = 0; break; } /* * Check to see if we have link. If we do, we don't * need to restart the autonegotiation process. */ val = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (val & BMSR_LINK) { sc->mii_ticks = 0; /* Reset autoneg timer. */ break; } /* Announce link loss right after it happens. */ if (sc->mii_ticks++ == 0) break; /* Only retry autonegotiation every mii_anegticks seconds. */ if (sc->mii_ticks <= sc->mii_anegticks) break; /* Retry autonegotiation */ sc->mii_ticks = 0; brgphy_mii_phy_auto(sc, ife->ifm_media); break; } /* Update the media status. */ 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: bcm5401_load_dspcode(sc); break; case MII_MODEL_BROADCOM_BCM5401: if (sc->mii_mpd_rev == 1 || sc->mii_mpd_rev == 3) bcm5401_load_dspcode(sc); break; case MII_MODEL_BROADCOM_BCM5411: bcm5411_load_dspcode(sc); break; case MII_MODEL_BROADCOM_BCM54K2: bcm54k2_load_dspcode(sc); break; } break; } } 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); }
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 = 0, gig; 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; 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_2500_SX: speed = BRGPHY_5708S_BMCR_2500; goto setit; case IFM_1000_T: speed = BRGPHY_S1000; goto setit; case IFM_100_TX: speed = BRGPHY_S100; goto setit; case IFM_10_T: speed = BRGPHY_S10; setit: brgphy_loop(sc); if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) { speed |= BRGPHY_BMCR_FDX; gig = BRGPHY_1000CTL_AFD; } else { gig = BRGPHY_1000CTL_AHD; } PHY_WRITE(sc, BRGPHY_MII_1000CTL, 0); PHY_WRITE(sc, BRGPHY_MII_ANAR, BRGPHY_SEL_TYPE); PHY_WRITE(sc, BRGPHY_MII_BMCR, speed); if ((IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) && (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_SX) && (IFM_SUBTYPE(ife->ifm_media) != IFM_2500_SX)) break; PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig); PHY_WRITE(sc, BRGPHY_MII_BMCR, speed|BRGPHY_BMCR_AUTOEN|BRGPHY_BMCR_STARTNEG); if (sc->mii_model != MII_MODEL_xxBROADCOM_BCM5701) break; if (mii->mii_media.ifm_media & IFM_ETH_MASTER) gig |= BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC; PHY_WRITE(sc, BRGPHY_MII_1000CTL, 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) 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. */ reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (reg & BMSR_LINK) break; /* * Only retry autonegotiation every mii_anegticks seconds. */ if (++sc->mii_ticks <= sc->mii_anegticks) break; sc->mii_ticks = 0; brgphy_mii_phy_auto(sc); break; } /* 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_model) { case MII_MODEL_BROADCOM_BCM5400: brgphy_bcm5401_dspcode(sc); break; case MII_MODEL_xxBROADCOM_BCM5401: if (sc->mii_rev == 1 || sc->mii_rev == 3) brgphy_bcm5401_dspcode(sc); break; case MII_MODEL_xxBROADCOM_BCM5411: brgphy_bcm5411_dspcode(sc); break; } } /* 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; brgphy_reset(sc); /* XXX hardware bug work-around */ switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_AUTO: #ifdef foo /* * If we're already in auto mode, just return. */ if (PHY_READ(sc, BRGPHY_MII_BMCR) & BRGPHY_BMCR_AUTOEN) return (0); #endif brgphy_mii_phy_auto(sc); break; case IFM_1000_T: speed = BRGPHY_S1000; goto setit; case IFM_100_TX: speed = BRGPHY_S100; goto setit; case IFM_10_T: speed = BRGPHY_S10; setit: brgphy_loop(sc); if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) { speed |= BRGPHY_BMCR_FDX; gig = BRGPHY_1000CTL_AFD; } else { gig = BRGPHY_1000CTL_AHD; } PHY_WRITE(sc, BRGPHY_MII_1000CTL, 0); PHY_WRITE(sc, BRGPHY_MII_ANAR, BRGPHY_SEL_TYPE); PHY_WRITE(sc, BRGPHY_MII_BMCR, speed); if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) break; PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig); PHY_WRITE(sc, BRGPHY_MII_BMCR, speed|BRGPHY_BMCR_AUTOEN|BRGPHY_BMCR_STARTNEG); if (sc->mii_model != MII_MODEL_xxBROADCOM_BCM5701) break; /* * When settning the link manually, one side must * be the master and the other the slave. However * ifmedia doesn't give us a good way to specify * this, so we fake it by using one of the LINK * flags. If LINK0 is set, we program the PHY to * be a master, otherwise it's a slave. */ if ((mii->mii_ifp->if_flags & IFF_LINK0)) { PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig|BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC); } else { PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig|BRGPHY_1000CTL_MSE); } break; #ifdef foo case IFM_NONE: PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN); break; #endif case IFM_100_T4: 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) 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. */ reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (reg & BMSR_LINK) { sc->mii_ticks = 0; break; } /* * Only retry autonegotiation every 5 seconds. */ if (++sc->mii_ticks <= sc->mii_anegticks) break; sc->mii_ticks = 0; brgphy_mii_phy_auto(sc); break; } /* Update the media status. */ brgphy_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_model) { case MII_MODEL_xxBROADCOM_BCM5400: brgphy_bcm5401_dspcode(sc); break; case MII_MODEL_xxBROADCOM_BCM5401: if (sc->mii_rev == 1 || sc->mii_rev == 3) brgphy_bcm5401_dspcode(sc); break; case MII_MODEL_xxBROADCOM_BCM5411: brgphy_bcm5411_dspcode(sc); break; } } mii_phy_update(sc, cmd); return (0); }
static int brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct brgphy_softc *bsc = (struct brgphy_softc *)sc; struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int error = 0; int val; switch (cmd) { case MII_POLLSTAT: /* If we're not polling our PHY instance, just return. */ if (IFM_INST(ife->ifm_media) != sc->mii_inst) goto brgphy_service_exit; break; case MII_MEDIACHG: /* * If the media indicates a different PHY instance, * isolate ourselves. */ if (IFM_INST(ife->ifm_media) != sc->mii_inst) { PHY_WRITE(sc, MII_BMCR, PHY_READ(sc, MII_BMCR) | BMCR_ISO); goto brgphy_service_exit; } /* If the interface is not up, don't do anything. */ if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; /* Todo: Why is this here? Is it really needed? */ brgphy_reset(sc); /* XXX hardware bug work-around */ switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_AUTO: brgphy_mii_phy_auto(sc); break; case IFM_2500_SX: case IFM_1000_SX: case IFM_1000_T: case IFM_100_TX: case IFM_10_T: brgphy_setmedia(sc, ife->ifm_media, mii->mii_ifp->if_flags & IFF_LINK0); break; default: error = EINVAL; goto brgphy_service_exit; } break; case MII_TICK: /* Bail if we're not currently selected. */ if (IFM_INST(ife->ifm_media) != sc->mii_inst) goto brgphy_service_exit; /* Bail if the interface isn't up. */ if ((mii->mii_ifp->if_flags & IFF_UP) == 0) goto brgphy_service_exit; /* Bail if autoneg isn't in process. */ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { sc->mii_ticks = 0; break; } /* * Check to see if we have link. If we do, we don't * need to restart the autonegotiation process. */ val = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (val & BMSR_LINK) { sc->mii_ticks = 0; /* Reset autoneg timer. */ break; } /* Announce link loss right after it happens. */ if (sc->mii_ticks++ == 0) break; /* Only retry autonegotiation every mii_anegticks seconds. */ if (sc->mii_ticks <= sc->mii_anegticks) break; /* Retry autonegotiation */ sc->mii_ticks = 0; brgphy_mii_phy_auto(sc); break; } /* Update the media status. */ brgphy_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 (bsc->mii_oui) { case MII_OUI_BROADCOM: break; case MII_OUI_xxBROADCOM: switch (bsc->mii_model) { case MII_MODEL_xxBROADCOM_BCM5400: bcm5401_load_dspcode(sc); break; case MII_MODEL_xxBROADCOM_BCM5401: if (bsc->mii_rev == 1 || bsc->mii_rev == 3) bcm5401_load_dspcode(sc); break; case MII_MODEL_xxBROADCOM_BCM5411: bcm5411_load_dspcode(sc); break; } break; case MII_OUI_xxBROADCOM_ALT1: break; } } mii_phy_update(sc, cmd); brgphy_service_exit: return (error); }