diff options
| author | Bill Paul <wpaul@FreeBSD.org> | 2002-04-04 06:01:31 +0000 |
|---|---|---|
| committer | Bill Paul <wpaul@FreeBSD.org> | 2002-04-04 06:01:31 +0000 |
| commit | a1d52896af691db343b30f1636b6a6dac0486f02 (patch) | |
| tree | 9e2d2f9a0e717e8ae342dde059ec89f2364d019c /sys | |
| parent | 2dfe3200368e7c0f87249c4408d374615c13e9a9 (diff) | |
Notes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/dev/bge/if_bge.c | 70 | ||||
| -rw-r--r-- | sys/dev/bge/if_bgereg.h | 18 |
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 |
