summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/bge/if_bge.c126
-rw-r--r--sys/dev/bge/if_bgereg.h6
2 files changed, 98 insertions, 34 deletions
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index c6c0ea0..18f9a80 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -106,6 +106,13 @@ __FBSDID("$FreeBSD$");
#include "miidevs.h"
#include <dev/mii/brgphyreg.h>
+#ifdef __sparc64__
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/openfirm.h>
+#include <machine/ofw_machdep.h>
+#include <machine/ver.h>
+#endif
+
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
@@ -348,6 +355,7 @@ static int bge_init_tx_ring(struct bge_softc *);
static int bge_chipinit(struct bge_softc *);
static int bge_blockinit(struct bge_softc *);
+static int bge_has_eeprom(struct bge_softc *);
static uint32_t bge_readmem_ind(struct bge_softc *, int);
static void bge_writemem_ind(struct bge_softc *, int, int);
#ifdef notdef
@@ -428,6 +436,50 @@ SYSCTL_INT(_hw_bge, OID_AUTO, fake_autoneg, CTLFLAG_RD, &bge_fake_autoneg, 0,
SYSCTL_INT(_hw_bge, OID_AUTO, allow_asf, CTLFLAG_RD, &bge_allow_asf, 0,
"Allow ASF mode if available");
+#define SPARC64_BLADE_1500_MODEL "SUNW,Sun-Blade-1500"
+#define SPARC64_BLADE_1500_PATH_BGE "/pci@1f,700000/network@2"
+#define SPARC64_BLADE_2500_MODEL "SUNW,Sun-Blade-2500"
+#define SPARC64_BLADE_2500_PATH_BGE "/pci@1c,600000/network@3"
+#define SPARC64_OFW_SUBVENDOR "subsystem-vendor-id"
+
+static int
+bge_has_eeprom(struct bge_softc *sc)
+{
+#ifdef __sparc64__
+ char buf[sizeof(SPARC64_BLADE_1500_PATH_BGE)];
+ device_t dev;
+ uint32_t subvendor;
+
+ dev = sc->bge_dev;
+
+ /*
+ * The on-board BGEs found in sun4u machines aren't fitted with
+ * an EEPROM which means that we have to obtain the MAC address
+ * via OFW and that some tests will always fail. We distinguish
+ * such BGEs by the subvendor ID, which also has to be obtained
+ * from OFW instead of the PCI configuration space as the latter
+ * indicates Broadcom as the subvendor of the netboot interface.
+ * For early Blade 1500 and 2500 we even have to check the OFW
+ * device path as the subvendor ID always defaults to Broadcom
+ * there.
+ */
+ if (OF_getprop(ofw_bus_get_node(dev), SPARC64_OFW_SUBVENDOR,
+ &subvendor, sizeof(subvendor)) == sizeof(subvendor) &&
+ subvendor == SUN_VENDORID)
+ return (0);
+ memset(buf, 0, sizeof(buf));
+ if (OF_package_to_path(ofw_bus_get_node(dev), buf, sizeof(buf)) > 0) {
+ if (strcmp(sparc64_model, SPARC64_BLADE_1500_MODEL) == 0 &&
+ strcmp(buf, SPARC64_BLADE_1500_PATH_BGE) == 0)
+ return (0);
+ if (strcmp(sparc64_model, SPARC64_BLADE_2500_MODEL) == 0 &&
+ strcmp(buf, SPARC64_BLADE_2500_PATH_BGE) == 0)
+ return (0);
+ }
+#endif
+ return (1);
+}
+
static uint32_t
bge_readmem_ind(struct bge_softc *sc, int off)
{
@@ -1100,9 +1152,12 @@ bge_chipinit(struct bge_softc *sc)
/*
* Check the 'ROM failed' bit on the RX CPU to see if
- * self-tests passed.
+ * self-tests passed. Skip this check when there's no
+ * EEPROM fitted, since in that case it will always
+ * fail.
*/
- if (CSR_READ_4(sc, BGE_RXCPU_MODE) & BGE_RXCPUMODE_ROMFAIL) {
+ if ((sc->bge_flags & BGE_FLAG_EEPROM) &&
+ CSR_READ_4(sc, BGE_RXCPU_MODE) & BGE_RXCPUMODE_ROMFAIL) {
device_printf(sc->bge_dev, "RX CPU self-diagnostics failed!\n");
return (ENODEV);
}
@@ -2171,8 +2226,8 @@ bge_attach(device_t dev)
struct bge_softc *sc;
uint32_t hwcfg = 0;
uint32_t mac_tmp = 0;
- u_char eaddr[6];
- int error = 0, rid, trys, reg;
+ u_char eaddr[ETHER_ADDR_LEN];
+ int error, reg, rid, trys;
sc = device_get_softc(dev);
sc->bge_dev = dev;
@@ -2203,6 +2258,9 @@ bge_attach(device_t dev)
sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid);
sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid);
+ if (bge_has_eeprom(sc))
+ sc->bge_flags |= BGE_FLAG_EEPROM;
+
/* Save chipset family. */
switch (sc->bge_asicrev) {
case BGE_ASICREV_BCM5700:
@@ -2316,7 +2374,6 @@ bge_attach(device_t dev)
/* Try to reset the chip. */
if (bge_reset(sc)) {
device_printf(sc->bge_dev, "chip reset failed\n");
- bge_release_resources(sc);
error = ENXIO;
goto fail;
}
@@ -2339,7 +2396,6 @@ bge_attach(device_t dev)
bge_sig_pre_reset(sc, BGE_RESET_STOP);
if (bge_reset(sc)) {
device_printf(sc->bge_dev, "chip reset failed\n");
- bge_release_resources(sc);
error = ENXIO;
goto fail;
}
@@ -2349,29 +2405,32 @@ bge_attach(device_t dev)
if (bge_chipinit(sc)) {
device_printf(sc->bge_dev, "chip initialization failed\n");
- bge_release_resources(sc);
error = ENXIO;
goto fail;
}
- /*
- * Get station address from the EEPROM.
- */
- mac_tmp = bge_readmem_ind(sc, 0x0C14);
- if ((mac_tmp >> 16) == 0x484B) {
- eaddr[0] = (u_char)(mac_tmp >> 8);
- eaddr[1] = (u_char)mac_tmp;
- mac_tmp = bge_readmem_ind(sc, 0x0C18);
- eaddr[2] = (u_char)(mac_tmp >> 24);
- eaddr[3] = (u_char)(mac_tmp >> 16);
- eaddr[4] = (u_char)(mac_tmp >> 8);
- eaddr[5] = (u_char)mac_tmp;
- } else if (bge_read_eeprom(sc, eaddr,
- BGE_EE_MAC_OFFSET + 2, ETHER_ADDR_LEN)) {
- device_printf(sc->bge_dev, "failed to read station address\n");
- bge_release_resources(sc);
- error = ENXIO;
- goto fail;
+#ifdef __sparc64__
+ if ((sc->bge_flags & BGE_FLAG_EEPROM) == 0)
+ OF_getetheraddr(dev, eaddr);
+ else
+#endif
+ {
+ mac_tmp = bge_readmem_ind(sc, 0x0C14);
+ if ((mac_tmp >> 16) == 0x484B) {
+ eaddr[0] = (u_char)(mac_tmp >> 8);
+ eaddr[1] = (u_char)mac_tmp;
+ mac_tmp = bge_readmem_ind(sc, 0x0C18);
+ eaddr[2] = (u_char)(mac_tmp >> 24);
+ eaddr[3] = (u_char)(mac_tmp >> 16);
+ eaddr[4] = (u_char)(mac_tmp >> 8);
+ eaddr[5] = (u_char)mac_tmp;
+ } else if (bge_read_eeprom(sc, eaddr,
+ BGE_EE_MAC_OFFSET + 2, ETHER_ADDR_LEN)) {
+ device_printf(sc->bge_dev,
+ "failed to read station address\n");
+ error = ENXIO;
+ goto fail;
+ }
}
/* 5705 limits RX return ring to 512 entries. */
@@ -2383,7 +2442,6 @@ bge_attach(device_t dev)
if (bge_dma_alloc(dev)) {
device_printf(sc->bge_dev,
"failed to allocate DMA resources\n");
- bge_release_resources(sc);
error = ENXIO;
goto fail;
}
@@ -2399,7 +2457,6 @@ bge_attach(device_t dev)
ifp = sc->bge_ifp = if_alloc(IFT_ETHER);
if (ifp == NULL) {
device_printf(sc->bge_dev, "failed to if_alloc()\n");
- bge_release_resources(sc);
error = ENXIO;
goto fail;
}
@@ -2445,11 +2502,10 @@ bge_attach(device_t dev)
*/
if (bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_SIG) == BGE_MAGIC_NUMBER)
hwcfg = bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM_NICCFG);
- else {
+ else if (sc->bge_flags & BGE_FLAG_EEPROM) {
if (bge_read_eeprom(sc, (caddr_t)&hwcfg, BGE_EE_HWCFG_OFFSET,
sizeof(hwcfg))) {
device_printf(sc->bge_dev, "failed to read EEPROM\n");
- bge_release_resources(sc);
error = ENXIO;
goto fail;
}
@@ -2495,7 +2551,6 @@ again:
}
device_printf(sc->bge_dev, "MII without any PHY!\n");
- bge_release_resources(sc);
error = ENXIO;
goto fail;
}
@@ -2543,7 +2598,11 @@ again:
bge_add_sysctls(sc);
+ return (0);
+
fail:
+ bge_release_resources(sc);
+
return (error);
}
@@ -2726,8 +2785,8 @@ bge_reset(struct bge_softc *sc)
/*
* Poll until we see the 1's complement of the magic number.
- * This indicates that the firmware initialization
- * is complete.
+ * This indicates that the firmware initialization is complete.
+ * We expect this to fail if no EEPROM is fitted though.
*/
for (i = 0; i < BGE_TIMEOUT; i++) {
val = bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM);
@@ -2736,10 +2795,9 @@ bge_reset(struct bge_softc *sc)
DELAY(10);
}
- if (i == BGE_TIMEOUT) {
+ if ((sc->bge_flags & BGE_FLAG_EEPROM) && i == BGE_TIMEOUT)
device_printf(sc->bge_dev, "firmware handshake timed out, "
"found 0x%08x\n", val);
- }
/*
* XXX Wait for the value of the PCISTATE register to
diff --git a/sys/dev/bge/if_bgereg.h b/sys/dev/bge/if_bgereg.h
index 769cbdf..5698793 100644
--- a/sys/dev/bge/if_bgereg.h
+++ b/sys/dev/bge/if_bgereg.h
@@ -2080,6 +2080,11 @@ struct bge_status_block {
#define APPLE_DEVICE_BCM5701 0x1645
/*
+ * Sun PCI vendor ID
+ */
+#define SUN_VENDORID 0x108e
+
+/*
* Offset of MAC address inside EEPROM.
*/
#define BGE_EE_MAC_OFFSET 0x7C
@@ -2454,6 +2459,7 @@ struct bge_softc {
uint32_t bge_flags;
#define BGE_FLAG_TBI 0x00000001
#define BGE_FLAG_JUMBO 0x00000002
+#define BGE_FLAG_EEPROM 0x00000004
#define BGE_FLAG_MSI 0x00000100
#define BGE_FLAG_PCIX 0x00000200
#define BGE_FLAG_PCIE 0x00000400
OpenPOWER on IntegriCloud