Index: dev/bge/if_bge.c =================================================================== RCS file: /devel/FreeBSD/ncvs/src/sys/dev/bge/if_bge.c,v retrieving revision 1.204 diff -u -r1.204 if_bge.c --- dev/bge/if_bge.c 11 Mar 2008 15:05:54 -0000 1.204 +++ dev/bge/if_bge.c 25 Mar 2008 02:44:25 -0000 @@ -196,6 +196,8 @@ { BCOM_VENDORID, BCOM_DEVICEID_BCM5901 }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5901A2 }, { BCOM_VENDORID, BCOM_DEVICEID_BCM5903M }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM5906 }, + { BCOM_VENDORID, BCOM_DEVICEID_BCM5906M }, { SK_VENDORID, SK_DEVICEID_ALTIMA }, @@ -273,6 +275,8 @@ { BGE_CHIPID_BCM5787_A0, "BCM5754/5787 A0" }, { BGE_CHIPID_BCM5787_A1, "BCM5754/5787 A1" }, { BGE_CHIPID_BCM5787_A2, "BCM5754/5787 A2" }, + { BGE_CHIPID_BCM5906_A1, "BCM5906 A1" }, + { BGE_CHIPID_BCM5906_A2, "BCM5906 A2" }, { 0, NULL } }; @@ -295,6 +299,7 @@ { BGE_ASICREV_BCM5755, "unknown BCM5755" }, /* 5754 and 5787 share the same ASIC ID */ { BGE_ASICREV_BCM5787, "unknown BCM5754/5787" }, + { BGE_ASICREV_BCM5906, "unknown BCM5906" }, { 0, NULL } }; @@ -307,6 +312,9 @@ const struct bge_revision * bge_lookup_rev(uint32_t); const struct bge_vendor * bge_lookup_vendor(uint16_t); + +typedef int (*bge_eaddr_fcn_t)(struct bge_softc *, uint8_t[]); + static int bge_probe(device_t); static int bge_attach(device_t); static int bge_detach(device_t); @@ -317,6 +325,11 @@ static int bge_dma_alloc(device_t); static void bge_dma_free(struct bge_softc *); +static int bge_get_eaddr_mem(struct bge_softc *, uint8_t[]); +static int bge_get_eaddr_nvram(struct bge_softc *, uint8_t[]); +static int bge_get_eaddr_eeprom(struct bge_softc *, uint8_t[]); +static int bge_get_eaddr(struct bge_softc *, uint8_t[]); + static void bge_txeof(struct bge_softc *); static void bge_rxeof(struct bge_softc *); @@ -339,6 +352,9 @@ static int bge_ifmedia_upd(struct ifnet *); static void bge_ifmedia_sts(struct ifnet *, struct ifmediareq *); +static uint8_t bge_nvram_getbyte(struct bge_softc *, int, uint8_t *); +static int bge_read_nvram(struct bge_softc *, caddr_t, int, int); + static uint8_t bge_eeprom_getbyte(struct bge_softc *, int, uint8_t *); static int bge_read_eeprom(struct bge_softc *, caddr_t, int, int); @@ -361,6 +377,7 @@ static int bge_has_eeprom(struct bge_softc *); static uint32_t bge_readmem_ind(struct bge_softc *, int); static void bge_writemem_ind(struct bge_softc *, int, int); +static void bge_writembx(struct bge_softc *, int, int); #ifdef notdef static uint32_t bge_readreg_ind(struct bge_softc *, int); #endif @@ -476,6 +493,10 @@ return (0); } #endif + + if (sc->bge_asicrev == BGE_ASICREV_BCM5906) + return (0); + return (1); } @@ -535,6 +556,15 @@ CSR_WRITE_4(sc, off, val); } +static void +bge_writembx(struct bge_softc *sc, int off, int val) +{ + if (sc->bge_asicrev == BGE_ASICREV_BCM5906) + off += BGE_LPMBX_IRQ0_HI - BGE_MBX_IRQ0_HI; + + CSR_WRITE_4(sc, off, val); +} + /* * Map a single buffer address. */ @@ -557,6 +587,78 @@ ctx->bge_busaddr = segs->ds_addr; } +static uint8_t +bge_nvram_getbyte(struct bge_softc *sc, int addr, uint8_t *dest) +{ + uint32_t access, byte = 0; + int i; + + /* Lock. */ + CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_SET1); + for (i = 0; i < 8000; i++) { + if (CSR_READ_4(sc, BGE_NVRAM_SWARB) & BGE_NVRAMSWARB_GNT1) + break; + DELAY(20); + } + if (i == 8000) + return (1); + + /* Enable access. */ + access = CSR_READ_4(sc, BGE_NVRAM_ACCESS); + CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access | BGE_NVRAMACC_ENABLE); + + CSR_WRITE_4(sc, BGE_NVRAM_ADDR, addr & 0xfffffffc); + CSR_WRITE_4(sc, BGE_NVRAM_CMD, BGE_NVRAM_READCMD); + for (i = 0; i < BGE_TIMEOUT * 10; i++) { + DELAY(10); + if (CSR_READ_4(sc, BGE_NVRAM_CMD) & BGE_NVRAMCMD_DONE) { + DELAY(10); + break; + } + } + + if (i == BGE_TIMEOUT * 10) { + if_printf(sc->bge_ifp, "nvram read timed out\n"); + return (1); + } + + /* Get result. */ + byte = CSR_READ_4(sc, BGE_NVRAM_RDDATA); + + *dest = (bswap32(byte) >> ((addr % 4) * 8)) & 0xFF; + + /* Disable access. */ + CSR_WRITE_4(sc, BGE_NVRAM_ACCESS, access); + + /* Unlock. */ + CSR_WRITE_4(sc, BGE_NVRAM_SWARB, BGE_NVRAMSWARB_CLR1); + CSR_READ_4(sc, BGE_NVRAM_SWARB); + + return (0); +} + +/* + * Read a sequence of bytes from NVRAM. + */ +static int +bge_read_nvram(struct bge_softc *sc, caddr_t dest, int off, int cnt) +{ + int err = 0, i; + uint8_t byte = 0; + + if (sc->bge_asicrev != BGE_ASICREV_BCM5906) + return (1); + + for (i = 0; i < cnt; i++) { + err = bge_nvram_getbyte(sc, off + i, &byte); + if (err) + break; + *(dest + i) = byte; + } + + return (err ? 1 : 0); +} + /* * Read a byte of data stored in the EEPROM at address 'addr.' The * BCM570x supports both the traditional bitbang interface and an @@ -661,11 +763,13 @@ } if (i == BGE_TIMEOUT) { - device_printf(sc->bge_dev, "PHY read timed out\n"); + device_printf(sc->bge_dev, "PHY read timed out " + "(phy %d, reg %d, val 0x%08x)\n", phy, reg, val); val = 0; goto done; } + DELAY(5); val = CSR_READ_4(sc, BGE_MI_COMM); done: @@ -689,6 +793,10 @@ sc = device_get_softc(dev); + if (sc->bge_asicrev == BGE_ASICREV_BCM5906 && + (reg == BRGPHY_MII_1000CTL || reg == BRGPHY_MII_AUXCTL)) + return(0); + /* Reading with autopolling on may trigger PCI errors */ autopoll = CSR_READ_4(sc, BGE_MI_MODE); if (autopoll & BGE_MIMODE_AUTOPOLL) { @@ -701,12 +809,17 @@ for (i = 0; i < BGE_TIMEOUT; i++) { DELAY(10); - if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY)) + if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY)) { + DELAY(5); + CSR_READ_4(sc, BGE_MI_COMM); /* dummy read */ break; + } } if (i == BGE_TIMEOUT) { - device_printf(sc->bge_dev, "PHY write timed out\n"); + device_printf(sc->bge_dev, + "PHY write timed out (phy %d, reg %d, val %d)\n", + phy, reg, val); return (0); } @@ -889,7 +1002,7 @@ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); sc->bge_std = i - 1; - CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std); + bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std); return (0); } @@ -936,7 +1049,7 @@ BGE_RCB_FLAG_USE_EXT_RX_BD); CSR_WRITE_4(sc, BGE_RX_JUMBO_RCB_MAXLEN_FLAGS, rcb->bge_maxlen_flags); - CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo); + bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo); return (0); } @@ -992,17 +1105,17 @@ /* Initialize transmit producer index for host-memory send ring. */ sc->bge_tx_prodidx = 0; - CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx); + bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx); /* 5700 b2 errata */ if (sc->bge_chiprev == BGE_CHIPREV_5700_BX) - CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx); + bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, sc->bge_tx_prodidx); /* NIC-memory send ring not used; initialize to zero. */ - CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0); + bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0); /* 5700 b2 errata */ if (sc->bge_chiprev == BGE_CHIPREV_5700_BX) - CSR_WRITE_4(sc, BGE_MBX_TX_NIC_PROD0_LO, 0); + bge_writembx(sc, BGE_MBX_TX_NIC_PROD0_LO, 0); return (0); } @@ -1273,6 +1386,15 @@ /* Set the timer prescaler (always 66Mhz) */ CSR_WRITE_4(sc, BGE_MISC_CFG, BGE_32BITTIME_66MHZ); + if (sc->bge_asicrev == BGE_ASICREV_BCM5906) { + DELAY(40); /* XXX */ + + /* Put PHY into ready state */ + BGE_CLRBIT(sc, BGE_MISC_CFG, BGE_MISCCFG_EPHY_IDDQ); + CSR_READ_4(sc, BGE_MISC_CFG); /* Flush */ + DELAY(40); + } + return (0); } @@ -1309,15 +1431,21 @@ CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_LEN, 0x2000); } + /* Configure mbuf pool watermarks */ - 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 { + if (!BGE_IS_5705_PLUS(sc)) { 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); + } else if (sc->bge_asicrev == BGE_ASICREV_BCM5906) { + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x04); + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x10); + } else { + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_READDMA_LOWAT, 0x0); + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_MACRX_LOWAT, 0x10); + CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60); } - CSR_WRITE_4(sc, BGE_BMAN_MBUFPOOL_HIWAT, 0x60); /* Configure DMA resource watermarks */ CSR_WRITE_4(sc, BGE_BMAN_DMA_DESCPOOL_LOWAT, 5); @@ -1464,15 +1592,15 @@ BGE_RCB_MAXLEN_FLAGS(sc->bge_return_ring_cnt, BGE_RCB_FLAG_RING_DISABLED)); RCB_WRITE_4(sc, vrcb, bge_nicaddr, 0); - CSR_WRITE_4(sc, BGE_MBX_RX_CONS0_LO + + bge_writembx(sc, BGE_MBX_RX_CONS0_LO + (i * (sizeof(uint64_t))), 0); vrcb += sizeof(struct bge_rcb); } /* Initialize RX ring indexes */ - CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, 0); - CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0); - CSR_WRITE_4(sc, BGE_MBX_RX_MINI_PROD_LO, 0); + bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, 0); + bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, 0); + bge_writembx(sc, BGE_MBX_RX_MINI_PROD_LO, 0); /* * Set up RX return ring 0 @@ -2232,7 +2360,6 @@ struct ifnet *ifp; struct bge_softc *sc; uint32_t hwcfg = 0; - uint32_t mac_tmp = 0; u_char eaddr[ETHER_ADDR_LEN]; int error, reg, rid, trys; @@ -2294,6 +2421,7 @@ case BGE_ASICREV_BCM5752: case BGE_ASICREV_BCM5755: case BGE_ASICREV_BCM5787: + case BGE_ASICREV_BCM5906: sc->bge_flags |= BGE_FLAG_575X_PLUS; /* FALLTHRU */ case BGE_ASICREV_BCM5705: @@ -2316,7 +2444,7 @@ sc->bge_asicrev == BGE_ASICREV_BCM5787) { if (sc->bge_chipid != BGE_CHIPID_BCM5722_A0) sc->bge_flags |= BGE_FLAG_JITTER_BUG; - } else + } else if (sc->bge_asicrev != BGE_ASICREV_BCM5906) sc->bge_flags |= BGE_FLAG_BER_BUG; } @@ -2427,22 +2555,14 @@ } #ifdef __sparc64__ - if ((sc->bge_flags & BGE_FLAG_EEPROM) == 0) + if (((sc->bge_flags & BGE_FLAG_EEPROM) == 0) && + (sc->bge_asicrev != BGE_ASICREV_BCM5906)) OF_getetheraddr(dev, eaddr); else #endif { - mac_tmp = bge_readmem_ind(sc, 0x0C14); - if ((mac_tmp >> 16) == 0x484B) { - eaddr[0] = (u_char)(mac_tmp >> 8); - eaddr[1] = (u_char)mac_tmp; - mac_tmp = bge_readmem_ind(sc, 0x0C18); - eaddr[2] = (u_char)(mac_tmp >> 24); - eaddr[3] = (u_char)(mac_tmp >> 16); - eaddr[4] = (u_char)(mac_tmp >> 8); - eaddr[5] = (u_char)mac_tmp; - } else if (bge_read_eeprom(sc, eaddr, - BGE_EE_MAC_OFFSET + 2, ETHER_ADDR_LEN)) { + error = bge_get_eaddr(sc, eaddr); + if (error) { device_printf(sc->bge_dev, "failed to read station address\n"); error = ENXIO; @@ -2700,7 +2820,8 @@ dev = sc->bge_dev; - if (BGE_IS_575X_PLUS(sc) && !BGE_IS_5714_FAMILY(sc)) { + if (BGE_IS_575X_PLUS(sc) && !BGE_IS_5714_FAMILY(sc) && + (sc->bge_asicrev != BGE_ASICREV_BCM5906)) { if (sc->bge_flags & BGE_FLAG_PCIE) write_op = bge_writemem_direct; else @@ -2756,6 +2877,17 @@ /* Issue global reset */ write_op(sc, BGE_MISC_CFG, reset); + if (sc->bge_asicrev == BGE_ASICREV_BCM5906) { + uint32_t status, ctrl; + + status = CSR_READ_4(sc, BGE_VCPU_STATUS); + CSR_WRITE_4(sc, BGE_VCPU_STATUS, + status | BGE_VCPU_STATUS_DRV_RESET); + ctrl = CSR_READ_4(sc, BGE_VCPU_EXT_CTRL); + CSR_WRITE_4(sc, BGE_VCPU_EXT_CTRL, + ctrl & ~BGE_VCPU_EXT_CTRL_HALT_CPU); + } + DELAY(1000); /* XXX: Broadcom Linux driver. */ @@ -2800,21 +2932,34 @@ } else CSR_WRITE_4(sc, BGE_MARB_MODE, BGE_MARBMODE_ENABLE); - /* - * Poll until we see the 1's complement of the magic number. - * This indicates that the firmware initialization is complete. - * We expect this to fail if no EEPROM is fitted though. - */ - for (i = 0; i < BGE_TIMEOUT; i++) { - DELAY(10); - val = bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM); - if (val == ~BGE_MAGIC_NUMBER) - break; - } + if (sc->bge_asicrev == BGE_ASICREV_BCM5906) { + for (i = 0; i < BGE_TIMEOUT; i++) { + val = CSR_READ_4(sc, BGE_VCPU_STATUS); + if (val & BGE_VCPU_STATUS_INIT_DONE) + break; + DELAY(100); + } + if (i == BGE_TIMEOUT) { + device_printf(sc->bge_dev, "reset timed out\n"); + return (1); + } + } else { + /* + * Poll until we see the 1's complement of the magic number. + * This indicates that the firmware initialization is complete. + * We expect this to fail if no EEPROM is fitted though. + */ + for (i = 0; i < BGE_TIMEOUT; i++) { + DELAY(10); + val = bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM); + if (val == ~BGE_MAGIC_NUMBER) + break; + } - if ((sc->bge_flags & BGE_FLAG_EEPROM) && i == BGE_TIMEOUT) - device_printf(sc->bge_dev, "firmware handshake timed out, " - "found 0x%08x\n", val); + if ((sc->bge_flags & BGE_FLAG_EEPROM) && i == BGE_TIMEOUT) + device_printf(sc->bge_dev, "firmware handshake timed out, " + "found 0x%08x\n", val); + } /* * XXX Wait for the value of the PCISTATE register to @@ -3034,11 +3179,11 @@ 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); + bge_writembx(sc, BGE_MBX_RX_CONS0_LO, sc->bge_rx_saved_considx); if (stdcnt) - CSR_WRITE_4(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std); + bge_writembx(sc, BGE_MBX_RX_STD_PROD_LO, sc->bge_std); if (jumbocnt) - CSR_WRITE_4(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo); + bge_writembx(sc, BGE_MBX_RX_JUMBO_PROD_LO, sc->bge_jumbo); #ifdef notyet /* * This register wraps very quickly under heavy packet drops. @@ -3180,7 +3325,7 @@ * the status check). So toggling would probably be a pessimization * even with MSI. It would only be needed for using a task queue. */ - CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0); + bge_writembx(sc, BGE_MBX_IRQ0_LO, 0); /* * Do the mandatory PCI flush as well as get the link status. @@ -3557,10 +3702,10 @@ return; /* Transmit. */ - CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); + bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); /* 5700 b2 errata */ if (sc->bge_chiprev == BGE_CHIPREV_5700_BX) - CSR_WRITE_4(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); + bge_writembx(sc, BGE_MBX_TX_HOST_PROD0_LO, prodidx); sc->bge_tx_prodidx = prodidx; @@ -3687,7 +3832,7 @@ if (ifp->if_capenable & IFCAP_POLLING) { BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR); - CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1); + bge_writembx(sc, BGE_MBX_IRQ0_LO, 1); } else #endif @@ -3695,7 +3840,7 @@ { BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLEAR_INTA); BGE_CLRBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR); - CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0); + bge_writembx(sc, BGE_MBX_IRQ0_LO, 0); } bge_ifmedia_upd_locked(ifp); @@ -3918,7 +4063,7 @@ BGE_LOCK(sc); BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR); - CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1); + bge_writembx(sc, BGE_MBX_IRQ0_LO, 1); ifp->if_capenable |= IFCAP_POLLING; BGE_UNLOCK(sc); } else { @@ -3927,7 +4072,7 @@ BGE_LOCK(sc); BGE_CLRBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR); - CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0); + bge_writembx(sc, BGE_MBX_IRQ0_LO, 0); ifp->if_capenable &= ~IFCAP_POLLING; BGE_UNLOCK(sc); } @@ -4052,7 +4197,7 @@ /* Disable host interrupts. */ BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR); - CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1); + bge_writembx(sc, BGE_MBX_IRQ0_LO, 1); /* * Tell firmware we're shutting down. @@ -4548,3 +4693,64 @@ return (error); } #endif + +static int +bge_get_eaddr_mem(struct bge_softc *sc, uint8_t ether_addr[]) +{ + uint32_t mac_addr; + int ret = 1; + + mac_addr = bge_readmem_ind(sc, 0x0c14); + if ((mac_addr >> 16) == 0x484b) { + ether_addr[0] = (uint8_t)(mac_addr >> 8); + ether_addr[1] = (uint8_t)mac_addr; + mac_addr = bge_readmem_ind(sc, 0x0c18); + ether_addr[2] = (uint8_t)(mac_addr >> 24); + ether_addr[3] = (uint8_t)(mac_addr >> 16); + ether_addr[4] = (uint8_t)(mac_addr >> 8); + ether_addr[5] = (uint8_t)mac_addr; + ret = 0; + } + return ret; +} + +static int +bge_get_eaddr_nvram(struct bge_softc *sc, uint8_t ether_addr[]) +{ + int mac_offset = BGE_EE_MAC_OFFSET; + + if (sc->bge_asicrev == BGE_ASICREV_BCM5906) + mac_offset = BGE_EE_MAC_OFFSET_5906; + + return bge_read_nvram(sc, ether_addr, mac_offset + 2, ETHER_ADDR_LEN); +} + +static int +bge_get_eaddr_eeprom(struct bge_softc *sc, uint8_t ether_addr[]) +{ + if (!(sc->bge_flags & BGE_FLAG_EEPROM)) + return 1; + + return bge_read_eeprom(sc, ether_addr, BGE_EE_MAC_OFFSET + 2, + ETHER_ADDR_LEN); +} + +static int +bge_get_eaddr(struct bge_softc *sc, uint8_t eaddr[]) +{ + static const bge_eaddr_fcn_t bge_eaddr_funcs[] = { + /* NOTE: Order is critical */ + bge_get_eaddr_mem, + bge_get_eaddr_nvram, + bge_get_eaddr_eeprom, + NULL + }; + const bge_eaddr_fcn_t *func; + + for (func = bge_eaddr_funcs; *func != NULL; ++func) { + if ((*func)(sc, eaddr) == 0) + break; + } + return (*func == NULL ? ENXIO : 0); +} + Index: dev/bge/if_bgereg.h =================================================================== RCS file: /devel/FreeBSD/ncvs/src/sys/dev/bge/if_bgereg.h,v retrieving revision 1.77 diff -u -r1.77 if_bgereg.h --- dev/bge/if_bgereg.h 6 Mar 2008 21:48:34 -0000 1.77 +++ dev/bge/if_bgereg.h 25 Mar 2008 02:41:09 -0000 @@ -284,6 +284,8 @@ #define BGE_CHIPID_BCM5787_A0 0xb0000000 #define BGE_CHIPID_BCM5787_A1 0xb0010000 #define BGE_CHIPID_BCM5787_A2 0xb0020000 +#define BGE_CHIPID_BCM5906_A1 0xc0010000 +#define BGE_CHIPID_BCM5906_A2 0xc0020000 /* shorthand one */ #define BGE_ASICREV(x) ((x) >> 28) @@ -300,6 +302,7 @@ #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) @@ -1439,6 +1442,17 @@ #define BGE_RXCPUSTAT_MA_REQ_FIFOOFLOW 0x40000000 #define BGE_RXCPUSTAT_BLOCKING_READ 0x80000000 +/* + * V? CPU registers + */ +#define BGE_VCPU_STATUS 0x5100 +#define BGE_VCPU_EXT_CTRL 0x6890 + +#define BGE_VCPU_STATUS_INIT_DONE 0x04000000 +#define BGE_VCPU_STATUS_DRV_RESET 0x08000000 + +#define BGE_VCPU_EXT_CTRL_HALT_CPU 0x00400000 +#define BGE_VCPU_EXT_CTRL_DISABLE_WOL 0x20000000 /* * TX CPU registers @@ -1684,6 +1698,55 @@ #define BGE_MDI_CTL 0x6844 #define BGE_EE_DELAY 0x6848 #define BGE_FASTBOOT_PC 0x6894 +/* + * NVRAM Control registers + */ +#define BGE_NVRAM_CMD 0x7000 +#define BGE_NVRAM_STAT 0x7004 +#define BGE_NVRAM_WRDATA 0x7008 +#define BGE_NVRAM_ADDR 0x700c +#define BGE_NVRAM_RDDATA 0x7010 +#define BGE_NVRAM_CFG1 0x7014 +#define BGE_NVRAM_CFG2 0x7018 +#define BGE_NVRAM_CFG3 0x701c +#define BGE_NVRAM_SWARB 0x7020 +#define BGE_NVRAM_ACCESS 0x7024 +#define BGE_NVRAM_WRITE1 0x7028 + +#define BGE_NVRAMCMD_RESET 0x00000001 +#define BGE_NVRAMCMD_DONE 0x00000008 +#define BGE_NVRAMCMD_START 0x00000010 +#define BGE_NVRAMCMD_WR 0x00000020 /* 1 = wr, 0 = rd */ +#define BGE_NVRAMCMD_ERASE 0x00000040 +#define BGE_NVRAMCMD_FIRST 0x00000080 +#define BGE_NVRAMCMD_LAST 0x00000100 + +#define BGE_NVRAM_READCMD \ + (BGE_NVRAMCMD_FIRST|BGE_NVRAMCMD_LAST| \ + BGE_NVRAMCMD_START|BGE_NVRAMCMD_DONE) +#define BGE_NVRAM_WRITECMD \ + (BGE_NVRAMCMD_FIRST|BGE_NVRAMCMD_LAST| \ + BGE_NVRAMCMD_START|BGE_NVRAMCMD_DONE|BGE_NVRAMCMD_WR) + +#define BGE_NVRAMSWARB_SET0 0x00000001 +#define BGE_NVRAMSWARB_SET1 0x00000002 +#define BGE_NVRAMSWARB_SET2 0x00000003 +#define BGE_NVRAMSWARB_SET3 0x00000004 +#define BGE_NVRAMSWARB_CLR0 0x00000010 +#define BGE_NVRAMSWARB_CLR1 0x00000020 +#define BGE_NVRAMSWARB_CLR2 0x00000040 +#define BGE_NVRAMSWARB_CLR3 0x00000080 +#define BGE_NVRAMSWARB_GNT0 0x00000100 +#define BGE_NVRAMSWARB_GNT1 0x00000200 +#define BGE_NVRAMSWARB_GNT2 0x00000400 +#define BGE_NVRAMSWARB_GNT3 0x00000800 +#define BGE_NVRAMSWARB_REQ0 0x00001000 +#define BGE_NVRAMSWARB_REQ1 0x00002000 +#define BGE_NVRAMSWARB_REQ2 0x00004000 +#define BGE_NVRAMSWARB_REQ3 0x00008000 + +#define BGE_NVRAMACC_ENABLE 0x00000001 +#define BGE_NVRAMACC_WRENABLE 0x00000002 /* Mode control register */ #define BGE_MODECTL_INT_SNDCOAL_ONLY 0x00000001 @@ -1712,6 +1775,7 @@ /* Misc. config register */ #define BGE_MISCCFG_RESET_CORE_CLOCKS 0x00000001 #define BGE_MISCCFG_TIMER_PRESCALER 0x000000FE +#define BGE_MISCCFG_EPHY_IDDQ 0x00200000 #define BGE_32BITTIME_66MHZ (0x41 << 1) @@ -2039,6 +2103,8 @@ #define BCOM_DEVICEID_BCM5901 0x170D #define BCOM_DEVICEID_BCM5901A2 0x170E #define BCOM_DEVICEID_BCM5903M 0x16FF +#define BCOM_DEVICEID_BCM5906 0x1712 +#define BCOM_DEVICEID_BCM5906M 0x1713 /* * Alteon AceNIC PCI vendor/device ID. @@ -2092,6 +2158,7 @@ * Offset of MAC address inside EEPROM. */ #define BGE_EE_MAC_OFFSET 0x7C +#define BGE_EE_MAC_OFFSET_5906 0x10 #define BGE_EE_HWCFG_OFFSET 0xC8 #define BGE_HWCFG_VOLTAGE 0x00000003 @@ -2477,6 +2544,7 @@ #define BGE_FLAG_BER_BUG 0x02000000 #define BGE_FLAG_ADJUST_TRIM 0x04000000 #define BGE_FLAG_CRC_BUG 0x08000000 +#define BGE_FLAG_NO_EEPROM 0x10000000 uint32_t bge_chipid; uint8_t bge_asicrev; uint8_t bge_chiprev; Index: dev/mii/brgphy.c =================================================================== RCS file: /devel/FreeBSD/ncvs/src/sys/dev/mii/brgphy.c,v retrieving revision 1.73 diff -u -r1.73 brgphy.c --- dev/mii/brgphy.c 6 Mar 2008 21:42:48 -0000 1.73 +++ dev/mii/brgphy.c 25 Mar 2008 02:47:22 -0000 @@ -134,6 +134,7 @@ MII_PHY_DESC(xxBROADCOM_ALT1, BCM5709CAX), MII_PHY_DESC(xxBROADCOM_ALT1, BCM5722), MII_PHY_DESC(xxBROADCOM_ALT1, BCM5709C), + MII_PHY_DESC(BROADCOM2, BCM5906), MII_PHY_END }; @@ -189,6 +190,7 @@ /* Handle any special cases based on the PHY ID */ switch (bsc->mii_oui) { case MII_OUI_BROADCOM: + case MII_OUI_BROADCOM2: break; case MII_OUI_xxBROADCOM: switch (bsc->mii_model) { @@ -229,12 +231,14 @@ bce_sc = ifp->if_softc; } - /* Todo: Need to add additional controllers such as 5906 & 5787F */ + /* Todo: Need to add additional controllers such as 5787F */ /* The 590x chips are 10/100 only. */ if (bge_sc && pci_get_vendor(bge_sc->bge_dev) == BCOM_VENDORID && (pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901 || - pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901A2)) { + pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901A2 || + pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5906 || + pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5906M)) { fast_ether = 1; sc->mii_anegticks = MII_ANEGTICKS; } @@ -927,6 +931,11 @@ PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) & ~BRGPHY_PHY_EXTCTL_3_LED); } + + /* Adjust output voltage (From Linux driver) */ + if (bge_sc->bge_asicrev == BGE_ASICREV_BCM5906) + PHY_WRITE(sc, BRGPHY_MII_EPHY_PTEST, 0x12); + /* Handle any bce (NetXtreme II) workarounds. */ } else if (bce_sc) { Index: dev/mii/brgphyreg.h =================================================================== RCS file: /devel/FreeBSD/ncvs/src/sys/dev/mii/brgphyreg.h,v retrieving revision 1.10 diff -u -r1.10 brgphyreg.h --- dev/mii/brgphyreg.h 7 Jun 2007 02:21:38 -0000 1.10 +++ dev/mii/brgphyreg.h 25 Mar 2008 02:41:09 -0000 @@ -161,6 +161,7 @@ #define BRGPHY_MII_DSP_RW_PORT 0x15 /* DSP coefficient r/w port */ #define BRGPHY_MII_DSP_ADDR_REG 0x17 /* DSP coefficient addr register */ +#define BRGPHY_MII_EPHY_PTEST 0x17 /* 5906 PHY register */ #define BRGPHY_DSP_TAP_NUMBER_MASK 0x00 #define BRGPHY_DSP_AGC_A 0x00 Index: dev/mii/miidevs =================================================================== RCS file: /devel/FreeBSD/ncvs/src/sys/dev/mii/miidevs,v retrieving revision 1.51 diff -u -r1.51 miidevs --- dev/mii/miidevs 6 Mar 2008 21:42:48 -0000 1.51 +++ dev/mii/miidevs 25 Mar 2008 02:43:03 -0000 @@ -52,6 +52,7 @@ oui ALTIMA 0x0010a9 Altima Communications oui AMD 0x00001a Advanced Micro Devices oui BROADCOM 0x001018 Broadcom Corporation +oui BROADCOM2 0x000af7 Broadcom Corporation oui CICADA 0x0003F1 Cicada Semiconductor oui DAVICOM 0x00606e Davicom Semiconductor oui ICPLUS 0x0090c3 IC Plus Corp. @@ -138,6 +139,7 @@ model xxBROADCOM_ALT1 BCM5709CAX 0x002c BCM5709C(AX) 10/100/1000baseTX PHY model xxBROADCOM_ALT1 BCM5722 0x002d BCM5722 10/100/1000baseTX PHY model xxBROADCOM_ALT1 BCM5709C 0x003c BCM5709C 10/100/1000baseTX PHY +model BROADCOM2 BCM5906 0x0004 BCM5906 10/100baseTX PHY /* Cicada Semiconductor PHYs (now owned by Vitesse?) */ model CICADA CS8201 0x0001 Cicada CS8201 10/100/1000TX PHY