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

📄 e1000_mac.c

📁 DELL755 Intel 网卡驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
 *  e1000_check_for_copper_link_generic - Check for link (Copper) *  @hw: pointer to the HW structure * *  Checks to see of the link status of the hardware has changed.  If a *  change in link status has been detected, then we read the PHY registers *  to get the current speed/duplex if link exists. **/s32 e1000_check_for_copper_link_generic(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	s32 ret_val;	bool link;	DEBUGFUNC("e1000_check_for_copper_link");	/*	 * We only want to go out to the PHY registers to see if Auto-Neg	 * has completed and/or if our link status has changed.  The	 * get_link_status flag is set upon receiving a Link Status	 * Change or Rx Sequence Error interrupt.	 */	if (!mac->get_link_status) {		ret_val = E1000_SUCCESS;		goto out;	}	/*	 * First we want to see if the MII Status Register reports	 * link.  If so, then we want to get the current speed/duplex	 * of the PHY.	 */	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;	/*	 * Check if there was DownShift, must be checked	 * immediately after link-up	 */	e1000_check_downshift_generic(hw);	/*	 * If we are forcing speed/duplex, then we simply return since	 * we have already determined whether we have link or not.	 */	if (!mac->autoneg) {		ret_val = -E1000_ERR_CONFIG;		goto out;	}	/*	 * Auto-Neg is enabled.  Auto Speed Detection takes care	 * of MAC speed/duplex configuration.  So we only need to	 * configure Collision Distance in the MAC.	 */	e1000_config_collision_dist_generic(hw);	/*	 * 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");	}out:	return ret_val;}/** *  e1000_check_for_fiber_link_generic - 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. **/s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	u32 rxcw;	u32 ctrl;	u32 status;	s32 ret_val = E1000_SUCCESS;	DEBUGFUNC("e1000_check_for_fiber_link_generic");	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) == 1 == have signal */	if ((ctrl & E1000_CTRL_SWDPIN1) && (!(status & E1000_STATUS_LU)) &&	    (!(rxcw & E1000_RXCW_C))) {		if (mac->autoneg_failed == 0) {			mac->autoneg_failed = 1;			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_check_for_serdes_link_generic - Check for link (Serdes) *  @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. **/s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	u32 rxcw;	u32 ctrl;	u32 status;	s32 ret_val = E1000_SUCCESS;	DEBUGFUNC("e1000_check_for_serdes_link_generic");	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), 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.	 */	/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */	if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {		if (mac->autoneg_failed == 0) {			mac->autoneg_failed = 1;			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;	} else if (!(E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW))) {		/*		 * If we force link for non-auto-negotiation switch, check		 * link status based on MAC synchronization for internal		 * serdes media type.		 */		/* SYNCH bit and IV bit are sticky. */		usec_delay(10);		if (E1000_RXCW_SYNCH & E1000_READ_REG(hw, E1000_RXCW)) {			if (!(rxcw & E1000_RXCW_IV)) {				mac->serdes_has_link = true;				DEBUGOUT("SERDES: Link is up.\n");			}		} else {			mac->serdes_has_link = false;			DEBUGOUT("SERDES: Link is down.\n");		}	}	if (E1000_TXCW_ANE & E1000_READ_REG(hw, E1000_TXCW)) {		status = E1000_READ_REG(hw, E1000_STATUS);		mac->serdes_has_link = (status & E1000_STATUS_LU)					? true					: false;	}out:	return ret_val;}/** *  e1000_setup_link_generic - Setup flow control and link settings *  @hw: pointer to the HW structure * *  Determines which flow control settings to use, then configures flow *  control.  Calls the appropriate media-specific link configuration *  function.  Assuming the adapter has a valid link partner, a valid link *  should be established.  Assumes the hardware has previously been reset *  and the transmitter and receiver are not enabled. **/s32 e1000_setup_link_generic(struct e1000_hw *hw){	s32 ret_val = E1000_SUCCESS;	DEBUGFUNC("e1000_setup_link_generic");	/*	 * In the case of the phy reset being blocked, we already have a link.	 * We do not need to set it up again.	 */	if (hw->phy.ops.check_reset_block)		if (hw->phy.ops.check_reset_block(hw))			goto out;	/*	 * If flow control is set to default, set flow control based on	 * the EEPROM flow control settings.	 */	if (hw->fc.type == e1000_fc_default) {		ret_val = e1000_set_default_fc_generic(hw);		if (ret_val)			goto out;	}	/*	 * We want to save off the original Flow Control configuration just	 * in case we get disconnected and then reconnected into a different	 * hub or switch with different Flow Control capabilities.	 */	hw->fc.original_type = hw->fc.type;	DEBUGOUT1("After fix-ups FlowControl is now = %x\n", hw->fc.type);	/* Call the necessary media_type subroutine to configure the link. */	ret_val = hw->mac.ops.setup_physical_interface(hw);	if (ret_val)		goto out;	/*	 * Initialize the flow control address, type, and PAUSE timer	 * registers to their default values.  This is done even if flow	 * control is disabled, because it does not hurt anything to	 * initialize these registers.	 */	DEBUGOUT("Initializing the Flow Control address, type and timer regs\n");	E1000_WRITE_REG(hw, E1000_FCT, FLOW_CONTROL_TYPE);	E1000_WRITE_REG(hw, E1000_FCAH, FLOW_CONTROL_ADDRESS_HIGH);	E1000_WRITE_REG(hw, E1000_FCAL, FLOW_CONTROL_ADDRESS_LOW);	E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time);	ret_val = e1000_set_fc_watermarks_generic(hw);out:	return ret_val;}/** *  e1000_setup_fiber_serdes_link_generic - Setup link for fiber/serdes *  @hw: pointer to the HW structure * *  Configures collision distance and flow control for fiber and serdes *  links.  Upon successful setup, poll for link. **/s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw){	u32 ctrl;	s32 ret_val = E1000_SUCCESS;	DEBUGFUNC("e1000_setup_fiber_serdes_link_generic");	ctrl = E1000_READ_REG(hw, E1000_CTRL);	/* Take the link out of reset */	ctrl &= ~E1000_CTRL_LRST;	e1000_config_collision_dist_generic(hw);	ret_val = e1000_commit_fc_settings_generic(hw);	if (ret_val)		goto out;	/*	 * Since auto-negotiation is enabled, take the link out of reset (the	 * link will be in reset, because we previously reset the chip). This	 * will restart auto-negotiation.  If auto-negotiation is successful	 * then the link-up status bit will be set and the flow control enable	 * bits (RFCE and TFCE) will be set according to their negotiated value.	 */	DEBUGOUT("Auto-negotiation enabled\n");	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);	E1000_WRITE_FLUSH(hw);	msec_delay(1);	/*	 * For these adapters, the SW definable pin 1 is set when the optics	 * detect a signal.  If we have a signal, then poll for a "Link-Up"	 * indication.	 */	if (hw->phy.media_type == e1000_media_type_internal_serdes ||	    (E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) {		ret_val = e1000_poll_fiber_serdes_link_generic(hw);	} else {		DEBUGOUT("No signal detected\n");	}out:	return ret_val;}/** *  e1000_config_collision_dist_generic - Configure collision distance *  @hw: pointer to the HW structure * *  Configures the collision distance to the default value and is used *  during link setup. Currently no func pointer exists and all *  implementations are handled in the generic version of this function. **/void e1000_config_collision_dist_generic(struct e1000_hw *hw){	u32 tctl;	DEBUGFUNC("e1000_config_collision_dist_generic");	tctl = E1000_READ_REG(hw, E1000_TCTL);	tctl &= ~E1000_TCTL_COLD;	tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;	E1000_WRITE_REG(hw, E1000_TCTL, tctl);	E1000_WRITE_FLUSH(hw);}/** *  e1000_poll_fiber_serdes_link_generic - Poll for link up *  @hw: pointer to the HW structure * *  Polls for link up by reading the status register, if link fails to come *  up with auto-negotiation, then the link is forced if a signal is detected. **/s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	u32 i, status;	s32 ret_val = E1000_SUCCESS;	DEBUGFUNC("e1000_poll_fiber_serdes_link_generic");	/*	 * If we have a signal (the cable is plugged in, or assumed true for	 * serdes media) then poll for a "Link-Up" indication in the Device	 * Status Register.  Time-out if a link isn't seen in 500 milliseconds	 * seconds (Auto-negotiation should complete in less than 500	 * milliseconds even if the other end is doing it in SW).	 */	for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) {		msec_delay(10);		status = E1000_READ_REG(hw, E1000_STATUS);		if (status & E1000_STATUS_LU)			break;	}	if (i == FIBER_LINK_UP_LIMIT) {		DEBUGOUT("Never got a valid link from auto-neg!!!\n");		mac->autoneg_failed = 1;		/*		 * AutoNeg failed to achieve a link, so we'll call		 * mac->check_for_link. This routine will force the		 * link up if we detect a signal. This will allow us to		 * communicate with non-autonegotiating link partners.		 */		ret_val = hw->mac.ops.check_for_link(hw);		if (ret_val) {			DEBUGOUT("Error while checking for link\n");			goto out;		}		mac->autoneg_failed = 0;	} else {		mac->autoneg_failed = 0;		DEBUGOUT("Valid Link Found\n");	}out:	return ret_val;}/** *  e1000_commit_fc_settings_generic - Configure flow control *  @hw: pointer to the HW structure * *  Write the flow control settings to the Transmit Config Word Register (TXCW) *  base on the flow control settings in e1000_mac_info. **/s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	u32 txcw;	s32 ret_val = E1000_SUCCESS;	DEBUGFUNC("e1000_commit_fc_settings_generic");	/*	 * Check for a software override of the flow control settings, and	 * setup the device accordingly.  If auto-negotiation is enabled, then	 * software will have to set the "PAUSE" bits to the correct value in	 * the Transmit Config Word Register (TXCW) and re-start auto-	 * negotiation.  However, if auto-negotiation is disabled, then	 * software will have to manually configure the two flow control enable	 * bits in the CTRL register.	 *	 * 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 but we	 *          do not support receiving pause frames).	 *      3:  Both Rx and Tx flow control (symmetric) are enabled.	 */	switch (hw->fc.type) {	case e1000_fc_none:		/* Flow control completely disabled by a software over-ride. */		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);		break;	case e1000_fc_rx_pause:		/*		 * Rx Flow control is enabled and Tx Flow control is disabled		 * by a software over-ride. Since there really isn't a way to		 * advertise that we are capable of Rx Pause ONLY, we will		 * advertise that we support both symmetric and asymmetric RX		 * PAUSE.  Later, we will disable the adapter's ability to send		 * PAUSE frames.		 */		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);		break;	case e1000_fc_tx_pause:		/*		 * Tx Flow control is enabled, and Rx Flow control is disabled,		 * by a software over-ride.		 */		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);		break;	case e1000_fc_full:		/*		 * Flow control (both Rx and Tx) is enabled by a software

⌨️ 快捷键说明

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