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:
John Baldwin 2008-04-29 19:47:13 +00:00
parent 624e4d168d
commit 38cc658ff6
5 changed files with 351 additions and 61 deletions

View File

@ -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);
}

View File

@ -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;

View File

@ -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) {

View File

@ -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

View File

@ -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