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

📄 e1000.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 5 页
字号:
			phy_data &= ~(CR_1000T_MS_VALUE);			break;		case e1000_ms_auto:			phy_data &= ~CR_1000T_MS_ENABLE;		default:			break;		}#endif		if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL,		                                  phy_data)))			return ret_val;	} else {		/* Enable CRS on TX. This must be set for half-duplex operation. */		if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,		                                 &phy_data)))			return ret_val;		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)		 */#if 0		phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;		switch (hw->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:#endif			phy_data |= M88E1000_PSCR_AUTO_X_MODE;#if 0			break;		}#endif		/* Options:		 *   disable_polarity_correction = 0 (default)		 *       Automatic Correction for Reversed Cable Polarity		 *   0 - Disabled		 *   1 - Enabled		 */		phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;		if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,		                                  phy_data)))			return ret_val;		/* Force TX_CLK in the Extended PHY Specific Control Register		 * to 25MHz clock.		 */		if((ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,		                                 &phy_data)))			return ret_val;		phy_data |= M88E1000_EPSCR_TX_CLK_25;#ifdef LINUX_DRIVER		if (hw->phy_revision < M88E1011_I_REV_4) {#endif			/* 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);			if((ret_val = e1000_write_phy_reg(hw,			                                  M88E1000_EXT_PHY_SPEC_CTRL,			                                  phy_data)))				return ret_val;		}			/* SW Reset the PHY so all changes take effect */		if((ret_val = e1000_phy_reset(hw))) {			DEBUGOUT("Error Resetting the PHY\n");			return ret_val;#ifdef LINUX_DRIVER		}#endif	}		/* Options:	 *   autoneg = 1 (default)	 *      PHY will advertise value(s) parsed from	 *      autoneg_advertised and fc	 *   autoneg = 0	 *      PHY will be set to 10H, 10F, 100H, or 100F	 *      depending on value parsed from forced_speed_duplex.	 */		/* Is autoneg enabled?  This is enabled by default or by software	 * override.  If so, call e1000_phy_setup_autoneg routine to parse the	 * autoneg_advertised and fc options. If autoneg is NOT enabled, then	 * the user should have provided a speed/duplex override.  If so, then	 * call e1000_phy_force_speed_duplex to parse and set this up.	 */	/* Perform some bounds checking on the hw->autoneg_advertised	 * parameter.  If this variable is zero, then set it to the default.	 */	hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;		/* If autoneg_advertised is zero, we assume it was not defaulted	 * by the calling code so we set to advertise full capability.	 */	if(hw->autoneg_advertised == 0)		hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;		DEBUGOUT("Reconfiguring auto-neg advertisement params\n");	if((ret_val = e1000_phy_setup_autoneg(hw))) {		DEBUGOUT("Error Setting up Auto-Negotiation\n");		return ret_val;	}	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.	 */	if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data)))		return ret_val;	phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);	if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data)))		return ret_val;#if 0		/* Does the user want to wait for Auto-Neg to complete here, or	 * check at a later time (for example, callback routine).	 */	if(hw->wait_autoneg_complete) {		if((ret_val = e1000_wait_autoneg(hw))) {			DEBUGOUT("Error while waiting for autoneg to complete\n");			return ret_val;		}	}#else	/* If we do not wait for autonegotiation to complete I 	 * do not see a valid link status.	 */	if((ret_val = e1000_wait_autoneg(hw))) {		DEBUGOUT("Error while waiting for autoneg to complete\n");		return ret_val;	}#endif	} /* !hw->phy_reset_disable */		/* Check link status. Wait up to 100 microseconds for link to become	 * valid.	 */	for(i = 0; i < 10; i++) {		if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))			return ret_val;		if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))			return ret_val;		if(phy_data & MII_SR_LINK_STATUS) {			/* We have link, so we need to finish the config process:			 *   1) Set up the MAC to the current PHY speed/duplex			 *      if we are on 82543.  If we			 *      are on newer silicon, we only need to configure			 *      collision distance in the Transmit Control Register.			 *   2) Set up flow control on the MAC to that established with			 *      the link partner.			 */			if(hw->mac_type >= e1000_82544) {				e1000_config_collision_dist(hw);			} else {				if((ret_val = e1000_config_mac_to_phy(hw))) {					DEBUGOUT("Error configuring MAC to PHY settings\n");					return ret_val;				}			}			if((ret_val = e1000_config_fc_after_link_up(hw))) {				DEBUGOUT("Error Configuring Flow Control\n");				return ret_val;			}#if 0			if(hw->phy_type == e1000_phy_igp) {				if((ret_val = e1000_config_dsp_after_link_change(hw, TRUE))) {					DEBUGOUT("Error Configuring DSP after link up\n");					return ret_val;				}			}#endif			DEBUGOUT("Valid link established!!!\n");			return E1000_SUCCESS;		}		udelay(10);	}		DEBUGOUT("Unable to establish link!!!\n");	return -E1000_ERR_NOLINK;}/******************************************************************************* Configures PHY autoneg and flow control advertisement settings** hw - Struct containing variables accessed by shared code******************************************************************************/static inte1000_phy_setup_autoneg(struct e1000_hw *hw){	int32_t ret_val;	uint16_t mii_autoneg_adv_reg;	uint16_t mii_1000t_ctrl_reg;	DEBUGFUNC("e1000_phy_setup_autoneg");		/* Read the MII Auto-Neg Advertisement Register (Address 4). */	if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,	                                 &mii_autoneg_adv_reg)))		return ret_val;	/* Read the MII 1000Base-T Control Register (Address 9). */	if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg)))		return ret_val;	/* 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 &= ~REG4_SPEED_MASK;	mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;	DEBUGOUT1("autoneg_advertised %x\n", hw->autoneg_advertised);	/* Do we want to advertise 10 Mb Half Duplex? */	if(hw->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(hw->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(hw->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(hw->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(hw->autoneg_advertised & ADVERTISE_1000_HALF) {		DEBUGOUT("Advertise 1000mb Half duplex requested, request denied!\n");	}	/* Do we want to advertise 1000 Mb Full Duplex? */	if(hw->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) {	case e1000_fc_none: /* 0 */		/* 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: /* 1 */		/* 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: /* 2 */		/* 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: /* 3 */		/* 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");		return -E1000_ERR_CONFIG;	}	if((ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV,	                       mii_autoneg_adv_reg)))		return ret_val;	DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);	if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg)))		return ret_val;	return E1000_SUCCESS;}/******************************************************************************* Sets the collision distance in the Transmit Control register** hw - Struct containing variables accessed by shared code** Link should have been established previously. Reads the speed and duplex* information from the Device Status register.******************************************************************************/static voide1000_config_collision_dist(struct e1000_hw *hw){	uint32_t tctl;	tctl = E1000_READ_REG(hw, TCTL);		tctl &= ~E1000_TCTL_COLD;	tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;		E1000_WRITE_REG(hw, TCTL, tctl);	E1000_WRITE_FLUSH(hw);}/******************************************************************************* Sets MAC speed and duplex settings to reflect the those in the PHY** hw - Struct containing variables accessed by shared code* mii_reg - data to write to the MII control register** The contents of the PHY register containing the needed information need to* be passed in.******************************************************************************/static inte1000_config_mac_to_phy(struct e1000_hw *hw){	uint32_t ctrl;	int32_t ret_val;	uint16_t phy_data;	DEBUGFUNC("e1000_config_mac_to_phy");	/* Read the Device Control Register and set the bits to Force Speed	 * and Duplex.	 */	ctrl = E1000_READ_REG(hw, CTRL);	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);	ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);	/* Set up duplex in the Device Control and Transmit Control	 * registers depending on negotiated values.	 */	if (hw->phy_type == e1000_phy_igp) {		if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,		                                 &phy_data)))			return ret_val;		if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD;		else ctrl &= ~E1000_CTRL_FD;		e1000_config_collision_dist(hw);		/* Set up speed in the Device Control register depending on		 * negotiated values.		 */		if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==		   IGP01E1000_PSSR_SPEED_1000MBPS)			ctrl |= E1000_CTRL_SPD_1000;		else if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==			IGP01E1000_PSSR_SPEED_100MBPS)			ctrl |= E1000_CTRL_SPD_100;	} else {		if((ret_val = e1000_read_phy_reg(hw, M

⌨️ 快捷键说明

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