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

📄 e1000_phy.c

📁 e1000 8.0.1 version.最新的e1000 linux下的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
	usec_delay(2);	hw->phy.ops.release(hw);out:	return ret_val;}/** *  e1000_copper_link_setup_m88 - Setup m88 PHY's for copper link *  @hw: pointer to the HW structure * *  Sets up MDI/MDI-X and polarity for m88 PHY's.  If necessary, transmit clock *  and downshift values are set also. **/s32 e1000_copper_link_setup_m88(struct e1000_hw *hw){	struct e1000_phy_info *phy = &hw->phy;	s32 ret_val;	u16 phy_data;	DEBUGFUNC("e1000_copper_link_setup_m88");	if (phy->reset_disable) {		ret_val = E1000_SUCCESS;		goto out;	}	/* Enable CRS on TX. This must be set for half-duplex operation. */	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);	if (ret_val)		goto out;	phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;	/*	 * Options:	 *   MDI/MDI-X = 0 (default)	 *   0 - Auto for all speeds	 *   1 - MDI mode	 *   2 - MDI-X mode	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)	 */	phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;	switch (phy->mdix) {		case 1:			phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;			break;		case 2:			phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;			break;		case 3:			phy_data |= M88E1000_PSCR_AUTO_X_1000T;			break;		case 0:		default:			phy_data |= M88E1000_PSCR_AUTO_X_MODE;			break;	}	/*	 * Options:	 *   disable_polarity_correction = 0 (default)	 *       Automatic Correction for Reversed Cable Polarity	 *   0 - Disabled	 *   1 - Enabled	 */	phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;	if (phy->disable_polarity_correction == 1)		phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;	ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);	if (ret_val)		goto out;	if (phy->revision < E1000_REVISION_4) {		/*		 * Force TX_CLK in the Extended PHY Specific Control Register		 * to 25MHz clock.		 */		ret_val = phy->ops.read_reg(hw,		                             M88E1000_EXT_PHY_SPEC_CTRL,		                             &phy_data);		if (ret_val)			goto out;		phy_data |= M88E1000_EPSCR_TX_CLK_25;		if ((phy->revision == E1000_REVISION_2) &&		    (phy->id == M88E1111_I_PHY_ID)) {			/* 82573L PHY - set the downshift counter to 5x. */			phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK;			phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X;		} else {			/* Configure Master and Slave downshift values */			phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |			             M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);			phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |			             M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);		}		ret_val = phy->ops.write_reg(hw,		                             M88E1000_EXT_PHY_SPEC_CTRL,		                             phy_data);		if (ret_val)			goto out;	}	/* Commit the changes. */	ret_val = phy->ops.commit(hw);	if (ret_val) {		DEBUGOUT("Error committing the PHY changes\n");		goto out;	}out:	return ret_val;}/** *  e1000_copper_link_setup_igp - Setup igp PHY's for copper link *  @hw: pointer to the HW structure * *  Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for *  igp PHY's. **/s32 e1000_copper_link_setup_igp(struct e1000_hw *hw){	struct e1000_phy_info *phy = &hw->phy;	s32 ret_val;	u16 data;	DEBUGFUNC("e1000_copper_link_setup_igp");	if (phy->reset_disable) {		ret_val = E1000_SUCCESS;		goto out;	}	ret_val = e1000_phy_hw_reset(hw);	if (ret_val) {		DEBUGOUT("Error resetting the PHY.\n");		goto out;	}	/*	 * Wait 100ms for MAC to configure PHY from NVM settings, to avoid	 * timeout issues when LFS is enabled.	 */	msec_delay(100);	/*	 * The NVM settings will configure LPLU in D3 for	 * non-IGP1 PHYs.	 */	if (phy->type == e1000_phy_igp) {		/* disable lplu d3 during driver init */		ret_val = e1000_set_d3_lplu_state(hw, FALSE);		if (ret_val) {			DEBUGOUT("Error Disabling LPLU D3\n");			goto out;		}	}	/* disable lplu d0 during driver init */	ret_val = e1000_set_d0_lplu_state(hw, FALSE);	if (ret_val) {		DEBUGOUT("Error Disabling LPLU D0\n");		goto out;	}	/* Configure mdi-mdix settings */	ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data);	if (ret_val)		goto out;	data &= ~IGP01E1000_PSCR_AUTO_MDIX;	switch (phy->mdix) {	case 1:		data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;		break;	case 2:		data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;		break;	case 0:	default:		data |= IGP01E1000_PSCR_AUTO_MDIX;		break;	}	ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data);	if (ret_val)		goto out;	/* set auto-master slave resolution settings */	if (hw->mac.autoneg) {		/*		 * when autonegotiation advertisement is only 1000Mbps then we		 * should disable SmartSpeed and enable Auto MasterSlave		 * resolution as hardware default.		 */		if (phy->autoneg_advertised == ADVERTISE_1000_FULL) {			/* Disable SmartSpeed */			ret_val = phy->ops.read_reg(hw,			                             IGP01E1000_PHY_PORT_CONFIG,			                             &data);			if (ret_val)				goto out;			data &= ~IGP01E1000_PSCFR_SMART_SPEED;			ret_val = phy->ops.write_reg(hw,			                             IGP01E1000_PHY_PORT_CONFIG,			                             data);			if (ret_val)				goto out;			/* Set auto Master/Slave resolution process */			ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data);			if (ret_val)				goto out;			data &= ~CR_1000T_MS_ENABLE;			ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data);			if (ret_val)				goto out;		}		ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data);		if (ret_val)			goto out;		/* load defaults for future use */		phy->original_ms_type = (data & CR_1000T_MS_ENABLE) ?			((data & CR_1000T_MS_VALUE) ?			e1000_ms_force_master :			e1000_ms_force_slave) :			e1000_ms_auto;		switch (phy->ms_type) {		case e1000_ms_force_master:			data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);			break;		case e1000_ms_force_slave:			data |= CR_1000T_MS_ENABLE;			data &= ~(CR_1000T_MS_VALUE);			break;		case e1000_ms_auto:			data &= ~CR_1000T_MS_ENABLE;		default:			break;		}		ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data);		if (ret_val)			goto out;	}out:	return ret_val;}/** *  e1000_copper_link_autoneg - Setup/Enable autoneg for copper link *  @hw: pointer to the HW structure * *  Performs initial bounds checking on autoneg advertisement parameter, then *  configure to advertise the full capability.  Setup the PHY to autoneg *  and restart the negotiation process between the link partner.  If *  autoneg_wait_to_complete, then wait for autoneg to complete before exiting. **/s32 e1000_copper_link_autoneg(struct e1000_hw *hw){	struct e1000_phy_info *phy = &hw->phy;	s32 ret_val;	u16 phy_ctrl;	DEBUGFUNC("e1000_copper_link_autoneg");	/*	 * Perform some bounds checking on the autoneg advertisement	 * parameter.	 */	phy->autoneg_advertised &= phy->autoneg_mask;	/*	 * If autoneg_advertised is zero, we assume it was not defaulted	 * by the calling code so we set to advertise full capability.	 */	if (phy->autoneg_advertised == 0)		phy->autoneg_advertised = phy->autoneg_mask;	DEBUGOUT("Reconfiguring auto-neg advertisement params\n");	ret_val = e1000_phy_setup_autoneg(hw);	if (ret_val) {		DEBUGOUT("Error Setting up Auto-Negotiation\n");		goto out;	}	DEBUGOUT("Restarting Auto-Neg\n");	/*	 * Restart auto-negotiation by setting the Auto Neg Enable bit and	 * the Auto Neg Restart bit in the PHY control register.	 */	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);	if (ret_val)		goto out;	phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);	if (ret_val)		goto out;	/*	 * Does the user want to wait for Auto-Neg to complete here, or	 * check at a later time (for example, callback routine).	 */	if (phy->autoneg_wait_to_complete) {		ret_val = e1000_wait_autoneg(hw);		if (ret_val) {			DEBUGOUT("Error while waiting for "			         "autoneg to complete\n");			goto out;		}	}	hw->mac.get_link_status = TRUE;out:	return ret_val;}/** *  e1000_phy_setup_autoneg - Configure PHY for auto-negotiation *  @hw: pointer to the HW structure * *  Reads the MII auto-neg advertisement register and/or the 1000T control *  register and if the PHY is already setup for auto-negotiation, then *  return successful.  Otherwise, setup advertisement and flow control to *  the appropriate values for the wanted auto-negotiation. **/s32 e1000_phy_setup_autoneg(struct e1000_hw *hw){	struct e1000_phy_info *phy = &hw->phy;	s32 ret_val;	u16 mii_autoneg_adv_reg;	u16 mii_1000t_ctrl_reg = 0;	DEBUGFUNC("e1000_phy_setup_autoneg");	phy->autoneg_advertised &= phy->autoneg_mask;	/* Read the MII Auto-Neg Advertisement Register (Address 4). */	ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);	if (ret_val)		goto out;	if (phy->autoneg_mask & ADVERTISE_1000_FULL) {		/* Read the MII 1000Base-T Control Register (Address 9). */		ret_val = phy->ops.read_reg(hw,		                            PHY_1000T_CTRL,		                            &mii_1000t_ctrl_reg);		if (ret_val)			goto out;	}	/*	 * Need to parse both autoneg_advertised and fc and set up	 * the appropriate PHY registers.  First we will parse for	 * autoneg_advertised software override.  Since we can advertise	 * a plethora of combinations, we need to check each bit	 * individually.	 */	/*	 * First we clear all the 10/100 mb speed bits in the Auto-Neg	 * Advertisement Register (Address 4) and the 1000 mb speed bits in	 * the  1000Base-T Control Register (Address 9).	 */	mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS |	                         NWAY_AR_100TX_HD_CAPS |	                         NWAY_AR_10T_FD_CAPS   |	                         NWAY_AR_10T_HD_CAPS);	mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);	DEBUGOUT1("autoneg_advertised %x\n", phy->autoneg_advertised);	/* Do we want to advertise 10 Mb Half Duplex? */	if (phy->autoneg_advertised & ADVERTISE_10_HALF) {		DEBUGOUT("Advertise 10mb Half duplex\n");		mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;	}	/* Do we want to advertise 10 Mb Full Duplex? */	if (phy->autoneg_advertised & ADVERTISE_10_FULL) {		DEBUGOUT("Advertise 10mb Full duplex\n");		mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;	}	/* Do we want to advertise 100 Mb Half Duplex? */	if (phy->autoneg_advertised & ADVERTISE_100_HALF) {		DEBUGOUT("Advertise 100mb Half duplex\n");		mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;	}	/* Do we want to advertise 100 Mb Full Duplex? */	if (phy->autoneg_advertised & ADVERTISE_100_FULL) {		DEBUGOUT("Advertise 100mb Full duplex\n");		mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;	}	/* We do not allow the Phy to advertise 1000 Mb Half Duplex */	if (phy->autoneg_advertised & ADVERTISE_1000_HALF) {		DEBUGOUT("Advertise 1000mb Half duplex request denied!\n");	}	/* Do we want to advertise 1000 Mb Full Duplex? */	if (phy->autoneg_advertised & ADVERTISE_1000_FULL) {		DEBUGOUT("Advertise 1000mb Full duplex\n");		mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;	}	/*	 * Check for a software override of the flow control settings, and	 * setup the PHY advertisement registers accordingly.  If	 * auto-negotiation is enabled, then software will have to set the	 * "PAUSE" bits to the correct value in the Auto-Negotiation	 * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-	 * negotiation.	 *	 * 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.	 *  other:  No software override.  The flow control configuration	 *          in the EEPROM is used.	 */	switch (hw->fc.type) {	case e1000_fc_none:		/*		 * Flow control (Rx & Tx) is completely disabled by a		 * software over-ride.		 */		mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);		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		 * (in e1000_config_fc_after_link_up) we will disable the		 * hw's ability to send PAUSE frames.		 */		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);		break;	case e1000_fc_tx_pause:		/*		 * Tx Flow control is enabled, and Rx Flow control is		 * disabled, by a software over-ride.		 */		mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;		mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;		break;	case e1000_fc_full:		/*		 * Flow control (both Rx and Tx) is enabled by a software		 * over-ride.		 */		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);		break;	default:		DEBUGOUT("Flow control param set incorrectly\n");		ret_val = -E1000_ERR_CONFIG;		goto out;	}	ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);	if (ret_val)		goto out;	DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);	if (phy->autoneg_mask & ADVERTISE_1000_FULL) {		ret_val = phy->ops.write_reg(hw,		                              PHY_1000T_CTRL,		                              mii_1000t_ctrl_reg);		if (ret_val)			goto out;	}out:	return ret_val;}/** *  e1000_setup_copper_link_generic - Configure copper link settings *  @hw: pointer to the HW structure * *  Calls the appropriate function to configure the link for auto-neg or forced *  speed and duplex.  Then we check for link, once link is established calls *  to configure collision distance and flow control are called.  If link is *  not established, we return -E1000_ERR_PHY (-2). **/s32 e1000_setup_copper_link_generic(struct e1000_hw *hw){	s32 ret_val;	bool link;	DEBUGFUNC("e1000_setup_copper_link_generic");	if (hw->mac.autoneg) {		/*		 * Setup autoneg and flow control advertisement and perform		 * autonegotiation.		 */		ret_val = e1000_copper_link_autoneg(hw);		if (ret_val)			goto out;	} else {		/*		 * PHY will be set to 10H, 10F, 100H or 100F		 * depending on user settings.		 */		DEBUGOUT("Forcing Speed and Duplex\n");		ret_val = hw->phy.ops.force_speed_duplex(hw);		if (ret_val) {			DEBUGOUT("Error Forcing Speed and Duplex\n");			goto out;		}	}	/*	 * Check link status. Wait up to 100 microseconds for link to become	 * valid.	 */	ret_val = e1000_phy_has_link_generic(hw,

⌨️ 快捷键说明

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