Module Name: src Committed By: msaitoh Date: Sun Jun 2 09:36:22 UTC 2013
Modified Files: src/sys/dev/pci: if_wm.c if_wmvar.h Log Message: Add I217 (and I218) support. - The name of I217 is similar to I210, but the function is rather similar to PCH2. - Not tested well. Tested with my own Intel DQ87PG which has I217LM onboard. - It seems that PCH2 and PCH_LPT specific function for RAL should be written. - Quick hack for the NVM checksum mismatch. if_wm.c currently has no wm_write_eeprom(), so it cannot update NVM's "updated bit". To avoid this problem, check only the last 12bits of the checksum. My own DQ87PG's updated bit is not set, and I could avoid the problem using with this hack. To generate a diff of this commit: cvs rdiff -u -r1.248 -r1.249 src/sys/dev/pci/if_wm.c cvs rdiff -u -r1.15 -r1.16 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.248 src/sys/dev/pci/if_wm.c:1.249 --- src/sys/dev/pci/if_wm.c:1.248 Sun Apr 21 19:59:41 2013 +++ src/sys/dev/pci/if_wm.c Sun Jun 2 09:36:22 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wm.c,v 1.248 2013/04/21 19:59:41 msaitoh Exp $ */ +/* $NetBSD: if_wm.c,v 1.249 2013/06/02 09:36:22 msaitoh Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -76,7 +76,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.248 2013/04/21 19:59:41 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.249 2013/06/02 09:36:22 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -1045,6 +1045,18 @@ static const struct wm_product { { 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 }, @@ -1347,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, @@ -1516,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); /* @@ -1536,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; @@ -1612,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); @@ -1762,6 +1778,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); @@ -1864,7 +1881,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); @@ -1953,6 +1971,7 @@ wm_attach(device_t parent, device_t self 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; @@ -4054,6 +4073,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: @@ -4168,6 +4188,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) { /* @@ -4277,6 +4298,7 @@ wm_reset(struct wm_softc *sc) case WM_T_ICH10: case WM_T_PCH: case WM_T_PCH2: + case WM_T_PCH_LPT: wm_lan_init_done(sc); break; default: @@ -4410,6 +4432,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; @@ -4592,6 +4615,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 @@ -4932,6 +4956,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) @@ -5013,6 +5038,7 @@ wm_get_cfg_done(struct wm_softc *sc) case WM_T_ICH10: case WM_T_PCH: case WM_T_PCH2: + case WM_T_PCH_LPT: if (sc->sc_type >= WM_T_PCH) { reg = CSR_READ(sc, WMREG_STATUS); if ((reg & STATUS_PHYRA) != 0) @@ -5297,8 +5323,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 @@ -5308,8 +5338,9 @@ 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; @@ -5318,15 +5349,26 @@ wm_validate_eeprom_checksum(struct wm_so if (sc->sc_type == WM_T_I211) return 0; + if (sc->sc_type == WM_T_PCH_LPT) { + printf("[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)); } } @@ -5350,8 +5392,19 @@ 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 + /* + * XXX quick hack for non-updated NVM. + * Check only last 12bit until wm_write_eeprom() will be + * implemented. + */ + if ((checksum & 0x0fff) != ((uint16_t)NVM_CHECKSUM & 0x0fff)) + return 1; + } return 0; } @@ -5374,7 +5427,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); @@ -5654,7 +5707,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); @@ -5702,7 +5755,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; @@ -5718,7 +5772,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; @@ -5745,7 +5799,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; @@ -6098,6 +6153,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: @@ -6184,6 +6240,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); @@ -6221,6 +6278,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: @@ -6269,6 +6327,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); @@ -6450,10 +6509,10 @@ wm_gmii_mediainit(struct wm_softc *sc, p } /* - * If the MAC is PCH2 and failed to detect MII PHY, call + * 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) && + 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, @@ -7769,6 +7828,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: @@ -7870,6 +7930,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; @@ -7916,6 +7977,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; @@ -8381,6 +8443,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; @@ -8456,6 +8519,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_wmvar.h diff -u src/sys/dev/pci/if_wmvar.h:1.15 src/sys/dev/pci/if_wmvar.h:1.16 --- src/sys/dev/pci/if_wmvar.h:1.15 Thu Apr 18 12:42:03 2013 +++ src/sys/dev/pci/if_wmvar.h Sun Jun 2 09:36:22 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmvar.h,v 1.15 2013/04/18 12:42:03 msaitoh Exp $ */ +/* $NetBSD: if_wmvar.h,v 1.16 2013/06/02 09:36:22 msaitoh Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -129,9 +129,7 @@ typedef enum { WM_T_ICH10, /* ICH10 LAN */ WM_T_PCH, /* PCH LAN */ WM_T_PCH2, /* PCH2 LAN */ -#if 0 WM_T_PCH_LPT, /* PCH LPT LAN (I21[78]) */ -#endif } wm_chip_type; typedef enum {