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

📄 lib.c

📁 grub源码分析文档
💻 C
📖 第 1 页 / 共 5 页
字号:
	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:		hw_dbg(hw, "Flow control param set incorrectly\n");		return -E1000_ERR_CONFIG;	}	ew32(CTRL, ctrl);	return 0;}/** *  e1000e_config_fc_after_link_up - 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 e1000e_config_fc_after_link_up(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	s32 ret_val = 0;	u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;	u16 speed, duplex;	/*	 * 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->phy.media_type == e1000_media_type_fiber ||		    hw->phy.media_type == e1000_media_type_internal_serdes)			ret_val = e1000e_force_mac_fc(hw);	} else {		if (hw->phy.media_type == e1000_media_type_copper)			ret_val = e1000e_force_mac_fc(hw);	}	if (ret_val) {		hw_dbg(hw, "Error forcing flow control settings\n");		return ret_val;	}	/*	 * 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->phy.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 = e1e_rphy(hw, PHY_STATUS, &mii_status_reg);		if (ret_val)			return ret_val;		ret_val = e1e_rphy(hw, PHY_STATUS, &mii_status_reg);		if (ret_val)			return ret_val;		if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {			hw_dbg(hw, "Copper PHY and Auto Neg "				 "has not completed.\n");			return ret_val;		}		/*		 * 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 = e1e_rphy(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg);		if (ret_val)			return ret_val;		ret_val = e1e_rphy(hw, PHY_LP_ABILITY,				   &mii_nway_lp_ability_reg);		if (ret_val)			return ret_val;		/*		 * 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 (hw->fc.original_type == e1000_fc_full) {				hw->fc.type = e1000_fc_full;				hw_dbg(hw, "Flow Control = FULL.\r\n");			} else {				hw->fc.type = e1000_fc_rx_pause;				hw_dbg(hw, "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)) {			hw->fc.type = e1000_fc_tx_pause;			hw_dbg(hw, "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)) {			hw->fc.type = e1000_fc_rx_pause;			hw_dbg(hw, "Flow Control = Rx PAUSE frames only.\r\n");		} else {			/*			 * Per the IEEE spec, at this point flow control			 * should be disabled.			 */			hw->fc.type = e1000_fc_none;			hw_dbg(hw, "Flow Control = NONE.\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 = mac->ops.get_link_up_info(hw, &speed, &duplex);		if (ret_val) {			hw_dbg(hw, "Error getting link speed and duplex\n");			return ret_val;		}		if (duplex == HALF_DUPLEX)			hw->fc.type = e1000_fc_none;		/*		 * Now we call a subroutine to actually force the MAC		 * controller to use the correct flow control settings.		 */		ret_val = e1000e_force_mac_fc(hw);		if (ret_val) {			hw_dbg(hw, "Error forcing flow control settings\n");			return ret_val;		}	}	return 0;}/** *  e1000e_get_speed_and_duplex_copper - Retrieve 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 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, u16 *duplex){	u32 status;	status = er32(STATUS);	if (status & E1000_STATUS_SPEED_1000) {		*speed = SPEED_1000;		hw_dbg(hw, "1000 Mbs, ");	} else if (status & E1000_STATUS_SPEED_100) {		*speed = SPEED_100;		hw_dbg(hw, "100 Mbs, ");	} else {		*speed = SPEED_10;		hw_dbg(hw, "10 Mbs, ");	}	if (status & E1000_STATUS_FD) {		*duplex = FULL_DUPLEX;		hw_dbg(hw, "Full Duplex\n");	} else {		*duplex = HALF_DUPLEX;		hw_dbg(hw, "Half Duplex\n");	}	return 0;}/** *  e1000e_get_speed_and_duplex_fiber_serdes - Retrieve 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 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, u16 *speed, u16 *duplex){	*speed = SPEED_1000;	*duplex = FULL_DUPLEX;	return 0;}/** *  e1000e_get_hw_semaphore - Acquire hardware semaphore *  @hw: pointer to the HW structure * *  Acquire the HW semaphore to access the PHY or NVM **/s32 e1000e_get_hw_semaphore(struct e1000_hw *hw){	u32 swsm;	s32 timeout = hw->nvm.word_size + 1;	s32 i = 0;	/* Get the SW semaphore */	while (i < timeout) {		swsm = er32(SWSM);		if (!(swsm & E1000_SWSM_SMBI))			break;		udelay(50);		i++;	}	if (i == timeout) {		hw_dbg(hw, "Driver can't access device - SMBI bit is set.\n");		return -E1000_ERR_NVM;	}	/* Get the FW semaphore. */	for (i = 0; i < timeout; i++) {		swsm = er32(SWSM);		ew32(SWSM, swsm | E1000_SWSM_SWESMBI);		/* Semaphore acquired if bit latched */		if (er32(SWSM) & E1000_SWSM_SWESMBI)			break;		udelay(50);	}	if (i == timeout) {		/* Release semaphores */		e1000e_put_hw_semaphore(hw);		hw_dbg(hw, "Driver can't access the NVM\n");		return -E1000_ERR_NVM;	}	return 0;}/** *  e1000e_put_hw_semaphore - Release hardware semaphore *  @hw: pointer to the HW structure * *  Release hardware semaphore used to access the PHY or NVM **/void e1000e_put_hw_semaphore(struct e1000_hw *hw){	u32 swsm;	swsm = er32(SWSM);	swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);	ew32(SWSM, swsm);}/** *  e1000e_get_auto_rd_done - Check for auto read completion *  @hw: pointer to the HW structure * *  Check EEPROM for Auto Read done bit. **/s32 e1000e_get_auto_rd_done(struct e1000_hw *hw){	s32 i = 0;	while (i < AUTO_READ_DONE_TIMEOUT) {		if (er32(EECD) & E1000_EECD_AUTO_RD)			break;		msleep(1);		i++;	}	if (i == AUTO_READ_DONE_TIMEOUT) {		hw_dbg(hw, "Auto read by HW from NVM has not completed.\n");		return -E1000_ERR_RESET;	}	return 0;}/** *  e1000e_valid_led_default - Verify a valid default LED config *  @hw: pointer to the HW structure *  @data: pointer to the NVM (EEPROM) * *  Read the EEPROM for the current default LED configuration.  If the *  LED configuration is not valid, set to a valid LED configuration. **/s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data){	s32 ret_val;	ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data);	if (ret_val) {		hw_dbg(hw, "NVM Read Error\n");		return ret_val;	}	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)		*data = ID_LED_DEFAULT;	return 0;}/** *  e1000e_id_led_init - *  @hw: pointer to the HW structure * **/s32 e1000e_id_led_init(struct e1000_hw *hw){	struct e1000_mac_info *mac = &hw->mac;	s32 ret_val;	const u32 ledctl_mask = 0x000000FF;	const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON;	const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF;	u16 data, i, temp;	const u16 led_mask = 0x0F;	ret_val = hw->nvm.ops.valid_led_default(hw, &data);	if (ret_val)		return ret_val;	mac->ledctl_default = er32(LEDCTL);	mac->ledctl_mode1 = mac->ledctl_default;	mac->ledctl_mode2 = mac->ledctl_default;	for (i = 0; i < 4; i++) {		temp = (data >> (i << 2)) & led_mask;		switch (temp) {		case ID_LED_ON1_DEF2:		case ID_LED_ON1_ON2:		case ID_LED_ON1_OFF2:			mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3));			mac->ledctl_mode1 |= ledctl_on << (i << 3);			break;		case ID_LED_OFF1_DEF2:		case ID_LED_OFF1_ON2:		case ID_LED_OFF1_OFF2:			mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3));			mac->ledctl_mode1 |= ledctl_off << (i << 3);			break;		default:			/* Do nothing */			break;		}		switch (temp) {		case ID_LED_DEF1_ON2:		case ID_LED_ON1_ON2:		case ID_LED_OFF1_ON2:			mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3));			mac->ledctl_mode2 |= ledctl_on << (i << 3);			break;		case ID_LED_DEF1_OFF2:		case ID_LED_ON1_OFF2:		case ID_LED_OFF1_OFF2:			mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3));			mac->ledctl_mode2 |= ledctl_off << (i << 3);			break;		default:			/* Do nothing */			break;		}	}	return 0;}/** *  e1000e_cleanup_led_generic - 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. **/s32 e1000e_cleanup_led_generic(struct e1000_hw *hw){	ew32(LEDCTL, hw->mac.ledctl_default);	return 0;}/** *  e1000e_blink_led - Blink LED *  @hw: pointer to the HW structure * *  Blink the LEDs which are set to be on. **/s32 e1000e_blink_led(struct e1000_hw *hw){	u32 ledctl_blink = 0;	u32 i;	if (hw->phy.media_type == e1000_media_type_fiber) {		/* always blink LED0 for PCI-E fiber */		ledctl_blink = E1000_LEDCTL_LED0_BLINK |		     (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);	} else {		/*		 * set the blink bit for each LED that's "on" (0x0E)		 * in ledctl_mode2		 */		ledctl_blink = hw->mac.ledctl_mode2;		for (i = 0; i < 4; i++)			if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==			    E1000_LEDCTL_MODE_LED_ON)				ledctl_blink |= (E1000_LEDCTL_LED0_BLINK <<						 (i * 8));	}

⌨️ 快捷键说明

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