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

📄 tlan.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  2.	Turn off interrupts. ( Probably isn't necessary ) */	data = inl(dev->base_addr + TLAN_HOST_CMD);	data |= TLAN_HC_INT_OFF;	outl(data, dev->base_addr + TLAN_HOST_CMD);/*  3.	Clear AREGs and HASHs. */ 	for ( i = TLAN_AREG_0; i <= TLAN_HASH_2; i += 4 ) {		TLan_DioWrite32( dev->base_addr, (u16) i, 0 );	}/*  4.	Setup NetConfig register. */	data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;	TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, (u16) data );/*  5.	Load Ld_Tmr and Ld_Thr in HOST_CMD. */ 	outl( TLAN_HC_LD_TMR | 0x0, dev->base_addr + TLAN_HOST_CMD ); 	outl( TLAN_HC_LD_THR | 0x1, dev->base_addr + TLAN_HOST_CMD );/*  6.	Unreset the MII by setting NMRST (in NetSio) to 1. */	outw( TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR );	addr = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;	TLan_SetBit( TLAN_NET_SIO_NMRST, addr );/*  7.	Setup the remaining registers. */	if ( priv->tlanRev >= 0x30 ) {		data8 = TLAN_ID_TX_EOC | TLAN_ID_RX_EOC;		TLan_DioWrite8( dev->base_addr, TLAN_INT_DIS, data8 );	}	TLan_PhyDetect( dev );	data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN;	if ( priv->adapter->flags & TLAN_ADAPTER_BIT_RATE_PHY ) {		data |= TLAN_NET_CFG_BIT;		if ( priv->aui == 1 ) {			TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x0a );		} else if ( priv->duplex == TLAN_DUPLEX_FULL ) {			TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x00 );			priv->tlanFullDuplex = TRUE;		} else {			TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x08 );		}	}	if ( priv->phyNum == 0 ) {		data |= TLAN_NET_CFG_PHY_EN;	}	TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, (u16) data );	if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {		TLan_FinishReset( dev );	} else {		TLan_PhyPowerDown( dev );	}} /* TLan_ResetAdapter */voidTLan_FinishReset( struct device *dev ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	u8		data;	u32		phy;	u8		sio;	u16		status;	u16		tlphy_ctl;	phy = priv->phy[priv->phyNum];	data = TLAN_NET_CMD_NRESET | TLAN_NET_CMD_NWRAP;	if ( priv->tlanFullDuplex ) {		data |= TLAN_NET_CMD_DUPLEX;	}	TLan_DioWrite8( dev->base_addr, TLAN_NET_CMD, data );	data = TLAN_NET_MASK_MASK4 | TLAN_NET_MASK_MASK5; 	if ( priv->phyNum == 0 ) {		data |= TLAN_NET_MASK_MASK7; 	}	TLan_DioWrite8( dev->base_addr, TLAN_NET_MASK, data );	TLan_DioWrite16( dev->base_addr, TLAN_MAX_RX, TLAN_MAX_FRAME_SIZE );	if ( ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) || ( priv->aui ) ) {		status = MII_GS_LINK;		printk( "TLAN:  %s: Link forced.\n", dev->name );	} else {		TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );		udelay( 1000 );		TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );		if ( status & MII_GS_LINK ) {			printk( "TLAN:  %s: Link active.\n", dev->name );			TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );		}	}	if ( priv->phyNum == 0 ) {        	TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl );        	tlphy_ctl |= TLAN_TC_INTEN;        	TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl );        	sio = TLan_DioRead8( dev->base_addr, TLAN_NET_SIO );        	sio |= TLAN_NET_SIO_MINTEN;        	TLan_DioWrite8( dev->base_addr, TLAN_NET_SIO, sio );	}	if ( status & MII_GS_LINK ) {		TLan_SetMac( dev, 0, dev->dev_addr );		priv->phyOnline = 1;		outb( ( TLAN_HC_INT_ON >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );		if ( debug >= 1 ) {			outb( ( TLAN_HC_REQ_INT >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );		}		outl( virt_to_bus( priv->rxList ), dev->base_addr + TLAN_CH_PARM );		outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD );	} else {		printk( "TLAN:  %s: Link inactive, will retry in 10 secs...\n", dev->name );		TLan_SetTimer( dev, 1000, TLAN_TIMER_FINISH_RESET );		return;	}} /* TLan_FinishReset */	/***************************************************************	 *	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 device *dev, int areg, char *mac ){	int i;				areg *= 6;	if ( mac != NULL ) {		for ( i = 0; i < 6; i++ )			TLan_DioWrite8( dev->base_addr, TLAN_AREG_0 + areg + i, mac[i] );	} else {		for ( i = 0; i < 6; i++ )			TLan_DioWrite8( dev->base_addr, TLAN_AREG_0 + areg + i, 0 );	}} /* TLan_SetMac *//***********************************************************************************************************************************************************	ThunderLAN Driver PHY Layer Routines***********************************************************************************************************************************************************/	/*********************************************************************	 *	TLan_PhyPrint	 *	 *	Returns:	 *		Nothing	 *	Parms:	 *		dev	A pointer to the device structure of the	 *			TLAN device having the PHYs to be detailed.	 *					 *	This function prints the registers a PHY (aka tranceiver).	 *	 ********************************************************************/void TLan_PhyPrint( struct device *dev ){	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;	u16 i, data0, data1, data2, data3, phy;	phy = priv->phy[priv->phyNum];	if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {		printk( "TLAN:   Device %s, Unmanaged PHY.\n", dev->name );	} else if ( phy <= TLAN_PHY_MAX_ADDR ) {		printk( "TLAN:   Device %s, PHY 0x%02x.\n", dev->name, phy );		printk( "TLAN:      Off.  +0     +1     +2     +3 \n" );                for ( i = 0; i < 0x20; i+= 4 ) {			printk( "TLAN:      0x%02x", i );			TLan_MiiReadReg( dev, phy, i, &data0 );			printk( " 0x%04hx", data0 );			TLan_MiiReadReg( dev, phy, i + 1, &data1 );			printk( " 0x%04hx", data1 );			TLan_MiiReadReg( dev, phy, i + 2, &data2 );			printk( " 0x%04hx", data2 );			TLan_MiiReadReg( dev, phy, i + 3, &data3 );			printk( " 0x%04hx\n", data3 );		}	} else {		printk( "TLAN:   Device %s, Invalid PHY.\n", dev->name );	}} /* TLan_PhyPrint */	/*********************************************************************	 *	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 device *dev ){	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;	u16		control;	u16		hi;	u16		lo;	u32		phy;	if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {		priv->phyNum = 0xFFFF;		return;	}	TLan_MiiReadReg( dev, 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( dev, phy, MII_GEN_CTL, &control );		TLan_MiiReadReg( dev, phy, MII_GEN_ID_HI, &hi );		TLan_MiiReadReg( dev, phy, MII_GEN_ID_LO, &lo );		if ( ( control != 0xFFFF ) || ( hi != 0xFFFF ) || ( lo != 0xFFFF ) ) {			TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: PHY found at %02x %04x %04x %04x\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 {		printk( "TLAN:  Cannot initialize device, no PHY was found!\n" );	}} /* TLan_PhyDetect */void TLan_PhyPowerDown( struct device *dev ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	u16		value;	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Powering down PHY(s).\n", dev->name );	value = MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE;	TLan_MiiSync( dev->base_addr );	TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );	if ( ( priv->phyNum == 0 ) && ( priv->phy[1] != TLAN_PHY_NONE ) && ( ! ( priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10 ) ) ) {		TLan_MiiSync( dev->base_addr );		TLan_MiiWriteReg( dev, priv->phy[1], MII_GEN_CTL, value );	}	/* Wait for 5 jiffies (50 ms) and powerup	 * This is abitrary.  It is intended to make sure the	 * tranceiver settles.	 */	TLan_SetTimer( dev, 5, TLAN_TIMER_PHY_PUP );} /* TLan_PhyPowerDown */void TLan_PhyPowerUp( struct device *dev ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	u16		value;	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Powering up PHY.\n", dev->name );	TLan_MiiSync( dev->base_addr );	value = MII_GC_LOOPBK;	TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );	/* Wait for 50 jiffies (500 ms) and reset the	 * tranceiver.  The TLAN docs say both 50 ms and	 * 500 ms, so do the longer, just in case	 */	TLan_SetTimer( dev, 50, TLAN_TIMER_PHY_RESET );} /* TLan_PhyPowerUp */void TLan_PhyReset( struct device *dev ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	u16		phy;	u16		value;	phy = priv->phy[priv->phyNum];	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Reseting PHY.\n", dev->name );	TLan_MiiSync( dev->base_addr );	value = MII_GC_LOOPBK | MII_GC_RESET;	TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, value );	TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value );	while ( value & MII_GC_RESET ) {		TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value );	}	TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0 );	/* Wait for 50 jiffies (500 ms) and initialize.	 * I don't remember why I wait this long.	 */	TLan_SetTimer( dev, 50, TLAN_TIMER_PHY_START_LINK );} /* TLan_PhyReset */void TLan_PhyStartLink( struct device *dev ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	u16		ability;	u16		control;	u16		data;	u16		phy;	u16		status;	u16		tctl;	phy = priv->phy[priv->phyNum];	TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:  %s: Trying to activate link.\n", dev->name );	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );	if ( ( status & MII_GS_AUTONEG ) && 	     ( priv->duplex == TLAN_DUPLEX_DEFAULT ) && 	     ( priv->speed == TLAN_SPEED_DEFAULT ) &&	     ( ! priv->aui ) ) {		ability = status >> 11;		if ( priv->speed == TLAN_SPEED_10 ) {			ability &= 0x0003;		} else if ( priv->speed == TLAN_SPEED_100 ) {			ability &= 0x001C;		}		if ( priv->duplex == TLAN_DUPLEX_FULL ) {			ability &= 0x000A;		} else if ( priv->duplex == TLAN_DUPLEX_HALF ) {			ability &= 0x0005;		}		TLan_MiiWriteReg( dev, phy, MII_AN_ADV, ( ability << 5 ) | 1 );       		TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1000 );		TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1200 );		/* Wait for 400 jiffies (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.		 */		printk( "TLAN:  %s: Starting autonegotiation.\n", dev->name );		TLan_SetTimer( dev, 400, 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( dev->base_addr, TLAN_NET_CONFIG, data );		TLan_SetTimer( dev, 4, TLAN_TIMER_PHY_PDOWN );		return;	} else if ( priv->phyNum == 0 ) {        	TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tctl );		if ( priv->aui ) {                	tctl |= TLAN_TC_AUISEL;		} else {                	tctl &= ~TLAN_TC_AUISEL;			control = 0;			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( dev, phy, MII_GEN_CTL, control );		}        	TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tctl );	}	/* Wait for 100 jiffies (1 sec) to give the tranceiver time	 * to establish link.	 */	TLan_SetTimer( dev, 100, TLAN_TIMER_FINISH_RESET );} /* TLan_PhyStartLink */void TLan_PhyFinishAutoNeg( struct device *dev ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	u16		an_adv;	u16		an_lpa;	u16		data;	u16		mode;	u16		phy;	u16		status;		phy = priv->phy[priv->phyNum];	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );	if ( ! ( status & MII_GS_AUTOCMPLT ) ) {		/* Wait for 800 jiffies (8 sec) to give the process		 * more time.  Perhaps we should fail after a while.		 */		printk( "TLAN:  Giving autonegotiation more time.\n" );		TLan_SetTimer( dev, 800, TLAN_TIMER_PHY_FINISH_AN );		return;	}	printk( "TLAN:  %s: Autonegotiation complete.\n", dev->name );	TLan_MiiReadReg( dev, phy, MII_AN_ADV, &an_adv );	TLan_MiiReadReg( dev, phy, MII_AN_LPA, &an_lpa );	mode = an_adv & an_lpa & 0x03E0;	if ( mode & 0x0100 ) {		priv->tlanFullDuplex = TRUE;	} else if ( ! ( mode & 0x0080 ) && ( mode & 0x00

⌨️ 快捷键说明

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