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

📄 e1000_82543.c

📁 linux系统的网卡驱动包
💻 C
📖 第 1 页 / 共 4 页
字号:
 *  @hw: pointer to the HW structure * *  Checks the phy for link, if link exists, do the following: *   - check for downshift *   - do polarity workaround (if necessary) *   - configure collision distance *   - configure flow control after link up *   - configure tbi compatibility **/static s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	u32 icr, rctl;	s32 ret_val;	u16 speed, duplex;	bool link;	DEBUGFUNC("e1000_check_for_copper_link_82543");	if (!mac->get_link_status) {		ret_val = E1000_SUCCESS;		goto out;	}	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);	if (ret_val)		goto out;	if (!link)		goto out; /* No link detected */	mac->get_link_status = FALSE;	e1000_check_downshift_generic(hw);	/*	 * If we are forcing speed/duplex, then we can return since	 * we have already determined whether we have link or not.	 */	if (!mac->autoneg) {		/*		 * If speed and duplex are forced to 10H or 10F, then we will		 * implement the polarity reversal workaround.  We disable		 * interrupts first, and upon returning, place the devices		 * interrupt state to its previous value except for the link		 * status change interrupt which will happened due to the		 * execution of this workaround.		 */		if (mac->forced_speed_duplex & E1000_ALL_10_SPEED) {			E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);			ret_val = e1000_polarity_reversal_workaround_82543(hw);			icr = E1000_READ_REG(hw, E1000_ICR);			E1000_WRITE_REG(hw, E1000_ICS, (icr & ~E1000_ICS_LSC));			E1000_WRITE_REG(hw, E1000_IMS, IMS_ENABLE_MASK);		}		ret_val = -E1000_ERR_CONFIG;		goto out;	}	/*	 * We have a M88E1000 PHY and Auto-Neg is enabled.  If we	 * have Si on board that is 82544 or newer, Auto	 * Speed Detection takes care of MAC speed/duplex	 * configuration.  So we only need to configure Collision	 * Distance in the MAC.  Otherwise, we need to force	 * speed/duplex on the MAC to the current PHY speed/duplex	 * settings.	 */	if (mac->type == e1000_82544)		e1000_config_collision_dist_generic(hw);	else {		ret_val = e1000_config_mac_to_phy_82543(hw);		if (ret_val) {			DEBUGOUT("Error configuring MAC to PHY settings\n");			goto out;		}	}	/*	 * Configure Flow Control now that Auto-Neg has completed.	 * First, we need to restore the desired flow control	 * settings because we may have had to re-autoneg with a	 * different link partner.	 */	ret_val = e1000_config_fc_after_link_up_generic(hw);	if (ret_val) {		DEBUGOUT("Error configuring flow control\n");	}	/*	 * At this point we know that we are on copper and we have	 * auto-negotiated link.  These are conditions for checking the link	 * partner capability register.  We use the link speed to determine if	 * TBI compatibility needs to be turned on or off.  If the link is not	 * at gigabit speed, then TBI compatibility is not needed.  If we are	 * at gigabit speed, we turn on TBI compatibility.	 */	if (e1000_tbi_compatibility_enabled_82543(hw)) {		ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);		if (ret_val) {			DEBUGOUT("Error getting link speed and duplex\n");			return ret_val;		}		if (speed != SPEED_1000) {			/*			 * If link speed is not set to gigabit speed,			 * we do not need to enable TBI compatibility.			 */			if (e1000_tbi_sbp_enabled_82543(hw)) {				/*				 * If we previously were in the mode,				 * turn it off.				 */				e1000_set_tbi_sbp_82543(hw, FALSE);				rctl = E1000_READ_REG(hw, E1000_RCTL);				rctl &= ~E1000_RCTL_SBP;				E1000_WRITE_REG(hw, E1000_RCTL, rctl);			}		} else {			/*			 * If TBI compatibility is was previously off,			 * turn it on. For compatibility with a TBI link			 * partner, we will store bad packets. Some			 * frames have an additional byte on the end and			 * will look like CRC errors to to the hardware.			 */			if (!e1000_tbi_sbp_enabled_82543(hw)) {				e1000_set_tbi_sbp_82543(hw, TRUE);				rctl = E1000_READ_REG(hw, E1000_RCTL);				rctl |= E1000_RCTL_SBP;				E1000_WRITE_REG(hw, E1000_RCTL, rctl);			}		}	}out:	return ret_val;}/** *  e1000_check_for_fiber_link_82543 - Check for link (Fiber) *  @hw: pointer to the HW structure * *  Checks for link up on the hardware.  If link is not up and we have *  a signal, then we need to force link up. **/static s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	u32 rxcw, ctrl, status;	s32 ret_val = E1000_SUCCESS;	DEBUGFUNC("e1000_check_for_fiber_link_82543");	ctrl = E1000_READ_REG(hw, E1000_CTRL);	status = E1000_READ_REG(hw, E1000_STATUS);	rxcw = E1000_READ_REG(hw, E1000_RXCW);	/*	 * If we don't have link (auto-negotiation failed or link partner	 * cannot auto-negotiate), the cable is plugged in (we have signal),	 * and our link partner is not trying to auto-negotiate with us (we	 * are receiving idles or data), we need to force link up. We also	 * need to give auto-negotiation time to complete, in case the cable	 * was just plugged in. The autoneg_failed flag does this.	 */	/* (ctrl & E1000_CTRL_SWDPIN1) == 0 == have signal */	if ((!(ctrl & E1000_CTRL_SWDPIN1)) &&	    (!(status & E1000_STATUS_LU)) &&	    (!(rxcw & E1000_RXCW_C))) {		if (mac->autoneg_failed == 0) {			mac->autoneg_failed = 1;			ret_val = 0;			goto out;		}		DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");		/* Disable auto-negotiation in the TXCW register */		E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));		/* Force link-up and also force full-duplex. */		ctrl = E1000_READ_REG(hw, E1000_CTRL);		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);		/* Configure Flow Control after forcing link up. */		ret_val = e1000_config_fc_after_link_up_generic(hw);		if (ret_val) {			DEBUGOUT("Error configuring flow control\n");			goto out;		}	} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {		/*		 * If we are forcing link and we are receiving /C/ ordered		 * sets, re-enable auto-negotiation in the TXCW register		 * and disable forced link in the Device Control register		 * in an attempt to auto-negotiate with our link partner.		 */		DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");		E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);		E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU));		mac->serdes_has_link = TRUE;	}out:	return ret_val;}/** *  e1000_config_mac_to_phy_82543 - Configure MAC to PHY settings *  @hw: pointer to the HW structure * *  For the 82543 silicon, we need to set the MAC to match the settings *  of the PHY, even if the PHY is auto-negotiating. **/static s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw){	u32 ctrl;	s32 ret_val;	u16 phy_data;	DEBUGFUNC("e1000_config_mac_to_phy_82543");	/* Set the bits to force speed and duplex */	ctrl = E1000_READ_REG(hw, E1000_CTRL);	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);	ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);	/*	 * Set up duplex in the Device Control and Transmit Control	 * registers depending on negotiated values.	 */	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);	if (ret_val)		goto out;	ctrl &= ~E1000_CTRL_FD;	if (phy_data & M88E1000_PSSR_DPLX)		ctrl |= E1000_CTRL_FD;	e1000_config_collision_dist_generic(hw);	/*	 * Set up speed in the Device Control register depending on	 * negotiated values.	 */	if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)		ctrl |= E1000_CTRL_SPD_1000;	else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)		ctrl |= E1000_CTRL_SPD_100;	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);out:	return ret_val;}/** *  e1000_write_vfta_82543 - Write value to VLAN filter table *  @hw: pointer to the HW structure *  @offset: the 32-bit offset in which to write the value to. *  @value: the 32-bit value to write at location offset. * *  This writes a 32-bit value to a 32-bit offset in the VLAN filter *  table. **/static void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset, u32 value){	u32 temp;	DEBUGFUNC("e1000_write_vfta_82543");	if ((hw->mac.type == e1000_82544) && (offset & 1)) {		temp = E1000_READ_REG_ARRAY(hw, E1000_VFTA, offset - 1);		E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);		E1000_WRITE_FLUSH(hw);		E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset - 1, temp);		E1000_WRITE_FLUSH(hw);	} else {		e1000_write_vfta_generic(hw, offset, value);	}}/** *  e1000_mta_set_82543 - Set multicast filter table address *  @hw: pointer to the HW structure *  @hash_value: determines the MTA register and bit to set * *  The multicast table address is a register array of 32-bit registers. *  The hash_value is used to determine what register the bit is in, the *  current value is read, the new bit is OR'd in and the new value is *  written back into the register. **/static void e1000_mta_set_82543(struct e1000_hw *hw, u32 hash_value){	u32 hash_bit, hash_reg, mta, temp;	DEBUGFUNC("e1000_mta_set_82543");	hash_reg = (hash_value >> 5);	/*	 * If we are on an 82544 and we are trying to write an odd offset	 * in the MTA, save off the previous entry before writing and	 * restore the old value after writing.	 */	if ((hw->mac.type == e1000_82544) && (hash_reg & 1)) {		hash_reg &= (hw->mac.mta_reg_count - 1);		hash_bit = hash_value & 0x1F;		mta = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg);		mta |= (1 << hash_bit);		temp = E1000_READ_REG_ARRAY(hw, E1000_MTA, hash_reg - 1);		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg, mta);		E1000_WRITE_FLUSH(hw);		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, hash_reg - 1, temp);		E1000_WRITE_FLUSH(hw);	} else {		e1000_mta_set_generic(hw, hash_value);	}}/** *  e1000_led_on_82543 - Turn on SW controllable LED *  @hw: pointer to the HW structure * *  Turns the SW defined LED on.  This is a function pointer entry point *  called by the api module. **/static s32 e1000_led_on_82543(struct e1000_hw *hw){	u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);	DEBUGFUNC("e1000_led_on_82543");	if (hw->mac.type == e1000_82544 &&	    hw->phy.media_type == e1000_media_type_copper) {		/* Clear SW-defineable Pin 0 to turn on the LED */		ctrl &= ~E1000_CTRL_SWDPIN0;		ctrl |= E1000_CTRL_SWDPIO0;	} else {		/* Fiber 82544 and all 82543 use this method */		ctrl |= E1000_CTRL_SWDPIN0;		ctrl |= E1000_CTRL_SWDPIO0;	}	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);	return E1000_SUCCESS;}/** *  e1000_led_off_82543 - Turn off SW controllable LED *  @hw: pointer to the HW structure * *  Turns the SW defined LED off.  This is a function pointer entry point *  called by the api module. **/static s32 e1000_led_off_82543(struct e1000_hw *hw){	u32 ctrl = E1000_READ_REG(hw, E1000_CTRL);	DEBUGFUNC("e1000_led_off_82543");	if (hw->mac.type == e1000_82544 &&	    hw->phy.media_type == e1000_media_type_copper) {		/* Set SW-defineable Pin 0 to turn off the LED */		ctrl |= E1000_CTRL_SWDPIN0;		ctrl |= E1000_CTRL_SWDPIO0;	} else {		ctrl &= ~E1000_CTRL_SWDPIN0;		ctrl |= E1000_CTRL_SWDPIO0;	}	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);	return E1000_SUCCESS;}/** *  e1000_clear_hw_cntrs_82543 - 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_82543(struct e1000_hw *hw){	volatile u32 temp;	DEBUGFUNC("e1000_clear_hw_cntrs_82543");	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);}

⌨️ 快捷键说明

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