summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2003-07-16 00:09:56 +0000
committerwpaul <wpaul@FreeBSD.org>2003-07-16 00:09:56 +0000
commite611c416998a4d947f82577fc6d0507a5dbd56f0 (patch)
treef818757ae33508b65cd8a7c6e007210e8174151c
parenta54595f215d4214fd4bf8611ab2de5ebb1cc5f69 (diff)
downloadFreeBSD-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.c327
-rw-r--r--sys/dev/bge/if_bgereg.h82
-rw-r--r--sys/dev/mii/brgphy.c26
-rw-r--r--sys/dev/mii/miidevs1
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
OpenPOWER on IntegriCloud