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

📄 tlan.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 4 页
字号:
	TLan_SetBit(TLAN_NET_SIO_MCLK, sio);	if (minten)		TLan_SetBit(TLAN_NET_SIO_MINTEN, sio);}				/* TLan_MiiWriteReg */	/***************************************************************	 *	TLan_SetMac	 *	 *	Returns:	 *		Nothing	 *	Parms:	 *		dev	Pointer to device structure of adapter	 *			on which to change the AREG.	 *		areg	The AREG to set the address in (0 - 3).	 *		mac	A pointer to an array of chars.  Each	 *			element stores one byte of the address.	 *			IE, it isn't in ascii.	 *	 *	This function transfers a MAC address to one of the	 *	TLAN AREGs (address registers).  The TLAN chip locks	 *	the register on writing to offset 0 and unlocks the	 *	register after writing to offset 5.  If NULL is passed	 *	in mac, then the AREG is filled with 0's.	 *	 **************************************************************/void TLan_SetMac(struct nic *nic __unused, int areg, char *mac){	int i;	areg *= 6;	if (mac != NULL) {		for (i = 0; i < 6; i++)			TLan_DioWrite8(BASE, TLAN_AREG_0 + areg + i,				       mac[i]);	} else {		for (i = 0; i < 6; i++)			TLan_DioWrite8(BASE, TLAN_AREG_0 + areg + i, 0);	}}				/* TLan_SetMac */	/*********************************************************************	 *	TLan_PhyDetect	 *	 *	Returns:	 *		Nothing	 *	Parms:	 *		dev	A pointer to the device structure of the adapter	 *			for which the PHY needs determined.	 *	 *	So far I've found that adapters which have external PHYs	 *	may also use the internal PHY for part of the functionality.	 *	(eg, AUI/Thinnet).  This function finds out if this TLAN	 *	chip has an internal PHY, and then finds the first external	 *	PHY (starting from address 0) if it exists).	 *	 ********************************************************************/void TLan_PhyDetect(struct nic *nic){	u16 control;	u16 hi;	u16 lo;	u32 phy;	if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY) {		priv->phyNum = 0xFFFF;		return;	}	TLan_MiiReadReg(nic, TLAN_PHY_MAX_ADDR, MII_GEN_ID_HI, &hi);	if (hi != 0xFFFF) {		priv->phy[0] = TLAN_PHY_MAX_ADDR;	} else {		priv->phy[0] = TLAN_PHY_NONE;	}	priv->phy[1] = TLAN_PHY_NONE;	for (phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++) {		TLan_MiiReadReg(nic, phy, MII_GEN_CTL, &control);		TLan_MiiReadReg(nic, phy, MII_GEN_ID_HI, &hi);		TLan_MiiReadReg(nic, phy, MII_GEN_ID_LO, &lo);		if ((control != 0xFFFF) || (hi != 0xFFFF)		    || (lo != 0xFFFF)) {			printf("PHY found at %hX %hX %hX %hX\n", phy,			       control, hi, lo);			if ((priv->phy[1] == TLAN_PHY_NONE)			    && (phy != TLAN_PHY_MAX_ADDR)) {				priv->phy[1] = phy;			}		}	}	if (priv->phy[1] != TLAN_PHY_NONE) {		priv->phyNum = 1;	} else if (priv->phy[0] != TLAN_PHY_NONE) {		priv->phyNum = 0;	} else {		printf		    ("TLAN:  Cannot initialize device, no PHY was found!\n");	}}				/* TLan_PhyDetect */void TLan_PhyPowerDown(struct nic *nic){	u16 value;	printf("%s: Powering down PHY(s).\n", priv->nic_name);	value = MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE;	TLan_MiiSync(BASE);	TLan_MiiWriteReg(nic, priv->phy[priv->phyNum], MII_GEN_CTL, value);	if ((priv->phyNum == 0) && (priv->phy[1] != TLAN_PHY_NONE)	    &&	    (!(tlan_pci_tbl[chip_idx].	       flags & TLAN_ADAPTER_USE_INTERN_10))) {		TLan_MiiSync(BASE);		TLan_MiiWriteReg(nic, priv->phy[1], MII_GEN_CTL, value);	}	/* Wait for 50 ms and powerup	 * This is abitrary.  It is intended to make sure the	 * tranceiver settles.	 */	/* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_PUP ); */	mdelay(50);	TLan_PhyPowerUp(nic);}				/* TLan_PhyPowerDown */void TLan_PhyPowerUp(struct nic *nic){	u16 value;	printf("%s: Powering up PHY.\n", priv->nic_name);	TLan_MiiSync(BASE);	value = MII_GC_LOOPBK;	TLan_MiiWriteReg(nic, priv->phy[priv->phyNum], MII_GEN_CTL, value);	TLan_MiiSync(BASE);	/* Wait for 500 ms and reset the	 * tranceiver.  The TLAN docs say both 50 ms and	 * 500 ms, so do the longer, just in case.	 */	mdelay(500);	TLan_PhyReset(nic);	/* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_RESET ); */}				/* TLan_PhyPowerUp */void TLan_PhyReset(struct nic *nic){	u16 phy;	u16 value;	phy = priv->phy[priv->phyNum];	printf("%s: Reseting PHY.\n", priv->nic_name);	TLan_MiiSync(BASE);	value = MII_GC_LOOPBK | MII_GC_RESET;	TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, value);	TLan_MiiReadReg(nic, phy, MII_GEN_CTL, &value);	while (value & MII_GC_RESET) {		TLan_MiiReadReg(nic, phy, MII_GEN_CTL, &value);	}	/* Wait for 500 ms and initialize.	 * I don't remember why I wait this long.	 * I've changed this to 50ms, as it seems long enough.	 */	/* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_START_LINK ); */	mdelay(50);	TLan_PhyStartLink(nic);}				/* TLan_PhyReset */void TLan_PhyStartLink(struct nic *nic){	u16 ability;	u16 control;	u16 data;	u16 phy;	u16 status;	u16 tctl;	phy = priv->phy[priv->phyNum];	printf("%s: Trying to activate link.\n", priv->nic_name);	TLan_MiiReadReg(nic, phy, MII_GEN_STS, &status);	TLan_MiiReadReg(nic, phy, MII_GEN_STS, &ability);	if ((status & MII_GS_AUTONEG) && (!priv->aui)) {		ability = status >> 11;		if (priv->speed == TLAN_SPEED_10 &&		    priv->duplex == TLAN_DUPLEX_HALF) {			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x0000);		} else if (priv->speed == TLAN_SPEED_10 &&			   priv->duplex == TLAN_DUPLEX_FULL) {			priv->tlanFullDuplex = TRUE;			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x0100);		} else if (priv->speed == TLAN_SPEED_100 &&			   priv->duplex == TLAN_DUPLEX_HALF) {			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x2000);		} else if (priv->speed == TLAN_SPEED_100 &&			   priv->duplex == TLAN_DUPLEX_FULL) {			priv->tlanFullDuplex = TRUE;			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x2100);		} else {			/* Set Auto-Neg advertisement */			TLan_MiiWriteReg(nic, phy, MII_AN_ADV,					 (ability << 5) | 1);			/* Enablee Auto-Neg */			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x1000);			/* Restart Auto-Neg */			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x1200);			/* Wait for 4 sec for autonegotiation			 * to complete.  The max spec time is less than this			 * but the card need additional time to start AN.			 * .5 sec should be plenty extra.			 */			printf("TLAN: %s: Starting autonegotiation.\n",			       priv->nic_name);			mdelay(4000);			TLan_PhyFinishAutoNeg(nic);			/* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_PHY_FINISH_AN ); */			return;		}	}	if ((priv->aui) && (priv->phyNum != 0)) {		priv->phyNum = 0;		data =		    TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN |		    TLAN_NET_CFG_PHY_EN;		TLan_DioWrite16(BASE, TLAN_NET_CONFIG, data);		mdelay(50);		/* TLan_SetTimer( dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN ); */		TLan_PhyPowerDown(nic);		return;	} else if (priv->phyNum == 0) {		control = 0;		TLan_MiiReadReg(nic, phy, TLAN_TLPHY_CTL, &tctl);		if (priv->aui) {			tctl |= TLAN_TC_AUISEL;		} else {			tctl &= ~TLAN_TC_AUISEL;			if (priv->duplex == TLAN_DUPLEX_FULL) {				control |= MII_GC_DUPLEX;				priv->tlanFullDuplex = TRUE;			}			if (priv->speed == TLAN_SPEED_100) {				control |= MII_GC_SPEEDSEL;			}		}		TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, control);		TLan_MiiWriteReg(nic, phy, TLAN_TLPHY_CTL, tctl);	}	/* Wait for 2 sec to give the tranceiver time	 * to establish link.	 */	/* TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_FINISH_RESET ); */	mdelay(2000);	TLan_FinishReset(nic);}				/* TLan_PhyStartLink */void TLan_PhyFinishAutoNeg(struct nic *nic){	u16 an_adv;	u16 an_lpa;	u16 data;	u16 mode;	u16 phy;	u16 status;	phy = priv->phy[priv->phyNum];	TLan_MiiReadReg(nic, phy, MII_GEN_STS, &status);	udelay(1000);	TLan_MiiReadReg(nic, phy, MII_GEN_STS, &status);	if (!(status & MII_GS_AUTOCMPLT)) {		/* Wait for 8 sec to give the process		 * more time.  Perhaps we should fail after a while.		 */		if (!priv->neg_be_verbose++) {			printf			    ("TLAN:  Giving autonegotiation more time.\n");			printf			    ("TLAN:  Please check that your adapter has\n");			printf			    ("TLAN:  been properly connected to a HUB or Switch.\n");			printf			    ("TLAN:  Trying to establish link in the background...\n");		}		mdelay(8000);		TLan_PhyFinishAutoNeg(nic);		/* TLan_SetTimer( dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN ); */		return;	}	printf("TLAN: %s: Autonegotiation complete.\n", priv->nic_name);	TLan_MiiReadReg(nic, phy, MII_AN_ADV, &an_adv);	TLan_MiiReadReg(nic, phy, MII_AN_LPA, &an_lpa);	mode = an_adv & an_lpa & 0x03E0;	if (mode & 0x0100) {		printf("Full Duplex\n");		priv->tlanFullDuplex = TRUE;	} else if (!(mode & 0x0080) && (mode & 0x0040)) {		priv->tlanFullDuplex = TRUE;		printf("Full Duplex\n");	}	if ((!(mode & 0x0180))	    && (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_USE_INTERN_10)	    && (priv->phyNum != 0)) {		priv->phyNum = 0;		data =		    TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN |		    TLAN_NET_CFG_PHY_EN;		TLan_DioWrite16(BASE, TLAN_NET_CONFIG, data);		/* TLan_SetTimer( nic, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN ); */		mdelay(400);		TLan_PhyPowerDown(nic);		return;	}	if (priv->phyNum == 0) {		if ((priv->duplex == TLAN_DUPLEX_FULL)		    || (an_adv & an_lpa & 0x0040)) {			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL,					 MII_GC_AUTOENB | MII_GC_DUPLEX);			printf			    ("TLAN:  Starting internal PHY with FULL-DUPLEX\n");		} else {			TLan_MiiWriteReg(nic, phy, MII_GEN_CTL,					 MII_GC_AUTOENB);			printf			    ("TLAN:  Starting internal PHY with HALF-DUPLEX\n");		}	}	/* Wait for 100 ms.  No reason in partiticular.	 */	/* TLan_SetTimer( dev, (HZ/10), TLAN_TIMER_FINISH_RESET ); */	mdelay(100);	TLan_FinishReset(nic);}				/* TLan_PhyFinishAutoNeg */#ifdef MONITOR	/*********************************************************************        *        *      TLan_phyMonitor        *        *      Returns:        *              None        *        *      Params:        *              dev             The device structure of this device.        *        *        *      This function monitors PHY condition by reading the status        *      register via the MII bus. This can be used to give info        *      about link changes (up/down), and possible switch to alternate        *      media.        *        * ******************************************************************/void TLan_PhyMonitor(struct net_device *dev){	TLanPrivateInfo *priv = dev->priv;	u16 phy;	u16 phy_status;	phy = priv->phy[priv->phyNum];	/* Get PHY status register */	TLan_MiiReadReg(nic, phy, MII_GEN_STS, &phy_status);	/* Check if link has been lost */	if (!(phy_status & MII_GS_LINK)) {		if (priv->link) {			priv->link = 0;			printf("TLAN: %s has lost link\n", priv->nic_name);			priv->flags &= ~IFF_RUNNING;			mdelay(2000);			TLan_PhyMonitor(nic);			/* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT ); */			return;		}	}	/* Link restablished? */	if ((phy_status & MII_GS_LINK) && !priv->link) {		priv->link = 1;		printf("TLAN: %s has reestablished link\n",		       priv->nic_name);		priv->flags |= IFF_RUNNING;	}	/* Setup a new monitor */	/* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT ); */	mdelay(2000);	TLan_PhyMonitor(nic);}#endif				/* MONITOR */#ifdef EB51static struct pci_id tlan_nics[] = {	PCI_ROM(0x0e11, 0xae34, "netel10", "Compaq Netelligent 10 T PCI UTP"),	PCI_ROM(0x0e11, 0xae32, "netel100","Compaq Netelligent 10/100 TX PCI UTP"),	PCI_ROM(0x0e11, 0xae35, "netflex3i", "Compaq Integrated NetFlex-3/P"),	PCI_ROM(0x0e11, 0xf130, "thunder", "Compaq NetFlex-3/P"),	PCI_ROM(0x0e11, 0xf150, "netflex3b", "Compaq NetFlex-3/P"),	PCI_ROM(0x0e11, 0xae43, "netel100pi", "Compaq Netelligent Integrated 10/100 TX UTP"),	PCI_ROM(0x0e11, 0xae40, "netel100d", "Compaq Netelligent Dual 10/100 TX PCI UTP"),	PCI_ROM(0x0e11, 0xb011, "netel100i", "Compaq Netelligent 10/100 TX Embedded UTP"),	PCI_ROM(0x108d, 0x0013, "oc2183", "Olicom OC-2183/2185"),	PCI_ROM(0x108d, 0x0012, "oc2325", "Olicom OC-2325"),	PCI_ROM(0x108d, 0x0014, "oc2326", "Olicom OC-2326"),	PCI_ROM(0x0e11, 0xb030, "netelligent_10_100_ws_5100", "Compaq Netelligent 10/100 TX UTP"),	PCI_ROM(0x0e11, 0xb012, "netelligent_10_t2", "Compaq Netelligent 10 T/2 PCI UTP/Coax"),};static struct pci_driver tlan_driver __pci_driver = {	.type = NIC_DRIVER,	.name = "TLAN/PCI",	.probe = tlan_probe,	.ids = tlan_nics,	.id_count = sizeof(tlan_nics) / sizeof(tlan_nics[0]),	.class = 0,};#endif

⌨️ 快捷键说明

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