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

📄 e100_phy.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*******************************************************************************    Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.    This program is free software; you can redistribute it and/or modify it   under the terms of the GNU General Public License as published by the Free   Software Foundation; either version 2 of the License, or (at your option)   any later version.    This program is distributed in the hope that it will be useful, but WITHOUT   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   more details.    You should have received a copy of the GNU General Public License along with  this program; if not, write to the Free Software Foundation, Inc., 59   Temple Place - Suite 330, Boston, MA  02111-1307, USA.    The full GNU General Public License is included in this distribution in the  file called LICENSE.    Contact Information:  Linux NICS <linux.nics@intel.com>  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497*******************************************************************************/#include "e100_phy.h"void e100_handle_zlock(struct e100_private *bdp);/*  * Procedure:	e100_mdi_write * * Description: This routine will write a value to the specified MII register *		of an external MDI compliant device (e.g. PHY 100).  The *		command will execute in polled mode. * * Arguments: *	bdp - Ptr to this card's e100_bdconfig structure *	reg_addr - The MII register that we are writing to *	phy_addr - The MDI address of the Phy component. *	data - The value that we are writing to the MII register. * * Returns: *	NOTHING */inte100_mdi_write(struct e100_private *bdp, u32 reg_addr, u32 phy_addr, u16 data){	int e100_retry;	u32 temp_val;	unsigned int mdi_cntrl;	spin_lock_bh(&bdp->mdi_access_lock);	temp_val = (((u32) data) | (reg_addr << 16) |		    (phy_addr << 21) | (MDI_WRITE << 26));	writel(temp_val, &bdp->scb->scb_mdi_cntrl);	readw(&bdp->scb->scb_status);	/* wait 20usec before checking status */	udelay(20);	/* poll for the mdi write to complete */	e100_retry = E100_CMD_WAIT;	while ((!((mdi_cntrl = readl(&bdp->scb->scb_mdi_cntrl)) & MDI_PHY_READY)) && (e100_retry)) {		udelay(20);		e100_retry--;	}	spin_unlock_bh(&bdp->mdi_access_lock);	if (mdi_cntrl & MDI_PHY_READY) 		return 0;	else {		printk(KERN_ERR "e100: MDI write timeout\n");		return 1;	}}/*  * Procedure:	e100_mdi_read * * Description: This routine will read a value from the specified MII register *		of an external MDI compliant device (e.g. PHY 100), and return *		it to the calling routine.  The command will execute in polled *		mode. * * Arguments: *	bdp - Ptr to this card's e100_bdconfig structure *	reg_addr - The MII register that we are reading from *	phy_addr - The MDI address of the Phy component. * * Results: *	data - The value that we read from the MII register. * * Returns: *	NOTHING */inte100_mdi_read(struct e100_private *bdp, u32 reg_addr, u32 phy_addr, u16 *data){	int e100_retry;	u32 temp_val;	unsigned int mdi_cntrl;	spin_lock_bh(&bdp->mdi_access_lock);	/* Issue the read command to the MDI control register. */	temp_val = ((reg_addr << 16) | (phy_addr << 21) | (MDI_READ << 26));	writel(temp_val, &bdp->scb->scb_mdi_cntrl);	readw(&bdp->scb->scb_status);	/* wait 20usec before checking status */	udelay(20);	/* poll for the mdi read to complete */	e100_retry = E100_CMD_WAIT;	while ((!((mdi_cntrl = readl(&bdp->scb->scb_mdi_cntrl)) & MDI_PHY_READY)) && (e100_retry)) {		udelay(20);		e100_retry--;	}	spin_unlock_bh(&bdp->mdi_access_lock);	if (mdi_cntrl & MDI_PHY_READY) {		/* return the lower word */		*data = (u16) mdi_cntrl;		return 0;	}	else {		printk(KERN_ERR "e100: MDI read timeout\n");		return 1;	}}static unsigned chare100_phy_valid(struct e100_private *bdp, unsigned int phy_address){	u16 ctrl_reg, stat_reg;	/* Read the MDI control register */	e100_mdi_read(bdp, MII_BMCR, phy_address, &ctrl_reg);	/* Read the status register twice, bacause of sticky bits */	e100_mdi_read(bdp, MII_BMSR, phy_address, &stat_reg);	e100_mdi_read(bdp, MII_BMSR, phy_address, &stat_reg);	if ((ctrl_reg == 0xffff) || ((stat_reg == 0) && (ctrl_reg == 0)))		return false;	return true;}static voide100_phy_address_detect(struct e100_private *bdp){	unsigned int addr;	unsigned char valid_phy_found = false;	if (IS_NC3133(bdp)) {		bdp->phy_addr = 0;		return;	}	if (e100_phy_valid(bdp, PHY_DEFAULT_ADDRESS)) {		bdp->phy_addr = PHY_DEFAULT_ADDRESS;		valid_phy_found = true;	} else {		for (addr = MIN_PHY_ADDR; addr <= MAX_PHY_ADDR; addr++) {			if (e100_phy_valid(bdp, addr)) {				bdp->phy_addr = addr;				valid_phy_found = true;				break;			}		}	}	if (!valid_phy_found) {		bdp->phy_addr = PHY_ADDRESS_503;	}}static voide100_phy_id_detect(struct e100_private *bdp){	u16 low_id_reg, high_id_reg;	if (bdp->phy_addr == PHY_ADDRESS_503) {		bdp->PhyId = PHY_503;		return;	}	if (!(bdp->flags & IS_ICH)) {		if (bdp->rev_id >= D102_REV_ID) {			bdp->PhyId = PHY_82562ET;			return;		}	}	/* Read phy id from the MII register */	e100_mdi_read(bdp, MII_PHYSID1, bdp->phy_addr, &low_id_reg);	e100_mdi_read(bdp, MII_PHYSID2, bdp->phy_addr, &high_id_reg);	bdp->PhyId = ((unsigned int) low_id_reg |		      ((unsigned int) high_id_reg << 16));}static voide100_phy_isolate(struct e100_private *bdp){	unsigned int phy_address;	u16 ctrl_reg;	/* Go over all phy addresses. Deisolate the selected one, and isolate	 * all the rest */	for (phy_address = 0; phy_address <= MAX_PHY_ADDR; phy_address++) {		if (phy_address != bdp->phy_addr) {			e100_mdi_write(bdp, MII_BMCR, phy_address,				       BMCR_ISOLATE);		} else {			e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &ctrl_reg);			ctrl_reg &= ~BMCR_ISOLATE;			e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg);		}		udelay(100);	}}static unsigned chare100_phy_specific_setup(struct e100_private *bdp){	u16 misc_reg;	if (bdp->phy_addr == PHY_ADDRESS_503) {		switch (bdp->params.e100_speed_duplex) {		case E100_AUTONEG:			/* The adapter can't autoneg. so set to 10/HALF */			printk(KERN_INFO			       "e100: 503 serial component detected which "			       "cannot autonegotiate\n");			printk(KERN_INFO			       "e100: speed/duplex forced to "			       "10Mbps / Half duplex\n");			bdp->params.e100_speed_duplex = E100_SPEED_10_HALF;			break;		case E100_SPEED_100_HALF:		case E100_SPEED_100_FULL:			printk(KERN_ERR			       "e100: 503 serial component detected "			       "which does not support 100Mbps\n");			printk(KERN_ERR			       "e100: Change the forced speed/duplex "			       "to a supported setting\n");			return false;		}		return true;	}	if (IS_NC3133(bdp)) {		u16 int_reg;		/* enable 100BASE fiber interface */		e100_mdi_write(bdp, MDI_NC3133_CONFIG_REG, bdp->phy_addr,			       MDI_NC3133_100FX_ENABLE);		if ((bdp->params.e100_speed_duplex != E100_AUTONEG) &&		    (bdp->params.e100_speed_duplex != E100_SPEED_100_FULL)) {			/* just inform user about 100 full */			printk(KERN_ERR "e100: NC3133 NIC can only run "			       "at 100Mbps full duplex\n");		}		bdp->params.e100_speed_duplex = E100_SPEED_100_FULL;		/* enable interrupts */		e100_mdi_read(bdp, MDI_NC3133_INT_ENABLE_REG,			      bdp->phy_addr, &int_reg);		int_reg |= MDI_NC3133_INT_ENABLE;		e100_mdi_write(bdp, MDI_NC3133_INT_ENABLE_REG,			       bdp->phy_addr, int_reg);	}	/* Handle the National TX */	if ((bdp->PhyId & PHY_MODEL_REV_ID_MASK) == PHY_NSC_TX) {		e100_mdi_read(bdp, NSC_CONG_CONTROL_REG,			      bdp->phy_addr, &misc_reg);		misc_reg |= NSC_TX_CONG_TXREADY;		/* disable the congestion control bit in the National Phy */		misc_reg &= ~NSC_TX_CONG_ENABLE;		e100_mdi_write(bdp, NSC_CONG_CONTROL_REG,			       bdp->phy_addr, misc_reg);	}	return true;}/*  * Procedure:	e100_phy_fix_squelch * * Description: *	Help find link on certain rare scenarios. *	NOTE: This routine must be called once per watchdog, *	      and *after* setting the current link state. * * Arguments: *	bdp - Ptr to this card's e100_bdconfig structure * * Returns: *	NOTHING */static voide100_phy_fix_squelch(struct e100_private *bdp){	if ((bdp->PhyId != PHY_82555_TX) || (bdp->flags & DF_SPEED_FORCED))		return;	if (netif_carrier_ok(bdp->device)) {		switch (bdp->PhyState) {		case 0:			break;		case 1:			e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,				       bdp->phy_addr, 0x0000);			break;		case 2:			e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,				       bdp->phy_addr, 0x3000);			break;		}		bdp->PhyState = 0;		bdp->PhyDelay = 0;	} else if (!bdp->PhyDelay--) {		switch (bdp->PhyState) {		case 0:			e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,				       bdp->phy_addr, EXTENDED_SQUELCH_BIT);			bdp->PhyState = 1;			break;		case 1:			e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL,				       bdp->phy_addr, 0x0000);			e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,				       bdp->phy_addr, 0x2010);			bdp->PhyState = 2;			break;		case 2:			e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR,				       bdp->phy_addr, 0x3000);			bdp->PhyState = 0;			break;		}		e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr,			       BMCR_ANENABLE | BMCR_ANRESTART);		bdp->PhyDelay = 3;	}}/*  * Procedure:	e100_fix_polarity * * Description: *	Fix for 82555 auto-polarity toggle problem. With a short cable  *	connecting an 82555 with an 840A link partner, if the medium is noisy, *	the 82555 sometime thinks that the polarity might be wrong and so  *	toggles polarity. This happens repeatedly and results in a high bit  *	error rate. *	NOTE: This happens only at 10 Mbps * * Arguments: *	bdp - Ptr to this card's e100_bdconfig structure * * Returns: *	NOTHING */static voide100_fix_polarity(struct e100_private *bdp){	u16 status;	u16 errors;	u16 misc_reg;

⌨️ 快捷键说明

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