> 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
> 
> 

Reply via email to