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

📄 e1000_ich8lan.c

📁 DELL755 Intel 网卡驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
 *  routines for the PHY and NVM parts. **/static void e1000_release_swflag_ich8lan(struct e1000_hw *hw){	u32 extcnf_ctrl;	DEBUGFUNC("e1000_release_swflag_ich8lan");	extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);	extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;	E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);	return;}/** *  e1000_check_mng_mode_ich8lan - Checks management mode *  @hw: pointer to the HW structure * *  This checks if the adapter has manageability enabled. *  This is a function pointer entry point only called by read/write *  routines for the PHY and NVM parts. **/static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw){	u32 fwsm;	DEBUGFUNC("e1000_check_mng_mode_ich8lan");	fwsm = E1000_READ_REG(hw, E1000_FWSM);	return ((fwsm & E1000_FWSM_MODE_MASK) ==	        (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));}/** *  e1000_check_reset_block_ich8lan - Check if PHY reset is blocked *  @hw: pointer to the HW structure * *  Checks if firmware is blocking the reset of the PHY. *  This is a function pointer entry point only called by *  reset routines. **/static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw){	u32 fwsm;	DEBUGFUNC("e1000_check_reset_block_ich8lan");	fwsm = E1000_READ_REG(hw, E1000_FWSM);	return (fwsm & E1000_ICH_FWSM_RSPCIPHY) ? E1000_SUCCESS	                                        : E1000_BLK_PHY_RESET;}/** *  e1000_phy_force_speed_duplex_ich8lan - Force PHY speed & duplex *  @hw: pointer to the HW structure * *  Forces the speed and duplex settings of the PHY. *  This is a function pointer entry point only called by *  PHY setup routines. **/static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw){	struct e1000_phy_info *phy = &hw->phy;	s32 ret_val;	u16 data;	bool link;	DEBUGFUNC("e1000_phy_force_speed_duplex_ich8lan");	if (phy->type != e1000_phy_ife) {		ret_val = e1000_phy_force_speed_duplex_igp(hw);		goto out;	}	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data);	if (ret_val)		goto out;	e1000_phy_force_speed_duplex_setup(hw, &data);	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data);	if (ret_val)		goto out;	/* Disable MDI-X support for 10/100 */	ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);	if (ret_val)		goto out;	data &= ~IFE_PMC_AUTO_MDIX;	data &= ~IFE_PMC_FORCE_MDIX;	ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data);	if (ret_val)		goto out;	DEBUGOUT1("IFE PMC: %X\n", data);	usec_delay(1);	if (phy->autoneg_wait_to_complete) {		DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n");		ret_val = e1000_phy_has_link_generic(hw,		                                     PHY_FORCE_LIMIT,		                                     100000,		                                     &link);		if (ret_val)			goto out;		if (!link) {			DEBUGOUT("Link taking longer than expected.\n");		}		/* Try once more */		ret_val = e1000_phy_has_link_generic(hw,		                                     PHY_FORCE_LIMIT,		                                     100000,		                                     &link);		if (ret_val)			goto out;	}out:	return ret_val;}/** *  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;	struct e1000_nvm_info *nvm = &hw->nvm;	u32 i, 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;	DEBUGFUNC("e1000_phy_hw_reset_ich8lan");	ret_val = e1000_phy_hw_reset_generic(hw);	if (ret_val)		goto out;	/*	 * 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) {		/* Check if SW needs configure the PHY */		if ((hw->device_id == E1000_DEV_ID_ICH8_IGP_M_AMT) ||		    (hw->device_id == E1000_DEV_ID_ICH8_IGP_M))			sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;		else			sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;		data = E1000_READ_REG(hw, E1000_FEXTNVM);		if (!(data & sw_cfg_mask))			goto out;		/* Wait for basic configuration completes before proceeding*/		do {			data = E1000_READ_REG(hw, E1000_STATUS);			data &= E1000_STATUS_LAN_INIT_DONE;			usec_delay(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) {			DEBUGOUT("LAN_INIT_DONE not set, increase timeout\n");		}		/* Clear the Init Done bit for the next init event */		data = E1000_READ_REG(hw, E1000_STATUS);		data &= ~E1000_STATUS_LAN_INIT_DONE;		E1000_WRITE_REG(hw, E1000_STATUS, data);		/*		 * Make sure HW does not configure LCD from PHY		 * extended configuration before SW configuration		 */		data = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);		if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)			goto out;		cnf_size = E1000_READ_REG(hw, E1000_EXTCNF_SIZE);		cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;		cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;		if (!cnf_size)			goto out;		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 = nvm->ops.read(hw,			                        (word_addr + i * 2),			                        1,			                        &reg_data);			if (ret_val)				goto out;			ret_val = nvm->ops.read(hw,			                        (word_addr + i * 2 + 1),			                        1,			                        &reg_addr);			if (ret_val)				goto out;			/* 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 = phy->ops.write_reg(hw,			                             (u32)reg_addr,			                             reg_data);			if (ret_val)				goto out;		}	}out:	return ret_val;}/** *  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){	s32 ret_val = -E1000_ERR_PHY_TYPE;	DEBUGFUNC("e1000_get_phy_info_ich8lan");	switch (hw->phy.type) {	case e1000_phy_ife:		ret_val = e1000_get_phy_info_ife_ich8lan(hw);		break;	case e1000_phy_igp_3:	case e1000_phy_bm:		ret_val = e1000_get_phy_info_igp(hw);		break;	default:		break;	}	return ret_val;}/** *  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;	DEBUGFUNC("e1000_get_phy_info_ife_ich8lan");	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);	if (ret_val)		goto out;	if (!link) {		DEBUGOUT("Phy info is only valid if link is up\n");		ret_val = -E1000_ERR_CONFIG;		goto out;	}	ret_val = phy->ops.read_reg(hw, IFE_PHY_SPECIAL_CONTROL, &data);	if (ret_val)		goto out;	phy->polarity_correction = (data & IFE_PSC_AUTO_POLARITY_DISABLE)	                           ? false : true;	if (phy->polarity_correction) {		ret_val = e1000_check_polarity_ife_ich8lan(hw);		if (ret_val)			goto out;	} else {		/* Polarity is forced */		phy->cable_polarity = (data & IFE_PSC_FORCE_POLARITY)		                      ? e1000_rev_polarity_reversed		                      : e1000_rev_polarity_normal;	}	ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);	if (ret_val)		goto out;	phy->is_mdix = (data & IFE_PMC_MDIX_STATUS) ? true : false;	/* 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;out:	return ret_val;}/** *  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;	DEBUGFUNC("e1000_check_polarity_ife_ich8lan");	/*	 * 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 = phy->ops.read_reg(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 = E1000_SUCCESS;	u16 data;	DEBUGFUNC("e1000_set_d0_lplu_state_ich8lan");	if (phy->type == e1000_phy_ife)		goto out;	phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);	if (active) {		phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;		E1000_WRITE_REG(hw, E1000_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))			e1000_gig_downshift_workaround_ich8lan(hw);		/* When LPLU is enabled, we should disable SmartSpeed */		ret_val = phy->ops.read_reg(hw,		                            IGP01E1000_PHY_PORT_CONFIG,		                            &data);		data &= ~IGP01E1000_PSCFR_SMART_SPEED;		ret_val = phy->ops.write_reg(hw,		                             IGP01E1000_PHY_PORT_CONFIG,		                             data);		if (ret_val)			goto out;	} else {		phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;		E1000_WRITE_REG(hw, E1000_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 = phy->ops.read_reg(hw,			                            IGP01E1000_PHY_PORT_CONFIG,			                            &data);			if (ret_val)				goto out;

⌨️ 快捷键说明

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