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

📄 tlan.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/***********************************************************************************************************************************************************	ThunderLAN Driver Adapter Related Routines***********************************************************************************************************************************************************/	/***************************************************************	 *	TLan_ResetLists	 *  	 *	Returns:	 *		Nothing	 *	Parms:	 *		dev	The device structure with the list	 *			stuctures to be reset.	 *	 *	This routine sets the variables associated with managing	 *	the TLAN lists to their initial values.	 *	 **************************************************************/void TLan_ResetLists( struct net_device *dev ){	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;	int		i;	TLanList	*list;	struct sk_buff	*skb;	void		*t = NULL;	priv->txHead = 0;	priv->txTail = 0;	for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {		list = priv->txList + i;		list->cStat = TLAN_CSTAT_UNUSED;		if ( bbuf ) {			list->buffer[0].address = virt_to_bus( priv->txBuffer + ( i * TLAN_MAX_FRAME_SIZE ) );		} else {			list->buffer[0].address = 0;		}		list->buffer[2].count = 0;		list->buffer[2].address = 0;	}	priv->rxHead = 0;	priv->rxTail = TLAN_NUM_RX_LISTS - 1;	for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ ) {		list = priv->rxList + i;		list->cStat = TLAN_CSTAT_READY;		list->frameSize = TLAN_MAX_FRAME_SIZE;		list->buffer[0].count = TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;		if ( bbuf ) {			list->buffer[0].address = virt_to_bus( priv->rxBuffer + ( i * TLAN_MAX_FRAME_SIZE ) );		} else {			skb = dev_alloc_skb( TLAN_MAX_FRAME_SIZE + 7 );			if ( skb == NULL ) {				printk( "TLAN:  Couldn't allocate memory for received data.\n" );				/* If this ever happened it would be a problem */			} else {				skb->dev = dev;				skb_reserve( skb, 2 );				t = (void *) skb_put( skb, TLAN_MAX_FRAME_SIZE );			}			list->buffer[0].address = virt_to_bus( t );			list->buffer[9].address = (u32) skb;		}		list->buffer[1].count = 0;		list->buffer[1].address = 0;		if ( i < TLAN_NUM_RX_LISTS - 1 )			list->forward = virt_to_bus( list + 1 );		else			list->forward = 0;	}} /* TLan_ResetLists */void TLan_FreeLists( struct net_device *dev ){	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;	int		i;	TLanList	*list;	struct sk_buff	*skb;	if ( ! bbuf ) {		for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {			list = priv->txList + i;			skb = (struct sk_buff *) list->buffer[9].address;			if ( skb ) {				dev_kfree_skb_any( skb );				list->buffer[9].address = 0;			}		}		for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ ) {			list = priv->rxList + i;			skb = (struct sk_buff *) list->buffer[9].address;			if ( skb ) {				dev_kfree_skb_any( skb );				list->buffer[9].address = 0;			}		}	}} /* TLan_FreeLists */	/***************************************************************	 *	TLan_PrintDio	 *  	 *	Returns:	 *		Nothing	 *	Parms:	 *		io_base		Base IO port of the device of	 *				which to print DIO registers.	 *	 *	This function prints out all the the internal (DIO)	 *	registers of a TLAN chip.	 *	 **************************************************************/void TLan_PrintDio( u16 io_base ){	u32 data0, data1;	int	i;	printk( "TLAN:   Contents of internal registers for io base 0x%04hx.\n", io_base );	printk( "TLAN:      Off.  +0         +4\n" );	for ( i = 0; i < 0x4C; i+= 8 ) {		data0 = TLan_DioRead32( io_base, i );		data1 = TLan_DioRead32( io_base, i + 0x4 );		printk( "TLAN:      0x%02x  0x%08x 0x%08x\n", i, data0, data1 );	}} /* TLan_PrintDio */	/***************************************************************	 *	TLan_PrintList	 *  	 *	Returns:	 *		Nothing	 *	Parms:	 *		list	A pointer to the TLanList structure to	 *			be printed.	 *		type	A string to designate type of list,	 *			"Rx" or "Tx".	 *		num	The index of the list.	 *	 *	This function prints out the contents of the list	 *	pointed to by the list parameter.	 *	 **************************************************************/void TLan_PrintList( TLanList *list, char *type, int num){	int i;	printk( "TLAN:   %s List %d at 0x%08x\n", type, num, (u32) list );	printk( "TLAN:      Forward    = 0x%08x\n",  list->forward );	printk( "TLAN:      CSTAT      = 0x%04hx\n", list->cStat );	printk( "TLAN:      Frame Size = 0x%04hx\n", list->frameSize );	/* for ( i = 0; i < 10; i++ ) { */	for ( i = 0; i < 2; i++ ) {		printk( "TLAN:      Buffer[%d].count, addr = 0x%08x, 0x%08x\n", i, list->buffer[i].count, list->buffer[i].address );	}} /* TLan_PrintList */	/***************************************************************	 *	TLan_ReadAndClearStats	 *	 *	Returns:	 *		Nothing	 *	Parms:	 *		dev	Pointer to device structure of adapter	 *			to which to read stats.	 *		record	Flag indicating whether to add 	 *	 *	This functions reads all the internal status registers	 *	of the TLAN chip, which clears them as a side effect.	 *	It then either adds the values to the device's status	 *	struct, or discards them, depending on whether record	 *	is TLAN_RECORD (!=0)  or TLAN_IGNORE (==0).	 *	 **************************************************************/void TLan_ReadAndClearStats( struct net_device *dev, int record ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	u32		tx_good, tx_under;	u32		rx_good, rx_over;	u32		def_tx, crc, code;	u32		multi_col, single_col;	u32		excess_col, late_col, loss;	outw( TLAN_GOOD_TX_FRMS, dev->base_addr + TLAN_DIO_ADR );	tx_good  = inb( dev->base_addr + TLAN_DIO_DATA );	tx_good += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;	tx_good += inb( dev->base_addr + TLAN_DIO_DATA + 2 ) << 16;	tx_under = inb( dev->base_addr + TLAN_DIO_DATA + 3 );	outw( TLAN_GOOD_RX_FRMS, dev->base_addr + TLAN_DIO_ADR );	rx_good  = inb( dev->base_addr + TLAN_DIO_DATA );	rx_good += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;	rx_good += inb( dev->base_addr + TLAN_DIO_DATA + 2 ) << 16;	rx_over  = inb( dev->base_addr + TLAN_DIO_DATA + 3 );			outw( TLAN_DEFERRED_TX, dev->base_addr + TLAN_DIO_ADR );	def_tx  = inb( dev->base_addr + TLAN_DIO_DATA );	def_tx += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;	crc     = inb( dev->base_addr + TLAN_DIO_DATA + 2 );	code    = inb( dev->base_addr + TLAN_DIO_DATA + 3 );		outw( TLAN_MULTICOL_FRMS, dev->base_addr + TLAN_DIO_ADR );	multi_col   = inb( dev->base_addr + TLAN_DIO_DATA );	multi_col  += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;	single_col  = inb( dev->base_addr + TLAN_DIO_DATA + 2 );	single_col += inb( dev->base_addr + TLAN_DIO_DATA + 3 ) << 8;	outw( TLAN_EXCESSCOL_FRMS, dev->base_addr + TLAN_DIO_ADR );	excess_col = inb( dev->base_addr + TLAN_DIO_DATA );	late_col   = inb( dev->base_addr + TLAN_DIO_DATA + 1 );	loss       = inb( dev->base_addr + TLAN_DIO_DATA + 2 );	if ( record ) {		priv->stats.rx_packets += rx_good;		priv->stats.rx_errors  += rx_over + crc + code;		priv->stats.tx_packets += tx_good;		priv->stats.tx_errors  += tx_under + loss;		priv->stats.collisions += multi_col + single_col + excess_col + late_col;		priv->stats.rx_over_errors    += rx_over;		priv->stats.rx_crc_errors     += crc;		priv->stats.rx_frame_errors   += code;		priv->stats.tx_aborted_errors += tx_under;		priv->stats.tx_carrier_errors += loss;	}			} /* TLan_ReadAndClearStats */	/***************************************************************	 *	TLan_Reset	 *	 *	Returns:	 *		0	 *	Parms:	 *		dev	Pointer to device structure of adapter	 *			to be reset.	 *	 *	This function resets the adapter and it's physical	 *	device.  See Chap. 3, pp. 9-10 of the "ThunderLAN	 *	Programmer's Guide" for details.  The routine tries to	 *	implement what is detailed there, though adjustments	 *	have been made.	 *	 **************************************************************/voidTLan_ResetAdapter( struct net_device *dev ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	int		i;	u32		addr;	u32		data;	u8		data8;	priv->tlanFullDuplex = FALSE;	priv->phyOnline=0;/*  1.	Assert reset bit. */	data = inl(dev->base_addr + TLAN_HOST_CMD);	data |= TLAN_HC_AD_RST;	outl(data, dev->base_addr + TLAN_HOST_CMD);		udelay(1000);/*  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 net_device *dev ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	u8		data;	u32		phy;	u8		sio;	u16		status;	u16		partner;	u16		tlphy_ctl;	u16 		tlphy_par;	u16		tlphy_id1, tlphy_id2;	int 		i;	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 );	TLan_MiiReadReg( dev, phy, MII_GEN_ID_HI, &tlphy_id1 );	TLan_MiiReadReg( dev, phy, MII_GEN_ID_LO, &tlphy_id2 );		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) &&	 /* We only support link info on Nat.Sem. PHY's */ 			(tlphy_id1 == NAT_SEM_ID1) &&			(tlphy_id2 == NAT_SEM_ID2) ) {			TLan_MiiReadReg( dev, phy, MII_AN_LPA, &partner );			TLan_MiiReadReg( dev, phy, TLAN_TLPHY_PAR, &tlphy_par );						printk( "TLAN: %s: Link active with ", dev->name );			if (!(tlphy_par & TLAN_PHY_AN_EN_STAT)) {			      	 printk( "forced 10%sMbps %s-Duplex\n", 						tlphy_par & TLAN_PHY_SPEED_100 ? "" : "0",						tlphy_par & TLAN_PHY_DUPLEX_FULL ? "Full" : "Half");			} else {				printk( "AutoNegotiation enabled, at 10%sMbps %s-Duplex\n",						tlphy_par & TLAN_PHY_SPEED_100 ? "" : "0",						tlphy_par & TLAN_PHY_DUPLEX_FULL ? "Full" : "Half");				printk("TLAN: Partner capability: ");					for (i = 5; i <= 10; i++)						if (partner & (1<<i))							printk("%s", media[i-5]);							printk("\n");			}			TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );#ifdef MONITOR						/* We have link beat..for now anyway */	        	priv->link = 1;	        	/*Enabling link beat monitoring */			TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_LINK_BEAT );#endif 		} else 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 && debug != TLAN_DEBUG_PROBE ) {			outb( ( TLAN_HC_REQ_INT >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );		}		outl( virt_to

⌨️ 快捷键说明

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