On 2010/04/06 21:26, Brad wrote: > Please test the following diff if you have a system utilizing the > BCM5709S chipset. This diff adds support for the fiber PHY coupled > with the BCM5709S controller.
Has anyone tested this on an R610 or R210? > > Index: pci/if_bnx.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/if_bnx.c,v > retrieving revision 1.86 > diff -u -p -r1.86 if_bnx.c > --- pci/if_bnx.c 23 Nov 2009 10:54:43 -0000 1.86 > +++ pci/if_bnx.c 28 Mar 2010 21:45:11 -0000 > @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD: src/sys/dev/bce/if_b > * BCM5708C B1, B2 > * BCM5708S B1, B2 > * BCM5709C A1, C0 > + * BCM5709S A1, C0 > * BCM5716 C0 > * > * The following controllers are not supported by this driver: > @@ -50,7 +51,7 @@ __FBSDID("$FreeBSD: src/sys/dev/bce/if_b > * BCM5708C A0, B0 > * BCM5708S A0, B0 > * BCM5709C A0 B0, B1, B2 (pre-production) > - * BCM5709S A0, A1, B0, B1, B2, C0 (pre-production) > + * BCM5709S A0, B0, B1, B2 (pre-production) > */ > > #include <dev/pci/if_bnxreg.h> > @@ -340,6 +341,7 @@ int bnx_nvram_write(struct bnx_softc *, > /* > */ > > /****************************************************************************/ > void bnx_get_media(struct bnx_softc *); > +void bnx_init_media(struct bnx_softc *); > int bnx_dma_alloc(struct bnx_softc *); > void bnx_dma_free(struct bnx_softc *); > void bnx_release_resources(struct bnx_softc *); > @@ -905,6 +907,9 @@ bnx_attachhook(void *xsc) > sc->bnx_mii.mii_writereg = bnx_miibus_write_reg; > sc->bnx_mii.mii_statchg = bnx_miibus_statchg; > > + /* Handle any special PHY initialization for SerDes PHYs. */ > + bnx_init_media(sc); > + > /* Look for our PHY. */ > ifmedia_init(&sc->bnx_mii.mii_media, 0, bnx_ifmedia_upd, > bnx_ifmedia_sts); > @@ -1120,6 +1125,16 @@ bnx_miibus_read_reg(struct device *dev, > return(0); > } > > + /* > + * The BCM5709S PHY is an IEEE Clause 45 PHY > + * with special mappings to work with IEEE > + * Clause 22 register accesses. > + */ > + if ((sc->bnx_phy_flags & BNX_PHY_IEEE_CLAUSE_45_FLAG) != 0) { > + if (reg >= MII_BMCR && reg <= MII_ANLPRNP) > + reg += 0x10; > + } > + > if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) { > val = REG_RD(sc, BNX_EMAC_MDIO_MODE); > val &= ~BNX_EMAC_MDIO_MODE_AUTO_POLL; > @@ -1199,6 +1214,16 @@ bnx_miibus_write_reg(struct device *dev, > "val = 0x%04X\n", __FUNCTION__, > phy, (u_int16_t) reg & 0xffff, (u_int16_t) val & 0xffff); > > + /* > + * The BCM5709S PHY is an IEEE Clause 45 PHY > + * with special mappings to work with IEEE > + * Clause 22 register accesses. > + */ > + if ((sc->bnx_phy_flags & BNX_PHY_IEEE_CLAUSE_45_FLAG) != 0) { > + if (reg >= MII_BMCR && reg <= MII_ANLPRNP) > + reg += 0x10; > + } > + > if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) { > val1 = REG_RD(sc, BNX_EMAC_MDIO_MODE); > val1 &= ~BNX_EMAC_MDIO_MODE_AUTO_POLL; > @@ -2179,6 +2204,7 @@ bnx_get_media(struct bnx_softc *sc) > DBPRINT(sc, BNX_INFO_LOAD, > "BCM5709 s/w configured for SerDes.\n"); > sc->bnx_phy_flags |= BNX_PHY_SERDES_FLAG; > + break; > default: > DBPRINT(sc, BNX_INFO_LOAD, > "BCM5709 s/w configured for Copper.\n"); > @@ -2191,6 +2217,7 @@ bnx_get_media(struct bnx_softc *sc) > DBPRINT(sc, BNX_INFO_LOAD, > "BCM5709 s/w configured for SerDes.\n"); > sc->bnx_phy_flags |= BNX_PHY_SERDES_FLAG; > + break; > default: > DBPRINT(sc, BNX_INFO_LOAD, > "BCM5709 s/w configured for Copper.\n"); > @@ -2202,6 +2229,14 @@ bnx_get_media(struct bnx_softc *sc) > > if (sc->bnx_phy_flags && BNX_PHY_SERDES_FLAG) { > sc->bnx_flags |= BNX_NO_WOL_FLAG; > + > + if (BNX_CHIP_NUM(sc) == BNX_CHIP_NUM_5709) > + sc->bnx_phy_flags |= BNX_PHY_IEEE_CLAUSE_45_FLAG; > + > + /* > + * The BCM5708S, BCM5709S, and BCM5716S controllers use a > + * separate PHY for SerDes. > + */ > if (BNX_CHIP_NUM(sc) != BNX_CHIP_NUM_5706) { > sc->bnx_phy_addr = 2; > val = REG_RD_IND(sc, sc->bnx_shmem_base + > @@ -2219,6 +2254,36 @@ bnx_get_media(struct bnx_softc *sc) > bnx_get_media_exit: > DBPRINT(sc, (BNX_INFO_LOAD | BNX_INFO_PHY), > "Using PHY address %d.\n", sc->bnx_phy_addr); > +} > + > +/****************************************************************************/ > +/* Performs PHY initialization required before MII drivers access the > */ > +/* device. > */ > +/* > */ > +/* Returns: > */ > +/* Nothing. > */ > +/****************************************************************************/ > +void > +bnx_init_media(struct bnx_softc *sc) > +{ > + if (sc->bnx_phy_flags & BNX_PHY_IEEE_CLAUSE_45_FLAG) { > + /* > + * Configure the BCM5709S / BCM5716S PHYs to use traditional > + * IEEE Clause 22 method. Otherwise we have no way to attach > + * the PHY to the mii(4) layer. PHY specific configuration > + * is done by the mii(4) layer. > + */ > + > + /* Select auto-negotiation MMD of the PHY. */ > + bnx_miibus_write_reg(&sc->bnx_dev, sc->bnx_phy_addr, > + BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_ADDR_EXT); > + > + bnx_miibus_write_reg(&sc->bnx_dev, sc->bnx_phy_addr, > + BRGPHY_ADDR_EXT, BRGPHY_ADDR_EXT_AN_MMD); > + > + bnx_miibus_write_reg(&sc->bnx_dev, sc->bnx_phy_addr, > + BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_COMBO_IEEE0); > + } > } > > > /****************************************************************************/ > Index: pci/if_bnxreg.h > =================================================================== > RCS file: /cvs/src/sys/dev/pci/if_bnxreg.h,v > retrieving revision 1.34 > diff -u -p -r1.34 if_bnxreg.h > --- pci/if_bnxreg.h 23 Nov 2009 10:54:43 -0000 1.34 > +++ pci/if_bnxreg.h 28 Mar 2010 23:59:31 -0000 > @@ -4803,6 +4803,7 @@ struct bnx_softc { > #define BNX_PHY_INT_MODE_MASK_FLAG 0x300 > #define BNX_PHY_INT_MODE_AUTO_POLLING_FLAG 0x100 > #define BNX_PHY_INT_MODE_LINK_READY_FLAG 0x200 > +#define BNX_PHY_IEEE_CLAUSE_45_FLAG 0x400 > > /* Values that need to be shared with the PHY driver. */ > u_int32_t bnx_shared_hw_cfg; > Index: mii/brgphy.c > =================================================================== > RCS file: /cvs/src/sys/dev/mii/brgphy.c,v > retrieving revision 1.91 > diff -u -p -r1.91 brgphy.c > --- mii/brgphy.c 6 Apr 2010 20:20:52 -0000 1.91 > +++ mii/brgphy.c 7 Apr 2010 00:18:21 -0000 > @@ -81,6 +81,7 @@ int brgphy_service(struct mii_softc *, s > void brgphy_copper_status(struct mii_softc *); > void brgphy_fiber_status(struct mii_softc *); > void brgphy_5708s_status(struct mii_softc *); > +void brgphy_5709s_status(struct mii_softc *); > int brgphy_mii_phy_auto(struct mii_softc *); > void brgphy_loop(struct mii_softc *); > void brgphy_reset(struct mii_softc *); > @@ -108,6 +109,10 @@ const struct mii_phy_funcs brgphy_5708s_ > brgphy_service, brgphy_5708s_status, brgphy_reset, > }; > > +const struct mii_phy_funcs brgphy_5709s_funcs = { > + brgphy_service, brgphy_5709s_status, brgphy_reset, > +}; > + > static const struct mii_phydesc brgphys[] = { > { MII_OUI_xxBROADCOM, MII_MODEL_xxBROADCOM_BCM5400, > MII_STR_xxBROADCOM_BCM5400 }, > @@ -161,6 +166,8 @@ static const struct mii_phydesc brgphys[ > MII_STR_xxBROADCOM2_BCM5708S }, > { MII_OUI_xxBROADCOM2, MII_MODEL_xxBROADCOM2_BCM5709C, > MII_STR_xxBROADCOM2_BCM5709C }, > + { MII_OUI_xxBROADCOM2, MII_MODEL_xxBROADCOM2_BCM5709S, > + MII_STR_xxBROADCOM2_BCM5709S }, > { MII_OUI_xxBROADCOM2, MII_MODEL_xxBROADCOM2_BCM5709CAX, > MII_STR_xxBROADCOM2_BCM5709CAX }, > { MII_OUI_xxBROADCOM3, MII_MODEL_xxBROADCOM3_BCM57780, > @@ -219,6 +226,8 @@ brgphy_attach(struct device *parent, str > if (strcmp(devname, "bnx") == 0) { > if (BNX_CHIP_NUM(bnx_sc) == BNX_CHIP_NUM_5708) > sc->mii_funcs = &brgphy_5708s_funcs; > + else if (BNX_CHIP_NUM(bnx_sc) == BNX_CHIP_NUM_5709) > + sc->mii_funcs = &brgphy_5709s_funcs; > else > sc->mii_funcs = &brgphy_fiber_funcs; > } else > @@ -609,6 +618,64 @@ brgphy_5708s_status(struct mii_softc *sc > mii->mii_media_active = ife->ifm_media; > } > > +void > +brgphy_5709s_status(struct mii_softc *sc) > +{ > + struct mii_data *mii = sc->mii_pdata; > + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; > + int bmcr, bmsr; > + > + mii->mii_media_status = IFM_AVALID; > + mii->mii_media_active = IFM_ETHER; > + > + bmsr = PHY_READ(sc, BRGPHY_MII_BMSR) | PHY_READ(sc, BRGPHY_MII_BMSR); > + if (bmsr & BRGPHY_BMSR_LINK) > + mii->mii_media_status |= IFM_ACTIVE; > + > + bmcr = PHY_READ(sc, BRGPHY_MII_BMCR); > + if (bmcr & BRGPHY_BMCR_LOOP) > + mii->mii_media_active |= IFM_LOOP; > + > + if (bmcr & BRGPHY_BMCR_AUTOEN) { > + int xstat; > + > + if ((bmsr & BRGPHY_BMSR_ACOMP) == 0) { > + /* Erg, still trying, I guess... */ > + mii->mii_media_active |= IFM_NONE; > + return; > + } > + > + PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, > + BRGPHY_BLOCK_ADDR_GP_STATUS); > + > + xstat = PHY_READ(sc, BRGPHY_GP_STATUS_TOP_ANEG_STATUS); > + > + PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, > + BRGPHY_BLOCK_ADDR_COMBO_IEEE0); > + > + switch (xstat & BRGPHY_GP_STATUS_TOP_ANEG_SPEED_MASK) { > + case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_10: > + mii->mii_media_active |= IFM_10_FL; > + break; > + case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_100: > + mii->mii_media_active |= IFM_100_FX; > + break; > + case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_1G: > + mii->mii_media_active |= IFM_1000_SX; > + break; > + case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_25G: > + mii->mii_media_active |= IFM_2500_SX; > + break; > + } > + > + if (xstat & BRGPHY_GP_STATUS_TOP_ANEG_FDX) > + mii->mii_media_active |= IFM_FDX; > + else > + mii->mii_media_active |= IFM_HDX; > + } else > + mii->mii_media_active = ife->ifm_media; > +} > + > int > brgphy_mii_phy_auto(struct mii_softc *sc) > { > @@ -792,6 +859,56 @@ brgphy_reset(struct mii_softc *sc) > PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, > BRGPHY_5708S_DIG_PG0); > } > + } else if (BNX_CHIP_NUM(bnx_sc) == BNX_CHIP_NUM_5709 && > + sc->mii_flags & MIIF_HAVEFIBER) { > + /* 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 (bnx_sc->bnx_phy_flags & 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(bnx_sc) == BNX_CHIP_NUM_5709) { > if (BNX_CHIP_REV(bnx_sc) == BNX_CHIP_REV_Ax || > BNX_CHIP_REV(bnx_sc) == BNX_CHIP_REV_Bx) > Index: mii/brgphyreg.h > =================================================================== > RCS file: /cvs/src/sys/dev/mii/brgphyreg.h,v > retrieving revision 1.13 > diff -u -p -r1.13 brgphyreg.h > --- mii/brgphyreg.h 8 Nov 2008 03:03:50 -0000 1.13 > +++ mii/brgphyreg.h 30 Mar 2010 00:16:57 -0000 > @@ -369,6 +369,61 @@ > /* End: PHY register values for the 5708S SerDes PHY */ > /*******************************************************/ > > +/*******************************************************/ > +/* Begin: PHY register values for the 5709S SerDes PHY */ > +/*******************************************************/ > + > +/* 5709S SerDes "General Purpose Status" Registers */ > +#define BRGPHY_BLOCK_ADDR_GP_STATUS 0x8120 > +#define BRGPHY_GP_STATUS_TOP_ANEG_STATUS 0x1B > +#define BRGPHY_GP_STATUS_TOP_ANEG_SPEED_MASK 0x3F00 > +#define BRGPHY_GP_STATUS_TOP_ANEG_SPEED_10 0x0000 > +#define BRGPHY_GP_STATUS_TOP_ANEG_SPEED_100 0x0100 > +#define BRGPHY_GP_STATUS_TOP_ANEG_SPEED_1G 0x0200 > +#define BRGPHY_GP_STATUS_TOP_ANEG_SPEED_25G 0x0300 > +#define BRGPHY_GP_STATUS_TOP_ANEG_SPEED_1GKX 0x0D00 > +#define BRGPHY_GP_STATUS_TOP_ANEG_FDX 0x0008 > +#define BRGPHY_GP_STATUS_TOP_ANEG_LINK_UP 0x0004 > +#define BRGPHY_GP_STATUS_TOP_ANEG_CL73_COMP 0x0001 > + > +/* 5709S SerDes "SerDes Digital" Registers */ > +#define BRGPHY_BLOCK_ADDR_SERDES_DIG 0x8300 > +#define BRGPHY_SERDES_DIG_1000X_CTL1 0x0010 > +#define BRGPHY_SD_DIG_1000X_CTL1_AUTODET 0x0010 > +#define BRGPHY_SD_DIG_1000X_CTL1_FIBER 0x0001 > + > +/* 5709S SerDes "Over 1G" Registers */ > +#define BRGPHY_BLOCK_ADDR_OVER_1G 0x8320 > +#define BRGPHY_OVER_1G_UNFORMAT_PG1 0x19 > + > +/* 5709S SerDes "Multi-Rate Backplane Ethernet" Registers */ > +#define BRGPHY_BLOCK_ADDR_MRBE 0x8350 > +#define BRGPHY_MRBE_MSG_PG5_NP 0x10 > +#define BRGPHY_MRBE_MSG_PG5_NP_MBRE 0x0001 > +#define BRGPHY_MRBE_MSG_PG5_NP_T2 0x0001 > + > +/* 5709S SerDes "IEEE Clause 73 User B0" Registers */ > +#define BRGPHY_BLOCK_ADDR_CL73_USER_B0 0x8370 > +#define BRGPHY_CL73_USER_B0_MBRE_CTL1 0x12 > +#define BRGPHY_CL73_USER_B0_MBRE_CTL1_NP_AFT_BP 0x2000 > +#define BRGPHY_CL73_USER_B0_MBRE_CTL1_STA_MGR 0x4000 > +#define BRGPHY_CL73_USER_B0_MBRE_CTL1_ANEG 0x8000 > + > +/* 5709S SerDes "IEEE Clause 73 User B0" Registers */ > +#define BRGPHY_BLOCK_ADDR_ADDR_EXT 0xFFD0 > + > +/* 5709S SerDes "Combo IEEE 0" Registers */ > +#define BRGPHY_BLOCK_ADDR_COMBO_IEEE0 0xFFE0 > + > +#define BRGPHY_ADDR_EXT 0x1E > +#define BRGPHY_BLOCK_ADDR 0x1F > + > +#define BRGPHY_ADDR_EXT_AN_MMD 0x3800 > + > +/*******************************************************/ > +/* End: PHY register values for the 5709S SerDes PHY */ > +/*******************************************************/ > + > #define BRGPHY_INTRS \ > ~(BRGPHY_IMR_LNK_CHG|BRGPHY_IMR_LSP_CHG|BRGPHY_IMR_DUP_CHG) > > > -- > This message has been scanned for viruses and > dangerous content by MailScanner, and is > believed to be clean.