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 | |
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')
-rw-r--r-- | sys/dev/bge/if_bge.c | 327 | ||||
-rw-r--r-- | sys/dev/bge/if_bgereg.h | 82 |
2 files changed, 298 insertions, 111 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); diff --git a/sys/dev/bge/if_bgereg.h b/sys/dev/bge/if_bgereg.h index 3670ce8..4ec9541 100644 --- a/sys/dev/bge/if_bgereg.h +++ b/sys/dev/bge/if_bgereg.h @@ -229,6 +229,10 @@ #define BGE_CHIPID_BCM5704_A0 0x20000000 #define BGE_CHIPID_BCM5704_A1 0x20010000 #define BGE_CHIPID_BCM5704_A2 0x20020000 +#define BGE_CHIPID_BCM5705_A0 0x30000000 +#define BGE_CHIPID_BCM5705_A1 0x30010000 +#define BGE_CHIPID_BCM5705_A2 0x30020000 +#define BGE_CHIPID_BCM5705_A3 0x30030000 /* shorthand one */ #define BGE_ASICREV(x) ((x) >> 28) @@ -236,6 +240,7 @@ #define BGE_ASICREV_BCM5701 0x00 #define BGE_ASICREV_BCM5703 0x01 #define BGE_ASICREV_BCM5704 0x02 +#define BGE_ASICREV_BCM5705 0x03 /* chip revisions */ #define BGE_CHIPREV(x) ((x) >> 24) @@ -1801,10 +1806,16 @@ struct bge_status_block { #define BCOM_VENDORID 0x14E4 #define BCOM_DEVICEID_BCM5700 0x1644 #define BCOM_DEVICEID_BCM5701 0x1645 -#define BCOM_DEVICEID_BCM5702X 0x16A6 -#define BCOM_DEVICEID_BCM5703X 0x16A7 +#define BCOM_DEVICEID_BCM5702 0x16A6 +#define BCOM_DEVICEID_BCM5702X 0x16C6 +#define BCOM_DEVICEID_BCM5703 0x16A7 +#define BCOM_DEVICEID_BCM5703X 0x16C7 #define BCOM_DEVICEID_BCM5704C 0x1648 #define BCOM_DEVICEID_BCM5704S 0x16A8 +#define BCOM_DEVICEID_BCM5705 0x1653 +#define BCOM_DEVICEID_BCM5705M 0x165D +#define BCOM_DEVICEID_BCM5705M_ALT 0x165E +#define BCOM_DEVICEID_BCM5782 0x1696 /* * Alteon AceNIC PCI vendor/device ID. @@ -1873,6 +1884,10 @@ struct bge_status_block { #define BGE_MINI_RX_RING_CNT 1024 #define BGE_RETURN_RING_CNT 1024 +/* 5705 has smaller return ring size */ + +#define BGE_RETURN_RING_CNT_5705 512 + /* * Possible TX ring sizes. */ @@ -1891,10 +1906,8 @@ struct bge_status_block { /* * Tigon III statistics counters. */ -struct bge_stats { - u_int8_t Reserved0[256]; - - /* Statistics maintained by Receive MAC. */ +/* Statistics maintained MAC Receive block. */ +struct bge_rx_mac_stats { bge_hostaddr ifHCInOctets; bge_hostaddr Reserved1; bge_hostaddr etherStatsFragments; @@ -1922,10 +1935,11 @@ struct bge_stats { bge_hostaddr etherStatsPkts2048Octetsto4095Octets; bge_hostaddr etherStatsPkts4096Octetsto8191Octets; bge_hostaddr etherStatsPkts8192Octetsto9022Octets; +}; - bge_hostaddr Unused1[37]; - /* Statistics maintained by Transmit MAC. */ +/* Statistics maintained MAC Transmit block. */ +struct bge_tx_mac_stats { bge_hostaddr ifHCOutOctets; bge_hostaddr Reserved2; bge_hostaddr etherStatsCollisions; @@ -1959,6 +1973,55 @@ struct bge_stats { bge_hostaddr dot3StatsCarrierSenseErrors; bge_hostaddr ifOutDiscards; bge_hostaddr ifOutErrors; +}; + +/* Stats counters access through registers */ +struct bge_mac_stats_regs { + u_int32_t ifHCOutOctets; + u_int32_t Reserved0; + u_int32_t etherStatsCollisions; + u_int32_t outXonSent; + u_int32_t outXoffSent; + u_int32_t Reserved1; + u_int32_t dot3StatsInternalMacTransmitErrors; + u_int32_t dot3StatsSingleCollisionFrames; + u_int32_t dot3StatsMultipleCollisionFrames; + u_int32_t dot3StatsDeferredTransmissions; + u_int32_t Reserved2; + u_int32_t dot3StatsExcessiveCollisions; + u_int32_t dot3StatsLateCollisions; + u_int32_t Reserved3[14]; + u_int32_t ifHCOutUcastPkts; + u_int32_t ifHCOutMulticastPkts; + u_int32_t ifHCOutBroadcastPkts; + u_int32_t Reserved4[2]; + u_int32_t ifHCInOctets; + u_int32_t Reserved5; + u_int32_t etherStatsFragments; + u_int32_t ifHCInUcastPkts; + u_int32_t ifHCInMulticastPkts; + u_int32_t ifHCInBroadcastPkts; + u_int32_t dot3StatsFCSErrors; + u_int32_t dot3StatsAlignmentErrors; + u_int32_t xonPauseFramesReceived; + u_int32_t xoffPauseFramesReceived; + u_int32_t macControlFramesReceived; + u_int32_t xoffStateEntered; + u_int32_t dot3StatsFramesTooLong; + u_int32_t etherStatsJabbers; + u_int32_t etherStatsUndersizePkts; +}; + +struct bge_stats { + u_int8_t Reserved0[256]; + + /* Statistics maintained by Receive MAC. */ + struct bge_rx_mac_stats rxstats; + + bge_hostaddr Unused1[37]; + + /* Statistics maintained by Transmit MAC. */ + struct bge_tx_mac_stats txstats; bge_hostaddr Unused2[31]; @@ -2118,7 +2181,7 @@ struct bge_type { #define BGE_HWREV_TIGON 0x01 #define BGE_HWREV_TIGON_II 0x02 -#define BGE_TIMEOUT 1000 +#define BGE_TIMEOUT 100000 #define BGE_TXCONS_UNSET 0xFFFF /* impossible value */ struct bge_jpool_entry { @@ -2154,6 +2217,7 @@ struct bge_softc { u_int16_t bge_tx_saved_considx; u_int16_t bge_rx_saved_considx; u_int16_t bge_ev_saved_considx; + u_int16_t bge_return_ring_cnt; u_int16_t bge_std; /* current std ring head */ u_int16_t bge_jumbo; /* current jumo ring head */ SLIST_HEAD(__bge_jfreehead, bge_jpool_entry) bge_jfree_listhead; |