Add support for the BCM5906[M] adapters. These adapters only support
10/100 operation and place the mailbox registers at a different offset. They also do not have an EEPROM, so the MAC address must be read from NVRAM instead. MFC after: 1 month PR: kern/118975 Submitted by: benjsc, Thomas Nyström thn at saeab dot se Submitted by: sephe (original patch for DragonflyBSD)
This commit is contained in:
parent
624e4d168d
commit
38cc658ff6
@ -196,6 +196,8 @@ static struct bge_type {
|
||||
{ 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 @@ static const struct bge_revision {
|
||||
{ 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 @@ static const struct bge_revision bge_majorrevs[] = {
|
||||
{ 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 @@ static const struct bge_revision bge_majorrevs[] = {
|
||||
|
||||
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 void bge_dma_map_addr(void *, bus_dma_segment_t *, int, int);
|
||||
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_locked(struct ifnet *);
|
||||
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_blockinit(struct bge_softc *);
|
||||
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 @@ bge_has_eeprom(struct bge_softc *sc)
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sc->bge_asicrev == BGE_ASICREV_BCM5906)
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -535,6 +556,15 @@ bge_writemem_direct(struct bge_softc *sc, int off, int val)
|
||||
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 @@ bge_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
||||
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 @@ bge_miibus_readreg(device_t dev, int phy, int reg)
|
||||
}
|
||||
|
||||
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 @@ bge_miibus_writereg(device_t dev, int phy, int reg, int val)
|
||||
|
||||
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 @@ bge_miibus_writereg(device_t dev, int phy, int reg, int val)
|
||||
|
||||
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 @@ bge_init_rx_ring_std(struct bge_softc *sc)
|
||||
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_init_rx_ring_jumbo(struct bge_softc *sc)
|
||||
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 @@ bge_init_tx_ring(struct bge_softc *sc)
|
||||
|
||||
/* 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,16 @@ bge_chipinit(struct bge_softc *sc)
|
||||
/* Set the timer prescaler (always 66Mhz) */
|
||||
CSR_WRITE_4(sc, BGE_MISC_CFG, BGE_32BITTIME_66MHZ);
|
||||
|
||||
/* XXX: The Linux tg3 driver does this at the start of brgphy_reset. */
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1310,14 +1433,19 @@ bge_blockinit(struct bge_softc *sc)
|
||||
}
|
||||
|
||||
/* 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);
|
||||
@ -1423,6 +1551,9 @@ bge_blockinit(struct bge_softc *sc)
|
||||
* requirement of all 575x family chips. The Linux driver sets
|
||||
* the lower threshold for all 5705 family chips as well, but there
|
||||
* are reports that it might not need to be so strict.
|
||||
*
|
||||
* XXX Linux does some extra fiddling here for the 5906 parts as
|
||||
* well.
|
||||
*/
|
||||
if (BGE_IS_5705_PLUS(sc))
|
||||
val = 8;
|
||||
@ -1464,15 +1595,15 @@ bge_blockinit(struct bge_softc *sc)
|
||||
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
|
||||
@ -2226,7 +2357,6 @@ bge_attach(device_t dev)
|
||||
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;
|
||||
|
||||
@ -2260,10 +2390,11 @@ bge_attach(device_t dev)
|
||||
sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid);
|
||||
|
||||
/*
|
||||
* Don't enable Ethernet@WireSpeed for the 5700 or the
|
||||
* Don't enable Ethernet@WireSpeed for the 5700, 5906, or the
|
||||
* 5705 A0 and A1 chips.
|
||||
*/
|
||||
if (sc->bge_asicrev != BGE_ASICREV_BCM5700 &&
|
||||
sc->bge_asicrev != BGE_ASICREV_BCM5906 &&
|
||||
sc->bge_chipid != BGE_CHIPID_BCM5705_A0 &&
|
||||
sc->bge_chipid != BGE_CHIPID_BCM5705_A1)
|
||||
sc->bge_flags |= BGE_FLAG_WIRESPEED;
|
||||
@ -2288,6 +2419,7 @@ bge_attach(device_t dev)
|
||||
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:
|
||||
@ -2310,7 +2442,7 @@ bge_attach(device_t dev)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2421,22 +2553,14 @@ bge_attach(device_t dev)
|
||||
}
|
||||
|
||||
#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;
|
||||
@ -2694,7 +2818,8 @@ bge_reset(struct bge_softc *sc)
|
||||
|
||||
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
|
||||
@ -2750,6 +2875,17 @@ bge_reset(struct bge_softc *sc)
|
||||
/* 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. */
|
||||
@ -2794,21 +2930,34 @@ bge_reset(struct bge_softc *sc)
|
||||
} 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
|
||||
@ -3028,11 +3177,11 @@ bge_rxeof(struct bge_softc *sc)
|
||||
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.
|
||||
@ -3174,7 +3323,7 @@ bge_intr(void *xsc)
|
||||
* 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.
|
||||
@ -3551,10 +3700,10 @@ bge_start_locked(struct ifnet *ifp)
|
||||
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;
|
||||
|
||||
@ -3681,7 +3830,7 @@ bge_init_locked(struct bge_softc *sc)
|
||||
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
|
||||
|
||||
@ -3689,7 +3838,7 @@ bge_init_locked(struct bge_softc *sc)
|
||||
{
|
||||
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);
|
||||
@ -3929,7 +4078,7 @@ bge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
||||
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 {
|
||||
@ -3938,7 +4087,7 @@ bge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
||||
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);
|
||||
}
|
||||
@ -4063,7 +4212,7 @@ bge_stop(struct bge_softc *sc)
|
||||
|
||||
/* 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.
|
||||
@ -4559,3 +4708,63 @@ bge_sysctl_mem_read(SYSCTL_HANDLER_ARGS)
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
@ -1685,6 +1699,56 @@
|
||||
#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
|
||||
#define BGE_MODECTL_BYTESWAP_NONFRAME 0x00000002
|
||||
@ -1712,6 +1776,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 +2104,8 @@ struct bge_status_block {
|
||||
#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 +2159,7 @@ struct bge_status_block {
|
||||
* 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 +2545,7 @@ struct bge_softc {
|
||||
#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;
|
||||
|
@ -134,6 +134,7 @@ static const struct mii_phydesc brgphys[] = {
|
||||
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 @@ brgphy_attach(device_t dev)
|
||||
/* 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 @@ brgphy_attach(device_t dev)
|
||||
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 @@ brgphy_reset(struct mii_softc *sc)
|
||||
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) {
|
||||
|
||||
|
@ -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
|
||||
|
@ -52,6 +52,7 @@ $FreeBSD$
|
||||
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 BCM5708S 0x0015 BCM5708S 1000/2500BaseSX PHY
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user