> Date: Wed, 20 Nov 2013 14:45:38 +1100 > From: Jonathan Gray <j...@jsg.id.au> > > On Tue, Nov 19, 2013 at 01:09:32AM +1100, Jonathan Gray wrote: > > On Sat, Nov 16, 2013 at 10:42:05AM +0100, Markus Hennecke wrote: > > > On Sat, 9 Nov 2013, Jonathan Gray wrote: > > > > > > > This adds the initial bits for the i217/i218 PHY and the > > > > Lynx Point PCH found in Haswell systems. > > > > > > > > Doesn't include the new workarounds yet and follows > > > > the pch2/82579 paths for now but this seems to be enough > > > > to make a desktop machine with I217-LM work > > > > > > This fails for the I217-V with an EEPROM invalid checksum error: > > > > Here is a revised diff with different eeprom bank logic > > from FreeBSD as suggested by Masanobu SAITOH: > > And here is a version that should fix gigabit autoneg:
Time to get this tested on all other em(4) types. > Index: if_em.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/if_em.c,v > retrieving revision 1.271 > diff -u -p -r1.271 if_em.c > --- if_em.c 15 Nov 2013 14:53:03 -0000 1.271 > +++ if_em.c 16 Nov 2013 09:35:41 -0000 > @@ -130,6 +130,10 @@ const struct pci_matchid em_devices[] = > { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82578DM }, > { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82579LM }, > { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82579V }, > + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I217_LM }, > + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I217_V }, > + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I218_LM }, > + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_I218_V }, > { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_COPPER }, > { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_FIBER }, > { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_SERDES }, > @@ -788,6 +792,7 @@ em_init(void *arg) > break; > case em_pchlan: > case em_pch2lan: > + case em_pch_lpt: > pba = E1000_PBA_26K; > break; > default: > @@ -1626,7 +1631,8 @@ em_allocate_pci_resources(struct em_soft > sc->hw.mac_type == em_ich9lan || > sc->hw.mac_type == em_ich10lan || > sc->hw.mac_type == em_pchlan || > - sc->hw.mac_type == em_pch2lan) { > + sc->hw.mac_type == em_pch2lan || > + sc->hw.mac_type == em_pch_lpt) { > val = pci_conf_read(pa->pa_pc, pa->pa_tag, EM_FLASH); > if (PCI_MAPREG_TYPE(val) != PCI_MAPREG_TYPE_MEM) { > printf(": flash is not mem space\n"); > Index: if_em_hw.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/if_em_hw.c,v > retrieving revision 1.73 > diff -u -p -r1.73 if_em_hw.c > --- if_em_hw.c 7 Aug 2013 01:06:34 -0000 1.73 > +++ if_em_hw.c 20 Nov 2013 03:32:03 -0000 > @@ -179,6 +179,7 @@ int32_t em_get_pcs_speed_and_duplex_825 > uint16_t *); > int32_t em_set_eee_i350(struct em_hw *); > int32_t em_set_eee_pchlan(struct em_hw *); > +int32_t em_valid_nvm_bank_detect_ich8lan(struct em_hw *, > uint32_t *); > > > /* IGP cable length table */ > @@ -255,6 +256,9 @@ em_set_phy_type(struct em_hw *hw) > case I82579_E_PHY_ID: > hw->phy_type = em_phy_82579; > break; > + case I217_E_PHY_ID: > + hw->phy_type = em_phy_i217; > + break; > case I82580_I_PHY_ID: > case I350_I_PHY_ID: > hw->phy_type = em_phy_82580; > @@ -568,6 +572,12 @@ em_set_mac_type(struct em_hw *hw) > case E1000_DEV_ID_PCH2_LV_V: > hw->mac_type = em_pch2lan; > break; > + case E1000_DEV_ID_PCH_LPT_I217_LM: > + case E1000_DEV_ID_PCH_LPT_I217_V: > + case E1000_DEV_ID_PCH_LPTLP_I218_LM: > + case E1000_DEV_ID_PCH_LPTLP_I218_V: > + hw->mac_type = em_pch_lpt; > + break; > case E1000_DEV_ID_EP80579_LAN_1: > hw->mac_type = em_icp_xxxx; > hw->icp_xxxx_port_num = 0; > @@ -591,6 +601,7 @@ em_set_mac_type(struct em_hw *hw) > case em_ich10lan: > case em_pchlan: > case em_pch2lan: > + case em_pch_lpt: > hw->swfwhw_semaphore_present = TRUE; > hw->asf_firmware_present = TRUE; > break; > @@ -682,6 +693,7 @@ em_set_media_type(struct em_hw *hw) > case em_ich10lan: > case em_pchlan: > case em_pch2lan: > + case em_pch_lpt: > case em_82573: > case em_82574: > /* > @@ -838,6 +850,7 @@ em_reset_hw(struct em_hw *hw) > case em_ich10lan: > case em_pchlan: > case em_pch2lan: > + case em_pch_lpt: > if (!hw->phy_reset_disable && > em_check_phy_reset_block(hw) == E1000_SUCCESS) { > /* > @@ -973,7 +986,8 @@ em_reset_hw(struct em_hw *hw) > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > uint32_t kab = E1000_READ_REG(hw, KABGTXD); > kab |= E1000_KABGTXD_BGSQLBIAS; > E1000_WRITE_REG(hw, KABGTXD, kab); > @@ -1089,6 +1103,7 @@ em_initialize_hardware_bits(struct em_hw > case em_ich10lan: > case em_pchlan: > case em_pch2lan: > + case em_pch_lpt: > if (hw->mac_type == em_ich8lan) > /* Set TARC0 bits 29 and 28 */ > reg_tarc0 |= 0x30000000; > @@ -1162,7 +1177,8 @@ em_init_hw(struct em_hw *hw) > } > > if (hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > /* > * The MAC-PHY interconnect may still be in SMBus mode > * after Sx->S0. Toggle the LANPHYPC Value bit to force > @@ -1224,7 +1240,8 @@ em_init_hw(struct em_hw *hw) > hw->mac_type != em_ich9lan && > hw->mac_type != em_ich10lan && > hw->mac_type != em_pchlan && > - hw->mac_type != em_pch2lan) { > + hw->mac_type != em_pch2lan && > + hw->mac_type != em_pch_lpt) { > if (hw->mac_type < em_82545_rev_3) > E1000_WRITE_REG(hw, VET, 0); > if (hw->mac_type == em_i350) > @@ -1261,7 +1278,8 @@ em_init_hw(struct em_hw *hw) > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) > mta_size = E1000_MC_TBL_SIZE_ICH8LAN; > for (i = 0; i < mta_size; i++) { > E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); > @@ -1319,7 +1337,8 @@ em_init_hw(struct em_hw *hw) > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) > msec_delay(15); > > /* > @@ -1383,6 +1402,7 @@ em_init_hw(struct em_hw *hw) > case em_ich10lan: > case em_pchlan: > case em_pch2lan: > + case em_pch_lpt: > ctrl = E1000_READ_REG(hw, TXDCTL1); > ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | > E1000_TXDCTL_FULL_TX_DESC_WB; > @@ -1410,7 +1430,8 @@ em_init_hw(struct em_hw *hw) > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > if (hw->mac_type == em_ich8lan) > snoop = PCI_EX_82566_SNOOP_ALL; > else > @@ -1517,6 +1538,7 @@ em_setup_link(struct em_hw *hw) > case em_ich10lan: > case em_pchlan: > case em_pch2lan: > + case em_pch_lpt: > case em_82573: > case em_82574: > hw->fc = E1000_FC_FULL; > @@ -1609,7 +1631,8 @@ em_setup_link(struct em_hw *hw) > hw->mac_type != em_ich9lan && > hw->mac_type != em_ich10lan && > hw->mac_type != em_pchlan && > - hw->mac_type != em_pch2lan) { > + hw->mac_type != em_pch2lan && > + hw->mac_type != em_pch_lpt) { > E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE); > E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH); > E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW); > @@ -1618,7 +1641,8 @@ em_setup_link(struct em_hw *hw) > > if (hw->phy_type == em_phy_82577 || > hw->phy_type == em_phy_82578 || > - hw->phy_type == em_phy_82579) { > + hw->phy_type == em_phy_82579 || > + hw->phy_type == em_phy_i217) { > E1000_WRITE_REG(hw, FCRTV_PCH, 0x1000); > em_write_phy_reg(hw, PHY_REG(BM_PORT_CTRL_PAGE, 27), > hw->fc_pause_time); > @@ -1969,7 +1993,8 @@ em_copper_link_igp_setup(struct em_hw *h > } > /* disable lplu d0 during driver init */ > if (hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) > ret_val = em_set_lplu_state_pchlan(hw, FALSE); > else > ret_val = em_set_d0_lplu_state(hw, FALSE); > @@ -2240,7 +2265,8 @@ em_copper_link_mgp_setup(struct em_hw *h > > /* disable lplu d0 during driver init */ > if (hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) > ret_val = em_set_lplu_state_pchlan(hw, FALSE); > > /* Enable CRS on TX. This must be set for half-duplex operation. */ > @@ -2582,6 +2608,7 @@ em_setup_copper_link(struct em_hw *hw) > case em_ich10lan: > case em_pchlan: > case em_pch2lan: > + case em_pch_lpt: > /* > * Set the mac to wait the maximum time between each > * iteration and increase the max iterations when polling the > @@ -2641,7 +2668,8 @@ em_setup_copper_link(struct em_hw *hw) > if (ret_val) > return ret_val; > } else if (hw->phy_type == em_phy_82577 || > - hw->phy_type == em_phy_82579) { > + hw->phy_type == em_phy_82579 || > + hw->phy_type == em_phy_i217) { > ret_val = em_copper_link_82577_setup(hw); > if (ret_val) > return ret_val; > @@ -3692,7 +3720,8 @@ em_check_for_link(struct em_hw *hw) > em_check_downshift(hw); > > /* Enable/Disable EEE after link up */ > - if (hw->mac_type == em_pch2lan) { > + if (hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > ret_val = em_set_eee_pchlan(hw); > if (ret_val) > return ret_val; > @@ -4476,7 +4505,8 @@ em_read_phy_reg(struct em_hw *hw, uint32 > DEBUGFUNC("em_read_phy_reg"); > > if (hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) > return (em_access_phy_reg_hv(hw, reg_addr, phy_data, TRUE)); > > if (((hw->mac_type == em_80003es2lan) || (hw->mac_type == em_82575)) && > @@ -4589,7 +4619,7 @@ em_read_phy_reg_ex(struct em_hw *hw, uin > } > *phy_data = (uint16_t) mdic; > > - if (hw->mac_type == em_pch2lan) > + if (hw->mac_type == em_pch2lan || hw->mac_type == em_pch_lpt) > usec_delay(100); > } else { > /* > @@ -4639,7 +4669,8 @@ em_write_phy_reg(struct em_hw *hw, uint3 > DEBUGFUNC("em_write_phy_reg"); > > if (hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) > return (em_access_phy_reg_hv(hw, reg_addr, &phy_data, FALSE)); > > if (em_swfw_sync_acquire(hw, hw->swfw)) > @@ -4739,7 +4770,7 @@ em_write_phy_reg_ex(struct em_hw *hw, ui > return -E1000_ERR_PHY; > } > > - if (hw->mac_type == em_pch2lan) > + if (hw->mac_type == em_pch2lan || hw->mac_type == em_pch_lpt) > usec_delay(100); > } else { > /* > @@ -4918,14 +4949,14 @@ em_oem_bits_config_pchlan(struct em_hw * > uint16_t oem_reg; > uint16_t swfw = E1000_SWFW_PHY0_SM; > > - if ((hw->mac_type != em_pchlan) && (hw->mac_type != em_pch2lan)) > + if (hw->mac_type < em_pchlan) > return ret_val; > > ret_val = em_swfw_sync_acquire(hw, swfw); > if (ret_val) > return ret_val; > > - if (hw->mac_type != em_pch2lan) { > + if (hw->mac_type == em_pchlan) { > mac_reg = E1000_READ_REG(hw, EXTCNF_CTRL); > if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) > goto out; > @@ -5019,31 +5050,30 @@ em_phy_reset(struct em_hw *hw) > /* Allow time for h/w to get to a quiescent state after reset */ > msec_delay(10); > > - if (hw->phy_type == em_phy_igp || hw->phy_type == em_phy_igp_2) { > + if (hw->phy_type == em_phy_igp || hw->phy_type == em_phy_igp_2) > em_phy_init_script(hw); > - } else if (hw->mac_type == em_pchlan) { > - ret_val = em_hv_phy_workarounds_ich8lan(hw); > - if (ret_val) > - return ret_val; > > - ret_val = em_oem_bits_config_pchlan(hw, TRUE); > + if (hw->mac_type == em_pchlan) { > + ret_val = em_hv_phy_workarounds_ich8lan(hw); > if (ret_val) > return ret_val; > - > } else if (hw->mac_type == em_pch2lan) { > ret_val = em_lv_phy_workarounds_ich8lan(hw); > if (ret_val) > return ret_val; > - > + } > + > + if (hw->mac_type >= em_pchlan) { > ret_val = em_oem_bits_config_pchlan(hw, TRUE); > if (ret_val) > return ret_val; > + } > > - /* Ungate automatic PHY configuration on non-managed 82579 */ > - if (!(E1000_READ_REG(hw, FWSM) & E1000_FWSM_FW_VALID)) { > - msec_delay(10); > - em_gate_hw_phy_config_ich8lan(hw, FALSE); > - } > + /* Ungate automatic PHY configuration on non-managed 82579 */ > + if ((hw->mac_type == em_pch2lan) && > + !(E1000_READ_REG(hw, FWSM) & E1000_FWSM_FW_VALID)) { > + msec_delay(10); > + em_gate_hw_phy_config_ich8lan(hw, FALSE); > } > > return E1000_SUCCESS; > @@ -5215,6 +5245,10 @@ em_match_gig_phy(struct em_hw *hw) > if (hw->phy_id == I82579_E_PHY_ID) > match = TRUE; > break; > + case em_pch_lpt: > + if (hw->phy_id == I217_E_PHY_ID) > + match = TRUE; > + break; > case em_icp_xxxx: > if (hw->phy_id == M88E1141_E_PHY_ID) > match = TRUE; > @@ -5495,6 +5529,7 @@ em_init_eeprom_params(struct em_hw *hw) > case em_ich10lan: > case em_pchlan: > case em_pch2lan: > + case em_pch_lpt: > { > int32_t i = 0; > uint32_t flash_size = > @@ -6119,7 +6154,8 @@ em_is_onboard_nvm_eeprom(struct em_hw *h > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) > return FALSE; > > if ((hw->mac_type == em_82573) || (hw->mac_type == em_82574)) { > @@ -6184,17 +6220,31 @@ em_validate_eeprom_checksum(struct em_hw > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > + uint16_t word; > + uint16_t valid_csum_mask; > + > /* > * Drivers must allocate the shadow ram structure for the > * EEPROM checksum to be updated. Otherwise, this bit as > * well as the checksum must both be set correctly for this > * validation to pass. > */ > - em_read_eeprom(hw, 0x19, 1, &eeprom_data); > - if ((eeprom_data & 0x40) == 0) { > - eeprom_data |= 0x40; > - em_write_eeprom(hw, 0x19, 1, &eeprom_data); > + switch (hw->mac_type) { > + case em_pch_lpt: > + word = EEPROM_COMPAT; > + valid_csum_mask = EEPROM_COMPAT_VALID_CSUM; > + break; > + default: > + word = EEPROM_FUTURE_INIT_WORD1; > + valid_csum_mask = EEPROM_FUTURE_INIT_WORD1_VALID_CSUM; > + break; > + } > + em_read_eeprom(hw, word, 1, &eeprom_data); > + if ((eeprom_data & valid_csum_mask) == 0) { > + eeprom_data |= valid_csum_mask; > + em_write_eeprom(hw, word, 1, &eeprom_data); > em_update_eeprom_checksum(hw); > } > } > @@ -6602,7 +6652,7 @@ em_commit_shadow_ram(struct em_hw *hw) > * in progress > */ > if (i == E1000_ICH_NVM_SIG_WORD) > - high_byte = E1000_ICH_NVM_SIG_MASK | > + high_byte = > E1000_ICH_NVM_VALID_SIG_MASK | > high_byte; > > error = em_verify_write_ich8_byte(hw, (i << 1) > @@ -6771,7 +6821,8 @@ em_init_rx_addrs(struct em_hw *hw) > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) > rar_num = E1000_RAR_ENTRIES_ICH8LAN; > if (hw->mac_type == em_ich8lan) > rar_num -= 1; > @@ -6826,7 +6877,8 @@ em_mc_addr_list_update(struct em_hw *hw, > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) > num_rar_entry = E1000_RAR_ENTRIES_ICH8LAN; > if (hw->mac_type == em_ich8lan) > num_rar_entry -= 1; > @@ -6852,7 +6904,8 @@ em_mc_addr_list_update(struct em_hw *hw, > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) > num_mta_entry = E1000_NUM_MTA_REGISTERS_ICH8LAN; > > for (i = 0; i < num_mta_entry; i++) { > @@ -6915,7 +6968,8 @@ em_hash_mc_addr(struct em_hw *hw, uint8_ > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > /* [47:38] i.e. 0x158 for above example address */ > hash_value = ((mc_addr[4] >> 6) | > (((uint16_t) mc_addr[5]) << 2)); > @@ -6930,7 +6984,8 @@ em_hash_mc_addr(struct em_hw *hw, uint8_ > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > /* [46:37] i.e. 0x2B1 for above example address */ > hash_value = ((mc_addr[4] >> 5) | > (((uint16_t) mc_addr[5]) << 3)); > @@ -6945,7 +7000,8 @@ em_hash_mc_addr(struct em_hw *hw, uint8_ > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > /* [45:36] i.e. 0x163 for above example address */ > hash_value = ((mc_addr[4] >> 4) | > (((uint16_t) mc_addr[5]) << 4)); > @@ -6960,7 +7016,8 @@ em_hash_mc_addr(struct em_hw *hw, uint8_ > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > /* [43:34] i.e. 0x18D for above example address */ > hash_value = ((mc_addr[4] >> 2) | > (((uint16_t) mc_addr[5]) << 6)); > @@ -6977,7 +7034,8 @@ em_hash_mc_addr(struct em_hw *hw, uint8_ > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) > hash_value &= 0x3FF; > > return hash_value; > @@ -7009,7 +7067,8 @@ em_mta_set(struct em_hw *hw, uint32_t ha > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) > hash_reg &= 0x1F; > > hash_bit = hash_value & 0x1F; > @@ -7104,7 +7163,8 @@ em_clear_vfta(struct em_hw *hw) > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) > return; > > if ((hw->mac_type == em_82573) || (hw->mac_type == em_82574)) { > @@ -7259,7 +7319,8 @@ em_clear_hw_cntrs(struct em_hw *hw) > hw->mac_type != em_ich9lan && > hw->mac_type != em_ich10lan && > hw->mac_type != em_pchlan && > - hw->mac_type != em_pch2lan) { > + hw->mac_type != em_pch2lan && > + hw->mac_type != em_pch_lpt) { > temp = E1000_READ_REG(hw, PRC64); > temp = E1000_READ_REG(hw, PRC127); > temp = E1000_READ_REG(hw, PRC255); > @@ -7291,7 +7352,8 @@ em_clear_hw_cntrs(struct em_hw *hw) > hw->mac_type != em_ich9lan && > hw->mac_type != em_ich10lan && > hw->mac_type != em_pchlan && > - hw->mac_type != em_pch2lan) { > + hw->mac_type != em_pch2lan && > + hw->mac_type != em_pch_lpt) { > temp = E1000_READ_REG(hw, PTC64); > temp = E1000_READ_REG(hw, PTC127); > temp = E1000_READ_REG(hw, PTC255); > @@ -7328,7 +7390,8 @@ em_clear_hw_cntrs(struct em_hw *hw) > > if (hw->phy_type == em_phy_82577 || > hw->phy_type == em_phy_82578 || > - hw->phy_type == em_phy_82579) { > + hw->phy_type == em_phy_82579 || > + hw->phy_type == em_phy_i217) { > uint16_t phy_data; > > em_read_phy_reg(hw, HV_SCC_UPPER, &phy_data); > @@ -7351,7 +7414,7 @@ em_clear_hw_cntrs(struct em_hw *hw) > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type != em_pch2lan) > + (hw->mac_type != em_pch2lan && hw->mac_type != em_pch_lpt)) > return; > > temp = E1000_READ_REG(hw, ICRXPTC); > @@ -7491,6 +7554,7 @@ em_get_bus_info(struct em_hw *hw) > case em_ich10lan: > case em_pchlan: > case em_pch2lan: > + case em_pch_lpt: > hw->bus_type = em_bus_type_pci_express; > hw->bus_speed = em_bus_speed_2500; > hw->bus_width = em_bus_width_pciex_1; > @@ -8066,7 +8130,8 @@ em_set_d3_lplu_state(struct em_hw *hw, b > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > /* > * MAC writes into PHY register based on the state transition > * and start auto-negotiation. SW driver can overwrite the > @@ -8093,7 +8158,8 @@ em_set_d3_lplu_state(struct em_hw *hw, b > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; > E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl); > } else { > @@ -8149,7 +8215,8 @@ em_set_d3_lplu_state(struct em_hw *hw, b > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; > E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl); > } else { > @@ -8205,7 +8272,8 @@ em_set_d0_lplu_state(struct em_hw *hw, b > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > phy_ctrl = E1000_READ_REG(hw, PHY_CTRL); > } else { > ret_val = em_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, > @@ -8219,7 +8287,8 @@ em_set_d0_lplu_state(struct em_hw *hw, b > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; > E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl); > } else { > @@ -8263,7 +8332,8 @@ em_set_d0_lplu_state(struct em_hw *hw, b > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; > E1000_WRITE_REG(hw, PHY_CTRL, phy_ctrl); > } else { > @@ -8456,7 +8526,8 @@ em_check_mng_mode(struct em_hw *hw) > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > if ((fwsm & E1000_FWSM_MODE_MASK) == > (E1000_MNG_ICH_IAMT_MODE << E1000_FWSM_MODE_SHIFT)) > return TRUE; > @@ -8705,6 +8776,7 @@ em_get_auto_rd_done(struct em_hw *hw) > case em_ich10lan: > case em_pchlan: > case em_pch2lan: > + case em_pch_lpt: > while (timeout) { > if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) > break; > @@ -8944,7 +9016,8 @@ em_check_phy_reset_block(struct em_hw *h > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > fwsm = E1000_READ_REG(hw, FWSM); > return (fwsm & E1000_FWSM_RSPCIPHY) ? E1000_SUCCESS : > E1000_BLK_PHY_RESET; > @@ -8986,7 +9059,8 @@ em_set_pci_ex_no_snoop(struct em_hw *hw, > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > uint32_t ctrl_ext; > ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); > ctrl_ext |= E1000_CTRL_EXT_RO_DIS; > @@ -9015,7 +9089,8 @@ em_get_software_flag(struct em_hw *hw) > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > while (timeout) { > extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL); > extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; > @@ -9055,7 +9130,8 @@ em_release_software_flag(struct em_hw *h > hw->mac_type == em_ich9lan || > hw->mac_type == em_ich10lan || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) { > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) { > extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL); > extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; > E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl); > @@ -9063,6 +9139,72 @@ em_release_software_flag(struct em_hw *h > return; > } > > +/** > + * em_valid_nvm_bank_detect_ich8lan - finds out the valid bank 0 or 1 > + * @hw: pointer to the HW structure > + * @bank: pointer to the variable that returns the active bank > + * > + * Reads signature byte from the NVM using the flash access registers. > + * Word 0x13 bits 15:14 = 10b indicate a valid signature for that bank. > + **/ > +int32_t > +em_valid_nvm_bank_detect_ich8lan(struct em_hw *hw, uint32_t *bank) > +{ > + uint32_t eecd; > + uint32_t bank1_offset = hw->flash_bank_size * sizeof(uint16_t); > + uint32_t act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1; > + uint8_t sig_byte = 0; > + int32_t ret_val; > + > + DEBUGFUNC("em_valid_nvm_bank_detect_ich8lan"); > + > + switch (hw->mac_type) { > + case em_ich8lan: > + case em_ich9lan: > + eecd = E1000_READ_REG(hw, EECD); > + if ((eecd & E1000_EECD_SEC1VAL_VALID_MASK) == > + E1000_EECD_SEC1VAL_VALID_MASK) { > + if (eecd & E1000_EECD_SEC1VAL) > + *bank = 1; > + else > + *bank = 0; > + > + return E1000_SUCCESS; > + } > + DEBUGOUT("Unable to determine valid NVM bank via EEC - reading > flash signature\n"); > + /* fall-thru */ > + default: > + /* set bank to 0 in case flash read fails */ > + *bank = 0; > + > + /* Check bank 0 */ > + ret_val = em_read_ich8_byte(hw, act_offset, > + &sig_byte); > + if (ret_val) > + return ret_val; > + if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == > + E1000_ICH_NVM_SIG_VALUE) { > + *bank = 0; > + return E1000_SUCCESS; > + } > + > + /* Check bank 1 */ > + ret_val = em_read_ich8_byte(hw, act_offset + > + bank1_offset, > + &sig_byte); > + if (ret_val) > + return ret_val; > + if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == > + E1000_ICH_NVM_SIG_VALUE) { > + *bank = 1; > + return E1000_SUCCESS; > + } > + > + DEBUGOUT("ERROR: No valid NVM bank present\n"); > + return -1; > + } > +} > + > > /****************************************************************************** > * Reads a 16 bit word or words from the EEPROM using the ICH8's flash access > * register. > @@ -9088,18 +9230,23 @@ em_read_eeprom_ich8(struct em_hw *hw, ui > * flash_bank. So it cannot be trusted and needs to be updated with > * each read. > */ > - /* Value of bit 22 corresponds to the flash bank we're on. */ > - flash_bank = (E1000_READ_REG(hw, EECD) & E1000_EECD_SEC1VAL) ? 1 : 0; > + > + error = em_get_software_flag(hw); > + if (error != E1000_SUCCESS) > + return error; > + > + error = em_valid_nvm_bank_detect_ich8lan(hw, &flash_bank); > + if (error != E1000_SUCCESS) { > + DEBUGOUT("Could not detect valid bank, assuming bank 0\n"); > + flash_bank = 0; > + } > + > /* > * Adjust offset appropriately if we're on bank 1 - adjust for word > * size > */ > bank_offset = flash_bank * (hw->flash_bank_size * 2); > > - error = em_get_software_flag(hw); > - if (error != E1000_SUCCESS) > - return error; > - > for (i = 0; i < words; i++) { > if (hw->eeprom_shadow_ram != NULL && > hw->eeprom_shadow_ram[offset + i].modified == TRUE) { > @@ -9744,7 +9891,8 @@ em_init_lcd_from_nvm(struct em_hw *hw) > if (hw->device_id == E1000_DEV_ID_ICH8_IGP_M_AMT || > hw->device_id == E1000_DEV_ID_ICH8_IGP_M || > hw->mac_type == em_pchlan || > - hw->mac_type == em_pch2lan) > + hw->mac_type == em_pch2lan || > + hw->mac_type == em_pch_lpt) > sw_cfg_mask = FEXTNVM_SW_CONFIG_ICH8M; > else > sw_cfg_mask = FEXTNVM_SW_CONFIG; > @@ -10321,7 +10469,8 @@ em_set_eee_pchlan(struct em_hw *hw) > > DEBUGFUNC("em_set_eee_pchlan"); > > - if (hw->phy_type != em_phy_82579) > + if (hw->phy_type != em_phy_82579 && > + hw->phy_type != em_phy_i217) > goto out; > > ret_val = em_read_phy_reg(hw, I82579_LPI_CTRL, &phy_reg); > Index: if_em_hw.h > =================================================================== > RCS file: /cvs/src/sys/dev/pci/if_em_hw.h,v > retrieving revision 1.54 > diff -u -p -r1.54 if_em_hw.h > --- if_em_hw.h 26 Nov 2012 01:17:41 -0000 1.54 > +++ if_em_hw.h 18 Nov 2013 13:37:19 -0000 > @@ -78,6 +78,7 @@ typedef enum { > em_ich10lan, > em_pchlan, > em_pch2lan, > + em_pch_lpt, > em_num_macs > } em_mac_type; > > @@ -242,6 +243,7 @@ typedef enum { > em_phy_82577, > em_phy_82578, > em_phy_82579, > + em_phy_i217, > em_phy_82580, > em_phy_undefined = 0xFF > } em_phy_type; > @@ -536,6 +538,10 @@ int32_t em_check_phy_reset_block(struct > #define E1000_DEV_ID_PCH_D_HV_DC 0x10F0 > #define E1000_DEV_ID_PCH2_LV_LM 0x1502 > #define E1000_DEV_ID_PCH2_LV_V 0x1503 > +#define E1000_DEV_ID_PCH_LPT_I217_LM 0x153A > +#define E1000_DEV_ID_PCH_LPT_I217_V 0x153B > +#define E1000_DEV_ID_PCH_LPTLP_I218_LM 0x155A > +#define E1000_DEV_ID_PCH_LPTLP_I218_V 0x1559 > #define E1000_DEV_ID_82575EB_PT 0x10A7 > #define E1000_DEV_ID_82575EB_PF 0x10A9 > #define E1000_DEV_ID_82575GB_QP 0x10D6 > @@ -1698,13 +1704,16 @@ struct em_hw { > #define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */ > #define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */ > #define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */ > +#define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | > E1000_EECD_PRES) > #define E1000_EECD_SECVAL_SHIFT 22 > #define E1000_STM_OPCODE 0xDB00 > #define E1000_HICR_FW_RESET 0xC0 > > -#define E1000_SHADOW_RAM_WORDS 2048 > -#define E1000_ICH_NVM_SIG_WORD 0x13 > -#define E1000_ICH_NVM_SIG_MASK 0xC0 > +#define E1000_SHADOW_RAM_WORDS 2048 > +#define E1000_ICH_NVM_SIG_WORD 0x13 > +#define E1000_ICH_NVM_SIG_MASK 0xC000 > +#define E1000_ICH_NVM_VALID_SIG_MASK 0xC0 > +#define E1000_ICH_NVM_SIG_VALUE 0x80 > > /* EEPROM Read */ > #define E1000_EERD_START 0x00000001 /* Start Read */ > @@ -2443,6 +2452,10 @@ struct em_host_command_info { > #define EEPROM_FLASH_VERSION 0x0032 > #define EEPROM_CHECKSUM_REG 0x003F > > +#define EEPROM_COMPAT_VALID_CSUM 0x0001 > +#define EEPROM_FUTURE_INIT_WORD1 0x0019 > +#define EEPROM_FUTURE_INIT_WORD1_VALID_CSUM 0x0040 > + > #define E1000_NVM_CFG_DONE_PORT_0 0x040000 /* MNG config cycle done */ > #define E1000_NVM_CFG_DONE_PORT_1 0x080000 /* ...for second port */ > #define E1000_NVM_CFG_DONE_PORT_2 0x100000 /* ...for third port */ > @@ -3360,6 +3373,7 @@ struct em_host_command_info { > #define I82577_E_PHY_ID 0x01540050 > #define I82578_E_PHY_ID 0x004DD040 > #define I82579_E_PHY_ID 0x01540090 > +#define I217_E_PHY_ID 0x015400A0 > #define I82580_I_PHY_ID 0x015403A0 > #define I350_I_PHY_ID 0x015403B0 > #define IGP04E1000_E_PHY_ID 0x02A80391 > >