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

📄 e1000_82541.c

📁 linux系统的网卡驱动包
💻 C
📖 第 1 页 / 共 3 页
字号:
	return ret_val;}/** *  e1000_get_cable_length_igp_82541 - Determine cable length for igp PHY *  @hw: pointer to the HW structure * *  The automatic gain control (agc) normalizes the amplitude of the *  received signal, adjusting for the attenuation produced by the *  cable.  By reading the AGC registers, which reperesent the *  cobination of course and fine gain value, the value can be put *  into a lookup table to obtain the approximate cable length *  for each channel.  This is a function pointer entry point called by the *  api module. **/static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw){	struct e1000_phy_info *phy = &hw->phy;	s32 ret_val = E1000_SUCCESS;	u16 i, data;	u16 cur_agc_value, agc_value = 0;	u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;	u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =	                                                 {IGP01E1000_PHY_AGC_A,	                                                  IGP01E1000_PHY_AGC_B,	                                                  IGP01E1000_PHY_AGC_C,	                                                  IGP01E1000_PHY_AGC_D};	DEBUGFUNC("e1000_get_cable_length_igp_82541");	/* Read the AGC registers for all channels */	for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {		ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &data);		if (ret_val)			goto out;		cur_agc_value = data >> IGP01E1000_AGC_LENGTH_SHIFT;		/* Bounds checking */		if ((cur_agc_value >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) ||		    (cur_agc_value == 0)) {			ret_val = -E1000_ERR_PHY;			goto out;		}		agc_value += cur_agc_value;		if (min_agc_value > cur_agc_value)			min_agc_value = cur_agc_value;	}	/* Remove the minimal AGC result for length < 50m */	if (agc_value < IGP01E1000_PHY_CHANNEL_NUM * 50) {		agc_value -= min_agc_value;		/* Average the three remaining channels for the length. */		agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1);	} else {		/* Average the channels for the length. */		agc_value /= IGP01E1000_PHY_CHANNEL_NUM;	}	phy->min_cable_length = (e1000_igp_cable_length_table[agc_value] >	                         IGP01E1000_AGC_RANGE)	                        ? (e1000_igp_cable_length_table[agc_value] -	                           IGP01E1000_AGC_RANGE)	                        : 0;	phy->max_cable_length = e1000_igp_cable_length_table[agc_value] +	                        IGP01E1000_AGC_RANGE;	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;out:	return ret_val;}/** *  e1000_set_d3_lplu_state_82541 - Sets low power link up state for D3 *  @hw: pointer to the HW structure *  @active: boolean used to enable/disable lplu * *  Success returns 0, Failure returns 1 * *  The low power link up (lplu) state is set to the power management level D3 *  and SmartSpeed is disabled when active is true, else clear lplu for D3 *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU *  is used during Dx states where the power conservation is most important. *  During driver activity, SmartSpeed should be enabled so performance is *  maintained.  This is a function pointer entry point called by the *  api module. **/static s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, bool active){	struct e1000_phy_info *phy = &hw->phy;	s32 ret_val;	u16 data;	DEBUGFUNC("e1000_set_d3_lplu_state_82541");	switch (hw->mac.type) {	case e1000_82541_rev_2:	case e1000_82547_rev_2:		break;	default:		ret_val = e1000_set_d3_lplu_state_generic(hw, active);		goto out;		break;	}	ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &data);	if (ret_val)		goto out;	if (!active) {		data &= ~IGP01E1000_GMII_FLEX_SPD;		ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, data);		if (ret_val)			goto out;		/*		 * 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 = e1000_read_phy_reg(hw,			                            IGP01E1000_PHY_PORT_CONFIG,			                            &data);			if (ret_val)				goto out;			data |= IGP01E1000_PSCFR_SMART_SPEED;			ret_val = e1000_write_phy_reg(hw,			                             IGP01E1000_PHY_PORT_CONFIG,			                             data);			if (ret_val)				goto out;		} else if (phy->smart_speed == e1000_smart_speed_off) {			ret_val = e1000_read_phy_reg(hw,			                            IGP01E1000_PHY_PORT_CONFIG,			                            &data);			if (ret_val)				goto out;			data &= ~IGP01E1000_PSCFR_SMART_SPEED;			ret_val = e1000_write_phy_reg(hw,			                             IGP01E1000_PHY_PORT_CONFIG,			                             data);			if (ret_val)				goto out;		}	} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||	           (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||	           (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {		data |= IGP01E1000_GMII_FLEX_SPD;		ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, data);		if (ret_val)			goto out;		/* When LPLU is enabled, we should disable SmartSpeed */		ret_val = e1000_read_phy_reg(hw,		                            IGP01E1000_PHY_PORT_CONFIG,		                            &data);		if (ret_val)			goto out;		data &= ~IGP01E1000_PSCFR_SMART_SPEED;		ret_val = e1000_write_phy_reg(hw,		                             IGP01E1000_PHY_PORT_CONFIG,		                             data);	}out:	return ret_val;}/** *  e1000_setup_led_82541 - Configures SW controllable LED *  @hw: pointer to the HW structure * *  This prepares the SW controllable LED for use and saves the current state *  of the LED so it can be later restored.  This is a function pointer entry *  point called by the api module. **/static s32 e1000_setup_led_82541(struct e1000_hw *hw){	struct e1000_dev_spec_82541 *dev_spec;	s32 ret_val;	DEBUGFUNC("e1000_setup_led_82541");	dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec;	ret_val = e1000_read_phy_reg(hw,	                            IGP01E1000_GMII_FIFO,	                            &dev_spec->spd_default);	if (ret_val)		goto out;	ret_val = e1000_write_phy_reg(hw,	                             IGP01E1000_GMII_FIFO,	                             (u16)(dev_spec->spd_default &	                                        ~IGP01E1000_GMII_SPD));	if (ret_val)		goto out;	E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1);out:	return ret_val;}/** *  e1000_cleanup_led_82541 - Set LED config to default operation *  @hw: pointer to the HW structure * *  Remove the current LED configuration and set the LED configuration *  to the default value, saved from the EEPROM.  This is a function pointer *  entry point called by the api module. **/static s32 e1000_cleanup_led_82541(struct e1000_hw *hw){	struct e1000_dev_spec_82541 *dev_spec;	s32 ret_val;	DEBUGFUNC("e1000_cleanup_led_82541");	dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec;	ret_val = e1000_write_phy_reg(hw,	                             IGP01E1000_GMII_FIFO,	                             dev_spec->spd_default);	if (ret_val)		goto out;	E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default);out:	return ret_val;}/** *  e1000_phy_init_script_82541 - Initialize GbE PHY *  @hw: pointer to the HW structure * *  Initializes the IGP PHY. **/static s32 e1000_phy_init_script_82541(struct e1000_hw *hw){	struct e1000_dev_spec_82541 *dev_spec;	u32 ret_val;	u16 phy_saved_data;	DEBUGFUNC("e1000_phy_init_script_82541");	dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec;	if (!dev_spec->phy_init_script) {		ret_val = E1000_SUCCESS;		goto out;	}	/* Delay after phy reset to enable NVM configuration to load */	msec_delay(20);	/*	 * Save off the current value of register 0x2F5B to be restored at	 * the end of this routine.	 */	ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);	/* Disabled the PHY transmitter */	e1000_write_phy_reg(hw, 0x2F5B, 0x0003);	msec_delay(20);	e1000_write_phy_reg(hw, 0x0000, 0x0140);	msec_delay(5);	switch (hw->mac.type) {	case e1000_82541:	case e1000_82547:		e1000_write_phy_reg(hw, 0x1F95, 0x0001);		e1000_write_phy_reg(hw, 0x1F71, 0xBD21);		e1000_write_phy_reg(hw, 0x1F79, 0x0018);		e1000_write_phy_reg(hw, 0x1F30, 0x1600);		e1000_write_phy_reg(hw, 0x1F31, 0x0014);		e1000_write_phy_reg(hw, 0x1F32, 0x161C);		e1000_write_phy_reg(hw, 0x1F94, 0x0003);		e1000_write_phy_reg(hw, 0x1F96, 0x003F);		e1000_write_phy_reg(hw, 0x2010, 0x0008);		break;	case e1000_82541_rev_2:	case e1000_82547_rev_2:		e1000_write_phy_reg(hw, 0x1F73, 0x0099);		break;	default:		break;	}	e1000_write_phy_reg(hw, 0x0000, 0x3300);	msec_delay(20);	/* Now enable the transmitter */	e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);	if (hw->mac.type == e1000_82547) {		u16 fused, fine, coarse;		/* Move to analog registers page */		e1000_read_phy_reg(hw,		                  IGP01E1000_ANALOG_SPARE_FUSE_STATUS,		                  &fused);		if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {			e1000_read_phy_reg(hw,			                  IGP01E1000_ANALOG_FUSE_STATUS,			                  &fused);			fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;			coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;			if (coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {				coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10;				fine -= IGP01E1000_ANALOG_FUSE_FINE_1;			} else if (coarse ==			           IGP01E1000_ANALOG_FUSE_COARSE_THRESH)				fine -= IGP01E1000_ANALOG_FUSE_FINE_10;			fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |			        (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |			        (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);			e1000_write_phy_reg(hw,			                   IGP01E1000_ANALOG_FUSE_CONTROL,			                   fused);			e1000_write_phy_reg(hw,			              IGP01E1000_ANALOG_FUSE_BYPASS,			              IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);		}	}out:	return ret_val;}/** *  e1000_init_script_state_82541 - Enable/Disable PHY init script *  @hw: pointer to the HW structure *  @state: boolean value used to enable/disable PHY init script * *  Allows the driver to enable/disable the PHY init script, if the PHY is an *  IGP PHY.  This is a function pointer entry point called by the api module. **/void e1000_init_script_state_82541(struct e1000_hw *hw, bool state){	struct e1000_dev_spec_82541 *dev_spec;	DEBUGFUNC("e1000_init_script_state_82541");	if (hw->phy.type != e1000_phy_igp) {		DEBUGOUT("Initialization script not necessary.\n");		goto out;	}	dev_spec = (struct e1000_dev_spec_82541 *)hw->dev_spec;	if (!dev_spec) {		DEBUGOUT("dev_spec pointer is set to NULL.\n");		goto out;	}	dev_spec->phy_init_script = state;out:	return;}/** * e1000_power_down_phy_copper_82541 - Remove link in case of PHY power down * @hw: pointer to the HW structure * * In the case of a PHY power down to save power, or to turn off link during a * driver unload, or wake on lan is not enabled, remove the link. **/static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw){	/* If the management interface is not enabled, then power down */	if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN))		e1000_power_down_phy_copper(hw);	return;}/** *  e1000_clear_hw_cntrs_82541 - Clear device specific hardware counters *  @hw: pointer to the HW structure * *  Clears the hardware counters by reading the counter registers. **/static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw){	volatile u32 temp;	DEBUGFUNC("e1000_clear_hw_cntrs_82541");	e1000_clear_hw_cntrs_base_generic(hw);	temp = E1000_READ_REG(hw, E1000_PRC64);	temp = E1000_READ_REG(hw, E1000_PRC127);	temp = E1000_READ_REG(hw, E1000_PRC255);	temp = E1000_READ_REG(hw, E1000_PRC511);	temp = E1000_READ_REG(hw, E1000_PRC1023);	temp = E1000_READ_REG(hw, E1000_PRC1522);	temp = E1000_READ_REG(hw, E1000_PTC64);	temp = E1000_READ_REG(hw, E1000_PTC127);	temp = E1000_READ_REG(hw, E1000_PTC255);	temp = E1000_READ_REG(hw, E1000_PTC511);	temp = E1000_READ_REG(hw, E1000_PTC1023);	temp = E1000_READ_REG(hw, E1000_PTC1522);	temp = E1000_READ_REG(hw, E1000_ALGNERRC);	temp = E1000_READ_REG(hw, E1000_RXERRC);	temp = E1000_READ_REG(hw, E1000_TNCRS);	temp = E1000_READ_REG(hw, E1000_CEXTERR);	temp = E1000_READ_REG(hw, E1000_TSCTC);	temp = E1000_READ_REG(hw, E1000_TSCTFC);	temp = E1000_READ_REG(hw, E1000_MGTPRC);	temp = E1000_READ_REG(hw, E1000_MGTPDC);	temp = E1000_READ_REG(hw, E1000_MGTPTC);}

⌨️ 快捷键说明

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