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

📄 e100_phy.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	int speed;	if ((bdp->PhyId != PHY_82555_TX) && (bdp->PhyId != PHY_82562ET) &&	    (bdp->PhyId != PHY_82562EM))		return;	/* If the user wants auto-polarity disabled, do only that and nothing *	 * else. * e100_autopolarity == 0 means disable --- we do just the	 * disabling * e100_autopolarity == 1 means enable  --- we do nothing at	 * all * e100_autopolarity >= 2 means we do the workaround code. */	/* Change for 82558 enhancement */	switch (E100_AUTOPOLARITY) {	case 0:		e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL,			      bdp->phy_addr, &misc_reg);		e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr,			       (u16) (misc_reg | DISABLE_AUTO_POLARITY));		break;	case 1:		e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL,			      bdp->phy_addr, &misc_reg);		e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr,			       (u16) (misc_reg & ~DISABLE_AUTO_POLARITY));		break;	case 2:		/* we do this only if link is up */		if (!netif_carrier_ok(bdp->device)) {			break;		}		e100_mdi_read(bdp, PHY_82555_CSR, bdp->phy_addr, &status);		speed = (status & PHY_82555_SPEED_BIT) ? 100 : 10;		/* we need to do this only if speed is 10 */		if (speed != 10) {			break;		}		/* see if we have any end of frame errors */		e100_mdi_read(bdp, PHY_82555_EOF_COUNTER,			      bdp->phy_addr, &errors);		/* if non-zero, wait for 100 ms before reading again */		if (errors) {			udelay(200);			e100_mdi_read(bdp, PHY_82555_EOF_COUNTER,				      bdp->phy_addr, &errors);			/* if non-zero again, we disable polarity */			if (errors) {				e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL,					      bdp->phy_addr, &misc_reg);				e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,					       bdp->phy_addr,					       (u16) (misc_reg |						      DISABLE_AUTO_POLARITY));			}		}		if (!errors) {			/* it is safe to read the polarity now */			e100_mdi_read(bdp, PHY_82555_CSR,				      bdp->phy_addr, &status);			/* if polarity is normal, disable polarity */			if (!(status & PHY_82555_POLARITY_BIT)) {				e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL,					      bdp->phy_addr, &misc_reg);				e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,					       bdp->phy_addr,					       (u16) (misc_reg |						      DISABLE_AUTO_POLARITY));			}		}		break;	default:		break;	}}/*  * Procedure:	e100_find_speed_duplex * * Description: This routine will figure out what line speed and duplex mode *		the PHY is currently using. * * Arguments: *	bdp - Ptr to this card's e100_bdconfig structure * * Returns: *	NOTHING */static voide100_find_speed_duplex(struct e100_private *bdp){	unsigned int PhyId;	u16 stat_reg, misc_reg;	u16 ad_reg, lp_ad_reg;	PhyId = bdp->PhyId & PHY_MODEL_REV_ID_MASK;	/* First we should check to see if we have link */	/* If we don't have a link no reason to print a speed and duplex */	if (!e100_update_link_state(bdp)) {		bdp->cur_line_speed = 0;		bdp->cur_dplx_mode = 0;		return;	}	/* On the 82559 and later controllers, speed/duplex is part of the *	 * SCB. So, we save an mdi_read and get these from the SCB. * */	if (bdp->rev_id >= D101MA_REV_ID) {		/* Read speed */		if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_1)			bdp->cur_line_speed = 100;		else			bdp->cur_line_speed = 10;		/* Read duplex */		if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_2)			bdp->cur_dplx_mode = FULL_DUPLEX;		else			bdp->cur_dplx_mode = HALF_DUPLEX;		return;	}	/* If this is a Phy 100, then read bits 1 and 0 of extended register 0,	 * to get the current speed and duplex settings. */	if ((PhyId == PHY_100_A) || (PhyId == PHY_100_C) ||	    (PhyId == PHY_82555_TX)) {		/* Read Phy 100 extended register 0 */		e100_mdi_read(bdp, EXTENDED_REG_0, bdp->phy_addr, &misc_reg);		/* Get current speed setting */		if (misc_reg & PHY_100_ER0_SPEED_INDIC)			bdp->cur_line_speed = 100;		else			bdp->cur_line_speed = 10;		/* Get current duplex setting -- FDX enabled if bit is set */		if (misc_reg & PHY_100_ER0_FDX_INDIC)			bdp->cur_dplx_mode = FULL_DUPLEX;		else			bdp->cur_dplx_mode = HALF_DUPLEX;		return;	}	/* See if link partner is capable of Auto-Negotiation (bit 0, reg 6) */	e100_mdi_read(bdp, MII_EXPANSION, bdp->phy_addr, &misc_reg);	/* See if Auto-Negotiation was complete (bit 5, reg 1) */	e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg);	/* If a True NWAY connection was made, then we can detect speed/dplx	 * by ANDing our adapter's advertised abilities with our link partner's	 * advertised ablilities, and then assuming that the highest common	 * denominator was chosed by NWAY. */	if ((misc_reg & EXPANSION_NWAY) && (stat_reg & BMSR_ANEGCOMPLETE)) {		/* Read our advertisement register */		e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &ad_reg);		/* Read our link partner's advertisement register */		e100_mdi_read(bdp, MII_LPA, bdp->phy_addr, &lp_ad_reg);		/* AND the two advertisement registers together, and get rid		 * of any extraneous bits. */		ad_reg &= (lp_ad_reg & NWAY_LP_ABILITY);		/* Get speed setting */		if (ad_reg &		    (ADVERTISE_100HALF | ADVERTISE_100FULL |		     ADVERTISE_100BASE4))			bdp->cur_line_speed = 100;		else			bdp->cur_line_speed = 10;		/* Get duplex setting -- use priority resolution algorithm */		if (ad_reg & ADVERTISE_100BASE4) {			bdp->cur_dplx_mode = HALF_DUPLEX;		} else if (ad_reg & ADVERTISE_100FULL) {			bdp->cur_dplx_mode = FULL_DUPLEX;		} else if (ad_reg & ADVERTISE_100HALF) {			bdp->cur_dplx_mode = HALF_DUPLEX;		} else if (ad_reg & ADVERTISE_10FULL) {			bdp->cur_dplx_mode = FULL_DUPLEX;		} else {			bdp->cur_dplx_mode = HALF_DUPLEX;		}		return;	}	/* If we are connected to a dumb (non-NWAY) repeater or hub, and the	 * line speed was determined automatically by parallel detection, then	 * we have no way of knowing exactly what speed the PHY is set to	 * unless that PHY has a propietary register which indicates speed in	 * this situation. The NSC TX PHY does have such a register. Also,	 * since NWAY didn't establish the connection, the duplex setting	 * should HALF duplex. */	bdp->cur_dplx_mode = HALF_DUPLEX;	if (PhyId == PHY_NSC_TX) {		/* Read register 25 to get the SPEED_10 bit */		e100_mdi_read(bdp, NSC_SPEED_IND_REG, bdp->phy_addr, &misc_reg);		/* If bit 6 was set then we're at 10Mbps */		if (misc_reg & NSC_TX_SPD_INDC_SPEED)			bdp->cur_line_speed = 10;		else			bdp->cur_line_speed = 100;	} else {		/* If we don't know the line speed, default to 10Mbps */		bdp->cur_line_speed = 10;	}}/*  * Procedure: e100_force_speed_duplex * * Description: This routine forces line speed and duplex mode of the * adapter based on the values the user has set in e100.c. * * Arguments:  bdp - Pointer to the e100_private structure for the board * * Returns: void * */voide100_force_speed_duplex(struct e100_private *bdp){	u16 control;	unsigned long expires;	bdp->flags |= DF_SPEED_FORCED;	e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control);	control &= ~BMCR_ANENABLE;	control &= ~BMCR_LOOPBACK;	switch (bdp->params.e100_speed_duplex) {	case E100_SPEED_10_HALF:		control &= ~BMCR_SPEED100;		control &= ~BMCR_FULLDPLX;		bdp->cur_line_speed = 10;		bdp->cur_dplx_mode = HALF_DUPLEX;		break;	case E100_SPEED_10_FULL:		control &= ~BMCR_SPEED100;		control |= BMCR_FULLDPLX;		bdp->cur_line_speed = 10;		bdp->cur_dplx_mode = FULL_DUPLEX;		break;	case E100_SPEED_100_HALF:		control |= BMCR_SPEED100;		control &= ~BMCR_FULLDPLX;		bdp->cur_line_speed = 100;		bdp->cur_dplx_mode = HALF_DUPLEX;		break;	case E100_SPEED_100_FULL:		control |= BMCR_SPEED100;		control |= BMCR_FULLDPLX;		bdp->cur_line_speed = 100;		bdp->cur_dplx_mode = FULL_DUPLEX;		break;	}	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control);	/* loop must run at least once */	expires = jiffies + 2 * HZ;	do {		if (e100_update_link_state(bdp) || 		    time_after(jiffies, expires)) {			break;		} else {			yield();		}	} while (true);}voide100_force_speed_duplex_to_phy(struct e100_private *bdp){	u16 control;	e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control);	control &= ~BMCR_ANENABLE;	control &= ~BMCR_LOOPBACK;	switch (bdp->params.e100_speed_duplex) {	case E100_SPEED_10_HALF:		control &= ~BMCR_SPEED100;		control &= ~BMCR_FULLDPLX;		break;	case E100_SPEED_10_FULL:		control &= ~BMCR_SPEED100;		control |= BMCR_FULLDPLX;		break;	case E100_SPEED_100_HALF:		control |= BMCR_SPEED100;		control &= ~BMCR_FULLDPLX;		break;	case E100_SPEED_100_FULL:		control |= BMCR_SPEED100;		control |= BMCR_FULLDPLX;		break;	}	/* Send speed/duplex command to PHY layer. */	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control);}/*  * Procedure: e100_set_fc * * Description: Checks the link's capability for flow control. *  * Arguments:  bdp - Pointer to the e100_private structure for the board *		     * Returns: void * */static voide100_set_fc(struct e100_private *bdp){	u16 ad_reg;	u16 lp_ad_reg;	u16 exp_reg;	/* no flow control for 82557, forced links or half duplex */	if (!netif_carrier_ok(bdp->device) || (bdp->flags & DF_SPEED_FORCED) ||	    (bdp->cur_dplx_mode == HALF_DUPLEX) ||	    !(bdp->flags & IS_BACHELOR)) {		bdp->flags &= ~DF_LINK_FC_CAP;		return;	}	/* See if link partner is capable of Auto-Negotiation (bit 0, reg 6) */	e100_mdi_read(bdp, MII_EXPANSION, bdp->phy_addr, &exp_reg);	if (exp_reg & EXPANSION_NWAY) {		/* Read our advertisement register */		e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &ad_reg);		/* Read our link partner's advertisement register */		e100_mdi_read(bdp, MII_LPA, bdp->phy_addr, &lp_ad_reg);		ad_reg &= lp_ad_reg;	/* AND the 2 ad registers */		if (ad_reg & NWAY_AD_FC_SUPPORTED)			bdp->flags |= DF_LINK_FC_CAP;		else			/* If link partner is capable of autoneg, but  */			/* not capable of flow control, Received PAUSE */			/* frames are still honored, i.e.,             */		        /* transmitted frames would be paused */			/* by incoming PAUSE frames           */			bdp->flags |= DF_LINK_FC_TX_ONLY;	} else {		bdp->flags &= ~DF_LINK_FC_CAP;	}}/*  * Procedure: e100_phy_check *  * Arguments:  bdp - Pointer to the e100_private structure for the board * * Returns: true if link state was changed *	   false otherwise

⌨️ 快捷键说明

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