[Midnightbsd-cvs] src: dev/mii: merge changes
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Tue Nov 25 12:04:42 EST 2008
Log Message:
-----------
merge changes
Modified Files:
--------------
src/sys/dev/mii:
brgphy.c (r1.2 -> r1.3)
mii.c (r1.2 -> r1.3)
miidevs (r1.2 -> r1.3)
-------------- next part --------------
Index: mii.c
===================================================================
RCS file: /home/cvs/src/sys/dev/mii/mii.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/mii/mii.c -L sys/dev/mii/mii.c -u -r1.2 -r1.3
--- sys/dev/mii/mii.c
+++ sys/dev/mii/mii.c
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/dev/mii/mii.c,v 1.26.2.1 2006/03/17 20:17:43 glebius Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/mii/mii.c,v 1.29 2007/05/01 18:21:24 marcel Exp $");
/*
* MII bus layer, glues MII-capable network interface drivers to sharable
@@ -64,6 +64,7 @@
#include "miibus_if.h"
+static int miibus_print_child(device_t dev, device_t child);
static int miibus_child_location_str(device_t bus, device_t child, char *buf,
size_t buflen);
static int miibus_child_pnpinfo_str(device_t bus, device_t child, char *buf,
@@ -82,7 +83,7 @@
DEVMETHOD(device_shutdown, bus_generic_shutdown),
/* bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_print_child, miibus_print_child),
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_child_pnpinfo_str, miibus_child_pnpinfo_str),
DEVMETHOD(bus_child_location_str, miibus_child_location_str),
@@ -105,6 +106,11 @@
sizeof(struct mii_data)
};
+struct miibus_ivars {
+ ifm_change_cb_t ifmedia_upd;
+ ifm_stat_cb_t ifmedia_sts;
+};
+
/*
* Helper function used by network interface drivers, attaches PHYs
* to the network interface driver parent.
@@ -165,9 +171,7 @@
int
miibus_attach(device_t dev)
{
- void **v;
- ifm_change_cb_t ifmedia_upd;
- ifm_stat_cb_t ifmedia_sts;
+ struct miibus_ivars *ivars;
struct mii_data *mii;
mii = device_get_softc(dev);
@@ -176,10 +180,9 @@
* XXX: EVIL HACK!
*/
mii->mii_ifp = *(struct ifnet**)device_get_softc(device_get_parent(dev));
- v = device_get_ivars(dev);
- ifmedia_upd = v[0];
- ifmedia_sts = v[1];
- ifmedia_init(&mii->mii_media, IFM_IMASK, ifmedia_upd, ifmedia_sts);
+ ivars = device_get_ivars(dev);
+ ifmedia_init(&mii->mii_media, IFM_IMASK, ivars->ifmedia_upd,
+ ivars->ifmedia_sts);
bus_generic_attach(dev);
return(0);
@@ -199,6 +202,20 @@
}
static int
+miibus_print_child(device_t dev, device_t child)
+{
+ struct mii_attach_args *ma;
+ int retval;
+
+ ma = device_get_ivars(child);
+ retval = bus_print_child_header(dev, child);
+ retval += printf(" PHY %d", ma->mii_phyno);
+ retval += bus_print_child_footer(dev, child);
+
+ return (retval);
+}
+
+static int
miibus_child_pnpinfo_str(device_t bus, device_t child, char *buf,
size_t buflen)
{
@@ -309,17 +326,16 @@
mii_phy_probe(device_t dev, device_t *child, ifm_change_cb_t ifmedia_upd,
ifm_stat_cb_t ifmedia_sts)
{
- void **v;
+ struct miibus_ivars *ivars;
int bmsr, i;
- v = malloc(sizeof(vm_offset_t) * 2, M_DEVBUF, M_NOWAIT);
- if (v == 0) {
+ ivars = malloc(sizeof(*ivars), M_DEVBUF, M_NOWAIT);
+ if (ivars == NULL)
return (ENOMEM);
- }
- v[0] = ifmedia_upd;
- v[1] = ifmedia_sts;
+ ivars->ifmedia_upd = ifmedia_upd;
+ ivars->ifmedia_sts = ifmedia_sts;
*child = device_add_child(dev, "miibus", -1);
- device_set_ivars(*child, v);
+ device_set_ivars(*child, ivars);
for (i = 0; i < MII_NPHY; i++) {
bmsr = MIIBUS_READREG(dev, i, MII_BMSR);
Index: miidevs
===================================================================
RCS file: /home/cvs/src/sys/dev/mii/miidevs,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/mii/miidevs -L sys/dev/mii/miidevs -u -r1.2 -r1.3
--- sys/dev/mii/miidevs
+++ sys/dev/mii/miidevs
@@ -1,4 +1,4 @@
-$FreeBSD: /repoman/r/ncvs/src/sys/dev/mii/miidevs,v 1.30.2.1.2.1 2006/04/12 18:09:28 ps Exp $
+$FreeBSD: src/sys/dev/mii/miidevs,v 1.46.2.1 2007/11/05 01:42:02 yongari Exp $
/*$NetBSD: miidevs,v 1.6 1999/05/14 11:37:30 drochner Exp $*/
/*-
@@ -54,6 +54,7 @@
oui BROADCOM 0x001018 Broadcom Corporation
oui CICADA 0x0003F1 Cicada Semiconductor
oui DAVICOM 0x00606e Davicom Semiconductor
+oui ICPLUS 0x0090c3 IC Plus Corp.
oui ICS 0x00a0be Integrated Circuit Systems
oui INTEL 0x00aa00 Intel
oui JATO 0x00e083 Jato Technologies
@@ -65,6 +66,7 @@
oui SIS 0x00e006 Silicon Integrated Systems
oui TDK 0x00c039 TDK
oui TI 0x080028 Texas Instruments
+oui VITESSE 0x0001c1 Vitesse Semiconductor
oui XAQTI 0x00e0ae XaQti Corp.
oui MARVELL 0x005043 Marvell Semiconductor
oui xxMARVELL 0x000ac2 Marvell Semiconductor
@@ -79,6 +81,7 @@
(ie, ordered as on the wire) */
oui xxALTIMA 0x000895 Altima Communications
oui xxBROADCOM 0x000818 Broadcom Corporation
+oui xxBROADCOM_ALT1 0x0050ef Broadcom Corporation
oui xxICS 0x00057d Integrated Circuit Systems
oui xxSEEQ 0x0005be Seeq
oui xxSIS 0x000760 Silicon Integrated Systems
@@ -92,7 +95,7 @@
/* Don't know what's going on here. */
oui xxDAVICOM 0x006040 Davicom Semiconductor
-/* This is the OUI of the gigE PHY in the RealTek 8169S/8110S chips */
+/* This is the OUI of the gigE PHY in the RealTek 8169S/8110S/8211B chips */
oui xxREALTEK 0x000732
/*
@@ -102,11 +105,12 @@
/* Altima Communications PHYs */
model xxALTIMA AC101 0x0021 AC101 10/100 media interface
model xxALTIMA AC101L 0x0012 AC101L 10/100 media interface
+model xxALTIMA ACXXX 0x0001 ACXXX 10/100 media interface
/* Advanced Micro Devices PHYs */
-model xxAMD 79C873 0x0000 Am79C873 10/100 media interface
model AMD 79c973phy 0x0036 Am79c973 internal PHY
model AMD 79c978 0x0039 Am79c978 HomePNA PHY
+model xxAMD 79C873 0x0000 Am79C873/DM9101 10/100 media interface
/* Broadcom Corp. PHYs. */
model BROADCOM 3C905B 0x0012 3c905B 10/100 internal PHY
@@ -117,26 +121,40 @@
model xxBROADCOM BCM5400 0x0004 Broadcom 1000baseTX PHY
model xxBROADCOM BCM5401 0x0005 BCM5401 10/100/1000baseTX PHY
model xxBROADCOM BCM5411 0x0007 BCM5411 10/100/1000baseTX PHY
+model xxBROADCOM BCM5754 0x000e BCM5754 10/100/1000baseTX PHY
+model xxBROADCOM BCM5752 0x0010 BCM5752 10/100/1000baseTX PHY
model xxBROADCOM BCM5701 0x0011 BCM5701 10/100/1000baseTX PHY
+model xxBROADCOM BCM5706 0x0015 BCM5706 10/100/1000baseTX/SX PHY
model xxBROADCOM BCM5703 0x0016 BCM5703 10/100/1000baseTX PHY
model xxBROADCOM BCM5704 0x0019 BCM5704 10/100/1000baseTX PHY
model xxBROADCOM BCM5705 0x001a BCM5705 10/100/1000baseTX PHY
model xxBROADCOM BCM5750 0x0018 BCM5750 10/100/1000baseTX PHY
model xxBROADCOM BCM5714 0x0034 BCM5714 10/100/1000baseTX PHY
model xxBROADCOM BCM5780 0x0035 BCM5780 10/100/1000baseTX PHY
-model xxBROADCOM BCM5706C 0x0015 BCM5706C 10/100/1000baseTX PHY
model xxBROADCOM BCM5708C 0x0036 BCM5708C 10/100/1000baseTX PHY
+model xxBROADCOM_ALT1 BCM5755 0x000c BCM5755 10/100/1000baseTX PHY
+model xxBROADCOM_ALT1 BCM5787 0x000e BCM5787 10/100/1000baseTX PHY
+model xxBROADCOM_ALT1 BCM5708S 0x0015 BCM5708S 1000/2500BaseSX PHY
/* Cicada Semiconductor PHYs (now owned by Vitesse?) */
model CICADA CS8201 0x0001 Cicada CS8201 10/100/1000TX PHY
model CICADA CS8201A 0x0020 Cicada CS8201 10/100/1000TX PHY
model CICADA CS8201B 0x0021 Cicada CS8201 10/100/1000TX PHY
+model VITESSE VSC8601 0x0002 Vitesse VSC8601 10/100/1000TX PHY
/* Davicom Semiconductor PHYs */
+model DAVICOM DM9102 0x0004 DM9102 10/100 media interface
model xxDAVICOM DM9101 0x0000 DM9101 10/100 media interface
/* Integrated Circuit Systems PHYs */
+model xxICS 1889 0x0001 ICS1889 10/100 media interface
model xxICS 1890 0x0002 ICS1890 10/100 media interface
+model xxICS 1892 0x0003 ICS1892 10/100 media interface
+model xxICS 1893 0x0004 ICS1893 10/100 media interface
+
+/* IC Plus Corp. PHYs */
+model ICPLUS IP101 0x0005 IC Plus 10/100 PHY
+model ICPLUS IP1000A 0x0008 IC Plus 10/100/1000 media interface
/* Intel PHYs */
model xxINTEL I82553AB 0x0000 i83553 10/100 media interface
@@ -162,7 +180,8 @@
/* RealTek Semiconductor PHYs */
model REALTEK RTL8201L 0x0020 RTL8201L 10/100 media interface
-model xxREALTEK RTL8169S 0x0011 RTL8169S/8110S media interface
+model xxREALTEK RTL8305SC 0x0005 RTL8305SC 10/100 802.1q switch
+model xxREALTEK RTL8169S 0x0011 RTL8169S/8110S/8211B media interface
/* Seeq PHYs */
model xxSEEQ 80220 0x0003 Seeq 80220 10/100 media interface
@@ -184,4 +203,18 @@
/* Marvell Semiconductor PHYs */
model MARVELL E1000 0x0000 Marvell 88E1000 Gigabit PHY
model MARVELL E1011 0x0002 Marvell 88E1011 Gigabit PHY
+model MARVELL E1000_3 0x0003 Marvell 88E1000 Gigabit PHY
+model MARVELL E1000S 0x0004 Marvell 88E1000S Gigabit PHY
+model MARVELL E1000_5 0x0005 Marvell 88E1000 Gigabit PHY
+model MARVELL E1000_6 0x0006 Marvell 88E1000 Gigabit PHY
+model MARVELL E3082 0x0008 Marvell 88E3082 10/100 Fast Ethernet PHY
+model MARVELL E1112 0x0009 Marvell 88E1112 Gigabit PHY
+model MARVELL E1149 0x000b Marvell 88E1149 Gigabit PHY
+model MARVELL E1111 0x000c Marvell 88E1111 Gigabit PHY
+model MARVELL E1116 0x0021 Marvell 88E1116 Gigabit PHY
+model MARVELL E1118 0x0022 Marvell 88E1118 Gigabit PHY
model xxMARVELL E1000 0x0005 Marvell 88E1000 Gigabit PHY
+model xxMARVELL E1011 0x0002 Marvell 88E1011 Gigabit PHY
+model xxMARVELL E1000_3 0x0003 Marvell 88E1000 Gigabit PHY
+model xxMARVELL E1000_5 0x0005 Marvell 88E1000 Gigabit PHY
+model xxMARVELL E1111 0x000c Marvell 88E1111 Gigabit PHY
Index: brgphy.c
===================================================================
RCS file: /home/cvs/src/sys/dev/mii/brgphy.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/mii/brgphy.c -L sys/dev/mii/brgphy.c -u -r1.2 -r1.3
--- sys/dev/mii/brgphy.c
+++ sys/dev/mii/brgphy.c
@@ -31,11 +31,10 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/dev/mii/brgphy.c,v 1.34.2.3.2.2 2006/04/12 18:38:59 ps Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/mii/brgphy.c,v 1.70 2007/06/08 02:34:44 davidch Exp $");
/*
- * Driver for the Broadcom BCR5400 1000baseTX PHY. Speed is always
- * 1000mbps; all we need to negotiate here is full or half duplex.
+ * Driver for the Broadcom BCM54xx/57xx 1000baseTX PHY.
*/
#include <sys/param.h>
@@ -45,8 +44,6 @@
#include <sys/socket.h>
#include <sys/bus.h>
-#include <machine/clock.h>
-
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_media.h>
@@ -69,6 +66,17 @@
static int brgphy_probe(device_t);
static int brgphy_attach(device_t);
+struct brgphy_softc {
+ struct mii_softc mii_sc;
+ int mii_oui;
+ int mii_model;
+ int mii_rev;
+ int serdes_flags; /* Keeps track of the serdes type used */
+#define BRGPHY_5706S 0x0001
+#define BRGPHY_5708S 0x0002
+ int bce_phy_flags; /* PHY flags transferred from the MAC driver */
+};
+
static device_method_t brgphy_methods[] = {
/* device interface */
DEVMETHOD(device_probe, brgphy_probe),
@@ -83,324 +91,292 @@
static driver_t brgphy_driver = {
"brgphy",
brgphy_methods,
- sizeof(struct mii_softc)
+ sizeof(struct brgphy_softc)
};
DRIVER_MODULE(brgphy, miibus, brgphy_driver, brgphy_devclass, 0, 0);
static int brgphy_service(struct mii_softc *, struct mii_data *, int);
+static void brgphy_setmedia(struct mii_softc *, int, int);
static void brgphy_status(struct mii_softc *);
-static int brgphy_mii_phy_auto(struct mii_softc *);
+static void brgphy_mii_phy_auto(struct mii_softc *);
static void brgphy_reset(struct mii_softc *);
-static void brgphy_loop(struct mii_softc *);
+static void brgphy_enable_loopback(struct mii_softc *);
static void bcm5401_load_dspcode(struct mii_softc *);
static void bcm5411_load_dspcode(struct mii_softc *);
-static void bcm5703_load_dspcode(struct mii_softc *);
-static void bcm5750_load_dspcode(struct mii_softc *);
-static int brgphy_mii_model;
+static void brgphy_fixup_5704_a0_bug(struct mii_softc *);
+static void brgphy_fixup_adc_bug(struct mii_softc *);
+static void brgphy_fixup_adjust_trim(struct mii_softc *);
+static void brgphy_fixup_ber_bug(struct mii_softc *);
+static void brgphy_fixup_crc_bug(struct mii_softc *);
+static void brgphy_fixup_jitter_bug(struct mii_softc *);
+static void brgphy_ethernet_wirespeed(struct mii_softc *);
+static void brgphy_jumbo_settings(struct mii_softc *, u_long);
+
+static const struct mii_phydesc brgphys[] = {
+ MII_PHY_DESC(xxBROADCOM, BCM5400),
+ MII_PHY_DESC(xxBROADCOM, BCM5401),
+ MII_PHY_DESC(xxBROADCOM, BCM5411),
+ MII_PHY_DESC(xxBROADCOM, BCM5701),
+ MII_PHY_DESC(xxBROADCOM, BCM5703),
+ MII_PHY_DESC(xxBROADCOM, BCM5704),
+ MII_PHY_DESC(xxBROADCOM, BCM5705),
+ MII_PHY_DESC(xxBROADCOM, BCM5706),
+ MII_PHY_DESC(xxBROADCOM, BCM5714),
+ MII_PHY_DESC(xxBROADCOM, BCM5750),
+ MII_PHY_DESC(xxBROADCOM, BCM5752),
+ MII_PHY_DESC(xxBROADCOM, BCM5754),
+ MII_PHY_DESC(xxBROADCOM, BCM5780),
+ MII_PHY_DESC(xxBROADCOM, BCM5708C),
+ MII_PHY_DESC(xxBROADCOM_ALT1, BCM5755),
+ MII_PHY_DESC(xxBROADCOM_ALT1, BCM5787),
+ MII_PHY_DESC(xxBROADCOM_ALT1, BCM5708S),
+ MII_PHY_END
+};
+
+/* Search for our PHY in the list of known PHYs */
static int
-brgphy_probe(dev)
- device_t dev;
+brgphy_probe(device_t dev)
{
- struct mii_attach_args *ma;
-
- ma = device_get_ivars(dev);
-
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
- MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5400) {
- device_set_desc(dev, MII_STR_xxBROADCOM_BCM5400);
- return(0);
- }
-
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
- MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5401) {
- device_set_desc(dev, MII_STR_xxBROADCOM_BCM5401);
- return(0);
- }
-
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
- MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5411) {
- device_set_desc(dev, MII_STR_xxBROADCOM_BCM5411);
- return(0);
- }
-
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
- MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5701) {
- device_set_desc(dev, MII_STR_xxBROADCOM_BCM5701);
- return(0);
- }
-
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
- MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5703) {
- device_set_desc(dev, MII_STR_xxBROADCOM_BCM5703);
- return(0);
- }
-
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
- MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5704) {
- device_set_desc(dev, MII_STR_xxBROADCOM_BCM5704);
- return(0);
- }
-
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
- MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5705) {
- device_set_desc(dev, MII_STR_xxBROADCOM_BCM5705);
- return(0);
- }
-
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
- MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5750) {
- device_set_desc(dev, MII_STR_xxBROADCOM_BCM5750);
- return(0);
- }
-
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
- MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5714) {
- device_set_desc(dev, MII_STR_xxBROADCOM_BCM5714);
- return(0);
- }
-
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
- MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5780) {
- device_set_desc(dev, MII_STR_xxBROADCOM_BCM5780);
- return (0);
- }
-
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
- MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5706C) {
- device_set_desc(dev, MII_STR_xxBROADCOM_BCM5706C);
- return(0);
- }
-
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
- MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5708C) {
- device_set_desc(dev, MII_STR_xxBROADCOM_BCM5708C);
- return(0);
- }
-
- return(ENXIO);
+ return (mii_phy_dev_probe(dev, brgphys, BUS_PROBE_DEFAULT));
}
+/* Attach the PHY to the MII bus */
static int
-brgphy_attach(dev)
- device_t dev;
+brgphy_attach(device_t dev)
{
+ struct brgphy_softc *bsc;
+ struct bge_softc *bge_sc = NULL;
+ struct bce_softc *bce_sc = NULL;
struct mii_softc *sc;
struct mii_attach_args *ma;
struct mii_data *mii;
- const char *sep = "";
- struct bge_softc *bge_sc = NULL;
- struct bce_softc *bce_sc = NULL;
- int fast_ether_only = FALSE;
+ struct ifnet *ifp;
+ int fast_ether;
- sc = device_get_softc(dev);
+ bsc = device_get_softc(dev);
+ sc = &bsc->mii_sc;
ma = device_get_ivars(dev);
sc->mii_dev = device_get_parent(dev);
mii = device_get_softc(sc->mii_dev);
LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
+ /* Initialize mii_softc structure */
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = brgphy_service;
sc->mii_pdata = mii;
-
- sc->mii_flags |= MIIF_NOISOLATE;
+ sc->mii_anegticks = MII_ANEGTICKS_GIGE;
+ sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
mii->mii_instance++;
-#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
-#define PRINT(s) printf("%s%s", sep, s); sep = ", "
+ /* Initialize brgphy_softc structure */
+ bsc->mii_oui = MII_OUI(ma->mii_id1, ma->mii_id2);
+ bsc->mii_model = MII_MODEL(ma->mii_id2);
+ bsc->mii_rev = MII_REV(ma->mii_id2);
+ bsc->serdes_flags = 0;
+
+ fast_ether = 0;
+
+ if (bootverbose)
+ device_printf(dev, "OUI 0x%06x, model 0x%04x, rev. %d\n",
+ bsc->mii_oui, bsc->mii_model, bsc->mii_rev);
+
+ /* Handle any special cases based on the PHY ID */
+ switch (bsc->mii_oui) {
+ case MII_OUI_BROADCOM:
+ break;
+ case MII_OUI_xxBROADCOM:
+ switch (bsc->mii_model) {
+ case MII_MODEL_xxBROADCOM_BCM5706:
+ /*
+ * The 5464 PHY used in the 5706 supports both copper
+ * and fiber interfaces over GMII. Need to check the
+ * shadow registers to see which mode is actually
+ * in effect, and therefore whether we have 5706C or
+ * 5706S.
+ */
+ PHY_WRITE(sc, BRGPHY_MII_SHADOW_1C,
+ BRGPHY_SHADOW_1C_MODE_CTRL);
+ if (PHY_READ(sc, BRGPHY_MII_SHADOW_1C) &
+ BRGPHY_SHADOW_1C_ENA_1000X) {
+ bsc->serdes_flags |= BRGPHY_5706S;
+ sc->mii_flags |= MIIF_HAVEFIBER;
+ }
+ break;
+ } break;
+ case MII_OUI_xxBROADCOM_ALT1:
+ switch (bsc->mii_model) {
+ case MII_MODEL_xxBROADCOM_ALT1_BCM5708S:
+ bsc->serdes_flags |= BRGPHY_5708S;
+ sc->mii_flags |= MIIF_HAVEFIBER;
+ break;
+ } break;
+ default:
+ device_printf(dev, "Unrecognized OUI for PHY!\n");
+ }
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
- BMCR_ISO);
-#if 0
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
- BMCR_LOOP|BMCR_S100);
-#endif
+ ifp = sc->mii_pdata->mii_ifp;
- brgphy_mii_model = MII_MODEL(ma->mii_id2);
- brgphy_reset(sc);
+ /* Find the MAC driver associated with this PHY. */
+ if (strcmp(ifp->if_dname, "bge") == 0) {
+ bge_sc = ifp->if_softc;
+ } else if (strcmp(ifp->if_dname, "bce") == 0) {
+ bce_sc = ifp->if_softc;
+ }
+
+ /* Todo: Need to add additional controllers such as 5906 & 5787F */
+ /* The 590x chips are 10/100 only. */
+ if (bge_sc &&
+ pci_get_vendor(bge_sc->bge_dev) == BCOM_VENDORID &&
+ (pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901 ||
+ pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901A2)) {
+ fast_ether = 1;
+ sc->mii_anegticks = MII_ANEGTICKS;
+ }
+ brgphy_reset(sc);
sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
- sc->mii_capabilities &= ~BMSR_ANEG;
+ if (sc->mii_capabilities & BMSR_EXTSTAT)
+ sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
device_printf(dev, " ");
- mii_add_media(sc);
- /* Find the driver associated with this PHY. */
- if (strcmp(mii->mii_ifp->if_dname, "bge") == 0) {
- bge_sc = mii->mii_ifp->if_softc;
- } else if (strcmp(mii->mii_ifp->if_dname, "bce") == 0) {
- bce_sc = mii->mii_ifp->if_softc;
- }
+#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
- /* The 590x chips are 10/100 only. */
- if (strcmp(mii->mii_ifp->if_dname, "bge") == 0 &&
- pci_get_vendor(bge_sc->bge_dev) == BCOM_VENDORID &&
- (pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901 ||
- pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901A2))
- fast_ether_only = TRUE;
+ /* Create an instance of Ethernet media. */
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), BMCR_ISO);
- if (fast_ether_only == FALSE) {
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0,
- sc->mii_inst), BRGPHY_BMCR_FDX);
- PRINT(", 1000baseTX");
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T,
- IFM_FDX, sc->mii_inst), 0);
- PRINT("1000baseTX-FDX");
+ /* Add the supported media types */
+ if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
+ BRGPHY_S10);
+ printf("10baseT, ");
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
+ BRGPHY_S10 | BRGPHY_BMCR_FDX);
+ printf("10baseT-FDX, ");
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
+ BRGPHY_S100);
+ printf("100baseTX, ");
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
+ BRGPHY_S100 | BRGPHY_BMCR_FDX);
+ printf("100baseTX-FDX, ");
+ if (fast_ether == 0) {
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst),
+ BRGPHY_S1000);
+ printf("1000baseT, ");
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst),
+ BRGPHY_S1000 | BRGPHY_BMCR_FDX);
+ printf("1000baseT-FDX, ");
+ }
+ } else {
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst),
+ BRGPHY_S1000 | BRGPHY_BMCR_FDX);
+ printf("1000baseSX-FDX, ");
+ /* 2.5G support is a software enabled feature on the 5708S */
+ if (bce_sc && (bce_sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)) {
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_2500_SX, IFM_FDX, sc->mii_inst), 0);
+ printf("2500baseSX-FDX, ");
+ }
}
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
- PRINT("auto");
+ printf("auto\n");
- printf("\n");
#undef ADD
-#undef PRINT
-
MIIBUS_MEDIAINIT(sc->mii_dev);
- return(0);
+ return (0);
}
static int
-brgphy_service(sc, mii, cmd)
- struct mii_softc *sc;
- struct mii_data *mii;
- int cmd;
+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 reg, speed, gig;
+ int error = 0;
+ int val;
switch (cmd) {
case MII_POLLSTAT:
- /*
- * If we're not polling our PHY instance, just return.
- */
+ /* If we're not polling our PHY instance, just return. */
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
- return (0);
+ 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) {
- reg = PHY_READ(sc, MII_BMCR);
- PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
- return (0);
+ 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 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:
-#ifdef foo
- /*
- * If we're already in auto mode, just return.
- */
- if (PHY_READ(sc, BRGPHY_MII_BMCR) & BRGPHY_BMCR_AUTOEN)
- return (0);
-#endif
- (void) brgphy_mii_phy_auto(sc);
+ brgphy_mii_phy_auto(sc);
break;
+ case IFM_2500_SX:
+ case IFM_1000_SX:
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_BMCR, speed);
- PHY_WRITE(sc, BRGPHY_MII_ANAR, BRGPHY_SEL_TYPE);
-
- 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 (brgphy_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);
+ brgphy_setmedia(sc, ife->ifm_media,
+ mii->mii_ifp->if_flags & IFF_LINK0);
break;
-#endif
- case IFM_100_T4:
default:
- return (EINVAL);
+ error = EINVAL;
+ goto brgphy_service_exit;
}
break;
-
case MII_TICK:
- /*
- * If we're not currently selected, just return.
- */
+ /* Bail if we're not currently selected. */
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
- return (0);
+ goto brgphy_service_exit;
- /*
- * Is the interface even up?
- */
+ /* Bail if the interface isn't up. */
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
- return (0);
+ goto brgphy_service_exit;
- /*
- * Only used for autonegotiation.
- */
- if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+
+ /* 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. Read
- * the BMSR twice in case it's latched.
+ * need to restart the autonegotiation process.
*/
- reg = PHY_READ(sc, BRGPHY_MII_AUXSTS);
- if (reg & BRGPHY_AUXSTS_LINK)
+ val = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
+ if (val & BMSR_LINK) {
+ sc->mii_ticks = 0; /* Reset autoneg timer. */
break;
+ }
- /*
- * Only retry autonegotiation every 5 seconds.
- */
- if (++sc->mii_ticks <= 5)
+#if 0
+ /* Todo: Is this correct? */
+ /* Announce link loss right after it happens. */
+ if (sc->mii_ticks++ == 0)
break;
-
+#endif
+
+ /* Only retry autonegotiation every mii_anegticks seconds. */
+ if (sc->mii_ticks <= sc->mii_anegticks)
+ goto brgphy_service_exit;
+
+
+ /* Retry autonegotiation */
sc->mii_ticks = 0;
brgphy_mii_phy_auto(sc);
break;
@@ -412,126 +388,264 @@
/*
* 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 ||
+ if (sc->mii_media_active != mii->mii_media_active ||
sc->mii_media_status != mii->mii_media_status ||
cmd == MII_MEDIACHG) {
- switch (brgphy_mii_model) {
- case MII_MODEL_xxBROADCOM_BCM5400:
- case MII_MODEL_xxBROADCOM_BCM5401:
- bcm5401_load_dspcode(sc);
+ switch (bsc->mii_oui) {
+ case MII_OUI_BROADCOM:
break;
- case MII_MODEL_xxBROADCOM_BCM5411:
- bcm5411_load_dspcode(sc);
+ 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);
- return (0);
+brgphy_service_exit:
+ return (error);
}
static void
-brgphy_status(sc)
- struct mii_softc *sc;
+brgphy_setmedia(struct mii_softc *sc, int media, int master)
+{
+ struct brgphy_softc *bsc = (struct brgphy_softc *)sc;
+ int bmcr = 0, gig;
+
+ switch (IFM_SUBTYPE(media)) {
+ case IFM_2500_SX:
+ break;
+ case IFM_1000_SX:
+ case IFM_1000_T:
+ bmcr = BRGPHY_S1000;
+ break;
+ case IFM_100_TX:
+ bmcr = BRGPHY_S100;
+ break;
+ case IFM_10_T:
+ default:
+ bmcr = BRGPHY_S10;
+ break;
+ }
+ if ((media & IFM_GMASK) == IFM_FDX) {
+ bmcr |= BRGPHY_BMCR_FDX;
+ gig = BRGPHY_1000CTL_AFD;
+ } else {
+ gig = BRGPHY_1000CTL_AHD;
+ }
+
+ brgphy_enable_loopback(sc);
+ PHY_WRITE(sc, BRGPHY_MII_1000CTL, 0);
+ PHY_WRITE(sc, BRGPHY_MII_BMCR, bmcr);
+ PHY_WRITE(sc, BRGPHY_MII_ANAR, BRGPHY_SEL_TYPE);
+
+ if ((IFM_SUBTYPE(media) != IFM_1000_T) && (IFM_SUBTYPE(media) != IFM_1000_SX))
+ goto brgphy_setmedia_exit;
+
+ PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig);
+ PHY_WRITE(sc, BRGPHY_MII_BMCR,
+ bmcr | BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG);
+
+ if (bsc->mii_model != MII_MODEL_xxBROADCOM_BCM5701)
+ goto brgphy_setmedia_exit;
+
+ /*
+ * When setting 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 (master) {
+ PHY_WRITE(sc, BRGPHY_MII_1000CTL,
+ gig | BRGPHY_1000CTL_MSE | BRGPHY_1000CTL_MSC);
+ } else {
+ PHY_WRITE(sc, BRGPHY_MII_1000CTL,
+ gig | BRGPHY_1000CTL_MSE);
+ }
+brgphy_setmedia_exit:
+ return;
+}
+
+/* Set the media status based on the PHY settings. */
+/* IFM_FLAG0 = 0 (RX flow control disabled | 1 (enabled) */
+/* IFM_FLAG1 = 0 (TX flow control disabled | 1 (enabled) */
+static void
+brgphy_status(struct mii_softc *sc)
{
+ struct brgphy_softc *bsc = (struct brgphy_softc *)sc;
struct mii_data *mii = sc->mii_pdata;
- struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
- int bmsr, bmcr;
+ int aux, bmcr, bmsr, anar, anlpar, xstat, val;
+
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
- bmsr = PHY_READ(sc, BRGPHY_MII_BMSR);
- if (PHY_READ(sc, BRGPHY_MII_AUXSTS) & BRGPHY_AUXSTS_LINK)
- mii->mii_media_status |= IFM_ACTIVE;
+ bmsr = PHY_READ(sc, BRGPHY_MII_BMSR) | PHY_READ(sc, BRGPHY_MII_BMSR);
+ bmcr = PHY_READ(sc, BRGPHY_MII_BMCR);
+ anar = PHY_READ(sc, BRGPHY_MII_ANAR);
+ anlpar = PHY_READ(sc, BRGPHY_MII_ANLPAR);
- bmcr = PHY_READ(sc, BRGPHY_MII_BMCR);
+ /* Loopback is enabled. */
+ if (bmcr & BRGPHY_BMCR_LOOP) {
- if (bmcr & BRGPHY_BMCR_LOOP)
mii->mii_media_active |= IFM_LOOP;
+ }
- if (bmcr & BRGPHY_BMCR_AUTOEN) {
- if ((bmsr & BRGPHY_BMSR_ACOMP) == 0) {
- /* Erg, still trying, I guess... */
- mii->mii_media_active |= IFM_NONE;
- return;
+ /* Autoneg is still in progress. */
+ if ((bmcr & BRGPHY_BMCR_AUTOEN) &&
+ (bmsr & BRGPHY_BMSR_ACOMP) == 0) {
+ /* Erg, still trying, I guess... */
+ mii->mii_media_active |= IFM_NONE;
+ goto brgphy_status_exit;
+ }
+
+ /* Autoneg is enabled and complete, link should be up. */
+ if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
+ aux = PHY_READ(sc, BRGPHY_MII_AUXSTS);
+
+ /* If copper link is up, get the negotiated speed/duplex. */
+ if (aux & BRGPHY_AUXSTS_LINK) {
+ mii->mii_media_status |= IFM_ACTIVE;
+ switch (aux & BRGPHY_AUXSTS_AN_RES) {
+ case BRGPHY_RES_1000FD:
+ mii->mii_media_active |= IFM_1000_T | IFM_FDX; break;
+ case BRGPHY_RES_1000HD:
+ mii->mii_media_active |= IFM_1000_T | IFM_HDX; 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 | IFM_HDX; 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 | IFM_HDX; break;
+ default:
+ mii->mii_media_active |= IFM_NONE; break;
+ }
+ }
+ } else {
+ /* If serdes link is up, get the negotiated speed/duplex. */
+ if (bmsr & BRGPHY_BMSR_LINK) {
+ mii->mii_media_status |= IFM_ACTIVE;
}
- switch (PHY_READ(sc, BRGPHY_MII_AUXSTS) &
- BRGPHY_AUXSTS_AN_RES) {
- case BRGPHY_RES_1000FD:
- mii->mii_media_active |= IFM_1000_T | IFM_FDX;
- break;
- case BRGPHY_RES_1000HD:
- mii->mii_media_active |= IFM_1000_T | IFM_HDX;
- 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 | IFM_HDX;
- 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 | IFM_HDX;
- break;
- default:
- mii->mii_media_active |= IFM_NONE;
- break;
+ /* Check the link speed/duplex based on the PHY type. */
+ if (bsc->serdes_flags & BRGPHY_5706S) {
+ mii->mii_media_active |= IFM_1000_SX;
+
+ /* If autoneg enabled, read negotiated duplex settings */
+ if (bmcr & BRGPHY_BMCR_AUTOEN) {
+ val = PHY_READ(sc, BRGPHY_SERDES_ANAR) & PHY_READ(sc, BRGPHY_SERDES_ANLPAR);
+ if (val & BRGPHY_SERDES_ANAR_FDX)
+ mii->mii_media_active |= IFM_FDX;
+ else
+ mii->mii_media_active |= IFM_HDX;
+ }
+
+ } else if (bsc->serdes_flags & BRGPHY_5708S) {
+ PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG_PG0);
+ xstat = PHY_READ(sc, BRGPHY_5708S_PG0_1000X_STAT1);
+
+ /* Todo: Create #defines for hard coded values */
+ switch (xstat & BRGPHY_5708S_PG0_1000X_STAT1_SPEED_MASK) {
+ case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_10:
+ mii->mii_media_active |= IFM_10_FL; break;
+ case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_100:
+ mii->mii_media_active |= IFM_100_FX; break;
+ case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_1G:
+ mii->mii_media_active |= IFM_1000_SX; break;
+ case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_25G:
+ mii->mii_media_active |= IFM_2500_SX; break;
+ }
+
+ if (xstat & BRGPHY_5708S_PG0_1000X_STAT1_FDX)
+ mii->mii_media_active |= IFM_FDX;
+ else
+ mii->mii_media_active |= IFM_HDX;
+ }
+ }
+
+#if 0
+ /* Todo: Change bge/bce to use these settings. */
+
+ /* Fetch flow control settings from the PHY */
+ if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
+ /* Set FLAG0 is RX is enabled and FLAG1 if TX is enabled */
+ if ((anar & BRGPHY_ANAR_PC) && (anlpar & BRGPHY_ANLPAR_PC)) {
+ mii->mii_media_active |= IFM_FLAG0 | IFM_FLAG1;
+ } else if (!(anar & BRGPHY_ANAR_PC) && (anlpar & BRGPHY_ANAR_ASP) &&
+ (anlpar & BRPHY_ANLPAR_PC) && (anlpar & BRGPHY_ANLPAR_ASP)) {
+ mii->mii_media_active |= IFM_FLAG1;
+ } else if ((anar & BRGPHY_ANAR_PC) && (anar & BRGPHY_ANAR_ASP) &&
+ !(anlpar & BRGPHY_ANLPAR_PC) && (anlpar & BRGPHY_ANLPAR_ASP)) {
+ mii->mii_media_active |= IFM_FLAG0;
}
- return;
}
+ /* Todo: Add support for fiber settings too. */
+#endif
- mii->mii_media_active = ife->ifm_media;
+brgphy_status_exit:
return;
}
-
-static int
-brgphy_mii_phy_auto(mii)
- struct mii_softc *mii;
+static void
+brgphy_mii_phy_auto(struct mii_softc *sc)
{
+ struct brgphy_softc *bsc = (struct brgphy_softc *)sc;
int ktcr = 0;
- brgphy_loop(mii);
- brgphy_reset(mii);
- ktcr = BRGPHY_1000CTL_AFD|BRGPHY_1000CTL_AHD;
- if (brgphy_mii_model == MII_MODEL_xxBROADCOM_BCM5701)
- ktcr |= BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC;
- PHY_WRITE(mii, BRGPHY_MII_1000CTL, ktcr);
- ktcr = PHY_READ(mii, BRGPHY_MII_1000CTL);
- DELAY(1000);
- PHY_WRITE(mii, BRGPHY_MII_ANAR,
- BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA);
- DELAY(1000);
- PHY_WRITE(mii, BRGPHY_MII_BMCR,
- BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG);
- PHY_WRITE(mii, BRGPHY_MII_IMR, 0xFF00);
- return (EJUSTRETURN);
+ brgphy_reset(sc);
+
+ /* Enable flow control in the advertisement register. */
+ if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
+ /* Pause capability advertisement (pause capable & asymmetric) */
+ PHY_WRITE(sc, BRGPHY_MII_ANAR,
+ BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA |
+ BRGPHY_ANAR_ASP | BRGPHY_ANAR_PC);
+ } else {
+ PHY_WRITE(sc, BRGPHY_SERDES_ANAR, BRGPHY_SERDES_ANAR_FDX |
+ BRGPHY_SERDES_ANAR_HDX | BRGPHY_SERDES_ANAR_BOTH_PAUSE);
+ }
+
+ /* Enable speed in the 1000baseT control register */
+ ktcr = BRGPHY_1000CTL_AFD | BRGPHY_1000CTL_AHD;
+ if (bsc->mii_model == MII_MODEL_xxBROADCOM_BCM5701)
+ ktcr |= BRGPHY_1000CTL_MSE | BRGPHY_1000CTL_MSC;
+ PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr);
+ ktcr = PHY_READ(sc, BRGPHY_MII_1000CTL);
+
+ /* Start autonegotiation */
+ PHY_WRITE(sc, BRGPHY_MII_BMCR,BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG);
+ PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00);
+
}
+/* Enable loopback to force the link down. */
static void
-brgphy_loop(struct mii_softc *sc)
+brgphy_enable_loopback(struct mii_softc *sc)
{
- u_int32_t bmsr;
int i;
PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_LOOP);
for (i = 0; i < 15000; i++) {
- bmsr = PHY_READ(sc, BRGPHY_MII_BMSR);
- if (!(bmsr & BRGPHY_BMSR_LINK)) {
-#if 0
- device_printf(sc->mii_dev, "looped %d\n", i);
-#endif
+ if (!(PHY_READ(sc, BRGPHY_MII_BMSR) & BRGPHY_BMSR_LINK))
break;
- }
DELAY(10);
}
}
@@ -583,7 +697,24 @@
}
static void
-bcm5703_load_dspcode(struct mii_softc *sc)
+brgphy_fixup_5704_a0_bug(struct mii_softc *sc)
+{
+ static const struct {
+ int reg;
+ uint16_t val;
+ } dspcode[] = {
+ { 0x1c, 0x8d68 },
+ { 0x1c, 0x8d68 },
+ { 0, 0 },
+ };
+ int i;
+
+ for (i = 0; dspcode[i].reg != 0; i++)
+ PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
+}
+
+static void
+brgphy_fixup_adc_bug(struct mii_softc *sc)
{
static const struct {
int reg;
@@ -601,14 +732,59 @@
}
static void
-bcm5704_load_dspcode(struct mii_softc *sc)
+brgphy_fixup_adjust_trim(struct mii_softc *sc)
{
static const struct {
int reg;
- u_int16_t val;
+ uint16_t val;
} dspcode[] = {
+ { BRGPHY_MII_AUXCTL, 0x0c00 },
+ { BRGPHY_MII_DSP_ADDR_REG, 0x000a },
+ { BRGPHY_MII_DSP_RW_PORT, 0x110b },
+ { BRGPHY_MII_TEST1, 0x0014 },
+ { BRGPHY_MII_AUXCTL, 0x0400 },
+ { 0, 0 },
+ };
+ int i;
+
+ for (i = 0; dspcode[i].reg != 0; i++)
+ PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
+}
+
+static void
+brgphy_fixup_ber_bug(struct mii_softc *sc)
+{
+ static const struct {
+ int reg;
+ uint16_t val;
+ } dspcode[] = {
+ { BRGPHY_MII_AUXCTL, 0x0c00 },
+ { BRGPHY_MII_DSP_ADDR_REG, 0x000a },
+ { BRGPHY_MII_DSP_RW_PORT, 0x310b },
+ { BRGPHY_MII_DSP_ADDR_REG, 0x201f },
+ { BRGPHY_MII_DSP_RW_PORT, 0x9506 },
+ { BRGPHY_MII_DSP_ADDR_REG, 0x401f },
+ { BRGPHY_MII_DSP_RW_PORT, 0x14e2 },
+ { BRGPHY_MII_AUXCTL, 0x0400 },
+ { 0, 0 },
+ };
+ int i;
+
+ for (i = 0; dspcode[i].reg != 0; i++)
+ PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val);
+}
+
+static void
+brgphy_fixup_crc_bug(struct mii_softc *sc)
+{
+ static const struct {
+ int reg;
+ uint16_t val;
+ } dspcode[] = {
+ { BRGPHY_MII_DSP_RW_PORT, 0x0a75 },
+ { 0x1c, 0x8c68 },
{ 0x1c, 0x8d68 },
- { 0x1c, 0x8d68 },
+ { 0x1c, 0x8c68 },
{ 0, 0 },
};
int i;
@@ -618,20 +794,16 @@
}
static void
-bcm5750_load_dspcode(struct mii_softc *sc)
+brgphy_fixup_jitter_bug(struct mii_softc *sc)
{
static const struct {
int reg;
- u_int16_t val;
+ uint16_t val;
} dspcode[] = {
- { 0x18, 0x0c00 },
- { 0x17, 0x000a },
- { 0x15, 0x310b },
- { 0x17, 0x201f },
- { 0x15, 0x9506 },
- { 0x17, 0x401f },
- { 0x15, 0x14e2 },
- { 0x18, 0x0400 },
+ { BRGPHY_MII_AUXCTL, 0x0c00 },
+ { BRGPHY_MII_DSP_ADDR_REG, 0x000a },
+ { BRGPHY_MII_DSP_RW_PORT, 0x010b },
+ { BRGPHY_MII_AUXCTL, 0x0400 },
{ 0, 0 },
};
int i;
@@ -641,35 +813,78 @@
}
static void
+brgphy_ethernet_wirespeed(struct mii_softc *sc)
+{
+ uint32_t val;
+
+ /* Enable Ethernet at WireSpeed. */
+ PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007);
+ val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
+ PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val | (1 << 15) | (1 << 4));
+}
+
+static void
+brgphy_jumbo_settings(struct mii_softc *sc, u_long mtu)
+{
+ struct brgphy_softc *bsc = (struct brgphy_softc *)sc;
+ uint32_t val;
+
+ /* Set or clear jumbo frame settings in the PHY. */
+ if (mtu > ETHER_MAX_LEN) {
+ if (bsc->mii_model == MII_MODEL_xxBROADCOM_BCM5401) {
+ /* BCM5401 PHY cannot read-modify-write. */
+ PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x4c20);
+ } else {
+ PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7);
+ val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
+ PHY_WRITE(sc, BRGPHY_MII_AUXCTL,
+ val | BRGPHY_AUXCTL_LONG_PKT);
+ }
+
+ val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL);
+ PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
+ val | BRGPHY_PHY_EXTCTL_HIGH_LA);
+ } else {
+ PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7);
+ val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
+ PHY_WRITE(sc, BRGPHY_MII_AUXCTL,
+ val & ~(BRGPHY_AUXCTL_LONG_PKT | 0x7));
+
+ val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL);
+ PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
+ val & ~BRGPHY_PHY_EXTCTL_HIGH_LA);
+ }
+}
+
+static void
brgphy_reset(struct mii_softc *sc)
{
- u_int32_t val;
- struct ifnet *ifp;
- struct bge_softc *bge_sc = NULL;
- struct bce_softc *bce_sc = NULL;
+ struct brgphy_softc *bsc = (struct brgphy_softc *)sc;
+ struct bge_softc *bge_sc = NULL;
+ struct bce_softc *bce_sc = NULL;
+ struct ifnet *ifp;
mii_phy_reset(sc);
- switch (brgphy_mii_model) {
- case MII_MODEL_xxBROADCOM_BCM5400:
- case MII_MODEL_xxBROADCOM_BCM5401:
- bcm5401_load_dspcode(sc);
- break;
- case MII_MODEL_xxBROADCOM_BCM5411:
- bcm5411_load_dspcode(sc);
- break;
- case MII_MODEL_xxBROADCOM_BCM5703:
- bcm5703_load_dspcode(sc);
- break;
- case MII_MODEL_xxBROADCOM_BCM5704:
- bcm5704_load_dspcode(sc);
- break;
- case MII_MODEL_xxBROADCOM_BCM5750:
- case MII_MODEL_xxBROADCOM_BCM5714:
- case MII_MODEL_xxBROADCOM_BCM5780:
- case MII_MODEL_xxBROADCOM_BCM5706C:
- case MII_MODEL_xxBROADCOM_BCM5708C:
- bcm5750_load_dspcode(sc);
+ /* Handle any PHY specific procedures to finish the reset. */
+ 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;
}
@@ -677,61 +892,102 @@
/* Find the driver associated with this PHY. */
if (strcmp(ifp->if_dname, "bge") == 0) {
- bge_sc = ifp->if_softc;
+ bge_sc = ifp->if_softc;
} else if (strcmp(ifp->if_dname, "bce") == 0) {
bce_sc = ifp->if_softc;
}
- /* Handle any NetXtreme/bge workarounds. */
+ /* Handle any bge (NetXtreme/NetLink) workarounds. */
if (bge_sc) {
- /*
+ /* Fix up various bugs */
+ if (bge_sc->bge_flags & BGE_FLAG_5704_A0_BUG)
+ brgphy_fixup_5704_a0_bug(sc);
+ if (bge_sc->bge_flags & BGE_FLAG_ADC_BUG)
+ brgphy_fixup_adc_bug(sc);
+ if (bge_sc->bge_flags & BGE_FLAG_ADJUST_TRIM)
+ brgphy_fixup_adjust_trim(sc);
+ if (bge_sc->bge_flags & BGE_FLAG_BER_BUG)
+ brgphy_fixup_ber_bug(sc);
+ if (bge_sc->bge_flags & BGE_FLAG_CRC_BUG)
+ brgphy_fixup_crc_bug(sc);
+ if (bge_sc->bge_flags & BGE_FLAG_JITTER_BUG)
+ brgphy_fixup_jitter_bug(sc);
+
+ brgphy_jumbo_settings(sc, ifp->if_mtu);
+
+ /*
* Don't enable Ethernet at WireSpeed for the 5700 or the
- * 5705 A1 and A2 chips. Make sure we only do this test
- * on "bge" NICs, since other drivers may use this same
- * PHY subdriver.
+ * 5705 A1 and A2 chips.
*/
- if (bge_sc->bge_asicrev == BGE_ASICREV_BCM5700 ||
- bge_sc->bge_chipid == BGE_CHIPID_BCM5705_A1 ||
- bge_sc->bge_chipid == BGE_CHIPID_BCM5705_A2)
- return;
-
- /* Enable Ethernet at WireSpeed. */
- PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007);
- val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
- PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val | (1 << 15) | (1 << 4));
+ if (bge_sc->bge_asicrev != BGE_ASICREV_BCM5700 &&
+ bge_sc->bge_chipid != BGE_CHIPID_BCM5705_A1 &&
+ bge_sc->bge_chipid != BGE_CHIPID_BCM5705_A2)
+ brgphy_ethernet_wirespeed(sc);
/* Enable Link LED on Dell boxes */
- if (bge_sc->bge_no_3_led) {
- PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
- PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL)
- & ~BRGPHY_PHY_EXTCTL_3_LED);
+ if (bge_sc->bge_flags & BGE_FLAG_NO_3LED) {
+ PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
+ PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) &
+ ~BRGPHY_PHY_EXTCTL_3_LED);
}
+ /* Handle any bce (NetXtreme II) workarounds. */
} else if (bce_sc) {
- /* Set or clear jumbo frame settings in the PHY. */
- if (ifp->if_mtu > ETHER_MAX_LEN) {
- PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7);
- val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
- PHY_WRITE(sc, BRGPHY_MII_AUXCTL,
- val | BRGPHY_AUXCTL_LONG_PKT);
+ if (BCE_CHIP_NUM(bce_sc) == BCE_CHIP_NUM_5708 &&
+ BCE_CHIP_BOND_ID(bce_sc) & BCE_CHIP_BOND_ID_SERDES_BIT) {
- val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL);
- PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
- val | BRGPHY_PHY_EXTCTL_HIGH_LA);
- } else {
- PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7);
- val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
- PHY_WRITE(sc, BRGPHY_MII_AUXCTL,
- val & ~(BRGPHY_AUXCTL_LONG_PKT | 0x7));
+ /* 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 (bce_sc->bce_phy_flags & BCE_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 ((BCE_CHIP_ID(bce_sc) == BCE_CHIP_ID_5708_A0) ||
+ (BCE_CHIP_ID(bce_sc) == BCE_CHIP_ID_5708_B0) ||
+ (BCE_CHIP_ID(bce_sc) == BCE_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) & ~0x30);
+ PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR,
+ BRGPHY_5708S_DIG_PG0);
+ }
- val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL);
- PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL,
- val & ~BRGPHY_PHY_EXTCTL_HIGH_LA);
+ /* Backplanes use special driver/pre-driver/pre-emphasis values. */
+ if ((bce_sc->bce_shared_hw_cfg & BCE_SHARED_HW_CFG_PHY_BACKPLANE) &&
+ (bce_sc->bce_port_hw_cfg & BCE_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,
+ bce_sc->bce_port_hw_cfg &
+ BCE_PORT_HW_CFG_CFG_TXCTL3_MASK);
+ PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR,
+ BRGPHY_5708S_DIG_PG0);
+ }
+ } else {
+ brgphy_fixup_ber_bug(sc);
+ brgphy_jumbo_settings(sc, ifp->if_mtu);
+ brgphy_ethernet_wirespeed(sc);
}
- /* Enable Ethernet at Wirespeed */
- PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007);
- val = PHY_READ(sc, BRGPHY_MII_AUXCTL);
- PHY_WRITE(sc, BRGPHY_MII_AUXCTL, (val | (1 << 15) | (1 << 4)));
}
}
+
More information about the Midnightbsd-cvs
mailing list