summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorBill Paul <wpaul@FreeBSD.org>2002-04-04 06:01:31 +0000
committerBill Paul <wpaul@FreeBSD.org>2002-04-04 06:01:31 +0000
commita1d52896af691db343b30f1636b6a6dac0486f02 (patch)
tree9e2d2f9a0e717e8ae342dde059ec89f2364d019c /sys
parent2dfe3200368e7c0f87249c4408d374615c13e9a9 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/bge/if_bge.c70
-rw-r--r--sys/dev/bge/if_bgereg.h18
2 files changed, 73 insertions, 15 deletions
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index bd7adb53f4dc..67000b6084c0 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -482,9 +482,6 @@ bge_miibus_readreg(dev, phy, reg)
if (sc->bge_asicrev == BGE_ASICREV_BCM5701_B5 && phy != 1)
return(0);
- if (ifp->if_flags & IFF_RUNNING)
- BGE_CLRBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
-
CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_READ|BGE_MICOMM_BUSY|
BGE_MIPHY(phy)|BGE_MIREG(reg));
@@ -501,9 +498,6 @@ bge_miibus_readreg(dev, phy, reg)
val = CSR_READ_4(sc, BGE_MI_COMM);
- if (ifp->if_flags & IFF_RUNNING)
- BGE_SETBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
-
if (val & BGE_MICOMM_READFAIL)
return(0);
@@ -1423,8 +1417,12 @@ bge_blockinit(sc)
/* Enable PHY auto polling (for MII/GMII only) */
if (sc->bge_tbi) {
CSR_WRITE_4(sc, BGE_MI_STS, BGE_MISTS_LINK);
- } else
+ } else {
BGE_SETBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL|10<<16);
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5700)
+ CSR_WRITE_4(sc, BGE_MAC_EVT_ENB,
+ BGE_EVTENB_MI_INTERRUPT);
+ }
/* Enable link state change attentions. */
BGE_SETBIT(sc, BGE_MAC_EVT_ENB, BGE_EVTENB_LINK_CHANGED);
@@ -1478,6 +1476,7 @@ bge_attach(dev)
u_int32_t command;
struct ifnet *ifp;
struct bge_softc *sc;
+ u_int32_t hwcfg = 0;
int unit, error = 0, rid;
s = splimp();
@@ -1632,6 +1631,22 @@ bge_attach(dev)
pci_read_config(dev, BGE_PCI_MISC_CTL, 4) &
BGE_PCIMISCCTL_ASICREV;
+ /* Pretend all 5700s are the same */
+ if ((sc->bge_asicrev & 0xFF000000) == BGE_ASICREV_BCM5700)
+ sc->bge_asicrev = BGE_ASICREV_BCM5700;
+
+ /*
+ * Figure out what sort of media we have by checking the
+ * hardware config word in the EEPROM. Note: on some BCM5700
+ * cards, this value appears to be unset. If that's the
+ * case, we have to rely on identifying the NIC by its PCI
+ * subsystem ID, as we do below for the SysKonnect SK-9D41.
+ */
+ bge_read_eeprom(sc, (caddr_t)&hwcfg,
+ BGE_EE_HWCFG_OFFSET, sizeof(hwcfg));
+ if ((ntohl(hwcfg) & BGE_HWCFG_MEDIA) == BGE_MEDIA_FIBER)
+ sc->bge_tbi = 1;
+
/* The SysKonnect SK-9D41 is a 1000baseSX card. */
if ((pci_read_config(dev, BGE_PCI_SUBSYS, 4) >> 16) == SK_SUBSYSID_9D41)
sc->bge_tbi = 1;
@@ -1987,18 +2002,43 @@ bge_intr(xsc)
/* Ack interrupt and stop others from occuring. */
CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1);
- /* Process link state changes. */
- if (sc->bge_rdata->bge_status_block.bge_status &
- BGE_STATFLAG_LINKSTATE_CHANGED) {
- if (sc->bge_asicrev != BGE_ASICREV_BCM5701_B5) {
+ /*
+ * Process link state changes.
+ * Grrr. The link status word in the status block does
+ * not work correctly on the BCM5700 rev AX and BX chips,
+ * according to all avaibable information. Hence, we have
+ * to enable MII interrupts in order to properly obtain
+ * async link changes. Unfortunately, this also means that
+ * we have to read the MAC status register to detect link
+ * changes, thereby adding an additional register access to
+ * the interrupt handler.
+ */
+
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5700) {
+ u_int32_t status;
+
+ status = CSR_READ_4(sc, BGE_MAC_STS);
+ if (status & BGE_MACSTAT_MI_INTERRUPT) {
+ sc->bge_link = 0;
+ untimeout(bge_tick, sc, sc->bge_stat_ch);
+ bge_tick(sc);
+ /* Clear the interrupt */
+ CSR_WRITE_4(sc, BGE_MAC_EVT_ENB,
+ BGE_EVTENB_MI_INTERRUPT);
+ bge_miibus_readreg(sc->bge_dev, 1, BRGPHY_MII_ISR);
+ bge_miibus_writereg(sc->bge_dev, 1, BRGPHY_MII_IMR,
+ BRGPHY_INTRS);
+ }
+ } else {
+ if (sc->bge_rdata->bge_status_block.bge_status &
+ BGE_STATFLAG_LINKSTATE_CHANGED) {
sc->bge_link = 0;
untimeout(bge_tick, sc, sc->bge_stat_ch);
bge_tick(sc);
+ /* Clear the interrupt */
+ CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED|
+ BGE_MACSTAT_CFG_CHANGED);
}
- /* ack the event to clear/reset it */
- CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED|
- BGE_MACSTAT_CFG_CHANGED);
- CSR_WRITE_4(sc, BGE_MI_STS, 0);
}
if (ifp->if_flags & IFF_RUNNING) {
diff --git a/sys/dev/bge/if_bgereg.h b/sys/dev/bge/if_bgereg.h
index 39ea6bb61f8c..55de00385254 100644
--- a/sys/dev/bge/if_bgereg.h
+++ b/sys/dev/bge/if_bgereg.h
@@ -222,6 +222,9 @@
#define BGE_ASICREV_BCM5701_B2 0x01020000
#define BGE_ASICREV_BCM5701_B5 0x01050000
+/* shorthand one */
+#define BGE_ASICREV_BCM5700 0x71000000
+
/* PCI DMA Read/Write Control register */
#define BGE_PCIDMARWCTL_MINDMA 0x000000FF
#define BGE_PCIDMARWCTL_RDADRR_BNDRY 0x00000700
@@ -1815,6 +1818,21 @@ struct bge_status_block {
#define BGE_EE_MAC_OFFSET 0x7C
#define BGE_EE_HWCFG_OFFSET 0xC8
+#define BGE_HWCFG_VOLTAGE 0x00000003
+#define BGE_HWCFG_PHYLED_MODE 0x0000000C
+#define BGE_HWCFG_MEDIA 0x00000030
+
+#define BGE_VOLTAGE_1POINT3 0x00000000
+#define BGE_VOLTAGE_1POINT8 0x00000001
+
+#define BGE_PHYLEDMODE_UNSPEC 0x00000000
+#define BGE_PHYLEDMODE_TRIPLELED 0x00000004
+#define BGE_PHYLEDMODE_SINGLELED 0x00000008
+
+#define BGE_MEDIA_UNSPEC 0x00000000
+#define BGE_MEDIA_COPPER 0x00000010
+#define BGE_MEDIA_FIBER 0x00000020
+
#define BGE_PCI_READ_CMD 0x06000000
#define BGE_PCI_WRITE_CMD 0x70000000