⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ich8lan.c

📁 grub源码分析文档
💻 C
📖 第 1 页 / 共 5 页
字号:
	ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, data);	if (ret_val)		return ret_val;	hw_dbg(hw, "IFE PMC: %X\n", data);	udelay(1);	if (phy->autoneg_wait_to_complete) {		hw_dbg(hw, "Waiting for forced speed/duplex link on IFE phy.\n");		ret_val = e1000e_phy_has_link_generic(hw,						     PHY_FORCE_LIMIT,						     100000,						     &link);		if (ret_val)			return ret_val;		if (!link)			hw_dbg(hw, "Link taking longer than expected.\n");		/* Try once more */		ret_val = e1000e_phy_has_link_generic(hw,						     PHY_FORCE_LIMIT,						     100000,						     &link);		if (ret_val)			return ret_val;	}	return 0;}/** *  e1000_phy_hw_reset_ich8lan - Performs a PHY reset *  @hw: pointer to the HW structure * *  Resets the PHY *  This is a function pointer entry point called by drivers *  or other shared routines. **/static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw){	struct e1000_phy_info *phy = &hw->phy;	u32 i;	u32 data, cnf_size, cnf_base_addr, sw_cfg_mask;	s32 ret_val;	u16 loop = E1000_ICH8_LAN_INIT_TIMEOUT;	u16 word_addr, reg_data, reg_addr, phy_page = 0;	ret_val = e1000e_phy_hw_reset_generic(hw);	if (ret_val)		return ret_val;	/*	 * Initialize the PHY from the NVM on ICH platforms.  This	 * is needed due to an issue where the NVM configuration is	 * not properly autoloaded after power transitions.	 * Therefore, after each PHY reset, we will load the	 * configuration data out of the NVM manually.	 */	if (hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) {		struct e1000_adapter *adapter = hw->adapter;		/* Check if SW needs configure the PHY */		if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) ||		    (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M))			sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;		else			sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;		data = er32(FEXTNVM);		if (!(data & sw_cfg_mask))			return 0;		/* Wait for basic configuration completes before proceeding*/		do {			data = er32(STATUS);			data &= E1000_STATUS_LAN_INIT_DONE;			udelay(100);		} while ((!data) && --loop);		/*		 * If basic configuration is incomplete before the above loop		 * count reaches 0, loading the configuration from NVM will		 * leave the PHY in a bad state possibly resulting in no link.		 */		if (loop == 0) {			hw_dbg(hw, "LAN_INIT_DONE not set, increase timeout\n");		}		/* Clear the Init Done bit for the next init event */		data = er32(STATUS);		data &= ~E1000_STATUS_LAN_INIT_DONE;		ew32(STATUS, data);		/*		 * Make sure HW does not configure LCD from PHY		 * extended configuration before SW configuration		 */		data = er32(EXTCNF_CTRL);		if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)			return 0;		cnf_size = er32(EXTCNF_SIZE);		cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;		cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;		if (!cnf_size)			return 0;		cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;		cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;		/* Configure LCD from extended configuration region. */		/* cnf_base_addr is in DWORD */		word_addr = (u16)(cnf_base_addr << 1);		for (i = 0; i < cnf_size; i++) {			ret_val = e1000_read_nvm(hw,						(word_addr + i * 2),						1,						&reg_data);			if (ret_val)				return ret_val;			ret_val = e1000_read_nvm(hw,						(word_addr + i * 2 + 1),						1,						&reg_addr);			if (ret_val)				return ret_val;			/* Save off the PHY page for future writes. */			if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {				phy_page = reg_data;				continue;			}			reg_addr |= phy_page;			ret_val = e1e_wphy(hw, (u32)reg_addr, reg_data);			if (ret_val)				return ret_val;		}	}	return 0;}/** *  e1000_get_phy_info_ife_ich8lan - Retrieves various IFE PHY states *  @hw: pointer to the HW structure * *  Populates "phy" structure with various feature states. *  This function is only called by other family-specific *  routines. **/static s32 e1000_get_phy_info_ife_ich8lan(struct e1000_hw *hw){	struct e1000_phy_info *phy = &hw->phy;	s32 ret_val;	u16 data;	bool link;	ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);	if (ret_val)		return ret_val;	if (!link) {		hw_dbg(hw, "Phy info is only valid if link is up\n");		return -E1000_ERR_CONFIG;	}	ret_val = e1e_rphy(hw, IFE_PHY_SPECIAL_CONTROL, &data);	if (ret_val)		return ret_val;	phy->polarity_correction = (!(data & IFE_PSC_AUTO_POLARITY_DISABLE));	if (phy->polarity_correction) {		ret_val = e1000_check_polarity_ife_ich8lan(hw);		if (ret_val)			return ret_val;	} else {		/* Polarity is forced */		phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY)				      ? e1000_rev_polarity_reversed				      : e1000_rev_polarity_normal;	}	ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data);	if (ret_val)		return ret_val;	phy->is_mdix = (data & IFE_PMC_MDIX_STATUS);	/* The following parameters are undefined for 10/100 operation. */	phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;	phy->local_rx = e1000_1000t_rx_status_undefined;	phy->remote_rx = e1000_1000t_rx_status_undefined;	return 0;}/** *  e1000_get_phy_info_ich8lan - Calls appropriate PHY type get_phy_info *  @hw: pointer to the HW structure * *  Wrapper for calling the get_phy_info routines for the appropriate phy type. *  This is a function pointer entry point called by drivers *  or other shared routines. **/static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw){	switch (hw->phy.type) {	case e1000_phy_ife:		return e1000_get_phy_info_ife_ich8lan(hw);		break;	case e1000_phy_igp_3:	case e1000_phy_bm:		return e1000e_get_phy_info_igp(hw);		break;	default:		break;	}	return -E1000_ERR_PHY_TYPE;}/** *  e1000_check_polarity_ife_ich8lan - Check cable polarity for IFE PHY *  @hw: pointer to the HW structure * *  Polarity is determined on the polarity reversal feature being enabled. *  This function is only called by other family-specific *  routines. **/static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw){	struct e1000_phy_info *phy = &hw->phy;	s32 ret_val;	u16 phy_data, offset, mask;	/*	 * Polarity is determined based on the reversal feature being enabled.	 */	if (phy->polarity_correction) {		offset	= IFE_PHY_EXTENDED_STATUS_CONTROL;		mask	= IFE_PESC_POLARITY_REVERSED;	} else {		offset	= IFE_PHY_SPECIAL_CONTROL;		mask	= IFE_PSC_FORCE_POLARITY;	}	ret_val = e1e_rphy(hw, offset, &phy_data);	if (!ret_val)		phy->cable_polarity = (phy_data & mask)				      ? e1000_rev_polarity_reversed				      : e1000_rev_polarity_normal;	return ret_val;}/** *  e1000_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state *  @hw: pointer to the HW structure *  @active: TRUE to enable LPLU, FALSE to disable * *  Sets the LPLU D0 state according to the active flag.  When *  activating LPLU this function also disables smart speed *  and vice versa.  LPLU will not be activated unless the *  device autonegotiation advertisement meets standards of *  either 10 or 10/100 or 10/100/1000 at all duplexes. *  This is a function pointer entry point only called by *  PHY setup routines. **/static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active){	struct e1000_phy_info *phy = &hw->phy;	u32 phy_ctrl;	s32 ret_val = 0;	u16 data;	if (phy->type == e1000_phy_ife)		return ret_val;	phy_ctrl = er32(PHY_CTRL);	if (active) {		phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;		ew32(PHY_CTRL, phy_ctrl);		/*		 * Call gig speed drop workaround on LPLU before accessing		 * any PHY registers		 */		if ((hw->mac.type == e1000_ich8lan) &&		    (hw->phy.type == e1000_phy_igp_3))			e1000e_gig_downshift_workaround_ich8lan(hw);		/* When LPLU is enabled, we should disable SmartSpeed */		ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data);		data &= ~IGP01E1000_PSCFR_SMART_SPEED;		ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data);		if (ret_val)			return ret_val;	} else {		phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;		ew32(PHY_CTRL, phy_ctrl);		/*		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used		 * during Dx states where the power conservation is most		 * important.  During driver activity we should enable		 * SmartSpeed, so performance is maintained.		 */		if (phy->smart_speed == e1000_smart_speed_on) {			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,					   &data);			if (ret_val)				return ret_val;			data |= IGP01E1000_PSCFR_SMART_SPEED;			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,					   data);			if (ret_val)				return ret_val;		} else if (phy->smart_speed == e1000_smart_speed_off) {			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,					   &data);			if (ret_val)				return ret_val;			data &= ~IGP01E1000_PSCFR_SMART_SPEED;			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,					   data);			if (ret_val)				return ret_val;		}	}	return 0;}/** *  e1000_set_d3_lplu_state_ich8lan - Set Low Power Linkup D3 state *  @hw: pointer to the HW structure *  @active: TRUE to enable LPLU, FALSE to disable * *  Sets the LPLU D3 state according to the active flag.  When *  activating LPLU this function also disables smart speed *  and vice versa.  LPLU will not be activated unless the *  device autonegotiation advertisement meets standards of *  either 10 or 10/100 or 10/100/1000 at all duplexes. *  This is a function pointer entry point only called by *  PHY setup routines. **/static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active){	struct e1000_phy_info *phy = &hw->phy;	u32 phy_ctrl;	s32 ret_val;	u16 data;	phy_ctrl = er32(PHY_CTRL);	if (!active) {		phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;		ew32(PHY_CTRL, phy_ctrl);		/*		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used		 * during Dx states where the power conservation is most		 * important.  During driver activity we should enable		 * SmartSpeed, so performance is maintained.		 */		if (phy->smart_speed == e1000_smart_speed_on) {			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,					   &data);			if (ret_val)				return ret_val;			data |= IGP01E1000_PSCFR_SMART_SPEED;			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,					   data);			if (ret_val)				return ret_val;		} else if (phy->smart_speed == e1000_smart_speed_off) {			ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG,					   &data);			if (ret_val)				return ret_val;			data &= ~IGP01E1000_PSCFR_SMART_SPEED;			ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG,					   data);			if (ret_val)				return ret_val;		}	} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||		   (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||		   (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {		phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;		ew32(PHY_CTRL, phy_ctrl);		/*		 * Call gig speed drop workaround on LPLU before accessing		 * any PHY registers		 */		if ((hw->mac.type == e1000_ich8lan) &&		    (hw->phy.type == e1000_phy_igp_3))			e1000e_gig_downshift_workaround_ich8lan(hw);		/* When LPLU is enabled, we should disable SmartSpeed */		ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data);		if (ret_val)			return ret_val;		data &= ~IGP01E1000_PSCFR_SMART_SPEED;		ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data);	}	return 0;}/** *  e1000_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. **/static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank){	if (er32(EECD) & E1000_EECD_SEC1VAL)		*bank = 1;	else		*bank = 0;		return 0;}/** *  e1000_read_nvm_ich8lan - Read word(s) from the NVM *  @hw: pointer to the HW structure *  @offset: The offset (in bytes) of the word(s) to read. *  @words: Size of data to read in words *  @data: Pointer to the word(s) to read at offset. * *  Reads a word(s) from the NVM using the flash access registers. **/static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,				  u16 *data){	struct e1000_nvm_info *nvm = &hw->nvm;	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;	u32 act_offset;	s32 ret_val;	u32 bank = 0;	u16 i, word;	if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||	    (words == 0)) {		hw_dbg(hw, "nvm parameter(s) out of bounds\n");		return -E1000_ERR_NVM;	}	ret_val = e1000_acquire_swflag_ich8lan(hw);	if (ret_val)		return ret_val;	ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);	if (ret_val)		return ret_val;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -