diff options
author | Nathan Binkert <nate@cvs.openbsd.org> | 2002-04-08 21:46:24 +0000 |
---|---|---|
committer | Nathan Binkert <nate@cvs.openbsd.org> | 2002-04-08 21:46:24 +0000 |
commit | e982f35d0a1b2781d4b4004ab01955a5ff42965c (patch) | |
tree | b591739bfb68da7689e1f91e51bde3a09cc4a416 /sys/dev/pci | |
parent | 4b8f0c731225a3cdcf34b9db773685c4d97be267 (diff) |
Make fiber cards work (3com 3c996-SX)
Make the BCM5701 chips work. (3com 3c996B-T)
From FreeBSD
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_bge.c | 144 | ||||
-rw-r--r-- | sys/dev/pci/if_bgereg.h | 33 |
2 files changed, 135 insertions, 42 deletions
diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c index 9f23a2ea674..d16be0beadd 100644 --- a/sys/dev/pci/if_bge.c +++ b/sys/dev/pci/if_bge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bge.c,v 1.8 2002/03/14 01:26:58 millert Exp $ */ +/* $OpenBSD: if_bge.c,v 1.9 2002/04/08 21:46:23 nate Exp $ */ /* * Copyright (c) 2001 Wind River Systems * Copyright (c) 1997, 1998, 1999, 2001 @@ -31,7 +31,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/bge/if_bge.c,v 1.2 2001/09/28 18:56:57 wpaul Exp $ + * $FreeBSD: if_bge.c,v 1.11 2002/04/04 06:01:31 wpaul Exp $ */ /* @@ -137,8 +137,7 @@ void bge_shutdown(void *); int bge_ifmedia_upd(struct ifnet *); void bge_ifmedia_sts(struct ifnet *, struct ifmediareq *); -u_int8_t bge_eeprom_getbyte(struct bge_softc *, - int, u_int8_t *); +u_int8_t bge_eeprom_getbyte(struct bge_softc *, int, u_int8_t *); int bge_read_eeprom(struct bge_softc *, caddr_t, int, int); u_int32_t bge_crc(struct bge_softc *, caddr_t); @@ -161,9 +160,11 @@ int bge_init_tx_ring(struct bge_softc *); int bge_chipinit(struct bge_softc *); int bge_blockinit(struct bge_softc *); +#ifdef notdef u_int8_t bge_vpd_readbyte(struct bge_softc *, int); void bge_vpd_read_res(struct bge_softc *, struct vpd_res *, int); void bge_vpd_read(struct bge_softc *); +#endif u_int32_t bge_readmem_ind(struct bge_softc *, int); void bge_writemem_ind(struct bge_softc *, int, int); @@ -235,6 +236,7 @@ bge_writereg_ind(sc, off, val) pci_conf_write(pa->pa_pc, pa->pa_tag, BGE_PCI_REG_DATA, val); } +#ifdef notdef u_int8_t bge_vpd_readbyte(sc, addr) struct bge_softc *sc; @@ -322,6 +324,7 @@ bge_vpd_read(sc) for (i = 0; i < res.vr_len + 1; i++) sc->bge_vpd_readonly[i] = bge_vpd_readbyte(sc, i + pos); } +#endif /* * Read a byte of data stored in the EEPROM at address 'addr.' The @@ -407,8 +410,8 @@ bge_miibus_readreg(dev, phy, reg) ifp = &sc->arpcom.ac_if; - if (ifp->if_flags & IFF_RUNNING) - BGE_CLRBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL); + if (sc->bge_asicrev == BGE_ASICREV_BCM5701_B5 && phy != 1) + return(0); CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_READ|BGE_MICOMM_BUSY| BGE_MIPHY(phy)|BGE_MIREG(reg)); @@ -426,9 +429,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); @@ -641,15 +641,11 @@ bge_newbuf_std(sc, i, m) if (m == NULL) { MGETHDR(m_new, M_DONTWAIT, MT_DATA); if (m_new == NULL) { - printf("%s: mbuf allocation failed " - "-- packet dropped!\n", sc->bge_dev.dv_xname); return(ENOBUFS); } MCLGET(m_new, M_DONTWAIT); if (!(m_new->m_flags & M_EXT)) { - printf("%s: cluster allocation failed " - "-- packet dropped!\n", sc->bge_dev.dv_xname); m_freem(m_new); return(ENOBUFS); } @@ -693,8 +689,6 @@ bge_newbuf_jumbo(sc, i, m) /* Allocate the mbuf. */ MGETHDR(m_new, M_DONTWAIT, MT_DATA); if (m_new == NULL) { - printf("%s: mbuf allocation failed " - "-- packet dropped!\n", sc->bge_dev.dv_xname); return(ENOBUFS); } @@ -1386,8 +1380,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); @@ -1424,6 +1422,10 @@ bge_probe(parent, match, aux) PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ALTEON_BCM5701)) return (1); + if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ALTIMA && + PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ALTIMA_AC100X) + return (1); + if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROADCOM && (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_BCM5700 || PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROADCOM_BCM5701)) @@ -1454,6 +1456,7 @@ bge_attach(parent, self, aux) bus_size_t iosize; bus_dma_segment_t seg; int s, rseg; + u_int32_t hwcfg = 0; u_int32_t command; struct ifnet *ifp; int unit, error = 0; @@ -1627,26 +1630,60 @@ bge_attach(parent, self, aux) sc->bge_mii.mii_writereg = bge_miibus_writereg; sc->bge_mii.mii_statchg = bge_miibus_statchg; + /* Save ASIC rev. */ + + sc->bge_asicrev = + pci_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_MISC_CTL) & + 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_conf_read(pa->pa_pc, pa->pa_tag, BGE_PCI_SUBSYS) >> 16) == SK_SUBSYSID_9D41) sc->bge_tbi = 1; - /* - * Do transceiver setup. - */ - ifmedia_init(&sc->bge_mii.mii_media, 0, bge_ifmedia_upd, - bge_ifmedia_sts); - mii_attach(&sc->bge_dev, &sc->bge_mii, 0xffffffff, - MII_PHY_ANY, MII_OFFSET_ANY, 0); - - if (LIST_FIRST(&sc->bge_mii.mii_phys) == NULL) { - printf("%s: no PHY found!\n", sc->bge_dev.dv_xname); - ifmedia_add(&sc->bge_mii.mii_media, IFM_ETHER|IFM_MANUAL, + if (sc->bge_tbi) { + ifmedia_init(&sc->bge_ifmedia, IFM_IMASK, bge_ifmedia_upd, + bge_ifmedia_sts); + ifmedia_add(&sc->bge_ifmedia, IFM_ETHER|IFM_1000_SX, 0, NULL); + ifmedia_add(&sc->bge_ifmedia, IFM_ETHER|IFM_1000_SX|IFM_FDX, 0, NULL); - ifmedia_set(&sc->bge_mii.mii_media, IFM_ETHER|IFM_MANUAL); - } else - ifmedia_set(&sc->bge_mii.mii_media, IFM_ETHER|IFM_AUTO); + ifmedia_add(&sc->bge_ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); + ifmedia_set(&sc->bge_ifmedia, IFM_ETHER|IFM_AUTO); + } else { + /* + * Do transceiver setup. + */ + ifmedia_init(&sc->bge_mii.mii_media, 0, bge_ifmedia_upd, + bge_ifmedia_sts); + mii_attach(&sc->bge_dev, &sc->bge_mii, 0xffffffff, + MII_PHY_ANY, MII_OFFSET_ANY, 0); + + if (LIST_FIRST(&sc->bge_mii.mii_phys) == NULL) { + printf("%s: no PHY found!\n", sc->bge_dev.dv_xname); + ifmedia_add(&sc->bge_mii.mii_media, + IFM_ETHER|IFM_MANUAL, 0, NULL); + ifmedia_set(&sc->bge_mii.mii_media, + IFM_ETHER|IFM_MANUAL); + } else + ifmedia_set(&sc->bge_mii.mii_media, + IFM_ETHER|IFM_AUTO); + } /* * Call MI attach routine. @@ -1954,16 +1991,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) { - sc->bge_link = 0; - timeout_del(&sc->bge_timeout); - bge_tick(sc); - /* 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); + /* + * 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; + timeout_del(&sc->bge_timeout); + 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; + timeout_del(&sc->bge_timeout); + bge_tick(sc); + /* Clear the interrupt */ + CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED| + BGE_MACSTAT_CFG_CHANGED); + } } if (ifp->if_flags & IFF_RUNNING) { diff --git a/sys/dev/pci/if_bgereg.h b/sys/dev/pci/if_bgereg.h index 38d9edd73ae..bd733243177 100644 --- a/sys/dev/pci/if_bgereg.h +++ b/sys/dev/pci/if_bgereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bgereg.h,v 1.3 2002/03/06 23:13:58 nate Exp $ */ +/* $OpenBSD: if_bgereg.h,v 1.4 2002/04/08 21:46:23 nate Exp $ */ /* * Copyright (c) 2001 Wind River Systems * Copyright (c) 1997, 1998, 1999, 2001 @@ -31,7 +31,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD$ + * $FreeBSD: if_bgereg.h,v 1.4 2002/04/04 06:01:31 wpaul Exp $ */ /* @@ -218,6 +218,13 @@ #define BGE_ASICREV_BCM5700_B2 0x71030000 #define BGE_ASICREV_BCM5700_ALTIMA 0x71040000 #define BGE_ASICREV_BCM5700_C0 0x72000000 +#define BGE_ASICREV_BCM5701_A0 0x00000000 /* grrrr */ +#define BGE_ASICREV_BCM5701_B0 0x01000000 +#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 @@ -1809,11 +1816,32 @@ struct bge_status_block { #define SK_SUBSYSID_9D41 0x4441 /* + * Altima PCI vendor/device ID. + */ +#define ALTIMA_VENDORID 0x173b +#define ALTIMA_DEVICE_AC1000 0x03e8 + +/* * Offset of MAC address inside EEPROM. */ #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 @@ -2134,6 +2162,7 @@ struct bge_softc { u_int8_t bge_extram; /* has external SSRAM */ u_int8_t bge_tbi; bus_dma_tag_t bge_dmatag; + u_int32_t bge_asicrev; struct bge_ring_data *bge_rdata; /* rings */ struct bge_chain_data bge_cdata; /* mbufs */ bus_dmamap_t bge_ring_map; |