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 | |
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.)
-rw-r--r-- | sys/dev/bge/if_bge.c | 327 | ||||
-rw-r--r-- | sys/dev/bge/if_bgereg.h | 82 | ||||
-rw-r--r-- | sys/dev/mii/brgphy.c | 26 | ||||
-rw-r--r-- | sys/dev/mii/miidevs | 1 |
4 files changed, 325 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; diff --git a/sys/dev/mii/brgphy.c b/sys/dev/mii/brgphy.c index 614d0af..9f6ed9c 100644 --- a/sys/dev/mii/brgphy.c +++ b/sys/dev/mii/brgphy.c @@ -54,6 +54,9 @@ __FBSDID("$FreeBSD$"); #include "miidevs.h" #include <dev/mii/brgphyreg.h> +#include <net/if_arp.h> +#include <machine/bus.h> +#include <dev/bge/if_bgereg.h> #include "miibus_if.h" @@ -133,6 +136,12 @@ brgphy_probe(dev) return(0); } + if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM && + MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5705) { + device_set_desc(dev, MII_STR_xxBROADCOM_BCM5705); + return(0); + } + return(ENXIO); } @@ -552,6 +561,8 @@ static void brgphy_reset(struct mii_softc *sc) { u_int32_t val; + struct ifnet *ifp; + struct bge_softc *bge_sc; mii_phy_reset(sc); @@ -570,6 +581,21 @@ brgphy_reset(struct mii_softc *sc) break; } + ifp = sc->mii_pdata->mii_ifp; + bge_sc = ifp->if_softc; + + /* + * Don't enable Ethernet@WireSpeed for the 5700 or the + * 5705 A1 and A2 chips. Make sure we only do this test + * on "bge" NICs, since other drivers may use this same + * PHY subdriver. + */ + if (strcmp(ifp->if_name, "bge") == 0 && + (bge_sc->bge_asicrev == BGE_ASICREV_BCM5700 || + bge_sc->bge_chipid == BGE_CHIPID_BCM5705_A1 || + bge_sc->bge_chipid == BGE_CHIPID_BCM5705_A2)) + return; + /* Enable Ethernet@WireSpeed. */ PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007); val = PHY_READ(sc, BRGPHY_MII_AUXCTL); diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs index 6bac515..d57c890 100644 --- a/sys/dev/mii/miidevs +++ b/sys/dev/mii/miidevs @@ -116,6 +116,7 @@ model xxBROADCOM BCM5411 0x0007 BCM5411 10/100/1000baseTX PHY model xxBROADCOM BCM5701 0x0011 BCM5701 10/100/1000baseTX PHY model xxBROADCOM BCM5703 0x0016 BCM5703 10/100/1000baseTX PHY model xxBROADCOM BCM5704 0x0019 BCM5704 10/100/1000baseTX PHY +model xxBROADCOM BCM5705 0x001a BCM5705 10/100/1000baseTX PHY /* Davicom Semiconductor PHYs */ model xxDAVICOM DM9101 0x0000 DM9101 10/100 media interface |