Module Name: src
Committed By: riz
Date: Sun Jul 14 20:39:13 UTC 2013
Modified Files:
src/sys/dev/pci [netbsd-6]: if_wm.c if_wmreg.h if_wmvar.h
Log Message:
Apply changes (requested by msaitoh in ticket #907):
sys/dev/pci/if_wm.c 1.238, 1.244-1.247, 1.249-1.258
sys/dev/pci/if_wmreg.h 1.50-1.51, 1.53
sys/dev/pci/if_wmvar.h 1.15-1.16
Various fixes to wm(4):
Add I21[0178] support.
Fix a bug that wm_attach() may fail on some PCH2 or newer system.
wm_valid_nvm_bank_detect_ich8lan() misunderstood the NVM's bank
number. Fixes PR#47878.
Fix a bug that the check of reset complete fails on Intel 8 series
with "wm_lan_init_done: lan_init_done failed to complete" message.
The broken code was used for ICH8, 9... and PCH2.
The wm_linkintr_gmii() function is called from interrupt. That's
not tick, so call mii_pollstat() instead of mii_tick().
Add ECC support for the packet buffer. Only 82571 and I21[78] support
ECC.
Fix a bug that wrong semaphore is used in wm_gmii_hv_{read,write}reg.
Change style, add comments, fix some comments, use macros and
remove trailing whitespaces.
[msaitoh, ticket #907]
To generate a diff of this commit:
cvs rdiff -u -r1.227.2.8 -r1.227.2.9 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.46.2.3 -r1.46.2.4 src/sys/dev/pci/if_wmreg.h
cvs rdiff -u -r1.12.10.2 -r1.12.10.3 src/sys/dev/pci/if_wmvar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.227.2.8 src/sys/dev/pci/if_wm.c:1.227.2.9
--- src/sys/dev/pci/if_wm.c:1.227.2.8 Mon Feb 18 18:05:29 2013
+++ src/sys/dev/pci/if_wm.c Sun Jul 14 20:39:13 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wm.c,v 1.227.2.8 2013/02/18 18:05:29 riz Exp $ */
+/* $NetBSD: if_wm.c,v 1.227.2.9 2013/07/14 20:39:13 riz Exp $ */
/*
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -37,32 +37,32 @@
/*******************************************************************************
- Copyright (c) 2001-2005, Intel Corporation
+ Copyright (c) 2001-2005, Intel Corporation
All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
+
+ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
+
+ 1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of the Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived from
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -76,7 +76,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.227.2.8 2013/02/18 18:05:29 riz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.227.2.9 2013/07/14 20:39:13 riz Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -533,10 +533,8 @@ static void wm_gmii_reset(struct wm_soft
static int wm_gmii_i82543_readreg(device_t, int, int);
static void wm_gmii_i82543_writereg(device_t, int, int, int);
-
static int wm_gmii_i82544_readreg(device_t, int, int);
static void wm_gmii_i82544_writereg(device_t, int, int, int);
-
static int wm_gmii_i80003_readreg(device_t, int, int);
static void wm_gmii_i80003_writereg(device_t, int, int, int);
static int wm_gmii_bm_readreg(device_t, int, int);
@@ -1024,6 +1022,41 @@ static const struct wm_product {
"I350 Gigabit Connection",
WM_T_I350, WMP_F_1000T },
#endif
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_T1,
+ "I210-T1 Ethernet Server Adapter",
+ WM_T_I210, WMP_F_1000T },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_COPPER_OEM1,
+ "I210 Ethernet (Copper OEM)",
+ WM_T_I210, WMP_F_1000T },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_COPPER_IT,
+ "I210 Ethernet (Copper IT)",
+ WM_T_I210, WMP_F_1000T },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_FIBER,
+ "I210 Gigabit Ethernet (Fiber)",
+ WM_T_I210, WMP_F_1000X },
+#if 0
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_SERDES,
+ "I210 Gigabit Ethernet (SERDES)",
+ WM_T_I210, WMP_F_SERDES },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I210_SGMII,
+ "I210 Gigabit Ethernet (SGMII)",
+ WM_T_I210, WMP_F_SERDES },
+#endif
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I211_COPPER,
+ "I211 Ethernet (COPPER)",
+ WM_T_I211, WMP_F_1000T },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I217_V,
+ "I217 V Ethernet Connection",
+ WM_T_PCH_LPT, WMP_F_1000T },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I217_LM,
+ "I217 LM Ethernet Connection",
+ WM_T_PCH_LPT, WMP_F_1000T },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I218_V,
+ "I218 V Ethernet Connection",
+ WM_T_PCH_LPT, WMP_F_1000T },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I218_LM,
+ "I218 LM Ethernet Connection",
+ WM_T_PCH_LPT, WMP_F_1000T },
{ 0, 0,
NULL,
0, 0 },
@@ -1175,7 +1208,8 @@ wm_attach(device_t parent, device_t self
if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)
|| (sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)
- || (sc->sc_type == WM_T_I350))
+ || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I210)
+ || (sc->sc_type == WM_T_I211))
sc->sc_flags |= WM_F_NEWQUEUE;
/* Set device properties (mactype) */
@@ -1325,7 +1359,8 @@ wm_attach(device_t parent, device_t self
if ((sc->sc_type != WM_T_ICH8) && (sc->sc_type != WM_T_ICH9)
&& (sc->sc_type != WM_T_ICH10)
&& (sc->sc_type != WM_T_PCH)
- && (sc->sc_type != WM_T_PCH2)) {
+ && (sc->sc_type != WM_T_PCH2)
+ && (sc->sc_type != WM_T_PCH_LPT)) {
sc->sc_flags |= WM_F_EEPROM_SEMAPHORE;
/* ICH* and PCH* have no PCIe capability registers */
if (pci_get_capability(pa->pa_pc, pa->pa_tag,
@@ -1494,7 +1529,8 @@ wm_attach(device_t parent, device_t self
CSR_READ(sc, WMREG_RXERRC);
/* get PHY control from SMBus to PCIe */
- if ((sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2))
+ if ((sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2)
+ || (sc->sc_type == WM_T_PCH_LPT))
wm_smbustopci(sc);
/*
@@ -1514,6 +1550,7 @@ wm_attach(device_t parent, device_t self
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
if (wm_check_mng_mode(sc) != 0)
wm_get_hw_control(sc);
break;
@@ -1590,6 +1627,7 @@ wm_attach(device_t parent, device_t self
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
/* FLASH */
sc->sc_flags |= WM_F_EEPROM_FLASH | WM_F_SWFWHW_SYNC;
memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, WM_ICH8_FLASH);
@@ -1609,6 +1647,11 @@ wm_attach(device_t parent, device_t self
sc->sc_ich8_flash_bank_size *= ICH_FLASH_SECTOR_SIZE;
sc->sc_ich8_flash_bank_size /= 2 * sizeof(uint16_t);
break;
+ case WM_T_I210:
+ case WM_T_I211:
+ sc->sc_flags |= WM_F_EEPROM_FLASH_HW;
+ sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_SWFW_SYNC;
+ break;
default:
break;
}
@@ -1636,7 +1679,9 @@ wm_attach(device_t parent, device_t self
if (sc->sc_flags & WM_F_EEPROM_INVALID)
aprint_verbose_dev(sc->sc_dev, "No EEPROM\n");
- else if (sc->sc_flags & WM_F_EEPROM_FLASH) {
+ else if (sc->sc_flags & WM_F_EEPROM_FLASH_HW) {
+ aprint_verbose_dev(sc->sc_dev, "FLASH(HW)\n");
+ } else if (sc->sc_flags & WM_F_EEPROM_FLASH) {
aprint_verbose_dev(sc->sc_dev, "FLASH\n");
} else {
if (sc->sc_flags & WM_F_EEPROM_SPI)
@@ -1731,6 +1776,7 @@ wm_attach(device_t parent, device_t self
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
/* XXX The funcid should be checked on some devices */
apme_mask = WUC_APME;
eeprom_data = CSR_READ(sc, WMREG_WUC);
@@ -1833,7 +1879,8 @@ wm_attach(device_t parent, device_t self
*/
if (sc->sc_type == WM_T_ICH8 || sc->sc_type == WM_T_ICH9
|| sc->sc_type == WM_T_ICH10 || sc->sc_type == WM_T_PCH
- || sc->sc_type == WM_T_PCH2 || sc->sc_type == WM_T_82573
+ || sc->sc_type == WM_T_PCH2 || sc->sc_type == WM_T_PCH_LPT
+ || sc->sc_type == WM_T_82573
|| sc->sc_type == WM_T_82574 || sc->sc_type == WM_T_82583) {
/* STATUS_TBIMODE reserved/reused, can't rely on it */
wm_gmii_mediainit(sc, wmp->wmp_product);
@@ -1850,6 +1897,8 @@ wm_attach(device_t parent, device_t self
case WM_T_82580:
case WM_T_82580ER:
case WM_T_I350:
+ case WM_T_I210:
+ case WM_T_I211:
reg = CSR_READ(sc, WMREG_CTRL_EXT);
switch (reg & CTRL_EXT_LINK_MODE_MASK) {
case CTRL_EXT_LINK_MODE_SGMII:
@@ -1914,10 +1963,13 @@ wm_attach(device_t parent, device_t self
case WM_T_82580:
case WM_T_82580ER:
case WM_T_I350:
+ case WM_T_I210:
+ case WM_T_I211:
case WM_T_80003:
case WM_T_ICH9:
case WM_T_ICH10:
case WM_T_PCH2: /* PCH2 supports 9K frame size */
+ case WM_T_PCH_LPT:
/* XXX limited to 9234 */
sc->sc_ethercom.ec_capabilities |= ETHERCAP_JUMBO_MTU;
break;
@@ -2109,7 +2161,7 @@ wm_detach(device_t self, int flags __unu
if_detach(ifp);
- /* Unload RX dmamaps and free mbufs */
+ /* Unload RX dmamaps and free mbufs */
wm_rxdrain(sc);
/* Free dmamap. It's the same as the end of the wm_attach() function */
@@ -2958,9 +3010,9 @@ wm_nq_tx_offload(struct wm_softc *sc, st
sc->sc_nq_txdescs[sc->sc_txnext].nqrx_ctx.nqtxc_vl_len =
htole32(vl_len);
sc->sc_nq_txdescs[sc->sc_txnext].nqrx_ctx.nqtxc_sn = 0;
- sc->sc_nq_txdescs[sc->sc_txnext].nqrx_ctx.nqtxc_cmd =
+ sc->sc_nq_txdescs[sc->sc_txnext].nqrx_ctx.nqtxc_cmd =
htole32(cmdc);
- sc->sc_nq_txdescs[sc->sc_txnext].nqrx_ctx.nqtxc_mssidx =
+ sc->sc_nq_txdescs[sc->sc_txnext].nqrx_ctx.nqtxc_mssidx =
htole32(mssidx);
WM_CDTXSYNC(sc, sc->sc_txnext, 1, BUS_DMASYNC_PREWRITE);
DPRINTF(WM_DEBUG_TX,
@@ -3161,7 +3213,7 @@ wm_nq_start(struct ifnet *ifp)
htole32(fields);
DPRINTF(WM_DEBUG_TX,
("%s: TX: adv data desc %d 0x%" PRIx64 "\n",
- device_xname(sc->sc_dev), nexttx,
+ device_xname(sc->sc_dev), nexttx,
(uint64_t)dmamap->dm_segs[0].ds_addr));
DPRINTF(WM_DEBUG_TX,
("\t 0x%08x%08x\n", fields,
@@ -3646,7 +3698,7 @@ wm_rxintr(struct wm_softc *sc)
/*
* Okay, we have the entire packet now. The chip is
- * configured to include the FCS except I350
+ * configured to include the FCS except I350 and I21[01]
* (not all chips can be configured to strip it),
* so we need to trim it.
* May need to adjust length of previous mbuf in the
@@ -3654,7 +3706,8 @@ wm_rxintr(struct wm_softc *sc)
* For an eratta, the RCTL_SECRC bit in RCTL register
* is always set in I350, so we don't trim it.
*/
- if (sc->sc_type != WM_T_I350) {
+ if ((sc->sc_type != WM_T_I350) && (sc->sc_type != WM_T_I210)
+ && (sc->sc_type != WM_T_I211)) {
if (m->m_len < ETHER_CRC_LEN) {
sc->sc_rxtail->m_len
-= (ETHER_CRC_LEN - m->m_len);
@@ -3767,9 +3820,9 @@ wm_linkintr_gmii(struct wm_softc *sc, ui
if (icr & ICR_LSC) {
DPRINTF(WM_DEBUG_LINK,
- ("%s: LINK: LSC -> mii_tick\n",
+ ("%s: LINK: LSC -> mii_pollstat\n",
device_xname(sc->sc_dev)));
- mii_tick(&sc->sc_mii);
+ mii_pollstat(&sc->sc_mii);
if (sc->sc_type == WM_T_82543) {
int miistatus, active;
@@ -3994,6 +4047,10 @@ wm_reset(struct wm_softc *sc)
case WM_T_82580ER:
sc->sc_pba = PBA_35K;
break;
+ case WM_T_I210:
+ case WM_T_I211:
+ sc->sc_pba = PBA_34K;
+ break;
case WM_T_82576:
sc->sc_pba = PBA_64K;
break;
@@ -4014,6 +4071,7 @@ wm_reset(struct wm_softc *sc)
break;
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
sc->sc_pba = PBA_26K;
break;
default:
@@ -4031,7 +4089,8 @@ wm_reset(struct wm_softc *sc)
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
while (timeout--) {
- if ((CSR_READ(sc, WMREG_STATUS) & STATUS_GIO_M_ENA) == 0)
+ if ((CSR_READ(sc, WMREG_STATUS) & STATUS_GIO_M_ENA)
+ == 0)
break;
delay(100);
}
@@ -4127,6 +4186,7 @@ wm_reset(struct wm_softc *sc)
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
reg = CSR_READ(sc, WMREG_CTRL) | CTRL_RST;
if (wm_check_reset_block(sc) == 0) {
/*
@@ -4163,6 +4223,8 @@ wm_reset(struct wm_softc *sc)
case WM_T_82580ER:
case WM_T_82583:
case WM_T_I350:
+ case WM_T_I210:
+ case WM_T_I211:
default:
/* Everything else can safely use the documented method. */
CSR_WRITE(sc, WMREG_CTRL, CSR_READ(sc, WMREG_CTRL) | CTRL_RST);
@@ -4223,16 +4285,18 @@ wm_reset(struct wm_softc *sc)
case WM_T_82580:
case WM_T_82580ER:
case WM_T_I350:
+ case WM_T_I210:
+ case WM_T_I211:
case WM_T_80003:
- case WM_T_ICH8:
- case WM_T_ICH9:
/* check EECD_EE_AUTORD */
wm_get_auto_rd_done(sc);
break;
+ case WM_T_ICH8:
+ case WM_T_ICH9:
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
- wm_lan_init_done(sc);
+ case WM_T_PCH_LPT:
break;
default:
panic("%s: unknown type\n", __func__);
@@ -4365,6 +4429,7 @@ wm_init(struct ifnet *ifp)
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
if (wm_check_mng_mode(sc) != 0)
wm_get_hw_control(sc);
break;
@@ -4378,7 +4443,8 @@ wm_init(struct ifnet *ifp)
reg = CSR_READ(sc, WMREG_CTRL_EXT);
/* Enable PHY low-power state when MAC is at D3 w/o WoL */
- if ((sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2))
+ if ((sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2)
+ || (sc->sc_type == WM_T_PCH_LPT))
CSR_WRITE(sc, WMREG_CTRL_EXT, reg | CTRL_EXT_PHYPDEN);
/* Initialize the transmit descriptor ring. */
@@ -4463,16 +4529,16 @@ wm_init(struct ifnet *ifp)
} else {
CSR_WRITE(sc, WMREG_RDH, 0);
CSR_WRITE(sc, WMREG_RDT, 0);
- CSR_WRITE(sc, WMREG_RDTR, 375 | RDTR_FPD); /* ITR/4 */
- CSR_WRITE(sc, WMREG_RADV, 375); /* MUST be same */
+ CSR_WRITE(sc, WMREG_RDTR, 375 | RDTR_FPD); /* ITR/4 */
+ CSR_WRITE(sc, WMREG_RADV, 375); /* MUST be same */
}
}
for (i = 0; i < WM_NRXDESC; i++) {
rxs = &sc->sc_rxsoft[i];
if (rxs->rxs_mbuf == NULL) {
if ((error = wm_add_rxbuf(sc, i)) != 0) {
- log(LOG_ERR, "%s: unable to allocate or map rx "
- "buffer %d, error = %d\n",
+ log(LOG_ERR, "%s: unable to allocate or map "
+ "rx buffer %d, error = %d\n",
device_xname(sc->sc_dev), i, error);
/*
* XXX Should attempt to run with fewer receive
@@ -4514,7 +4580,7 @@ wm_init(struct ifnet *ifp)
*/
if ((sc->sc_type != WM_T_ICH8) && (sc->sc_type != WM_T_ICH9)
&& (sc->sc_type != WM_T_ICH10) && (sc->sc_type != WM_T_PCH)
- && (sc->sc_type != WM_T_PCH2)) {
+ && (sc->sc_type != WM_T_PCH2) && (sc->sc_type != WM_T_PCH_LPT)) {
CSR_WRITE(sc, WMREG_FCAL, FCAL_CONST);
CSR_WRITE(sc, WMREG_FCAH, FCAH_CONST);
CSR_WRITE(sc, WMREG_FCT, ETHERTYPE_FLOWCONTROL);
@@ -4547,6 +4613,7 @@ wm_init(struct ifnet *ifp)
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
/*
* Set the mac to wait the maximum time between each
* iteration and increase the max iterations when
@@ -4611,7 +4678,7 @@ wm_init(struct ifnet *ifp)
if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9)
|| (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH)
- || (sc->sc_type == WM_T_PCH2)) {
+ || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) {
reg = CSR_READ(sc, WMREG_KABGTXD);
reg |= KABGTXD_BGSQLBIAS;
CSR_WRITE(sc, WMREG_KABGTXD, reg);
@@ -4697,7 +4764,7 @@ wm_init(struct ifnet *ifp)
* The I350 has a bug where it always strips the CRC whether
* asked to or not. So ask for stripped CRC here and cope in rxeof
*/
- if (sc->sc_type == WM_T_I350)
+ if ((sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I210))
sc->sc_rctl |= RCTL_SECRC;
if (((sc->sc_ethercom.ec_capabilities & ETHERCAP_JUMBO_MTU) != 0)
@@ -4732,6 +4799,26 @@ wm_init(struct ifnet *ifp)
/* Set the receive filter. */
wm_set_filter(sc);
+ /* Enable ECC */
+ switch (sc->sc_type) {
+ case WM_T_82571:
+ reg = CSR_READ(sc, WMREG_PBA_ECC);
+ reg |= PBA_ECC_CORR_EN;
+ CSR_WRITE(sc, WMREG_PBA_ECC, reg);
+ break;
+ case WM_T_PCH_LPT:
+ reg = CSR_READ(sc, WMREG_PBECCSTS);
+ reg |= PBECCSTS_UNCORR_ECC_ENABLE;
+ CSR_WRITE(sc, WMREG_PBECCSTS, reg);
+
+ reg = CSR_READ(sc, WMREG_CTRL);
+ reg |= CTRL_MEHE;
+ CSR_WRITE(sc, WMREG_CTRL, reg);
+ break;
+ default:
+ break;
+ }
+
/* On 575 and later set RDT only if RX enabled */
if ((sc->sc_flags & WM_F_NEWQUEUE) != 0)
for (i = 0; i < WM_NRXDESC; i++)
@@ -4856,6 +4943,8 @@ wm_get_auto_rd_done(struct wm_softc *sc)
case WM_T_82580:
case WM_T_82580ER:
case WM_T_I350:
+ case WM_T_I210:
+ case WM_T_I211:
case WM_T_80003:
case WM_T_ICH8:
case WM_T_ICH9:
@@ -4885,6 +4974,7 @@ wm_lan_init_done(struct wm_softc *sc)
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
for (i = 0; i < WM_ICH8_LAN_INIT_TIMEOUT; i++) {
reg = CSR_READ(sc, WMREG_STATUS);
if ((reg & STATUS_LAN_INIT_DONE) != 0)
@@ -4944,6 +5034,8 @@ wm_get_cfg_done(struct wm_softc *sc)
case WM_T_82580:
case WM_T_82580ER:
case WM_T_I350:
+ case WM_T_I210:
+ case WM_T_I211:
if (sc->sc_type == WM_T_82571) {
/* Only 82571 shares port 0 */
mask = EEMNGCTL_CFGDONE_0;
@@ -4964,13 +5056,16 @@ wm_get_cfg_done(struct wm_softc *sc)
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
- if (sc->sc_type >= WM_T_PCH) {
- reg = CSR_READ(sc, WMREG_STATUS);
- if ((reg & STATUS_PHYRA) != 0)
- CSR_WRITE(sc, WMREG_STATUS,
- reg & ~STATUS_PHYRA);
- }
+ case WM_T_PCH_LPT:
delay(10*1000);
+ if (sc->sc_type >= WM_T_ICH10)
+ wm_lan_init_done(sc);
+ else
+ wm_get_auto_rd_done(sc);
+
+ reg = CSR_READ(sc, WMREG_STATUS);
+ if ((reg & STATUS_PHYRA) != 0)
+ CSR_WRITE(sc, WMREG_STATUS, reg & ~STATUS_PHYRA);
break;
default:
panic("%s: %s: unknown type\n", device_xname(sc->sc_dev),
@@ -5153,7 +5248,7 @@ wm_read_eeprom_uwire(struct wm_softc *sc
delay(2);
}
/* XXX: end of workaround */
-
+
/* Set CHIP SELECT. */
reg |= EECD_CS;
CSR_WRITE(sc, WMREG_EECD, reg);
@@ -5248,8 +5343,12 @@ wm_read_eeprom_spi(struct wm_softc *sc,
return 0;
}
-#define EEPROM_CHECKSUM 0xBABA
-#define EEPROM_SIZE 0x0040
+#define NVM_CHECKSUM 0xBABA
+#define EEPROM_SIZE 0x0040
+#define NVM_COMPAT 0x0003
+#define NVM_COMPAT_VALID_CHECKSUM 0x0001
+#define NVM_FUTURE_INIT_WORD1 0x0019
+#define NVM_FUTURE_INIT_WORD1_VALID_CHECKSUM 0x0040
/*
* wm_validate_eeprom_checksum
@@ -5259,21 +5358,36 @@ wm_read_eeprom_spi(struct wm_softc *sc,
static int
wm_validate_eeprom_checksum(struct wm_softc *sc)
{
- uint16_t checksum;
+ uint16_t checksum, valid_checksum;
uint16_t eeprom_data;
+ uint16_t csum_wordaddr;
int i;
checksum = 0;
+ /* Don't check for I211 */
+ if (sc->sc_type == WM_T_I211)
+ return 0;
+
+ if (sc->sc_type == WM_T_PCH_LPT) {
+ csum_wordaddr = NVM_COMPAT;
+ valid_checksum = NVM_COMPAT_VALID_CHECKSUM;
+ } else {
+ csum_wordaddr = NVM_FUTURE_INIT_WORD1;
+ valid_checksum = NVM_FUTURE_INIT_WORD1_VALID_CHECKSUM;
+ }
+
#ifdef WM_DEBUG
/* Dump EEPROM image for debug */
if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9)
|| (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH)
- || (sc->sc_type == WM_T_PCH2)) {
- wm_read_eeprom(sc, 0x19, 1, &eeprom_data);
- if ((eeprom_data & 0x40) == 0) {
- DPRINTF(WM_DEBUG_NVM,("%s: NVM need to be updated\n",
- device_xname(sc->sc_dev)));
+ || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) {
+ wm_read_eeprom(sc, csum_wordaddr, 1, &eeprom_data);
+ if ((eeprom_data & valid_checksum) == 0) {
+ DPRINTF(WM_DEBUG_NVM,
+ ("%s: NVM need to be updated (%04x != %04x)\n",
+ device_xname(sc->sc_dev), eeprom_data,
+ valid_checksum));
}
}
@@ -5297,8 +5411,12 @@ wm_validate_eeprom_checksum(struct wm_so
checksum += eeprom_data;
}
- if (checksum != (uint16_t) EEPROM_CHECKSUM)
- return 1;
+ if (checksum != (uint16_t) NVM_CHECKSUM) {
+#ifdef WM_DEBUG
+ printf("%s: NVM checksum mismatch (%04x != %04x)\n",
+ device_xname(sc->sc_dev), checksum, NVM_CHECKSUM);
+#endif
+ }
return 0;
}
@@ -5321,7 +5439,7 @@ wm_read_eeprom(struct wm_softc *sc, int
if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9)
|| (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH)
- || (sc->sc_type == WM_T_PCH2))
+ || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT))
rv = wm_read_eeprom_ich8(sc, word, wordcnt, data);
else if (sc->sc_flags & WM_F_EEPROM_EERDEEWR)
rv = wm_read_eeprom_eerd(sc, word, wordcnt, data);
@@ -5438,6 +5556,8 @@ wm_read_mac_addr(struct wm_softc *sc, ui
case WM_T_82575:
case WM_T_82576:
case WM_T_80003:
+ case WM_T_I210:
+ case WM_T_I211:
if (wm_check_alt_mac_addr(sc) != 0) {
/* reset the offset to LAN0 */
offset = EEPROM_OFF_MACADDR;
@@ -5545,7 +5665,7 @@ wm_add_rxbuf(struct wm_softc *sc, int id
if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) {
if ((sc->sc_rctl & RCTL_EN) != 0)
WM_INIT_RXDESC(sc, idx);
- } else
+ } else
WM_INIT_RXDESC(sc, idx);
return 0;
@@ -5599,7 +5719,7 @@ wm_mchash(struct wm_softc *sc, const uin
if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9)
|| (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH)
- || (sc->sc_type == WM_T_PCH2)) {
+ || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) {
hash = (enaddr[4] >> ich8_lo_shift[sc->sc_mchash_type]) |
(((uint16_t) enaddr[5]) << ich8_hi_shift[sc->sc_mchash_type]);
return (hash & 0x3ff);
@@ -5647,7 +5767,8 @@ wm_set_filter(struct wm_softc *sc)
if (sc->sc_type == WM_T_ICH8)
size = WM_RAL_TABSIZE_ICH8 -1;
else if ((sc->sc_type == WM_T_ICH9) || (sc->sc_type == WM_T_ICH10)
- || (sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2))
+ || (sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2)
+ || (sc->sc_type == WM_T_PCH_LPT))
size = WM_RAL_TABSIZE_ICH8;
else if (sc->sc_type == WM_T_82575)
size = WM_RAL_TABSIZE_82575;
@@ -5663,7 +5784,7 @@ wm_set_filter(struct wm_softc *sc)
if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9)
|| (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH)
- || (sc->sc_type == WM_T_PCH2))
+ || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT))
size = WM_ICH8_MC_TABSIZE;
else
size = WM_MC_TABSIZE;
@@ -5690,7 +5811,8 @@ wm_set_filter(struct wm_softc *sc)
reg = (hash >> 5);
if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9)
|| (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH)
- || (sc->sc_type == WM_T_PCH2))
+ || (sc->sc_type == WM_T_PCH2)
+ || (sc->sc_type == WM_T_PCH_LPT))
reg &= 0x1f;
else
reg &= 0x7f;
@@ -6033,6 +6155,8 @@ wm_gmii_reset(struct wm_softc *sc)
case WM_T_82580:
case WM_T_82580ER:
case WM_T_I350:
+ case WM_T_I210:
+ case WM_T_I211:
case WM_T_80003:
rv = wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]);
break;
@@ -6041,6 +6165,7 @@ wm_gmii_reset(struct wm_softc *sc)
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
rv = wm_get_swfwhw_semaphore(sc);
break;
default:
@@ -6104,6 +6229,8 @@ wm_gmii_reset(struct wm_softc *sc)
case WM_T_82580:
case WM_T_82580ER:
case WM_T_I350:
+ case WM_T_I210:
+ case WM_T_I211:
case WM_T_82583:
case WM_T_80003:
/* generic reset */
@@ -6125,6 +6252,7 @@ wm_gmii_reset(struct wm_softc *sc)
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
/* generic reset */
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl | CTRL_PHY_RESET);
delay(100);
@@ -6152,6 +6280,8 @@ wm_gmii_reset(struct wm_softc *sc)
case WM_T_82580:
case WM_T_82580ER:
case WM_T_I350:
+ case WM_T_I210:
+ case WM_T_I211:
case WM_T_80003:
wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]);
break;
@@ -6160,6 +6290,7 @@ wm_gmii_reset(struct wm_softc *sc)
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
wm_put_swfwhw_semaphore(sc);
break;
default:
@@ -6193,6 +6324,8 @@ wm_gmii_reset(struct wm_softc *sc)
case WM_T_82580:
case WM_T_82580ER:
case WM_T_I350:
+ case WM_T_I210:
+ case WM_T_I211:
case WM_T_82583:
case WM_T_80003:
/* null */
@@ -6206,6 +6339,7 @@ wm_gmii_reset(struct wm_softc *sc)
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
/* Allow time for h/w to get to a quiescent state afer reset */
delay(10*1000);
@@ -6229,7 +6363,8 @@ wm_gmii_reset(struct wm_softc *sc)
*/
/* Configure the LCD with the OEM bits in NVM */
- if ((sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2)) {
+ if ((sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2)
+ || (sc->sc_type == WM_T_PCH_LPT)) {
/*
* Disable LPLU.
* XXX It seems that 82567 has LPLU, too.
@@ -6255,6 +6390,7 @@ static void
wm_gmii_mediainit(struct wm_softc *sc, pci_product_id_t prodid)
{
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+ struct mii_data *mii = &sc->sc_mii;
/* We have MII. */
sc->sc_flags |= WM_F_HAS_MII;
@@ -6274,29 +6410,50 @@ wm_gmii_mediainit(struct wm_softc *sc, p
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
/* Initialize our media structures and probe the GMII. */
- sc->sc_mii.mii_ifp = ifp;
+ mii->mii_ifp = ifp;
+ /*
+ * Determine the PHY access method.
+ *
+ * For SGMII, use SGMII specific method.
+ *
+ * For some devices, we can determine the PHY access method
+ * from sc_type.
+ *
+ * For ICH8 variants, it's difficult to detemine the PHY access
+ * method by sc_type, so use the PCI product ID for some devices.
+ * For other ICH8 variants, try to use igp's method. If the PHY
+ * can't detect, then use bm's method.
+ */
switch (prodid) {
case PCI_PRODUCT_INTEL_PCH_M_LM:
case PCI_PRODUCT_INTEL_PCH_M_LC:
/* 82577 */
sc->sc_phytype = WMPHY_82577;
- sc->sc_mii.mii_readreg = wm_gmii_hv_readreg;
- sc->sc_mii.mii_writereg = wm_gmii_hv_writereg;
+ mii->mii_readreg = wm_gmii_hv_readreg;
+ mii->mii_writereg = wm_gmii_hv_writereg;
break;
case PCI_PRODUCT_INTEL_PCH_D_DM:
case PCI_PRODUCT_INTEL_PCH_D_DC:
/* 82578 */
sc->sc_phytype = WMPHY_82578;
- sc->sc_mii.mii_readreg = wm_gmii_hv_readreg;
- sc->sc_mii.mii_writereg = wm_gmii_hv_writereg;
+ mii->mii_readreg = wm_gmii_hv_readreg;
+ mii->mii_writereg = wm_gmii_hv_writereg;
break;
case PCI_PRODUCT_INTEL_PCH2_LV_LM:
case PCI_PRODUCT_INTEL_PCH2_LV_V:
- /* 82578 */
+ /* 82579 */
sc->sc_phytype = WMPHY_82579;
- sc->sc_mii.mii_readreg = wm_gmii_hv_readreg;
- sc->sc_mii.mii_writereg = wm_gmii_hv_writereg;
+ mii->mii_readreg = wm_gmii_hv_readreg;
+ mii->mii_writereg = wm_gmii_hv_writereg;
+ break;
+ case PCI_PRODUCT_INTEL_I217_LM:
+ case PCI_PRODUCT_INTEL_I217_V:
+ case PCI_PRODUCT_INTEL_I218_LM:
+ case PCI_PRODUCT_INTEL_I218_V:
+ /* I21[78] */
+ mii->mii_readreg = wm_gmii_hv_readreg;
+ mii->mii_writereg = wm_gmii_hv_writereg;
break;
case PCI_PRODUCT_INTEL_82801I_BM:
case PCI_PRODUCT_INTEL_82801J_R_BM_LM:
@@ -6306,40 +6463,44 @@ wm_gmii_mediainit(struct wm_softc *sc, p
case PCI_PRODUCT_INTEL_82801J_R_BM_V:
/* 82567 */
sc->sc_phytype = WMPHY_BM;
- sc->sc_mii.mii_readreg = wm_gmii_bm_readreg;
- sc->sc_mii.mii_writereg = wm_gmii_bm_writereg;
+ mii->mii_readreg = wm_gmii_bm_readreg;
+ mii->mii_writereg = wm_gmii_bm_writereg;
break;
default:
if ((sc->sc_flags & WM_F_SGMII) != 0) {
- sc->sc_mii.mii_readreg = wm_sgmii_readreg;
- sc->sc_mii.mii_writereg = wm_sgmii_writereg;
+ mii->mii_readreg = wm_sgmii_readreg;
+ mii->mii_writereg = wm_sgmii_writereg;
} else if (sc->sc_type >= WM_T_80003) {
- sc->sc_mii.mii_readreg = wm_gmii_i80003_readreg;
- sc->sc_mii.mii_writereg = wm_gmii_i80003_writereg;
+ mii->mii_readreg = wm_gmii_i80003_readreg;
+ mii->mii_writereg = wm_gmii_i80003_writereg;
+ } else if (sc->sc_type >= WM_T_I210) {
+ mii->mii_readreg = wm_gmii_i82544_readreg;
+ mii->mii_writereg = wm_gmii_i82544_writereg;
} else if (sc->sc_type >= WM_T_82580) {
sc->sc_phytype = WMPHY_82580;
- sc->sc_mii.mii_readreg = wm_gmii_82580_readreg;
- sc->sc_mii.mii_writereg = wm_gmii_82580_writereg;
+ mii->mii_readreg = wm_gmii_82580_readreg;
+ mii->mii_writereg = wm_gmii_82580_writereg;
} else if (sc->sc_type >= WM_T_82544) {
- sc->sc_mii.mii_readreg = wm_gmii_i82544_readreg;
- sc->sc_mii.mii_writereg = wm_gmii_i82544_writereg;
+ mii->mii_readreg = wm_gmii_i82544_readreg;
+ mii->mii_writereg = wm_gmii_i82544_writereg;
} else {
- sc->sc_mii.mii_readreg = wm_gmii_i82543_readreg;
- sc->sc_mii.mii_writereg = wm_gmii_i82543_writereg;
+ mii->mii_readreg = wm_gmii_i82543_readreg;
+ mii->mii_writereg = wm_gmii_i82543_writereg;
}
break;
}
- sc->sc_mii.mii_statchg = wm_gmii_statchg;
+ mii->mii_statchg = wm_gmii_statchg;
wm_gmii_reset(sc);
sc->sc_ethercom.ec_mii = &sc->sc_mii;
- ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, wm_gmii_mediachange,
+ ifmedia_init(&mii->mii_media, IFM_IMASK, wm_gmii_mediachange,
wm_gmii_mediastatus);
if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)
|| (sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)
- || (sc->sc_type == WM_T_I350)) {
+ || (sc->sc_type == WM_T_I350) || (sc->sc_type == WM_T_I210)
+ || (sc->sc_type == WM_T_I211)) {
if ((sc->sc_flags & WM_F_SGMII) == 0) {
/* Attach only one port */
mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, 1,
@@ -6368,31 +6529,44 @@ wm_gmii_mediainit(struct wm_softc *sc, p
MII_OFFSET_ANY, MIIF_DOPAUSE);
}
- if ((sc->sc_type == WM_T_PCH2) &&
- (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL)) {
+ /*
+ * If the MAC is PCH2 or PCH_LPT and failed to detect MII PHY, call
+ * wm_set_mdio_slow_mode_hv() for a workaround and retry.
+ */
+ if (((sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) &&
+ (LIST_FIRST(&mii->mii_phys) == NULL)) {
wm_set_mdio_slow_mode_hv(sc);
mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
MII_OFFSET_ANY, MIIF_DOPAUSE);
}
-
- if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
+
+ /*
+ * (For ICH8 variants)
+ * If PHY detection failed, use BM's r/w function and retry.
+ */
+ if (LIST_FIRST(&mii->mii_phys) == NULL) {
/* if failed, retry with *_bm_* */
- sc->sc_mii.mii_readreg = wm_gmii_bm_readreg;
- sc->sc_mii.mii_writereg = wm_gmii_bm_writereg;
+ mii->mii_readreg = wm_gmii_bm_readreg;
+ mii->mii_writereg = wm_gmii_bm_writereg;
mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
MII_OFFSET_ANY, MIIF_DOPAUSE);
}
- if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
- ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
- ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
+
+ if (LIST_FIRST(&mii->mii_phys) == NULL) {
+ /* Any PHY wasn't find */
+ ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
+ ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_NONE);
sc->sc_phytype = WMPHY_NONE;
} else {
- /* Check PHY type */
+ /*
+ * PHY Found!
+ * Check PHY type.
+ */
uint32_t model;
struct mii_softc *child;
- child = LIST_FIRST(&sc->sc_mii.mii_phys);
+ child = LIST_FIRST(&mii->mii_phys);
if (device_is_a(child->mii_dev, "igphy")) {
struct igphy_softc *isc = (struct igphy_softc *)child;
@@ -6401,7 +6575,7 @@ wm_gmii_mediainit(struct wm_softc *sc, p
sc->sc_phytype = WMPHY_IGP_3;
}
- ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO);
+ ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
}
}
@@ -6745,12 +6919,12 @@ wm_gmii_bm_readreg(device_t self, int ph
if (reg > BME1000_MAX_MULTI_PAGE_REG) {
if (phy == 1)
- wm_gmii_i82544_writereg(self, phy, 0x1f,
+ wm_gmii_i82544_writereg(self, phy, MII_IGPHY_PAGE_SELECT,
reg);
else
- wm_gmii_i82544_writereg(self, phy, GG82563_PHY_PAGE_SELECT,
+ wm_gmii_i82544_writereg(self, phy,
+ GG82563_PHY_PAGE_SELECT,
reg >> GG82563_PAGE_SHIFT);
-
}
rv = wm_gmii_i82544_readreg(self, phy, reg & GG82563_MAX_REG_ADDRESS);
@@ -6780,12 +6954,12 @@ wm_gmii_bm_writereg(device_t self, int p
if (reg > BME1000_MAX_MULTI_PAGE_REG) {
if (phy == 1)
- wm_gmii_i82544_writereg(self, phy, 0x1f,
+ wm_gmii_i82544_writereg(self, phy, MII_IGPHY_PAGE_SELECT,
reg);
else
- wm_gmii_i82544_writereg(self, phy, GG82563_PHY_PAGE_SELECT,
+ wm_gmii_i82544_writereg(self, phy,
+ GG82563_PHY_PAGE_SELECT,
reg >> GG82563_PAGE_SHIFT);
-
}
wm_gmii_i82544_writereg(self, phy, reg & GG82563_MAX_REG_ADDRESS, val);
@@ -6849,7 +7023,7 @@ wm_gmii_hv_readreg(device_t self, int ph
uint16_t val;
int rv;
- if (wm_get_swfw_semaphore(sc, SWFW_PHY0_SM)) {
+ if (wm_get_swfwhw_semaphore(sc)) {
aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
__func__);
return 0;
@@ -6881,7 +7055,7 @@ wm_gmii_hv_readreg(device_t self, int ph
}
rv = wm_gmii_i82544_readreg(self, phy, regnum & IGPHY_MAXREGADDR);
- wm_put_swfw_semaphore(sc, SWFW_PHY0_SM);
+ wm_put_swfwhw_semaphore(sc);
return rv;
}
@@ -6899,7 +7073,7 @@ wm_gmii_hv_writereg(device_t self, int p
uint16_t page = BM_PHY_REG_PAGE(reg);
uint16_t regnum = BM_PHY_REG_NUM(reg);
- if (wm_get_swfw_semaphore(sc, SWFW_PHY0_SM)) {
+ if (wm_get_swfwhw_semaphore(sc)) {
aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
__func__);
return;
@@ -6936,13 +7110,13 @@ wm_gmii_hv_writereg(device_t self, int p
}
wm_gmii_i82544_writereg(self, phy, regnum & IGPHY_MAXREGADDR, val);
- wm_put_swfw_semaphore(sc, SWFW_PHY0_SM);
+ wm_put_swfwhw_semaphore(sc);
}
/*
- * wm_gmii_hv_readreg: [mii interface function]
+ * wm_sgmii_readreg: [mii interface function]
*
- * Read a PHY register on the kumeran
+ * Read a PHY register on the SGMII
* This could be handled by the PHY layer if we didn't have to lock the
* ressource ...
*/
@@ -6983,9 +7157,9 @@ wm_sgmii_readreg(device_t self, int phy,
}
/*
- * wm_gmii_hv_writereg: [mii interface function]
+ * wm_sgmii_writereg: [mii interface function]
*
- * Write a PHY register on the kumeran.
+ * Write a PHY register on the SGMII.
* This could be handled by the PHY layer if we didn't have to lock the
* ressource ...
*/
@@ -7352,31 +7526,42 @@ wm_put_swfwhw_semaphore(struct wm_softc
static int
wm_valid_nvm_bank_detect_ich8lan(struct wm_softc *sc, unsigned int *bank)
{
+ uint32_t eecd;
uint32_t act_offset = ICH_NVM_SIG_WORD * 2 + 1;
uint32_t bank1_offset = sc->sc_ich8_flash_bank_size * sizeof(uint16_t);
+ uint8_t sig_byte = 0;
- if ((sc->sc_type != WM_T_ICH10) && (sc->sc_type != WM_T_PCH)) {
- /* Value of bit 22 corresponds to the flash bank we're on. */
- *bank = (CSR_READ(sc, WMREG_EECD) & EECD_SEC1VAL) ? 1 : 0;
- } else {
- uint8_t bank_high_byte;
- wm_read_ich8_byte(sc, act_offset, &bank_high_byte);
- if ((bank_high_byte & 0xc0) == 0x80)
+ switch (sc->sc_type) {
+ case WM_T_ICH8:
+ case WM_T_ICH9:
+ eecd = CSR_READ(sc, WMREG_EECD);
+ if ((eecd & EECD_SEC1VAL_VALMASK) == EECD_SEC1VAL_VALMASK) {
+ *bank = ((eecd & EECD_SEC1VAL) != 0) ? 1 : 0;
+ return 0;
+ }
+ /* FALLTHROUGH */
+ default:
+ /* Default to 0 */
+ *bank = 0;
+
+ /* Check bank 0 */
+ wm_read_ich8_byte(sc, act_offset, &sig_byte);
+ if ((sig_byte & ICH_NVM_VALID_SIG_MASK) == ICH_NVM_SIG_VALUE) {
*bank = 0;
- else {
- wm_read_ich8_byte(sc, act_offset + bank1_offset,
- &bank_high_byte);
- if ((bank_high_byte & 0xc0) == 0x80)
- *bank = 1;
- else {
- aprint_error_dev(sc->sc_dev,
- "EEPROM not present\n");
- return -1;
- }
+ return 0;
+ }
+
+ /* Check bank 1 */
+ wm_read_ich8_byte(sc, act_offset + bank1_offset,
+ &sig_byte);
+ if ((sig_byte & ICH_NVM_VALID_SIG_MASK) == ICH_NVM_SIG_VALUE) {
+ *bank = 1;
+ return 0;
}
}
- return 0;
+ aprint_error_dev(sc->sc_dev, "EEPROM not present\n");
+ return -1;
}
/******************************************************************************
@@ -7410,7 +7595,10 @@ wm_read_eeprom_ich8(struct wm_softc *sc,
return error;
}
- /* Adjust offset appropriately if we're on bank 1 - adjust for word size */
+ /*
+ * Adjust offset appropriately if we're on bank 1 - adjust for word
+ * size
+ */
bank_offset = flash_bank * (sc->sc_ich8_flash_bank_size * 2);
error = wm_get_swfwhw_semaphore(sc);
@@ -7425,8 +7613,8 @@ wm_read_eeprom_ich8(struct wm_softc *sc,
act_offset = bank_offset + ((offset + i) * 2);
error = wm_read_ich8_word(sc, act_offset, &word);
if (error) {
- aprint_error_dev(sc->sc_dev, "%s: failed to read NVM\n",
- __func__);
+ aprint_error_dev(sc->sc_dev,
+ "%s: failed to read NVM\n", __func__);
break;
}
data[i] = word;
@@ -7671,6 +7859,7 @@ wm_check_mng_mode(struct wm_softc *sc)
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
rv = wm_check_mng_mode_ich8lan(sc);
break;
case WM_T_82574:
@@ -7772,6 +7961,7 @@ wm_check_reset_block(struct wm_softc *sc
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
reg = CSR_READ(sc, WMREG_FWSM);
if ((reg & FWSM_RSPCIPHY) != 0)
return 0;
@@ -7818,6 +8008,7 @@ wm_get_hw_control(struct wm_softc *sc)
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
reg = CSR_READ(sc, WMREG_CTRL_EXT);
CSR_WRITE(sc, WMREG_CTRL_EXT, reg | CTRL_EXT_DRV_LOAD);
break;
@@ -7833,7 +8024,7 @@ wm_release_hw_control(struct wm_softc *s
if ((sc->sc_flags & WM_F_HAS_MANAGE) == 0)
return;
-
+
if (sc->sc_type == WM_T_82573) {
reg = CSR_READ(sc, WMREG_SWSM);
reg &= ~SWSM_DRV_LOAD;
@@ -7950,7 +8141,7 @@ wm_kmrn_lock_loss_workaround_ich8lan(str
reg = CSR_READ(sc, WMREG_PHY_CTRL);
reg |= PHY_CTRL_GBE_DIS | PHY_CTRL_NOND0A_GBE_DIS;
CSR_WRITE(sc, WMREG_PHY_CTRL, reg);
-
+
/*
* Call gig speed drop workaround on Gig disable before accessing
* any PHY registers.
@@ -8230,7 +8421,7 @@ wm_init_manageability(struct wm_softc *s
manc |= MANC_EN_MNG2HOST;
manc2h |= MANC2H_PORT_623| MANC2H_PORT_624;
CSR_WRITE(sc, WMREG_MANC2H, manc2h);
-
+
}
CSR_WRITE(sc, WMREG_MANC, manc);
@@ -8261,7 +8452,7 @@ wm_get_wakeup(struct wm_softc *sc)
case WM_T_82583:
sc->sc_flags |= WM_F_HAS_AMT;
/* FALLTHROUGH */
- case WM_T_80003:
+ case WM_T_80003:
case WM_T_82541:
case WM_T_82547:
case WM_T_82571:
@@ -8283,6 +8474,7 @@ wm_get_wakeup(struct wm_softc *sc)
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
sc->sc_flags |= WM_F_HAS_AMT;
sc->sc_flags |= WM_F_ASF_FIRMWARE_PRES;
break;
@@ -8358,6 +8550,7 @@ wm_enable_wakeup(struct wm_softc *sc)
case WM_T_ICH10:
case WM_T_PCH:
case WM_T_PCH2:
+ case WM_T_PCH_LPT:
/* Disable gig during WOL */
reg = CSR_READ(sc, WMREG_PHY_CTRL);
reg |= PHY_CTRL_D0A_LPLU | PHY_CTRL_GBE_DIS;
Index: src/sys/dev/pci/if_wmreg.h
diff -u src/sys/dev/pci/if_wmreg.h:1.46.2.3 src/sys/dev/pci/if_wmreg.h:1.46.2.4
--- src/sys/dev/pci/if_wmreg.h:1.46.2.3 Mon Feb 18 18:05:30 2013
+++ src/sys/dev/pci/if_wmreg.h Sun Jul 14 20:39:13 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wmreg.h,v 1.46.2.3 2013/02/18 18:05:30 riz Exp $ */
+/* $NetBSD: if_wmreg.h,v 1.46.2.4 2013/07/14 20:39:13 riz Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -35,6 +35,39 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+/******************************************************************************
+
+ Copyright (c) 2001-2012, Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
/*
* Register description for the Intel i82542 (``Wiseman''),
* i82543 (``Livengood''), and i82544 (``Cordova'') Gigabit
@@ -200,6 +233,7 @@ struct livengood_tcpip_ctxdesc {
#define CTRL_SWDPIO_SHIFT 22
#define CTRL_SWDPIO_MASK 0x0f
#define CTRL_SWDPIO(x) (1U << (CTRL_SWDPIO_SHIFT + (x)))
+#define CTRL_MEHE (1U << 17) /* Memory Error Handling Enable(I217)*/
#define CTRL_RST (1U << 26) /* device reset */
#define CTRL_RFCE (1U << 27) /* Rx flow control enable */
#define CTRL_TFCE (1U << 28) /* Tx flow control enable */
@@ -255,6 +289,7 @@ struct livengood_tcpip_ctxdesc {
#define EECD_EE_TYPE (1U << 13) /* EEPROM type
(0 = Microwire, 1 = SPI) */
#define EECD_SEC1VAL (1U << 22) /* Sector One Valid */
+#define EECD_SEC1VAL_VALMASK (EECD_EE_AUTORD | EECD_EE_PRES) /* Valid Mask */
#define UWIRE_OPC_ERASE 0x04 /* MicroWire "erase" opcode */
#define UWIRE_OPC_WRITE 0x05 /* MicroWire "write" opcode */
@@ -683,6 +718,7 @@ struct livengood_tcpip_ctxdesc {
#define PBA_26K 0x001a
#define PBA_30K 0x001e
#define PBA_32K 0x0020
+#define PBA_34K 0x0022
#define PBA_35K 0x0023
#define PBA_40K 0x0028
#define PBA_48K 0x0030 /* 48K, default Rx allocation */
@@ -690,6 +726,11 @@ struct livengood_tcpip_ctxdesc {
#define WMREG_PBS 0x1008 /* Packet Buffer Size (ICH) */
+#define WMREG_PBECCSTS 0x100c /* Packet Buffer ECC Status (PCH_LPT) */
+#define PBECCSTS_CORR_ERR_CNT_MASK 0x000000ff
+#define PBECCSTS_UNCORR_ERR_CNT_MASK 0x0000ff00
+#define PBECCSTS_UNCORR_ECC_ENABLE 0x00010000
+
#define WMREG_EEMNGCTL 0x1010 /* MNG EEprom Control */
#define EEMNGCTL_CFGDONE_0 0x040000 /* MNG config cycle done */
#define EEMNGCTL_CFGDONE_1 0x080000 /* 2nd port */
@@ -708,6 +749,13 @@ struct livengood_tcpip_ctxdesc {
#define MAX_SGMII_PHY_REG_ADDR 255
#define I2CCMD_PHY_TIMEOUT 200
+#define WMREG_PBA_ECC 0x01100 /* PBA ECC */
+#define PBA_ECC_COUNTER_MASK 0xfff00000 /* ECC counter mask */
+#define PBA_ECC_COUNTER_SHIFT 20 /* ECC counter shift value */
+#define PBA_ECC_CORR_EN 0x00000001 /* Enable ECC error correction */
+#define PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */
+#define PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 on ECC error */
+
#define WMREG_EICS 0x01520 /* Ext. Interrupt Cause Set - WO */
#define WMREG_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
#define WMREG_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
@@ -963,6 +1011,8 @@ struct livengood_tcpip_ctxdesc {
#define ICH_NVM_SIG_WORD 0x13
#define ICH_NVM_SIG_MASK 0xc000
+#define ICH_NVM_VALID_SIG_MASK 0xc0
+#define ICH_NVM_SIG_VALUE 0x80
/* for PCI express Capability registers */
#define WM_PCI_PCIE_DCSR2_16MS 0x00000005
Index: src/sys/dev/pci/if_wmvar.h
diff -u src/sys/dev/pci/if_wmvar.h:1.12.10.2 src/sys/dev/pci/if_wmvar.h:1.12.10.3
--- src/sys/dev/pci/if_wmvar.h:1.12.10.2 Thu Feb 14 22:08:28 2013
+++ src/sys/dev/pci/if_wmvar.h Sun Jul 14 20:39:13 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wmvar.h,v 1.12.10.2 2013/02/14 22:08:28 jdc Exp $ */
+/* $NetBSD: if_wmvar.h,v 1.12.10.3 2013/07/14 20:39:13 riz Exp $ */
/*
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -94,6 +94,7 @@
#define WM_F_HAS_MANAGE 0x00080000
#define WM_F_WOL 0x00100000
#define WM_F_EEE 0x00200000 /* Energy Efficiency Ethernet */
+#define WM_F_EEPROM_FLASH_HW 0x00400000 /* EEPROM is FLASH */
typedef enum {
WM_T_unknown = 0,
@@ -120,12 +121,15 @@ typedef enum {
WM_T_82580, /* i82580 */
WM_T_82580ER, /* i82580ER */
WM_T_I350, /* I350 */
+ WM_T_I210, /* I210 */
+ WM_T_I211, /* I211 */
WM_T_80003, /* i80003 */
WM_T_ICH8, /* ICH8 LAN */
WM_T_ICH9, /* ICH9 LAN */
WM_T_ICH10, /* ICH10 LAN */
WM_T_PCH, /* PCH LAN */
WM_T_PCH2, /* PCH2 LAN */
+ WM_T_PCH_LPT, /* PCH LPT LAN (I21[78]) */
} wm_chip_type;
typedef enum {