summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorNathan Binkert <nate@cvs.openbsd.org>2002-04-08 21:46:24 +0000
committerNathan Binkert <nate@cvs.openbsd.org>2002-04-08 21:46:24 +0000
commite982f35d0a1b2781d4b4004ab01955a5ff42965c (patch)
treeb591739bfb68da7689e1f91e51bde3a09cc4a416 /sys/dev/pci
parent4b8f0c731225a3cdcf34b9db773685c4d97be267 (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.c144
-rw-r--r--sys/dev/pci/if_bgereg.h33
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;