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

📄 tlan.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	/**************************************************************	 *	TLan_ioctl	 *		 *	Returns:	 *		0 on success, error code otherwise	 *	Params:	 *		dev	structure of device to receive ioctl.	 *			 *		rq	ifreq structure to hold userspace data.	 *	 *		cmd	ioctl command.	 *	 *	 *************************************************************/static int TLan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	TLanPrivateInfo *priv = dev->priv;	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;	u32 phy   = priv->phy[priv->phyNum];		if (!priv->phyOnline)		return -EAGAIN;	switch(cmd) {	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */			data->phy_id = phy;	case SIOCGMIIREG:		/* Read MII PHY register. */	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */			TLan_MiiReadReg(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, &data->val_out);			return 0;			case SIOCSMIIREG:		/* Write MII PHY register. */	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */			if (!capable(CAP_NET_ADMIN))				return -EPERM;			TLan_MiiWriteReg(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);			return 0;		default:			return -EOPNOTSUPP;	}} /* tlan_ioctl */	/***************************************************************	 * 	TLan_tx_timeout	 *	 * 	Returns: nothing	 *	 * 	Params:	 * 		dev	structure of device which timed out 	 * 			during transmit.	 *	 **************************************************************/static void TLan_tx_timeout(struct net_device *dev){		TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Transmit timed out.\n", dev->name);		/* Ok so we timed out, lets see what we can do about it...*/	TLan_FreeLists( dev );	TLan_ResetLists( dev );			TLan_ReadAndClearStats( dev, TLAN_IGNORE );	TLan_ResetAdapter( dev );	dev->trans_start = jiffies;	netif_wake_queue( dev );	}		/***************************************************************	 *	TLan_StartTx	 *  	 *	Returns:	 *		0 on success, non-zero on failure.	 *	Parms:	 *		skb	A pointer to the sk_buff containing the	 *			frame to be sent.	 *		dev	The device to send the data on.	 *	 *	This function adds a frame to the Tx list to be sent	 *	ASAP.  First it	verifies that the adapter is ready and	 *	there is room in the queue.  Then it sets up the next	 *	available list, copies the frame to the	corresponding	 *	buffer.  If the adapter Tx channel is idle, it gives	 *	the adapter a Tx Go command on the list, otherwise it	 *	sets the forward address of the previous list to point	 *	to this one.  Then it frees the sk_buff.	 *	 **************************************************************/static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev ){	TLanPrivateInfo *priv = dev->priv;	TLanList	*tail_list;	u8		*tail_buffer;	int		pad;	unsigned long	flags;	if ( ! priv->phyOnline ) {		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  %s PHY is not ready\n", dev->name );		dev_kfree_skb_any(skb);		return 0;	}	tail_list = priv->txList + priv->txTail;		if ( tail_list->cStat != TLAN_CSTAT_UNUSED ) {		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  %s is busy (Head=%d Tail=%d)\n", dev->name, priv->txHead, priv->txTail );		netif_stop_queue(dev);		priv->txBusyCount++;		return 1;	}	tail_list->forward = 0;	if ( bbuf ) {		tail_buffer = priv->txBuffer + ( priv->txTail * TLAN_MAX_FRAME_SIZE );		memcpy( tail_buffer, skb->data, skb->len );	} else {		tail_list->buffer[0].address = virt_to_bus( skb->data );		tail_list->buffer[9].address = (u32) skb;	}	pad = TLAN_MIN_FRAME_SIZE - skb->len;	if ( pad > 0 ) {		tail_list->frameSize = (u16) skb->len + pad;		tail_list->buffer[0].count = (u32) skb->len;		tail_list->buffer[1].count = TLAN_LAST_BUFFER | (u32) pad;		tail_list->buffer[1].address = virt_to_bus( TLanPadBuffer );	} else {		tail_list->frameSize = (u16) skb->len;		tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) skb->len;		tail_list->buffer[1].count = 0;		tail_list->buffer[1].address = 0;	}	spin_lock_irqsave(&priv->lock, flags);	tail_list->cStat = TLAN_CSTAT_READY;	if ( ! priv->txInProgress ) {		priv->txInProgress = 1;		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Starting TX on buffer %d\n", priv->txTail );		outl( virt_to_bus( tail_list ), dev->base_addr + TLAN_CH_PARM );		outl( TLAN_HC_GO, dev->base_addr + TLAN_HOST_CMD );	} else {		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Adding buffer %d to TX channel\n", priv->txTail );		if ( priv->txTail == 0 ) {			( priv->txList + ( TLAN_NUM_TX_LISTS - 1 ) )->forward = virt_to_bus( tail_list );		} else {			( priv->txList + ( priv->txTail - 1 ) )->forward = virt_to_bus( tail_list );		}	}	spin_unlock_irqrestore(&priv->lock, flags);	CIRC_INC( priv->txTail, TLAN_NUM_TX_LISTS );	if ( bbuf )		dev_kfree_skb_any(skb);			dev->trans_start = jiffies;	return 0;} /* TLan_StartTx */	/***************************************************************	 *	TLan_HandleInterrupt	 *  	 *	Returns:		 *		Nothing	 *	Parms:	 *		irq	The line on which the interrupt	 *			occurred.	 *		dev_id	A pointer to the device assigned to	 *			this irq line.	 *		regs	???	 *	 *	This function handles an interrupt generated by its	 *	assigned TLAN adapter.  The function deactivates	 *	interrupts on its adapter, records the type of	 *	interrupt, executes the appropriate subhandler, and	 *	acknowdges the interrupt to the adapter (thus	 *	re-enabling adapter interrupts.	 *	 **************************************************************/static void TLan_HandleInterrupt(int irq, void *dev_id, struct pt_regs *regs){	u32		ack;	struct net_device	*dev;	u32		host_cmd;	u16		host_int;	int		type;	TLanPrivateInfo *priv;	dev = dev_id;	priv = dev->priv;	spin_lock(&priv->lock);	host_int = inw( dev->base_addr + TLAN_HOST_INT );	outw( host_int, dev->base_addr + TLAN_HOST_INT );	type = ( host_int & TLAN_HI_IT_MASK ) >> 2;	ack = TLanIntVector[type]( dev, host_int );	if ( ack ) {		host_cmd = TLAN_HC_ACK | ack | ( type << 18 );		outl( host_cmd, dev->base_addr + TLAN_HOST_CMD );	}	spin_unlock(&priv->lock);} /* TLan_HandleInterrupts */	/***************************************************************	 *	TLan_Close	 *  	 * 	Returns:	 *		An error code.	 *	Parms:	 *		dev	The device structure of the device to	 *			close.	 *	 *	This function shuts down the adapter.  It records any	 *	stats, puts the adapter into reset state, deactivates	 *	its time as needed, and	frees the irq it is using.	 *	 **************************************************************/static int TLan_Close(struct net_device *dev){	TLanPrivateInfo *priv = dev->priv;	netif_stop_queue(dev);	priv->neg_be_verbose = 0;	TLan_ReadAndClearStats( dev, TLAN_RECORD );	outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );	if ( priv->timer.function != NULL ) {		del_timer_sync( &priv->timer );		priv->timer.function = NULL;	}		free_irq( dev->irq, dev );	TLan_FreeLists( dev );	TLAN_DBG( TLAN_DEBUG_GNRL, "Device %s closed.\n", dev->name );	return 0;} /* TLan_Close */	/***************************************************************	 *	TLan_GetStats	 *  	 *	Returns:	 *		A pointer to the device's statistics structure.	 *	Parms:	 *		dev	The device structure to return the	 *			stats for.	 *	 *	This function updates the devices statistics by reading	 *	the TLAN chip's onboard registers.  Then it returns the	 *	address of the statistics structure.	 *	 **************************************************************/static struct net_device_stats *TLan_GetStats( struct net_device *dev ){	TLanPrivateInfo	*priv = dev->priv;	int i;	/* Should only read stats if open ? */	TLan_ReadAndClearStats( dev, TLAN_RECORD );	TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE:  %s EOC count = %d\n", dev->name, priv->rxEocCount );	TLAN_DBG( TLAN_DEBUG_TX, "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.	 *	 **************************************************************/static void TLan_SetMulticastList( struct net_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 net_device *dev, u16 host_int ){	/* 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 net_device *dev, u16 host_int ){	TLanPrivateInfo	*priv = dev->priv;	int		eoc = 0;	TLanList	*head_list;	u32		ack = 0;	u16		tmpCStat;		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Handling TX EOF (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );

⌨️ 快捷键说明

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