summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsg <jsg@openbsd.org>2013-11-21 14:44:37 +0000
committerjsg <jsg@openbsd.org>2013-11-21 14:44:37 +0000
commit87cf7c02448cd8440a08db3d6260af3c489688b5 (patch)
tree76d8185cd8f2c3a491b9bc3f0d7c377f72fbe788
parentRevert r1.41, in this driver sc_attached does not indicate that the (diff)
downloadwireguard-openbsd-87cf7c02448cd8440a08db3d6260af3c489688b5.tar.xz
wireguard-openbsd-87cf7c02448cd8440a08db3d6260af3c489688b5.zip
Initial support for the integrated Lynx Point and Lynx Point LP Ethernet
with external i217 and i218 PHYs. Requires a changed way of detecting the eeprom flash bank from FreeBSD as suggested by Masanobu SAITOH. Thanks to everyone who tested.
-rw-r--r--sys/dev/pci/if_em.c10
-rw-r--r--sys/dev/pci/if_em_hw.c293
-rw-r--r--sys/dev/pci/if_em_hw.h22
3 files changed, 247 insertions, 78 deletions
diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
index 9720341f9c0..9c597daa793 100644
--- a/sys/dev/pci/if_em.c
+++ b/sys/dev/pci/if_em.c
@@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
-/* $OpenBSD: if_em.c,v 1.271 2013/11/15 14:53:03 deraadt Exp $ */
+/* $OpenBSD: if_em.c,v 1.272 2013/11/21 14:44:37 jsg Exp $ */
/* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */
#include <dev/pci/if_em.h>
@@ -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_softc *sc)
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");
diff --git a/sys/dev/pci/if_em_hw.c b/sys/dev/pci/if_em_hw.c
index b5a3ea3cfed..e2d07933a5f 100644
--- a/sys/dev/pci/if_em_hw.c
+++ b/sys/dev/pci/if_em_hw.c
@@ -31,7 +31,7 @@
*******************************************************************************/
-/* $OpenBSD: if_em_hw.c,v 1.73 2013/08/07 01:06:34 bluhm Exp $ */
+/* $OpenBSD: if_em_hw.c,v 1.74 2013/11/21 14:44:37 jsg Exp $ */
/*
* if_em_hw.c Shared functions for accessing and configuring the MAC
*/
@@ -179,6 +179,7 @@ int32_t em_get_pcs_speed_and_duplex_82575(struct em_hw *, uint16_t *,
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 *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 *hw)
}
/* 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 *hw)
/* 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_t reg_addr, uint16_t *phy_data)
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, uint32_t reg_addr, uint16_t *phy_data)
}
*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, uint32_t reg_addr, uint16_t phy_data)
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, uint32_t reg_addr, uint16_t phy_data)
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 *hw, boolean_t d0_state)
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 *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 FALSE;
if ((hw->mac_type == em_82573) || (hw->mac_type == em_82574)) {
@@ -6184,17 +6220,31 @@ em_validate_eeprom_checksum(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) {
+ 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, uint8_t *mc_addr_list,
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, uint8_t *mc_addr_list,
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_t *mc_addr)
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_t *mc_addr)
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_t *mc_addr)
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_t *mc_addr)
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_t *mc_addr)
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 hash_value)
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, boolean_t active)
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, boolean_t active)
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, boolean_t active)
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, boolean_t active)
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, boolean_t active)
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, boolean_t active)
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 *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) {
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, uint32_t no_snoop)
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 *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) {
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 *hw)
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, uint16_t offset, uint16_t words,
* 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);
diff --git a/sys/dev/pci/if_em_hw.h b/sys/dev/pci/if_em_hw.h
index f6a43de34d1..e4aca62ea85 100644
--- a/sys/dev/pci/if_em_hw.h
+++ b/sys/dev/pci/if_em_hw.h
@@ -31,7 +31,7 @@
*******************************************************************************/
-/* $OpenBSD: if_em_hw.h,v 1.54 2012/11/26 01:17:41 jsg Exp $ */
+/* $OpenBSD: if_em_hw.h,v 1.55 2013/11/21 14:44:37 jsg Exp $ */
/* $FreeBSD: if_em_hw.h,v 1.15 2005/05/26 23:32:02 tackerman Exp $ */
/* if_em_hw.h
@@ -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 em_hw *hw);
#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