diff options
author | wpaul <wpaul@FreeBSD.org> | 2003-07-16 00:09:56 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2003-07-16 00:09:56 +0000 |
commit | e611c416998a4d947f82577fc6d0507a5dbd56f0 (patch) | |
tree | f818757ae33508b65cd8a7c6e007210e8174151c /sys/dev/bge/if_bge.c | |
parent | a54595f215d4214fd4bf8611ab2de5ebb1cc5f69 (diff) | |
download | FreeBSD-src-e611c416998a4d947f82577fc6d0507a5dbd56f0.zip FreeBSD-src-e611c416998a4d947f82577fc6d0507a5dbd56f0.tar.gz |
Add support for the BCM5705 and its ilk. Changes:
- 5705 doesn't support jumbo frames
- Statistics must be read from registers
- RX return ring must be capped at 512 entries
- Omit initialization of certain device blocks
- Acknowledge link change interrupts by setting the 'link changed'
bit in the status register (used to have no effect)
- Remember to toggle the MI completion bit too
- Set the mbuf low watermark differently (on-chip memory buffers,
not BSD mbufs)
- Don't enable Ethernet@WireSpeed feature for certain 5705 chip revs
- Add additional PCI IDs for 5705 and 5782 parts
- Add a forgotten 5704 PCI ID
Most changes ripped kicking and screaming from the Broadcom linux driver.
Thanks to Paul Saab for sanity testing. (My lack of sanity has been
confirmed.)
Diffstat (limited to 'sys/dev/bge/if_bge.c')
-rw-r--r-- | sys/dev/bge/if_bge.c | 327 |
1 files changed, 225 insertions, 102 deletions
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c index 7012cdf..e0dce80 100644 --- a/sys/dev/bge/if_bge.c +++ b/sys/dev/bge/if_bge.c @@ -135,14 +135,26 @@ static struct bge_type bge_devs[] = { "Broadcom BCM5700 Gigabit Ethernet" }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5701, "Broadcom BCM5701 Gigabit Ethernet" }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM5702, + "Broadcom BCM5702 Gigabit Ethernet" }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5702X, "Broadcom BCM5702X Gigabit Ethernet" }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM5703, + "Broadcom BCM5703 Gigabit Ethernet" }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5703X, "Broadcom BCM5703X Gigabit Ethernet" }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5704C, "Broadcom BCM5704C Dual Gigabit Ethernet" }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5704S, "Broadcom BCM5704S Dual Gigabit Ethernet" }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM5705, + "Broadcom BCM5705 Gigabit Ethernet" }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM5705M, + "Broadcom BCM5705M Gigabit Ethernet" }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM5705M_ALT, + "Broadcom BCM5705M Gigabit Ethernet" }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM5782, + "Broadcom BCM5782 Gigabit Ethernet" }, { SK_VENDORID, SK_DEVICEID_ALTIMA, "SysKonnect Gigabit Ethernet" }, { ALTIMA_VENDORID, ALTIMA_DEVICE_AC1000, @@ -162,6 +174,8 @@ static void bge_rxeof (struct bge_softc *); static void bge_tick (void *); static void bge_stats_update (struct bge_softc *); +static void bge_stats_update_regs + (struct bge_softc *); static int bge_encap (struct bge_softc *, struct mbuf *, u_int32_t *); @@ -480,13 +494,17 @@ bge_miibus_readreg(dev, phy, reg) sc = device_get_softc(dev); + /* + * Broadcom's own driver always assumes the internal + * PHY is at GMII address 1. On some chips, the PHY responds + * to accesses at all addresses, which could cause us to + * bogusly attach the PHY 32 times at probe type. Always + * restricting the lookup to address 1 is simpler than + * trying to figure out which chips revisions should be + * special-cased. + */ if (phy != 1) - switch(sc->bge_chipid) { - case BGE_CHIPID_BCM5701_B5: - case BGE_CHIPID_BCM5703_A2: - case BGE_CHIPID_BCM5704_A0: - return(0); - } + return(0); /* Reading with autopolling on may trigger PCI errors */ autopoll = CSR_READ_4(sc, BGE_MI_MODE); @@ -1084,7 +1102,8 @@ bge_chipinit(sc) } if (sc->bge_asicrev == BGE_ASICREV_BCM5703 || - sc->bge_asicrev == BGE_ASICREV_BCM5704) + sc->bge_asicrev == BGE_ASICREV_BCM5704 || + sc->bge_asicrev == BGE_ASICREV_BCM5705) dma_rw_ctl &= ~BGE_PCIDMARWCTL_MINDMA; pci_write_config(sc->bge_dev, BGE_PCI_DMA_RW_CTL, dma_rw_ctl, 4); @@ -1136,22 +1155,32 @@ bge_blockinit(sc) */ CSR_WRITE_4(sc, BGE_PCI_MEMWIN_BASEADDR, 0); - /* Configure mbuf memory pool */ - if (sc->bge_extram) { - CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_BASEADDR, BGE_EXT_SSRAM); - CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_LEN, 0x18000); - } else { - CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_BASEADDR, BGE_BUFFPOOL_1); - CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_LEN, 0x18000); - } + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) { + /* Configure mbuf memory pool */ + if (sc->bge_extram) { + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_BASEADDR, + BGE_EXT_SSRAM); + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_LEN, 0x18000); + } else { + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_BASEADDR, + BGE_BUFFPOOL_1); + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_LEN, 0x18000); + } - /* Configure DMA resource pool */ - CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_BASEADDR, BGE_DMA_DESCRIPTORS); - CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_LEN, 0x2000); + /* Configure DMA resource pool */ + CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_BASEADDR, + BGE_DMA_DESCRIPTORS); + CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_LEN, 0x2000); + } /* Configure mbuf pool watermarks */ - CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x50); - CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x20); + if (sc->bge_asicrev == BGE_ASICREV_BCM5705) { + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x10); + } else { + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x50); + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x20); + } CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60); /* Configure DMA resource watermarks */ @@ -1159,20 +1188,22 @@ bge_blockinit(sc) CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_HIWAT, 10); /* Enable buffer manager */ - CSR_WRITE_4(sc, BGE_BMAN_MODE, - BGE_BMANMODE_ENABLE|BGE_BMANMODE_LOMBUF_ATTN); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) { + CSR_WRITE_4(sc, BGE_BMAN_MODE, + BGE_BMANMODE_ENABLE|BGE_BMANMODE_LOMBUF_ATTN); - /* Poll for buffer manager start indication */ - for (i = 0; i < BGE_TIMEOUT; i++) { - if (CSR_READ_4(sc, BGE_BMAN_MODE) & BGE_BMANMODE_ENABLE) - break; - DELAY(10); - } + /* Poll for buffer manager start indication */ + for (i = 0; i < BGE_TIMEOUT; i++) { + if (CSR_READ_4(sc, BGE_BMAN_MODE) & BGE_BMANMODE_ENABLE) + break; + DELAY(10); + } - if (i == BGE_TIMEOUT) { - printf("bge%d: buffer manager failed to start\n", - sc->bge_unit); - return(ENXIO); + if (i == BGE_TIMEOUT) { + printf("bge%d: buffer manager failed to start\n", + sc->bge_unit); + return(ENXIO); + } } /* Enable flow-through queues */ @@ -1196,7 +1227,11 @@ bge_blockinit(sc) rcb = &sc->bge_rdata->bge_info.bge_std_rx_rcb; BGE_HOSTADDR(rcb->bge_hostaddr, vtophys(&sc->bge_rdata->bge_rx_std_ring)); - rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(BGE_MAX_FRAMELEN, 0); + if (sc->bge_asicrev == BGE_ASICREV_BCM5705) + rcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(512, 0); + else + rcb->bge_maxlen_flags = + BGE_RCB_MAXLEN_FLAGS(BGE_MAX_FRAMELEN, 0); if (sc->bge_extram) rcb->bge_nicaddr = BGE_EXT_STD_RX_RINGS; else @@ -1213,27 +1248,32 @@ bge_blockinit(sc) * using this ring (i.e. once we set the MTU * high enough to require it). */ - rcb = &sc->bge_rdata->bge_info.bge_jumbo_rx_rcb; - BGE_HOSTADDR(rcb->bge_hostaddr, - vtophys(&sc->bge_rdata->bge_rx_jumbo_ring)); - rcb->bge_maxlen_flags = - BGE_RCB_MAXLEN_FLAGS(BGE_MAX_FRAMELEN, BGE_RCB_FLAG_RING_DISABLED); - if (sc->bge_extram) - rcb->bge_nicaddr = BGE_EXT_JUMBO_RX_RINGS; - else - rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS; - CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_HI, - rcb->bge_hostaddr.bge_addr_hi); - CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_LO, - rcb->bge_hostaddr.bge_addr_lo); - CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags); - CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_NICADDR, rcb->bge_nicaddr); - - /* Set up dummy disabled mini ring RCB */ - rcb = &sc->bge_rdata->bge_info.bge_mini_rx_rcb; - rcb->bge_maxlen_flags = - BGE_RCB_MAXLEN_FLAGS(0, BGE_RCB_FLAG_RING_DISABLED); - CSR_WRITE_4(sc, BGE_RX_MINI_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) { + rcb = &sc->bge_rdata->bge_info.bge_jumbo_rx_rcb; + BGE_HOSTADDR(rcb->bge_hostaddr, + vtophys(&sc->bge_rdata->bge_rx_jumbo_ring)); + rcb->bge_maxlen_flags = + BGE_RCB_MAXLEN_FLAGS(BGE_MAX_FRAMELEN, + BGE_RCB_FLAG_RING_DISABLED); + if (sc->bge_extram) + rcb->bge_nicaddr = BGE_EXT_JUMBO_RX_RINGS; + else + rcb->bge_nicaddr = BGE_JUMBO_RX_RINGS; + CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_HI, + rcb->bge_hostaddr.bge_addr_hi); + CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_HADDR_LO, + rcb->bge_hostaddr.bge_addr_lo); + CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, + rcb->bge_maxlen_flags); + CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_NICADDR, rcb->bge_nicaddr); + + /* Set up dummy disabled mini ring RCB */ + rcb = &sc->bge_rdata->bge_info.bge_mini_rx_rcb; + rcb->bge_maxlen_flags = + BGE_RCB_MAXLEN_FLAGS(0, BGE_RCB_FLAG_RING_DISABLED); + CSR_WRITE_4(sc, BGE_RX_MINI_RCB_MAXLEN_FLAGS, + rcb->bge_maxlen_flags); + } /* * Set the BD ring replentish thresholds. The recommended @@ -1263,7 +1303,9 @@ bge_blockinit(sc) vrcb->bge_hostaddr.bge_addr_hi = 0; BGE_HOSTADDR(vrcb->bge_hostaddr, vtophys(&sc->bge_rdata->bge_tx_ring)); vrcb->bge_nicaddr = BGE_NIC_TXRING_ADDR(0, BGE_TX_RING_CNT); - vrcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(BGE_TX_RING_CNT, 0); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + vrcb->bge_maxlen_flags = + BGE_RCB_MAXLEN_FLAGS(BGE_TX_RING_CNT, 0); /* Disable all unused RX return rings */ vrcb = (volatile struct bge_rcb *)(sc->bge_vhandle + BGE_MEMWIN_START + @@ -1272,7 +1314,7 @@ bge_blockinit(sc) vrcb->bge_hostaddr.bge_addr_hi = 0; vrcb->bge_hostaddr.bge_addr_lo = 0; vrcb->bge_maxlen_flags = - BGE_RCB_MAXLEN_FLAGS(BGE_RETURN_RING_CNT, + BGE_RCB_MAXLEN_FLAGS(sc->bge_return_ring_cnt, BGE_RCB_FLAG_RING_DISABLED); vrcb->bge_nicaddr = 0; CSR_WRITE_4(sc, BGE_MBX_RX_CONS0_LO + @@ -1297,7 +1339,8 @@ bge_blockinit(sc) BGE_HOSTADDR(vrcb->bge_hostaddr, vtophys(&sc->bge_rdata->bge_rx_return_ring)); vrcb->bge_nicaddr = 0x00000000; - vrcb->bge_maxlen_flags = BGE_RCB_MAXLEN_FLAGS(BGE_RETURN_RING_CNT, 0); + vrcb->bge_maxlen_flags = + BGE_RCB_MAXLEN_FLAGS(sc->bge_return_ring_cnt, 0); /* Set random backoff seed for TX */ CSR_WRITE_4(sc, BGE_TX_RANDOM_BACKOFF, @@ -1346,23 +1389,29 @@ bge_blockinit(sc) CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS, sc->bge_tx_coal_ticks); CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS, sc->bge_rx_max_coal_bds); CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS, sc->bge_tx_max_coal_bds); - CSR_WRITE_4(sc, BGE_HCC_RX_COAL_TICKS_INT, 0); - CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS_INT, 0); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) { + CSR_WRITE_4(sc, BGE_HCC_RX_COAL_TICKS_INT, 0); + CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS_INT, 0); + } CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT, 0); CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 0); - CSR_WRITE_4(sc, BGE_HCC_STATS_TICKS, sc->bge_stat_ticks); /* Set up address of statistics block */ - CSR_WRITE_4(sc, BGE_HCC_STATS_BASEADDR, BGE_STATS_BLOCK); - CSR_WRITE_4(sc, BGE_HCC_STATS_ADDR_HI, 0); - CSR_WRITE_4(sc, BGE_HCC_STATS_ADDR_LO, - vtophys(&sc->bge_rdata->bge_info.bge_stats)); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) { + CSR_WRITE_4(sc, BGE_HCC_STATS_ADDR_HI, 0); + CSR_WRITE_4(sc, BGE_HCC_STATS_ADDR_LO, + vtophys(&sc->bge_rdata->bge_info.bge_stats)); + + CSR_WRITE_4(sc, BGE_HCC_STATS_BASEADDR, BGE_STATS_BLOCK); + CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_BASEADDR, BGE_STATUS_BLOCK); + CSR_WRITE_4(sc, BGE_HCC_STATS_TICKS, sc->bge_stat_ticks); + } /* Set up address of status block */ - CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_BASEADDR, BGE_STATUS_BLOCK); CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_ADDR_HI, 0); CSR_WRITE_4(sc, BGE_HCC_STATUSBLK_ADDR_LO, vtophys(&sc->bge_rdata->bge_status_block)); + sc->bge_rdata->bge_status_block.bge_idx[0].bge_rx_prod_idx = 0; sc->bge_rdata->bge_status_block.bge_idx[0].bge_tx_cons_idx = 0; @@ -1377,7 +1426,8 @@ bge_blockinit(sc) CSR_WRITE_4(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); /* Turn on RX list selector state machine. */ - CSR_WRITE_4(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + CSR_WRITE_4(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE); /* Turn on DMA, clear stats */ CSR_WRITE_4(sc, BGE_MAC_MODE, BGE_MACMODE_TXDMA_ENB| @@ -1398,7 +1448,8 @@ bge_blockinit(sc) #endif /* Turn on DMA completion state machine */ - CSR_WRITE_4(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + CSR_WRITE_4(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE); /* Turn on write DMA state machine */ CSR_WRITE_4(sc, BGE_WDMA_MODE, @@ -1418,7 +1469,8 @@ bge_blockinit(sc) CSR_WRITE_4(sc, BGE_RDBDI_MODE, BGE_RDBDIMODE_ENABLE); /* Turn on Mbuf cluster free state machine */ - CSR_WRITE_4(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + CSR_WRITE_4(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE); /* Turn on send BD completion state machine */ CSR_WRITE_4(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); @@ -1441,8 +1493,8 @@ bge_blockinit(sc) /* ack/clear link change events */ CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED| - BGE_MACSTAT_CFG_CHANGED); - CSR_WRITE_4(sc, BGE_MI_STS, 0); + BGE_MACSTAT_CFG_CHANGED|BGE_MACSTAT_MI_COMPLETE| + BGE_MACSTAT_LINK_CHANGED); /* Enable PHY auto polling (for MII/GMII only) */ if (sc->bge_tbi) { @@ -1615,13 +1667,26 @@ bge_attach(dev) bzero(sc->bge_rdata, sizeof(struct bge_ring_data)); - /* Try to allocate memory for jumbo buffers. */ - if (bge_alloc_jumbo_mem(sc)) { - printf("bge%d: jumbo buffer allocation " - "failed\n", sc->bge_unit); - bge_release_resources(sc); - error = ENXIO; - goto fail; + /* Save ASIC rev. */ + + sc->bge_chipid = + pci_read_config(dev, BGE_PCI_MISC_CTL, 4) & + BGE_PCIMISCCTL_ASICREV; + sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid); + sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid); + + /* + * Try to allocate memory for jumbo buffers. + * The 5705 does not appear to support jumbo frames. + */ + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) { + if (bge_alloc_jumbo_mem(sc)) { + printf("bge%d: jumbo buffer allocation " + "failed\n", sc->bge_unit); + bge_release_resources(sc); + error = ENXIO; + goto fail; + } } /* Set default tuneable values. */ @@ -1631,6 +1696,12 @@ bge_attach(dev) sc->bge_rx_max_coal_bds = 64; sc->bge_tx_max_coal_bds = 128; + /* 5705 limits RX return ring to 512 entries. */ + if (sc->bge_asicrev == BGE_ASICREV_BCM5705) + sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT_5705; + else + sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT; + /* Set up ifnet structure */ ifp = &sc->arpcom.ac_if; ifp->if_softc = sc; @@ -1645,17 +1716,10 @@ bge_attach(dev) ifp->if_mtu = ETHERMTU; ifp->if_snd.ifq_maxlen = BGE_TX_RING_CNT - 1; ifp->if_hwassist = BGE_CSUM_FEATURES; - ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU; + ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_VLAN_HWTAGGING | + IFCAP_VLAN_MTU; ifp->if_capenable = ifp->if_capabilities; - /* Save ASIC rev. */ - - sc->bge_chipid = - pci_read_config(dev, BGE_PCI_MISC_CTL, 4) & - BGE_PCIMISCCTL_ASICREV; - sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid); - sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid); - /* * Figure out what sort of media we have by checking the * hardware config word in the first 32k of NIC internal memory, @@ -1760,7 +1824,8 @@ bge_detach(dev) } bge_release_resources(sc); - bge_free_jumbo_mem(sc); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + bge_free_jumbo_mem(sc); splx(s); @@ -1869,7 +1934,8 @@ bge_reset(sc) } /* Enable memory arbiter. */ - CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); /* Fix up byte swapping */ CSR_WRITE_4(sc, BGE_MODE_CTL, BGE_MODECTL_BYTESWAP_NONFRAME| @@ -1913,7 +1979,7 @@ bge_rxeof(sc) &sc->bge_rdata->bge_rx_return_ring[sc->bge_rx_saved_considx]; rxidx = cur_rx->bge_idx; - BGE_INC(sc->bge_rx_saved_considx, BGE_RETURN_RING_CNT); + BGE_INC(sc->bge_rx_saved_considx, sc->bge_return_ring_cnt); if (cur_rx->bge_flags & BGE_RXBDFLAG_VLAN_TAG) { have_tag = 1; @@ -2109,7 +2175,8 @@ bge_intr(xsc) } /* Clear the interrupt */ CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED| - BGE_MACSTAT_CFG_CHANGED); + BGE_MACSTAT_CFG_CHANGED|BGE_MACSTAT_MI_COMPLETE| + BGE_MACSTAT_LINK_CHANGED); /* Force flush the status block cached by PCI bridge */ CSR_READ_4(sc, BGE_MBX_IRQ0_LO); @@ -2150,7 +2217,10 @@ bge_tick(xsc) s = splimp(); - bge_stats_update(sc); + if (sc->bge_asicrev == BGE_ASICREV_BCM5705) + bge_stats_update_regs(sc); + else + bge_stats_update(sc); sc->bge_stat_ch = timeout(bge_tick, sc, hz); if (sc->bge_link) { splx(s); @@ -2191,6 +2261,33 @@ bge_tick(xsc) } static void +bge_stats_update_regs(sc) + struct bge_softc *sc; +{ + struct ifnet *ifp; + struct bge_mac_stats_regs stats; + u_int32_t *s; + int i; + + ifp = &sc->arpcom.ac_if; + + s = (u_int32_t *)&stats; + for (i = 0; i < sizeof(struct bge_mac_stats_regs); i += 4) { + *s = CSR_READ_4(sc, BGE_RX_STATS + i); + s++; + } + + ifp->if_collisions += + (stats.dot3StatsSingleCollisionFrames + + stats.dot3StatsMultipleCollisionFrames + + stats.dot3StatsExcessiveCollisions + + stats.dot3StatsLateCollisions) - + ifp->if_collisions; + + return; +} + +static void bge_stats_update(sc) struct bge_softc *sc; { @@ -2203,10 +2300,10 @@ bge_stats_update(sc) BGE_MEMWIN_START + BGE_STATS_BLOCK); ifp->if_collisions += - (stats->dot3StatsSingleCollisionFrames.bge_addr_lo + - stats->dot3StatsMultipleCollisionFrames.bge_addr_lo + - stats->dot3StatsExcessiveCollisions.bge_addr_lo + - stats->dot3StatsLateCollisions.bge_addr_lo) - + (stats->txstats.dot3StatsSingleCollisionFrames.bge_addr_lo + + stats->txstats.dot3StatsMultipleCollisionFrames.bge_addr_lo + + stats->txstats.dot3StatsExcessiveCollisions.bge_addr_lo + + stats->txstats.dot3StatsLateCollisions.bge_addr_lo) - ifp->if_collisions; #ifdef notdef @@ -2431,6 +2528,24 @@ bge_init(xsc) /* Init RX ring. */ bge_init_rx_ring_std(sc); + /* + * Workaround for a bug in 5705 ASIC rev A0. Poll the NIC's + * memory to insure that the chip has in fact read the first + * entry of the ring. + */ + if (sc->bge_chipid == BGE_CHIPID_BCM5705_A0) { + u_int32_t v, i; + for (i = 0; i < 10; i++) { + DELAY(20); + v = bge_readmem_ind(sc, BGE_STD_RX_RINGS + 8); + if (v == (MCLBYTES - ETHER_ALIGN)) + break; + } + if (i == 10) + printf ("bge%d: 5705 A0 chip failed to load RX ring\n", + sc->bge_unit); + } + /* Init jumbo RX ring. */ if (ifp->if_mtu > (ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN)) bge_init_rx_ring_jumbo(sc); @@ -2566,7 +2681,9 @@ bge_ioctl(ifp, command, data) switch(command) { case SIOCSIFMTU: - if (ifr->ifr_mtu > BGE_JUMBO_MTU) + /* Disallow jumbo frames on 5705. */ + if ((sc->bge_asicrev == BGE_ASICREV_BCM5705 && + ifr->ifr_mtu > ETHERMTU) || ifr->ifr_mtu > BGE_JUMBO_MTU) error = EINVAL; else { ifp->if_mtu = ifr->ifr_mtu; @@ -2686,7 +2803,8 @@ bge_stop(sc) BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_ENABLE); BGE_CLRBIT(sc, BGE_RBDI_MODE, BGE_RBDIMODE_ENABLE); BGE_CLRBIT(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); - BGE_CLRBIT(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + BGE_CLRBIT(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE); BGE_CLRBIT(sc, BGE_RDBDI_MODE, BGE_RBDIMODE_ENABLE); BGE_CLRBIT(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE); BGE_CLRBIT(sc, BGE_RBDC_MODE, BGE_RBDCMODE_ENABLE); @@ -2699,7 +2817,8 @@ bge_stop(sc) BGE_CLRBIT(sc, BGE_SDI_MODE, BGE_SDIMODE_ENABLE); BGE_CLRBIT(sc, BGE_RDMA_MODE, BGE_RDMAMODE_ENABLE); BGE_CLRBIT(sc, BGE_SDC_MODE, BGE_SDCMODE_ENABLE); - BGE_CLRBIT(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + BGE_CLRBIT(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE); BGE_CLRBIT(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); /* @@ -2708,11 +2827,14 @@ bge_stop(sc) */ BGE_CLRBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE); BGE_CLRBIT(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE); - BGE_CLRBIT(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + BGE_CLRBIT(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE); CSR_WRITE_4(sc, BGE_FTQ_RESET, 0xFFFFFFFF); CSR_WRITE_4(sc, BGE_FTQ_RESET, 0); - BGE_CLRBIT(sc, BGE_BMAN_MODE, BGE_BMANMODE_ENABLE); - BGE_CLRBIT(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) { + BGE_CLRBIT(sc, BGE_BMAN_MODE, BGE_BMANMODE_ENABLE); + BGE_CLRBIT(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); + } /* Disable host interrupts. */ BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR); @@ -2727,7 +2849,8 @@ bge_stop(sc) bge_free_rx_ring_std(sc); /* Free jumbo RX list. */ - bge_free_rx_ring_jumbo(sc); + if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + bge_free_rx_ring_jumbo(sc); /* Free TX buffers. */ bge_free_tx_ring(sc); |