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

📄 e1000_mac.c

📁 Intel 82546系列lan driver源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	er32(BPRC);	er32(MPRC);	er32(GPTC);	er32(GORCL);	er32(GORCH);	er32(GOTCL);	er32(GOTCH);	er32(RNBC);	er32(RUC);	er32(RFC);	er32(ROC);	er32(RJC);	er32(TORL);	er32(TORH);	er32(TOTL);	er32(TOTH);	er32(TPR);	er32(TPT);	er32(MPTC);	er32(BPTC);}/** *  e1000e_check_for_copper_link - 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 e1000e_check_for_copper_link(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	s32 ret_val;	bool 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 = e1000e_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	 */	e1000e_check_downshift(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.	 */	e1000e_config_collision_dist(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 = e1000e_config_fc_after_link_up(hw);	if (ret_val)		e_dbg("Error configuring flow control\n");out:	return ret_val;}/** *  e1000e_check_for_fiber_link - 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 e1000e_check_for_fiber_link(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	u32 rxcw;	u32 ctrl;	u32 status;	s32 ret_val = E1000_SUCCESS;	ctrl = er32(CTRL);	status = er32(STATUS);	rxcw = er32(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;		}		e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n");		/* Disable auto-negotiation in the TXCW register */		ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));		/* Force link-up and also force full-duplex. */		ctrl = er32(CTRL);		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);		ew32(CTRL, ctrl);		/* Configure Flow Control after forcing link up. */		ret_val = e1000e_config_fc_after_link_up(hw);		if (ret_val) {			e_dbg("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.		 */		e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n");		ew32(TXCW, mac->txcw);		ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));		mac->serdes_has_link = true;	}out:	return ret_val;}/** *  e1000e_check_for_serdes_link - 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 e1000e_check_for_serdes_link(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	u32 rxcw;	u32 ctrl;	u32 status;	s32 ret_val = E1000_SUCCESS;	ctrl = er32(CTRL);	status = er32(STATUS);	rxcw = er32(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;		}		e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n");		/* Disable auto-negotiation in the TXCW register */		ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE));		/* Force link-up and also force full-duplex. */		ctrl = er32(CTRL);		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);		ew32(CTRL, ctrl);		/* Configure Flow Control after forcing link up. */		ret_val = e1000e_config_fc_after_link_up(hw);		if (ret_val) {			e_dbg("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.		 */		e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n");		ew32(TXCW, mac->txcw);		ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));		mac->serdes_has_link = true;	} else if (!(E1000_TXCW_ANE & er32(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. */		udelay(10);		rxcw = er32(RXCW);		if (rxcw & E1000_RXCW_SYNCH) {			if (!(rxcw & E1000_RXCW_IV)) {				mac->serdes_has_link = true;				e_dbg("SERDES: Link up - forced.\n");			}		} else {			mac->serdes_has_link = false;			e_dbg("SERDES: Link down - force failed.\n");		}	}	if (E1000_TXCW_ANE & er32(TXCW)) {		status = er32(STATUS);		if (status & E1000_STATUS_LU) {			/* SYNCH bit and IV bit are sticky, so reread rxcw. */			udelay(10);			rxcw = er32(RXCW);			if (rxcw & E1000_RXCW_SYNCH) {				if (!(rxcw & E1000_RXCW_IV)) {					mac->serdes_has_link = true;					e_dbg("SERDES: Link up - autoneg "					   "completed sucessfully.\n");				} else {					mac->serdes_has_link = false;					e_dbg("SERDES: Link down - invalid"					   "codewords detected in autoneg.\n");				}			} else {				mac->serdes_has_link = false;				e_dbg("SERDES: Link down - no sync.\n");			}		} else {			mac->serdes_has_link = false;			e_dbg("SERDES: Link down - autoneg failed\n");		}	}out:	return ret_val;}/** *  e1000e_setup_link - 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 e1000e_setup_link(struct e1000_hw *hw){	s32 ret_val = E1000_SUCCESS;	/*	 * 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 (e1000_check_reset_block(hw))			goto out;	/*	 * If requested flow control is set to default, set flow control	 * based on the EEPROM flow control settings.	 */	if (hw->fc.requested_mode == e1000_fc_default) {		ret_val = e1000_set_default_fc_generic(hw);		if (ret_val)			goto out;	}	/*	 * Save off the requested flow control mode for use later.  Depending	 * on the link partner's capabilities, we may or may not use this mode.	 */	hw->fc.current_mode = hw->fc.requested_mode;	e_dbg("After fix-ups FlowControl is now = %x\n",		hw->fc.current_mode);	/* 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.	 */	e_dbg("Initializing the Flow Control address, type and timer regs\n");	ew32(FCT, FLOW_CONTROL_TYPE);	ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);	ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);	ew32(FCTTV, hw->fc.pause_time);	ret_val = e1000e_set_fc_watermarks(hw);out:	return ret_val;}/** *  e1000e_setup_fiber_serdes_link - 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 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw){	u32 ctrl;	s32 ret_val = E1000_SUCCESS;	ctrl = er32(CTRL);	/* Take the link out of reset */	ctrl &= ~E1000_CTRL_LRST;	e1000e_config_collision_dist(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.	 */	e_dbg("Auto-negotiation enabled\n");	ew32(CTRL, ctrl);	e1e_flush();	msleep(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 ||	    (er32(CTRL) & E1000_CTRL_SWDPIN1)) {		ret_val = e1000_poll_fiber_serdes_link_generic(hw);	} else {		e_dbg("No signal detected\n");	}out:	return ret_val;}/** *  e1000e_config_collision_dist - 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 e1000e_config_collision_dist(struct e1000_hw *hw){	u32 tctl;	tctl = er32(TCTL);	tctl &= ~E1000_TCTL_COLD;	tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;	ew32(TCTL, tctl);	e1e_flush();}/** *  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. **/static 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;	/*	 * 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++) {		msleep(10);		status = er32(STATUS);		if (status & E1000_STATUS_LU)			break;	}	if (i == FIBER_LINK_UP_LIMIT) {		e_dbg("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) {			e_dbg("Error while checking for link\n");			goto out;		}		mac->autoneg_failed = 0;	} else {		mac->autoneg_failed = 0;		e_dbg("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. **/static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw){

⌨️ 快捷键说明

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