summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <david@gwynne.id.au>2015-01-30 02:08:46 +0000
committerRobert Mustacchi <rm@joyent.com>2015-03-12 10:10:40 -0700
commit087a28d18c24cf4938e8a2617b5127a2fd29ddf4 (patch)
tree3538f594779423e38e4a5159c404dc898b4bab8d
parentfc01d378bd20b13dcb27185d874fc628d851b161 (diff)
downloadillumos-gate-087a28d18c24cf4938e8a2617b5127a2fd29ddf4.tar.gz
3446 Update bge to support missing 57xx/577xx devices
Reviewed by: Dan McDonald <danmcd@omniti.com> Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com> Approved by: Garrett D'Amore <garrett@damore.org>
-rw-r--r--exception_lists/cstyle7
-rw-r--r--usr/src/pkg/manifests/driver-network-bge.mf5
-rw-r--r--usr/src/uts/common/io/bge/bge_chip2.c1462
-rw-r--r--usr/src/uts/common/io/bge/bge_hw.h347
-rw-r--r--usr/src/uts/common/io/bge/bge_impl.h77
-rw-r--r--usr/src/uts/common/io/bge/bge_kstats.c45
-rw-r--r--usr/src/uts/common/io/bge/bge_lint.c18
-rw-r--r--usr/src/uts/common/io/bge/bge_main2.c683
-rw-r--r--usr/src/uts/common/io/bge/bge_mii.c378
-rw-r--r--usr/src/uts/common/io/bge/bge_send.c13
-rw-r--r--usr/src/uts/intel/bge/Makefile4
-rw-r--r--usr/src/uts/sparc/bge/Makefile2
12 files changed, 2477 insertions, 564 deletions
diff --git a/exception_lists/cstyle b/exception_lists/cstyle
index 7b8a7b4d41..d7bac64803 100644
--- a/exception_lists/cstyle
+++ b/exception_lists/cstyle
@@ -878,6 +878,13 @@ usr/src/uts/common/io/bnxe/bnxe_tx.c
usr/src/uts/common/io/bnxe/bnxe_workq.c
usr/src/uts/common/io/bnxe/bnxe.h
usr/src/uts/common/io/bnxe/version.h
+usr/src/uts/common/io/bge/bge_main2.c
+usr/src/uts/common/io/bge/bge_chip2.c
+usr/src/uts/common/io/bge/bge_mii.c
+usr/src/uts/common/io/bge/bge_kstats.c
+usr/src/uts/common/io/bge/bge_impl.h
+usr/src/uts/common/io/bge/bge_send.c
+usr/src/uts/common/io/bge/bge_hw.h
usr/src/uts/common/io/e1000api/e1000_80003es2lan.c
usr/src/uts/common/io/e1000api/e1000_80003es2lan.h
usr/src/uts/common/io/e1000api/e1000_82540.c
diff --git a/usr/src/pkg/manifests/driver-network-bge.mf b/usr/src/pkg/manifests/driver-network-bge.mf
index 74b2555119..0b0cbb6898 100644
--- a/usr/src/pkg/manifests/driver-network-bge.mf
+++ b/usr/src/pkg/manifests/driver-network-bge.mf
@@ -77,11 +77,15 @@ $(i386_ONLY)driver name=bge clone_perms="bge 0666 root sys" \
alias=pci14e4,16a7 \
alias=pci14e4,16a8 \
alias=pci14e4,16c7 \
+ alias=pciex14e4,1643 \
alias=pciex14e4,1655 \
alias=pciex14e4,1656 \
+ alias=pciex14e4,1657 \
alias=pciex14e4,165a \
alias=pciex14e4,165b \
alias=pciex14e4,165c \
+ alias=pciex14e4,165f \
+ alias=pciex14e4,1665 \
alias=pciex14e4,1673 \
alias=pciex14e4,1674 \
alias=pciex14e4,1677 \
@@ -92,6 +96,7 @@ $(i386_ONLY)driver name=bge clone_perms="bge 0666 root sys" \
alias=pciex14e4,1684 \
alias=pciex14e4,1692 \
alias=pciex14e4,169d \
+ alias=pciex14e4,16f3 \
alias=pciex14e4,16fd \
alias=pciex14e4,1713
$(sparc_ONLY)driver name=bge clone_perms="bge 0666 root sys" \
diff --git a/usr/src/uts/common/io/bge/bge_chip2.c b/usr/src/uts/common/io/bge/bge_chip2.c
index f687ce4892..7790c2df6e 100644
--- a/usr/src/uts/common/io/bge/bge_chip2.c
+++ b/usr/src/uts/common/io/bge/bge_chip2.c
@@ -20,16 +20,19 @@
*/
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010-2013, by Broadcom, Inc.
+ * All Rights Reserved.
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates.
+ * All rights reserved.
*/
#include "bge_impl.h"
#define PIO_ADDR(bgep, offset) ((void *)((caddr_t)(bgep)->io_regs+(offset)))
+#define APE_ADDR(bgep, offset) ((void *)((caddr_t)(bgep)->ape_regs+(offset)))
/*
* Future features ... ?
@@ -54,11 +57,6 @@ boolean_t bge_enable_msi = B_TRUE;
boolean_t bge_relaxed_ordering = B_TRUE;
/*
- * Property names
- */
-static char knownids_propname[] = "bge-known-subsystems";
-
-/*
* Patchable globals:
*
* bge_autorecover
@@ -98,7 +96,7 @@ static uint32_t bge_dma_rwctrl_5714 = PDRWCR_VAR_5714;
static uint32_t bge_dma_rwctrl_5715 = PDRWCR_VAR_5715;
uint32_t bge_rx_ticks_norm = 128;
-uint32_t bge_tx_ticks_norm = 2048; /* 8 for FJ2+ !?!? */
+uint32_t bge_tx_ticks_norm = 512;
uint32_t bge_rx_count_norm = 8;
uint32_t bge_tx_count_norm = 128;
@@ -243,8 +241,10 @@ bge_ind_get32(bge_t *bgep, bge_regno_t regno)
BGE_TRACE(("bge_ind_get32($%p, 0x%lx)", (void *)bgep, regno));
#ifdef __sparc
- if (DEVICE_5717_SERIES_CHIPSETS(bgep))
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
regno = LE_32(regno);
+ }
#endif
pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_RIAAR, regno);
val = pci_config_get32(bgep->cfg_handle, PCI_CONF_BGE_RIADR);
@@ -268,8 +268,10 @@ bge_ind_put32(bge_t *bgep, bge_regno_t regno, uint32_t val)
val = LE_32(val);
#ifdef __sparc
- if (DEVICE_5717_SERIES_CHIPSETS(bgep))
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
regno = LE_32(regno);
+ }
#endif
pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_RIAAR, regno);
pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_RIADR, val);
@@ -327,6 +329,8 @@ bge_chip_cfg_init(bge_t *bgep, chip_id_t *cidp, boolean_t enable_dma)
ddi_acc_handle_t handle;
uint16_t command;
uint32_t mhcr;
+ uint32_t prodid;
+ uint32_t pci_state;
uint16_t value16;
int i;
@@ -360,10 +364,23 @@ bge_chip_cfg_init(bge_t *bgep, chip_id_t *cidp, boolean_t enable_dma)
* byte-swapped value to it. So we just write zero first for simplicity.
*/
cidp->device = pci_config_get16(handle, PCI_CONF_DEVID);
- if (DEVICE_5717_SERIES_CHIPSETS(bgep))
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
pci_config_put32(handle, PCI_CONF_BGE_MHCR, 0);
+ }
+
mhcr = pci_config_get32(handle, PCI_CONF_BGE_MHCR);
- cidp->asic_rev = mhcr & MHCR_CHIP_REV_MASK;
+ cidp->asic_rev = (mhcr & MHCR_CHIP_REV_MASK);
+ cidp->asic_rev_prod_id = 0;
+ if ((cidp->asic_rev & 0xf0000000) == CHIP_ASIC_REV_USE_PROD_ID_REG) {
+ prodid = CHIP_ASIC_REV_PROD_ID_REG;
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
+ prodid = CHIP_ASIC_REV_PROD_ID_GEN2_REG;
+ }
+ cidp->asic_rev_prod_id = pci_config_get32(handle, prodid);
+ }
+
cidp->businfo = pci_config_get32(handle, PCI_CONF_BGE_PCISTATE);
cidp->command = pci_config_get16(handle, PCI_CONF_COMM);
@@ -374,6 +391,12 @@ bge_chip_cfg_init(bge_t *bgep, chip_id_t *cidp, boolean_t enable_dma)
cidp->clsize = pci_config_get8(handle, PCI_CONF_CACHE_LINESZ);
cidp->latency = pci_config_get8(handle, PCI_CONF_LATENCY_TIMER);
+ /* 5717 C0 is treated just like 5720 A0 */
+ if (pci_config_get16(bgep->cfg_handle, PCI_CONF_DEVID) ==
+ DEVICE_ID_5717_C0) {
+ cidp->device = DEVICE_ID_5720;
+ }
+
BGE_DEBUG(("bge_chip_cfg_init: %s bus is %s and %s; #INTA is %s",
cidp->businfo & PCISTATE_BUS_IS_PCI ? "PCI" : "PCI-X",
cidp->businfo & PCISTATE_BUS_IS_FAST ? "fast" : "slow",
@@ -445,25 +468,31 @@ bge_chip_cfg_init(bge_t *bgep, chip_id_t *cidp, boolean_t enable_dma)
* see whether the host is truly up to date, and regenerate
* its interrupt if not.
*/
- mhcr = MHCR_ENABLE_INDIRECT_ACCESS |
- MHCR_ENABLE_TAGGED_STATUS_MODE |
- MHCR_MASK_INTERRUPT_MODE |
- MHCR_CLEAR_INTERRUPT_INTA;
-
+ mhcr = MHCR_ENABLE_INDIRECT_ACCESS |
+ MHCR_ENABLE_PCI_STATE_RW |
+ MHCR_ENABLE_TAGGED_STATUS_MODE |
+ MHCR_MASK_INTERRUPT_MODE |
+ MHCR_CLEAR_INTERRUPT_INTA;
if (bgep->intr_type == DDI_INTR_TYPE_FIXED)
mhcr |= MHCR_MASK_PCI_INT_OUTPUT;
#ifdef _BIG_ENDIAN
mhcr |= MHCR_ENABLE_ENDIAN_WORD_SWAP | MHCR_ENABLE_ENDIAN_BYTE_SWAP;
#endif /* _BIG_ENDIAN */
-
- if (DEVICE_5717_SERIES_CHIPSETS(bgep))
- pci_config_put32(handle, PCI_CONF_BGE_MHCR, 0);
pci_config_put32(handle, PCI_CONF_BGE_MHCR, mhcr);
#ifdef BGE_IPMI_ASF
bgep->asf_wordswapped = B_FALSE;
#endif
+
+ pci_state = (PCISTATE_EXT_ROM_ENABLE | PCISTATE_EXT_ROM_RETRY);
+ /* allow reads and writes to the APE register and memory space */
+ if (bgep->ape_enabled) {
+ pci_state |= PCISTATE_ALLOW_APE_CTLSPC_WR |
+ PCISTATE_ALLOW_APE_SHMEM_WR | PCISTATE_ALLOW_APE_PSPACE_WR;
+ }
+ pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_PCISTATE, pci_state);
+
/*
* Step 1 (also step 7): Enable PCI Memory Space accesses
* Disable Memory Write/Invalidate
@@ -533,9 +562,14 @@ bge_chip_cfg_init(bge_t *bgep, chip_id_t *cidp, boolean_t enable_dma)
if (DEVICE_5723_SERIES_CHIPSETS(bgep)) {
bge_cfg_clr16(bgep, PCI_CONF_DEV_CTRL_5723,
DEV_CTRL_NO_SNOOP | DEV_CTRL_RELAXED);
- } else
+ } else if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
+ bge_cfg_clr16(bgep, PCI_CONF_DEV_CTRL_5717,
+ DEV_CTRL_NO_SNOOP | DEV_CTRL_RELAXED);
+ } else {
bge_cfg_clr16(bgep, PCI_CONF_DEV_CTRL,
DEV_CTRL_NO_SNOOP | DEV_CTRL_RELAXED);
+ }
}
}
@@ -629,8 +663,10 @@ bge_reg_get64(bge_t *bgep, bge_regno_t regno)
uint64_t regval;
#ifdef __amd64
- if (DEVICE_5723_SERIES_CHIPSETS(bgep) || bge_get_em64t_type() ||
- DEVICE_5717_SERIES_CHIPSETS(bgep)) {
+ if (DEVICE_5723_SERIES_CHIPSETS(bgep) ||
+ bge_get_em64t_type() ||
+ DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
regval = ddi_get32(bgep->io_handle, PIO_ADDR(bgep, regno + 4));
regval <<= 32;
regval |= ddi_get32(bgep->io_handle, PIO_ADDR(bgep, regno));
@@ -639,7 +675,8 @@ bge_reg_get64(bge_t *bgep, bge_regno_t regno)
}
#elif defined(__sparc)
if (DEVICE_5723_SERIES_CHIPSETS(bgep) ||
- DEVICE_5717_SERIES_CHIPSETS(bgep)) {
+ DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
regval = ddi_get32(bgep->io_handle, PIO_ADDR(bgep, regno));
regval <<= 32;
regval |= ddi_get32(bgep->io_handle, PIO_ADDR(bgep, regno + 4));
@@ -674,8 +711,10 @@ bge_reg_put64(bge_t *bgep, bge_regno_t regno, uint64_t data)
#endif /* _LITTLE_ENDIAN */
#ifdef __amd64
- if (DEVICE_5723_SERIES_CHIPSETS(bgep) || bge_get_em64t_type() ||
- DEVICE_5717_SERIES_CHIPSETS(bgep)) {
+ if (DEVICE_5723_SERIES_CHIPSETS(bgep) ||
+ bge_get_em64t_type() ||
+ DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
ddi_put32(bgep->io_handle,
PIO_ADDR(bgep, regno), (uint32_t)data);
BGE_PCICHK(bgep);
@@ -687,7 +726,8 @@ bge_reg_put64(bge_t *bgep, bge_regno_t regno, uint64_t data)
}
#elif defined(__sparc)
if (DEVICE_5723_SERIES_CHIPSETS(bgep) ||
- DEVICE_5717_SERIES_CHIPSETS(bgep)) {
+ DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
ddi_put32(bgep->io_handle,
PIO_ADDR(bgep, regno + 4), (uint32_t)data);
BGE_PCICHK(bgep);
@@ -845,8 +885,10 @@ bge_nic_setwin(bge_t *bgep, bge_regno_t base)
B_TRUE : B_FALSE);
}
#ifdef __sparc
- if (DEVICE_5717_SERIES_CHIPSETS(bgep))
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
base = LE_32(base);
+ }
#endif
pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MWBAR, base);
}
@@ -905,8 +947,10 @@ bge_nic_put32(bge_t *bgep, bge_regno_t addr, uint32_t data)
#endif
#ifdef __sparc
- if (DEVICE_5717_SERIES_CHIPSETS(bgep))
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
addr = LE_32(addr);
+ }
pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MWBAR, addr);
data = LE_32(data);
pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MWDAR, data);
@@ -933,8 +977,10 @@ bge_nic_get64(bge_t *bgep, bge_regno_t addr)
addr += NIC_MEM_WINDOW_OFFSET;
#ifdef __amd64
- if (DEVICE_5723_SERIES_CHIPSETS(bgep) || bge_get_em64t_type() ||
- DEVICE_5717_SERIES_CHIPSETS(bgep)) {
+ if (DEVICE_5723_SERIES_CHIPSETS(bgep) ||
+ bge_get_em64t_type() ||
+ DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
data = ddi_get32(bgep->io_handle,
PIO_ADDR(bgep, addr + 4));
data <<= 32;
@@ -944,7 +990,8 @@ bge_nic_get64(bge_t *bgep, bge_regno_t addr)
}
#elif defined(__sparc)
if (DEVICE_5723_SERIES_CHIPSETS(bgep) ||
- DEVICE_5717_SERIES_CHIPSETS(bgep)) {
+ DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
data = ddi_get32(bgep->io_handle, PIO_ADDR(bgep, addr));
data <<= 32;
data |= ddi_get32(bgep->io_handle,
@@ -976,8 +1023,10 @@ bge_nic_put64(bge_t *bgep, bge_regno_t addr, uint64_t data)
addr += NIC_MEM_WINDOW_OFFSET;
#ifdef __amd64
- if (DEVICE_5723_SERIES_CHIPSETS(bgep) || bge_get_em64t_type() ||
- DEVICE_5717_SERIES_CHIPSETS(bgep)) {
+ if (DEVICE_5723_SERIES_CHIPSETS(bgep) ||
+ bge_get_em64t_type() ||
+ DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
ddi_put32(bgep->io_handle,
PIO_ADDR(bgep, addr + 4), (uint32_t)data);
BGE_PCICHK(bgep);
@@ -988,7 +1037,8 @@ bge_nic_put64(bge_t *bgep, bge_regno_t addr, uint64_t data)
}
#elif defined(__sparc)
if (DEVICE_5723_SERIES_CHIPSETS(bgep) ||
- DEVICE_5717_SERIES_CHIPSETS(bgep)) {
+ DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
ddi_put32(bgep->io_handle,
PIO_ADDR(bgep, addr + 4), (uint32_t)data);
BGE_PCICHK(bgep);
@@ -1028,8 +1078,10 @@ bge_nic_putrcb(bge_t *bgep, bge_regno_t addr, bge_rcb_t *rcbp)
p = (void *)rcbp;
#ifdef __amd64
- if (DEVICE_5723_SERIES_CHIPSETS(bgep) || bge_get_em64t_type() ||
- DEVICE_5717_SERIES_CHIPSETS(bgep)) {
+ if (DEVICE_5723_SERIES_CHIPSETS(bgep) ||
+ bge_get_em64t_type() ||
+ DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
ddi_put32(bgep->io_handle, PIO_ADDR(bgep, addr),
(uint32_t)(*p));
ddi_put32(bgep->io_handle, PIO_ADDR(bgep, addr + 4),
@@ -1045,7 +1097,8 @@ bge_nic_putrcb(bge_t *bgep, bge_regno_t addr, bge_rcb_t *rcbp)
}
#elif defined(__sparc)
if (DEVICE_5723_SERIES_CHIPSETS(bgep) ||
- DEVICE_5717_SERIES_CHIPSETS(bgep)) {
+ DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
ddi_put32(bgep->io_handle, PIO_ADDR(bgep, addr + 4),
(uint32_t)(*p));
ddi_put32(bgep->io_handle, PIO_ADDR(bgep, addr),
@@ -1246,6 +1299,32 @@ bge_mii_put16(bge_t *bgep, bge_regno_t regno, uint16_t data)
(void) bge_mii_access(bgep, regno, data, MI_COMMS_COMMAND_WRITE);
}
+uint16_t
+bge_phydsp_read(bge_t *bgep, bge_regno_t regno)
+{
+ BGE_TRACE(("bge_phydsp_read($%p, 0x%lx)",
+ (void *)bgep, regno));
+
+ ASSERT(mutex_owned(bgep->genlock));
+
+ bge_mii_put16(bgep, MII_DSP_ADDRESS, regno);
+ return bge_mii_get16(bgep, MII_DSP_RW_PORT);
+}
+
+#pragma no_inline(bge_phydsp_write)
+
+void
+bge_phydsp_write(bge_t *bgep, bge_regno_t regno, uint16_t data)
+{
+ BGE_TRACE(("bge_phydsp_write($%p, 0x%lx, 0x%x)",
+ (void *)bgep, regno, data));
+
+ ASSERT(mutex_owned(bgep->genlock));
+
+ bge_mii_put16(bgep, MII_DSP_ADDRESS, regno);
+ bge_mii_put16(bgep, MII_DSP_RW_PORT, data);
+}
+
#undef BGE_DBG
#define BGE_DBG BGE_DBG_SEEPROM /* debug flag for this code */
@@ -1720,6 +1799,7 @@ bge_nvmem_rw32(bge_t *bgep, uint32_t cmd, bge_regno_t addr, uint32_t *dp)
if (DEVICE_5721_SERIES_CHIPSETS(bgep) ||
DEVICE_5723_SERIES_CHIPSETS(bgep) ||
DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep) ||
DEVICE_5714_SERIES_CHIPSETS(bgep)) {
bge_reg_set32(bgep, NVM_ACCESS_REG,
NVM_ACCESS_ENABLE);
@@ -1729,6 +1809,7 @@ bge_nvmem_rw32(bge_t *bgep, uint32_t cmd, bge_regno_t addr, uint32_t *dp)
if (DEVICE_5721_SERIES_CHIPSETS(bgep) ||
DEVICE_5723_SERIES_CHIPSETS(bgep) ||
DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep) ||
DEVICE_5714_SERIES_CHIPSETS(bgep)) {
bge_reg_clr32(bgep, NVM_ACCESS_REG,
NVM_ACCESS_ENABLE);
@@ -1739,6 +1820,7 @@ bge_nvmem_rw32(bge_t *bgep, uint32_t cmd, bge_regno_t addr, uint32_t *dp)
if (DEVICE_5721_SERIES_CHIPSETS(bgep) ||
DEVICE_5723_SERIES_CHIPSETS(bgep) ||
DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep) ||
DEVICE_5714_SERIES_CHIPSETS(bgep)) {
bge_reg_set32(bgep, NVM_ACCESS_REG,
NVM_WRITE_ENABLE|NVM_ACCESS_ENABLE);
@@ -1750,6 +1832,7 @@ bge_nvmem_rw32(bge_t *bgep, uint32_t cmd, bge_regno_t addr, uint32_t *dp)
if (DEVICE_5721_SERIES_CHIPSETS(bgep) ||
DEVICE_5723_SERIES_CHIPSETS(bgep) ||
DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep) ||
DEVICE_5714_SERIES_CHIPSETS(bgep)) {
bge_reg_clr32(bgep, NVM_ACCESS_REG,
NVM_WRITE_ENABLE|NVM_ACCESS_ENABLE);
@@ -1768,6 +1851,42 @@ bge_nvmem_rw32(bge_t *bgep, uint32_t cmd, bge_regno_t addr, uint32_t *dp)
return (err);
}
+static uint32_t
+bge_nvmem_access_cmd(bge_t *bgep, boolean_t read)
+{
+ switch (bgep->chipid.nvtype) {
+ case BGE_NVTYPE_NONE:
+ case BGE_NVTYPE_UNKNOWN:
+ default:
+ return 0;
+
+ case BGE_NVTYPE_SEEPROM:
+ case BGE_NVTYPE_LEGACY_SEEPROM:
+ return (read ? BGE_SEE_READ : BGE_SEE_WRITE);
+
+ case BGE_NVTYPE_UNBUFFERED_FLASH:
+ case BGE_NVTYPE_BUFFERED_FLASH:
+ return (read ? BGE_FLASH_READ : BGE_FLASH_WRITE);
+ }
+}
+
+
+int
+bge_nvmem_read32(bge_t *bgep, bge_regno_t addr, uint32_t *dp)
+{
+ return (bge_nvmem_rw32(bgep, bge_nvmem_access_cmd(bgep, B_TRUE),
+ addr, dp));
+}
+
+
+int
+bge_nvmem_write32(bge_t *bgep, bge_regno_t addr, uint32_t *dp)
+{
+ return (bge_nvmem_rw32(bgep, bge_nvmem_access_cmd(bgep, B_FALSE),
+ addr, dp));
+}
+
+
/*
* Attempt to get a MAC address from the SEEPROM or Flash, if any
*/
@@ -1896,7 +2015,11 @@ bge_nvmem_id(bge_t *bgep)
case DEVICE_ID_5705_2:
case DEVICE_ID_5717:
case DEVICE_ID_5718:
+ case DEVICE_ID_5719:
+ case DEVICE_ID_5720:
case DEVICE_ID_5724:
+ case DEVICE_ID_5725:
+ case DEVICE_ID_5727:
case DEVICE_ID_57780:
case DEVICE_ID_5780:
case DEVICE_ID_5782:
@@ -1942,6 +2065,453 @@ bge_nvmem_id(bge_t *bgep)
}
#undef BGE_DBG
+#define BGE_DBG BGE_DBG_APE /* debug flag for this code */
+
+uint32_t bge_ape_get32(bge_t *bgep, bge_regno_t regno);
+#pragma inline(bge_ape_get32)
+
+uint32_t
+bge_ape_get32(bge_t *bgep, bge_regno_t regno)
+{
+ BGE_TRACE(("bge_ape_get32($%p, 0x%lx)",
+ (void *)bgep, regno));
+
+ return (ddi_get32(bgep->ape_handle, APE_ADDR(bgep, regno)));
+}
+
+void bge_ape_put32(bge_t *bgep, bge_regno_t regno, uint32_t data);
+#pragma inline(bge_ape_put32)
+
+void
+bge_ape_put32(bge_t *bgep, bge_regno_t regno, uint32_t data)
+{
+ BGE_TRACE(("bge_ape_put32($%p, 0x%lx, 0x%x)",
+ (void *)bgep, regno, data));
+
+ ddi_put32(bgep->ape_handle, APE_ADDR(bgep, regno), data);
+ BGE_PCICHK(bgep);
+}
+
+void
+bge_ape_lock_init(bge_t *bgep)
+{
+ int i;
+ uint32_t regbase;
+ uint32_t bit;
+
+ BGE_TRACE(("bge_ape_lock_init($%p)", (void *)bgep));
+
+ if (bgep->chipid.device == DEVICE_ID_5761)
+ regbase = BGE_APE_LOCK_GRANT;
+ else
+ regbase = BGE_APE_PER_LOCK_GRANT;
+
+ /* Make sure the driver hasn't any stale locks. */
+ for (i = BGE_APE_LOCK_PHY0; i <= BGE_APE_LOCK_GPIO; i++) {
+ switch (i) {
+ case BGE_APE_LOCK_PHY0:
+ case BGE_APE_LOCK_PHY1:
+ case BGE_APE_LOCK_PHY2:
+ case BGE_APE_LOCK_PHY3:
+ bit = APE_LOCK_GRANT_DRIVER;
+ break;
+ default:
+ if (!bgep->pci_func)
+ bit = APE_LOCK_GRANT_DRIVER;
+ else
+ bit = 1 << bgep->pci_func;
+ }
+ bge_ape_put32(bgep, regbase + 4 * i, bit);
+ }
+}
+
+static int
+bge_ape_lock(bge_t *bgep, int locknum)
+{
+ int i, off;
+ int ret = 0;
+ uint32_t status;
+ uint32_t req;
+ uint32_t gnt;
+ uint32_t bit;
+
+ BGE_TRACE(("bge_ape_lock($%p, 0x%x)", (void *)bgep, locknum));
+
+ if (!bgep->ape_enabled)
+ return (0);
+
+ switch (locknum) {
+ case BGE_APE_LOCK_GPIO:
+ if (bgep->chipid.device == DEVICE_ID_5761)
+ return (0);
+ case BGE_APE_LOCK_GRC:
+ case BGE_APE_LOCK_MEM:
+ if (!bgep->pci_func)
+ bit = APE_LOCK_REQ_DRIVER;
+ else
+ bit = 1 << bgep->pci_func;
+ break;
+ case BGE_APE_LOCK_PHY0:
+ case BGE_APE_LOCK_PHY1:
+ case BGE_APE_LOCK_PHY2:
+ case BGE_APE_LOCK_PHY3:
+ bit = APE_LOCK_REQ_DRIVER;
+ break;
+ default:
+ return (-1);
+ }
+
+ if (bgep->chipid.device == DEVICE_ID_5761) {
+ req = BGE_APE_LOCK_REQ;
+ gnt = BGE_APE_LOCK_GRANT;
+ } else {
+ req = BGE_APE_PER_LOCK_REQ;
+ gnt = BGE_APE_PER_LOCK_GRANT;
+ }
+
+ off = 4 * locknum;
+
+ bge_ape_put32(bgep, req + off, bit);
+
+ /* Wait for up to 1 millisecond to acquire lock. */
+ for (i = 0; i < 100; i++) {
+ status = bge_ape_get32(bgep, gnt + off);
+ if (status == bit)
+ break;
+ drv_usecwait(10);
+ }
+
+ if (status != bit) {
+ /* Revoke the lock request. */
+ bge_ape_put32(bgep, gnt + off, bit);
+ ret = -1;
+ }
+
+ return (ret);
+}
+
+static void
+bge_ape_unlock(bge_t *bgep, int locknum)
+{
+ uint32_t gnt;
+ uint32_t bit;
+
+ BGE_TRACE(("bge_ape_unlock($%p, 0x%x)", (void *)bgep, locknum));
+
+ if (!bgep->ape_enabled)
+ return;
+
+ switch (locknum) {
+ case BGE_APE_LOCK_GPIO:
+ if (bgep->chipid.device == DEVICE_ID_5761)
+ return;
+ case BGE_APE_LOCK_GRC:
+ case BGE_APE_LOCK_MEM:
+ if (!bgep->pci_func)
+ bit = APE_LOCK_GRANT_DRIVER;
+ else
+ bit = 1 << bgep->pci_func;
+ break;
+ case BGE_APE_LOCK_PHY0:
+ case BGE_APE_LOCK_PHY1:
+ case BGE_APE_LOCK_PHY2:
+ case BGE_APE_LOCK_PHY3:
+ bit = APE_LOCK_GRANT_DRIVER;
+ break;
+ default:
+ return;
+ }
+
+ if (bgep->chipid.device == DEVICE_ID_5761)
+ gnt = BGE_APE_LOCK_GRANT;
+ else
+ gnt = BGE_APE_PER_LOCK_GRANT;
+
+ bge_ape_put32(bgep, gnt + 4 * locknum, bit);
+}
+
+/* wait for pending event to finish, if successful returns with MEM locked */
+static int
+bge_ape_event_lock(bge_t *bgep, uint32_t timeout_us)
+{
+ uint32_t apedata;
+
+ BGE_TRACE(("bge_ape_event_lock($%p, %d)", (void *)bgep, timeout_us));
+
+ ASSERT(timeout_us > 0);
+
+ while (timeout_us) {
+ if (bge_ape_lock(bgep, BGE_APE_LOCK_MEM))
+ return (-1);
+
+ apedata = bge_ape_get32(bgep, BGE_APE_EVENT_STATUS);
+ if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
+ break;
+
+ bge_ape_unlock(bgep, BGE_APE_LOCK_MEM);
+
+ drv_usecwait(10);
+ timeout_us -= (timeout_us > 10) ? 10 : timeout_us;
+ }
+
+ return (timeout_us ? 0 : -1);
+}
+
+/* wait for pending event to finish, returns non-zero if not finished */
+static int
+bge_ape_wait_for_event(bge_t *bgep, uint32_t timeout_us)
+{
+ uint32_t i;
+ uint32_t apedata;
+
+ BGE_TRACE(("bge_ape_wait_for_event($%p, %d)", (void *)bgep, timeout_us));
+
+ ASSERT(timeout_us > 0);
+
+ for (i = 0; i < timeout_us / 10; i++) {
+ apedata = bge_ape_get32(bgep, BGE_APE_EVENT_STATUS);
+
+ if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
+ break;
+
+ drv_usecwait(10);
+ }
+
+ return (i == timeout_us / 10);
+}
+
+int
+bge_ape_scratchpad_read(bge_t *bgep, uint32_t *data, uint32_t base_off,
+ uint32_t lenToRead)
+{
+ int err;
+ uint32_t i;
+ uint32_t bufoff;
+ uint32_t msgoff;
+ uint32_t maxlen;
+ uint32_t apedata;
+
+ BGE_TRACE(("bge_ape_scratchpad_read($%p, %p, 0x%0x, %d)",
+ (void *)bgep, (void*)data, base_off, lenToRead));
+
+ if (!bgep->ape_has_ncsi)
+ return (0);
+
+ apedata = bge_ape_get32(bgep, BGE_APE_SEG_SIG);
+ if (apedata != APE_SEG_SIG_MAGIC)
+ return (-1);
+
+ apedata = bge_ape_get32(bgep, BGE_APE_FW_STATUS);
+ if (!(apedata & APE_FW_STATUS_READY))
+ return (-1);
+
+ bufoff = (bge_ape_get32(bgep, BGE_APE_SEG_MSG_BUF_OFF) +
+ BGE_APE_SHMEM_BASE);
+ msgoff = bufoff + 2 * sizeof(uint32_t);
+ maxlen = bge_ape_get32(bgep, BGE_APE_SEG_MSG_BUF_LEN);
+
+ while (lenToRead) {
+ uint32_t transferLen;
+
+ /* Cap xfer sizes to scratchpad limits. */
+ transferLen = (lenToRead > maxlen) ? maxlen : lenToRead;
+ lenToRead -= transferLen;
+
+ apedata = bge_ape_get32(bgep, BGE_APE_FW_STATUS);
+ if (!(apedata & APE_FW_STATUS_READY))
+ return (-1);
+
+ /* Wait for up to 1 millisecond for APE to service previous event. */
+ err = bge_ape_event_lock(bgep, 1000);
+ if (err)
+ return (err);
+
+ apedata = (APE_EVENT_STATUS_DRIVER_EVNT |
+ APE_EVENT_STATUS_SCRTCHPD_READ |
+ APE_EVENT_STATUS_EVENT_PENDING);
+ bge_ape_put32(bgep, BGE_APE_EVENT_STATUS, apedata);
+
+ bge_ape_put32(bgep, bufoff, base_off);
+ bge_ape_put32(bgep, bufoff + sizeof(uint32_t), transferLen);
+
+ bge_ape_unlock(bgep, BGE_APE_LOCK_MEM);
+ bge_ape_put32(bgep, BGE_APE_EVENT, APE_EVENT_1);
+
+ base_off += transferLen;
+
+ if (bge_ape_wait_for_event(bgep, 30000))
+ return (-1);
+
+ for (i = 0; transferLen; i += 4, transferLen -= 4) {
+ uint32_t val = bge_ape_get32(bgep, msgoff + i);
+ memcpy(data, &val, sizeof(uint32_t));
+ data++;
+ }
+ }
+
+ return (0);
+}
+
+int
+bge_ape_scratchpad_write(bge_t *bgep, uint32_t dstoff, uint32_t *data,
+ uint32_t lenToWrite)
+{
+ int err;
+ uint32_t i;
+ uint32_t bufoff;
+ uint32_t msgoff;
+ uint32_t maxlen;
+ uint32_t apedata;
+
+ BGE_TRACE(("bge_ape_scratchpad_write($%p, %d, %p, %d)",
+ (void *)bgep, dstoff, data, lenToWrite));
+
+ if (!bgep->ape_has_ncsi)
+ return (0);
+
+ apedata = bge_ape_get32(bgep, BGE_APE_SEG_SIG);
+ if (apedata != APE_SEG_SIG_MAGIC)
+ return (-1);
+
+ apedata = bge_ape_get32(bgep, BGE_APE_FW_STATUS);
+ if (!(apedata & APE_FW_STATUS_READY))
+ return (-1);
+
+ bufoff = (bge_ape_get32(bgep, BGE_APE_SEG_MSG_BUF_OFF) +
+ BGE_APE_SHMEM_BASE);
+ msgoff = bufoff + 2 * sizeof(uint32_t);
+ maxlen = bge_ape_get32(bgep, BGE_APE_SEG_MSG_BUF_LEN);
+
+ while (lenToWrite) {
+ uint32_t transferLen;
+
+ /* Cap xfer sizes to scratchpad limits. */
+ transferLen = (lenToWrite > maxlen) ? maxlen : lenToWrite;
+ lenToWrite -= transferLen;
+
+ /* Wait for up to 1 millisecond for
+ * APE to service previous event.
+ */
+ err = bge_ape_event_lock(bgep, 1000);
+ if (err)
+ return (err);
+
+ bge_ape_put32(bgep, bufoff, dstoff);
+ bge_ape_put32(bgep, bufoff + sizeof(uint32_t), transferLen);
+ apedata = msgoff;
+
+ dstoff += transferLen;
+
+ for (i = 0; transferLen; i += 4, transferLen -= 4) {
+ bge_ape_put32(bgep, apedata, *data++);
+ apedata += sizeof(uint32_t);
+ }
+
+ apedata = (APE_EVENT_STATUS_DRIVER_EVNT |
+ APE_EVENT_STATUS_SCRTCHPD_WRITE |
+ APE_EVENT_STATUS_EVENT_PENDING);
+ bge_ape_put32(bgep, BGE_APE_EVENT_STATUS, apedata);
+
+ bge_ape_unlock(bgep, BGE_APE_LOCK_MEM);
+ bge_ape_put32(bgep, BGE_APE_EVENT, APE_EVENT_1);
+ }
+
+ return (0);
+}
+
+static int
+bge_ape_send_event(bge_t *bgep, uint32_t event)
+{
+ int err;
+ uint32_t apedata;
+
+ BGE_TRACE(("bge_ape_send_event($%p, %d)", (void *)bgep, event));
+
+ apedata = bge_ape_get32(bgep, BGE_APE_SEG_SIG);
+ if (apedata != APE_SEG_SIG_MAGIC)
+ return (-1);
+
+ apedata = bge_ape_get32(bgep, BGE_APE_FW_STATUS);
+ if (!(apedata & APE_FW_STATUS_READY))
+ return (-1);
+
+ /* Wait for up to 1 millisecond for APE to service previous event. */
+ err = bge_ape_event_lock(bgep, 1000);
+ if (err)
+ return (err);
+
+ bge_ape_put32(bgep, BGE_APE_EVENT_STATUS,
+ event | APE_EVENT_STATUS_EVENT_PENDING);
+
+ bge_ape_unlock(bgep, BGE_APE_LOCK_MEM);
+ bge_ape_put32(bgep, BGE_APE_EVENT, APE_EVENT_1);
+
+ return 0;
+}
+
+static void
+bge_ape_driver_state_change(bge_t *bgep, int mode)
+{
+ uint32_t event;
+ uint32_t apedata;
+
+ BGE_TRACE(("bge_ape_driver_state_change($%p, %d)",
+ (void *)bgep, mode));
+
+ if (!bgep->ape_enabled)
+ return;
+
+ switch (mode) {
+ case BGE_INIT_RESET:
+ bge_ape_put32(bgep, BGE_APE_HOST_SEG_SIG,
+ APE_HOST_SEG_SIG_MAGIC);
+ bge_ape_put32(bgep, BGE_APE_HOST_SEG_LEN,
+ APE_HOST_SEG_LEN_MAGIC);
+ apedata = bge_ape_get32(bgep, BGE_APE_HOST_INIT_COUNT);
+ bge_ape_put32(bgep, BGE_APE_HOST_INIT_COUNT, ++apedata);
+ bge_ape_put32(bgep, BGE_APE_HOST_DRIVER_ID,
+ APE_HOST_DRIVER_ID_MAGIC(1, 0));
+ bge_ape_put32(bgep, BGE_APE_HOST_BEHAVIOR,
+ APE_HOST_BEHAV_NO_PHYLOCK);
+ bge_ape_put32(bgep, BGE_APE_HOST_DRVR_STATE,
+ BGE_APE_HOST_DRVR_STATE_START);
+
+ event = APE_EVENT_STATUS_STATE_START;
+ break;
+ case BGE_SHUTDOWN_RESET:
+ /* With the interface we are currently using,
+ * APE does not track driver state. Wiping
+ * out the HOST SEGMENT SIGNATURE forces
+ * the APE to assume OS absent status.
+ */
+ bge_ape_put32(bgep, BGE_APE_HOST_SEG_SIG, 0x0);
+
+#if 0
+ if (WOL supported) {
+ bge_ape_put32(bgep, BGE_APE_HOST_WOL_SPEED,
+ BGE_APE_HOST_WOL_SPEED_AUTO);
+ apedata = BGE_APE_HOST_DRVR_STATE_WOL;
+ } else
+#endif
+ apedata = BGE_APE_HOST_DRVR_STATE_UNLOAD;
+
+ bge_ape_put32(bgep, BGE_APE_HOST_DRVR_STATE, apedata);
+
+ event = APE_EVENT_STATUS_STATE_UNLOAD;
+ break;
+ case BGE_SUSPEND_RESET:
+ event = APE_EVENT_STATUS_STATE_SUSPEND;
+ break;
+ default:
+ return;
+ }
+
+ event |= APE_EVENT_STATUS_DRIVER_EVNT | APE_EVENT_STATUS_STATE_CHNGE;
+
+ bge_ape_send_event(bgep, event);
+}
+
+#undef BGE_DBG
#define BGE_DBG BGE_DBG_CHIP /* debug flag for this code */
static void
@@ -1973,7 +2543,6 @@ int
bge_chip_id_init(bge_t *bgep)
{
char buf[MAXPATHLEN]; /* any risk of stack overflow? */
- boolean_t sys_ok;
boolean_t dev_ok;
chip_id_t *cidp;
uint32_t subid;
@@ -1983,7 +2552,7 @@ bge_chip_id_init(bge_t *bgep)
int err;
uint_t i;
- sys_ok = dev_ok = B_FALSE;
+ dev_ok = B_FALSE;
cidp = &bgep->chipid;
/*
@@ -2026,13 +2595,31 @@ bge_chip_id_init(bge_t *bgep)
switch (cidp->device) {
case DEVICE_ID_5717:
case DEVICE_ID_5718:
+ case DEVICE_ID_5719:
+ case DEVICE_ID_5720:
case DEVICE_ID_5724:
- if (cidp->device == DEVICE_ID_5717)
+ case DEVICE_ID_5725:
+ case DEVICE_ID_5727:
+ if (cidp->device == DEVICE_ID_5717) {
cidp->chip_label = 5717;
- else if (cidp->device == DEVICE_ID_5718)
+ } else if (cidp->device == DEVICE_ID_5718) {
cidp->chip_label = 5718;
- else
+ } else if (cidp->device == DEVICE_ID_5719) {
+ cidp->chip_label = 5719;
+ } else if (cidp->device == DEVICE_ID_5720) {
+ if (pci_config_get16(bgep->cfg_handle, PCI_CONF_DEVID) ==
+ DEVICE_ID_5717_C0) {
+ cidp->chip_label = 5717;
+ } else {
+ cidp->chip_label = 5720;
+ }
+ } else if (cidp->device == DEVICE_ID_5724) {
cidp->chip_label = 5724;
+ } else if (cidp->device == DEVICE_ID_5725) {
+ cidp->chip_label = 5725;
+ } else /* (cidp->device == DEVICE_ID_5727) */ {
+ cidp->chip_label = 5727;
+ }
cidp->msi_enabled = bge_enable_msi;
#ifdef __sparc
cidp->mask_pci_int = LE_32(MHCR_MASK_PCI_INT_OUTPUT);
@@ -2048,7 +2635,6 @@ bge_chip_id_init(bge_t *bgep)
cidp->bge_mlcr_default = MLCR_DEFAULT_5717;
cidp->rx_rings = BGE_RECV_RINGS_MAX_5705;
cidp->tx_rings = BGE_SEND_RINGS_MAX_5705;
- cidp->flags |= CHIP_FLAG_NO_JUMBO;
cidp->statistic_type = BGE_STAT_REG;
dev_ok = B_TRUE;
break;
@@ -2451,10 +3037,15 @@ bge_chip_id_init(bge_t *bgep)
* For BCM5714/5715, there is only one standard receive ring. So the
* std buffer size should be set to BGE_JUMBO_BUFF_SIZE when jumbo
* feature is enabled.
+ *
+ * For the BCM5718 family we hijack the standard receive ring for
+ * the jumboframe traffic, keeps it simple.
*/
if (!(cidp->flags & CHIP_FLAG_NO_JUMBO) &&
(cidp->default_mtu > BGE_DEFAULT_MTU)) {
- if (DEVICE_5714_SERIES_CHIPSETS(bgep)) {
+ if (DEVICE_5714_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
cidp->mbuf_lo_water_rdma =
RDMA_MBUF_LOWAT_5714_JUMBO;
cidp->mbuf_lo_water_rmac =
@@ -2482,57 +3073,6 @@ bge_chip_id_init(bge_t *bgep)
cidp->nvtype = bge_nvmem_id(bgep);
/*
- * Now, we want to check whether this device is part of a
- * supported subsystem (e.g., on the motherboard of a Sun
- * branded platform).
- *
- * Rule 1: If the Subsystem Vendor ID is "Sun", then it's OK ;-)
- */
- if (cidp->subven == VENDOR_ID_SUN)
- sys_ok = B_TRUE;
-
- /*
- * Rule 2: If it's on the list on known subsystems, then it's OK.
- * Note: 0x14e41647 should *not* appear in the list, but the code
- * doesn't enforce that.
- */
- err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, bgep->devinfo,
- DDI_PROP_DONTPASS, knownids_propname, &ids, &i);
- if (err == DDI_PROP_SUCCESS) {
- /*
- * Got the list; scan for a matching subsystem vendor/device
- */
- subid = (cidp->subven << 16) | cidp->subdev;
- while (i--)
- if (ids[i] == subid)
- sys_ok = B_TRUE;
- ddi_prop_free(ids);
- }
-
- /*
- * Rule 3: If it's a Taco/ENWS motherboard device, then it's OK
- *
- * Unfortunately, early SunBlade 1500s and 2500s didn't reprogram
- * the Subsystem Vendor ID, so it defaults to Broadcom. Therefore,
- * we have to check specially for the exact device paths to the
- * motherboard devices on those platforms ;-(
- *
- * Note: we can't just use the "supported-subsystems" mechanism
- * above, because the entry would have to be 0x14e41647 -- which
- * would then accept *any* plugin card that *didn't* contain a
- * (valid) SEEPROM ;-(
- */
- sysname = ddi_node_name(ddi_root_node());
- devname = ddi_pathname(bgep->devinfo, buf);
- ASSERT(strlen(devname) > 0);
- if (strcmp(sysname, "SUNW,Sun-Blade-1500") == 0) /* Taco */
- if (strcmp(devname, "/pci@1f,700000/network@2") == 0)
- sys_ok = B_TRUE;
- if (strcmp(sysname, "SUNW,Sun-Blade-2500") == 0) /* ENWS */
- if (strcmp(devname, "/pci@1c,600000/network@3") == 0)
- sys_ok = B_TRUE;
-
- /*
* Now check what we've discovered: is this truly a supported
* chip on (the motherboard of) a supported platform?
*
@@ -2551,16 +3091,12 @@ bge_chip_id_init(bge_t *bgep)
"Device 'pci%04x,%04x' (%d) revision %d not supported",
cidp->vendor, cidp->device, cidp->chip_label,
cidp->revision);
-#if BGE_DEBUGGING
- else if (!sys_ok)
- bge_problem(bgep,
- "%d-based subsystem 'pci%04x,%04x' not validated",
- cidp->chip_label, cidp->subven, cidp->subdev);
-#endif
else
cidp->flags |= CHIP_FLAG_SUPPORTED;
+
if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK)
return (EIO);
+
return (0);
}
@@ -2643,7 +3179,9 @@ static boolean_t
bge_chip_reset_engine(bge_t *bgep, bge_regno_t regno)
{
uint32_t regval;
+ uint16_t val16;
uint32_t val32;
+ uint32_t mhcr;
regval = bge_reg_get32(bgep, regno);
@@ -2663,11 +3201,12 @@ bge_chip_reset_engine(bge_t *bgep, bge_regno_t regno)
* while the reset bit is written.
* See:P500 of 57xx-PG102-RDS.pdf.
*/
- if (DEVICE_5705_SERIES_CHIPSETS(bgep)||
- DEVICE_5717_SERIES_CHIPSETS(bgep)||
- DEVICE_5721_SERIES_CHIPSETS(bgep)||
- DEVICE_5723_SERIES_CHIPSETS(bgep)||
- DEVICE_5714_SERIES_CHIPSETS(bgep)||
+ if (DEVICE_5705_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5721_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5723_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5714_SERIES_CHIPSETS(bgep) ||
DEVICE_5906_SERIES_CHIPSETS(bgep)) {
regval |= MISC_CONFIG_GPHY_POWERDOWN_OVERRIDE;
if (bgep->chipid.pci_type == BGE_PCI_E) {
@@ -2727,6 +3266,14 @@ bge_chip_reset_engine(bge_t *bgep, bge_regno_t regno)
/* PCI-E device need more reset time */
drv_usecwait(120000);
+ /*
+ * (re)Disable interrupts as the bit can be reset after a
+ * core clock reset.
+ */
+ mhcr = pci_config_get32(bgep->cfg_handle, PCI_CONF_BGE_MHCR);
+ pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR,
+ mhcr | MHCR_MASK_PCI_INT_OUTPUT);
+
/* Set PCIE max payload size and clear error status. */
if ((bgep->chipid.chip_label == 5721) ||
(bgep->chipid.chip_label == 5751) ||
@@ -2746,6 +3293,16 @@ bge_chip_reset_engine(bge_t *bgep, bge_regno_t regno)
pci_config_put16(bgep->cfg_handle,
PCI_CONF_DEV_STUS_5723, DEVICE_ERROR_STUS);
}
+
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
+ val16 = pci_config_get16(bgep->cfg_handle,
+ PCI_CONF_DEV_CTRL_5717);
+ val16 &= ~READ_REQ_SIZE_MASK;
+ val16 |= READ_REQ_SIZE_2K;
+ pci_config_put16(bgep->cfg_handle,
+ PCI_CONF_DEV_CTRL_5717, val16);
+ }
}
BGE_PCICHK(bgep);
@@ -2802,13 +3359,27 @@ bge_chip_disable_engine(bge_t *bgep, bge_regno_t regno, uint32_t morebits)
return (B_TRUE);
default:
- regval = bge_reg_get32(bgep, regno);
- regval &= ~STATE_MACHINE_ENABLE_BIT;
- regval &= ~morebits;
- bge_reg_put32(bgep, regno, regval);
- return (bge_chip_poll_engine(bgep, regno,
- STATE_MACHINE_ENABLE_BIT, 0));
+ if (DEVICE_5704_SERIES_CHIPSETS(bgep)) {
+ break;
+ }
+
+ if ((regno == RCV_LIST_SELECTOR_MODE_REG) ||
+ (regno == DMA_COMPLETION_MODE_REG) ||
+ (regno == MBUF_CLUSTER_FREE_MODE_REG) ||
+ (regno == BUFFER_MANAGER_MODE_REG) ||
+ (regno == MEMORY_ARBITER_MODE_REG)) {
+ return B_TRUE;
+ }
+
+ break;
}
+
+ regval = bge_reg_get32(bgep, regno);
+ regval &= ~STATE_MACHINE_ENABLE_BIT;
+ regval &= ~morebits;
+ bge_reg_put32(bgep, regno, regval);
+
+ return bge_chip_poll_engine(bgep, regno, STATE_MACHINE_ENABLE_BIT, 0);
}
/*
@@ -2880,18 +3451,13 @@ bge_sync_mac_modes(bge_t *bgep)
* Reprogram the Ethernet MAC mode ...
*/
macmode = regval = bge_reg_get32(bgep, ETHERNET_MAC_MODE_REG);
- if ((bgep->chipid.flags & CHIP_FLAG_SERDES) &&
- (bgep->param_loop_mode != BGE_LOOP_INTERNAL_MAC))
- if (DEVICE_5714_SERIES_CHIPSETS(bgep))
- macmode |= ETHERNET_MODE_LINK_POLARITY;
- else
- macmode &= ~ETHERNET_MODE_LINK_POLARITY;
- else
- macmode |= ETHERNET_MODE_LINK_POLARITY;
+ macmode &= ~ETHERNET_MODE_LINK_POLARITY;
macmode &= ~ETHERNET_MODE_PORTMODE_MASK;
if ((bgep->chipid.flags & CHIP_FLAG_SERDES) &&
(bgep->param_loop_mode != BGE_LOOP_INTERNAL_MAC)) {
- if (DEVICE_5714_SERIES_CHIPSETS(bgep))
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5714_SERIES_CHIPSETS(bgep))
macmode |= ETHERNET_MODE_PORTMODE_GMII;
else
macmode |= ETHERNET_MODE_PORTMODE_TBI;
@@ -3102,38 +3668,6 @@ bge_chip_sync(bge_t *bgep)
return (retval);
}
-/*
- * This array defines the sequence of state machine control registers
- * in which the <enable> bit must be cleared to bring the chip to a
- * clean stop. Taken from Broadcom document 570X-PG102-R, p116.
- */
-static bge_regno_t shutdown_engine_regs[] = {
- RECEIVE_MAC_MODE_REG,
- RCV_BD_INITIATOR_MODE_REG,
- RCV_LIST_PLACEMENT_MODE_REG,
- RCV_LIST_SELECTOR_MODE_REG, /* BCM5704 series only */
- RCV_DATA_BD_INITIATOR_MODE_REG,
- RCV_DATA_COMPLETION_MODE_REG,
- RCV_BD_COMPLETION_MODE_REG,
-
- SEND_BD_SELECTOR_MODE_REG,
- SEND_BD_INITIATOR_MODE_REG,
- SEND_DATA_INITIATOR_MODE_REG,
- READ_DMA_MODE_REG,
- SEND_DATA_COMPLETION_MODE_REG,
- DMA_COMPLETION_MODE_REG, /* BCM5704 series only */
- SEND_BD_COMPLETION_MODE_REG,
- TRANSMIT_MAC_MODE_REG,
-
- HOST_COALESCE_MODE_REG,
- WRITE_DMA_MODE_REG,
- MBUF_CLUSTER_FREE_MODE_REG, /* BCM5704 series only */
- FTQ_RESET_REG, /* special - see code */
- BUFFER_MANAGER_MODE_REG, /* BCM5704 series only */
- MEMORY_ARBITER_MODE_REG, /* BCM5704 series only */
- BGE_REGNO_NONE /* terminator */
-};
-
#ifndef __sparc
static bge_regno_t quiesce_regs[] = {
READ_DMA_MODE_REG,
@@ -3185,30 +3719,44 @@ bge_chip_stop(bge_t *bgep, boolean_t fault)
{
bge_regno_t regno;
bge_regno_t *rbp;
- boolean_t ok;
+ boolean_t ok = B_TRUE;
BGE_TRACE(("bge_chip_stop($%p)",
(void *)bgep));
ASSERT(mutex_owned(bgep->genlock));
- rbp = shutdown_engine_regs;
- /*
- * When driver try to shutdown the BCM5705/5788/5721/5751/
- * 5752/5714 and 5715 chipsets,the buffer manager and the mem
- * -ory arbiter should not be disabled.
- */
- for (ok = B_TRUE; (regno = *rbp) != BGE_REGNO_NONE; ++rbp) {
- if (DEVICE_5704_SERIES_CHIPSETS(bgep))
- ok &= bge_chip_disable_engine(bgep, regno, 0);
- else if ((regno != RCV_LIST_SELECTOR_MODE_REG) &&
- (regno != DMA_COMPLETION_MODE_REG) &&
- (regno != MBUF_CLUSTER_FREE_MODE_REG)&&
- (regno != BUFFER_MANAGER_MODE_REG) &&
- (regno != MEMORY_ARBITER_MODE_REG))
- ok &= bge_chip_disable_engine(bgep,
- regno, 0);
- }
+ pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR,
+ (pci_config_get32(bgep->cfg_handle, PCI_CONF_BGE_MHCR) |
+ MHCR_MASK_PCI_INT_OUTPUT));
+
+ ok &= bge_chip_disable_engine(bgep, RECEIVE_MAC_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, RCV_BD_INITIATOR_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, RCV_LIST_PLACEMENT_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, RCV_LIST_SELECTOR_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, RCV_DATA_BD_INITIATOR_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, RCV_DATA_COMPLETION_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, RCV_BD_COMPLETION_MODE_REG, 0);
+
+ ok &= bge_chip_disable_engine(bgep, SEND_BD_SELECTOR_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, SEND_BD_INITIATOR_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, SEND_DATA_INITIATOR_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, READ_DMA_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, SEND_DATA_COMPLETION_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, DMA_COMPLETION_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, SEND_BD_COMPLETION_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, TRANSMIT_MAC_MODE_REG, 0);
+
+ bge_reg_clr32(bgep, ETHERNET_MAC_MODE_REG, ETHERNET_MODE_ENABLE_TDE);
+ drv_usecwait(40);
+
+ ok &= bge_chip_disable_engine(bgep, HOST_COALESCE_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, WRITE_DMA_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, MBUF_CLUSTER_FREE_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, FTQ_RESET_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, BUFFER_MANAGER_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, MEMORY_ARBITER_MODE_REG, 0);
+ ok &= bge_chip_disable_engine(bgep, MEMORY_ARBITER_MODE_REG, 0);
if (!ok && !fault)
ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_UNAFFECTED);
@@ -3295,8 +3843,7 @@ bge_poll_firmware(bge_t *bgep)
* GENCOMM word as "the upper half of a 64-bit quantity" makes
* it work correctly on both big- and little-endian hosts.
*/
- if (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev) ==
- MHCR_CHIP_ASIC_REV_5906) {
+ if (MHCR_CHIP_ASIC_REV(bgep) == MHCR_CHIP_ASIC_REV_5906) {
for (i = 0; i < 1000; ++i) {
drv_usecwait(1000);
val = bge_reg_get32(bgep, VCPU_STATUS_REG);
@@ -3310,6 +3857,9 @@ bge_poll_firmware(bge_t *bgep)
for (i = 0; i < 1000; ++i) {
drv_usecwait(1000);
gen = bge_nic_get64(bgep, NIC_MEM_GENCOMM) >> 32;
+ if (i == 0 && DEVICE_5704_SERIES_CHIPSETS(bgep))
+ drv_usecwait(100000);
+ mac = bge_reg_get64(bgep, MAC_ADDRESS_REG(0));
#ifdef BGE_IPMI_ASF
if (!bgep->asf_enabled) {
#endif
@@ -3318,7 +3868,6 @@ bge_poll_firmware(bge_t *bgep)
#ifdef BGE_IPMI_ASF
}
#endif
- mac = bge_reg_get64(bgep, MAC_ADDRESS_REG(0));
if (mac != 0ULL)
break;
if (bgep->bge_chip_state != BGE_CHIP_INITIAL)
@@ -3358,7 +3907,8 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma)
chip_id_t chipid;
uint64_t mac;
uint64_t magic;
- uint32_t modeflags;
+ uint32_t tmp;
+ uint32_t mhcr_base;
uint32_t mhcr;
uint32_t sx0;
uint32_t i, tries;
@@ -3395,24 +3945,26 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma)
break;
}
+ mhcr_base = MHCR_ENABLE_INDIRECT_ACCESS |
+ MHCR_ENABLE_PCI_STATE_RW |
+ MHCR_ENABLE_TAGGED_STATUS_MODE |
+ MHCR_MASK_INTERRUPT_MODE |
+ MHCR_MASK_PCI_INT_OUTPUT |
+ MHCR_CLEAR_INTERRUPT_INTA;
+
#ifdef BGE_IPMI_ASF
if (bgep->asf_enabled) {
-#ifdef __sparc
- mhcr = MHCR_ENABLE_INDIRECT_ACCESS |
- MHCR_ENABLE_TAGGED_STATUS_MODE |
- MHCR_MASK_INTERRUPT_MODE |
- MHCR_MASK_PCI_INT_OUTPUT |
- MHCR_CLEAR_INTERRUPT_INTA |
- MHCR_ENABLE_ENDIAN_WORD_SWAP |
- MHCR_ENABLE_ENDIAN_BYTE_SWAP;
- if (DEVICE_5717_SERIES_CHIPSETS(bgep))
- pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR,
- 0);
+ mhcr = mhcr_base;
+#ifdef _BIG_ENDIAN
+ mhcr |= (MHCR_ENABLE_ENDIAN_WORD_SWAP |
+ MHCR_ENABLE_ENDIAN_BYTE_SWAP);
+#endif
pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, mhcr);
+
bge_reg_put32(bgep, MEMORY_ARBITER_MODE_REG,
bge_reg_get32(bgep, MEMORY_ARBITER_MODE_REG) |
MEMORY_ARBITER_ENABLE);
-#endif
+
if (asf_mode == ASF_MODE_INIT) {
bge_asf_pre_reset_operations(bgep, BGE_INIT_RESET);
} else if (asf_mode == ASF_MODE_SHUTDOWN) {
@@ -3420,6 +3972,7 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma)
}
}
#endif
+
/*
* Adapted from Broadcom document 570X-PG102-R, pp 102-116.
* Updated to reflect Broadcom document 570X-PG104-R, pp 146-159.
@@ -3434,17 +3987,13 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma)
if (!bge_chip_enable_engine(bgep, MEMORY_ARBITER_MODE_REG, 0))
retval = DDI_FAILURE;
- mhcr = MHCR_ENABLE_INDIRECT_ACCESS |
- MHCR_ENABLE_TAGGED_STATUS_MODE |
- MHCR_MASK_INTERRUPT_MODE |
- MHCR_MASK_PCI_INT_OUTPUT |
- MHCR_CLEAR_INTERRUPT_INTA;
-#ifdef _BIG_ENDIAN
- mhcr |= MHCR_ENABLE_ENDIAN_WORD_SWAP | MHCR_ENABLE_ENDIAN_BYTE_SWAP;
-#endif /* _BIG_ENDIAN */
- if (DEVICE_5717_SERIES_CHIPSETS(bgep))
- pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, 0);
+ mhcr = mhcr_base;
+#ifdef _BIG_ENDIAN
+ mhcr |= (MHCR_ENABLE_ENDIAN_WORD_SWAP |
+ MHCR_ENABLE_ENDIAN_BYTE_SWAP);
+#endif
pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, mhcr);
+
#ifdef BGE_IPMI_ASF
if (bgep->asf_enabled)
bgep->asf_wordswapped = B_FALSE;
@@ -3459,6 +4008,8 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma)
BGE_DEBUG(("%s: fail to acquire nvram lock",
bgep->ifname));
+ bge_ape_lock(bgep, BGE_APE_LOCK_GRC);
+
#ifdef BGE_IPMI_ASF
if (!bgep->asf_enabled) {
#endif
@@ -3468,8 +4019,23 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma)
}
#endif
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
+ bge_reg_set32(bgep, FAST_BOOT_PC, 0);
+ if (!bge_chip_enable_engine(bgep, MEMORY_ARBITER_MODE_REG, 0))
+ retval = DDI_FAILURE;
+ }
+
+ mhcr = mhcr_base;
+#ifdef _BIG_ENDIAN
+ mhcr |= (MHCR_ENABLE_ENDIAN_WORD_SWAP |
+ MHCR_ENABLE_ENDIAN_BYTE_SWAP);
+#endif
+ pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, mhcr);
+
if (!bge_chip_reset_engine(bgep, MISC_CONFIG_REG))
retval = DDI_FAILURE;
+
bge_chip_cfg_init(bgep, &chipid, enable_dma);
/*
@@ -3485,7 +4051,6 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma)
(bgep->chipid.chip_label == 5906))
bge_reg_set32(bgep, TLP_CONTROL_REG, TLP_DATA_FIFO_PROTECT);
-
/*
* Step 9: enable MAC memory arbiter,bit30 and bit31 of 5714/5715 should
* not be changed.
@@ -3502,17 +4067,15 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma)
* Steps 14-15: Configure DMA endianness options. See
* the comments on the setting of the MHCR above.
*/
-#ifdef _BIG_ENDIAN
- modeflags = MODE_WORD_SWAP_FRAME | MODE_BYTE_SWAP_FRAME |
- MODE_WORD_SWAP_NONFRAME | MODE_BYTE_SWAP_NONFRAME;
-#else
- modeflags = MODE_WORD_SWAP_FRAME | MODE_BYTE_SWAP_FRAME;
-#endif /* _BIG_ENDIAN */
+ tmp = MODE_WORD_SWAP_FRAME | MODE_BYTE_SWAP_FRAME;
+#ifdef _BIG_ENDIAN
+ tmp |= (MODE_WORD_SWAP_NONFRAME | MODE_BYTE_SWAP_NONFRAME);
+#endif
#ifdef BGE_IPMI_ASF
if (bgep->asf_enabled)
- modeflags |= MODE_HOST_STACK_UP;
+ tmp |= MODE_HOST_STACK_UP;
#endif
- bge_reg_put32(bgep, MODE_CONTROL_REG, modeflags);
+ bge_reg_put32(bgep, MODE_CONTROL_REG, tmp);
#ifdef BGE_IPMI_ASF
if (bgep->asf_enabled) {
@@ -3564,11 +4127,20 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma)
#endif
}
#endif
+
+ bge_ape_unlock(bgep, BGE_APE_LOCK_GRC);
+
/*
* Steps 16-17: poll for firmware completion
*/
mac = bge_poll_firmware(bgep);
+ if (bgep->chipid.device == DEVICE_ID_5720) {
+ tmp = bge_reg_get32(bgep, CPMU_CLCK_ORIDE_REG);
+ bge_reg_put32(bgep, CPMU_CLCK_ORIDE_REG,
+ (tmp & ~CPMU_CLCK_ORIDE_MAC_ORIDE_EN));
+ }
+
/*
* Step 18: enable external memory -- doesn't apply.
*
@@ -3585,12 +4157,24 @@ bge_chip_reset(bge_t *bgep, boolean_t enable_dma)
*/
bge_reg_put32(bgep, MISC_LOCAL_CONTROL_REG,
bgep->chipid.bge_mlcr_default);
+
+ if ((bgep->chipid.flags & CHIP_FLAG_SERDES) &&
+ DEVICE_5714_SERIES_CHIPSETS(bgep)) {
+ tmp = bge_reg_get32(bgep, SERDES_RX_CONTROL);
+ tmp |= SERDES_RX_CONTROL_SIG_DETECT;
+ bge_reg_put32(bgep, SERDES_RX_CONTROL, tmp);
+ }
+
bge_reg_set32(bgep, SERIAL_EEPROM_ADDRESS_REG, SEEPROM_ACCESS_INIT);
/*
* Step 20: clear the Ethernet MAC mode register
*/
- bge_reg_put32(bgep, ETHERNET_MAC_MODE_REG, 0);
+ if (bgep->ape_enabled)
+ bge_reg_put32(bgep, ETHERNET_MAC_MODE_REG,
+ ETHERNET_MODE_APE_TX_EN | ETHERNET_MODE_APE_RX_EN);
+ else
+ bge_reg_put32(bgep, ETHERNET_MAC_MODE_REG, 0);
/*
* Step 21: restore cache-line-size, latency timer, and
@@ -3702,8 +4286,11 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys)
uint32_t stats_mask;
uint32_t dma_wrprio;
uint64_t ring;
+ uint32_t reg;
uint32_t regval;
+ uint32_t mhcr;
int retval = DDI_SUCCESS;
+ int i;
BGE_TRACE(("bge_chip_start($%p)",
(void *)bgep));
@@ -3711,6 +4298,22 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys)
ASSERT(mutex_owned(bgep->genlock));
ASSERT(bgep->bge_chip_state == BGE_CHIP_RESET);
+ /* Initialize EEE, enable MAC control of LPI */
+ bge_eee_init(bgep);
+
+ if (bgep->ape_enabled) {
+ /*
+ * Allow reads and writes to the
+ * APE register and memory space.
+ */
+ regval = pci_config_get32(bgep->cfg_handle,
+ PCI_CONF_BGE_PCISTATE);
+ regval |= PCISTATE_ALLOW_APE_CTLSPC_WR |
+ PCISTATE_ALLOW_APE_SHMEM_WR | PCISTATE_ALLOW_APE_PSPACE_WR;
+ pci_config_put32(bgep->cfg_handle,
+ PCI_CONF_BGE_PCISTATE, regval);
+ }
+
/*
* Taken from Broadcom document 570X-PG102-R, pp 102-116.
* The document specifies 95 separate steps to fully
@@ -3746,6 +4349,37 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys)
MODE_HOST_SEND_BDS |
MODE_HOST_STACK_UP);
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
+ reg = (CHIP_ASIC_REV(bgep) == CHIP_ASIC_REV_5762)
+ ? RDMA_RSRV_CTRL_REG2 : RDMA_RSRV_CTRL_REG;
+ regval = bge_reg_get32(bgep, reg);
+ if ((bgep->chipid.device == DEVICE_ID_5719) ||
+ (bgep->chipid.device == DEVICE_ID_5720) ||
+ (CHIP_ASIC_REV(bgep) == CHIP_ASIC_REV_5762)) {
+ regval &= ~(RDMA_RSRV_CTRL_TXMRGN_MASK |
+ RDMA_RSRV_CTRL_FIFO_LWM_MASK |
+ RDMA_RSRV_CTRL_FIFO_HWM_MASK);
+ regval |= (RDMA_RSRV_CTRL_TXMRGN_320B |
+ RDMA_RSRV_CTRL_FIFO_LWM_1_5K |
+ RDMA_RSRV_CTRL_FIFO_HWM_1_5K);
+ }
+ /* Enable the DMA FIFO Overrun fix. */
+ bge_reg_put32(bgep, reg,
+ (regval | RDMA_RSRV_CTRL_FIFO_OFLW_FIX));
+
+ if ((CHIP_ASIC_REV(bgep) == CHIP_ASIC_REV_5719) ||
+ (CHIP_ASIC_REV(bgep) == CHIP_ASIC_REV_5720) ||
+ (CHIP_ASIC_REV(bgep) == CHIP_ASIC_REV_5762)) {
+ reg = (CHIP_ASIC_REV(bgep) == CHIP_ASIC_REV_5762)
+ ? RDMA_CORR_CTRL_REG2 : RDMA_CORR_CTRL_REG;
+ regval = bge_reg_get32(bgep, reg);
+ bge_reg_put32(bgep, reg, (regval |
+ RDMA_CORR_CTRL_BLEN_BD_4K |
+ RDMA_CORR_CTRL_BLEN_LSO_4K));
+ }
+ }
+
/*
* Step 28: Configure checksum options:
* Solaris supports the hardware default checksum options.
@@ -3818,16 +4452,23 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys)
/*
* Steps 34-36: enable buffer manager & internal h/w queues
*/
- if (!bge_chip_enable_engine(bgep, BUFFER_MANAGER_MODE_REG,
- STATE_MACHINE_ATTN_ENABLE_BIT))
+ regval = STATE_MACHINE_ATTN_ENABLE_BIT;
+ if (bgep->chipid.device == DEVICE_ID_5719)
+ regval |= BUFFER_MANAGER_MODE_NO_TX_UNDERRUN;
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep))
+ regval |= BUFFER_MANAGER_MODE_MBLOW_ATTN_ENABLE;
+ if (!bge_chip_enable_engine(bgep, BUFFER_MANAGER_MODE_REG, regval))
retval = DDI_FAILURE;
+
if (!bge_chip_enable_engine(bgep, FTQ_RESET_REG, 0))
retval = DDI_FAILURE;
/*
* Steps 37-39: initialise Receive Buffer (Producer) RCBs
*/
- if (DEVICE_5717_SERIES_CHIPSETS(bgep)) {
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
buff_ring_t *brp = &bgep->buff[BGE_STD_BUFF_RING];
bge_reg_put64(bgep, STD_RCV_BD_RING_RCB_REG,
brp->desc.cookie.dmac_laddress);
@@ -3926,7 +4567,7 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys)
*/
bge_reg_put32(bgep, RCV_LP_CONFIG_REG,
RCV_LP_CONFIG(bgep->chipid.rx_rings));
- switch (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev)) {
+ switch (MHCR_CHIP_ASIC_REV(bgep)) {
case MHCR_CHIP_ASIC_REV_5700:
case MHCR_CHIP_ASIC_REV_5701:
case MHCR_CHIP_ASIC_REV_5703:
@@ -4008,12 +4649,28 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys)
* Receive List selector.Pay attention:0x3400 is not exist in BCM5714
* and BCM5715.
*/
+
+ if (bgep->chipid.device == DEVICE_ID_5719) {
+ for (i = 0; i < BGE_NUM_RDMA_CHANNELS; i++) {
+ if (bge_reg_get32(bgep, (BGE_RDMA_LENGTH + (i << 2))) >
+ bgep->chipid.default_mtu)
+ break;
+ }
+ if (i < BGE_NUM_RDMA_CHANNELS) {
+ regval = bge_reg_get32(bgep, RDMA_CORR_CTRL_REG);
+ regval |= RDMA_CORR_CTRL_TX_LENGTH_WA;
+ bge_reg_put32(bgep, RDMA_CORR_CTRL_REG, regval);
+ bgep->rdma_length_bug_on_5719 = B_TRUE;
+ }
+ }
+
if (bgep->chipid.tx_rings <= COALESCE_64_BYTE_RINGS &&
bgep->chipid.rx_rings <= COALESCE_64_BYTE_RINGS)
coalmode = COALESCE_64_BYTE_STATUS;
else
coalmode = 0;
- if (DEVICE_5717_SERIES_CHIPSETS(bgep))
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep))
coalmode = COALESCE_CLR_TICKS_RX;
if (!bge_chip_enable_engine(bgep, HOST_COALESCE_MODE_REG, coalmode))
retval = DDI_FAILURE;
@@ -4032,6 +4689,11 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys)
* Step 72: Enable MAC DMA engines
* Step 73: Clear & enable MAC statistics
*/
+ if (bgep->ape_enabled) {
+ /* XXX put32 instead of set32 ? */
+ bge_reg_put32(bgep, ETHERNET_MAC_MODE_REG,
+ ETHERNET_MODE_APE_TX_EN | ETHERNET_MODE_APE_RX_EN);
+ }
bge_reg_set32(bgep, ETHERNET_MAC_MODE_REG,
ETHERNET_MODE_ENABLE_FHDE |
ETHERNET_MODE_ENABLE_RDE |
@@ -4042,6 +4704,14 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys)
ETHERNET_MODE_CLEAR_TX_STATS |
ETHERNET_MODE_CLEAR_RX_STATS);
+ drv_usecwait(140);
+
+ if (bgep->ape_enabled) {
+ /* Write our heartbeat update interval to APE. */
+ bge_ape_put32(bgep, BGE_APE_HOST_HEARTBEAT_INT_MS,
+ APE_HOST_HEARTBEAT_INT_DISABLE);
+ }
+
/*
* Step 74: configure the MLCR (Miscellaneous Local Control
* Register); not required, as we set up the MLCR in step 10
@@ -4068,23 +4738,28 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys)
retval = DDI_FAILURE;
dma_wrprio = (bge_dma_wrprio << DMA_PRIORITY_SHIFT) |
ALL_DMA_ATTN_BITS;
- if ((MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev) ==
- MHCR_CHIP_ASIC_REV_5755) ||
- (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev) ==
- MHCR_CHIP_ASIC_REV_5723) ||
- (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev) ==
- MHCR_CHIP_ASIC_REV_5906)) {
+ /* the 5723 check here covers all newer chip families (OK) */
+ if ((MHCR_CHIP_ASIC_REV(bgep) == MHCR_CHIP_ASIC_REV_5755) ||
+ (MHCR_CHIP_ASIC_REV(bgep) == MHCR_CHIP_ASIC_REV_5723) ||
+ (MHCR_CHIP_ASIC_REV(bgep) == MHCR_CHIP_ASIC_REV_5906)) {
dma_wrprio |= DMA_STATUS_TAG_FIX_CQ12384;
}
if (!bge_chip_enable_engine(bgep, WRITE_DMA_MODE_REG,
dma_wrprio))
retval = DDI_FAILURE;
+
+ drv_usecwait(40);
+
if (DEVICE_5723_SERIES_CHIPSETS(bgep) ||
- DEVICE_5717_SERIES_CHIPSETS(bgep))
+ DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep))
bge_dma_rdprio = 0;
if (!bge_chip_enable_engine(bgep, READ_DMA_MODE_REG,
(bge_dma_rdprio << DMA_PRIORITY_SHIFT) | ALL_DMA_ATTN_BITS))
retval = DDI_FAILURE;
+
+ drv_usecwait(40);
+
if (!bge_chip_enable_engine(bgep, RCV_DATA_COMPLETION_MODE_REG,
STATE_MACHINE_ATTN_ENABLE_BIT))
retval = DDI_FAILURE;
@@ -4112,12 +4787,21 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys)
STATE_MACHINE_ATTN_ENABLE_BIT))
retval = DDI_FAILURE;
+ drv_usecwait(40);
+
/*
* Step 88: download firmware -- doesn't apply
* Steps 89-90: enable Transmit & Receive MAC Engines
*/
- if (!bge_chip_enable_engine(bgep, TRANSMIT_MAC_MODE_REG, 0))
+ regval = 0;
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep)) {
+ regval |= TRANSMIT_MODE_MBUF_LOCKUP_FIX;
+ }
+ if (!bge_chip_enable_engine(bgep, TRANSMIT_MAC_MODE_REG, regval))
retval = DDI_FAILURE;
+
+ drv_usecwait(100);
+
#ifdef BGE_IPMI_ASF
if (!bgep->asf_enabled) {
if (!bge_chip_enable_engine(bgep, RECEIVE_MAC_MODE_REG,
@@ -4133,6 +4817,8 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys)
retval = DDI_FAILURE;
#endif
+ drv_usecwait(100);
+
/*
* Step 91: disable auto-polling of PHY status
*/
@@ -4169,8 +4855,16 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys)
* restart autoneg (if required)
*/
if (reset_phys)
+ {
if (bge_phys_update(bgep) == DDI_FAILURE)
retval = DDI_FAILURE;
+ /* forcing a mac link update here */
+ bge_phys_check(bgep);
+ bgep->link_state = (bgep->param_link_up) ? LINK_STATE_UP :
+ LINK_STATE_DOWN;
+ bge_sync_mac_modes(bgep);
+ mac_link_update(bgep->mh, bgep->link_state);
+ }
/*
* Extra step (DSG): hand over all the Receive Buffers to the chip
@@ -4213,6 +4907,17 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys)
}
#endif
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
+ bge_cfg_clr16(bgep, PCI_CONF_DEV_CTRL_5717,
+ DEV_CTRL_NO_SNOOP | DEV_CTRL_RELAXED);
+#if 0
+ mhcr = pci_config_get32(bgep->cfg_handle, PCI_CONF_BGE_MHCR);
+ pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR,
+ (mhcr | MHCR_TLP_MINOR_ERR_TOLERANCE));
+#endif
+ }
+
/*
* Step 97: enable PCI interrupts!!!
*/
@@ -4283,6 +4988,53 @@ bge_wake_factotum(bge_t *bgep)
mutex_exit(bgep->softintrlock);
}
+static void
+bge_intr_error_handler(bge_t *bgep)
+{
+ uint32_t flow;
+ uint32_t rdma;
+ uint32_t wdma;
+ uint32_t tmac;
+ uint32_t rmac;
+ uint32_t rxrs;
+ uint32_t emac;
+ uint32_t msis;
+ uint32_t txrs = 0;
+
+ ASSERT(mutex_owned(bgep->genlock));
+
+ /*
+ * Read all the registers that show the possible
+ * reasons for the ERROR bit to be asserted
+ */
+ flow = bge_reg_get32(bgep, FLOW_ATTN_REG);
+ rdma = bge_reg_get32(bgep, READ_DMA_STATUS_REG);
+ wdma = bge_reg_get32(bgep, WRITE_DMA_STATUS_REG);
+ tmac = bge_reg_get32(bgep, TRANSMIT_MAC_STATUS_REG);
+ rmac = bge_reg_get32(bgep, RECEIVE_MAC_STATUS_REG);
+ rxrs = bge_reg_get32(bgep, RX_RISC_STATE_REG);
+ emac = bge_reg_get32(bgep, ETHERNET_MAC_STATUS_REG);
+ msis = bge_reg_get32(bgep, MSI_STATUS_REG);
+ if (DEVICE_5704_SERIES_CHIPSETS(bgep))
+ txrs = bge_reg_get32(bgep, TX_RISC_STATE_REG);
+
+ BGE_DEBUG(("factotum($%p) flow 0x%x rdma 0x%x wdma 0x%x emac 0x%x msis 0x%x",
+ (void *)bgep, flow, rdma, wdma, emac, msis));
+ BGE_DEBUG(("factotum($%p) tmac 0x%x rmac 0x%x rxrs 0x%08x txrs 0x%08x",
+ (void *)bgep, tmac, rmac, rxrs, txrs));
+
+ /*
+ * For now, just clear all the errors ...
+ */
+ if (DEVICE_5704_SERIES_CHIPSETS(bgep))
+ bge_reg_put32(bgep, TX_RISC_STATE_REG, ~0);
+ bge_reg_put32(bgep, RX_RISC_STATE_REG, ~0);
+ bge_reg_put32(bgep, RECEIVE_MAC_STATUS_REG, ~0);
+ bge_reg_put32(bgep, WRITE_DMA_STATUS_REG, ~0);
+ bge_reg_put32(bgep, READ_DMA_STATUS_REG, ~0);
+ bge_reg_put32(bgep, FLOW_ATTN_REG, ~0);
+}
+
/*
* bge_intr() -- handle chip interrupts
*/
@@ -4320,7 +5072,8 @@ bge_intr(caddr_t arg1, caddr_t arg2)
* bit is *zero* when the interrupt is asserted.
*/
regval = bge_reg_get32(bgep, MISC_LOCAL_CONTROL_REG);
- if (!(DEVICE_5717_SERIES_CHIPSETS(bgep)) &&
+ if (!(DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) &&
(regval & MLCR_INTA_STATE)) {
if (bge_check_acc_handle(bgep, bgep->io_handle)
!= DDI_FM_OK)
@@ -4372,8 +5125,9 @@ bge_intr(caddr_t arg1, caddr_t arg2)
mutex_exit(bgep->genlock);
return (DDI_INTR_CLAIMED);
}
- retval = bge_status_sync(bgep, STATUS_FLAG_UPDATED,
- &flags);
+
+ retval = bge_status_sync(bgep, STATUS_FLAG_UPDATED |
+ STATUS_FLAG_LINK_CHANGED | STATUS_FLAG_ERROR, &flags);
if (retval != DDI_FM_OK) {
bgep->bge_dma_error = B_TRUE;
goto chip_stop;
@@ -4391,6 +5145,28 @@ bge_intr(caddr_t arg1, caddr_t arg2)
DDI_FM_OK)
goto chip_stop;
+ if (flags & STATUS_FLAG_LINK_CHANGED) {
+ BGE_DEBUG(("bge_intr($%p) ($%p) link event", arg1, arg2));
+ if (bge_phys_check(bgep)) {
+ bgep->link_state = bgep->param_link_up ?
+ LINK_STATE_UP : LINK_STATE_DOWN;
+ bge_sync_mac_modes(bgep);
+ mac_link_update(bgep->mh, bgep->link_state);
+ }
+
+ if (bge_check_acc_handle(bgep, bgep->io_handle) !=
+ DDI_FM_OK)
+ goto chip_stop;
+ }
+
+ if (flags & STATUS_FLAG_ERROR) {
+ bge_intr_error_handler(bgep);
+
+ if (bge_check_acc_handle(bgep, bgep->io_handle) !=
+ DDI_FM_OK)
+ goto chip_stop;
+ }
+
/*
* Drop the mutex while we:
* Receive any newly-arrived packets
@@ -4421,15 +5197,6 @@ bge_intr(caddr_t arg1, caddr_t arg2)
bgep->missed_dmas = 0;
}
- /*
- * Check for exceptional conditions that we need to handle
- *
- * Link status changed
- * Status block not updated
- */
- if (flags & STATUS_FLAG_LINK_CHANGED)
- bge_wake_factotum(bgep);
-
if (bgep->missed_dmas) {
/*
* Probably due to the internal status tag not
@@ -4481,6 +5248,7 @@ bge_intr(caddr_t arg1, caddr_t arg2)
return (result);
chip_stop:
+
#ifdef BGE_IPMI_ASF
if (bgep->asf_enabled && bgep->asf_status == ASF_STAT_RUN) {
/*
@@ -4510,157 +5278,6 @@ chip_stop:
#undef BGE_DBG
#define BGE_DBG BGE_DBG_FACT /* debug flag for this code */
-static void bge_factotum_error_handler(bge_t *bgep);
-#pragma no_inline(bge_factotum_error_handler)
-
-static void
-bge_factotum_error_handler(bge_t *bgep)
-{
- uint32_t flow;
- uint32_t rdma;
- uint32_t wdma;
- uint32_t tmac;
- uint32_t rmac;
- uint32_t rxrs;
- uint32_t txrs = 0;
-
- ASSERT(mutex_owned(bgep->genlock));
-
- /*
- * Read all the registers that show the possible
- * reasons for the ERROR bit to be asserted
- */
- flow = bge_reg_get32(bgep, FLOW_ATTN_REG);
- rdma = bge_reg_get32(bgep, READ_DMA_STATUS_REG);
- wdma = bge_reg_get32(bgep, WRITE_DMA_STATUS_REG);
- tmac = bge_reg_get32(bgep, TRANSMIT_MAC_STATUS_REG);
- rmac = bge_reg_get32(bgep, RECEIVE_MAC_STATUS_REG);
- rxrs = bge_reg_get32(bgep, RX_RISC_STATE_REG);
- if (DEVICE_5704_SERIES_CHIPSETS(bgep))
- txrs = bge_reg_get32(bgep, TX_RISC_STATE_REG);
-
- BGE_DEBUG(("factotum($%p) flow 0x%x rdma 0x%x wdma 0x%x",
- (void *)bgep, flow, rdma, wdma));
- BGE_DEBUG(("factotum($%p) tmac 0x%x rmac 0x%x rxrs 0x%08x txrs 0x%08x",
- (void *)bgep, tmac, rmac, rxrs, txrs));
-
- /*
- * For now, just clear all the errors ...
- */
- if (DEVICE_5704_SERIES_CHIPSETS(bgep))
- bge_reg_put32(bgep, TX_RISC_STATE_REG, ~0);
- bge_reg_put32(bgep, RX_RISC_STATE_REG, ~0);
- bge_reg_put32(bgep, RECEIVE_MAC_STATUS_REG, ~0);
- bge_reg_put32(bgep, WRITE_DMA_STATUS_REG, ~0);
- bge_reg_put32(bgep, READ_DMA_STATUS_REG, ~0);
- bge_reg_put32(bgep, FLOW_ATTN_REG, ~0);
-}
-
-/*
- * Handler for hardware link state change.
- *
- * When this routine is called, the hardware link state has changed
- * and the new state is reflected in the param_* variables. Here
- * we must update the softstate and reprogram the MAC to match.
- */
-static void bge_factotum_link_handler(bge_t *bgep);
-#pragma no_inline(bge_factotum_link_handler)
-
-static void
-bge_factotum_link_handler(bge_t *bgep)
-{
- ASSERT(mutex_owned(bgep->genlock));
-
- /*
- * Update the s/w link_state
- */
- if (bgep->param_link_up)
- bgep->link_state = LINK_STATE_UP;
- else
- bgep->link_state = LINK_STATE_DOWN;
-
- /*
- * Reprogram the MAC modes to match
- */
- bge_sync_mac_modes(bgep);
-}
-
-static boolean_t bge_factotum_link_check(bge_t *bgep, int *dma_state);
-#pragma no_inline(bge_factotum_link_check)
-
-static boolean_t
-bge_factotum_link_check(bge_t *bgep, int *dma_state)
-{
- boolean_t check;
- uint64_t flags;
- uint32_t tmac_status;
-
- ASSERT(mutex_owned(bgep->genlock));
-
- /*
- * Get & clear the writable status bits in the Tx status register
- * (some bits are write-1-to-clear, others are just readonly).
- */
- tmac_status = bge_reg_get32(bgep, TRANSMIT_MAC_STATUS_REG);
- bge_reg_put32(bgep, TRANSMIT_MAC_STATUS_REG, tmac_status);
-
- /*
- * Get & clear the ERROR and LINK_CHANGED bits from the status block
- */
- *dma_state = bge_status_sync(bgep, STATUS_FLAG_ERROR |
- STATUS_FLAG_LINK_CHANGED, &flags);
- if (*dma_state != DDI_FM_OK)
- return (B_FALSE);
-
- /*
- * Clear any errors flagged in the status block ...
- */
- if (flags & STATUS_FLAG_ERROR)
- bge_factotum_error_handler(bgep);
-
- /*
- * We need to check the link status if:
- * the status block says there's been a link change
- * or there's any discrepancy between the various
- * flags indicating the link state (link_state,
- * param_link_up, and the LINK STATE bit in the
- * Transmit MAC status register).
- */
- check = (flags & STATUS_FLAG_LINK_CHANGED) != 0;
- switch (bgep->link_state) {
- case LINK_STATE_UP:
- check |= (bgep->param_link_up == B_FALSE);
- check |= ((tmac_status & TRANSMIT_STATUS_LINK_UP) == 0);
- break;
-
- case LINK_STATE_DOWN:
- check |= (bgep->param_link_up != B_FALSE);
- check |= ((tmac_status & TRANSMIT_STATUS_LINK_UP) != 0);
- break;
-
- default:
- check = B_TRUE;
- break;
- }
-
- /*
- * If <check> is false, we're sure the link hasn't changed.
- * If true, however, it's not yet definitive; we have to call
- * bge_phys_check() to determine whether the link has settled
- * into a new state yet ... and if it has, then call the link
- * state change handler.But when the chip is 5700 in Dell 6650
- * ,even if check is false, the link may have changed.So we
- * have to call bge_phys_check() to determine the link state.
- */
- if (check || bgep->chipid.device == DEVICE_ID_5700) {
- check = bge_phys_check(bgep);
- if (check)
- bge_factotum_link_handler(bgep);
- }
-
- return (check);
-}
-
/*
* Factotum routine to check for Tx stall, using the 'watchdog' counter
*/
@@ -4710,9 +5327,7 @@ bge_factotum_stall_check(bge_t *bgep)
/*
* The factotum is woken up when there's something to do that we'd rather
* not do from inside a hardware interrupt handler or high-level cyclic.
- * Its two main tasks are:
- * reset & restart the chip after an error
- * check the link status whenever necessary
+ * Its main task is to reset & restart the chip after an error.
*/
uint_t bge_chip_factotum(caddr_t arg);
#pragma no_inline(bge_chip_factotum)
@@ -4723,7 +5338,6 @@ bge_chip_factotum(caddr_t arg)
bge_t *bgep;
uint_t result;
boolean_t error;
- boolean_t linkchg;
int dma_state;
bgep = (void *)arg;
@@ -4740,7 +5354,6 @@ bge_chip_factotum(caddr_t arg)
result = DDI_INTR_CLAIMED;
error = B_FALSE;
- linkchg = B_FALSE;
mutex_enter(bgep->genlock);
switch (bgep->bge_chip_state) {
@@ -4748,7 +5361,16 @@ bge_chip_factotum(caddr_t arg)
break;
case BGE_CHIP_RUNNING:
- linkchg = bge_factotum_link_check(bgep, &dma_state);
+
+ if (bgep->chipid.device == DEVICE_ID_5700) {
+ if (bge_phys_check(bgep)) {
+ bgep->link_state = (bgep->param_link_up) ?
+ LINK_STATE_UP : LINK_STATE_DOWN;
+ bge_sync_mac_modes(bgep);
+ mac_link_update(bgep->mh, bgep->link_state);
+ }
+ }
+
error = bge_factotum_stall_check(bgep);
if (dma_state != DDI_FM_OK) {
bgep->bge_dma_error = B_TRUE;
@@ -4827,7 +5449,6 @@ bge_chip_factotum(caddr_t arg)
break;
}
-
/*
* If an error is detected, stop the chip now, marking it as
* faulty, so that it will be reset next time through ...
@@ -4857,25 +5478,6 @@ bge_chip_factotum(caddr_t arg)
}
mutex_exit(bgep->genlock);
- /*
- * If the link state changed, tell the world about it.
- * Note: can't do this while still holding the mutex.
- */
- if (bgep->link_update_timer == BGE_LINK_UPDATE_TIMEOUT &&
- bgep->link_state != LINK_STATE_UNKNOWN)
- linkchg = B_TRUE;
- else if (bgep->link_update_timer < BGE_LINK_UPDATE_TIMEOUT &&
- bgep->link_state == LINK_STATE_DOWN)
- linkchg = B_FALSE;
-
- if (linkchg) {
- mac_link_update(bgep->mh, bgep->link_state);
- bgep->link_update_timer = BGE_LINK_UPDATE_DONE;
- }
- if (bgep->manual_reset) {
- bgep->manual_reset = B_FALSE;
- }
-
return (result);
}
@@ -4893,6 +5495,7 @@ void
bge_chip_cyclic(void *arg)
{
bge_t *bgep;
+ uint32_t regval;
bgep = arg;
@@ -4901,22 +5504,44 @@ bge_chip_cyclic(void *arg)
return;
case BGE_CHIP_RUNNING:
+
+ /* XXX I really don't like this forced interrupt... */
bge_reg_set32(bgep, HOST_COALESCE_MODE_REG, COALESCE_NOW);
if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK)
ddi_fm_service_impact(bgep->devinfo,
DDI_SERVICE_UNAFFECTED);
- if (bgep->link_update_timer < BGE_LINK_UPDATE_TIMEOUT)
- bgep->link_update_timer++;
-
break;
case BGE_CHIP_FAULT:
case BGE_CHIP_ERROR:
+
break;
}
+ mutex_enter(bgep->genlock);
+
+ if (bgep->eee_lpi_wait && !--bgep->eee_lpi_wait) {
+ BGE_DEBUG(("eee cyclic, lpi enabled"));
+ bge_eee_enable(bgep);
+ }
+
+ if (bgep->rdma_length_bug_on_5719) {
+ if ((bge_reg_get32(bgep, STAT_IFHCOUT_UPKGS_REG) +
+ bge_reg_get32(bgep, STAT_IFHCOUT_MPKGS_REG) +
+ bge_reg_get32(bgep, STAT_IFHCOUT_BPKGS_REG)) >
+ BGE_NUM_RDMA_CHANNELS) {
+ regval = bge_reg_get32(bgep, RDMA_CORR_CTRL_REG);
+ regval &= ~RDMA_CORR_CTRL_TX_LENGTH_WA;
+ bge_reg_put32(bgep, RDMA_CORR_CTRL_REG, regval);
+ bgep->rdma_length_bug_on_5719 = B_FALSE;
+ }
+ }
+
+ mutex_exit(bgep->genlock);
+
bge_wake_factotum(bgep);
+
}
@@ -5784,8 +6409,10 @@ bge_nic_read32(bge_t *bgep, bge_regno_t addr)
addr = addr + 4;
}
#else
- if (DEVICE_5717_SERIES_CHIPSETS(bgep))
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
addr = LE_32(addr);
+ }
#endif
pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MWBAR, addr);
@@ -5925,6 +6552,10 @@ bge_asf_pre_reset_operations(bge_t *bgep, uint32_t mode)
break;
}
}
+
+ if (mode == BGE_INIT_RESET ||
+ mode == BGE_SUSPEND_RESET)
+ bge_ape_driver_state_change(bgep, mode);
}
@@ -5965,6 +6596,9 @@ bge_asf_post_reset_new_mode(bge_t *bgep, uint32_t mode)
default:
break;
}
+
+ if (mode == BGE_SHUTDOWN_RESET)
+ bge_ape_driver_state_change(bgep, mode);
}
#endif /* BGE_IPMI_ASF */
diff --git a/usr/src/uts/common/io/bge/bge_hw.h b/usr/src/uts/common/io/bge/bge_hw.h
index f8e6c4d09a..506b97774e 100644
--- a/usr/src/uts/common/io/bge/bge_hw.h
+++ b/usr/src/uts/common/io/bge/bge_hw.h
@@ -20,7 +20,13 @@
*/
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010-2013, by Broadcom, Inc.
+ * All Rights Reserved.
+ */
+
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates.
+ * All rights reserved.
*/
#ifndef _BGE_HW_H
@@ -64,8 +70,13 @@ extern "C" {
#define DEVICE_ID_5705C 0x1653
#define DEVICE_ID_5705_2 0x1654
#define DEVICE_ID_5717 0x1655
+#define DEVICE_ID_5717_C0 0x1665
#define DEVICE_ID_5718 0x1656
+#define DEVICE_ID_5719 0x1657
+#define DEVICE_ID_5720 0x165f
#define DEVICE_ID_5724 0x165c
+#define DEVICE_ID_5725 0x1643
+#define DEVICE_ID_5727 0x16f3
#define DEVICE_ID_5705M 0x165d
#define DEVICE_ID_5705MA3 0x165e
#define DEVICE_ID_5705F 0x166e
@@ -187,9 +198,15 @@ extern "C" {
(bgep->chipid.device == DEVICE_ID_5789))
#define DEVICE_5717_SERIES_CHIPSETS(bgep) \
- (bgep->chipid.device == DEVICE_ID_5717) ||\
+ ((bgep->chipid.device == DEVICE_ID_5717) ||\
(bgep->chipid.device == DEVICE_ID_5718) ||\
- (bgep->chipid.device == DEVICE_ID_5724)
+ (bgep->chipid.device == DEVICE_ID_5719) ||\
+ (bgep->chipid.device == DEVICE_ID_5720) ||\
+ (bgep->chipid.device == DEVICE_ID_5724))
+
+#define DEVICE_5725_SERIES_CHIPSETS(bgep) \
+ ((bgep->chipid.device == DEVICE_ID_5725) ||\
+ (bgep->chipid.device == DEVICE_ID_5727))
#define DEVICE_5723_SERIES_CHIPSETS(bgep) \
((bgep->chipid.device == DEVICE_ID_5723) ||\
@@ -230,11 +247,13 @@ extern "C" {
#define MHCR_ENABLE_INDIRECT_ACCESS 0x00000080
#define MHCR_ENABLE_REGISTER_WORD_SWAP 0x00000040
#define MHCR_ENABLE_CLOCK_CONTROL_WRITE 0x00000020
-#define MHCR_ENABLE_PCI_STATE_WRITE 0x00000010
+#define MHCR_ENABLE_PCI_STATE_RW 0x00000010
#define MHCR_ENABLE_ENDIAN_WORD_SWAP 0x00000008
#define MHCR_ENABLE_ENDIAN_BYTE_SWAP 0x00000004
#define MHCR_MASK_PCI_INT_OUTPUT 0x00000002
#define MHCR_CLEAR_INTERRUPT_INTA 0x00000001
+#define MHCR_BOUNDARY_CHECK 0x00002000
+#define MHCR_TLP_MINOR_ERR_TOLERANCE 0x00008000
#define MHCR_CHIP_REV_5700_B0 0x71000000
#define MHCR_CHIP_REV_5700_B2 0x71020000
@@ -304,12 +323,11 @@ extern "C" {
#define MHCR_CHIP_REV_5906_A1 0xc0010000
#define MHCR_CHIP_REV_5906_A2 0xc0020000
-#define MHCR_CHIP_REV_5723_A0 0xf0000000
-#define MHCR_CHIP_REV_5723_A1 0xf0010000
-#define MHCR_CHIP_REV_5723_A2 0xf0020000
-#define MHCR_CHIP_REV_5723_B0 0xf1000000
+#define CHIP_ASIC_REV_USE_PROD_ID_REG 0xf0000000
+#define MHCR_CHIP_ASIC_REV(bgep) ((bgep)->chipid.asic_rev & 0xf0000000)
+#define CHIP_ASIC_REV_PROD_ID(bgep) ((bgep)->chipid.asic_rev_prod_id)
+#define CHIP_ASIC_REV(bgep) ((bgep)->chipid.asic_rev_prod_id >> 12)
-#define MHCR_CHIP_ASIC_REV(ChipRevId) ((ChipRevId) & 0xf0000000)
#define MHCR_CHIP_ASIC_REV_5700 (0x7 << 28)
#define MHCR_CHIP_ASIC_REV_5701 (0x0 << 28)
#define MHCR_CHIP_ASIC_REV_5703 (0x1 << 28)
@@ -323,8 +341,30 @@ extern "C" {
#define MHCR_CHIP_ASIC_REV_5755 ((uint32_t)0xa << 28)
#define MHCR_CHIP_ASIC_REV_5715 ((uint32_t)0x9 << 28)
#define MHCR_CHIP_ASIC_REV_5906 ((uint32_t)0xc << 28)
+/* (0xf << 28) touches all 5717 and 5725 series as well (OK) */
#define MHCR_CHIP_ASIC_REV_5723 ((uint32_t)0xf << 28)
+#define CHIP_ASIC_REV_5723 0x5784
+#define CHIP_ASIC_REV_5761 0x5761
+#define CHIP_ASIC_REV_5785 0x5785
+#define CHIP_ASIC_REV_57780 0x57780
+
+#define CHIP_ASIC_REV_5717 0x5717
+#define CHIP_ASIC_REV_5719 0x5719
+#define CHIP_ASIC_REV_5720 0x5720
+#define CHIP_ASIC_REV_5762 0x5762 /* 5725/5727 */
+
+#define CHIP_ASIC_REV_PROD_ID_REG 0x000000bc
+#define CHIP_ASIC_REV_PROD_ID_GEN2_REG 0x000000f4
+
+#define CHIP_ASIC_REV_5717_B0 0x05717100
+#define CHIP_ASIC_REV_5717_C0 0x05717200
+#define CHIP_ASIC_REV_5718_B0 0x05717100
+#define CHIP_ASIC_REV_5719_A0 0x05719000
+#define CHIP_ASIC_REV_5719_A1 0x05719001
+#define CHIP_ASIC_REV_5720_A0 0x05720000
+#define CHIP_ASIC_REV_5725_A0 0x05762000
+#define CHIP_ASIC_REV_5727_B0 0x05762100
/*
* PCI DMA read/write Control Register, in PCI config space
@@ -374,6 +414,9 @@ extern "C" {
* is set in the MHCR, EXCEPT for the RETRY_SAME_DMA bit which is always RW
*/
#define PCI_CONF_BGE_PCISTATE 0x70
+#define PCISTATE_ALLOW_APE_CTLSPC_WR 0x00010000
+#define PCISTATE_ALLOW_APE_SHMEM_WR 0x00020000
+#define PCISTATE_ALLOW_APE_PSPACE_WR 0x00040000
#define PCISTATE_RETRY_SAME_DMA 0x00002000
#define PCISTATE_FLAT_VIEW 0x00000100
#define PCISTATE_EXT_ROM_RETRY 0x00000040
@@ -458,7 +501,10 @@ extern "C" {
*/
#define PCI_CONF_DEV_CTRL 0xd8
#define PCI_CONF_DEV_CTRL_5723 0xd4
+#define PCI_CONF_DEV_CTRL_5717 0xb4
+#define READ_REQ_SIZE_MASK 0x7000
#define READ_REQ_SIZE_MAX 0x5000
+#define READ_REQ_SIZE_2K 0x4000
#define DEV_CTRL_NO_SNOOP 0x0800
#define DEV_CTRL_RELAXED 0x0010
@@ -497,7 +543,7 @@ extern "C" {
#define NIC_MEM_SHADOW_SEND_7_8 0x7000 /* bogus */
#define NIC_MEM_SHADOW_SEND_9_16 0x8000 /* bogus */
#define NIC_MEM_SHADOW_BUFF_STD 0x6000
-#define NIC_MEM_SHADOW_BUFF_STD_5717 0x40000
+#define NIC_MEM_SHADOW_BUFF_STD_5717 0x40000
#define NIC_MEM_SHADOW_BUFF_JUMBO 0x7000
#define NIC_MEM_SHADOW_BUFF_MINI 0x8000 /* bogus */
#define NIC_MEM_SHADOW_SEND_RING(ring, nslots) (0x4000 + 4*(ring)*(nslots))
@@ -540,9 +586,31 @@ extern "C" {
#define HOST_COALESCE_MODE_REG 0x3c00
#define MEMORY_ARBITER_MODE_REG 0x4000
#define BUFFER_MANAGER_MODE_REG 0x4400
+#define BUFFER_MANAGER_MODE_NO_TX_UNDERRUN 0x80000000
+#define BUFFER_MANAGER_MODE_MBLOW_ATTN_ENABLE 0x00000010
#define READ_DMA_MODE_REG 0x4800
#define WRITE_DMA_MODE_REG 0x4c00
#define DMA_COMPLETION_MODE_REG 0x6400
+#define FAST_BOOT_PC 0x6894
+
+#define RDMA_RSRV_CTRL_REG 0x4900
+#define RDMA_RSRV_CTRL_REG2 0x4890
+#define RDMA_RSRV_CTRL_FIFO_OFLW_FIX 0x00000004
+#define RDMA_RSRV_CTRL_FIFO_LWM_1_5K 0x00000c00
+#define RDMA_RSRV_CTRL_FIFO_LWM_MASK 0x00000ff0
+#define RDMA_RSRV_CTRL_FIFO_HWM_1_5K 0x000c0000
+#define RDMA_RSRV_CTRL_FIFO_HWM_MASK 0x000ff000
+#define RDMA_RSRV_CTRL_TXMRGN_320B 0x28000000
+#define RDMA_RSRV_CTRL_TXMRGN_MASK 0xffe00000
+
+#define RDMA_CORR_CTRL_REG 0x4910
+#define RDMA_CORR_CTRL_REG2 0x48a0
+#define RDMA_CORR_CTRL_BLEN_BD_4K 0x00030000
+#define RDMA_CORR_CTRL_BLEN_LSO_4K 0x000c0000
+#define RDMA_CORR_CTRL_TX_LENGTH_WA 0x02000000
+
+#define BGE_NUM_RDMA_CHANNELS 4
+#define BGE_RDMA_LENGTH 0x4be0
/*
* Other bits in some of the above state machine control registers
@@ -552,6 +620,7 @@ extern "C" {
* Transmit MAC Mode Register
* (TRANSMIT_MAC_MODE_REG, 0x045c)
*/
+#define TRANSMIT_MODE_MBUF_LOCKUP_FIX 0x00000100
#define TRANSMIT_MODE_LONG_PAUSE 0x00000040
#define TRANSMIT_MODE_BIG_BACKOFF 0x00000020
#define TRANSMIT_MODE_FLOW_CONTROL 0x00000010
@@ -682,6 +751,8 @@ extern "C" {
* Ethernet MAC Mode Register
*/
#define ETHERNET_MAC_MODE_REG 0x0400
+#define ETHERNET_MODE_APE_TX_EN 0x10000000
+#define ETHERNET_MODE_APE_RX_EN 0x08000000
#define ETHERNET_MODE_ENABLE_FHDE 0x00800000
#define ETHERNET_MODE_ENABLE_RDE 0x00400000
#define ETHERNET_MODE_ENABLE_TDE 0x00200000
@@ -970,8 +1041,12 @@ extern "C" {
#define SERDES_STATUS_COMMA_DETECTED 0x00000100
#define SERDES_STATUS_RXSTAT 0x000000ff
+/* 5780/5714 only */
+#define SERDES_RX_CONTROL 0x000005b0
+#define SERDES_RX_CONTROL_SIG_DETECT 0x00000400
+
/*
- * SGMII Status Register (5717/5718 only)
+ * SGMII Status Register (5717/18/19/20 only)
*/
#define SGMII_STATUS_REG 0x5B4
#define MEDIA_SELECTION_MODE 0x00000100
@@ -1069,10 +1144,53 @@ extern "C" {
#define JUMBO_RCV_BD_REPLENISH_DEFAULT 0x00000020 /* 32 */
/*
- * CPMU registers (5717/5718 only)
+ * CPMU registers (5717/18/19/20 only)
+ */
+#define CPMU_CLCK_ORIDE_REG 0x3624
+#define CPMU_CLCK_ORIDE_MAC_ORIDE_EN 0x80000000
+#define CPMU_STATUS_REG 0x362c
+#define CPMU_STATUS_FUNC_NUM 0x20000000
+#define CPMU_STATUS_FUNC_NUM_SHIFT 29
+#define CPMU_STATUS_FUNC_NUM_5719 0xc0000000
+#define CPMU_STATUS_FUNC_NUM_5719_SHIFT 30
+
+/*
+ * EEE registers (5718/19/20 only)
*/
-#define CPMU_STATUS_REG 0x362c
-#define CPMU_STATUS_FUN_NUM 0x20000000
+#define EEE_MODE_REG 0x36b0
+#define EEE_MODE_APE_TX_DET_EN 0x00000004
+#define EEE_MODE_ERLY_L1_XIT_DET 0x00000008
+#define EEE_MODE_SND_IDX_DET_EN 0x00000040
+#define EEE_MODE_LPI_ENABLE 0x00000080
+#define EEE_MODE_LPI_IN_TX 0x00000100
+#define EEE_MODE_LPI_IN_RX 0x00000200
+#define EEE_MODE_EEE_ENABLE 0x00100000
+
+#define EEE_DEBOUNCE_T1_CONTROL_REG 0x36b4
+#define EEE_DEBOUNCE_T1_PCIEXIT_2047US 0x07ff0000
+#define EEE_DEBOUNCE_T1_LNKIDLE_2047US 0x000007ff
+
+#define EEE_DEBOUNCE_T2_CONTROL_REG 0x36b8
+#define EEE_DEBOUNCE_T2_APE_TX_2047US 0x07ff0000
+#define EEE_DEBOUNCE_T2_TXIDXEQ_2047US 0x000007ff
+
+#define EEE_LINK_IDLE_CONTROL_REG 0x36bc
+#define EEE_LINK_IDLE_PCIE_NL0 0x01000000
+#define EEE_LINK_IDLE_UART_IDL 0x00000004
+#define EEE_LINK_IDLE_APE_TX_MT 0x00000002
+
+#define EEE_CONTROL_REG 0x36d0
+#define EEE_CONTROL_EXIT_16_5_US 0x0000019d
+#define EEE_CONTROL_EXIT_36_US 0x00000384
+#define EEE_CONTROL_EXIT_20_1_US 0x000001f8
+
+/* Clause 45 expansion registers */
+#define EEE_CL45_D7_RESULT_STAT 0x803e
+#define EEE_CL45_D7_RESULT_STAT_LP_100TX 0x0002
+#define EEE_CL45_D7_RESULT_STAT_LP_1000T 0x0004
+
+#define MDIO_MMD_AN 0x0007
+#define MDIO_AN_EEE_ADV 0x003c
/*
* Host Coalescing Engine Control Registers
@@ -1259,25 +1377,43 @@ extern "C" {
* Miscellaneous Local Control Register (MLCR)
*/
#define MISC_LOCAL_CONTROL_REG 0x6808
+
#define MLCR_PCI_CTRL_SELECT 0x10000000
#define MLCR_LEGACY_PCI_MODE 0x08000000
#define MLCR_AUTO_SEEPROM_ACCESS 0x01000000
#define MLCR_SSRAM_CYCLE_DESELECT 0x00800000
#define MLCR_SSRAM_TYPE 0x00400000
#define MLCR_BANK_SELECT 0x00200000
+
+#define MLCR_SRAM_SIZE_16M 0x00180000
+#define MLCR_SRAM_SIZE_8M 0x00140000
+#define MLCR_SRAM_SIZE_4M 0x00100000
+#define MLCR_SRAM_SIZE_2M 0x000c0000
+#define MLCR_SRAM_SIZE_1M 0x00080000
+#define MLCR_SRAM_SIZE_512K 0x00040000
+#define MLCR_SRAM_SIZE_256K 0x00000000
#define MLCR_SRAM_SIZE_MASK 0x001c0000
-#define MLCR_ENABLE_EXTERNAL_MEMORY 0x00020000
+#define MLCR_ENABLE_EXTERNAL_MEMORY 0x00020000
#define MLCR_MISC_PINS_OUTPUT_2 0x00010000
+
#define MLCR_MISC_PINS_OUTPUT_1 0x00008000
#define MLCR_MISC_PINS_OUTPUT_0 0x00004000
#define MLCR_MISC_PINS_OUTPUT_ENABLE_2 0x00002000
#define MLCR_MISC_PINS_OUTPUT_ENABLE_1 0x00001000
+
#define MLCR_MISC_PINS_OUTPUT_ENABLE_0 0x00000800
#define MLCR_MISC_PINS_INPUT_2 0x00000400 /* R/O */
#define MLCR_MISC_PINS_INPUT_1 0x00000200 /* R/O */
#define MLCR_MISC_PINS_INPUT_0 0x00000100 /* R/O */
+#define MLCR_GPIO_OUTPUT3 0x00000080
+#define MLCR_GPIO_OE3 0x00000040
+#define MLCR_USE_EXT_SIG_DETECT 0x00000020 /* 5714/5780 only */
+#define MLCR_GPIO_INPUT3 0x00000020
+#define MLCR_GPIO_UART_SEL 0x00000010 /* 5755 only */
+#define MLCR_USE_SIG_DETECT 0x00000010 /* 5714/5780 only */
+
#define MLCR_INT_ON_ATTN 0x00000008 /* R/W */
#define MLCR_SET_INT 0x00000004 /* W/O */
#define MLCR_CLR_INT 0x00000002 /* W/O */
@@ -1292,9 +1428,20 @@ extern "C" {
* just this fashion. It has to be set as an OUTPUT and driven LOW to
* enable writing. Otherwise, the SEEPROM is protected.
*/
-#define MLCR_DEFAULT 0x0101c000
-#define MLCR_DEFAULT_5714 0x1901c000
-#define MLCR_DEFAULT_5717 0x01000000
+#define MLCR_DEFAULT (MLCR_AUTO_SEEPROM_ACCESS | \
+ MLCR_MISC_PINS_OUTPUT_2 | \
+ MLCR_MISC_PINS_OUTPUT_1 | \
+ MLCR_MISC_PINS_OUTPUT_0)
+
+#define MLCR_DEFAULT_5714 (MLCR_PCI_CTRL_SELECT | \
+ MLCR_LEGACY_PCI_MODE | \
+ MLCR_AUTO_SEEPROM_ACCESS | \
+ MLCR_MISC_PINS_OUTPUT_2 | \
+ MLCR_MISC_PINS_OUTPUT_1 | \
+ MLCR_MISC_PINS_OUTPUT_0 | \
+ MLCR_USE_SIG_DETECT)
+
+#define MLCR_DEFAULT_5717 (MLCR_AUTO_SEEPROM_ACCESS)
/*
* Serial EEPROM Data/Address Registers (auto-access mode)
@@ -1351,31 +1498,58 @@ extern "C" {
#define NVM_CFG1_FLASH_MODE 0x00000001
#define NVM_SW_ARBITRATION_REG 0x7020
-#define NVM_READ_REQ3 0X00008000
-#define NVM_READ_REQ2 0X00004000
-#define NVM_READ_REQ1 0X00002000
-#define NVM_READ_REQ0 0X00001000
-#define NVM_WON_REQ3 0X00000800
-#define NVM_WON_REQ2 0X00000400
-#define NVM_WON_REQ1 0X00000200
-#define NVM_WON_REQ0 0X00000100
-#define NVM_RESET_REQ3 0X00000080
-#define NVM_RESET_REQ2 0X00000040
-#define NVM_RESET_REQ1 0X00000020
-#define NVM_RESET_REQ0 0X00000010
-#define NVM_SET_REQ3 0X00000008
-#define NVM_SET_REQ2 0X00000004
-#define NVM_SET_REQ1 0X00000002
-#define NVM_SET_REQ0 0X00000001
+#define NVM_READ_REQ3 0x00008000
+#define NVM_READ_REQ2 0x00004000
+#define NVM_READ_REQ1 0x00002000
+#define NVM_READ_REQ0 0x00001000
+#define NVM_WON_REQ3 0x00000800
+#define NVM_WON_REQ2 0x00000400
+#define NVM_WON_REQ1 0x00000200
+#define NVM_WON_REQ0 0x00000100
+#define NVM_RESET_REQ3 0x00000080
+#define NVM_RESET_REQ2 0x00000040
+#define NVM_RESET_REQ1 0x00000020
+#define NVM_RESET_REQ0 0x00000010
+#define NVM_SET_REQ3 0x00000008
+#define NVM_SET_REQ2 0x00000004
+#define NVM_SET_REQ1 0x00000002
+#define NVM_SET_REQ0 0x00000001
+
+#define EEPROM_MAGIC 0x669955aa
+#define EEPROM_MAGIC_FW 0xa5000000
+#define EEPROM_MAGIC_FW_MSK 0xff000000
+#define EEPROM_SB_FORMAT_MASK 0x00e00000
+#define EEPROM_SB_FORMAT_1 0x00200000
+#define EEPROM_SB_REVISION_MASK 0x001f0000
+#define EEPROM_SB_REVISION_0 0x00000000
+#define EEPROM_SB_REVISION_2 0x00020000
+#define EEPROM_SB_REVISION_3 0x00030000
+#define EEPROM_SB_REVISION_4 0x00040000
+#define EEPROM_SB_REVISION_5 0x00050000
+#define EEPROM_SB_REVISION_6 0x00060000
+#define EEPROM_MAGIC_HW 0xabcd
+#define EEPROM_MAGIC_HW_MSK 0xffff
+
+#define NVM_DIR_START 0x18
+#define NVM_DIR_END 0x78
+#define NVM_DIRENT_SIZE 0xc
+#define NVM_DIRTYPE_SHIFT 24
+#define NVM_DIRTYPE_LENMSK 0x003fffff
+#define NVM_DIRTYPE_ASFINI 1
+#define NVM_DIRTYPE_EXTVPD 20
+#define NVM_PTREV_BCVER 0x94
+#define NVM_BCVER_MAJMSK 0x0000ff00
+#define NVM_BCVER_MAJSFT 8
+#define NVM_BCVER_MINMSK 0x000000ff
/*
* NVM access register
* Applicable to BCM5721,BCM5751,BCM5752,BCM5714
* and BCM5715 only.
*/
-#define NVM_ACCESS_REG 0X7024
-#define NVM_WRITE_ENABLE 0X00000002
-#define NVM_ACCESS_ENABLE 0X00000001
+#define NVM_ACCESS_REG 0x7024
+#define NVM_WRITE_ENABLE 0x00000002
+#define NVM_ACCESS_ENABLE 0x00000001
/*
* TLP Control Register
@@ -1406,6 +1580,24 @@ extern "C" {
/*
* Vendor-specific MII registers
*/
+
+#define MII_MMD_CTRL 0x0d /* MMD Access Control register */
+#define MII_MMD_CTRL_DATA_NOINC 0x4000
+#define MII_MMD_ADDRESS_DATA 0x0e /* MMD Address Data register */
+
+#define MII_RXR_COUNTERS 0x14 /* Local/Remote Rx Counts */
+#define MII_DSP_RW_PORT 0x15 /* DSP read/write port */
+#define MII_DSP_CONTROL 0x16 /* DSP control register */
+#define MII_DSP_ADDRESS 0x17 /* DSP address register */
+
+#define MII_DSP_TAP26 0x001a
+#define MII_DSP_TAP26_ALNOKO 0x0001
+#define MII_DSP_TAP26_RMRXSTO 0x0002
+#define MII_DSP_TAP26_OPCSINPT 0x0004
+
+#define MII_DSP_CH34TP2 0x4022
+#define MII_DSP_CH34TP2_HIBW01 0x017b
+
#define MII_EXT_CONTROL MII_VENDOR(0)
#define MII_EXT_STATUS MII_VENDOR(1)
#define MII_RCV_ERR_COUNT MII_VENDOR(2)
@@ -1491,6 +1683,9 @@ extern "C" {
#define MII_AUX_CTRL_MISC_WRITE_ENABLE 0x8000
#define MII_AUX_CTRL_MISC_WIRE_SPEED 0x0010
+#define MII_AUX_CTRL_TX_6DB 0x0400
+#define MII_AUX_CTRL_SMDSP_ENA 0x0800
+
/*
* Write this value to the AUX control register
* to select which shadow register will be read
@@ -1611,6 +1806,7 @@ typedef struct {
#define SBD_FLAG_IP_CKSUM 0x0002
#define SBD_FLAG_PACKET_END 0x0004
#define SBD_FLAG_IP_FRAG 0x0008
+#define SBD_FLAG_JMB_PKT 0x0008
#define SBD_FLAG_IP_FRAG_END 0x0010
#define SBD_FLAG_VLAN_TAG 0x0040
@@ -2095,6 +2291,83 @@ typedef struct {
#endif /* BGE_IPMI_ASF */
+/* APE registers. Accessible through BAR1 */
+#define BGE_APE_GPIO_MSG 0x0008
+#define BGE_APE_GPIO_MSG_SHIFT 4
+#define BGE_APE_EVENT 0x000c
+#define APE_EVENT_1 0x00000001
+#define BGE_APE_LOCK_REQ 0x002c
+#define APE_LOCK_REQ_DRIVER 0x00001000
+#define BGE_APE_LOCK_GRANT 0x004c
+#define APE_LOCK_GRANT_DRIVER 0x00001000
+#define BGE_APE_STICKY_TMR 0x00b0
+
+/* APE shared memory. Accessible through BAR1 */
+#define BGE_APE_SHMEM_BASE 0x4000
+#define BGE_APE_SEG_SIG 0x4000
+#define APE_SEG_SIG_MAGIC 0x41504521
+#define BGE_APE_FW_STATUS 0x400c
+#define APE_FW_STATUS_READY 0x00000100
+#define BGE_APE_FW_FEATURES 0x4010
+#define BGE_APE_FW_FEATURE_NCSI 0x00000002
+#define BGE_APE_FW_VERSION 0x4018
+#define APE_FW_VERSION_MAJMSK 0xff000000
+#define APE_FW_VERSION_MAJSFT 24
+#define APE_FW_VERSION_MINMSK 0x00ff0000
+#define APE_FW_VERSION_MINSFT 16
+#define APE_FW_VERSION_REVMSK 0x0000ff00
+#define APE_FW_VERSION_REVSFT 8
+#define APE_FW_VERSION_BLDMSK 0x000000ff
+#define BGE_APE_SEG_MSG_BUF_OFF 0x401c
+#define BGE_APE_SEG_MSG_BUF_LEN 0x4020
+#define BGE_APE_HOST_SEG_SIG 0x4200
+#define APE_HOST_SEG_SIG_MAGIC 0x484f5354
+#define BGE_APE_HOST_SEG_LEN 0x4204
+#define APE_HOST_SEG_LEN_MAGIC 0x00000020
+#define BGE_APE_HOST_INIT_COUNT 0x4208
+#define BGE_APE_HOST_DRIVER_ID 0x420c
+#define APE_HOST_DRIVER_ID_SOLARIS 0xf4000000
+#define APE_HOST_DRIVER_ID_MAGIC(maj, min) \
+ (APE_HOST_DRIVER_ID_SOLARIS | (maj & 0xff) << 16 | (min & 0xff) << 8)
+#define BGE_APE_HOST_BEHAVIOR 0x4210
+#define APE_HOST_BEHAV_NO_PHYLOCK 0x00000001
+#define BGE_APE_HOST_HEARTBEAT_INT_MS 0x4214
+#define APE_HOST_HEARTBEAT_INT_DISABLE 0
+#define APE_HOST_HEARTBEAT_INT_5SEC 5000
+#define BGE_APE_HOST_HEARTBEAT_COUNT 0x4218
+#define BGE_APE_HOST_DRVR_STATE 0x421c
+#define BGE_APE_HOST_DRVR_STATE_START 0x00000001
+#define BGE_APE_HOST_DRVR_STATE_UNLOAD 0x00000002
+#define BGE_APE_HOST_DRVR_STATE_WOL 0x00000003
+#define BGE_APE_HOST_WOL_SPEED 0x4224
+#define BGE_APE_HOST_WOL_SPEED_AUTO 0x00008000
+
+#define BGE_APE_EVENT_STATUS 0x4300
+
+#define APE_EVENT_STATUS_DRIVER_EVNT 0x00000010
+#define APE_EVENT_STATUS_STATE_CHNGE 0x00000500
+#define APE_EVENT_STATUS_SCRTCHPD_READ 0x00001600
+#define APE_EVENT_STATUS_SCRTCHPD_WRITE 0x00001700
+#define APE_EVENT_STATUS_STATE_START 0x00010000
+#define APE_EVENT_STATUS_STATE_UNLOAD 0x00020000
+#define APE_EVENT_STATUS_STATE_WOL 0x00030000
+#define APE_EVENT_STATUS_STATE_SUSPEND 0x00040000
+#define APE_EVENT_STATUS_EVENT_PENDING 0x80000000
+
+#define BGE_APE_PER_LOCK_REQ 0x8400
+#define APE_LOCK_PER_REQ_DRIVER 0x00001000
+#define BGE_APE_PER_LOCK_GRANT 0x8420
+#define APE_PER_LOCK_GRANT_DRIVER 0x00001000
+
+/* APE convenience enumerations. */
+#define BGE_APE_LOCK_PHY0 0
+#define BGE_APE_LOCK_GRC 1
+#define BGE_APE_LOCK_PHY1 2
+#define BGE_APE_LOCK_PHY2 3
+#define BGE_APE_LOCK_MEM 4
+#define BGE_APE_LOCK_PHY3 5
+#define BGE_APE_LOCK_GPIO 7
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/io/bge/bge_impl.h b/usr/src/uts/common/io/bge/bge_impl.h
index 772c989092..ccc57b94e7 100644
--- a/usr/src/uts/common/io/bge/bge_impl.h
+++ b/usr/src/uts/common/io/bge/bge_impl.h
@@ -20,7 +20,13 @@
*/
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010-2013, by Broadcom, Inc.
+ * All Rights Reserved.
+ */
+
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates.
+ * All rights reserved.
*/
#ifndef _BGE_IMPL_H
@@ -45,7 +51,6 @@ extern "C" {
#endif /* __sparcv9 */
#include <sys/kstat.h>
#include <sys/ethernet.h>
-#include <sys/vlan.h>
#include <sys/errno.h>
#include <sys/dlpi.h>
#include <sys/devops.h>
@@ -77,6 +82,18 @@ extern "C" {
#include <sys/x86_archext.h>
#endif
+#ifndef VLAN_TAGSZ
+#define VLAN_TAGSZ 4
+#endif
+
+#define BGE_STR_SIZE 32
+
+#ifndef OFFSETOF
+#define OFFSETOF(_s, _f) \
+ ((uint32_t)((uint8_t *)(&((_s *)0)->_f) - \
+ (uint8_t *)((uint8_t *) 0)))
+#endif
+
/*
* <sys/ethernet.h> *may* already have provided the typedef ether_addr_t;
* but of course C doesn't provide a way to check this directly. So here
@@ -94,7 +111,6 @@ typedef uchar_t ether_addr_t[ETHERADDRL];
*/
extern int secpolicy_net_config(const cred_t *, boolean_t);
-#include <sys/netlb.h> /* originally from cassini */
#include <sys/miiregs.h> /* by fjlite out of intel */
#include "bge.h"
@@ -133,6 +149,7 @@ extern int secpolicy_net_config(const cred_t *, boolean_t);
#define BGE_PCI_CONFIG_RNUMBER 0
#define BGE_PCI_OPREGS_RNUMBER 1
+#define BGE_PCI_APEREGS_RNUMBER 2
#define BGE_DMA_MODE DDI_DMA_STREAMING
#define BGE_HEADROOM 34
@@ -168,6 +185,7 @@ extern int secpolicy_net_config(const cred_t *, boolean_t);
#define BGE_HALFTICK 268435456LL /* 2**28 ns! */
#define BGE_CYCLIC_PERIOD (4*BGE_HALFTICK) /* ~1.0s */
+#define BGE_CYCLIC_TIMEOUT (drv_usectohz(1000000)) /* ~1.0s */
#define BGE_SERDES_STABLE_TIME (3*BGE_HALFTICK) /* ~0.8s */
#define BGE_PHY_STABLE_TIME (11*BGE_HALFTICK) /* ~3.0s */
#define BGE_LINK_SETTLE_TIME (111*BGE_HALFTICK) /* ~30.0s */
@@ -301,7 +319,6 @@ extern int secpolicy_net_config(const cred_t *, boolean_t);
#define BGE_LOWAT (256)
#define BGE_HIWAT (256*1024)
-
/*
* Basic data types, for clarity in distinguishing 'numbers'
* used for different purposes ...
@@ -593,6 +610,7 @@ enum bge_nvmem_type {
*/
typedef struct {
uint32_t asic_rev; /* masked from MHCR */
+ uint32_t asic_rev_prod_id; /* new revision ID format */
uint32_t businfo; /* from private reg */
uint16_t command; /* saved during attach */
@@ -627,6 +645,7 @@ typedef struct {
uint32_t rx_rings; /* from bge.conf */
uint32_t tx_rings; /* from bge.conf */
+ uint32_t eee; /* from bge.conf */
uint32_t default_mtu; /* from bge.conf */
uint64_t hw_mac_addr; /* from chip register */
@@ -718,11 +737,22 @@ typedef struct bge {
/*
* These fields are set by attach() and unchanged thereafter ...
*/
+ char version[BGE_STR_SIZE];
+#define BGE_FW_VER_SIZE 32
+ char fw_version[BGE_FW_VER_SIZE];
dev_info_t *devinfo; /* device instance */
+ uint32_t pci_bus; /* from "regs" prop */
+ uint32_t pci_dev; /* from "regs" prop */
+ uint32_t pci_func; /* from "regs" prop */
mac_handle_t mh; /* mac module handle */
ddi_acc_handle_t cfg_handle; /* DDI I/O handle */
ddi_acc_handle_t io_handle; /* DDI I/O handle */
void *io_regs; /* mapped registers */
+ ddi_acc_handle_t ape_handle; /* DDI I/O handle */
+ void *ape_regs; /* mapped registers */
+ boolean_t ape_enabled;
+ boolean_t ape_has_ncsi;
+
ddi_periodic_t periodic_id; /* periodical callback */
ddi_softintr_t factotum_id; /* factotum callback */
ddi_softintr_t drain_id; /* reschedule callback */
@@ -784,6 +814,8 @@ typedef struct bge {
recv_ring_t recv[BGE_RECV_RINGS_MAX]; /* 16*0x0090 */
send_ring_t send[BGE_SEND_RINGS_MAX]; /* 16*0x0100 */
+ mac_resource_handle_t macRxResourceHandles[BGE_RECV_RINGS_MAX];
+
/*
* Locks:
*
@@ -884,6 +916,7 @@ typedef struct bge {
uint64_t tx_resched;
uint32_t factotum_flag; /* softint pending */
uintptr_t pagemask;
+ boolean_t rdma_length_bug_on_5719;
/*
* NDD parameters (protected by genlock)
@@ -953,12 +986,13 @@ typedef struct bge {
uint32_t param_drain_max;
uint64_t param_link_speed;
link_duplex_t param_link_duplex;
+ uint32_t eee_lpi_wait;
-
- uint32_t link_update_timer;
uint64_t timestamp;
} bge_t;
+#define CATC_TRIGGER(bgep, data) bge_reg_put32(bgep, 0x0a00, (data))
+
/*
* 'Progress' bit flags ...
*/
@@ -1031,35 +1065,31 @@ typedef struct bge {
*/
#define BGE_DBG_STOP 0x00000001 /* early debug_enter() */
#define BGE_DBG_TRACE 0x00000002 /* general flow tracing */
-
+#define BGE_DBG_APE 0x00000004 /* low-level APE access */
+#define BGE_DBG_HPSD 0x00000008 /* low-level HPSD access*/
#define BGE_DBG_REGS 0x00000010 /* low-level accesses */
#define BGE_DBG_MII 0x00000020 /* low-level MII access */
#define BGE_DBG_SEEPROM 0x00000040 /* low-level SEEPROM IO */
#define BGE_DBG_CHIP 0x00000080 /* low(ish)-level code */
-
#define BGE_DBG_RECV 0x00000100 /* receive-side code */
#define BGE_DBG_SEND 0x00000200 /* packet-send code */
-
#define BGE_DBG_INT 0x00001000 /* interrupt handler */
#define BGE_DBG_FACT 0x00002000 /* factotum (softint) */
-
#define BGE_DBG_PHY 0x00010000 /* Copper PHY code */
#define BGE_DBG_SERDES 0x00020000 /* SerDes code */
#define BGE_DBG_PHYS 0x00040000 /* Physical layer code */
#define BGE_DBG_LINK 0x00080000 /* Link status check */
-
#define BGE_DBG_INIT 0x00100000 /* initialisation */
#define BGE_DBG_NEMO 0x00200000 /* nemo interaction */
#define BGE_DBG_ADDR 0x00400000 /* address-setting code */
#define BGE_DBG_STATS 0x00800000 /* statistics */
-
#define BGE_DBG_IOCTL 0x01000000 /* ioctl handling */
#define BGE_DBG_LOOP 0x02000000 /* loopback ioctl code */
#define BGE_DBG_PPIO 0x04000000 /* Peek/poke ioctls */
#define BGE_DBG_BADIOC 0x08000000 /* unknown ioctls */
-
#define BGE_DBG_MCTL 0x10000000 /* mctl (csum) code */
#define BGE_DBG_NDD 0x20000000 /* NDD operations */
+#define BGE_DBG_MEM 0x40000000 /* memory allocations and chunking */
/*
* Debugging ...
@@ -1067,7 +1097,7 @@ typedef struct bge {
#ifdef DEBUG
#define BGE_DEBUGGING 1
#else
-#define BGE_DEBUGGING 0
+#define BGE_DEBUGGING 1
#endif /* DEBUG */
@@ -1107,6 +1137,9 @@ typedef struct bge {
#define BGE_LDB(b, args) BGE_XDB(b, bgep->debug, (*bge_db(bgep)), args)
#define BGE_CDB(f, args) BGE_XDB(BGE_DBG, bgep->debug, f, args)
+#define DEVNAME(_sc) ((_sc)->ifname)
+#define DPRINTF(f, ...) do { cmn_err(CE_NOTE, (f), __VA_ARGS__); } while (0)
+
/*
* Conditional-print macros.
*
@@ -1147,11 +1180,20 @@ typedef struct bge {
/* bge_chip.c */
uint16_t bge_mii_get16(bge_t *bgep, bge_regno_t regno);
void bge_mii_put16(bge_t *bgep, bge_regno_t regno, uint16_t value);
+uint16_t bge_phydsp_read(bge_t *bgep, bge_regno_t regno);
+void bge_phydsp_write(bge_t *bgep, bge_regno_t regno, uint16_t value);
uint32_t bge_reg_get32(bge_t *bgep, bge_regno_t regno);
void bge_reg_put32(bge_t *bgep, bge_regno_t regno, uint32_t value);
void bge_reg_set32(bge_t *bgep, bge_regno_t regno, uint32_t bits);
void bge_reg_clr32(bge_t *bgep, bge_regno_t regno, uint32_t bits);
+uint32_t bge_ape_get32(bge_t *bgep, bge_regno_t regno);
+void bge_ape_put32(bge_t *bgep, bge_regno_t regno, uint32_t value);
void bge_mbx_put(bge_t *bgep, bge_regno_t regno, uint64_t value);
+void bge_ape_lock_init(bge_t *bgep);
+int bge_ape_scratchpad_read(bge_t *bgep, uint32_t *data, uint32_t base_off, uint32_t lenToRead);
+int bge_ape_scratchpad_write(bge_t *bgep, uint32_t dstoff, uint32_t *data, uint32_t lenToWrite);
+int bge_nvmem_read32(bge_t *bgep, bge_regno_t addr, uint32_t *dp);
+int bge_nvmem_write32(bge_t *bgep, bge_regno_t addr, uint32_t *dp);
void bge_chip_cfg_init(bge_t *bgep, chip_id_t *cidp, boolean_t enable_dma);
int bge_chip_id_init(bge_t *bgep);
void bge_chip_coalesce_update(bge_t *bgep);
@@ -1231,7 +1273,9 @@ void bge_intr_enable(bge_t *bgep);
void bge_intr_disable(bge_t *bgep);
int bge_reprogram(bge_t *);
-/* bge_phys.c */
+/* bge_mii.c */
+void bge_eee_init(bge_t *bgep);
+void bge_eee_enable(bge_t * bgep);
int bge_phys_init(bge_t *bgep);
void bge_phys_reset(bge_t *bgep);
int bge_phys_idle(bge_t *bgep);
@@ -1284,9 +1328,6 @@ void bge_adj_volt_5906(bge_t *bgep);
#define BGE_ASF_HEARTBEAT_INTERVAL 1500000
-#define BGE_LINK_UPDATE_TIMEOUT 10 /* ~ 5 sec */
-#define BGE_LINK_UPDATE_DONE (BGE_LINK_UPDATE_TIMEOUT+1)
-
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/io/bge/bge_kstats.c b/usr/src/uts/common/io/bge/bge_kstats.c
index c10a1b4601..9df359507e 100644
--- a/usr/src/uts/common/io/bge/bge_kstats.c
+++ b/usr/src/uts/common/io/bge/bge_kstats.c
@@ -20,6 +20,11 @@
*/
/*
+ * Copyright (c) 2010-2013, by Broadcom, Inc.
+ * All Rights Reserved.
+ */
+
+/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -286,6 +291,10 @@ static const bge_ksindex_t bge_chipid[] = {
{ 18, "&supported" },
{ 19, "&interface" },
+ { 20, "nvtype" },
+
+ { 21, "asic_rev_prod_id" },
+
{ -1, NULL }
};
@@ -343,6 +352,13 @@ bge_chipid_update(kstat_t *ksp, int flag)
bge_set_char_kstat(knp++,
tmp & CHIP_FLAG_SERDES ? "serdes" : "copper");
+ (knp++)->value.ui64 =
+ ((bgep->chipid.nvtype == BGE_NVTYPE_NONE) ||
+ (bgep->chipid.nvtype == BGE_NVTYPE_UNKNOWN)) ?
+ 0 : bgep->chipid.nvtype;
+
+ (knp++)->value.ui64 = bgep->chipid.asic_rev_prod_id;
+
return (0);
}
@@ -499,6 +515,7 @@ static const bge_ksindex_t bge_phydata[] = {
{ MII_INTR_STATUS, "intr_status" },
{ MII_INTR_MASK, "intr_mask" },
{ MII_HCD_STATUS, "hcd_status" },
+ { EEE_MODE_REG, "eee" },
{ -1, NULL }
};
@@ -540,6 +557,16 @@ bge_phydata_update(kstat_t *ksp, int flag)
knp->value.ui64 |= bge_mii_get16(bgep, MII_PHYIDL);
break;
+ case EEE_MODE_REG:
+ knp->value.ui64 = 0;
+ if (bgep->link_state == LINK_STATE_UP)
+ {
+ knp->value.ui64 =
+ (bge_reg_get32(bgep, EEE_MODE_REG) & 0x80) ?
+ 1 : 0;
+ }
+ break;
+
default:
knp->value.ui64 = bge_mii_get16(bgep, ksip->index);
break;
@@ -567,7 +594,7 @@ bge_setup_named_kstat(bge_t *bgep, int instance, char *name,
size /= sizeof (bge_ksindex_t);
ksp = kstat_create(BGE_DRIVER_NAME, instance, name, "net",
- KSTAT_TYPE_NAMED, size-1, KSTAT_FLAG_PERSISTENT);
+ KSTAT_TYPE_NAMED, size-1, 0);
if (ksp == NULL)
return (NULL);
@@ -663,7 +690,7 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val)
bge_statistics_t *bstp;
bge_statistics_reg_t *pstats;
- if (bgep->bge_chip_state == BGE_CHIP_FAULT) {
+ if (bgep->bge_chip_state != BGE_CHIP_RUNNING) {
return (EINVAL);
}
@@ -735,7 +762,8 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val)
switch (stat) {
case MAC_STAT_IFSPEED:
- *val = bgep->param_link_speed * 1000000ull;
+ *val = (bgep->link_state != LINK_STATE_UNKNOWN) ?
+ (bgep->param_link_speed * 1000000ull) : 0;
break;
case MAC_STAT_MULTIRCV:
@@ -916,12 +944,14 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val)
*val = pstats->dot3StatsFrameTooLongs;
break;
+#if (MAC_VERSION > 1)
case ETHER_STAT_TOOSHORT_ERRORS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
*val = bstp->s.etherStatsUndersizePkts;
else
*val = pstats->etherStatsUndersizePkts;
break;
+#endif
case ETHER_STAT_XCVR_ADDR:
*val = bgep->phy_mii_addr;
@@ -994,9 +1024,11 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val)
*val = 1;
break;
+#if (MAC_VERSION > 1)
case ETHER_STAT_CAP_REMFAULT:
*val = 1;
break;
+#endif
case ETHER_STAT_ADV_CAP_1000FDX:
*val = bgep->param_adv_1000fdx;
@@ -1034,6 +1066,7 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val)
*val = bgep->param_adv_autoneg;
break;
+#if (MAC_VERSION > 1)
case ETHER_STAT_ADV_REMFAULT:
if (bgep->chipid.flags & CHIP_FLAG_SERDES)
*val = 0;
@@ -1049,6 +1082,7 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val)
mutex_exit(bgep->genlock);
}
break;
+#endif
case ETHER_STAT_LP_CAP_1000FDX:
*val = bgep->param_lp_1000fdx;
@@ -1086,6 +1120,7 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val)
*val = bgep->param_lp_autoneg;
break;
+#if (MAC_VERSION > 1)
case ETHER_STAT_LP_REMFAULT:
if (bgep->chipid.flags & CHIP_FLAG_SERDES)
*val = 0;
@@ -1101,6 +1136,7 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val)
mutex_exit(bgep->genlock);
}
break;
+#endif
case ETHER_STAT_LINK_ASMPAUSE:
*val = bgep->param_adv_asym_pause &&
@@ -1117,7 +1153,8 @@ bge_m_stat(void *arg, uint_t stat, uint64_t *val)
break;
case ETHER_STAT_LINK_DUPLEX:
- *val = bgep->param_link_duplex;
+ *val = (bgep->link_state != LINK_STATE_UNKNOWN) ?
+ bgep->param_link_duplex : LINK_DUPLEX_UNKNOWN;
break;
default:
diff --git a/usr/src/uts/common/io/bge/bge_lint.c b/usr/src/uts/common/io/bge/bge_lint.c
new file mode 100644
index 0000000000..2f51987068
--- /dev/null
+++ b/usr/src/uts/common/io/bge/bge_lint.c
@@ -0,0 +1,18 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * This is a dummy lint file to pacify lint for bge, which due to its upstream,
+ * makes it, unfortunately, not realistic to lint. We have a dummy definition to
+ * ensure that we don't trigger lint's empty translation unit.
+ */
+
+extern int bge_lint;
diff --git a/usr/src/uts/common/io/bge/bge_main2.c b/usr/src/uts/common/io/bge/bge_main2.c
index f191f313c0..bd7e883ca1 100644
--- a/usr/src/uts/common/io/bge/bge_main2.c
+++ b/usr/src/uts/common/io/bge/bge_main2.c
@@ -20,7 +20,13 @@
*/
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010-2013, by Broadcom, Inc.
+ * All Rights Reserved.
+ */
+
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates.
+ * All rights reserved.
*/
#include "bge_impl.h"
@@ -29,6 +35,12 @@
#include <sys/mac.h>
#include <sys/mac_flow.h>
+
+#ifndef STRINGIFY
+#define XSTRINGIFY(x) #x
+#define STRINGIFY(x) XSTRINGIFY(x)
+#endif
+
/*
* This is the string displayed by modinfo, etc.
*/
@@ -47,18 +59,21 @@ static char subdev_propname[] = "subsystem-id";
static char subven_propname[] = "subsystem-vendor-id";
static char rxrings_propname[] = "bge-rx-rings";
static char txrings_propname[] = "bge-tx-rings";
+static char eee_propname[] = "bge-eee";
static char fm_cap[] = "fm-capable";
static char default_mtu[] = "default_mtu";
static int bge_add_intrs(bge_t *, int);
static void bge_rem_intrs(bge_t *);
static int bge_unicst_set(void *, const uint8_t *, int);
+static int bge_addmac(void *, const uint8_t *);
+static int bge_remmac(void *, const uint8_t *);
/*
* Describes the chip's DMA engine
*/
static ddi_dma_attr_t dma_attr = {
- DMA_ATTR_V0, /* dma_attr version */
+ DMA_ATTR_V0, /* dma_attr_version */
0x0000000000000000ull, /* dma_attr_addr_lo */
0xFFFFFFFFFFFFFFFFull, /* dma_attr_addr_hi */
0x00000000FFFFFFFFull, /* dma_attr_count_max */
@@ -66,7 +81,7 @@ static ddi_dma_attr_t dma_attr = {
0x00000FFF, /* dma_attr_burstsizes */
0x00000001, /* dma_attr_minxfer */
0x000000000000FFFFull, /* dma_attr_maxxfer */
- 0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */
+ 0x00000000FFFFFFFFull, /* dma_attr_seg */
1, /* dma_attr_sgllen */
0x00000001, /* dma_attr_granular */
DDI_DMA_FLAGERR /* dma_attr_flags */
@@ -103,7 +118,9 @@ static ddi_device_acc_attr_t bge_data_accattr = {
static int bge_m_start(void *);
static void bge_m_stop(void *);
static int bge_m_promisc(void *, boolean_t);
+static int bge_m_unicst(void * pArg, const uint8_t *);
static int bge_m_multicst(void *, boolean_t, const uint8_t *);
+static void bge_m_resources(void * arg);
static void bge_m_ioctl(void *, queue_t *, mblk_t *);
static boolean_t bge_m_getcapab(void *, mac_capab_t, void *);
static int bge_unicst_set(void *, const uint8_t *,
@@ -121,26 +138,48 @@ static int bge_get_priv_prop(bge_t *, const char *, uint_t,
static void bge_priv_propinfo(const char *,
mac_prop_info_handle_t);
-#define BGE_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | \
- MC_GETPROP | MC_PROPINFO)
-
static mac_callbacks_t bge_m_callbacks = {
- BGE_M_CALLBACK_FLAGS,
+ MC_IOCTL
+#ifdef MC_RESOURCES
+ | MC_RESOURCES
+#endif
+#ifdef MC_SETPROP
+ | MC_SETPROP
+#endif
+#ifdef MC_GETPROP
+ | MC_GETPROP
+#endif
+#ifdef MC_PROPINFO
+ | MC_PROPINFO
+#endif
+ | MC_GETCAPAB,
bge_m_stat,
bge_m_start,
bge_m_stop,
bge_m_promisc,
bge_m_multicst,
- NULL,
+ bge_m_unicst,
bge_m_tx,
+#ifdef MC_RESOURCES
+ bge_m_resources,
+#else
NULL,
+#endif
bge_m_ioctl,
bge_m_getcapab,
+#ifdef MC_OPEN
NULL,
NULL,
+#endif
+#ifdef MC_SETPROP
bge_m_setprop,
+#endif
+#ifdef MC_GETPROP
bge_m_getprop,
+#endif
+#ifdef MC_PROPINFO
bge_m_propinfo
+#endif
};
char *bge_priv_prop[] = {
@@ -489,7 +528,6 @@ bge_m_stop(void *arg)
} else
bge_stop(bgep);
- bgep->link_update_timer = 0;
bgep->link_state = LINK_STATE_UNKNOWN;
mac_link_update(bgep->mh, bgep->link_state);
@@ -542,6 +580,11 @@ bge_m_start(void *arg)
if ((bgep->asf_status == ASF_STAT_RUN) &&
(bgep->asf_pseudostop)) {
bgep->bge_mac_state = BGE_MAC_STARTED;
+ /* forcing a mac link update here */
+ bge_phys_check(bgep);
+ bgep->link_state = (bgep->param_link_up) ? LINK_STATE_UP :
+ LINK_STATE_DOWN;
+ mac_link_update(bgep->mh, bgep->link_state);
mutex_exit(bgep->genlock);
return (0);
}
@@ -601,7 +644,7 @@ bge_unicst_set(void *arg, const uint8_t *macaddr, int slot)
{
bge_t *bgep = arg; /* private device info */
- BGE_TRACE(("bge_m_unicst_set($%p, %s)", arg,
+ BGE_TRACE(("bge_unicst_set($%p, %s)", arg,
ether_sprintf((void *)macaddr)));
/*
* Remember the new current address in the driver state
@@ -668,7 +711,7 @@ bge_unicst_set(void *arg, const uint8_t *macaddr, int slot)
}
}
#endif
- BGE_DEBUG(("bge_m_unicst_set($%p) done", arg));
+ BGE_DEBUG(("bge_unicst_set($%p) done", arg));
if (bge_check_acc_handle(bgep, bgep->cfg_handle) != DDI_FM_OK) {
ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_DEGRADED);
mutex_exit(bgep->genlock);
@@ -1244,6 +1287,21 @@ bge_priv_propinfo(const char *pr_name, mac_prop_info_handle_t mph)
mac_prop_info_set_default_str(mph, valstr);
}
+
+static int
+bge_m_unicst(void * arg, const uint8_t * mac_addr)
+{
+ bge_t *bgep = arg;
+ int i;
+
+ /* XXX sets the mac address for all ring slots... OK? */
+ for (i = 0; i < MIN(bgep->chipid.rx_rings, MAC_ADDRESS_REGS_MAX); i++)
+ bge_addmac(&bgep->recv[i], mac_addr);
+
+ return (0);
+}
+
+
/*
* Compute the index of the required bit in the multicast hash map.
* This must mirror the way the hardware actually does it!
@@ -1404,6 +1462,37 @@ bge_m_promisc(void *arg, boolean_t on)
return (0);
}
+#ifdef MC_RESOURCES
+
+static void
+bge_blank(void * arg, time_t tick_cnt, uint_t pkt_cnt)
+{
+ (void)arg;
+ (void)tick_cnt;
+ (void)pkt_cnt;
+}
+
+static void
+bge_m_resources(void * arg)
+{
+ bge_t *bgep = arg;
+ mac_rx_fifo_t mrf;
+ int i;
+
+ mrf.mrf_type = MAC_RX_FIFO;
+ mrf.mrf_blank = bge_blank;
+ mrf.mrf_arg = (void *)bgep;
+ mrf.mrf_normal_blank_time = 25;
+ mrf.mrf_normal_pkt_count = 8;
+
+ for (i = 0; i < BGE_RECV_RINGS_MAX; i++) {
+ bgep->macRxResourceHandles[i] =
+ mac_resource_add(bgep->mh, (mac_resource_t *)&mrf);
+ }
+}
+
+#endif /* MC_RESOURCES */
+
/*
* Find the slot for the specified unicast address
*/
@@ -1427,7 +1516,7 @@ bge_unicst_find(bge_t *bgep, const uint8_t *mac_addr)
* specified ring 'arg'.
*/
static int
-bge_addmac(void *arg, const uint8_t *mac_addr)
+bge_addmac(void *arg, const uint8_t * mac_addr)
{
recv_ring_t *rrp = (recv_ring_t *)arg;
bge_t *bgep = rrp->bgep;
@@ -1579,8 +1668,9 @@ bge_remmac(void *arg, const uint8_t *mac_addr)
return (0);
}
+
static int
-bge_flag_intr_enable(mac_intr_handle_t ih)
+bge_flag_intr_enable(mac_ring_driver_t ih)
{
recv_ring_t *rrp = (recv_ring_t *)ih;
bge_t *bgep = rrp->bgep;
@@ -1593,7 +1683,7 @@ bge_flag_intr_enable(mac_intr_handle_t ih)
}
static int
-bge_flag_intr_disable(mac_intr_handle_t ih)
+bge_flag_intr_disable(mac_ring_driver_t ih)
{
recv_ring_t *rrp = (recv_ring_t *)ih;
bge_t *bgep = rrp->bgep;
@@ -1645,9 +1735,8 @@ bge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index,
infop->mri_stat = bge_rx_ring_stat;
mintr = &infop->mri_intr;
- mintr->mi_handle = (mac_intr_handle_t)rx_ring;
- mintr->mi_enable = bge_flag_intr_enable;
- mintr->mi_disable = bge_flag_intr_disable;
+ mintr->mi_enable = (mac_intr_enable_t)bge_flag_intr_enable;
+ mintr->mi_disable = (mac_intr_disable_t)bge_flag_intr_disable;
break;
}
@@ -1666,7 +1755,7 @@ bge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index,
*/
void
bge_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index,
- mac_group_info_t *infop, mac_group_handle_t gh)
+ mac_group_info_t * infop, mac_group_handle_t gh)
{
bge_t *bgep = arg;
@@ -1694,11 +1783,13 @@ bge_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index,
}
}
+
/*ARGSUSED*/
static boolean_t
bge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
{
bge_t *bgep = arg;
+ mac_capab_rings_t *cap_rings;
switch (cap) {
case MAC_CAPAB_HCKSUM: {
@@ -1707,26 +1798,30 @@ bge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
*txflags = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM;
break;
}
- case MAC_CAPAB_RINGS: {
- mac_capab_rings_t *cap_rings = cap_data;
+
+ case MAC_CAPAB_RINGS:
+ cap_rings = (mac_capab_rings_t *)cap_data;
/* Temporarily disable multiple tx rings. */
if (cap_rings->mr_type != MAC_RING_TYPE_RX)
return (B_FALSE);
cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
- cap_rings->mr_rnum = cap_rings->mr_gnum =
+ cap_rings->mr_rnum =
+ cap_rings->mr_gnum =
MIN(bgep->chipid.rx_rings, MAC_ADDRESS_REGS_MAX);
cap_rings->mr_rget = bge_fill_ring;
cap_rings->mr_gget = bge_fill_group;
break;
- }
+
default:
return (B_FALSE);
}
return (B_TRUE);
}
+#ifdef NOT_SUPPORTED_XXX
+
/*
* Loopback ioctl code
*/
@@ -1827,6 +1922,8 @@ bge_loop_ioctl(bge_t *bgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
}
}
+#endif /* NOT_SUPPORTED_XXX */
+
/*
* Specific bge IOCTLs, the gld module handles the generic ones.
*/
@@ -1866,6 +1963,7 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
case BGE_HARD_RESET:
break;
+#ifdef NOT_SUPPORTED_XXX
case LB_GET_INFO_SIZE:
case LB_GET_INFO:
case LB_GET_MODE:
@@ -1873,6 +1971,7 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
/* FALLTHRU */
case LB_SET_MODE:
break;
+#endif
}
@@ -1916,12 +2015,14 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
status = bge_chip_ioctl(bgep, wq, mp, iocp);
break;
+#ifdef NOT_SUPPORTED_XXX
case LB_GET_INFO_SIZE:
case LB_GET_INFO:
case LB_GET_MODE:
case LB_SET_MODE:
status = bge_loop_ioctl(bgep, wq, mp, iocp);
break;
+#endif
}
@@ -1994,7 +2095,7 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
*/
#undef BGE_DBG
-#define BGE_DBG BGE_DBG_INIT /* debug flag for this code */
+#define BGE_DBG BGE_DBG_MEM /* debug flag for this code */
/*
* Allocate an area of memory and a DMA handle for accessing it
*/
@@ -2588,8 +2689,11 @@ bge_alloc_bufs(bge_t *bgep)
/*
* Enable PCI relaxed ordering only for RX/TX data buffers
*/
- if (bge_relaxed_ordering)
- dma_attr.dma_attr_flags |= DDI_DMA_RELAXED_ORDERING;
+ if (!(DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep))) {
+ if (bge_relaxed_ordering)
+ dma_attr.dma_attr_flags |= DDI_DMA_RELAXED_ORDERING;
+ }
/*
* Allocate memory & handles for RX buffers
@@ -2602,6 +2706,9 @@ bge_alloc_bufs(bge_t *bgep)
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
}
+ BGE_DEBUG(("DMA ALLOC: allocated %d chunks for Rx Buffers (rxbuffsize = %d)",
+ rxbuffsize/BGE_SPLIT,
+ rxbuffsize));
/*
* Allocate memory & handles for TX buffers
@@ -2614,8 +2721,15 @@ bge_alloc_bufs(bge_t *bgep)
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
}
+ BGE_DEBUG(("DMA ALLOC: allocated %d chunks for Tx Buffers (txbuffsize = %d)",
+ txbuffsize/BGE_SPLIT,
+ txbuffsize));
- dma_attr.dma_attr_flags &= ~DDI_DMA_RELAXED_ORDERING;
+ if (!(DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep))) {
+ /* no relaxed ordering for descriptors rings? */
+ dma_attr.dma_attr_flags &= ~DDI_DMA_RELAXED_ORDERING;
+ }
/*
* Allocate memory & handles for receive return rings
@@ -2628,14 +2742,21 @@ bge_alloc_bufs(bge_t *bgep)
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
}
+ BGE_DEBUG(("DMA ALLOC: allocated %d chunks for Rx Descs cons (rx_rings = %d, rxdescsize = %d)",
+ rxdescsize/rx_rings,
+ rx_rings,
+ rxdescsize));
/*
- * Allocate memory & handles for buffer (producer) descriptor rings
+ * Allocate memory & handles for buffer (producer) descriptor rings.
+ * Note that split=rx_rings.
*/
err = bge_alloc_dma_mem(bgep, rxbuffdescsize, &bge_desc_accattr,
DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &bgep->rx_desc[split]);
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
+ BGE_DEBUG(("DMA ALLOC: allocated 1 chunks for Rx Descs prod (rxbuffdescsize = %d)",
+ rxdescsize));
/*
* Allocate memory & handles for TX descriptor rings,
@@ -2645,65 +2766,260 @@ bge_alloc_bufs(bge_t *bgep)
DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &bgep->tx_desc);
if (err != DDI_SUCCESS)
return (DDI_FAILURE);
+ BGE_DEBUG(("DMA ALLOC: allocated 1 chunks for Tx Descs / Status Block / Stats (txdescdize = %d)",
+ txdescsize));
/*
* Now carve up each of the allocated areas ...
*/
+
+ /* rx buffers */
for (split = 0; split < BGE_SPLIT; ++split) {
area = bgep->rx_buff[split];
+
+ BGE_DEBUG(("RXB CHNK %d INIT: va=%p alen=%d off=%d pa=%llx psz=%d",
+ split,
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
+
bge_slice_chunk(&bgep->buff[BGE_STD_BUFF_RING].buf[split],
&area, BGE_STD_SLOTS_USED/BGE_SPLIT,
bgep->chipid.std_buf_size);
+
+ BGE_DEBUG(("RXB SLCE %d STND: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ split,
+ bgep->buff[BGE_STD_BUFF_RING].buf[split].mem_va,
+ bgep->buff[BGE_STD_BUFF_RING].buf[split].alength,
+ bgep->buff[BGE_STD_BUFF_RING].buf[split].offset,
+ bgep->buff[BGE_STD_BUFF_RING].buf[split].cookie.dmac_laddress,
+ bgep->buff[BGE_STD_BUFF_RING].buf[split].cookie.dmac_size,
+ BGE_STD_SLOTS_USED/BGE_SPLIT,
+ bgep->chipid.std_buf_size));
+
bge_slice_chunk(&bgep->buff[BGE_JUMBO_BUFF_RING].buf[split],
&area, bgep->chipid.jumbo_slots/BGE_SPLIT,
bgep->chipid.recv_jumbo_size);
+
+ if ((bgep->chipid.jumbo_slots / BGE_SPLIT) > 0)
+ {
+ BGE_DEBUG(("RXB SLCE %d JUMB: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ split,
+ bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].mem_va,
+ bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].alength,
+ bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].offset,
+ bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].cookie.dmac_laddress,
+ bgep->buff[BGE_JUMBO_BUFF_RING].buf[split].cookie.dmac_size,
+ bgep->chipid.jumbo_slots/BGE_SPLIT,
+ bgep->chipid.recv_jumbo_size));
+ }
+
bge_slice_chunk(&bgep->buff[BGE_MINI_BUFF_RING].buf[split],
&area, BGE_MINI_SLOTS_USED/BGE_SPLIT,
BGE_MINI_BUFF_SIZE);
+
+ if ((BGE_MINI_SLOTS_USED / BGE_SPLIT) > 0)
+ {
+ BGE_DEBUG(("RXB SLCE %d MINI: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ split,
+ bgep->buff[BGE_MINI_BUFF_RING].buf[split].mem_va,
+ bgep->buff[BGE_MINI_BUFF_RING].buf[split].alength,
+ bgep->buff[BGE_MINI_BUFF_RING].buf[split].offset,
+ bgep->buff[BGE_MINI_BUFF_RING].buf[split].cookie.dmac_laddress,
+ bgep->buff[BGE_MINI_BUFF_RING].buf[split].cookie.dmac_size,
+ BGE_MINI_SLOTS_USED/BGE_SPLIT,
+ BGE_MINI_BUFF_SIZE));
+ }
+
+ BGE_DEBUG(("RXB CHNK %d DONE: va=%p alen=%d off=%d pa=%llx psz=%d",
+ split,
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
}
+ /* tx buffers */
for (split = 0; split < BGE_SPLIT; ++split) {
area = bgep->tx_buff[split];
- for (ring = 0; ring < tx_rings; ++ring)
+
+ BGE_DEBUG(("TXB CHNK %d INIT: va=%p alen=%d off=%d pa=%llx psz=%d",
+ split,
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
+
+ for (ring = 0; ring < tx_rings; ++ring) {
bge_slice_chunk(&bgep->send[ring].buf[0][split],
&area, BGE_SEND_BUF_NUM/BGE_SPLIT,
bgep->chipid.snd_buff_size);
- for (; ring < BGE_SEND_RINGS_MAX; ++ring)
+
+ BGE_DEBUG(("TXB SLCE %d RING %d: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ split, ring,
+ bgep->send[ring].buf[0][split].mem_va,
+ bgep->send[ring].buf[0][split].alength,
+ bgep->send[ring].buf[0][split].offset,
+ bgep->send[ring].buf[0][split].cookie.dmac_laddress,
+ bgep->send[ring].buf[0][split].cookie.dmac_size,
+ BGE_SEND_BUF_NUM/BGE_SPLIT,
+ bgep->chipid.snd_buff_size));
+ }
+
+ for (; ring < BGE_SEND_RINGS_MAX; ++ring) {
bge_slice_chunk(&bgep->send[ring].buf[0][split],
&area, 0, bgep->chipid.snd_buff_size);
+ }
+
+ BGE_DEBUG(("TXB CHNK %d DONE: va=%p alen=%d off=%d pa=%llx psz=%d",
+ split,
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
}
- for (ring = 0; ring < rx_rings; ++ring)
+ for (ring = 0; ring < rx_rings; ++ring) {
bge_slice_chunk(&bgep->recv[ring].desc, &bgep->rx_desc[ring],
bgep->chipid.recv_slots, sizeof (bge_rbd_t));
- area = bgep->rx_desc[rx_rings];
- for (; ring < BGE_RECV_RINGS_MAX; ++ring)
+ BGE_DEBUG(("RXD CONS RING %d: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ ring,
+ bgep->recv[ring].desc.mem_va,
+ bgep->recv[ring].desc.alength,
+ bgep->recv[ring].desc.offset,
+ bgep->recv[ring].desc.cookie.dmac_laddress,
+ bgep->recv[ring].desc.cookie.dmac_size,
+ bgep->chipid.recv_slots,
+ sizeof(bge_rbd_t)));
+ }
+
+ /* dma alloc for rxbuffdescsize is located at bgep->rx_desc[#rings] */
+ area = bgep->rx_desc[rx_rings]; /* note rx_rings = one beyond rings */
+
+ for (; ring < BGE_RECV_RINGS_MAX; ++ring) /* skip unused rings */
bge_slice_chunk(&bgep->recv[ring].desc, &area,
0, sizeof (bge_rbd_t));
+
+ BGE_DEBUG(("RXD PROD INIT: va=%p alen=%d off=%d pa=%llx psz=%d",
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
+
bge_slice_chunk(&bgep->buff[BGE_STD_BUFF_RING].desc, &area,
BGE_STD_SLOTS_USED, sizeof (bge_rbd_t));
+ BGE_DEBUG(("RXD PROD STND: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ bgep->buff[BGE_STD_BUFF_RING].desc.mem_va,
+ bgep->buff[BGE_STD_BUFF_RING].desc.alength,
+ bgep->buff[BGE_STD_BUFF_RING].desc.offset,
+ bgep->buff[BGE_STD_BUFF_RING].desc.cookie.dmac_laddress,
+ bgep->buff[BGE_STD_BUFF_RING].desc.cookie.dmac_size,
+ BGE_STD_SLOTS_USED,
+ sizeof(bge_rbd_t)));
+
bge_slice_chunk(&bgep->buff[BGE_JUMBO_BUFF_RING].desc, &area,
bgep->chipid.jumbo_slots, sizeof (bge_rbd_t));
+ BGE_DEBUG(("RXD PROD JUMB: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ bgep->buff[BGE_JUMBO_BUFF_RING].desc.mem_va,
+ bgep->buff[BGE_JUMBO_BUFF_RING].desc.alength,
+ bgep->buff[BGE_JUMBO_BUFF_RING].desc.offset,
+ bgep->buff[BGE_JUMBO_BUFF_RING].desc.cookie.dmac_laddress,
+ bgep->buff[BGE_JUMBO_BUFF_RING].desc.cookie.dmac_size,
+ bgep->chipid.jumbo_slots,
+ sizeof(bge_rbd_t)));
+
bge_slice_chunk(&bgep->buff[BGE_MINI_BUFF_RING].desc, &area,
BGE_MINI_SLOTS_USED, sizeof (bge_rbd_t));
+ BGE_DEBUG(("RXD PROD MINI: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ bgep->buff[BGE_MINI_BUFF_RING].desc.mem_va,
+ bgep->buff[BGE_MINI_BUFF_RING].desc.alength,
+ bgep->buff[BGE_MINI_BUFF_RING].desc.offset,
+ bgep->buff[BGE_MINI_BUFF_RING].desc.cookie.dmac_laddress,
+ bgep->buff[BGE_MINI_BUFF_RING].desc.cookie.dmac_size,
+ BGE_MINI_SLOTS_USED,
+ sizeof(bge_rbd_t)));
+
+ BGE_DEBUG(("RXD PROD DONE: va=%p alen=%d off=%d pa=%llx psz=%d",
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
+
ASSERT(area.alength == 0);
area = bgep->tx_desc;
- for (ring = 0; ring < tx_rings; ++ring)
+
+ BGE_DEBUG(("TXD INIT: va=%p alen=%d off=%d pa=%llx psz=%d",
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
+
+ for (ring = 0; ring < tx_rings; ++ring) {
bge_slice_chunk(&bgep->send[ring].desc, &area,
BGE_SEND_SLOTS_USED, sizeof (bge_sbd_t));
- for (; ring < BGE_SEND_RINGS_MAX; ++ring)
+
+ BGE_DEBUG(("TXD RING %d: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ ring,
+ bgep->send[ring].desc.mem_va,
+ bgep->send[ring].desc.alength,
+ bgep->send[ring].desc.offset,
+ bgep->send[ring].desc.cookie.dmac_laddress,
+ bgep->send[ring].desc.cookie.dmac_size,
+ BGE_SEND_SLOTS_USED,
+ sizeof(bge_sbd_t)));
+ }
+
+ for (; ring < BGE_SEND_RINGS_MAX; ++ring) /* skip unused rings */
bge_slice_chunk(&bgep->send[ring].desc, &area,
0, sizeof (bge_sbd_t));
+
bge_slice_chunk(&bgep->statistics, &area, 1, sizeof (bge_statistics_t));
+ BGE_DEBUG(("TXD STATISTICS: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ bgep->statistics.mem_va,
+ bgep->statistics.alength,
+ bgep->statistics.offset,
+ bgep->statistics.cookie.dmac_laddress,
+ bgep->statistics.cookie.dmac_size,
+ 1,
+ sizeof(bge_statistics_t)));
+
bge_slice_chunk(&bgep->status_block, &area, 1, sizeof (bge_status_t));
+ BGE_DEBUG(("TXD STATUS BLOCK: va=%p alen=%d off=%d pa=%llx psz=%d (nslots=%d slotlen=%d)",
+ bgep->status_block.mem_va,
+ bgep->status_block.alength,
+ bgep->status_block.offset,
+ bgep->status_block.cookie.dmac_laddress,
+ bgep->status_block.cookie.dmac_size,
+ 1,
+ sizeof(bge_status_t)));
+
+ BGE_DEBUG(("TXD DONE: va=%p alen=%d off=%d pa=%llx psz=%d",
+ area.mem_va,
+ area.alength,
+ area.offset,
+ area.cookie.dmac_laddress,
+ area.cookie.dmac_size));
+
ASSERT(area.alength == BGE_STATUS_PADDING);
+
DMA_ZERO(bgep->status_block);
return (DDI_SUCCESS);
}
+#undef BGE_DBG
+#define BGE_DBG BGE_DBG_INIT /* debug flag for this code */
+
/*
* This routine frees the transmit and receive buffers and descriptors.
* Make sure the chip is stopped before calling it!
@@ -2840,7 +3156,6 @@ bge_find_mac_address(bge_t *bgep, chip_id_t *cidp)
cidp->vendor_addr.set ? "" : "not "));
}
-
/*ARGSUSED*/
int
bge_check_acc_handle(bge_t *bgep, ddi_acc_handle_t handle)
@@ -2961,6 +3276,7 @@ bge_unattach(bge_t *bgep)
ddi_periodic_delete(bgep->periodic_id);
bgep->periodic_id = NULL;
}
+
if (bgep->progress & PROGRESS_KSTATS)
bge_fini_kstats(bgep);
if (bgep->progress & PROGRESS_PHY)
@@ -3008,8 +3324,11 @@ bge_unattach(bge_t *bgep)
ddi_remove_softintr(bgep->drain_id);
if (bgep->progress & PROGRESS_BUFS)
bge_free_bufs(bgep);
- if (bgep->progress & PROGRESS_REGS)
+ if (bgep->progress & PROGRESS_REGS) {
ddi_regs_map_free(&bgep->io_handle);
+ if (bgep->ape_enabled)
+ ddi_regs_map_free(&bgep->ape_handle);
+ }
if (bgep->progress & PROGRESS_CFG)
pci_config_teardown(&bgep->cfg_handle);
@@ -3093,6 +3412,209 @@ bge_resume(dev_info_t *devinfo)
return (DDI_SUCCESS);
}
+static int
+bge_fw_img_is_valid(bge_t *bgep, uint32_t offset)
+{
+ uint32_t val;
+
+ if (bge_nvmem_read32(bgep, offset, &val) ||
+ (val & 0xfc000000) != 0x0c000000 ||
+ bge_nvmem_read32(bgep, offset + 4, &val) ||
+ val != 0)
+ return (0);
+
+ return (1);
+}
+
+static void
+bge_read_mgmtfw_ver(bge_t *bgep)
+{
+ uint32_t val;
+ uint32_t offset;
+ uint32_t start;
+ int i, vlen;
+
+ for (offset = NVM_DIR_START;
+ offset < NVM_DIR_END;
+ offset += NVM_DIRENT_SIZE) {
+ if (bge_nvmem_read32(bgep, offset, &val))
+ return;
+
+ if ((val >> NVM_DIRTYPE_SHIFT) == NVM_DIRTYPE_ASFINI)
+ break;
+ }
+
+ if (offset == NVM_DIR_END)
+ return;
+
+ if (bge_nvmem_read32(bgep, offset - 4, &start))
+ return;
+
+ if (bge_nvmem_read32(bgep, offset + 4, &offset) ||
+ !bge_fw_img_is_valid(bgep, offset) ||
+ bge_nvmem_read32(bgep, offset + 8, &val))
+ return;
+
+ offset += val - start;
+
+ vlen = strlen(bgep->fw_version);
+
+ bgep->fw_version[vlen++] = ',';
+ bgep->fw_version[vlen++] = ' ';
+
+ for (i = 0; i < 4; i++) {
+ uint32_t v;
+
+ if (bge_nvmem_read32(bgep, offset, &v))
+ return;
+
+ v = BE_32(v);
+
+ offset += sizeof(v);
+
+ if (vlen > BGE_FW_VER_SIZE - sizeof(v)) {
+ memcpy(&bgep->fw_version[vlen], &v, BGE_FW_VER_SIZE - vlen);
+ break;
+ }
+
+ memcpy(&bgep->fw_version[vlen], &v, sizeof(v));
+ vlen += sizeof(v);
+ }
+}
+
+static void
+bge_read_dash_ver(bge_t *bgep)
+{
+ int vlen;
+ uint32_t apedata;
+ char *fwtype;
+
+ if (!bgep->ape_enabled || !bgep->asf_enabled)
+ return;
+
+ apedata = bge_ape_get32(bgep, BGE_APE_SEG_SIG);
+ if (apedata != APE_SEG_SIG_MAGIC)
+ return;
+
+ apedata = bge_ape_get32(bgep, BGE_APE_FW_STATUS);
+ if (!(apedata & APE_FW_STATUS_READY))
+ return;
+
+ apedata = bge_ape_get32(bgep, BGE_APE_FW_VERSION);
+
+ if (bge_ape_get32(bgep, BGE_APE_FW_FEATURES) &
+ BGE_APE_FW_FEATURE_NCSI) {
+ bgep->ape_has_ncsi = B_TRUE;
+ fwtype = "NCSI";
+ } else if ((bgep->chipid.device == DEVICE_ID_5725) ||
+ (bgep->chipid.device == DEVICE_ID_5727)) {
+ fwtype = "SMASH";
+ } else {
+ fwtype = "DASH";
+ }
+
+ vlen = strlen(bgep->fw_version);
+
+ snprintf(&bgep->fw_version[vlen], BGE_FW_VER_SIZE - vlen,
+ " %s v%d.%d.%d.%d", fwtype,
+ (apedata & APE_FW_VERSION_MAJMSK) >> APE_FW_VERSION_MAJSFT,
+ (apedata & APE_FW_VERSION_MINMSK) >> APE_FW_VERSION_MINSFT,
+ (apedata & APE_FW_VERSION_REVMSK) >> APE_FW_VERSION_REVSFT,
+ (apedata & APE_FW_VERSION_BLDMSK));
+}
+
+static void
+bge_read_bc_ver(bge_t *bgep)
+{
+ uint32_t val;
+ uint32_t offset;
+ uint32_t start;
+ uint32_t ver_offset;
+ int i, dst_off;
+ uint32_t major;
+ uint32_t minor;
+ boolean_t newver = B_FALSE;
+
+ if (bge_nvmem_read32(bgep, 0xc, &offset) ||
+ bge_nvmem_read32(bgep, 0x4, &start))
+ return;
+
+ if (bge_nvmem_read32(bgep, offset, &val))
+ return;
+
+ if ((val & 0xfc000000) == 0x0c000000) {
+ if (bge_nvmem_read32(bgep, offset + 4, &val))
+ return;
+
+ if (val == 0)
+ newver = B_TRUE;
+ }
+
+ dst_off = strlen(bgep->fw_version);
+
+ if (newver) {
+ if (((BGE_FW_VER_SIZE - dst_off) < 16) ||
+ bge_nvmem_read32(bgep, offset + 8, &ver_offset))
+ return;
+
+ offset = offset + ver_offset - start;
+ for (i = 0; i < 16; i += 4) {
+ if (bge_nvmem_read32(bgep, offset + i, &val))
+ return;
+ val = BE_32(val);
+ memcpy(bgep->fw_version + dst_off + i, &val,
+ sizeof(val));
+ }
+ } else {
+ if (bge_nvmem_read32(bgep, NVM_PTREV_BCVER, &ver_offset))
+ return;
+
+ major = (ver_offset & NVM_BCVER_MAJMSK) >> NVM_BCVER_MAJSFT;
+ minor = ver_offset & NVM_BCVER_MINMSK;
+ snprintf(&bgep->fw_version[dst_off], BGE_FW_VER_SIZE - dst_off,
+ "v%d.%02d", major, minor);
+ }
+}
+
+static void
+bge_read_fw_ver(bge_t *bgep)
+{
+ uint32_t val;
+ uint32_t magic;
+
+ *bgep->fw_version = 0;
+
+ if ((bgep->chipid.nvtype == BGE_NVTYPE_NONE) ||
+ (bgep->chipid.nvtype == BGE_NVTYPE_UNKNOWN)) {
+ snprintf(bgep->fw_version, sizeof(bgep->fw_version), "sb");
+ return;
+ }
+
+ mutex_enter(bgep->genlock);
+
+ bge_nvmem_read32(bgep, 0, &magic);
+
+ if (magic == EEPROM_MAGIC) {
+ bge_read_bc_ver(bgep);
+ } else {
+ /* ignore other configs for now */
+ mutex_exit(bgep->genlock);
+ return;
+ }
+
+ if (bgep->ape_enabled) {
+ if (bgep->asf_enabled) {
+ bge_read_dash_ver(bgep);
+ }
+ } else if (bgep->asf_enabled) {
+ bge_read_mgmtfw_ver(bgep);
+ }
+
+ mutex_exit(bgep->genlock);
+
+ bgep->fw_version[BGE_FW_VER_SIZE - 1] = 0; /* safety */
+}
+
/*
* attach(9E) -- Attach a device to the system
*
@@ -3108,6 +3630,10 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
int instance;
int err;
int intr_types;
+ int *props = NULL;
+ uint_t numProps;
+ uint32_t regval;
+ uint32_t pci_state_reg;
#ifdef BGE_IPMI_ASF
uint32_t mhcrValue;
#ifdef __sparc
@@ -3209,15 +3735,20 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
* has been set in PCI_CONF_COMM already, we need to write the
* byte-swapped value to it. So we just write zero first for simplicity.
*/
- if (DEVICE_5717_SERIES_CHIPSETS(bgep))
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep))
pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, 0);
+#else
+ mhcrValue = MHCR_ENABLE_INDIRECT_ACCESS |
+ MHCR_ENABLE_TAGGED_STATUS_MODE |
+ MHCR_MASK_INTERRUPT_MODE |
+ MHCR_MASK_PCI_INT_OUTPUT |
+ MHCR_CLEAR_INTERRUPT_INTA;
+#endif
pci_config_put32(bgep->cfg_handle, PCI_CONF_BGE_MHCR, mhcrValue);
bge_ind_put32(bgep, MEMORY_ARBITER_MODE_REG,
bge_ind_get32(bgep, MEMORY_ARBITER_MODE_REG) |
MEMORY_ARBITER_ENABLE);
-#else
- mhcrValue = pci_config_get32(bgep->cfg_handle, PCI_CONF_BGE_MHCR);
-#endif
if (mhcrValue & MHCR_ENABLE_ENDIAN_WORD_SWAP) {
bgep->asf_wordswapped = B_TRUE;
} else {
@@ -3231,7 +3762,7 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
}
bgep->progress |= PROGRESS_CFG;
cidp = &bgep->chipid;
- bzero(cidp, sizeof (*cidp));
+ bzero(cidp, sizeof(*cidp));
bge_chip_cfg_init(bgep, cidp, B_FALSE);
if (bge_check_acc_handle(bgep, bgep->cfg_handle) != DDI_FM_OK) {
ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_LOST);
@@ -3264,6 +3795,8 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
DDI_PROP_DONTPASS, rxrings_propname, cidp->rx_rings);
cidp->tx_rings = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
DDI_PROP_DONTPASS, txrings_propname, cidp->tx_rings);
+ cidp->eee = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
+ DDI_PROP_DONTPASS, eee_propname, cidp->eee);
cidp->default_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo,
DDI_PROP_DONTPASS, default_mtu, BGE_DEFAULT_MTU);
@@ -3282,6 +3815,36 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
goto attach_fail;
}
bgep->io_regs = regs;
+
+ bgep->ape_enabled = B_FALSE;
+ bgep->ape_regs = NULL;
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
+ err = ddi_regs_map_setup(devinfo, BGE_PCI_APEREGS_RNUMBER,
+ &regs, 0, 0, &bge_reg_accattr, &bgep->ape_handle);
+ if (err != DDI_SUCCESS) {
+ ddi_regs_map_free(&bgep->io_handle);
+ bge_problem(bgep, "ddi_regs_map_setup() failed");
+ goto attach_fail;
+ }
+ bgep->ape_regs = regs;
+ bgep->ape_enabled = B_TRUE;
+
+ /*
+ * Allow reads and writes to the
+ * APE register and memory space.
+ */
+
+ pci_state_reg = pci_config_get32(bgep->cfg_handle,
+ PCI_CONF_BGE_PCISTATE);
+ pci_state_reg |= PCISTATE_ALLOW_APE_CTLSPC_WR |
+ PCISTATE_ALLOW_APE_SHMEM_WR | PCISTATE_ALLOW_APE_PSPACE_WR;
+ pci_config_put32(bgep->cfg_handle,
+ PCI_CONF_BGE_PCISTATE, pci_state_reg);
+
+ bge_ape_lock_init(bgep);
+ }
+
bgep->progress |= PROGRESS_REGS;
/*
@@ -3293,6 +3856,29 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
goto attach_fail;
}
+ err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, bgep->devinfo,
+ 0, "reg", &props, &numProps);
+ if ((err == DDI_PROP_SUCCESS) && (numProps > 0)) {
+ bgep->pci_bus = PCI_REG_BUS_G(props[0]);
+ bgep->pci_dev = PCI_REG_DEV_G(props[0]);
+ bgep->pci_func = PCI_REG_FUNC_G(props[0]);
+ ddi_prop_free(props);
+ }
+
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) {
+ regval = bge_reg_get32(bgep, CPMU_STATUS_REG);
+ if ((bgep->chipid.device == DEVICE_ID_5719) ||
+ (bgep->chipid.device == DEVICE_ID_5720)) {
+ bgep->pci_func =
+ ((regval & CPMU_STATUS_FUNC_NUM_5719) >>
+ CPMU_STATUS_FUNC_NUM_5719_SHIFT);
+ } else {
+ bgep->pci_func = ((regval & CPMU_STATUS_FUNC_NUM) >>
+ CPMU_STATUS_FUNC_NUM_SHIFT);
+ }
+ }
+
err = bge_alloc_bufs(bgep);
if (err != DDI_SUCCESS) {
bge_problem(bgep, "DMA buffer allocation failed");
@@ -3477,6 +4063,16 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
* Determine whether to override the chip's own MAC address
*/
bge_find_mac_address(bgep, cidp);
+ {
+ int slot;
+ for (slot = 0; slot < MAC_ADDRESS_REGS_MAX; slot++) {
+ ethaddr_copy(cidp->vendor_addr.addr,
+ bgep->curr_addr[slot].addr);
+ bgep->curr_addr[slot].set = 1;
+ }
+ }
+
+ bge_read_fw_ver(bgep);
bgep->unicst_addr_total = MAC_ADDRESS_REGS_MAX;
bgep->unicst_addr_avail = MAC_ADDRESS_REGS_MAX;
@@ -3492,7 +4088,10 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
macp->m_max_sdu = cidp->ethmax_size - sizeof (struct ether_header);
macp->m_margin = VLAN_TAGSZ;
macp->m_priv_props = bge_priv_prop;
- macp->m_v12n = MAC_VIRT_LEVEL1;
+
+#if defined(ILLUMOS)
+ bge_m_unicst(bgep, cidp->vendor_addr.addr);
+#endif
/*
* Finally, we're ready to register ourselves with the MAC layer
diff --git a/usr/src/uts/common/io/bge/bge_mii.c b/usr/src/uts/common/io/bge/bge_mii.c
index f24b6a3f16..68823b3cba 100644
--- a/usr/src/uts/common/io/bge/bge_mii.c
+++ b/usr/src/uts/common/io/bge/bge_mii.c
@@ -20,7 +20,13 @@
*/
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010-2013, by Broadcom, Inc.
+ * All Rights Reserved.
+ */
+
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates.
+ * All rights reserved.
*/
#include "bge_impl.h"
@@ -143,6 +149,23 @@ bge_phydump(bge_t *bgep, uint16_t mii_status, uint16_t aux)
#endif /* BGE_DEBUGGING */
+static void
+bge_phy_toggle_auxctl_smdsp(bge_t *bgep,
+ boolean_t enable)
+{
+ uint16_t val;
+
+ val = bge_mii_get16(bgep, MII_AUX_CONTROL);
+
+ if (enable) {
+ val |= MII_AUX_CTRL_SMDSP_ENA;
+ } else {
+ val &= ~MII_AUX_CTRL_SMDSP_ENA;
+ }
+
+ bge_mii_put16(bgep, MII_AUX_CONTROL, (val | MII_AUX_CTRL_TX_6DB));
+}
+
/*
* Basic low-level function to probe for a PHY
*
@@ -153,6 +176,7 @@ bge_phy_probe(bge_t *bgep)
{
uint16_t miicfg;
uint32_t nicsig, niccfg;
+ int i;
BGE_TRACE(("bge_phy_probe($%p)", (void *)bgep));
@@ -174,8 +198,10 @@ bge_phy_probe(bge_t *bgep)
* order to clear any sticky bits (but they should
* have been cleared by the RESET, I think).
*/
- miicfg = bge_mii_get16(bgep, MII_STATUS);
- miicfg = bge_mii_get16(bgep, MII_STATUS);
+ for (i = 0; i < 100; i++) {
+ drv_usecwait(40);
+ miicfg = bge_mii_get16(bgep, MII_STATUS);
+ }
BGE_DEBUG(("bge_phy_probe: status 0x%x", miicfg));
/*
@@ -190,7 +216,7 @@ bge_phy_probe(bge_t *bgep)
case 0xffff:
return (B_FALSE);
- default :
+ default:
return (B_TRUE);
}
}
@@ -527,7 +553,7 @@ bge_phy_bit_err_fix(bge_t *bgep)
}
/*
- * End of Broadcom-derived workaround code *
+ * End of Broadcom-derived workaround code
*/
static int
@@ -536,12 +562,13 @@ bge_restart_copper(bge_t *bgep, boolean_t powerdown)
uint16_t phy_status;
boolean_t reset_ok;
uint16_t extctrl, auxctrl;
+ int i;
BGE_TRACE(("bge_restart_copper($%p, %d)", (void *)bgep, powerdown));
ASSERT(mutex_owned(bgep->genlock));
- switch (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev)) {
+ switch (MHCR_CHIP_ASIC_REV(bgep)) {
default:
/*
* Shouldn't happen; it means we don't recognise this chip.
@@ -559,7 +586,7 @@ bge_restart_copper(bge_t *bgep, boolean_t powerdown)
case MHCR_CHIP_ASIC_REV_5906:
case MHCR_CHIP_ASIC_REV_5700:
case MHCR_CHIP_ASIC_REV_5701:
- case MHCR_CHIP_ASIC_REV_5723:
+ case MHCR_CHIP_ASIC_REV_5723: /* 5717 and 5725 series as well */
case MHCR_CHIP_ASIC_REV_5721_5751:
/*
* Just a plain reset; the "check" code breaks these chips
@@ -588,7 +615,7 @@ bge_restart_copper(bge_t *bgep, boolean_t powerdown)
break;
}
- switch (MHCR_CHIP_ASIC_REV(bgep->chipid.asic_rev)) {
+ switch (MHCR_CHIP_ASIC_REV(bgep)) {
case MHCR_CHIP_ASIC_REV_5705:
case MHCR_CHIP_ASIC_REV_5721_5751:
bge_phy_bit_err_fix(bgep);
@@ -623,8 +650,10 @@ bge_restart_copper(bge_t *bgep, boolean_t powerdown)
* order to clear any sticky bits (but they should
* have been cleared by the RESET, I think).
*/
- phy_status = bge_mii_get16(bgep, MII_STATUS);
- phy_status = bge_mii_get16(bgep, MII_STATUS);
+ for (i = 0; i < 100; i++) {
+ drv_usecwait(40);
+ phy_status = bge_mii_get16(bgep, MII_STATUS);
+ }
BGE_DEBUG(("bge_restart_copper: status 0x%x", phy_status));
/*
@@ -635,6 +664,232 @@ bge_restart_copper(bge_t *bgep, boolean_t powerdown)
return (DDI_SUCCESS);
}
+boolean_t
+bge_eee_cap(bge_t * bgep)
+{
+ if (!(DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep))) {
+ /* EEE is not supported on this chip */
+ BGE_DEBUG(("bge_eee: eee not supported (device 0x%x)",
+ bgep->chipid.device));
+ return (B_FALSE);
+ }
+
+ switch (CHIP_ASIC_REV_PROD_ID(bgep)) {
+ case CHIP_ASIC_REV_5717_B0: /* = CHIP_ASIC_REV_5718_B0 */
+ case CHIP_ASIC_REV_5717_C0:
+ /* case CHIP_ASIC_REV_5718_B0: */
+ case CHIP_ASIC_REV_5719_A0:
+ case CHIP_ASIC_REV_5719_A1:
+ case CHIP_ASIC_REV_5720_A0:
+ case CHIP_ASIC_REV_5725_A0:
+ case CHIP_ASIC_REV_5727_B0:
+ return (B_TRUE);
+
+ default:
+ /* EEE is not supported on this asic rev */
+ BGE_DEBUG(("bge_eee: eee not supported (asic rev 0x%08x)",
+ bgep->chipid.asic_rev));
+ return (B_FALSE);
+ }
+}
+
+void
+bge_eee_init(bge_t * bgep)
+{
+ uint32_t val;
+
+ BGE_TRACE(("bge_eee_init($%p)", (void *)bgep));
+
+ ASSERT(mutex_owned(bgep->genlock));
+
+ if (!bge_eee_cap(bgep)) {
+ return;
+ }
+
+ /* Enable MAC control of LPI */
+
+ val = (EEE_LINK_IDLE_PCIE_NL0 | EEE_LINK_IDLE_UART_IDL);
+ if (DEVICE_5725_SERIES_CHIPSETS(bgep))
+ val |= EEE_LINK_IDLE_APE_TX_MT;
+ bge_reg_put32(bgep, EEE_LINK_IDLE_CONTROL_REG, val);
+
+ bge_reg_put32(bgep, EEE_CONTROL_REG, EEE_CONTROL_EXIT_20_1_US);
+
+ val = EEE_MODE_ERLY_L1_XIT_DET | EEE_MODE_LPI_IN_TX |
+ EEE_MODE_LPI_IN_RX | EEE_MODE_EEE_ENABLE;
+
+ if (bgep->chipid.device != DEVICE_ID_5717)
+ val |= EEE_MODE_SND_IDX_DET_EN;
+
+ //val |= EEE_MODE_APE_TX_DET_EN;
+
+ if (!bgep->chipid.eee) {
+ val = 0;
+ }
+
+ bge_reg_put32(bgep, EEE_MODE_REG, val);
+
+ /* Set EEE timer debounce values */
+
+ bge_reg_put32(bgep, EEE_DEBOUNCE_T1_CONTROL_REG,
+ EEE_DEBOUNCE_T1_PCIEXIT_2047US | EEE_DEBOUNCE_T1_LNKIDLE_2047US);
+
+ bge_reg_put32(bgep, EEE_DEBOUNCE_T2_CONTROL_REG,
+ EEE_DEBOUNCE_T2_APE_TX_2047US | EEE_DEBOUNCE_T2_TXIDXEQ_2047US);
+}
+
+void
+bge_eee_autoneg(bge_t * bgep, boolean_t adv_100fdx, boolean_t adv_1000fdx)
+{
+ uint32_t val;
+ uint16_t mii_val;
+
+ BGE_TRACE(("bge_eee_autoneg($%p)", (void *)bgep));
+
+ ASSERT(mutex_owned(bgep->genlock));
+
+ if (!bge_eee_cap(bgep)) {
+ return;
+ }
+
+ /* Disable LPI Requests */
+ val = bge_reg_get32(bgep, EEE_MODE_REG);
+ val &= ~EEE_MODE_LPI_ENABLE;
+ bge_reg_put32(bgep, EEE_MODE_REG, val);
+
+ bge_phy_toggle_auxctl_smdsp(bgep, B_TRUE);
+
+ mii_val = 0;
+
+ if (bgep->chipid.eee) {
+ if (adv_100fdx) {
+ mii_val |= EEE_CL45_D7_RESULT_STAT_LP_100TX;
+ }
+ if (adv_1000fdx) {
+ mii_val |= EEE_CL45_D7_RESULT_STAT_LP_1000T;
+ }
+ }
+
+ /* Enable EEE advertisement for the specified mode(s)... */
+ bge_mii_put16(bgep, MII_MMD_CTRL, MDIO_MMD_AN);
+ bge_mii_put16(bgep, MII_MMD_ADDRESS_DATA, MDIO_AN_EEE_ADV);
+ bge_mii_put16(bgep, MII_MMD_CTRL,
+ MII_MMD_CTRL_DATA_NOINC | MDIO_MMD_AN);
+ bge_mii_put16(bgep, MII_MMD_ADDRESS_DATA, mii_val);
+
+ /* Setup PHY DSP for EEE */
+ switch (bgep->chipid.device) {
+ case DEVICE_ID_5717:
+ case DEVICE_ID_5718:
+ case DEVICE_ID_5719:
+ /* If we advertised any EEE advertisements above... */
+ if (mii_val) {
+ mii_val = (MII_DSP_TAP26_ALNOKO |
+ MII_DSP_TAP26_RMRXSTO |
+ MII_DSP_TAP26_OPCSINPT);
+ }
+ bge_phydsp_write(bgep, MII_DSP_TAP26, mii_val);
+ /* fall through */
+ case DEVICE_ID_5720:
+ case DEVICE_ID_5725:
+ case DEVICE_ID_5727:
+ mii_val = bge_phydsp_read(bgep, MII_DSP_CH34TP2);
+ bge_phydsp_write(bgep, MII_DSP_CH34TP2,
+ (mii_val | MII_DSP_CH34TP2_HIBW01));
+ }
+
+ bge_phy_toggle_auxctl_smdsp(bgep, B_FALSE);
+}
+
+void
+bge_eee_adjust(bge_t * bgep)
+{
+ uint32_t val;
+ uint16_t mii_val;
+
+ BGE_TRACE(("bge_eee_adjust($%p, %d)", (void *)bgep));
+
+ ASSERT(mutex_owned(bgep->genlock));
+
+ if (!bge_eee_cap(bgep)) {
+ return;
+ }
+
+ bgep->eee_lpi_wait = 0;
+
+ /* Check for PHY link status */
+ if (bgep->param_link_up) {
+ BGE_DEBUG(("bge_eee_adjust: link status up"));
+
+ /*
+ * XXX if duplex full and speed is 1000 or 100 then do the
+ * following...
+ */
+
+ if (bgep->param_link_speed == 1000) {
+ BGE_DEBUG(("bge_eee_adjust: eee timing for 1000Mb"));
+ bge_reg_put32(bgep, EEE_CONTROL_REG,
+ EEE_CONTROL_EXIT_16_5_US);
+ } else if (bgep->param_link_speed == 100) {
+ BGE_DEBUG(("bge_eee_adjust: eee timing for 100Mb"));
+ bge_reg_put32(bgep, EEE_CONTROL_REG,
+ EEE_CONTROL_EXIT_36_US);
+ }
+
+ /* Read PHY's EEE negotiation status */
+ bge_mii_put16(bgep, MII_MMD_CTRL, MDIO_MMD_AN);
+ bge_mii_put16(bgep, MII_MMD_ADDRESS_DATA,
+ EEE_CL45_D7_RESULT_STAT);
+ bge_mii_put16(bgep, MII_MMD_CTRL,
+ MII_MMD_CTRL_DATA_NOINC | MDIO_MMD_AN);
+ mii_val = bge_mii_get16(bgep, MII_MMD_ADDRESS_DATA);
+
+ /* Enable EEE LPI request if EEE negotiated */
+ if ((mii_val == EEE_CL45_D7_RESULT_STAT_LP_1000T) ||
+ (mii_val == EEE_CL45_D7_RESULT_STAT_LP_100TX)) {
+ BGE_DEBUG(("bge_eee_adjust: eee negotiaton success, lpi scheduled"));
+ bgep->eee_lpi_wait = 2;
+ } else {
+ BGE_DEBUG(("bge_eee_adjust: eee negotiation failed"));
+ }
+ } else {
+ BGE_DEBUG(("bge_eee_adjust: link status down"));
+ }
+
+ if (!bgep->eee_lpi_wait) {
+ if (bgep->param_link_up) {
+ bge_phy_toggle_auxctl_smdsp(bgep, B_TRUE);
+ bge_phydsp_write(bgep, MII_DSP_TAP26, 0);
+ bge_phy_toggle_auxctl_smdsp(bgep, B_FALSE);
+ }
+
+ /* Disable LPI requests */
+ val = bge_reg_get32(bgep, EEE_MODE_REG);
+ val &= ~EEE_MODE_LPI_ENABLE;
+ bge_reg_put32(bgep, EEE_MODE_REG, val);
+ }
+}
+
+void
+bge_eee_enable(bge_t * bgep)
+{
+ uint32_t val;
+
+ /* XXX check for EEE for 5717 family... */
+
+ if (bgep->param_link_speed == 1000) {
+ bge_phy_toggle_auxctl_smdsp(bgep, B_TRUE);
+ bge_phydsp_write(bgep, MII_DSP_TAP26,
+ MII_DSP_TAP26_ALNOKO | MII_DSP_TAP26_RMRXSTO);
+ bge_phy_toggle_auxctl_smdsp(bgep, B_FALSE);
+ }
+
+ val = bge_reg_get32(bgep, EEE_MODE_REG);
+ val |= EEE_MODE_LPI_ENABLE;
+ bge_reg_put32(bgep, EEE_MODE_REG, val);
+}
+
/*
* Synchronise the (copper) PHY's speed/duplex/autonegotiation capabilities
* and advertisements with the required settings as specified by the various
@@ -866,6 +1121,10 @@ bge_update_copper(bge_t *bgep)
break;
}
#endif /* BGE_COPPER_WIRESPEED */
+
+ /* enable EEE on those chips that support it */
+ bge_eee_autoneg(bgep, adv_100fdx, adv_1000fdx);
+
return (DDI_SUCCESS);
}
@@ -877,13 +1136,17 @@ bge_check_copper(bge_t *bgep, boolean_t recheck)
uint16_t aux;
uint_t mode;
boolean_t linkup;
+ int i;
/*
* Step 10: read the status from the PHY (which is self-clearing
* on read!); also read & clear the main (Ethernet) MAC status
* (the relevant bits of this are write-one-to-clear).
*/
- mii_status = bge_mii_get16(bgep, MII_STATUS);
+ for (i = 0; i < 100; i++) {
+ drv_usecwait(40);
+ mii_status = bge_mii_get16(bgep, MII_STATUS);
+ }
emac_status = bge_reg_get32(bgep, ETHERNET_MAC_STATUS_REG);
bge_reg_put32(bgep, ETHERNET_MAC_STATUS_REG, emac_status);
@@ -897,14 +1160,19 @@ bge_check_copper(bge_t *bgep, boolean_t recheck)
* we not forcing a recheck (i.e. the link state was already
* known), there's nothing to do.
*/
- if (mii_status == bgep->phy_gen_status && !recheck)
+ if (mii_status == bgep->phy_gen_status && !recheck) {
+ BGE_DEBUG(("bge_check_copper: no link change"));
return (B_FALSE);
+ }
do {
/*
* Step 11: read AUX STATUS register to find speed/duplex
*/
- aux = bge_mii_get16(bgep, MII_AUX_STATUS);
+ for (i = 0; i < 2000; i++) {
+ drv_usecwait(10);
+ aux = bge_mii_get16(bgep, MII_AUX_STATUS);
+ }
BGE_CDB(bge_phydump, (bgep, mii_status, aux));
/*
@@ -935,7 +1203,12 @@ bge_check_copper(bge_t *bgep, boolean_t recheck)
*/
bgep->phy_aux_status = aux;
bgep->phy_gen_status = mii_status;
- mii_status = bge_mii_get16(bgep, MII_STATUS);
+
+ for (i = 0; i < 100; i++)
+ {
+ drv_usecwait(40);
+ mii_status = bge_mii_get16(bgep, MII_STATUS);
+ }
} while (mii_status != bgep->phy_gen_status);
/*
@@ -1014,10 +1287,12 @@ bge_check_copper(bge_t *bgep, boolean_t recheck)
bgep->param_link_duplex = bge_copper_link_duplex[mode];
}
- BGE_DEBUG(("bge_check_copper: link now %s speed %d duplex %d",
- UPORDOWN(bgep->param_link_up),
- bgep->param_link_speed,
- bgep->param_link_duplex));
+ bge_eee_adjust(bgep);
+
+ bge_log(bgep, "bge_check_copper: link now %s speed %d duplex %d",
+ UPORDOWN(bgep->param_link_up),
+ bgep->param_link_speed,
+ bgep->param_link_duplex);
return (B_TRUE);
}
@@ -1054,13 +1329,13 @@ bge_restart_serdes(bge_t *bgep, boolean_t powerdown)
* appropriately for the SerDes interface ...
*/
macmode = bge_reg_get32(bgep, ETHERNET_MAC_MODE_REG);
- if (DEVICE_5714_SERIES_CHIPSETS(bgep)) {
- macmode |= ETHERNET_MODE_LINK_POLARITY;
- macmode &= ~ETHERNET_MODE_PORTMODE_MASK;
+ macmode &= ~ETHERNET_MODE_LINK_POLARITY;
+ macmode &= ~ETHERNET_MODE_PORTMODE_MASK;
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5714_SERIES_CHIPSETS(bgep)) {
macmode |= ETHERNET_MODE_PORTMODE_GMII;
} else {
- macmode &= ~ETHERNET_MODE_LINK_POLARITY;
- macmode &= ~ETHERNET_MODE_PORTMODE_MASK;
macmode |= ETHERNET_MODE_PORTMODE_TBI;
}
bge_reg_put32(bgep, ETHERNET_MAC_MODE_REG, macmode);
@@ -1288,21 +1563,34 @@ bge_check_serdes(bge_t *bgep, boolean_t recheck)
* to BCM5705, BCM5788, BCM5721, BCM5751, BCM5752,
* BCM5714, and BCM5715 devices.
*/
- if (DEVICE_5714_SERIES_CHIPSETS(bgep)) {
+ if (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5714_SERIES_CHIPSETS(bgep)) {
tx_status = bge_reg_get32(bgep,
TRANSMIT_MAC_STATUS_REG);
linkup = BIS(tx_status, TRANSMIT_STATUS_LINK_UP);
emac_status = bge_reg_get32(bgep,
ETHERNET_MAC_STATUS_REG);
bgep->serdes_status = emac_status;
+ /* clear write-one-to-clear bits in MAC status */
+ if ((emac_status & ETHERNET_STATUS_MI_COMPLETE) &&
+ (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep))) {
+ emac_status |= ETHERNET_STATUS_SYNC_CHANGED |
+ ETHERNET_STATUS_CFG_CHANGED;
+ }
+ bge_reg_put32(bgep,
+ ETHERNET_MAC_STATUS_REG, emac_status);
+ /*
+ * If the link status has not changed then then
+ * break. If it has loop around and recheck again.
+ * Keep looping until the link status has not
+ * changed.
+ */
if ((linkup && linkup_old) ||
(!linkup && !linkup_old)) {
- emac_status &= ~ETHERNET_STATUS_LINK_CHANGED;
- emac_status &= ~ETHERNET_STATUS_RECEIVING_CFG;
break;
}
- emac_status |= ETHERNET_STATUS_LINK_CHANGED;
- emac_status |= ETHERNET_STATUS_RECEIVING_CFG;
if (linkup)
linkup_old = B_TRUE;
else
@@ -1467,10 +1755,10 @@ bge_check_serdes(bge_t *bgep, boolean_t recheck)
}
bgep->link_state = LINK_STATE_UNKNOWN;
- BGE_DEBUG(("bge_check_serdes: link now %s speed %d duplex %d",
- UPORDOWN(bgep->param_link_up),
- bgep->param_link_speed,
- bgep->param_link_duplex));
+ bge_log(bgep, "bge_check_serdes: link now %s speed %d duplex %d",
+ UPORDOWN(bgep->param_link_up),
+ bgep->param_link_speed,
+ bgep->param_link_duplex);
return (B_TRUE);
}
@@ -1495,6 +1783,8 @@ static const phys_ops_t serdes_ops = {
int
bge_phys_init(bge_t *bgep)
{
+ uint32_t regval;
+
BGE_TRACE(("bge_phys_init($%p)", (void *)bgep));
mutex_enter(bgep->genlock);
@@ -1506,13 +1796,12 @@ bge_phys_init(bge_t *bgep)
* BCM800x PHY.
*/
bgep->phy_mii_addr = 1;
+
if (DEVICE_5717_SERIES_CHIPSETS(bgep)) {
- int regval = bge_reg_get32(bgep, CPMU_STATUS_REG);
- if (regval & CPMU_STATUS_FUN_NUM)
- bgep->phy_mii_addr += 1;
+ bgep->phy_mii_addr = (bgep->pci_func + 1);
regval = bge_reg_get32(bgep, SGMII_STATUS_REG);
if (regval & MEDIA_SELECTION_MODE)
- bgep->phy_mii_addr += 7;
+ bgep->phy_mii_addr += 7; /* sgmii */
}
if (bge_phy_probe(bgep)) {
@@ -1606,18 +1895,15 @@ bge_phys_update(bge_t *bgep)
boolean_t
bge_phys_check(bge_t *bgep)
{
- int32_t orig_state;
- boolean_t recheck;
-
BGE_TRACE(("bge_phys_check($%p)", (void *)bgep));
ASSERT(mutex_owned(bgep->genlock));
- orig_state = bgep->link_state;
- recheck = orig_state == LINK_STATE_UNKNOWN;
- recheck = (*bgep->physops->phys_check)(bgep, recheck);
- if (!recheck)
- return (B_FALSE);
-
- return (B_TRUE);
+ /*
+ * Force a link recheck if current state is unknown.
+ * phys_check() returns TRUE if the link status changed,
+ * FALSE otherwise.
+ */
+ return ((*bgep->physops->phys_check)(bgep,
+ (bgep->link_state == LINK_STATE_UNKNOWN)));
}
diff --git a/usr/src/uts/common/io/bge/bge_send.c b/usr/src/uts/common/io/bge/bge_send.c
index 28080d93af..87e0c0105d 100644
--- a/usr/src/uts/common/io/bge/bge_send.c
+++ b/usr/src/uts/common/io/bge/bge_send.c
@@ -20,7 +20,13 @@
*/
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010-2013, by Broadcom, Inc.
+ * All Rights Reserved.
+ */
+
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates.
+ * All rights reserved.
*/
#include "bge_impl.h"
@@ -443,6 +449,11 @@ start_tx:
hw_sbd_p->flags |= SBD_FLAG_IP_CKSUM;
if (pktp->pflags & HCK_FULLCKSUM)
hw_sbd_p->flags |= SBD_FLAG_TCP_UDP_CKSUM;
+ if (!(bgep->chipid.flags & CHIP_FLAG_NO_JUMBO) &&
+ (DEVICE_5717_SERIES_CHIPSETS(bgep) ||
+ DEVICE_5725_SERIES_CHIPSETS(bgep)) &&
+ (txbuf->copy_len > ETHERMAX))
+ hw_sbd_p->flags |= SBD_FLAG_JMB_PKT;
hw_sbd_p->flags |= SBD_FLAG_PACKET_END;
txfill_next = NEXT(txfill_next, BGE_SEND_BUF_MAX);
diff --git a/usr/src/uts/intel/bge/Makefile b/usr/src/uts/intel/bge/Makefile
index 3d59fb4bf1..661d2b4fb3 100644
--- a/usr/src/uts/intel/bge/Makefile
+++ b/usr/src/uts/intel/bge/Makefile
@@ -38,7 +38,7 @@ UTSBASE = ../..
#
MODULE = bge
OBJECTS = $(BGE_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(BGE_OBJS:%.o=$(LINTS_DIR)/%.ln)
+LINTS = $(LINTS_DIR)/bge_lint.ln
ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE)
CONF_SRCDIR = $(UTSBASE)/common/io/bge
@@ -67,6 +67,8 @@ LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN
CERRWARN += -_gcc=-Wno-uninitialized
CERRWARN += -_gcc=-Wno-switch
CERRWARN += -_gcc=-Wno-parentheses
+CERRWARN += -_gcc=-Wno-unused-variable
+CERRWARN += -_gcc=-Wno-unused-function
#
# Driver depends on MAC
diff --git a/usr/src/uts/sparc/bge/Makefile b/usr/src/uts/sparc/bge/Makefile
index df29b5b014..765db1019d 100644
--- a/usr/src/uts/sparc/bge/Makefile
+++ b/usr/src/uts/sparc/bge/Makefile
@@ -39,7 +39,7 @@ UTSBASE = ../..
#
MODULE = bge
OBJECTS = $(BGE_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(BGE_OBJS:%.o=$(LINTS_DIR)/%.ln)
+LINTS = $(LINTS_DIR)/bge_lint.ln
ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE)
CONF_SRCDIR = $(UTSBASE)/common/io/bge