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

📄 tlan.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	 *	address of the statistics structure.	 *	 **************************************************************/struct net_device_stats *TLan_GetStats( struct device *dev ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	int i;	/* Should only read stats if open ? */	TLan_ReadAndClearStats( dev, TLAN_RECORD );	TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE:  %s EOC count = %d\n", dev->name, priv->rxEocCount );	TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  %s Busy count = %d\n", dev->name, priv->txBusyCount );	if ( debug & TLAN_DEBUG_GNRL ) {		TLan_PrintDio( dev->base_addr );		TLan_PhyPrint( dev );	}	if ( debug & TLAN_DEBUG_LIST ) {		for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ )			TLan_PrintList( priv->rxList + i, "RX", i );		for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ )			TLan_PrintList( priv->txList + i, "TX", i );	}		return ( &( (TLanPrivateInfo *) dev->priv )->stats );} /* TLan_GetStats */	/***************************************************************	 *	TLan_SetMulticastList	 *  	 *	Returns:	 *		Nothing	 *	Parms:	 *		dev	The device structure to set the	 *			multicast list for.	 *	 *	This function sets the TLAN adaptor to various receive	 *	modes.  If the IFF_PROMISC flag is set, promiscuous	 *	mode is acitviated.  Otherwise,	promiscuous mode is	 *	turned off.  If the IFF_ALLMULTI flag is set, then	 *	the hash table is set to receive all group addresses.	 *	Otherwise, the first three multicast addresses are	 *	stored in AREG_1-3, and the rest are selected via the	 *	hash table, as necessary.	 *	 **************************************************************/void TLan_SetMulticastList( struct device *dev ){		struct dev_mc_list	*dmi = dev->mc_list;	u32			hash1 = 0;	u32			hash2 = 0;	int			i;	u32			offset;	u8			tmp;	if ( dev->flags & IFF_PROMISC ) {		tmp = TLan_DioRead8( dev->base_addr, TLAN_NET_CMD );		TLan_DioWrite8( dev->base_addr, TLAN_NET_CMD, tmp | TLAN_NET_CMD_CAF );	} else {		tmp = TLan_DioRead8( dev->base_addr, TLAN_NET_CMD );		TLan_DioWrite8( dev->base_addr, TLAN_NET_CMD, tmp & ~TLAN_NET_CMD_CAF );		if ( dev->flags & IFF_ALLMULTI ) {			for ( i = 0; i < 3; i++ ) 				TLan_SetMac( dev, i + 1, NULL );			TLan_DioWrite32( dev->base_addr, TLAN_HASH_1, 0xFFFFFFFF );			TLan_DioWrite32( dev->base_addr, TLAN_HASH_2, 0xFFFFFFFF );		} else {			for ( i = 0; i < dev->mc_count; i++ ) {				if ( i < 3 ) {					TLan_SetMac( dev, i + 1, (char *) &dmi->dmi_addr );				} else {					offset = TLan_HashFunc( (u8 *) &dmi->dmi_addr );					if ( offset < 32 ) 						hash1 |= ( 1 << offset );					else						hash2 |= ( 1 << ( offset - 32 ) );				}				dmi = dmi->next;			}			for ( ; i < 3; i++ ) 				TLan_SetMac( dev, i + 1, NULL );			TLan_DioWrite32( dev->base_addr, TLAN_HASH_1, hash1 );			TLan_DioWrite32( dev->base_addr, TLAN_HASH_2, hash2 );		}	}} /* TLan_SetMulticastList *//***********************************************************************************************************************************************************        ThunderLAN Driver Interrupt Vectors and Table	Please see Chap. 4, "Interrupt Handling" of the "ThunderLAN	Programmer's Guide" for more informations on handling interrupts	generated by TLAN based adapters.  ***********************************************************************************************************************************************************/	/***************************************************************	 *	TLan_HandleInvalid	 *	 *	Returns:	 *		0	 *	Parms:	 *		dev		Device assigned the IRQ that was	 *				raised.	 *		host_int	The contents of the HOST_INT	 *				port.	 *	 *	This function handles invalid interrupts.  This should	 *	never happen unless some other adapter is trying to use	 *	the IRQ line assigned to the device.	 *	 **************************************************************/u32 TLan_HandleInvalid( struct device *dev, u16 host_int ){	host_int = 0;	/* printk( "TLAN:  Invalid interrupt on %s.\n", dev->name ); */	return 0;} /* TLan_HandleInvalid */	/***************************************************************	 *	TLan_HandleTxEOF	 *	 *	Returns:	 *		1	 *	Parms:	 *		dev		Device assigned the IRQ that was	 *				raised.	 *		host_int	The contents of the HOST_INT	 *				port.	 *	 *	This function handles Tx EOF interrupts which are raised	 *	by the adapter when it has completed sending the	 *	contents of a buffer.  If detemines which list/buffer	 *	was completed and resets it.  If the buffer was the last	 *	in the channel (EOC), then the function checks to see if	 *	another buffer is ready to send, and if so, sends a Tx	 *	Go command.  Finally, the driver activates/continues the	 *	activity LED.	 *	 **************************************************************/u32 TLan_HandleTxEOF( struct device *dev, u16 host_int ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	int		eoc = 0;	TLanList	*head_list;	u32		ack = 1;	TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  Handling TX EOF (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );	host_int = 0;	head_list = priv->txList + priv->txHead;	if ( ! bbuf ) {		dev_kfree_skb( (struct sk_buff *) head_list->buffer[9].address );		head_list->buffer[9].address = 0;	}	if ( head_list->cStat & TLAN_CSTAT_EOC )		eoc = 1;	if ( ! head_list->cStat & TLAN_CSTAT_FRM_CMP ) {		printk( "TLAN:  Received interrupt for uncompleted TX frame.\n" );	}#if LINUX_KERNEL_VERSION > 0x20100	priv->stats->tx_bytes += head_list->frameSize;#endif	head_list->cStat = TLAN_CSTAT_UNUSED;	dev->tbusy = 0;	CIRC_INC( priv->txHead, TLAN_NUM_TX_LISTS );	if ( eoc ) {		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  Handling TX EOC (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );		head_list = priv->txList + priv->txHead;		if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {			outl( virt_to_bus( head_list ), dev->base_addr + TLAN_CH_PARM );			ack |= TLAN_HC_GO;		} else {			priv->txInProgress = 0;		}	}	if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) {		TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );		if ( priv->timer.function == NULL ) {			TLan_SetTimer( dev, TLAN_TIMER_ACT_DELAY, TLAN_TIMER_ACTIVITY );		} else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) {			priv->timerSetAt = jiffies;		}	}	return ack;} /* TLan_HandleTxEOF */	/***************************************************************	 *	TLan_HandleStatOverflow	 *	 *	Returns:	 *		1	 *	Parms:	 *		dev		Device assigned the IRQ that was	 *				raised.	 *		host_int	The contents of the HOST_INT	 *				port.	 *	 *	This function handles the Statistics Overflow interrupt	 *	which means that one or more of the TLAN statistics	 *	registers has reached 1/2 capacity and needs to be read.	 *	 **************************************************************/u32 TLan_HandleStatOverflow( struct device *dev, u16 host_int ){	host_int = 0;	TLan_ReadAndClearStats( dev, TLAN_RECORD );	return 1;} /* TLan_HandleStatOverflow */	/***************************************************************	 *	TLan_HandleRxEOF	 *	 *	Returns:	 *		1	 *	Parms:	 *		dev		Device assigned the IRQ that was	 *				raised.	 *		host_int	The contents of the HOST_INT	 *				port.	 *	 *	This function handles the Rx EOF interrupt which	 *	indicates a frame has been received by the adapter from	 *	the net and the frame has been transferred to memory.	 *	The function determines the bounce buffer the frame has	 *	been loaded into, creates a new sk_buff big enough to	 *	hold the frame, and sends it to protocol stack.  It	 *	then resets the used buffer and appends it to the end	 *	of the list.  If the frame was the last in the Rx	 *	channel (EOC), the function restarts the receive channel	 *	by sending an Rx Go command to the adapter.  Then it	 *	activates/continues the the activity LED.	 *	 **************************************************************/u32 TLan_HandleRxEOF( struct device *dev, u16 host_int ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	u32		ack = 1;	int		eoc = 0;	u8		*head_buffer;	TLanList	*head_list;	struct sk_buff	*skb;	TLanList	*tail_list;	void		*t;	TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE:  Handling RX EOF (Head=%d Tail=%d)\n", priv->rxHead, priv->rxTail );	host_int = 0;	head_list = priv->rxList + priv->rxHead;	tail_list = priv->rxList + priv->rxTail;	if ( head_list->cStat & TLAN_CSTAT_EOC ) {		eoc = 1;	}	if ( ! head_list->cStat & TLAN_CSTAT_FRM_CMP ) {		printk( "TLAN:  Received interrupt for uncompleted RX frame.\n" );	} else if ( bbuf ) {		skb = dev_alloc_skb( head_list->frameSize + 7 );		if ( skb == NULL ) { 			printk( "TLAN:  Couldn't allocate memory for received data.\n" );		} else {			head_buffer = priv->rxBuffer + ( priv->rxHead * TLAN_MAX_FRAME_SIZE );			skb->dev = dev;			skb_reserve( skb, 2 );			t = (void *) skb_put( skb, head_list->frameSize );#if LINUX_KERNEL_VERSION > 0x20100			priv->stats->rx_bytes += head_list->frameSize;#endif			memcpy( t, head_buffer, head_list->frameSize );			skb->protocol = eth_type_trans( skb, dev );			netif_rx( skb );		}	} else {		struct sk_buff *new_skb;				/*		 *	I changed the algorithm here. What we now do		 *	is allocate the new frame. If this fails we		 *	simply recycle the frame.		 */				new_skb = dev_alloc_skb( TLAN_MAX_FRAME_SIZE + 7 );		if ( new_skb != NULL ) {			/* If this ever happened it would be a problem */			/* not any more - ac */			skb = (struct sk_buff *) head_list->buffer[9].address;			head_list->buffer[9].address = 0;			skb_trim( skb, head_list->frameSize );#if LINUX_KERNEL_VERSION > 0x20100			priv->stats->rx_bytes += head_list->frameSize;#endif			skb->protocol = eth_type_trans( skb, dev );			netif_rx( skb );				new_skb->dev = dev;			skb_reserve( new_skb, 2 );			t = (void *) skb_put( new_skb, TLAN_MAX_FRAME_SIZE );			head_list->buffer[0].address = virt_to_bus( t );			head_list->buffer[9].address = (u32) new_skb;		}		else			printk(KERN_WARNING "TLAN:  Couldn't allocate memory for received data.\n" );	}	head_list->forward = 0;	head_list->frameSize = TLAN_MAX_FRAME_SIZE;	head_list->buffer[0].count = TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;	tail_list->forward = virt_to_bus( head_list );	CIRC_INC( priv->rxHead, TLAN_NUM_RX_LISTS );	CIRC_INC( priv->rxTail, TLAN_NUM_RX_LISTS );	if ( eoc ) { 		TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE:  Handling RX EOC (Head=%d Tail=%d)\n", priv->rxHead, priv->rxTail );		head_list = priv->rxList + priv->rxHead;		outl( virt_to_bus( head_list ), dev->base_addr + TLAN_CH_PARM );		ack |= TLAN_HC_GO | TLAN_HC_RT;		priv->rxEocCount++;	}	if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) {		TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );		if ( priv->timer.function == NULL )  {			TLan_SetTimer( dev, TLAN_TIMER_ACT_DELAY, TLAN_TIMER_ACTIVITY );		} else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) {			priv->timerSetAt = jiffies;		}	}	dev->last_rx = jiffies;	return ack;} /* TLan_HandleRxEOF */	/***************************************************************	 *	TLan_HandleDummy	 *	 *	Returns:	 *		1	 *	Parms:	 *		dev		Device assigned the IRQ that was	 *				raised.	 *		host_int	The contents of the HOST_INT	 *				port.	 *	 *	This function handles the Dummy interrupt, which is	 *	raised whenever a test interrupt is generated by setting	 *	the Req_Int bit of HOST_CMD to 1.	 *	 **************************************************************/u32 TLan_HandleDummy( struct device *dev, u16 host_int ){	host_int = 0;	printk( "TLAN:  Test interrupt on %s.\n", dev->name );	return 1;} /* TLan_HandleDummy */	/***************************************************************	 *	TLan_HandleTxEOC	 *	 *	Returns:	 *		1	 *	Parms:	 *		dev		Device assigned the IRQ that was	 *				raised.	 *		host_int	The contents of the HOST_INT	 *				port.	 *	 *	This driver is structured to determine EOC occurances by	 *	reading the CSTAT member of the list structure.  Tx EOC	 *	interrupts are disabled via the DIO INTDIS register.	 *	However, TLAN chips before revision 3.0 didn't have this	 *	functionality, so process EOC events if this is the	 *	case.	 *	 **************************************************************/u32 TLan_HandleTxEOC( struct device *dev, u16 host_int ){	TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;	TLanList		*head_list;	u32				ack = 1;	host_int = 0;	if ( priv->tlanRev < 0x30 ) {		TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT:  Handling TX EOC (Head=%d Tail=%d) -- IRQ\n", priv->txHead, priv->txTail );		head_list = priv->txList + priv->txHead;		if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {			outl( virt_to_bus( head_list ), dev->base_addr + TLAN_CH_PARM );			ack |= TLAN_HC_GO;		} else {			priv->txInProgress = 0;		}	}	return ack;} /* TLan_HandleTxEOC */	/***************************************************************	 *	TLan_HandleStatusCheck	 *	 *	Returns:	 *		0 if Adapter check, 1 if Network Status check.	 *	Parms:	 *		dev		Device assigned the IRQ that was	 *				raised.	 *		host_int	The contents of the HOST_INT	 *				port.	 *	 *	This function handles Adapter Check/Network Status	 *	interrupts generated by the adapter.  It checks the	 *	vector in the HOST_INT register to determine if it is	 *	an Adapter Check interrupt.  If so, it resets the	 *	adapter.  Otherwise it clears the status registers	 *	and services the PHY.	 *	 **************************************************************/u32 TLan_HandleStatusCheck( struct device *dev, u16 host_int ){		TLanPrivateInfo	*priv = (TLanPrivateInfo *) dev->priv;

⌨️ 快捷键说明

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