Module Name: src Committed By: msaitoh Date: Sat May 16 22:41:59 UTC 2015
Modified Files: src/sys/dev/pci: if_wm.c if_wmreg.h if_wmvar.h Log Message: Add support iNVM (integrated Non-Volatile Memory) for I21[01]. This change fixes a bug that a MAC address is wrongly set on iNVM machines and NICs. Tested with Shuttle DS57U(iNVM based) and other non iNVM based I210 machines. To generate a diff of this commit: cvs rdiff -u -r1.320 -r1.321 src/sys/dev/pci/if_wm.c cvs rdiff -u -r1.70 -r1.71 src/sys/dev/pci/if_wmreg.h cvs rdiff -u -r1.23 -r1.24 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.320 src/sys/dev/pci/if_wm.c:1.321 --- src/sys/dev/pci/if_wm.c:1.320 Mon May 4 10:10:42 2015 +++ src/sys/dev/pci/if_wm.c Sat May 16 22:41:59 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wm.c,v 1.320 2015/05/04 10:10:42 msaitoh Exp $ */ +/* $NetBSD: if_wm.c,v 1.321 2015/05/16 22:41:59 msaitoh Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -81,7 +81,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.320 2015/05/04 10:10:42 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.321 2015/05/16 22:41:59 msaitoh Exp $"); #ifdef _KERNEL_OPT #include "opt_net_mpsafe.h" @@ -667,10 +667,14 @@ static int32_t wm_read_ich8_data(struct static int32_t wm_read_ich8_byte(struct wm_softc *, uint32_t, uint8_t *); static int32_t wm_read_ich8_word(struct wm_softc *, uint32_t, uint16_t *); static int wm_nvm_read_ich8(struct wm_softc *, int, int, uint16_t *); +/* iNVM */ +static int wm_nvm_read_word_invm(struct wm_softc *, uint16_t, uint16_t *); +static int wm_nvm_read_invm(struct wm_softc *, int, int, uint16_t *); /* Lock, detecting NVM type, validate checksum and read */ static int wm_nvm_acquire(struct wm_softc *); static void wm_nvm_release(struct wm_softc *); static int wm_nvm_is_onboard_eeprom(struct wm_softc *); +static int wm_nvm_get_flash_presence_i210(struct wm_softc *); static int wm_nvm_validate_checksum(struct wm_softc *); static int wm_nvm_read(struct wm_softc *, int, int, uint16_t *); @@ -1841,9 +1845,15 @@ wm_attach(device_t parent, device_t self break; case WM_T_I210: case WM_T_I211: - wm_nvm_set_addrbits_size_eecd(sc); - sc->sc_flags |= WM_F_EEPROM_FLASH_HW; - sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_LOCK_SWFW; + if (wm_nvm_get_flash_presence_i210(sc)) { + wm_nvm_set_addrbits_size_eecd(sc); + sc->sc_flags |= WM_F_EEPROM_FLASH_HW; + sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_LOCK_SWFW; + } else { + sc->sc_nvm_wordsize = INVM_SIZE; + sc->sc_flags |= WM_F_EEPROM_INVM; + sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_LOCK_SWFW; + } break; default: break; @@ -1903,11 +1913,13 @@ wm_attach(device_t parent, device_t self else { aprint_verbose_dev(sc->sc_dev, "%u words ", sc->sc_nvm_wordsize); - if (sc->sc_flags & WM_F_EEPROM_FLASH_HW) { + if (sc->sc_flags & WM_F_EEPROM_INVM) + aprint_verbose("iNVM\n"); + else if (sc->sc_flags & WM_F_EEPROM_FLASH_HW) aprint_verbose("FLASH(HW)\n"); - } else if (sc->sc_flags & WM_F_EEPROM_FLASH) { + else if (sc->sc_flags & WM_F_EEPROM_FLASH) aprint_verbose("FLASH\n"); - } else { + else { if (sc->sc_flags & WM_F_EEPROM_SPI) eetype = "SPI"; else @@ -8568,6 +8580,102 @@ wm_nvm_read_ich8(struct wm_softc *sc, in return error; } +/* iNVM */ + +static int +wm_nvm_read_word_invm(struct wm_softc *sc, uint16_t address, uint16_t *data) +{ + int32_t rv = 0; + uint32_t invm_dword; + uint16_t i; + uint8_t record_type, word_address; + + for (i = 0; i < INVM_SIZE; i++) { + invm_dword = CSR_READ(sc, E1000_INVM_DATA_REG(i)); + /* Get record type */ + record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword); + if (record_type == INVM_UNINITIALIZED_STRUCTURE) + break; + if (record_type == INVM_CSR_AUTOLOAD_STRUCTURE) + i += INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS; + if (record_type == INVM_RSA_KEY_SHA256_STRUCTURE) + i += INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS; + if (record_type == INVM_WORD_AUTOLOAD_STRUCTURE) { + word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword); + if (word_address == address) { + *data = INVM_DWORD_TO_WORD_DATA(invm_dword); + rv = 0; + break; + } + } + } + + return rv; +} + +static int +wm_nvm_read_invm(struct wm_softc *sc, int offset, int words, uint16_t *data) +{ + int rv = 0; + int i; + + for (i = 0; i < words; i++) { + switch (offset + i) { + case NVM_OFF_MACADDR: + case NVM_OFF_MACADDR1: + case NVM_OFF_MACADDR2: + rv = wm_nvm_read_word_invm(sc, offset + i, &data[i]); + if (rv != 0) { + data[i] = 0xffff; + rv = -1; + } + break; + case NVM_OFF_CFG2: + rv = wm_nvm_read_word_invm(sc, offset, data); + if (rv != 0) { + *data = NVM_INIT_CTRL_2_DEFAULT_I211; + rv = 0; + } + break; + case NVM_OFF_CFG4: + rv = wm_nvm_read_word_invm(sc, offset, data); + if (rv != 0) { + *data = NVM_INIT_CTRL_4_DEFAULT_I211; + rv = 0; + } + break; + case NVM_OFF_LED_1_CFG: + rv = wm_nvm_read_word_invm(sc, offset, data); + if (rv != 0) { + *data = NVM_LED_1_CFG_DEFAULT_I211; + rv = 0; + } + break; + case NVM_OFF_LED_0_2_CFG: + rv = wm_nvm_read_word_invm(sc, offset, data); + if (rv != 0) { + *data = NVM_LED_0_2_CFG_DEFAULT_I211; + rv = 0; + } + break; + case NVM_OFF_ID_LED_SETTINGS: + rv = wm_nvm_read_word_invm(sc, offset, data); + if (rv != 0) { + *data = ID_LED_RESERVED_FFFF; + rv = 0; + } + break; + default: + DPRINTF(WM_DEBUG_NVM, + ("NVM word 0x%02x is not mapped.\n", offset)); + *data = NVM_RESERVED_WORD; + break; + } + } + + return rv; +} + /* Lock, detecting NVM type, validate checksum and read */ /* @@ -8680,6 +8788,18 @@ wm_nvm_is_onboard_eeprom(struct wm_softc return 1; } +static int +wm_nvm_get_flash_presence_i210(struct wm_softc *sc) +{ + uint32_t eec; + + eec = CSR_READ(sc, WMREG_EEC); + if ((eec & EEC_FLASH_DETECTED) != 0) + return 1; + + return 0; +} + /* * wm_nvm_validate_checksum * @@ -8773,6 +8893,8 @@ wm_nvm_read(struct wm_softc *sc, int wor || (sc->sc_type == WM_T_ICH10) || (sc->sc_type == WM_T_PCH) || (sc->sc_type == WM_T_PCH2) || (sc->sc_type == WM_T_PCH_LPT)) rv = wm_nvm_read_ich8(sc, word, wordcnt, data); + else if (sc->sc_flags & WM_F_EEPROM_INVM) + rv = wm_nvm_read_invm(sc, word, wordcnt, data); else if (sc->sc_flags & WM_F_EEPROM_EERDEEWR) rv = wm_nvm_read_eerd(sc, word, wordcnt, data); else if (sc->sc_flags & WM_F_EEPROM_SPI) Index: src/sys/dev/pci/if_wmreg.h diff -u src/sys/dev/pci/if_wmreg.h:1.70 src/sys/dev/pci/if_wmreg.h:1.71 --- src/sys/dev/pci/if_wmreg.h:1.70 Fri May 15 07:59:00 2015 +++ src/sys/dev/pci/if_wmreg.h Sat May 16 22:41:59 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmreg.h,v 1.70 2015/05/15 07:59:00 msaitoh Exp $ */ +/* $NetBSD: if_wmreg.h,v 1.71 2015/05/16 22:41:59 msaitoh Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -891,6 +891,11 @@ struct livengood_tcpip_ctxdesc { #define WMREG_CRC_OFFSET 0x5f50 +#define WMREG_EEC 0x12010 +#define EEC_FLASH_DETECTED (1U << 19) /* FLASH */ +#define EEC_FLUPD (1U << 23) /* Update FLASH */ + + /* * NVM related values. * Microwire, SPI, and flash @@ -918,15 +923,21 @@ struct livengood_tcpip_ctxdesc { #define NVM_SIZE 0x0040 #define NVM_WORD_SIZE_BASE_SHIFT 6 -#define NVM_OFF_MACADDR 0x0000 /* MAC address offset */ +#define NVM_OFF_MACADDR 0x0000 /* MAC address offset 0 */ +#define NVM_OFF_MACADDR1 0x0001 /* MAC address offset 1 */ +#define NVM_OFF_MACADDR2 0x0002 /* MAC address offset 2 */ #define NVM_OFF_COMPAT 0x0003 +#define NVM_OFF_ID_LED_SETTINGS 0x0004 #define NVM_OFF_CFG1 0x000a /* config word 1 */ #define NVM_OFF_CFG2 0x000f /* config word 2 */ #define NVM_OFF_EEPROM_SIZE 0x0012 /* NVM SIZE */ +#define NVM_OFF_CFG4 0x0013 /* config word 4 */ #define NVM_OFF_CFG3_PORTB 0x0014 /* config word 3 */ #define NVM_OFF_FUTURE_INIT_WORD1 0x0019 #define NVM_OFF_INIT_3GIO_3 0x001a /* PCIe Initial Configuration Word 3 */ #define NVM_OFF_K1_CONFIG 0x001b /* NVM K1 Config */ +#define NVM_OFF_LED_1_CFG 0x001c +#define NVM_OFF_LED_0_2_CFG 0x001f #define NVM_OFF_SWDPIN 0x0020 /* SWD Pins (Cordova) */ #define NVM_OFF_CFG3_PORTA 0x0024 /* config word 3 */ #define NVM_OFF_ALT_MAC_ADDR_PTR 0x0037 /* to the alternative MAC addresses */ @@ -989,6 +1000,34 @@ struct livengood_tcpip_ctxdesc { */ #define NVM_OFF_LAN_FUNC_82580(x) ((x) ? (0x40 + (0x40 * (x))) : 0) +/* iNVM Registers for i21[01] */ +#define E1000_INVM_DATA_REG(reg) (0x12120 + 4*(reg)) +#define INVM_SIZE 64 /* Number of INVM Data Registers */ + +/* iNVM default vaule */ +#define NVM_INIT_CTRL_2_DEFAULT_I211 0x7243 +#define NVM_INIT_CTRL_4_DEFAULT_I211 0x00c1 +#define NVM_LED_1_CFG_DEFAULT_I211 0x0184 +#define NVM_LED_0_2_CFG_DEFAULT_I211 0x200c +#define NVM_RESERVED_WORD 0xffff + +#define INVM_DWORD_TO_RECORD_TYPE(dword) ((dword) & 0x7) +#define INVM_DWORD_TO_WORD_ADDRESS(dword) (((dword) & 0x0000FE00) >> 9) +#define INVM_DWORD_TO_WORD_DATA(dword) (((dword) & 0xFFFF0000) >> 16) + +#define INVM_UNINITIALIZED_STRUCTURE 0x0 +#define INVM_WORD_AUTOLOAD_STRUCTURE 0x1 +#define INVM_CSR_AUTOLOAD_STRUCTURE 0x2 +#define INVM_PHY_REGISTER_AUTOLOAD_STRUCTURE 0x3 +#define INVM_RSA_KEY_SHA256_STRUCTURE 0x4 +#define INVM_INVALIDATED_STRUCTURE 0x5 + +#define INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS 8 +#define INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS 1 + +/* Word definitions for ID LED Settings */ +#define ID_LED_RESERVED_FFFF 0xFFFF + /* ich8 flash control */ #define ICH_FLASH_COMMAND_TIMEOUT 5000 /* 5000 uSecs - adjusted */ #define ICH_FLASH_ERASE_TIMEOUT 3000000 /* Up to 3 seconds - worst case */ Index: src/sys/dev/pci/if_wmvar.h diff -u src/sys/dev/pci/if_wmvar.h:1.23 src/sys/dev/pci/if_wmvar.h:1.24 --- src/sys/dev/pci/if_wmvar.h:1.23 Thu Nov 27 11:42:02 2014 +++ src/sys/dev/pci/if_wmvar.h Sat May 16 22:41:59 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmvar.h,v 1.23 2014/11/27 11:42:02 msaitoh Exp $ */ +/* $NetBSD: if_wmvar.h,v 1.24 2015/05/16 22:41:59 msaitoh Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -96,6 +96,7 @@ #define WM_F_WOL 0x00200000 #define WM_F_EEE 0x00400000 /* Energy Efficiency Ethernet */ #define WM_F_ATTACHED 0x00800000 /* attach() finished successfully */ +#define WM_F_EEPROM_INVM 0x01000000 /* NVM is iNVM */ /*