tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
BCM5809S support in bnx(4) and brgphy(4)
Dear lists,
I have ported various modifications from OpenBSD and FreeBSD to bnx(4)
and brgphy(4) (see attach).
The modifications in question add BCM5709S support (SerDes 1000baseSX
FDX), and endianness hardware management (avoid using htole32()).
I thank anyone in advance that could have access to a bnx(4) supported
NIC (Broadcom 5400 and 5700 families) and that could test this patch,
especially on big endian system (sparc64).
There are two points I am not sure of:
- 1 -
The BCM5709S has its own custom registers for MII capabilities. This
means that I cannot use mii_phy_add_media() to attach brpghy MII
directly, and had to implement the logic directly into brgphyattach.
I can modify the bits in mii_capabilities to match what
mii_phy_add_media() does, or leave the logic inside brgphyattach().
Dunno what's the best.
- 2 -
Regarding autonegotiation, BCM5709S seems to have its own ANAR bits too:
/* Copper */
#define ANAR_X_PAUSE_NONE (0 << 10)
#define ANAR_X_PAUSE_SYM (1 << 10)
#define ANAR_X_PAUSE_ASYM (2 << 10)
#define ANAR_X_PAUSE_TOWARDS (3 << 10)
vs
/* SerDes autoneg is different from copper */
#define BRGPHY_SERDES_ANAR_NO_PAUSE (0x0 << 7)
#define BRGPHY_SERDES_ANAR_SYM_PAUSE (0x1 << 7)
#define BRGPHY_SERDES_ANAR_ASYM_PAUSE (0x2 << 7)
#define BRGPHY_SERDES_ANAR_BOTH_PAUSE (0x3 << 7)
As I don't have access to 802.3 (especially clause 37), I don't know if
its Broadcom's specific or standardized values for 1000baseSX.
Advices, and tests, are gratefully welcomed.
Many thanks to Uwe Toenjes <6bone%6bone.informatik.uni-leipzig.de@localhost> ,
who
kindly granted me access to a Dell M710 with BCM5709S NICs so I could
test my patch.
--
Jean-Yves Migeon
jeanyves.migeon%free.fr@localhost
Index: share/man/man4/bnx.4
===================================================================
RCS file: /cvsroot/src/share/man/man4/bnx.4,v
retrieving revision 1.2
diff -u -p -u -p -r1.2 bnx.4
--- share/man/man4/bnx.4 17 Dec 2006 23:53:28 -0000 1.2
+++ share/man/man4/bnx.4 30 Nov 2010 23:58:42 -0000
@@ -29,7 +29,7 @@
.\"
.\" $FreeBSD: /repoman/r/ncvs/src/share/man/man4/bce.4,v 1.2 2006/04/10
20:12:17 brueffer Exp $
.\"
-.Dd December 17, 2006
+.Dd December 1, 2010
.Dt BNX 4
.Os
.Sh NAME
@@ -42,7 +42,7 @@
The
.Nm
driver supports Broadcom's NetXtreme II product family, such as the
-BCM5706 PCI-X and BCM5708 PCI Express Ethernet controllers, which
+BCM5706 PCI-X and BCM5708-BCM5709 PCI Express Ethernet controllers, which
includes the following:
.Pp
.Bl -bullet -compact
@@ -51,6 +51,8 @@ Dell PowerEdge 1950 integrated BCM5708 N
.It
Dell PowerEdge 2950 integrated BCM5708 NIC (10/100/1000baseT)
.It
+Dell PowerEdge M710 integrated BCM5709S NIC (1000baseSX)
+.It
HP NC370F PCI-X Multifunction Gigabit server adapter (1000baseSX)
.It
HP NC370T PCI-X Multifunction Gigabit server adapter (10/100/1000baseT)
@@ -118,6 +120,18 @@ Set 1000baseTX operation over twisted pa
Only
.Cm full-duplex
mode is supported.
+.It Cm 1000baseSX
+Set 1000Mbps (Gigabit Ethernet) operation.
+Both
+.Cm full-duplex
+and
+.Cm half-duplex
+modes are supported.
+.It Cm 2500baseSX
+Set 2500Mbps operation.
+Only
+.Cm full-duplex
+mode is supported.
.El
.Pp
The
Index: share/man/man4/brgphy.4
===================================================================
RCS file: /cvsroot/src/share/man/man4/brgphy.4,v
retrieving revision 1.2
diff -u -p -u -p -r1.2 brgphy.4
--- share/man/man4/brgphy.4 30 Apr 2008 13:10:53 -0000 1.2
+++ share/man/man4/brgphy.4 30 Nov 2010 23:58:42 -0000
@@ -28,7 +28,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd June 1, 2001
+.Dd December 1, 2010
.Dt BRGPHY 4
.Os
.Sh NAME
@@ -39,7 +39,8 @@
.Sh DESCRIPTION
The
.Nm
-driver supports the Broadcom BCM5400-family Gigabit Ethernet PHYs.
+driver supports the Broadcom BCM5400-family and BCM5700-family
+Gigabit Ethernet PHYs.
These PHYs are found on a variety of Gigabit Ethernet interfaces.
.Sh SEE ALSO
.Xr ifmedia 4 ,
Index: sys/dev/mii/brgphy.c
===================================================================
RCS file: /cvsroot/src/sys/dev/mii/brgphy.c,v
retrieving revision 1.56
diff -u -p -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 30 Nov 2010 23:58:49 -0000
@@ -55,7 +55,7 @@
*/
/*
- * driver for the Broadcom BCM5400 Gig-E PHY.
+ * driver for the Broadcom BCM5400 and BCM5700 Gig-E PHYs.
*
* Programming information for this PHY was gleaned from FreeBSD
* (they were apparently able to get a datasheet from Broadcom).
@@ -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,41 @@ 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;
+ sc->mii_flags |= MIIF_IS_1000X;
+ sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
+
+#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
+#define PRINT(str) aprint_normal("%s%s", sep, str); sep = ", "
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX,
+ sc->mii_inst), BMCR_S1000 | BMCR_FDX);
+ PRINT("1000baseSX-FDX");
+
+ 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-FDX");
+ }
+ }
+
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
+ PRINT("auto");
+
+ if (!pmf_device_register(self, NULL, mii_phy_resume)) {
+ aprint_normal("\n");
+ aprint_error_dev(self,
+ "couldn't establish power handler");
+ }
+#undef ADD
+#undef PRINT
+ } else
mii_phy_add_media(sc);
aprint_normal("\n");
@@ -399,14 +435,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 +459,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;
}
@@ -482,18 +559,27 @@ brgphy_mii_phy_auto(struct mii_softc *sc
brgphy_loop(sc);
PHY_RESET(sc);
+
ktcr = GTCR_ADV_1000TFDX|GTCR_ADV_1000THDX;
if (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5701)
ktcr |= GTCR_MAN_MS|GTCR_ADV_MS;
PHY_WRITE(sc, MII_100T2CR, ktcr);
ktcr = PHY_READ(sc, MII_100T2CR);
DELAY(1000);
- anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
- if (sc->mii_flags & MIIF_DOPAUSE)
- anar |= ANAR_FC| ANAR_X_PAUSE_ASYM;
+ if (sc->mii_flags & MIIF_HAVEFIBER) {
+ anar = ANAR_X_FD | ANAR_X_HD;
+ if (sc->mii_flags & MIIF_DOPAUSE)
+ anar |= BRGPHY_SERDES_ANAR_BOTH_PAUSE;
+ } else {
+ anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
+ if (sc->mii_flags & MIIF_DOPAUSE)
+ anar |= ANAR_FC | ANAR_X_PAUSE_ASYM;
+ }
PHY_WRITE(sc, MII_ANAR, anar);
DELAY(1000);
+
+ /* Start autonegotiation */
PHY_WRITE(sc, MII_BMCR,
BMCR_AUTOEN | BMCR_STARTNEG);
PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00);
@@ -519,6 +605,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 +680,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 +733,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 +796,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 -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 30 Nov 2010 23:58:50 -0000
@@ -197,6 +197,25 @@
#define BRGPHY_IMR_CRCERR 0x0001 /* CEC error */
/*******************************************************/
+/* Begin: Shared SerDes PHY register definitions */
+/*******************************************************/
+
+/* SerDes autoneg is different from copper */
+#define BRGPHY_SERDES_ANAR_NO_PAUSE (0x0 << 7)
+#define BRGPHY_SERDES_ANAR_SYM_PAUSE (0x1 << 7)
+#define BRGPHY_SERDES_ANAR_ASYM_PAUSE (0x2 << 7)
+#define BRGPHY_SERDES_ANAR_BOTH_PAUSE (0x3 << 7)
+
+#define BRGPHY_SERDES_ANLPAR_NO_PAUSE (0x0 << 7)
+#define BRGPHY_SERDES_ANLPAR_SYM_PAUSE (0x1 << 7)
+#define BRGPHY_SERDES_ANLPAR_ASYM_PAUSE (0x2 << 7)
+#define BRGPHY_SERDES_ANLPAR_BOTH_PAUSE (0x3 << 7)
+
+/*******************************************************/
+/* End: Shared SerDes PHY register definitions */
+/*******************************************************/
+
+/*******************************************************/
/* Begin: PHY register values for the 5706 PHY */
/*******************************************************/
@@ -223,6 +242,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 -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 30 Nov 2010 23:58:52 -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 -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 30 Nov 2010 23:58:54 -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