summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2002-04-04 06:01:31 +0000
committerwpaul <wpaul@FreeBSD.org>2002-04-04 06:01:31 +0000
commit707ff463e26353854b4169a90551bf383e387d2b (patch)
tree9e2d2f9a0e717e8ae342dde059ec89f2364d019c /sys
parent8c02d0329f305986380cf670f082781fdc0207bf (diff)
downloadFreeBSD-src-707ff463e26353854b4169a90551bf383e387d2b.zip
FreeBSD-src-707ff463e26353854b4169a90551bf383e387d2b.tar.gz
Try to sort out the correct way to generate async link state change
interrupts. This is a bit harder than it needs to be because there's more than one way to generate link attentions, at least one of which does not work on the BCM5700, but does on the 5701. For the 5701, we can safely use the 'link changed' bit in the status block, and we enable link change attentions in the mac event register. For the 5700, we have to use MII interrupts, which require checking the MAC status register rather than the status block. This requires doing an extra register access on each interrupt which I'd prefer to avoid, but them's the breaks. Testing with both a 3c996-T and 3c996B-T shows that we do in fact detect the link going up and down properly on cable insertions/disconnections. Also, avoid twiddling the autopoll enable bit in the MI mode register when doing a PHY read. I think this coupled with the other changes will stop the interrupt storms Paul Saab has been harassing me about. Manually setting the link to 100baseTX full duplex seems to work ok for me. (I'm typing over the 3c996B-T right now.) Lastly, teach the driver how to recognize a 3c996B-SX by checking the hardware config word in the EEPROM in order to detect the media. We attach 5701 fiber cards correctly now, but I haven't verified that they send/receive packets yet since I don't have a second fiber interface at home. (I know that fiber 5700 cards work, so I'm keeping my fingers crossed.)
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 bd7adb5..67000b60 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 39ea6bb..55de003 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
OpenPOWER on IntegriCloud