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

📄 e1000_mac.c

📁 linux下的网卡驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
		/* Flow control (both RX and TX) is enabled by a software		 * over-ride.		 */		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);		break;	default:		DEBUGOUT("Flow control param set incorrectly\n");		ret_val = -E1000_ERR_CONFIG;		goto out;		break;	}	E1000_WRITE_REG(hw, E1000_TXCW, txcw);	mac->txcw = txcw;out:	return ret_val;}/** *  e1000_set_fc_watermarks_generic - Set flow control high/low watermarks *  @hw: pointer to the HW structure * *  Sets the flow control high/low threshold (watermark) registers.  If *  flow control XON frame transmission is enabled, then set XON frame *  tansmission as well. **/s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	s32 ret_val = E1000_SUCCESS;	u32 fcrtl = 0, fcrth = 0;	DEBUGFUNC("e1000_set_fc_watermarks_generic");	/* Set the flow control receive threshold registers.  Normally,	 * these registers will be set to a default threshold that may be	 * adjusted later by the driver's runtime code.  However, if the	 * ability to transmit pause frames is not enabled, then these	 * registers will be set to 0.	 */	if (mac->fc & e1000_fc_tx_pause) {		/* We need to set up the Receive Threshold high and low water		 * marks as well as (optionally) enabling the transmission of		 * XON frames.		 */		fcrtl = mac->fc_low_water;		if (mac->fc_send_xon)			fcrtl |= E1000_FCRTL_XONE;		fcrth = mac->fc_high_water;	}	E1000_WRITE_REG(hw, E1000_FCRTL, fcrtl);	E1000_WRITE_REG(hw, E1000_FCRTH, fcrth);	return ret_val;}/** *  e1000_set_default_fc_generic - Set flow control default values *  @hw: pointer to the HW structure * *  Read the EEPROM for the default values for flow control and store the *  values. **/s32 e1000_set_default_fc_generic(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	s32 ret_val = E1000_SUCCESS;	u16 nvm_data;	DEBUGFUNC("e1000_set_default_fc_generic");	if (mac->fc != e1000_fc_default)		goto out;	/* Read and store word 0x0F of the EEPROM. This word contains bits	 * that determine the hardware's default PAUSE (flow control) mode,	 * a bit that determines whether the HW defaults to enabling or	 * disabling auto-negotiation, and the direction of the	 * SW defined pins. If there is no SW over-ride of the flow	 * control setting, then the variable hw->fc will	 * be initialized based on a value in the EEPROM.	 */	ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data);	if (ret_val) {		DEBUGOUT("NVM Read Error\n");		goto out;	}	if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)		mac->fc = e1000_fc_none;	else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==		 NVM_WORD0F_ASM_DIR)		mac->fc = e1000_fc_tx_pause;	else		mac->fc = e1000_fc_full;out:	return ret_val;}/** *  e1000_force_mac_fc_generic - Force the MAC's flow control settings *  @hw: pointer to the HW structure * *  Force the MAC's flow control settings.  Sets the TFCE and RFCE bits in the *  device control register to reflect the adapter settings.  TFCE and RFCE *  need to be explicitly set by software when a copper PHY is used because *  autonegotiation is managed by the PHY rather than the MAC.  Software must *  also configure these bits when link is forced on a fiber connection. **/s32 e1000_force_mac_fc_generic(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	u32 ctrl;	s32 ret_val = E1000_SUCCESS;	DEBUGFUNC("e1000_force_mac_fc_generic");	ctrl = E1000_READ_REG(hw, E1000_CTRL);	/* Because we didn't get link via the internal auto-negotiation	 * mechanism (we either forced link or we got link via PHY	 * auto-neg), we have to manually enable/disable transmit an	 * receive flow control.	 *	 * The "Case" statement below enables/disable flow control	 * according to the "mac->fc" parameter.	 *	 * The possible values of the "fc" parameter are:	 *      0:  Flow control is completely disabled	 *      1:  Rx flow control is enabled (we can receive pause	 *          frames but not send pause frames).	 *      2:  Tx flow control is enabled (we can send pause frames	 *          frames but we do not receive pause frames).	 *      3:  Both Rx and TX flow control (symmetric) is enabled.	 *  other:  No other values should be possible at this point.	 */	DEBUGOUT1("mac->fc = %u\n", mac->fc);	switch (mac->fc) {	case e1000_fc_none:		ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));		break;	case e1000_fc_rx_pause:		ctrl &= (~E1000_CTRL_TFCE);		ctrl |= E1000_CTRL_RFCE;		break;	case e1000_fc_tx_pause:		ctrl &= (~E1000_CTRL_RFCE);		ctrl |= E1000_CTRL_TFCE;		break;	case e1000_fc_full:		ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);		break;	default:		DEBUGOUT("Flow control param set incorrectly\n");		ret_val = -E1000_ERR_CONFIG;		goto out;	}	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);out:	return ret_val;}/** *  e1000_config_fc_after_link_up_generic - Configures flow control after link *  @hw: pointer to the HW structure * *  Checks the status of auto-negotiation after link up to ensure that the *  speed and duplex were not forced.  If the link needed to be forced, then *  flow control needs to be forced also.  If auto-negotiation is enabled *  and did not fail, then we configure flow control based on our link *  partner. **/s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	s32 ret_val = E1000_SUCCESS;	u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;	u16 speed, duplex;	DEBUGFUNC("e1000_config_fc_after_link_up_generic");	/* Check for the case where we have fiber media and auto-neg failed	 * so we had to force link.  In this case, we need to force the	 * configuration of the MAC to match the "fc" parameter.	 */	if (mac->autoneg_failed) {		if (hw->media_type == e1000_media_type_fiber ||		    hw->media_type == e1000_media_type_internal_serdes)			ret_val = e1000_force_mac_fc_generic(hw);	} else {		if (hw->media_type == e1000_media_type_copper)			ret_val = e1000_force_mac_fc_generic(hw);	}	if (ret_val) {		DEBUGOUT("Error forcing flow control settings\n");		goto out;	}	/* Check for the case where we have copper media and auto-neg is	 * enabled.  In this case, we need to check and see if Auto-Neg	 * has completed, and if so, how the PHY and link partner has	 * flow control configured.	 */	if ((hw->media_type == e1000_media_type_copper) && mac->autoneg) {		/* Read the MII Status Register and check to see if AutoNeg		 * has completed.  We read this twice because this reg has		 * some "sticky" (latched) bits.		 */		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);		if (ret_val)			goto out;		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);		if (ret_val)			goto out;		if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {			DEBUGOUT("Copper PHY and Auto Neg "			         "has not completed.\n");			goto out;		}		/* The AutoNeg process has completed, so we now need to		 * read both the Auto Negotiation Advertisement		 * Register (Address 4) and the Auto_Negotiation Base		 * Page Ability Register (Address 5) to determine how		 * flow control was negotiated.		 */		ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,					    &mii_nway_adv_reg);		if (ret_val)			goto out;		ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,					    &mii_nway_lp_ability_reg);		if (ret_val)			goto out;		/* Two bits in the Auto Negotiation Advertisement Register		 * (Address 4) and two bits in the Auto Negotiation Base		 * Page Ability Register (Address 5) determine flow control		 * for both the PHY and the link partner.  The following		 * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,		 * 1999, describes these PAUSE resolution bits and how flow		 * control is determined based upon these settings.		 * NOTE:  DC = Don't Care		 *		 *   LOCAL DEVICE  |   LINK PARTNER		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution		 *-------|---------|-------|---------|--------------------		 *   0   |    0    |  DC   |   DC    | e1000_fc_none		 *   0   |    1    |   0   |   DC    | e1000_fc_none		 *   0   |    1    |   1   |    0    | e1000_fc_none		 *   0   |    1    |   1   |    1    | e1000_fc_tx_pause		 *   1   |    0    |   0   |   DC    | e1000_fc_none		 *   1   |   DC    |   1   |   DC    | e1000_fc_full		 *   1   |    1    |   0   |    0    | e1000_fc_none		 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause		 *		 */		/* Are both PAUSE bits set to 1?  If so, this implies		 * Symmetric Flow Control is enabled at both ends.  The		 * ASM_DIR bits are irrelevant per the spec.		 *		 * For Symmetric Flow Control:		 *		 *   LOCAL DEVICE  |   LINK PARTNER		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result		 *-------|---------|-------|---------|--------------------		 *   1   |   DC    |   1   |   DC    | E1000_fc_full		 *		 */		if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&		    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {			/* Now we need to check if the user selected RX ONLY			 * of pause frames.  In this case, we had to advertise			 * FULL flow control because we could not advertise RX			 * ONLY. Hence, we must now check to see if we need to			 * turn OFF  the TRANSMISSION of PAUSE frames.			 */			if (mac->original_fc == e1000_fc_full) {				mac->fc = e1000_fc_full;				DEBUGOUT("Flow Control = FULL.\r\n");			} else {				mac->fc = e1000_fc_rx_pause;				DEBUGOUT("Flow Control = "				         "RX PAUSE frames only.\r\n");			}		}		/* For receiving PAUSE frames ONLY.		 *		 *   LOCAL DEVICE  |   LINK PARTNER		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result		 *-------|---------|-------|---------|--------------------		 *   0   |    1    |   1   |    1    | e1000_fc_tx_pause		 *		 */		else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&		          (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&		          (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&		          (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {			mac->fc = e1000_fc_tx_pause;			DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n");		}		/* For transmitting PAUSE frames ONLY.		 *		 *   LOCAL DEVICE  |   LINK PARTNER		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result		 *-------|---------|-------|---------|--------------------		 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause		 *		 */		else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&		         (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&		         !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&		         (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {			mac->fc = e1000_fc_rx_pause;			DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");		}		/* Per the IEEE spec, at this point flow control should be		 * disabled.  However, we want to consider that we could		 * be connected to a legacy switch that doesn't advertise		 * desired flow control, but can be forced on the link		 * partner.  So if we advertised no flow control, that is		 * what we will resolve to.  If we advertised some kind of		 * receive capability (Rx Pause Only or Full Flow Control)		 * and the link partner advertised none, we will configure		 * ourselves to enable Rx Flow Control only.  We can do		 * this safely for two reasons:  If the link partner really		 * didn't want flow control enabled, and we enable Rx, no		 * harm done since we won't be receiving any PAUSE frames		 * anyway.  If the intent on the link partner was to have		 * flow control enabled, then by us enabling RX only, we		 * can at least receive pause frames and process them.		 * This is a good idea because in most cases, since we are		 * predominantly a server NIC, more times than not we will		 * be asked to delay transmission of packets than asking		 * our link partner to pause transmission of frames.		 */		else if ((mac->original_fc == e1000_fc_none ||		          mac->original_fc == e1000_fc_tx_pause) ||		         mac->fc_strict_ieee) {			mac->fc = e1000_fc_none;			DEBUGOUT("Flow Control = NONE.\r\n");		} else {			mac->fc = e1000_fc_rx_pause;			DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");		}		/* Now we need to do one last check...  If we auto-		 * negotiated to HALF DUPLEX, flow control should not be		 * enabled per IEEE 802.3 spec.		 */		ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);		if (ret_val) {			DEBUGOUT("Error getting link speed and duplex\n");			goto out;		}		if (duplex == HALF_DUPLEX)			mac->fc = e1000_fc_none;		/* Now we call a subroutine to actually force the MAC		 * controller to use the correct flow control settings.		 */		ret_val = e1000_force_mac_fc_generic(hw);		if (ret_val) {			DEBUGOUT("Error forcing flow control settings\n");			goto out;		}	}out:	return ret_val;}/** *  e1000_get_speed_and_duplex_copper_generic - Retreive current speed/duplex *  @hw: pointer to the HW structure *  @speed: stores the current speed *  @duplex: stores the current duplex * *  Read the status register for the current speed/duplex and store the current *  speed and duplex for copper connections. **/s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,                                              u16 *duplex){	u32 status;	DEBUGFUNC("e1000_get_speed_and_duplex_copper_generic");	status = E1000_READ_REG(hw, E1000_STATUS);	if (status & E1000_STATUS_SPEED_1000) {		*speed = SPEED_1000;		DEBUGOUT("1000 Mbs, ");	} else if (status & E1000_STATUS_SPEED_100) {		*speed = SPEED_100;		DEBUGOUT("100 Mbs, ");	} else {		*speed = SPEED_10;		DEBUGOUT("10 Mbs, ");	}	if (status & E1000_STATUS_FD) {		*duplex = FULL_DUPLEX;		DEBUGOUT("Full Duplex\n");	} else {		*duplex = HALF_DUPLEX;		DEBUGOUT("Half Duplex\n");	}	return E1000_SUCCESS;}/** *  e1000_get_speed_and_duplex_fiber_generic - Retreive current speed/duplex *  @hw: pointer to the HW structure *  @speed: stores the current speed *  @duplex: stores the current duplex * *  Sets the speed and duplex to gigabit full duplex (the only possible option) *  for fiber/serdes links. **/s32 e1000_get_speed_and_duplex_fiber_serdes_generic(struct e1000_hw *hw,                                                    u16 *speed, u16 *duplex){	DEBUGFUNC("e1000_get_speed_and_duplex_fiber_serdes_generic");	*speed = SPEED_1000;	*duplex = FULL_DUPLEX;	return E1000_SUCCESS;}/** *  e1000_get_hw_semaphore_generic - Acquire hardware semaphore *  @hw: pointer to the HW structure * *  Acquire the HW semaphore to access the PHY or NVM **/s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw){	u32 swsm;	s32 ret_val = E1000_SUCCESS;	s32 timeout = hw->nvm.word_size + 1;	s32 i = 0;	DEBUGFUNC("e1000_get_hw_semaphore_generic");	/* Get the SW semaphore */	while (i < timeout) {		swsm = E1000_READ_REG(hw, E1000_SWSM);		if (!(swsm & E1000_SWSM_SMBI))			break;		usec_delay(50);		i++;	}	if (i == timeout) {		DEBUGOUT("Driver can't access device - SMBI bit is set.\n");		ret_val = -E1000_ERR_NVM;		goto out;	}	/* Get the FW semaphore. */	for (i = 0; i < timeout; i++) {		swsm = E1000_READ_REG(hw, E1000_SWSM);		E1000_WRITE_REG(hw, E1000_SWSM, swsm | E1000_SWSM_SWESMBI);		/* Semaphore acquired if bit latched */		if (E1000_READ_REG(hw, E1000_SWSM) & E1000_SWSM_SWESMBI)

⌨️ 快捷键说明

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