From 726bef9a9bb9b1c740f3965f5a37cbd1634b0bd9 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Mon, 7 May 2007 04:54:32 +0000 Subject: [PATCH] Add new devices support for bge(4) - Recognize more devices, including PCI ids, chip ids and asic ids. - Use meaningful macros to distinguish chip family and capability, instead of test against chip id or asic id directly. - Pack bool fields of bge_softc into bge_softc.bge_flags, o bge_softc.bge_extram is gone, which was never adopted. o Add flags for jumbo frame capability. o Add flags for various chip families. o Add flags for the bus types (PCI-e/PCI-X). o Add flags for various PHY bugs, which will be used by brgphy. - Fix the detection of the bus type (PCI-e/PCI-X). (*) - Properly initialize PCI-X bge(4). - Fix support for certain 575x/578x chips (*): o Correct bge_{read,write}mem_ind() by clearing BGE_PCI_MEMWIN_BASEADDR before returning. o Use the appropriate register writing method when reseting the chip. o Program the descriptor DMA engine correctly. o Disable fastboot if the chips support it. o Add some 'magical' magics on chip resetting path. Obtained-from: FreeBSD # (*) are done in if_bge.c rev 1.159 and 1.178 by scottl@freebsd.org and # jkim@freebsd.org, based on code provided by David Christenson from Broadcom. Adapt brgphy to work with the changes in bge(4) - Recognize Broadcom 5755/5787 PHY. - Add DSP code for various PHY bug workarounds. - Detect PHY bugs based on the flags passed by bge(4) and load corresponding workaround DSP code. Obtained-from: OpenBSD - Set PHY jumbo frame settings. Obtained-from: FreeBSD --- sys/dev/netif/bge/if_bge.c | 514 +++++++++++++++++++++++------------- sys/dev/netif/bge/if_bgereg.h | 86 ++++-- sys/dev/netif/mii_layer/brgphy.c | 216 +++++++++------ sys/dev/netif/mii_layer/brgphyreg.h | 5 +- 4 files changed, 547 insertions(+), 274 deletions(-) diff --git a/sys/dev/netif/bge/if_bge.c b/sys/dev/netif/bge/if_bge.c index 04facfb383..e8040a0123 100644 --- a/sys/dev/netif/bge/if_bge.c +++ b/sys/dev/netif/bge/if_bge.c @@ -31,7 +31,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/bge/if_bge.c,v 1.3.2.39 2005/07/03 03:41:18 silby Exp $ - * $DragonFly: src/sys/dev/netif/bge/if_bge.c,v 1.74 2007/05/03 14:09:22 sephe Exp $ + * $DragonFly: src/sys/dev/netif/bge/if_bge.c,v 1.75 2007/05/07 04:54:32 sephe Exp $ * */ @@ -119,18 +119,36 @@ #define BGE_DEVDESC_MAX 64 /* Maximum device description length */ static struct bge_type bge_devs[] = { + { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C996, + "3COM 3C996 Gigabit Ethernet" }, + { PCI_VENDOR_ALTEON, PCI_PRODUCT_ALTEON_BCM5700, "Alteon BCM5700 Gigabit Ethernet" }, { PCI_VENDOR_ALTEON, PCI_PRODUCT_ALTEON_BCM5701, "Alteon BCM5701 Gigabit Ethernet" }, + + { PCI_VENDOR_ALTIMA, PCI_PRODUCT_ALTIMA_AC1000, + "Altima AC1000 Gigabit Ethernet" }, + { PCI_VENDOR_ALTIMA, PCI_PRODUCT_ALTIMA_AC1001, + "Altima AC1002 Gigabit Ethernet" }, + { PCI_VENDOR_ALTIMA, PCI_PRODUCT_ALTIMA_AC9100, + "Altima AC9100 Gigabit Ethernet" }, + + { PCI_VENDOR_APPLE, PCI_PRODUCT_APPLE_BCM5701, + "Apple BCM5701 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5700, "Broadcom BCM5700 Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5701, "Broadcom BCM5701 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5702, + "Broadcom BCM5702 Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5702X, "Broadcom BCM5702X Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5702_ALT, "Broadcom BCM5702 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5703, + "Broadcom BCM5703 Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5703X, "Broadcom BCM5703X Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5703A3, @@ -139,8 +157,12 @@ static struct bge_type bge_devs[] = { "Broadcom BCM5704C Dual Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5704S, "Broadcom BCM5704S Dual Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5704S_ALT, + "Broadcom BCM5704S Dual Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5705, "Broadcom BCM5705 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5705F, + "Broadcom BCM5705F Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5705K, "Broadcom BCM5705K Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5705M, @@ -149,20 +171,64 @@ static struct bge_type bge_devs[] = { "Broadcom BCM5705M Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5714, "Broadcom BCM5714C Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5714S, + "Broadcom BCM5714S Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5715, + "Broadcom BCM5715 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5715S, + "Broadcom BCM5715S Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5720, + "Broadcom BCM5720 Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5721, "Broadcom BCM5721 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5722, + "Broadcom BCM5722 Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5750, "Broadcom BCM5750 Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5750M, "Broadcom BCM5750M Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5751, "Broadcom BCM5751 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5751F, + "Broadcom BCM5751F Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5751M, "Broadcom BCM5751M Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5752, "Broadcom BCM5752 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5752M, + "Broadcom BCM5752M Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5753, + "Broadcom BCM5753 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5753F, + "Broadcom BCM5753F Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5753M, + "Broadcom BCM5753M Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5754, + "Broadcom BCM5754 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5754M, + "Broadcom BCM5754M Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5755, + "Broadcom BCM5755 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5755M, + "Broadcom BCM5755M Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5756, + "Broadcom BCM5756 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5780, + "Broadcom BCM5780 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5780S, + "Broadcom BCM5780S Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5781, + "Broadcom BCM5781 Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5782, "Broadcom BCM5782 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5786, + "Broadcom BCM5786 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5787, + "Broadcom BCM5787 Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5787F, + "Broadcom BCM5787F Gigabit Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5787M, + "Broadcom BCM5787M Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5788, "Broadcom BCM5788 Gigabit Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5789, @@ -171,17 +237,21 @@ static struct bge_type bge_devs[] = { "Broadcom BCM5901 Fast Ethernet" }, { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5901A2, "Broadcom BCM5901A2 Fast Ethernet" }, + { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5903M, + "Broadcom BCM5903M Fast Ethernet" }, + { PCI_VENDOR_SCHNEIDERKOCH, PCI_PRODUCT_SCHNEIDERKOCH_SK_9DX1, "SysKonnect Gigabit Ethernet" }, - { PCI_VENDOR_ALTIMA, PCI_PRODUCT_ALTIMA_AC1000, - "Altima AC1000 Gigabit Ethernet" }, - { PCI_VENDOR_ALTIMA, PCI_PRODUCT_ALTIMA_AC1001, - "Altima AC1002 Gigabit Ethernet" }, - { PCI_VENDOR_ALTIMA, PCI_PRODUCT_ALTIMA_AC9100, - "Altima AC9100 Gigabit Ethernet" }, + { 0, 0, NULL } }; +#define BGE_IS_JUMBO_CAPABLE(sc) ((sc)->bge_flags & BGE_FLAG_JUMBO) +#define BGE_IS_5700_FAMILY(sc) ((sc)->bge_flags & BGE_FLAG_5700_FAMILY) +#define BGE_IS_5705_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_5705_PLUS) +#define BGE_IS_5714_FAMILY(sc) ((sc)->bge_flags & BGE_FLAG_5714_FAMILY) +#define BGE_IS_575X_PLUS(sc) ((sc)->bge_flags & BGE_FLAG_575X_PLUS) + static int bge_probe(device_t); static int bge_attach(device_t); static int bge_detach(device_t); @@ -236,6 +306,7 @@ static void bge_writemem_ind(struct bge_softc *, uint32_t, uint32_t); static uint32_t bge_readreg_ind(struct bge_softc *, uint32_t); #endif static void bge_writereg_ind(struct bge_softc *, uint32_t, uint32_t); +static void bge_writemem_direct(struct bge_softc *, uint32_t, uint32_t); static int bge_miibus_readreg(device_t, int, int); static int bge_miibus_writereg(device_t, int, int, int); @@ -295,9 +366,12 @@ static uint32_t bge_readmem_ind(struct bge_softc *sc, uint32_t off) { device_t dev = sc->bge_dev; + uint32_t val; pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, off, 4); - return(pci_read_config(dev, BGE_PCI_MEMWIN_DATA, 4)); + val = pci_read_config(dev, BGE_PCI_MEMWIN_DATA, 4); + pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, 0, 4); + return (val); } static void @@ -307,6 +381,7 @@ bge_writemem_ind(struct bge_softc *sc, uint32_t off, uint32_t val) pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, off, 4); pci_write_config(dev, BGE_PCI_MEMWIN_DATA, val, 4); + pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, 0, 4); } #ifdef notdef @@ -329,6 +404,12 @@ bge_writereg_ind(struct bge_softc *sc, uint32_t off, uint32_t val) pci_write_config(dev, BGE_PCI_REG_DATA, val, 4); } +static void +bge_writemem_direct(struct bge_softc *sc, uint32_t off, uint32_t val) +{ + CSR_WRITE_4(sc, off, val); +} + /* * Read a byte of data stored in the EEPROM at address 'addr.' The * BCM570x supports both the traditional bitbang interface and an @@ -704,7 +785,7 @@ bge_newbuf_std(struct bge_softc *sc, int i, struct mbuf *m) } m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - if (!sc->bge_rx_alignment_bug) + if ((sc->bge_flags & BGE_FLAG_RX_ALIGNBUG) == 0) m_adj(m_new, ETHER_ALIGN); ctx.bge_maxsegs = 1; @@ -778,7 +859,7 @@ bge_newbuf_jumbo(struct bge_softc *sc, int i, struct mbuf *m) m_new->m_len = m_new->m_pkthdr.len = m_new->m_ext.ext_size; paddr = buf->bge_paddr; - if (!sc->bge_rx_alignment_bug) { + if ((sc->bge_flags & BGE_FLAG_RX_ALIGNBUG) == 0) { m_adj(m_new, ETHER_ALIGN); paddr += ETHER_ALIGN; } @@ -992,33 +1073,37 @@ bge_chipinit(struct bge_softc *sc) BGE_MEMWIN_WRITE(sc, i, 0); /* Set up the PCI DMA control register. */ - if (sc->bge_pcie) { + if (sc->bge_flags & BGE_FLAG_PCIE) { /* PCI Express */ dma_rw_ctl = BGE_PCI_READ_CMD|BGE_PCI_WRITE_CMD | (0xf << BGE_PCIDMARWCTL_RD_WAT_SHIFT) | (0x2 << BGE_PCIDMARWCTL_WR_WAT_SHIFT); - } else if (pci_read_config(sc->bge_dev, BGE_PCI_PCISTATE, 4) & - BGE_PCISTATE_PCI_BUSMODE) { - /* Conventional PCI bus */ - dma_rw_ctl = BGE_PCI_READ_CMD|BGE_PCI_WRITE_CMD | - (0x7 << BGE_PCIDMARWCTL_RD_WAT_SHIFT) | - (0x7 << BGE_PCIDMARWCTL_WR_WAT_SHIFT) | - (0x0F); - } else { + } else if (sc->bge_flags & BGE_FLAG_PCIX) { /* PCI-X bus */ - /* - * The 5704 uses a different encoding of read/write - * watermarks. - */ - if (sc->bge_asicrev == BGE_ASICREV_BCM5704) + if (BGE_IS_5714_FAMILY(sc)) { + dma_rw_ctl = BGE_PCI_READ_CMD|BGE_PCI_WRITE_CMD; + dma_rw_ctl &= ~BGE_PCIDMARWCTL_ONEDMA_ATONCE; /* XXX */ + /* XXX magic values, Broadcom-supplied Linux driver */ + if (sc->bge_asicrev == BGE_ASICREV_BCM5780) { + dma_rw_ctl |= (1 << 20) | (1 << 18) | + BGE_PCIDMARWCTL_ONEDMA_ATONCE; + } else { + dma_rw_ctl |= (1 << 20) | (1 << 18) | (1 << 15); + } + } else if (sc->bge_asicrev == BGE_ASICREV_BCM5704) { + /* + * The 5704 uses a different encoding of read/write + * watermarks. + */ dma_rw_ctl = BGE_PCI_READ_CMD|BGE_PCI_WRITE_CMD | (0x7 << BGE_PCIDMARWCTL_RD_WAT_SHIFT) | (0x3 << BGE_PCIDMARWCTL_WR_WAT_SHIFT); - else + } else { dma_rw_ctl = BGE_PCI_READ_CMD|BGE_PCI_WRITE_CMD | (0x3 << BGE_PCIDMARWCTL_RD_WAT_SHIFT) | (0x3 << BGE_PCIDMARWCTL_WR_WAT_SHIFT) | (0x0F); + } /* * 5703 and 5704 need ONEDMA_AT_ONCE as a workaround @@ -1032,12 +1117,17 @@ bge_chipinit(struct bge_softc *sc) if (tmp == 0x6 || tmp == 0x7) dma_rw_ctl |= BGE_PCIDMARWCTL_ONEDMA_ATONCE; } + } else { + /* Conventional PCI bus */ + dma_rw_ctl = BGE_PCI_READ_CMD|BGE_PCI_WRITE_CMD | + (0x7 << BGE_PCIDMARWCTL_RD_WAT_SHIFT) | + (0x7 << BGE_PCIDMARWCTL_WR_WAT_SHIFT) | + (0x0F); } if (sc->bge_asicrev == BGE_ASICREV_BCM5703 || sc->bge_asicrev == BGE_ASICREV_BCM5704 || - sc->bge_asicrev == BGE_ASICREV_BCM5705 || - sc->bge_asicrev == BGE_ASICREV_BCM5750) + 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); @@ -1066,6 +1156,7 @@ bge_blockinit(struct bge_softc *sc) struct bge_rcb *rcb; bus_size_t vrcb; bge_hostaddr taddr; + uint32_t val; int i; /* @@ -1078,24 +1169,13 @@ bge_blockinit(struct bge_softc *sc) /* Note: the BCM5704 has a smaller mbuf space than other chips. */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) { + if (!BGE_IS_5705_PLUS(sc)) { /* Configure mbuf memory pool */ - if (sc->bge_extram) { - CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_BASEADDR, - BGE_EXT_SSRAM); - if (sc->bge_asicrev == BGE_ASICREV_BCM5704) - CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_LEN, 0x10000); - else - CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_LEN, 0x18000); - } else { - CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_BASEADDR, - BGE_BUFFPOOL_1); - if (sc->bge_asicrev == BGE_ASICREV_BCM5704) - CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_LEN, 0x10000); - else - CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_LEN, 0x18000); - } + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_BASEADDR, BGE_BUFFPOOL_1); + if (sc->bge_asicrev == BGE_ASICREV_BCM5704) + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_LEN, 0x10000); + else + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_LEN, 0x18000); /* Configure DMA resource pool */ CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_BASEADDR, @@ -1104,8 +1184,7 @@ bge_blockinit(struct bge_softc *sc) } /* Configure mbuf pool watermarks */ - if (sc->bge_asicrev == BGE_ASICREV_BCM5705 || - sc->bge_asicrev == BGE_ASICREV_BCM5750) { + if (BGE_IS_5705_PLUS(sc)) { CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x10); } else { @@ -1119,8 +1198,7 @@ bge_blockinit(struct bge_softc *sc) CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_HIWAT, 10); /* Enable buffer manager */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) { + if (!BGE_IS_5705_PLUS(sc)) { CSR_WRITE_4(sc, BGE_BMAN_MODE, BGE_BMANMODE_ENABLE|BGE_BMANMODE_LOMBUF_ATTN); @@ -1163,16 +1241,12 @@ bge_blockinit(struct bge_softc *sc) BGE_ADDR_HI(sc->bge_ldata.bge_rx_std_ring_paddr); bus_dmamap_sync(sc->bge_cdata.bge_rx_std_ring_tag, sc->bge_cdata.bge_rx_std_ring_map, BUS_DMASYNC_PREREAD); - if (sc->bge_asicrev == BGE_ASICREV_BCM5705 || - sc->bge_asicrev == BGE_ASICREV_BCM5750) + if (BGE_IS_5705_PLUS(sc)) 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 - rcb->bge_nicaddr = BGE_STD_RX_RINGS; + rcb->bge_nicaddr = BGE_STD_RX_RINGS; CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_HI, rcb->bge_hostaddr.bge_addr_hi); CSR_WRITE_4(sc, BGE_RX_STD_RCB_HADDR_LO, rcb->bge_hostaddr.bge_addr_lo); CSR_WRITE_4(sc, BGE_RX_STD_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags); @@ -1185,8 +1259,7 @@ bge_blockinit(struct bge_softc *sc) * using this ring (i.e. once we set the MTU * high enough to require it). */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) { + if (BGE_IS_JUMBO_CAPABLE(sc)) { rcb = &sc->bge_ldata.bge_info.bge_jumbo_rx_rcb; rcb->bge_hostaddr.bge_addr_lo = @@ -1199,10 +1272,7 @@ bge_blockinit(struct bge_softc *sc) 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; + 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, @@ -1224,7 +1294,11 @@ bge_blockinit(struct bge_softc *sc) * values are 1/8th the number of descriptors allocated to * each ring. */ - CSR_WRITE_4(sc, BGE_RBDI_STD_REPL_THRESH, BGE_STD_RX_RING_CNT/8); + if (BGE_IS_5705_PLUS(sc)) + val = 8; + else + val = BGE_STD_RX_RING_CNT / 8; + CSR_WRITE_4(sc, BGE_RBDI_STD_REPL_THRESH, val); CSR_WRITE_4(sc, BGE_RBDI_JUMBO_REPL_THRESH, BGE_JUMBO_RX_RING_CNT/8); /* @@ -1247,8 +1321,7 @@ bge_blockinit(struct bge_softc *sc) RCB_WRITE_4(sc, vrcb, bge_hostaddr.bge_addr_lo, taddr.bge_addr_lo); RCB_WRITE_4(sc, vrcb, bge_nicaddr, BGE_NIC_TXRING_ADDR(0, BGE_TX_RING_CNT)); - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) { + if (!BGE_IS_5705_PLUS(sc)) { RCB_WRITE_4(sc, vrcb, bge_maxlen_flags, BGE_RCB_MAXLEN_FLAGS(BGE_TX_RING_CNT, 0)); } @@ -1333,8 +1406,7 @@ bge_blockinit(struct bge_softc *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); - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) { + if (!BGE_IS_5705_PLUS(sc)) { CSR_WRITE_4(sc, BGE_HCC_RX_COAL_TICKS_INT, 0); CSR_WRITE_4(sc, BGE_HCC_TX_COAL_TICKS_INT, 0); } @@ -1342,8 +1414,7 @@ bge_blockinit(struct bge_softc *sc) CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 0); /* Set up address of statistics block */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) { + if (!BGE_IS_5705_PLUS(sc)) { CSR_WRITE_4(sc, BGE_HCC_STATS_ADDR_HI, BGE_ADDR_HI(sc->bge_ldata.bge_stats_paddr)); CSR_WRITE_4(sc, BGE_HCC_STATS_ADDR_LO, @@ -1373,8 +1444,7 @@ bge_blockinit(struct bge_softc *sc) CSR_WRITE_4(sc, BGE_RXLP_MODE, BGE_RXLPMODE_ENABLE); /* Turn on RX list selector state machine. */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) + if (!BGE_IS_5705_PLUS(sc)) CSR_WRITE_4(sc, BGE_RXLS_MODE, BGE_RXLSMODE_ENABLE); /* Turn on DMA, clear stats */ @@ -1382,7 +1452,8 @@ bge_blockinit(struct bge_softc *sc) BGE_MACMODE_RXDMA_ENB|BGE_MACMODE_RX_STATS_CLEAR| BGE_MACMODE_TX_STATS_CLEAR|BGE_MACMODE_RX_STATS_ENB| BGE_MACMODE_TX_STATS_ENB|BGE_MACMODE_FRMHDR_DMA_ENB| - (sc->bge_tbi ? BGE_PORTMODE_TBI : BGE_PORTMODE_MII)); + ((sc->bge_flags & BGE_FLAG_TBI) ? + BGE_PORTMODE_TBI : BGE_PORTMODE_MII)); /* Set misc. local control, enable interrupts on attentions */ CSR_WRITE_4(sc, BGE_MISC_LOCAL_CTL, BGE_MLC_INTR_ONATTN); @@ -1396,13 +1467,15 @@ bge_blockinit(struct bge_softc *sc) #endif /* Turn on DMA completion state machine */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) + if (!BGE_IS_5705_PLUS(sc)) CSR_WRITE_4(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE); /* Turn on write DMA state machine */ - CSR_WRITE_4(sc, BGE_WDMA_MODE, - BGE_WDMAMODE_ENABLE|BGE_WDMAMODE_ALL_ATTNS); + val = BGE_WDMAMODE_ENABLE|BGE_WDMAMODE_ALL_ATTNS; + if (sc->bge_asicrev == BGE_ASICREV_BCM5755 || + sc->bge_asicrev == BGE_ASICREV_BCM5787) + val |= (1 << 29); /* Enable host coalescing bug fix. */ + CSR_WRITE_4(sc, BGE_WDMA_MODE, val); /* Turn on read DMA state machine */ CSR_WRITE_4(sc, BGE_RDMA_MODE, @@ -1418,8 +1491,7 @@ bge_blockinit(struct bge_softc *sc) CSR_WRITE_4(sc, BGE_RDBDI_MODE, BGE_RDBDIMODE_ENABLE); /* Turn on Mbuf cluster free state machine */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) + if (!BGE_IS_5705_PLUS(sc)) CSR_WRITE_4(sc, BGE_MBCF_MODE, BGE_MBCFMODE_ENABLE); /* Turn on send BD completion state machine */ @@ -1448,7 +1520,7 @@ bge_blockinit(struct bge_softc *sc) CSR_WRITE_4(sc, BGE_MI_STS, 0); /* Enable PHY auto polling (for MII/GMII only) */ - if (sc->bge_tbi) { + if (sc->bge_flags & BGE_FLAG_TBI) { CSR_WRITE_4(sc, BGE_MI_STS, BGE_MISTS_LINK); } else { BGE_SETBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL|10<<16); @@ -1509,7 +1581,7 @@ bge_probe(device_t dev) pci_read_config(dev, BGE_PCI_MISC_CTL, 4) >> 16); device_set_desc_copy(dev, descbuf); if (pci_get_subvendor(dev) == PCI_VENDOR_DELL) - sc->bge_no_3_led = 1; + sc->bge_flags |= BGE_FLAG_NO_3LED; kfree(descbuf, M_TEMP); return(0); } @@ -1547,18 +1619,6 @@ bge_attach(device_t dev) sc->bge_btag = rman_get_bustag(sc->bge_res); sc->bge_bhandle = rman_get_bushandle(sc->bge_res); - /* Allocate interrupt */ - rid = 0; - - sc->bge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - - if (sc->bge_irq == NULL) { - device_printf(dev, "couldn't map interrupt\n"); - error = ENXIO; - goto fail; - } - /* Save ASIC rev. */ sc->bge_chipid = pci_read_config(dev, BGE_PCI_MISC_CTL, 4) & @@ -1566,29 +1626,102 @@ bge_attach(device_t dev) sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid); sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid); - /* - * Treat the 5714 and the 5752 like the 5750 until we have more info - * on this chip. - */ - if (sc->bge_asicrev == BGE_ASICREV_BCM5714 || - sc->bge_asicrev == BGE_ASICREV_BCM5752) - sc->bge_asicrev = BGE_ASICREV_BCM5750; + /* Save chipset family. */ + switch (sc->bge_asicrev) { + case BGE_ASICREV_BCM5700: + case BGE_ASICREV_BCM5701: + case BGE_ASICREV_BCM5703: + case BGE_ASICREV_BCM5704: + sc->bge_flags |= BGE_FLAG_5700_FAMILY | BGE_FLAG_JUMBO; + break; + + case BGE_ASICREV_BCM5714_A0: + case BGE_ASICREV_BCM5780: + case BGE_ASICREV_BCM5714: + sc->bge_flags |= BGE_FLAG_5714_FAMILY; + /* Fall through */ + + case BGE_ASICREV_BCM5750: + case BGE_ASICREV_BCM5752: + case BGE_ASICREV_BCM5755: + case BGE_ASICREV_BCM5787: + sc->bge_flags |= BGE_FLAG_575X_PLUS; + /* Fall through */ + + case BGE_ASICREV_BCM5705: + sc->bge_flags |= BGE_FLAG_5705_PLUS; + break; + } /* - * XXX: Broadcom Linux driver. Not in specs or eratta. - * PCI-Express? + * Set various quirk flags. */ - if (sc->bge_asicrev == BGE_ASICREV_BCM5750) { - uint32_t v; - v = pci_read_config(dev, BGE_PCI_MSI_CAPID, 4); - if (((v >> 8) & 0xff) == BGE_PCIE_MSI_CAPID) { - v = pci_read_config(dev, BGE_PCIE_MSI_CAPID, 4); - if ((v & 0xff) == BGE_PCIE_MSI_CAPID_VAL) - sc->bge_pcie = 1; + sc->bge_flags |= BGE_FLAG_ETH_WIRESPEED; + if (sc->bge_asicrev == BGE_ASICREV_BCM5700 || + (sc->bge_asicrev == BGE_ASICREV_BCM5705 && + (sc->bge_chipid != BGE_CHIPID_BCM5705_A0 && + sc->bge_chipid != BGE_CHIPID_BCM5705_A1)) || + sc->bge_asicrev == BGE_ASICREV_BCM5906) + sc->bge_flags &= ~BGE_FLAG_ETH_WIRESPEED; + + if (sc->bge_chipid == BGE_CHIPID_BCM5701_A0 || + sc->bge_chipid == BGE_CHIPID_BCM5701_B0) + sc->bge_flags |= BGE_FLAG_CRC_BUG; + + if (sc->bge_chiprev == BGE_CHIPREV_5703_AX || + sc->bge_chiprev == BGE_CHIPREV_5704_AX) + sc->bge_flags |= BGE_FLAG_ADC_BUG; + + if (sc->bge_chipid == BGE_CHIPID_BCM5704_A0) + sc->bge_flags |= BGE_FLAG_5704_A0_BUG; + + if (BGE_IS_5705_PLUS(sc)) { + if (sc->bge_asicrev == BGE_ASICREV_BCM5755 || + sc->bge_asicrev == BGE_ASICREV_BCM5787) { + uint32_t product = pci_get_device(dev); + + if (product != PCI_PRODUCT_BROADCOM_BCM5722 && + product != PCI_PRODUCT_BROADCOM_BCM5756) + sc->bge_flags |= BGE_FLAG_JITTER_BUG; + if (product == PCI_PRODUCT_BROADCOM_BCM5755M) + sc->bge_flags |= BGE_FLAG_ADJUST_TRIM; + } else if (sc->bge_asicrev != BGE_ASICREV_BCM5906) { + sc->bge_flags |= BGE_FLAG_BER_BUG; } } + /* Allocate interrupt */ + rid = 0; + + sc->bge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_SHAREABLE | RF_ACTIVE); + + if (sc->bge_irq == NULL) { + device_printf(dev, "couldn't map interrupt\n"); + error = ENXIO; + goto fail; + } + + /* + * Check if this is a PCI-X or PCI Express device. + */ + if (BGE_IS_5705_PLUS(sc)) { + uint32_t reg; + + reg = pci_read_config(dev, BGE_PCIE_CAPID_REG, 4); + if ((reg & 0xff) == BGE_PCIE_CAPID) + sc->bge_flags |= BGE_FLAG_PCIE; + } else { + /* + * Check if the device is in PCI-X Mode. + * (This bit is not valid on PCI Express controllers.) + */ + if ((pci_read_config(sc->bge_dev, BGE_PCI_PCISTATE, 4) & + BGE_PCISTATE_PCI_BUSMODE) == 0) + sc->bge_flags |= BGE_FLAG_PCIX; + } + ifp = &sc->arpcom.ac_if; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); @@ -1621,8 +1754,7 @@ bge_attach(device_t dev) } /* 5705/5750 limits RX return ring to 512 entries. */ - if (sc->bge_asicrev == BGE_ASICREV_BCM5705 || - sc->bge_asicrev == BGE_ASICREV_BCM5750) + if (BGE_IS_5705_PLUS(sc)) sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT_5705; else sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT; @@ -1635,8 +1767,8 @@ bge_attach(device_t dev) sc->bge_stat_ticks = BGE_TICKS_PER_SEC; sc->bge_rx_coal_ticks = 150; sc->bge_tx_coal_ticks = 150; - sc->bge_rx_max_coal_bds = 64; - sc->bge_tx_max_coal_bds = 128; + sc->bge_rx_max_coal_bds = 10; + sc->bge_tx_max_coal_bds = 10; /* Set up ifnet structure */ ifp->if_softc = sc; @@ -1682,13 +1814,13 @@ bge_attach(device_t dev) } if ((hwcfg & BGE_HWCFG_MEDIA) == BGE_MEDIA_FIBER) - sc->bge_tbi = 1; + sc->bge_flags |= BGE_FLAG_TBI; /* The SysKonnect SK-9D41 is a 1000baseSX card. */ if (pci_get_subvendor(dev) == PCI_PRODUCT_SCHNEIDERKOCH_SK_9D41) - sc->bge_tbi = 1; + sc->bge_flags |= BGE_FLAG_TBI; - if (sc->bge_tbi) { + if (sc->bge_flags & BGE_FLAG_TBI) { ifmedia_init(&sc->bge_ifmedia, IFM_IMASK, bge_ifmedia_upd, bge_ifmedia_sts); ifmedia_add(&sc->bge_ifmedia, IFM_ETHER|IFM_1000_SX, 0, NULL); @@ -1717,24 +1849,15 @@ bge_attach(device_t dev) * which do not support unaligned accesses, we will realign the * payloads by copying the received packets. */ - switch (sc->bge_chipid) { - case BGE_CHIPID_BCM5701_A0: - case BGE_CHIPID_BCM5701_B0: - case BGE_CHIPID_BCM5701_B2: - case BGE_CHIPID_BCM5701_B5: - /* If in PCI-X mode, work around the alignment bug. */ - if ((pci_read_config(dev, BGE_PCI_PCISTATE, 4) & - (BGE_PCISTATE_PCI_BUSMODE | BGE_PCISTATE_PCI_BUSSPEED)) == - BGE_PCISTATE_PCI_BUSSPEED) - sc->bge_rx_alignment_bug = 1; - break; - } + if (sc->bge_asicrev == BGE_ASICREV_BCM5701 && + (sc->bge_flags & BGE_FLAG_PCIX)) + sc->bge_flags |= BGE_FLAG_RX_ALIGNBUG; if (sc->bge_asicrev == BGE_ASICREV_BCM5700 && sc->bge_chipid != BGE_CHIPID_BCM5700_B2) { sc->bge_link_upd = bge_bcm5700_link_upd; sc->bge_link_chg = BGE_MACSTAT_MI_INTERRUPT; - } else if (sc->bge_tbi) { + } else if (sc->bge_flags & BGE_FLAG_TBI) { sc->bge_link_upd = bge_tbi_link_upd; sc->bge_link_chg = BGE_MACSTAT_LINK_CHANGED; } else { @@ -1776,7 +1899,7 @@ bge_detach(device_t dev) ether_ifdetach(ifp); } - if (sc->bge_tbi) + if (sc->bge_flags & BGE_FLAG_TBI) ifmedia_removeall(&sc->bge_ifmedia); if (sc->bge_miibus) device_delete_child(dev, sc->bge_miibus); @@ -1808,10 +1931,20 @@ bge_reset(struct bge_softc *sc) { device_t dev; uint32_t cachesize, command, pcistate, reset; + void (*write_op)(struct bge_softc *, uint32_t, uint32_t); int i, val = 0; dev = sc->bge_dev; + if (BGE_IS_575X_PLUS(sc) && !BGE_IS_5714_FAMILY(sc)) { + if (sc->bge_flags & BGE_FLAG_PCIE) + write_op = bge_writemem_direct; + else + write_op = bge_writemem_ind; + } else { + write_op = bge_writereg_ind; + } + /* Save some important PCI state. */ cachesize = pci_read_config(dev, BGE_PCI_CACHESZ, 4); command = pci_read_config(dev, BGE_PCI_CMD, 4); @@ -1821,10 +1954,26 @@ bge_reset(struct bge_softc *sc) BGE_PCIMISCCTL_INDIRECT_ACCESS|BGE_PCIMISCCTL_MASK_PCI_INTR| BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW, 4); + /* Disable fastboot on controllers that support it. */ + if (sc->bge_asicrev == BGE_ASICREV_BCM5752 || + sc->bge_asicrev == BGE_ASICREV_BCM5755 || + sc->bge_asicrev == BGE_ASICREV_BCM5787) { + if (bootverbose) + if_printf(&sc->arpcom.ac_if, "Disabling fastboot\n"); + CSR_WRITE_4(sc, BGE_FASTBOOT_PC, 0x0); + } + + /* + * Write the magic number to SRAM at offset 0xB50. + * When firmware finishes its initialization it will + * write ~BGE_MAGIC_NUMBER to the same location. + */ + bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER); + reset = BGE_MISCCFG_RESET_CORE_CLOCKS|(65<<1); /* XXX: Broadcom Linux driver. */ - if (sc->bge_pcie) { + if (sc->bge_flags & BGE_FLAG_PCIE) { if (CSR_READ_4(sc, 0x7e2c) == 0x60) /* PCIE 1.0 */ CSR_WRITE_4(sc, 0x7e2c, 0x20); if (sc->bge_chipid != BGE_CHIPID_BCM5750_A0) { @@ -1834,13 +1983,20 @@ bge_reset(struct bge_softc *sc) } } + /* + * Set GPHY Power Down Override to leave GPHY + * powered up in D0 uninitialized. + */ + if (BGE_IS_5705_PLUS(sc)) + reset |= 0x04000000; + /* Issue global reset */ - bge_writereg_ind(sc, BGE_MISC_CFG, reset); + write_op(sc, BGE_MISC_CFG, reset); DELAY(1000); /* XXX: Broadcom Linux driver. */ - if (sc->bge_pcie) { + if (sc->bge_flags & BGE_FLAG_PCIE) { if (sc->bge_chipid == BGE_CHIPID_BCM5750_A0) { uint32_t v; @@ -1848,7 +2004,10 @@ bge_reset(struct bge_softc *sc) v = pci_read_config(dev, 0xc4, 4); pci_write_config(dev, 0xc4, v | (1<<15), 4); } - /* Set PCIE max payload size and clear error status. */ + /* + * Set PCIE max payload size to 128 bytes and + * clear error status. + */ pci_write_config(dev, 0xd8, 0xf5000, 4); } @@ -1858,20 +2017,20 @@ bge_reset(struct bge_softc *sc) BGE_HIF_SWAP_OPTIONS|BGE_PCIMISCCTL_PCISTATE_RW, 4); pci_write_config(dev, BGE_PCI_CACHESZ, cachesize, 4); pci_write_config(dev, BGE_PCI_CMD, command, 4); - bge_writereg_ind(sc, BGE_MISC_CFG, (65 << 1)); + write_op(sc, BGE_MISC_CFG, (65 << 1)); /* Enable memory arbiter. */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705) + if (BGE_IS_5714_FAMILY(sc)) { + uint32_t val; + + val = CSR_READ_4(sc, BGE_MARB_MODE); + CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE | val); + } else { CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); + } /* - * Prevent PXE restart: write a magic number to the - * general communications memory at 0xB50. - */ - bge_writemem_ind(sc, BGE_SOFTWARE_GENCOMM, BGE_MAGIC_NUMBER); - /* - * Poll the value location we just wrote until - * we see the 1's complement of the magic number. + * Poll until we see the 1's complement of the magic number. * This indicates that the firmware initialization * is complete. */ @@ -1883,7 +2042,8 @@ bge_reset(struct bge_softc *sc) } if (i == BGE_TIMEOUT) { - if_printf(&sc->arpcom.ac_if, "firmware handshake timed out\n"); + if_printf(&sc->arpcom.ac_if, "firmware handshake timed out," + "found 0x%08x\n", val); return; } @@ -1901,6 +2061,11 @@ bge_reset(struct bge_softc *sc) DELAY(10); } + if (sc->bge_flags & BGE_FLAG_PCIE) { + reset = bge_readmem_ind(sc, 0x7c00); + bge_writemem_ind(sc, 0x7c00, reset | (1 << 25)); + } + /* Fix up byte swapping */ CSR_WRITE_4(sc, BGE_MODE_CTL, BGE_DMA_SWAP_OPTIONS | BGE_MODECTL_BYTESWAP_DATA); @@ -1912,7 +2077,8 @@ bge_reset(struct bge_softc *sc) * adjustment to insure the SERDES drive level is set * to 1.2V. */ - if (sc->bge_asicrev == BGE_ASICREV_BCM5704 && sc->bge_tbi) { + if (sc->bge_asicrev == BGE_ASICREV_BCM5704 && + (sc->bge_flags & BGE_FLAG_TBI)) { uint32_t serdescfg; serdescfg = CSR_READ_4(sc, BGE_SERDES_CFG); @@ -1921,7 +2087,8 @@ bge_reset(struct bge_softc *sc) } /* XXX: Broadcom Linux driver. */ - if (sc->bge_pcie && sc->bge_chipid != BGE_CHIPID_BCM5750_A0) { + if ((sc->bge_flags & BGE_FLAG_PCIE) && + sc->bge_chipid != BGE_CHIPID_BCM5750_A0) { uint32_t v; v = CSR_READ_4(sc, 0x7c00); @@ -1958,8 +2125,7 @@ bge_rxeof(struct bge_softc *sc) bus_dmamap_sync(sc->bge_cdata.bge_rx_std_ring_tag, sc->bge_cdata.bge_rx_std_ring_map, BUS_DMASYNC_POSTREAD); - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) { + if (BGE_IS_JUMBO_CAPABLE(sc)) { bus_dmamap_sync(sc->bge_cdata.bge_rx_jumbo_ring_tag, sc->bge_cdata.bge_rx_jumbo_ring_map, BUS_DMASYNC_POSTREAD); @@ -2029,7 +2195,7 @@ bge_rxeof(struct bge_softc *sc) * The i386 allows unaligned accesses, but for other * platforms we must make sure the payload is aligned. */ - if (sc->bge_rx_alignment_bug) { + if (sc->bge_flags & BGE_FLAG_RX_ALIGNBUG) { bcopy(m->m_data, m->m_data + ETHER_ALIGN, cur_rx->bge_len); m->m_data += ETHER_ALIGN; @@ -2071,13 +2237,10 @@ bge_rxeof(struct bge_softc *sc) BUS_DMASYNC_PREWRITE); } - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) { - if (jumbocnt > 0) { - bus_dmamap_sync(sc->bge_cdata.bge_rx_jumbo_ring_tag, - sc->bge_cdata.bge_rx_jumbo_ring_map, - BUS_DMASYNC_PREWRITE); - } + if (BGE_IS_JUMBO_CAPABLE(sc) && jumbocnt > 0) { + bus_dmamap_sync(sc->bge_cdata.bge_rx_jumbo_ring_tag, + sc->bge_cdata.bge_rx_jumbo_ring_map, + BUS_DMASYNC_PREWRITE); } CSR_WRITE_4(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx); @@ -2199,13 +2362,12 @@ bge_tick(void *xsc) lwkt_serialize_enter(ifp->if_serializer); - if (sc->bge_asicrev == BGE_ASICREV_BCM5705 || - sc->bge_asicrev == BGE_ASICREV_BCM5750) + if (BGE_IS_5705_PLUS(sc)) bge_stats_update_regs(sc); else bge_stats_update(sc); - if (sc->bge_tbi) { + if (sc->bge_flags & BGE_FLAG_TBI) { /* * Since in TBI mode auto-polling can't be used we should poll * link status manually. Here we register pending link event @@ -2625,7 +2787,7 @@ bge_ifmedia_upd(struct ifnet *ifp) struct bge_softc *sc = ifp->if_softc; /* If this is a 1000baseX NIC, enable the TBI port. */ - if (sc->bge_tbi) { + if (sc->bge_flags & BGE_FLAG_TBI) { struct ifmedia *ifm = &sc->bge_ifmedia; if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) @@ -2689,7 +2851,7 @@ bge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) { struct bge_softc *sc = ifp->if_softc; - if (sc->bge_tbi) { + if (sc->bge_flags & BGE_FLAG_TBI) { ifmr->ifm_status = IFM_AVALID; ifmr->ifm_active = IFM_ETHER; if (CSR_READ_4(sc, BGE_MAC_STS) & @@ -2726,12 +2888,11 @@ bge_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) switch(command) { case SIOCSIFMTU: - /* Disallow jumbo frames on 5705/5750. */ - if (((sc->bge_asicrev == BGE_ASICREV_BCM5705 || - sc->bge_asicrev == BGE_ASICREV_BCM5750) && - ifr->ifr_mtu > ETHERMTU) || ifr->ifr_mtu > BGE_JUMBO_MTU) + if ((!BGE_IS_JUMBO_CAPABLE(sc) && ifr->ifr_mtu > ETHERMTU) || + (BGE_IS_JUMBO_CAPABLE(sc) && + ifr->ifr_mtu > BGE_JUMBO_MTU)) { error = EINVAL; - else { + } else if (ifp->if_mtu != ifr->ifr_mtu) { ifp->if_mtu = ifr->ifr_mtu; ifp->if_flags &= ~IFF_RUNNING; bge_init(sc); @@ -2774,7 +2935,7 @@ bge_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) break; case SIOCSIFMEDIA: case SIOCGIFMEDIA: - if (sc->bge_tbi) { + if (sc->bge_flags & BGE_FLAG_TBI) { error = ifmedia_ioctl(ifp, ifr, &sc->bge_ifmedia, command); } else { @@ -2831,7 +2992,7 @@ bge_stop(struct bge_softc *sc) ASSERT_SERIALIZED(ifp->if_serializer); - if (!sc->bge_tbi) + if ((sc->bge_flags & BGE_FLAG_TBI) == 0) mii = device_get_softc(sc->bge_miibus); callout_stop(&sc->bge_stat_timer); @@ -2842,8 +3003,7 @@ bge_stop(struct bge_softc *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); - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) + if (!BGE_IS_5705_PLUS(sc)) 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); @@ -2857,8 +3017,7 @@ bge_stop(struct bge_softc *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); - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) + if (!BGE_IS_5705_PLUS(sc)) BGE_CLRBIT(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE); BGE_CLRBIT(sc, BGE_SBDC_MODE, BGE_SBDCMODE_ENABLE); @@ -2868,13 +3027,11 @@ bge_stop(struct bge_softc *sc) */ BGE_CLRBIT(sc, BGE_HCC_MODE, BGE_HCCMODE_ENABLE); BGE_CLRBIT(sc, BGE_WDMA_MODE, BGE_WDMAMODE_ENABLE); - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) + if (!BGE_IS_5705_PLUS(sc)) 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); - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) { + if (!BGE_IS_5705_PLUS(sc)) { BGE_CLRBIT(sc, BGE_BMAN_MODE, BGE_BMANMODE_ENABLE); BGE_CLRBIT(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); } @@ -2892,8 +3049,7 @@ bge_stop(struct bge_softc *sc) bge_free_rx_ring_std(sc); /* Free jumbo RX list. */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) + if (BGE_IS_JUMBO_CAPABLE(sc)) bge_free_rx_ring_jumbo(sc); /* Free TX buffers. */ @@ -2904,7 +3060,7 @@ bge_stop(struct bge_softc *sc) * unchanged so that things will be put back to normal when * we bring the interface back up. */ - if (!sc->bge_tbi) { + if ((sc->bge_flags & BGE_FLAG_TBI) == 0) { itmp = ifp->if_flags; ifp->if_flags |= IFF_UP; ifm = mii->mii_media.ifm_cur; @@ -3044,8 +3200,7 @@ bge_dma_free(struct bge_softc *sc) sc->bge_cdata.bge_rx_std_ring_map, sc->bge_ldata.bge_rx_std_ring); - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) + if (BGE_IS_JUMBO_CAPABLE(sc)) bge_free_jumbo_mem(sc); /* Destroy RX return ring */ @@ -3166,8 +3321,7 @@ bge_dma_alloc(struct bge_softc *sc) /* * Create jumbo buffer pool. */ - if (sc->bge_asicrev != BGE_ASICREV_BCM5705 && - sc->bge_asicrev != BGE_ASICREV_BCM5750) { + if (BGE_IS_JUMBO_CAPABLE(sc)) { error = bge_alloc_jumbo_mem(sc); if (error) { if_printf(ifp, "could not create jumbo buffer pool\n"); diff --git a/sys/dev/netif/bge/if_bgereg.h b/sys/dev/netif/bge/if_bgereg.h index 73da22a414..7616861609 100644 --- a/sys/dev/netif/bge/if_bgereg.h +++ b/sys/dev/netif/bge/if_bgereg.h @@ -31,7 +31,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/bge/if_bgereg.h,v 1.1.2.16 2004/09/23 20:11:18 ps Exp $ - * $DragonFly: src/sys/dev/netif/bge/if_bgereg.h,v 1.20 2007/05/02 14:34:10 sephe Exp $ + * $DragonFly: src/sys/dev/netif/bge/if_bgereg.h,v 1.21 2007/05/07 04:54:32 sephe Exp $ */ /* @@ -170,8 +170,9 @@ #define BGE_PCI_MSI_ADDR_LO 0x60 #define BGE_PCI_MSI_DATA 0x64 -#define BGE_PCIE_MSI_CAPID 0xD0 -#define BGE_PCIE_MSI_CAPID_VAL 0x10 +/* PCI MSI. ??? */ +#define BGE_PCIE_CAPID_REG 0xD0 +#define BGE_PCIE_CAPID 0x10 /* * PCI registers specific to the BCM570x family. @@ -226,9 +227,12 @@ #define BGE_CHIPID_TIGON_I 0x40000000 #define BGE_CHIPID_TIGON_II 0x60000000 +#define BGE_CHIPID_BCM5700_A0 0x70000000 +#define BGE_CHIPID_BCM5700_A1 0x70010000 #define BGE_CHIPID_BCM5700_B0 0x71000000 #define BGE_CHIPID_BCM5700_B1 0x71010000 #define BGE_CHIPID_BCM5700_B2 0x71020000 +#define BGE_CHIPID_BCM5700_B3 0x71030000 #define BGE_CHIPID_BCM5700_ALTIMA 0x71040000 #define BGE_CHIPID_BCM5700_C0 0x72000000 #define BGE_CHIPID_BCM5701_A0 0x00000000 /* grrrr */ @@ -238,27 +242,60 @@ #define BGE_CHIPID_BCM5703_A0 0x10000000 #define BGE_CHIPID_BCM5703_A1 0x10010000 #define BGE_CHIPID_BCM5703_A2 0x10020000 +#define BGE_CHIPID_BCM5703_A3 0x10030000 +#define BGE_CHIPID_BCM5703_B0 0x11000000 #define BGE_CHIPID_BCM5704_A0 0x20000000 #define BGE_CHIPID_BCM5704_A1 0x20010000 #define BGE_CHIPID_BCM5704_A2 0x20020000 +#define BGE_CHIPID_BCM5704_A3 0x20030000 +#define BGE_CHIPID_BCM5704_B0 0x21000000 #define BGE_CHIPID_BCM5705_A0 0x30000000 #define BGE_CHIPID_BCM5705_A1 0x30010000 #define BGE_CHIPID_BCM5705_A2 0x30020000 #define BGE_CHIPID_BCM5705_A3 0x30030000 #define BGE_CHIPID_BCM5750_A0 0x40000000 #define BGE_CHIPID_BCM5750_A1 0x40010000 +#define BGE_CHIPID_BCM5750_A3 0x40030000 +#define BGE_CHIPID_BCM5750_B0 0x41000000 +#define BGE_CHIPID_BCM5750_B1 0x41010000 +#define BGE_CHIPID_BCM5750_C0 0x42000000 +#define BGE_CHIPID_BCM5750_C1 0x42010000 +#define BGE_CHIPID_BCM5750_C2 0x42020000 #define BGE_CHIPID_BCM5714_A0 0x50000000 +#define BGE_CHIPID_BCM5752_A0 0x60000000 +#define BGE_CHIPID_BCM5752_A1 0x60010000 +#define BGE_CHIPID_BCM5752_A2 0x60020000 +#define BGE_CHIPID_BCM5714_B0 0x80000000 +#define BGE_CHIPID_BCM5714_B3 0x80030000 +#define BGE_CHIPID_BCM5715_A0 0x90000000 +#define BGE_CHIPID_BCM5715_A1 0x90010000 +#define BGE_CHIPID_BCM5715_A3 0x90030000 +#define BGE_CHIPID_BCM5755_A0 0xa0000000 +#define BGE_CHIPID_BCM5755_A1 0xa0010000 +#define BGE_CHIPID_BCM5755_A2 0xa0020000 +#define BGE_CHIPID_BCM5754_A0 0xb0000000 +#define BGE_CHIPID_BCM5754_A1 0xb0010000 +#define BGE_CHIPID_BCM5754_A2 0xb0020000 +#define BGE_CHIPID_BCM5787_A0 0xb0000000 +#define BGE_CHIPID_BCM5787_A1 0xb0010000 +#define BGE_CHIPID_BCM5787_A2 0xb0020000 /* shorthand one */ #define BGE_ASICREV(x) ((x) >> 28) -#define BGE_ASICREV_BCM5700 0x07 #define BGE_ASICREV_BCM5701 0x00 #define BGE_ASICREV_BCM5703 0x01 #define BGE_ASICREV_BCM5704 0x02 #define BGE_ASICREV_BCM5705 0x03 #define BGE_ASICREV_BCM5750 0x04 -#define BGE_ASICREV_BCM5714 0x05 +#define BGE_ASICREV_BCM5714_A0 0x05 #define BGE_ASICREV_BCM5752 0x06 +#define BGE_ASICREV_BCM5700 0x07 +#define BGE_ASICREV_BCM5780 0x08 +#define BGE_ASICREV_BCM5714 0x09 +#define BGE_ASICREV_BCM5755 0x0a +#define BGE_ASICREV_BCM5754 0x0b +#define BGE_ASICREV_BCM5787 0x0b +#define BGE_ASICREV_BCM5906 0x0c /* chip revisions */ #define BGE_CHIPREV(x) ((x) >> 24) @@ -266,6 +303,9 @@ #define BGE_CHIPREV_5700_BX 0x71 #define BGE_CHIPREV_5700_CX 0x72 #define BGE_CHIPREV_5701_AX 0x00 +#define BGE_CHIPREV_5703_AX 0x10 +#define BGE_CHIPREV_5704_AX 0x20 +#define BGE_CHIPREV_5704_BX 0x21 /* PCI DMA Read/Write Control register */ #define BGE_PCIDMARWCTL_MINDMA 0x000000FF @@ -309,7 +349,7 @@ #define BGE_PCISTATE_FORCE_RESET 0x00000001 #define BGE_PCISTATE_INTR_STATE 0x00000002 #define BGE_PCISTATE_PCI_BUSMODE 0x00000004 /* 1 = PCI, 0 = PCI-X */ -#define BGE_PCISTATE_PCI_BUSSPEED 0x00000008 /* 1 = 33/66, 0 = 66/133 */ +#define BGE_PCISTATE_PCI_BUSSPEED 0x00000008 /* 1 = 66/133, 0 = 33/66 */ #define BGE_PCISTATE_32BIT_BUS 0x00000010 /* 1 = 32bit, 0 = 64bit */ #define BGE_PCISTATE_WANT_EXPROM 0x00000020 #define BGE_PCISTATE_EXPROM_RETRY 0x00000040 @@ -1633,6 +1673,7 @@ #define BGE_EE_CTL 0x6840 #define BGE_MDI_CTL 0x6844 #define BGE_EE_DELAY 0x6848 +#define BGE_FASTBOOT_PC 0x6894 /* Mode control register */ #define BGE_MODECTL_INT_SNDCOAL_ONLY 0x00000001 @@ -1745,10 +1786,11 @@ } while(0) /* - * This magic number is used to prevent PXE restart when we - * issue a software reset. We write this magic number to the - * firmware mailbox at 0xB50 in order to prevent the PXE boot - * code from running. + * This magic number is written to the firmware mailbox at 0xb50 + * before a software reset is issued. After the internal firmware + * has completed its initialization it will write the opposite of + * this value, ~BGE_MAGIC_NUMBER, to the same location, allowing the + * driver to synchronize with the firmware. */ #define BGE_MAGIC_NUMBER 0x4B657654 @@ -2303,14 +2345,28 @@ struct bge_softc { struct resource *bge_irq; struct resource *bge_res; struct ifmedia bge_ifmedia; /* TBI media info */ - uint8_t bge_extram; /* has external SSRAM */ - uint8_t bge_tbi; - uint8_t bge_rx_alignment_bug; + uint32_t bge_flags; +#define BGE_FLAG_TBI 0x00000001 +#define BGE_FLAG_JUMBO 0x00000002 +#define BGE_FLAG_ETH_WIRESPEED 0x00000004 +#define BGE_FLAG_MSI 0x00000100 /* unused */ +#define BGE_FLAG_PCIX 0x00000200 +#define BGE_FLAG_PCIE 0x00000400 +#define BGE_FLAG_5700_FAMILY 0x00001000 +#define BGE_FLAG_5705_PLUS 0x00002000 +#define BGE_FLAG_5714_FAMILY 0x00004000 +#define BGE_FLAG_575X_PLUS 0x00008000 +#define BGE_FLAG_RX_ALIGNBUG 0x00100000 +#define BGE_FLAG_NO_3LED 0x00200000 +#define BGE_FLAG_ADC_BUG 0x00400000 +#define BGE_FLAG_5704_A0_BUG 0x00800000 +#define BGE_FLAG_JITTER_BUG 0x01000000 +#define BGE_FLAG_BER_BUG 0x02000000 +#define BGE_FLAG_ADJUST_TRIM 0x04000000 +#define BGE_FLAG_CRC_BUG 0x08000000 uint32_t bge_chipid; uint8_t bge_asicrev; uint8_t bge_chiprev; - uint8_t bge_no_3_led; - uint8_t bge_pcie; struct bge_ring_data bge_ldata; /* rings */ struct bge_chain_data bge_cdata; /* mbufs */ uint16_t bge_tx_saved_considx; diff --git a/sys/dev/netif/mii_layer/brgphy.c b/sys/dev/netif/mii_layer/brgphy.c index fc83742a1f..c81310d9c6 100644 --- a/sys/dev/netif/mii_layer/brgphy.c +++ b/sys/dev/netif/mii_layer/brgphy.c @@ -32,7 +32,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/brgphy.c,v 1.1.2.7 2003/05/11 18:00:55 ps Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/brgphy.c,v 1.16 2007/05/02 14:34:10 sephe Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/brgphy.c,v 1.17 2007/05/07 04:54:32 sephe Exp $ */ /* @@ -46,8 +46,7 @@ #include #include -#include - +#include #include #include #include @@ -80,7 +79,9 @@ static const struct mii_phydesc brgphys[] = { MII_PHYDESC(xxBROADCOM, BCM5714), MII_PHYDESC(xxBROADCOM, BCM5750), MII_PHYDESC(xxBROADCOM, BCM5752), + MII_PHYDESC(xxBROADCOM2,BCM5755), MII_PHYDESC(xxBROADCOM, BCM5780), + MII_PHYDESC(xxBROADCOM2,BCM5787), MII_PHYDESC(xxBROADCOM, BCM5706C), MII_PHYDESC(xxBROADCOM, BCM5708C), @@ -113,14 +114,18 @@ static void brgphy_mii_phy_auto(struct mii_softc *); static void brgphy_reset(struct mii_softc *); static void brgphy_loop(struct mii_softc *); -static void brgphy_load_dspcode(struct mii_softc *); static void brgphy_bcm5401_dspcode(struct mii_softc *); static void brgphy_bcm5411_dspcode(struct mii_softc *); static void brgphy_bcm5421_dspcode(struct mii_softc *); static void brgphy_bcm54k2_dspcode(struct mii_softc *); -static void brgphy_bcm5703_dspcode(struct mii_softc *); -static void brgphy_bcm5704_dspcode(struct mii_softc *); -static void brgphy_bcm5750_dspcode(struct mii_softc *); + +static void brgphy_adc_bug(struct mii_softc *); +static void brgphy_5704_a0_bug(struct mii_softc *); +static void brgphy_ber_bug(struct mii_softc *); +static void brgphy_crc_bug(struct mii_softc *); + +static void brgphy_jumbo_settings(struct mii_softc *, u_long); +static void brgphy_eth_wirespeed(struct mii_softc *); static int brgphy_probe(device_t dev) @@ -340,10 +345,15 @@ setit: sc->mii_media_status != mii->mii_media_status || cmd == MII_MEDIACHG) { switch (sc->mii_model) { - case MII_MODEL_BROADCOM_BCM5400: + case MII_MODEL_xxBROADCOM_BCM5400: + brgphy_bcm5401_dspcode(sc); + break; case MII_MODEL_xxBROADCOM_BCM5401: + if (sc->mii_rev == 1 || sc->mii_rev == 3) + brgphy_bcm5401_dspcode(sc); + break; case MII_MODEL_xxBROADCOM_BCM5411: - brgphy_load_dspcode(sc); + brgphy_bcm5411_dspcode(sc); break; } } @@ -446,40 +456,69 @@ brgphy_loop(struct mii_softc *sc) static void brgphy_reset(struct mii_softc *sc) { - u_int32_t val; - struct ifnet *ifp; - struct bge_softc *bge_sc; + struct ifnet *ifp; mii_phy_reset(sc); + switch (sc->mii_model) { + case MII_MODEL_xxBROADCOM_BCM5400: + brgphy_bcm5401_dspcode(sc); + break; + case MII_MODEL_xxBROADCOM_BCM5401: + if (sc->mii_rev == 1 || sc->mii_rev == 3) + brgphy_bcm5401_dspcode(sc); + break; + case MII_MODEL_xxBROADCOM_BCM5411: + brgphy_bcm5411_dspcode(sc); + break; + case MII_MODEL_xxBROADCOM_BCM5421: + brgphy_bcm5421_dspcode(sc); + break; + case MII_MODEL_xxBROADCOM_BCM54K2: + brgphy_bcm54k2_dspcode(sc); + break; + } + ifp = sc->mii_pdata->mii_ifp; - bge_sc = ifp->if_softc; + if (strncmp(ifp->if_xname, "bge", 3) == 0) { + struct bge_softc *bge_sc = ifp->if_softc; + + if (bge_sc->bge_flags & BGE_FLAG_ADC_BUG) + brgphy_adc_bug(sc); + if (bge_sc->bge_flags & BGE_FLAG_5704_A0_BUG) + brgphy_5704_a0_bug(sc); + if (bge_sc->bge_flags & BGE_FLAG_BER_BUG) { + brgphy_ber_bug(sc); + } else if (bge_sc->bge_flags & BGE_FLAG_JITTER_BUG) { + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0c00); + PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a); + + if (bge_sc->bge_flags & BGE_FLAG_ADJUST_TRIM) { + PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 0x110b); + PHY_WRITE(sc, BRGPHY_TEST1, + BRGPHY_TEST1_TRIM_EN | 0x4); + } else { + PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 0x010b); + } - brgphy_load_dspcode(sc); + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0400); + } + if (bge_sc->bge_flags & BGE_FLAG_CRC_BUG) + brgphy_crc_bug(sc); - /* - * Don't enable Ethernet@WireSpeed for the 5700 or 5705 - * other than A0 and A1 chips. Make sure we only do this - * test on "bge" NICs, since other drivers may use this - * same PHY subdriver. - */ - if (strncmp(ifp->if_xname, "bge", 3) == 0 && - (bge_sc->bge_asicrev == BGE_ASICREV_BCM5700 || - (bge_sc->bge_asicrev == BGE_ASICREV_BCM5705 && - (bge_sc->bge_chipid != BGE_CHIPID_BCM5705_A0 && - bge_sc->bge_chipid != BGE_CHIPID_BCM5705_A1)))) - return; - - /* Enable Ethernet@WireSpeed. */ - PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007); - val = PHY_READ(sc, BRGPHY_MII_AUXCTL); - PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val | (1 << 15) | (1 << 4)); + /* Set Jumbo frame settings in the PHY. */ + brgphy_jumbo_settings(sc, ifp->if_mtu); - /* Enable Link LED on Dell boxes */ - if (bge_sc->bge_no_3_led) { - PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, - PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) - & ~BRGPHY_PHY_EXTCTL_3_LED); + /* Enable Ethernet@Wirespeed */ + if (bge_sc->bge_flags & BGE_FLAG_ETH_WIRESPEED) + brgphy_eth_wirespeed(sc); + + /* Enable Link LED on Dell boxes */ + if (bge_sc->bge_flags & BGE_FLAG_NO_3LED) { + PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, + PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) + & ~BRGPHY_PHY_EXTCTL_3_LED); + } } } @@ -567,7 +606,7 @@ brgphy_bcm54k2_dspcode(struct mii_softc *sc) } static void -brgphy_bcm5703_dspcode(struct mii_softc *sc) +brgphy_adc_bug(struct mii_softc *sc) { static const struct { int reg; @@ -576,6 +615,9 @@ brgphy_bcm5703_dspcode(struct mii_softc *sc) { BRGPHY_MII_AUXCTL, 0x0c00 }, { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, { BRGPHY_MII_DSP_RW_PORT, 0x2aaa }, + { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, + { BRGPHY_MII_DSP_RW_PORT, 0x0323 }, + { BRGPHY_MII_AUXCTL, 0x0400 }, { 0, 0 }, }; int i; @@ -585,18 +627,12 @@ brgphy_bcm5703_dspcode(struct mii_softc *sc) } static void -brgphy_bcm5704_dspcode(struct mii_softc *sc) +brgphy_5704_a0_bug(struct mii_softc *sc) { static const struct { int reg; u_int16_t val; } dspcode[] = { - { BRGPHY_MII_AUXCTL, 0x0c00 }, - { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, - { BRGPHY_MII_DSP_RW_PORT, 0x2aaa }, - { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, - { BRGPHY_MII_DSP_RW_PORT, 0x0323 }, - { BRGPHY_MII_AUXCTL, 0x0400 }, { 0x1c, 0x8d68 }, { 0x1c, 0x8d68 }, { 0, 0 }, @@ -608,7 +644,7 @@ brgphy_bcm5704_dspcode(struct mii_softc *sc) } static void -brgphy_bcm5750_dspcode(struct mii_softc *sc) +brgphy_ber_bug(struct mii_softc *sc) { static const struct { int reg; @@ -631,39 +667,63 @@ brgphy_bcm5750_dspcode(struct mii_softc *sc) } static void -brgphy_load_dspcode(struct mii_softc *sc) +brgphy_crc_bug(struct mii_softc *sc) { - switch (sc->mii_model) { - case MII_MODEL_BROADCOM_BCM5400: - brgphy_bcm5401_dspcode(sc); - break; - case MII_MODEL_BROADCOM_BCM5401: - if (sc->mii_rev == 1 || sc->mii_rev == 3) - brgphy_bcm5401_dspcode(sc); - break; - case MII_MODEL_BROADCOM_BCM5411: - brgphy_bcm5411_dspcode(sc); - break; - case MII_MODEL_xxBROADCOM_BCM5421: - brgphy_bcm5421_dspcode(sc); - break; - case MII_MODEL_xxBROADCOM_BCM54K2: - brgphy_bcm54k2_dspcode(sc); - break; - case MII_MODEL_xxBROADCOM_BCM5703: - brgphy_bcm5703_dspcode(sc); - break; - case MII_MODEL_xxBROADCOM_BCM5704: - brgphy_bcm5704_dspcode(sc); - break; - case MII_MODEL_xxBROADCOM_BCM5705: - case MII_MODEL_xxBROADCOM_BCM5750: - case MII_MODEL_xxBROADCOM_BCM5714: - case MII_MODEL_xxBROADCOM_BCM5780: - case MII_MODEL_xxBROADCOM_BCM5752: - case MII_MODEL_xxBROADCOM_BCM5706C: - case MII_MODEL_xxBROADCOM_BCM5708C: - brgphy_bcm5750_dspcode(sc); - break; + static const struct { + int reg; + uint16_t val; + } dspcode[] = { + { BRGPHY_MII_DSP_ADDR_REG, 0x0a75 }, + { 0x1c, 0x8c68 }, + { 0x1c, 0x8d68 }, + { 0x1c, 0x8c68 }, + { 0, 0 }, + }; + int i; + + for (i = 0; dspcode[i].reg != 0; i++) + PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); +} + +static void +brgphy_jumbo_settings(struct mii_softc *sc, u_long mtu) +{ + uint32_t val; + + /* Set or clear jumbo frame settings in the PHY. */ + if (mtu > ETHER_MAX_LEN) { + if (sc->mii_model == MII_MODEL_xxBROADCOM_BCM5401) { + /* BCM5401 PHY cannot read-modify-write. */ + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x4c20); + } else { + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7); + val = PHY_READ(sc, BRGPHY_MII_AUXCTL); + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, + val | BRGPHY_AUXCTL_LONG_PKT); + } + + val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL); + PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, + val | BRGPHY_PHY_EXTCTL_HIGH_LA); + } else { + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7); + val = PHY_READ(sc, BRGPHY_MII_AUXCTL); + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, + val & ~(BRGPHY_AUXCTL_LONG_PKT | 0x7)); + + val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL); + PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, + val & ~BRGPHY_PHY_EXTCTL_HIGH_LA); } } + +static void +brgphy_eth_wirespeed(struct mii_softc *sc) +{ + u_int32_t val; + + /* Enable Ethernet@Wirespeed */ + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007); + val = PHY_READ(sc, BRGPHY_MII_AUXCTL); + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, (val | (1 << 15) | (1 << 4))); +} diff --git a/sys/dev/netif/mii_layer/brgphyreg.h b/sys/dev/netif/mii_layer/brgphyreg.h index 83516bc298..c3a2e92971 100644 --- a/sys/dev/netif/mii_layer/brgphyreg.h +++ b/sys/dev/netif/mii_layer/brgphyreg.h @@ -30,7 +30,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/brgphyreg.h,v 1.1.2.2 2001/10/01 18:31:08 wpaul Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/brgphyreg.h,v 1.3 2004/02/10 22:14:14 hmp Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/brgphyreg.h,v 1.4 2007/05/07 04:54:32 sephe Exp $ */ #ifndef _DEV_MII_BRGPHYREG_H_ @@ -262,6 +262,9 @@ #define BRGPHY_IMR_LNK_CHG 0x0002 /* Link status change */ #define BRGPHY_IMR_CRCERR 0x0001 /* CEC error */ +#define BRGPHY_TEST1 0x1E +#define BRGPHY_TEST1_TRIM_EN 0x0010 + #define BRGPHY_INTRS \ ~(BRGPHY_IMR_LNK_CHG|BRGPHY_IMR_LSP_CHG|BRGPHY_IMR_DUP_CHG) -- 2.11.4.GIT