void brgphy_reset(struct mii_softc *sc) { char *devname; devname = sc->mii_dev.dv_parent->dv_cfdata->cf_driver->cd_name; mii_phy_reset(sc); switch (sc->mii_oui) { case MII_OUI_BROADCOM: switch (sc->mii_model) { case MII_MODEL_BROADCOM_BCM5400: brgphy_bcm5401_dspcode(sc); break; case MII_MODEL_BROADCOM_BCM5401: if (sc->mii_rev == 1 || sc->mii_rev == 3) brgphy_bcm5401_dspcode(sc); break; case MII_MODEL_BROADCOM_BCM5411: brgphy_bcm5411_dspcode(sc); break; } break; case MII_OUI_xxBROADCOM: switch (sc->mii_model) { case MII_MODEL_xxBROADCOM_BCM5421: brgphy_bcm5421_dspcode(sc); break; case MII_MODEL_xxBROADCOM_BCM54K2: brgphy_bcm54k2_dspcode(sc); break; } break; } /* Handle any bge (NetXtreme/NetLink) workarounds. */ if (strcmp(devname, "bge") == 0) brgphy_reset_bge(sc); /* Handle any bnx (NetXtreme II) workarounds. */ else if (strcmp(devname, "bnx") == 0) brgphy_reset_bnx(sc); }
static void brgphy_reset(struct mii_softc *sc) { struct brgphy_softc *bsc = device_private(sc->mii_dev); mii_phy_reset(sc); 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; case MII_MODEL_BROADCOM_BCM5421: brgphy_bcm5421_dspcode(sc); break; case MII_MODEL_BROADCOM_BCM54K2: brgphy_bcm54k2_dspcode(sc); break; } break; case MII_OUI_BROADCOM3: switch (sc->mii_mpd_model) { case MII_MODEL_BROADCOM3_BCM5717C: case MII_MODEL_BROADCOM3_BCM5719C: case MII_MODEL_BROADCOM3_BCM5720C: case MII_MODEL_BROADCOM3_BCM57765: return; } break; default: break; } /* Handle any bge (NetXtreme/NetLink) workarounds. */ if (bsc->sc_isbge) { if (!(sc->mii_flags & MIIF_HAVEFIBER)) { if (bsc->sc_phyflags & BGEPHYF_ADC_BUG) brgphy_adc_bug(sc); if (bsc->sc_phyflags & BGEPHYF_5704_A0_BUG) brgphy_5704_a0_bug(sc); if (bsc->sc_phyflags & BGEPHYF_BER_BUG) brgphy_ber_bug(sc); else if (bsc->sc_phyflags & BGEPHYF_JITTER_BUG) { PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0c00); PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a); if (bsc->sc_phyflags & BGEPHYF_ADJUST_TRIM) { PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 0x110b); PHY_WRITE(sc, BRGPHY_TEST1, BRGPHY_TEST1_TRIM_EN | 0x4); } else { PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 0x010b); } PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0400); } if (bsc->sc_phyflags & BGEPHYF_CRC_BUG) brgphy_crc_bug(sc); /* Set Jumbo frame settings in the PHY. */ if (bsc->sc_phyflags & BGEPHYF_JUMBO_CAPABLE) brgphy_jumbo_settings(sc); /* Adjust output voltage */ if ((sc->mii_mpd_oui == MII_OUI_BROADCOM2) && (sc->mii_mpd_model == MII_MODEL_BROADCOM2_BCM5906)) PHY_WRITE(sc, BRGPHY_MII_EPHY_PTEST, 0x12); /* Enable Ethernet@Wirespeed */ if (!(bsc->sc_phyflags & BGEPHYF_NO_WIRESPEED)) brgphy_eth_wirespeed(sc); #if 0 /* Enable Link LED on Dell boxes */ if (bsc->sc_phyflags & BGEPHYF_NO_3LED) { PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) & ~BRGPHY_PHY_EXTCTL_3_LED); } #endif } /* Handle any bnx (NetXtreme II) workarounds. */ } else if (bsc->sc_isbnx) { #if 0 /* not yet */ if ((sc->mii_mpd_oui == MII_OUI_BROADCOM2) && sc->mii_mpd_model == MII_MODEL_BROADCOM2_BCM5708S) { /* Store autoneg capabilities/results in digital block (Page 0) */ PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG3_PG2); PHY_WRITE(sc, BRGPHY_5708S_PG2_DIGCTL_3_0, BRGPHY_5708S_PG2_DIGCTL_3_0_USE_IEEE); PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG_PG0); /* Enable fiber mode and autodetection */ PHY_WRITE(sc, BRGPHY_5708S_PG0_1000X_CTL1, PHY_READ(sc, BRGPHY_5708S_PG0_1000X_CTL1) | BRGPHY_5708S_PG0_1000X_CTL1_AUTODET_EN | BRGPHY_5708S_PG0_1000X_CTL1_FIBER_MODE); /* Enable parallel detection */ PHY_WRITE(sc, BRGPHY_5708S_PG0_1000X_CTL2, PHY_READ(sc, BRGPHY_5708S_PG0_1000X_CTL2) | BRGPHY_5708S_PG0_1000X_CTL2_PAR_DET_EN); /* Advertise 2.5G support through next page during autoneg */ if (bnx_sc->bnx_phy_flags & BNX_PHY_2_5G_CAPABLE_FLAG) PHY_WRITE(sc, BRGPHY_5708S_ANEG_NXT_PG_XMIT1, PHY_READ(sc, BRGPHY_5708S_ANEG_NXT_PG_XMIT1) | BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G); /* Increase TX signal amplitude */ if ((BNX_CHIP_ID(bnx_sc) == BNX_CHIP_ID_5708_A0) || (BNX_CHIP_ID(bnx_sc) == BNX_CHIP_ID_5708_B0) || (BNX_CHIP_ID(bnx_sc) == BNX_CHIP_ID_5708_B1)) { PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_TX_MISC_PG5); PHY_WRITE(sc, BRGPHY_5708S_PG5_TXACTL1, PHY_READ(sc, BRGPHY_5708S_PG5_TXACTL1) & ~BRGPHY_5708S_PG5_TXACTL1_VCM); PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG_PG0); } /* Backplanes use special driver/pre-driver/pre-emphasis values. */ if ((bnx_sc->bnx_shared_hw_cfg & BNX_SHARED_HW_CFG_PHY_BACKPLANE) && (bnx_sc->bnx_port_hw_cfg & BNX_PORT_HW_CFG_CFG_TXCTL3_MASK)) { PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_TX_MISC_PG5); PHY_WRITE(sc, BRGPHY_5708S_PG5_TXACTL3, bnx_sc->bnx_port_hw_cfg & BNX_PORT_HW_CFG_CFG_TXCTL3_MASK); PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG_PG0); } } else #endif if ((sc->mii_mpd_oui == MII_OUI_BROADCOM2) && (sc->mii_mpd_model == MII_MODEL_BROADCOM2_BCM5709S)) { /* Select the SerDes Digital block of the AN MMD. */ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_SERDES_DIG); PHY_WRITE(sc, BRGPHY_SERDES_DIG_1000X_CTL1, (PHY_READ(sc, BRGPHY_SERDES_DIG_1000X_CTL1) & ~BRGPHY_SD_DIG_1000X_CTL1_AUTODET) | BRGPHY_SD_DIG_1000X_CTL1_FIBER); if (bsc->sc_phyflags & BNX_PHY_2_5G_CAPABLE_FLAG) { /* Select the Over 1G block of the AN MMD. */ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_OVER_1G); /* * Enable autoneg "Next Page" to advertise * 2.5G support. */ PHY_WRITE(sc, BRGPHY_OVER_1G_UNFORMAT_PG1, PHY_READ(sc, BRGPHY_OVER_1G_UNFORMAT_PG1) | BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G); } /* * Select the Multi-Rate Backplane Ethernet block of * the AN MMD. */ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_MRBE); /* Enable MRBE speed autoneg. */ PHY_WRITE(sc, BRGPHY_MRBE_MSG_PG5_NP, PHY_READ(sc, BRGPHY_MRBE_MSG_PG5_NP) | BRGPHY_MRBE_MSG_PG5_NP_MBRE | BRGPHY_MRBE_MSG_PG5_NP_T2); /* Select the Clause 73 User B0 block of the AN MMD. */ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_CL73_USER_B0); /* Enable MRBE speed autoneg. */ PHY_WRITE(sc, BRGPHY_CL73_USER_B0_MBRE_CTL1, BRGPHY_CL73_USER_B0_MBRE_CTL1_NP_AFT_BP | BRGPHY_CL73_USER_B0_MBRE_CTL1_STA_MGR | BRGPHY_CL73_USER_B0_MBRE_CTL1_ANEG); PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_COMBO_IEEE0); } else if (_BNX_CHIP_NUM(bsc->sc_chipid) == BNX_CHIP_NUM_5709) { if (_BNX_CHIP_REV(bsc->sc_chipid) == BNX_CHIP_REV_Ax || _BNX_CHIP_REV(bsc->sc_chipid) == BNX_CHIP_REV_Bx) brgphy_disable_early_dac(sc); /* Set Jumbo frame settings in the PHY. */ brgphy_jumbo_settings(sc); /* Enable Ethernet@Wirespeed */ brgphy_eth_wirespeed(sc); } else { if (!(sc->mii_flags & MIIF_HAVEFIBER)) { brgphy_ber_bug(sc); /* Set Jumbo frame settings in the PHY. */ brgphy_jumbo_settings(sc); /* Enable Ethernet@Wirespeed */ brgphy_eth_wirespeed(sc); } } } }
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 void brgphy_reset(struct mii_softc *sc) { mii_phy_reset(sc); 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; case MII_MODEL_xxBROADCOM_BCM5421: brgphy_bcm5421_dspcode(sc); break; case MII_MODEL_xxBROADCOM_BCM54K2: brgphy_bcm54k2_dspcode(sc); break; } if (sc->mii_privtag != MII_PRIVTAG_BRGPHY) return; if (sc->mii_priv & BRGPHY_FLAG_ADC_BUG) brgphy_adc_bug(sc); if (sc->mii_priv & BRGPHY_FLAG_5704_A0) brgphy_5704_a0_bug(sc); if (sc->mii_priv & BRGPHY_FLAG_BER_BUG) { brgphy_ber_bug(sc); } else if (sc->mii_priv & BRGPHY_FLAG_JITTER_BUG) { PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0c00); PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a); if (sc->mii_priv & BRGPHY_FLAG_ADJUST_TRIM) { PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 0x110b); PHY_WRITE(sc, BRGPHY_TEST1, BRGPHY_TEST1_TRIM_EN | 0x4); } else { PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 0x010b); } PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0400); } if (sc->mii_priv & BRGPHY_FLAG_CRC_BUG) brgphy_crc_bug(sc); if (sc->mii_priv & BRGPHY_FLAG_NO_EARLYDAC) brgphy_disable_early_dac(sc); /* Set Jumbo frame settings in the PHY. */ brgphy_jumbo_settings(sc, sc->mii_pdata->mii_ifp->if_mtu); /* Adjust output voltage */ if (sc->mii_priv & BRGPHY_FLAG_5906) PHY_WRITE(sc, BRGPHY_MII_EPHY_PTEST, 0x12); /* Enable Ethernet@Wirespeed */ if (sc->mii_priv & BRGPHY_FLAG_WIRESPEED) brgphy_eth_wirespeed(sc); /* Enable Link LED on Dell boxes */ if (sc->mii_priv & BRGPHY_FLAG_NO_3LED) { PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) & ~BRGPHY_PHY_EXTCTL_3_LED); } }
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); }
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); }