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

📄 tlan.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 5 页
字号:
} /* TLan_EeSendStart */	/***************************************************************	 *	TLan_EeSendByte	 *	 *	Returns:	 *		If the correct ack was received, 0, otherwise 1	 *	Parms:	io_base		The IO port base address for the	 *				TLAN device with the EEPROM to	 *				use.	 *		data		The 8 bits of information to	 *				send to the EEPROM.	 *		stop		If TLAN_EEPROM_STOP is passed, a	 *				stop cycle is sent after the	 *				byte is sent after the ack is	 *				read.	 *	 *	This function sends a byte on the serial EEPROM line,	 *	driving the clock to send each bit. The function then	 *	reverses transmission direction and reads an acknowledge	 *	bit.	 *	 **************************************************************/static int TLan_EeSendByte( u16 io_base, u8 data, int stop ){	int	err;	u8	place;	u16	sio;	outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );	sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;	/* Assume clock is low, tx is enabled; */	for ( place = 0x80; place != 0; place >>= 1 ) {		if ( place & data )			TLan_SetBit( TLAN_NET_SIO_EDATA, sio );		else			TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );		TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );	}	TLan_ClearBit( TLAN_NET_SIO_ETXEN, sio );	TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );	err = TLan_GetBit( TLAN_NET_SIO_EDATA, sio );	TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );	TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );	if ( ( ! err ) && stop ) {		TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );	/* STOP, raise data while clock is high */		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );		TLan_SetBit( TLAN_NET_SIO_EDATA, sio );	}	return ( err );} /* TLan_EeSendByte */	/***************************************************************	 *	TLan_EeReceiveByte	 *	 *	Returns:	 *		Nothing	 *	Parms:	 *		io_base		The IO port base address for the	 *				TLAN device with the EEPROM to	 *				use.	 *		data		An address to a char to hold the	 *				data sent from the EEPROM.	 *		stop		If TLAN_EEPROM_STOP is passed, a	 *				stop cycle is sent after the	 *				byte is received, and no ack is	 *				sent.	 *	 *	This function receives 8 bits of data from the EEPROM	 *	over the serial link.  It then sends and ack bit, or no	 *	ack and a stop bit.  This function is used to retrieve	 *	data after the address of a byte in the EEPROM has been	 *	sent.	 *	 **************************************************************/static void TLan_EeReceiveByte( u16 io_base, u8 *data, int stop ){	u8  place;	u16 sio;	outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );	sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;	*data = 0;	/* Assume clock is low, tx is enabled; */	TLan_ClearBit( TLAN_NET_SIO_ETXEN, sio );	for ( place = 0x80; place; place >>= 1 ) {		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );		if ( TLan_GetBit( TLAN_NET_SIO_EDATA, sio ) )			*data |= place;		TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );	}	TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );	if ( ! stop ) {		TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );	/* Ack = 0 */		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );		TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );	} else {		TLan_SetBit( TLAN_NET_SIO_EDATA, sio );		/* No ack = 1 (?) */		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );		TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );		TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );	/* STOP, raise data while clock is high */		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );		TLan_SetBit( TLAN_NET_SIO_EDATA, sio );	}} /* TLan_EeReceiveByte */	/***************************************************************	 *	TLan_EeReadByte	 *	 *	Returns:	 *		No error = 0, else, the stage at which the error	 *		occurred.	 *	Parms:	 *		io_base		The IO port base address for the	 *				TLAN device with the EEPROM to	 *				use.	 *		ee_addr		The address of the byte in the	 *				EEPROM whose contents are to be	 *				retrieved.	 *		data		An address to a char to hold the	 *				data obtained from the EEPROM.	 *	 *	This function reads a byte of information from an byte	 *	cell in the EEPROM.	 *	 **************************************************************/static int TLan_EeReadByte( u16 io_base, u8 ee_addr, u8 *data ){	int err;	unsigned long flags = 0;	int ret=0;	TLan_EeSendStart( io_base );	err = TLan_EeSendByte( io_base, 0xA0, TLAN_EEPROM_ACK );	if (err)	{		ret=1;		goto fail;	}	err = TLan_EeSendByte( io_base, ee_addr, TLAN_EEPROM_ACK );	if (err)	{		ret=2;		goto fail;	}	TLan_EeSendStart( io_base );	err = TLan_EeSendByte( io_base, 0xA1, TLAN_EEPROM_ACK );	if (err)	{		ret=3;		goto fail;	}	TLan_EeReceiveByte( io_base, data, TLAN_EEPROM_STOP );fail:	return ret;} /* TLan_EeReadByte */#if	0/* Not yet converted from Linux driver *//***********************************************************************************************************************************************************	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 net_device *dev ){	TLanPrivateInfo *priv = 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 net_device *dev ){	TLanPrivateInfo *priv = 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, "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 net_device *dev ){	TLanPrivateInfo	*priv = dev->priv;	u16		value;	TLAN_DBG( TLAN_DEBUG_GNRL, "%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 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 );} /* TLan_PhyPowerDown */void TLan_PhyPowerUp( struct net_device *dev ){	TLanPrivateInfo	*priv = dev->priv;	u16		value;	TLAN_DBG( TLAN_DEBUG_GNRL, "%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 );	TLan_MiiSync(dev->base_addr);	/* 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.	 */	TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_RESET );} /* TLan_PhyPowerUp */void TLan_PhyReset( struct net_device *dev ){	TLanPrivateInfo	*priv = dev->priv;	u16		phy;	u16		value;	phy = priv->phy[priv->phyNum];	TLAN_DBG( TLAN_DEBUG_GNRL, "%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 );	}	/* 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 );} /* TLan_PhyReset */void TLan_PhyStartLink( struct net_device *dev ){	TLanPrivateInfo	*priv = dev->priv;	u16		ability;	u16		control;	u16		data;	u16		phy;	u16		status;	u16		tctl;	phy = priv->phy[priv->phyNum];	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Trying to activate link.\n", dev->name );	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );	TLan_MiiReadReg( dev, 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( dev, phy, MII_GEN_CTL, 0x0000);		} else if ( priv->speed == TLAN_SPEED_10 &&			    priv->duplex == TLAN_DUPLEX_FULL) {			priv->tlanFullDuplex = TRUE;			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x0100);		} else if ( priv->speed == TLAN_SPEED_100 &&			    priv->duplex == TLAN_DUPLEX_HALF) {			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x2000);		} else if ( priv->speed == TLAN_SPEED_100 &&			    priv->duplex == TLAN_DUPLEX_FULL) {			priv->tlanFullDuplex = TRUE;			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x2100);		} else {				/* Set Auto-Neg advertisement */			TLan_MiiWriteReg( dev, phy, MII_AN_ADV, (ability << 5) | 1);			/* Enablee Auto-Neg */			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1000 );			/* Restart Auto-Neg */			TLan_MiiWriteReg( dev, 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.		 	*/			printk( "TLAN: %s: Starting autonegotiation.\n", dev->name );			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( dev->base_addr, TLAN_NET_CONFIG, data );		TLan_SetTimer( dev, (40*HZ/1000), 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;

⌨️ 快捷键说明

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