tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
brgphy(4) and bnx(4) BCM5709S (SerDes) support
Dear all,
Just FYI, in case someone else might be working on it: I am about to
update bnx(4) and brgphy(4) to support Broadcom cards with SerDes PHY
(BCM 5709S). Preliminary patch is attached.
Code originates from OpenBSD, with a few modifications here and there to
adapt to our own drivers (of interest: endianness support)
Unfortunately, I cannot test it for regressions extensively, as I don't
have any bnx(4) NIC at hand (I have only access to a Dell M710, kindly
provided by Uwe Toenjes, which contains BCM5709S NICs). So, if anyone
has a NIC working through bnx(4), and could eventually test the upcoming
patch, please mail me. bge(4) should remain unaffected.
SerDes and endianness support will be committed separately, once I get
confirmation that bnx(4) and brgphy(4) still work. Ideally, the
endianness patch should be tested on a big endian arch (sparc64)
Thanks to Uwe Toenjes <6bone.informatik.uni-leipzig.de> , who kindly
gave me access to a Dell M710 for porting and testing.
--
Jean-Yves Migeon
jeanyves.migeon%free.fr@localhost
Index: sys/dev/mii/brgphy.c
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/brgphy.c,v
retrieving revision 1.56
diff -u -p -r1.56 brgphy.c
--- sys/dev/mii/brgphy.c 27 Nov 2010 17:42:04 -0000 1.56
+++ sys/dev/mii/brgphy.c 27 Nov 2010 18:35:31 -0000
@@ -81,9 +81,7 @@ __KERNEL_RCSID(0, "$NetBSD: brgphy.c,v 1
#include <dev/mii/brgphyreg.h>
#include <dev/pci/if_bgereg.h>
-#if 0
#include <dev/pci/if_bnxreg.h>
-#endif
static int brgphymatch(device_t, cfdata_t, void *);
static void brgphyattach(device_t, device_t, void *);
@@ -182,6 +180,9 @@ static const struct mii_phydesc brgphys[
{ MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5709C,
MII_STR_BROADCOM2_BCM5709C },
+ { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5709S,
+ MII_STR_BROADCOM2_BCM5709S },
+
{ MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5709CAX,
MII_STR_BROADCOM2_BCM5709CAX },
@@ -226,6 +227,7 @@ brgphyattach(device_t parent, device_t s
struct mii_attach_args *ma = aux;
struct mii_data *mii = ma->mii_data;
const struct mii_phydesc *mpd;
+ const char *sep = "";
prop_dictionary_t dict;
mpd = mii_phy_match(ma, brgphys);
@@ -253,7 +255,35 @@ brgphyattach(device_t parent, device_t s
if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
(sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
aprint_error("no media present");
- else
+ else if (sc->mii_flags & MIIF_HAVEFIBER) {
+ sc->mii_anegticks = MII_ANEGTICKS_GIGE;
+#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
+#define PRINT(str) aprint_normal("%s%s", sep, str); sep = ", "
+ /* forcer sur extcapabilities si ca marche pas */
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX,
+ sc->mii_inst), BMCR_S1000 | BMCR_FDX);
+ PRINT("1000baseSX");
+ if (device_is_a(parent, "bnx")) {
+ struct bnx_softc *bnx_sc = device_private(parent);
+ /*
+ * 2.5Gb support is a software enabled feature on the
+ * BCM5708S and BCM5709S controllers.
+ */
+ if (bnx_sc->bnx_phy_flags & BNX_PHY_2_5G_CAPABLE_FLAG) {
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_2500_SX,
+ IFM_FDX, sc->mii_inst), 0);
+ PRINT("2500baseSX");
+ }
+ }
+
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
+
+ sc->mii_flags |= MIIF_IS_1000X;
+
+ sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
+#undef ADD
+#undef PRINT
+ } else
mii_phy_add_media(sc);
aprint_normal("\n");
@@ -399,14 +429,13 @@ brgphy_status(struct mii_softc *sc)
{
struct mii_data *mii = sc->mii_pdata;
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
- int bmcr, auxsts, gtsr;
+ int bmcr, bmsr, auxsts, gtsr;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
- auxsts = PHY_READ(sc, BRGPHY_MII_AUXSTS);
-
- if (auxsts & BRGPHY_AUXSTS_LINK)
+ bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
+ if (bmsr & BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
bmcr = PHY_READ(sc, MII_BMCR);
@@ -424,53 +453,95 @@ brgphy_status(struct mii_softc *sc)
* The media status bits are only valid of autonegotiation
* has completed (or it's disabled).
*/
- if ((auxsts & BRGPHY_AUXSTS_ACOMP) == 0) {
+ if ((bmsr & BMSR_ACOMP) == 0) {
/* Erg, still trying, I guess... */
mii->mii_media_active |= IFM_NONE;
return;
}
- switch (auxsts & BRGPHY_AUXSTS_AN_RES) {
- case BRGPHY_RES_1000FD:
- mii->mii_media_active |= IFM_1000_T|IFM_FDX;
- gtsr = PHY_READ(sc, MII_100T2SR);
- if (gtsr & GTSR_MS_RES)
- mii->mii_media_active |= IFM_ETH_MASTER;
- break;
+ if (sc->mii_mpd_model == MII_MODEL_BROADCOM2_BCM5709S) {
- case BRGPHY_RES_1000HD:
- mii->mii_media_active |= IFM_1000_T;
- gtsr = PHY_READ(sc, MII_100T2SR);
- if (gtsr & GTSR_MS_RES)
- mii->mii_media_active |= IFM_ETH_MASTER;
- break;
+ /* 5709S has its own general purpose status registers */
+
+ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR,
+ BRGPHY_BLOCK_ADDR_GP_STATUS);
- case BRGPHY_RES_100FD:
- mii->mii_media_active |= IFM_100_TX|IFM_FDX;
- break;
+ auxsts = PHY_READ(sc, BRGPHY_GP_STATUS_TOP_ANEG_STATUS);
- case BRGPHY_RES_100T4:
- mii->mii_media_active |= IFM_100_T4;
- break;
+ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR,
+ BRGPHY_BLOCK_ADDR_COMBO_IEEE0);
- case BRGPHY_RES_100HD:
- mii->mii_media_active |= IFM_100_TX;
- break;
+ switch (auxsts & 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;
+ default:
+ mii->mii_media_active |= IFM_NONE;
+ mii->mii_media_status = 0;
+ break;
+ }
- case BRGPHY_RES_10FD:
- mii->mii_media_active |= IFM_10_T|IFM_FDX;
- break;
+ if (auxsts & BRGPHY_GP_STATUS_TOP_ANEG_FDX)
+ mii->mii_media_active |= IFM_FDX;
+ else
+ mii->mii_media_active |= IFM_HDX;
- case BRGPHY_RES_10HD:
- mii->mii_media_active |= IFM_10_T;
- break;
+ } else {
+ auxsts = PHY_READ(sc, BRGPHY_MII_AUXSTS);
- default:
- mii->mii_media_active |= IFM_NONE;
- mii->mii_media_status = 0;
+ switch (auxsts & BRGPHY_AUXSTS_AN_RES) {
+ case BRGPHY_RES_1000FD:
+ mii->mii_media_active |= IFM_1000_T|IFM_FDX;
+ gtsr = PHY_READ(sc, MII_100T2SR);
+ if (gtsr & GTSR_MS_RES)
+ mii->mii_media_active |= IFM_ETH_MASTER;
+ break;
+
+ case BRGPHY_RES_1000HD:
+ mii->mii_media_active |= IFM_1000_T;
+ gtsr = PHY_READ(sc, MII_100T2SR);
+ if (gtsr & GTSR_MS_RES)
+ mii->mii_media_active |= IFM_ETH_MASTER;
+ break;
+
+ case BRGPHY_RES_100FD:
+ mii->mii_media_active |= IFM_100_TX|IFM_FDX;
+ break;
+
+ case BRGPHY_RES_100T4:
+ mii->mii_media_active |= IFM_100_T4;
+ break;
+
+ case BRGPHY_RES_100HD:
+ mii->mii_media_active |= IFM_100_TX;
+ break;
+
+ case BRGPHY_RES_10FD:
+ mii->mii_media_active |= IFM_10_T|IFM_FDX;
+ break;
+
+ case BRGPHY_RES_10HD:
+ mii->mii_media_active |= IFM_10_T;
+ break;
+
+ default:
+ mii->mii_media_active |= IFM_NONE;
+ mii->mii_media_status = 0;
+ }
}
+
if (mii->mii_media_active & IFM_FDX)
mii->mii_media_active |= mii_phy_flowstatus(sc);
+
} else
mii->mii_media_active = ife->ifm_media;
}
@@ -519,6 +590,7 @@ brgphy_loop(struct mii_softc *sc)
static void
brgphy_reset(struct mii_softc *sc)
{
+ struct bnx_softc *bnx_sc;
struct brgphy_softc *bsc = device_private(sc->mii_dev);
mii_phy_reset(sc);
@@ -593,11 +665,11 @@ brgphy_reset(struct mii_softc *sc)
}
#endif
}
-#if 0 /* not yet */
/* Handle any bnx (NetXtreme II) workarounds. */
- } else if (sc->sc_isbnx) {
- bnx_sc = sc->mii_pdata->mii_ifp->if_softc;
+ } else if (bsc->sc_isbnx) {
+ bnx_sc = device_private(device_parent(sc->mii_dev));
+#if 0 /* not yet */
if (sc->mii_mpd_model == MII_MODEL_xxBROADCOM2_BCM5708S) {
/* Store autoneg capabilities/results in digital block
(Page 0) */
PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR,
BRGPHY_5708S_DIG3_PG2);
@@ -646,6 +718,58 @@ brgphy_reset(struct mii_softc *sc)
PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR,
BRGPHY_5708S_DIG_PG0);
}
+ } else
+#endif
+ if (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 (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 (!(sc->mii_flags & MIIF_HAVEFIBER)) {
brgphy_ber_bug(sc);
@@ -657,7 +781,6 @@ brgphy_reset(struct mii_softc *sc)
brgphy_eth_wirespeed(sc);
}
}
-#endif
}
}
Index: sys/dev/mii/brgphyreg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/brgphyreg.h,v
retrieving revision 1.4
diff -u -p -r1.4 brgphyreg.h
--- sys/dev/mii/brgphyreg.h 19 Apr 2009 11:10:36 -0000 1.4
+++ sys/dev/mii/brgphyreg.h 27 Nov 2010 18:35:31 -0000
@@ -223,6 +223,111 @@
/* End: PHY register values for the 5706 PHY */
/*******************************************************/
+/*******************************************************/
+/* Begin: PHY register values for the 5708S SerDes PHY */
+/*******************************************************/
+
+#define BRGPHY_5708S_BMCR_2500 0x20
+
+/* Autoneg Next Page Transmit 1 Regiser */
+#define BRGPHY_5708S_ANEG_NXT_PG_XMIT1 0x0B
+#define BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G 0x0001
+
+/* Use the BLOCK_ADDR register to select the page for registers 0x10 to 0x1E */
+#define BRGPHY_5708S_BLOCK_ADDR 0x1f
+#define BRGPHY_5708S_DIG_PG0 0x0000
+#define BRGPHY_5708S_DIG3_PG2 0x0002
+#define BRGPHY_5708S_TX_MISC_PG5 0x0005
+
+/* 5708S SerDes "Digital" Registers (page 0) */
+#define BRGPHY_5708S_PG0_1000X_CTL1 0x10
+#define BRGPHY_5708S_PG0_1000X_CTL1_FIBER_MODE 0x0001
+#define BRGPHY_5708S_PG0_1000X_CTL1_AUTODET_EN 0x0010
+
+#define BRGPHY_5708S_PG0_1000X_STAT1 0x14
+#define BRGPHY_5708S_PG0_1000X_STAT1_SGMII 0x0001
+#define BRGPHY_5708S_PG0_1000X_STAT1_LINK 0x0002
+#define BRGPHY_5708S_PG0_1000X_STAT1_FDX 0x0004
+#define BRGPHY_5708S_PG0_1000X_STAT1_SPEED_MASK 0x0018
+#define BRGPHY_5708S_PG0_1000X_STAT1_SPEED_10 (0x0 << 3)
+#define BRGPHY_5708S_PG0_1000X_STAT1_SPEED_100 (0x1 << 3)
+#define BRGPHY_5708S_PG0_1000X_STAT1_SPEED_1G (0x2 << 3)
+#define BRGPHY_5708S_PG0_1000X_STAT1_SPEED_25G (0x3 << 3)
+
+#define BRGPHY_5708S_PG0_1000X_CTL2 0x11
+#define BRGPHY_5708S_PG0_1000X_CTL2_PAR_DET_EN 0x0001
+
+/* 5708S SerDes "Digital 3" Registers (page 2) */
+#define BRGPHY_5708S_PG2_DIGCTL_3_0 0x10
+#define BRGPHY_5708S_PG2_DIGCTL_3_0_USE_IEEE 0x0001
+
+/* 5708S SerDes "TX Misc" Registers (page 5) */
+#define BRGPHY_5708S_PG5_2500STATUS1 0x10
+
+#define BRGPHY_5708S_PG5_TXACTL1 0x15
+#define BRGPHY_5708S_PG5_TXACTL1_VCM 0x30
+
+#define BRGPHY_5708S_PG5_TXACTL3 0x17
+
+/*******************************************************/
+/* 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)
Index: sys/dev/pci/if_bnx.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_bnx.c,v
retrieving revision 1.35
diff -u -p -r1.35 if_bnx.c
--- sys/dev/pci/if_bnx.c 27 Nov 2010 17:48:58 -0000 1.35
+++ sys/dev/pci/if_bnx.c 27 Nov 2010 18:35:33 -0000
@@ -44,6 +44,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_bnx.c,v 1
* BCM5708C B1, B2
* BCM5708S B1, B2
* BCM5709C A1, C0
+ * BCM5709S A1, C0
* BCM5716 C0
*
* The following controllers are not supported by this driver:
@@ -53,7 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_bnx.c,v 1
* 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 <sys/callout.h>
@@ -343,6 +344,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 *);
@@ -705,6 +707,9 @@ bnx_attach(device_t parent, device_t sel
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);
+
sc->bnx_ec.ec_mii = &sc->bnx_mii;
ifmedia_init(&sc->bnx_mii.mii_media, 0, ether_mediachange,
ether_mediastatus);
@@ -917,6 +922,16 @@ bnx_miibus_read_reg(device_t dev, int ph
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;
@@ -996,6 +1011,16 @@ bnx_miibus_write_reg(device_t dev, int p
"val = 0x%04X\n", __func__,
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;
@@ -2002,6 +2027,14 @@ bnx_get_media(struct bnx_softc *sc)
u_int32_t val;
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 +
@@ -2022,6 +2055,36 @@ bnx_get_media_exit:
}
/****************************************************************************/
+/* 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);
+ }
+}
+
+/****************************************************************************/
/* Free any DMA memory owned by the driver. */
/* */
/* Scans through each data structre that requires DMA memory and frees */
@@ -3607,12 +3670,12 @@ bnx_add_buf(struct bnx_softc *sc, struct
*/
rxbd = &sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)];
- addr = (u_int32_t)(map->dm_segs[0].ds_addr);
- rxbd->rx_bd_haddr_lo = htole32(addr);
+ addr = (u_int32_t)map->dm_segs[0].ds_addr;
+ rxbd->rx_bd_haddr_lo = addr;
addr = (u_int32_t)((u_int64_t)map->dm_segs[0].ds_addr >> 32);
- rxbd->rx_bd_haddr_hi = htole32(addr);
- rxbd->rx_bd_len = htole32(map->dm_segs[0].ds_len);
- rxbd->rx_bd_flags = htole32(RX_BD_FLAGS_START);
+ rxbd->rx_bd_haddr_hi = addr;
+ rxbd->rx_bd_len = map->dm_segs[0].ds_len;
+ rxbd->rx_bd_flags = RX_BD_FLAGS_START;
*prod_bseq += map->dm_segs[0].ds_len;
bus_dmamap_sync(sc->bnx_dmatag,
sc->rx_bd_chain_map[RX_PAGE(*chain_prod)],
@@ -3626,11 +3689,11 @@ bnx_add_buf(struct bnx_softc *sc, struct
rxbd =
&sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)];
- addr = (u_int32_t)(map->dm_segs[i].ds_addr);
- rxbd->rx_bd_haddr_lo = htole32(addr);
+ addr = (u_int32_t)map->dm_segs[i].ds_addr;
+ rxbd->rx_bd_haddr_lo = addr;
addr = (u_int32_t)((u_int64_t)map->dm_segs[i].ds_addr >> 32);
- rxbd->rx_bd_haddr_hi = htole32(addr);
- rxbd->rx_bd_len = htole32(map->dm_segs[i].ds_len);
+ rxbd->rx_bd_haddr_hi = addr;
+ rxbd->rx_bd_len = map->dm_segs[i].ds_len;
rxbd->rx_bd_flags = 0;
*prod_bseq += map->dm_segs[i].ds_len;
bus_dmamap_sync(sc->bnx_dmatag,
@@ -3639,7 +3702,7 @@ bnx_add_buf(struct bnx_softc *sc, struct
sizeof(struct rx_bd), BUS_DMASYNC_PREREAD |
BUS_DMASYNC_PREWRITE);
}
- rxbd->rx_bd_flags |= htole32(RX_BD_FLAGS_END);
+ rxbd->rx_bd_flags |= RX_BD_FLAGS_END;
bus_dmamap_sync(sc->bnx_dmatag,
sc->rx_bd_chain_map[RX_PAGE(*chain_prod)],
sizeof(struct rx_bd) * RX_IDX(*chain_prod),
@@ -3894,10 +3957,10 @@ bnx_init_tx_chain(struct bnx_softc *sc)
else
j = i + 1;
- addr = (u_int32_t)(sc->tx_bd_chain_paddr[j]);
- txbd->tx_bd_haddr_lo = htole32(addr);
+ addr = (u_int32_t)sc->tx_bd_chain_paddr[j];
+ txbd->tx_bd_haddr_lo = addr;
addr = (u_int32_t)((u_int64_t)sc->tx_bd_chain_paddr[j] >> 32);
- txbd->tx_bd_haddr_hi = htole32(addr);
+ txbd->tx_bd_haddr_hi = addr;
bus_dmamap_sync(sc->bnx_dmatag, sc->tx_bd_chain_map[i], 0,
BNX_TX_CHAIN_PAGE_SZ, BUS_DMASYNC_PREWRITE);
}
@@ -4062,9 +4125,9 @@ bnx_init_rx_chain(struct bnx_softc *sc)
/* Setup the chain page pointers. */
addr = (u_int32_t)((u_int64_t)sc->rx_bd_chain_paddr[j] >> 32);
- rxbd->rx_bd_haddr_hi = htole32(addr);
- addr = (u_int32_t)(sc->rx_bd_chain_paddr[j]);
- rxbd->rx_bd_haddr_lo = htole32(addr);
+ rxbd->rx_bd_haddr_hi = addr;
+ addr = (u_int32_t)sc->rx_bd_chain_paddr[j];
+ rxbd->rx_bd_haddr_lo = addr;
bus_dmamap_sync(sc->bnx_dmatag, sc->rx_bd_chain_map[i],
0, BNX_RX_CHAIN_PAGE_SZ,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -4843,20 +4906,20 @@ again:
chain_prod = TX_CHAIN_IDX(prod);
txbd =
&sc->tx_bd_chain[TX_PAGE(chain_prod)][TX_IDX(chain_prod)];
- addr = (u_int32_t)(map->dm_segs[i].ds_addr);
- txbd->tx_bd_haddr_lo = htole32(addr);
+ addr = (u_int32_t)map->dm_segs[i].ds_addr;
+ txbd->tx_bd_haddr_lo = addr;
addr = (u_int32_t)((u_int64_t)map->dm_segs[i].ds_addr >> 32);
- txbd->tx_bd_haddr_hi = htole32(addr);
- txbd->tx_bd_mss_nbytes = htole16(map->dm_segs[i].ds_len);
- txbd->tx_bd_vlan_tag = htole16(vlan_tag);
- txbd->tx_bd_flags = htole16(flags);
+ txbd->tx_bd_haddr_hi = addr;
+ txbd->tx_bd_mss_nbytes = map->dm_segs[i].ds_len;
+ txbd->tx_bd_vlan_tag = vlan_tag;
+ txbd->tx_bd_flags = flags;
prod_bseq += map->dm_segs[i].ds_len;
if (i == 0)
- txbd->tx_bd_flags |= htole16(TX_BD_FLAGS_START);
+ txbd->tx_bd_flags |= TX_BD_FLAGS_START;
prod = NEXT_TX_BD(prod);
}
/* Set the END flag on the last TX buffer descriptor. */
- txbd->tx_bd_flags |= htole16(TX_BD_FLAGS_END);
+ txbd->tx_bd_flags |= TX_BD_FLAGS_END;
DBRUN(BNX_INFO_SEND, bnx_dump_tx_chain(sc, debug_prod, map->dm_nsegs));
Index: sys/dev/pci/if_bnxreg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_bnxreg.h,v
retrieving revision 1.10
diff -u -p -r1.10 if_bnxreg.h
--- sys/dev/pci/if_bnxreg.h 19 Jan 2010 22:07:00 -0000 1.10
+++ sys/dev/pci/if_bnxreg.h 27 Nov 2010 18:35:35 -0000
@@ -718,8 +718,13 @@ struct tx_bd {
u_int32_t tx_bd_haddr_hi;
u_int32_t tx_bd_haddr_lo;
u_int32_t tx_bd_mss_nbytes;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_int16_t tx_bd_vlan_tag;
+ u_int16_t tx_bd_flags;
+#else
u_int16_t tx_bd_flags;
u_int16_t tx_bd_vlan_tag;
+#endif
#define TX_BD_FLAGS_CONN_FAULT (1<<0)
#define TX_BD_FLAGS_TCP_UDP_CKSUM (1<<1)
#define TX_BD_FLAGS_IP_CKSUM (1<<2)
@@ -4588,7 +4593,6 @@ struct l2_fhdr {
#define DMA_WRITE_CHANS 3
/* Use the natural page size of the host CPU. */
-/* XXX: This has only been tested on amd64/i386 systems using 4KB pages. */
#define BCM_PAGE_BITS PAGE_SHIFT
#define BCM_PAGE_SIZE PAGE_SIZE
@@ -4612,7 +4616,7 @@ struct l2_fhdr {
#define TX_CHAIN_IDX(x) ((x) & MAX_TX_BD)
-#define TX_PAGE(x) (((x) & ~USABLE_TX_BD_PER_PAGE) >> 8)
+#define TX_PAGE(x) (((x) & ~USABLE_TX_BD_PER_PAGE) >> (BCM_PAGE_BITS - 4))
#define TX_IDX(x) ((x) & USABLE_TX_BD_PER_PAGE)
#define NEXT_RX_BD(x) (((x) & USABLE_RX_BD_PER_PAGE) == \
@@ -4621,7 +4625,7 @@ struct l2_fhdr {
#define RX_CHAIN_IDX(x) ((x) & MAX_RX_BD)
-#define RX_PAGE(x) (((x) & ~USABLE_RX_BD_PER_PAGE) >> 8)
+#define RX_PAGE(x) (((x) & ~USABLE_RX_BD_PER_PAGE) >> (BCM_PAGE_BITS - 4))
#define RX_IDX(x) ((x) & USABLE_RX_BD_PER_PAGE)
/* Context size. */
@@ -4800,6 +4804,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;
Home |
Main Index |
Thread Index |
Old Index