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

📄 e1000.c

📁 F:worksip2440a board可启动u-boot-like.tar.gz F:worksip2440a board可启动u-boot-like.tar.gz
💻 C
📖 第 1 页 / 共 5 页
字号:
	phy_data |= M88E1000_EPSCR_TX_CLK_25;	/* 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 (e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) {		DEBUGOUT("PHY Write Error\n");		return -E1000_ERR_PHY;	}	/* SW Reset the PHY so all changes take effect */	ret_val = e1000_phy_reset(hw);	if (ret_val < 0) {		DEBUGOUT("Error Resetting the PHY\n");		return ret_val;	}	/* 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");	ret_val = e1000_phy_setup_autoneg(hw);	if (ret_val < 0) {		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 (e1000_read_phy_reg(hw, PHY_CTRL, &phy_data) < 0) {		DEBUGOUT("PHY Read Error\n");		return -E1000_ERR_PHY;	}	phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);	if (e1000_write_phy_reg(hw, PHY_CTRL, phy_data) < 0) {		DEBUGOUT("PHY Write Error\n");		return -E1000_ERR_PHY;	}#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) {		ret_val = e1000_wait_autoneg(hw);		if (ret_val < 0) {			DEBUGOUT			    ("Error while waiting for autoneg to complete\n");			return ret_val;		}	}#else	/* If we do not wait for autonegtation to complete I	 * do not see a valid link status.	 */	ret_val = e1000_wait_autoneg(hw);	if (ret_val < 0) {		DEBUGOUT("Error while waiting for autoneg to complete\n");		return ret_val;	}#endif	/* Check link status. Wait up to 100 microseconds for link to become	 * valid.	 */	for (i = 0; i < 10; i++) {		if (e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) {			DEBUGOUT("PHY Read Error\n");			return -E1000_ERR_PHY;		}		if (e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) {			DEBUGOUT("PHY Read Error\n");			return -E1000_ERR_PHY;		}		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 {				ret_val = e1000_config_mac_to_phy(hw);				if (ret_val < 0) {					DEBUGOUT					    ("Error configuring MAC to PHY settings\n");					return ret_val;				}			}			ret_val = e1000_config_fc_after_link_up(hw);			if (ret_val < 0) {				DEBUGOUT("Error Configuring Flow Control\n");				return ret_val;			}			DEBUGOUT("Valid link established!!!\n");			return 0;		}		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){	uint16_t mii_autoneg_adv_reg;	uint16_t mii_1000t_ctrl_reg;	DEBUGFUNC();	/* Read the MII Auto-Neg Advertisement Register (Address 4). */	if (e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg) < 0) {		DEBUGOUT("PHY Read Error\n");		return -E1000_ERR_PHY;	}	/* Read the MII 1000Base-T Control Register (Address 9). */	if (e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg) < 0) {		DEBUGOUT("PHY Read Error\n");		return -E1000_ERR_PHY;	}	/* 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;	DEBUGOUT("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 (e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg) < 0) {		DEBUGOUT("PHY Write Error\n");		return -E1000_ERR_PHY;	}	DEBUGOUT("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);	if (e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg) < 0) {		DEBUGOUT("PHY Write Error\n");		return -E1000_ERR_PHY;	}	return 0;}/******************************************************************************* 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;	uint16_t phy_data;	DEBUGFUNC();	/* 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 (e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) {		DEBUGOUT("PHY Read Error\n");		return -E1000_ERR_PHY;	}	if (phy_data & M88E1000_PSSR_DPLX)		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 & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)		ctrl |= E1000_CTRL_SPD_1000;	else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)		ctrl |= E1000_CTRL_SPD_100;	/* Write the configured values back to the Device Control Reg. */	E1000_WRITE_REG(hw, CTRL, ctrl);	return 0;}/****************************************************************************** * Forces the MAC's flow control settings. * * hw - Struct containing variables accessed by shared code * * Sets the TFCE and RFCE bits in the device control register to reflect * the adapter settings. TFCE and RFCE need to be explicitly set by * software when a Copper PHY is used because autonegotiation is managed * by the PHY rather than the MAC. Software must also configure these * bits when link is forced on a fiber connection. *****************************************************************************/static inte1000_force_mac_fc(struct e1000_hw *hw){	uint32_t ctrl;	DEBUGFUNC();	/* Get the current configuration of the Device Control Register */	ctrl = E1000_READ_REG(hw, CTRL);	/* Because we didn't get link via the internal auto-negotiation	 * mechanism (we either forced link or we got link via PHY	 * auto-neg), we have to manually enable/disable transmit an	 * receive flow control.	 *	 * The "Case" statement below enables/disable flow control	 * according to the "hw->fc" parameter.	 *	 * 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	 *          frames but we do not receive pause frames).	 *      3:  Both Rx and TX flow control (symmetric) is enabled.	 *  other:  No other values should be possible at this point.	 */	switch (hw->fc) {	case e1000_fc_none:		ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));		break;	case e1000_fc_rx_pause:		ctrl &= (~E1000_CTRL_TFCE);		ctrl |= E1000_CTRL_RFCE;		break;	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;

⌨️ 快捷键说明

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