tlan.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,212 行 · 第 1/5 页

C
2,212
字号
				}				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;	dma_addr_t	head_list_phys;	u32		ack = 0;	u16		tmpCStat;		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Handling TX EOF (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );	head_list = priv->txList + priv->txHead;	while (((tmpCStat = head_list->cStat ) & TLAN_CSTAT_FRM_CMP) && (ack < 255)) {		ack++;		if ( ! bbuf ) {			struct sk_buff *skb = TLan_GetSKB(head_list);			pci_unmap_single(priv->pciDev, head_list->buffer[0].address, skb->len, PCI_DMA_TODEVICE);			dev_kfree_skb_any(skb);			head_list->buffer[8].address = 0;			head_list->buffer[9].address = 0;		}			if ( tmpCStat & TLAN_CSTAT_EOC )			eoc = 1;					priv->stats.tx_bytes += head_list->frameSize;		head_list->cStat = TLAN_CSTAT_UNUSED;		netif_start_queue(dev);				CIRC_INC( priv->txHead, TLAN_NUM_TX_LISTS ); 		head_list = priv->txList + priv->txHead;	}	if (!ack)		printk(KERN_INFO "TLAN: Received interrupt for uncompleted TX frame.\n");		if ( eoc ) {		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Handling TX EOC (Head=%d Tail=%d)\n", priv->txHead, priv->txTail );		head_list = priv->txList + priv->txHead;		head_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txHead;		if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {			outl(head_list_phys, 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 ) {			 priv->timer.function = &TLan_Timer;			 priv->timer.data = (unsigned long) dev;			 priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;			 priv->timerSetAt = jiffies;			 priv->timerType = TLAN_TIMER_ACTIVITY;			 add_timer(&priv->timer);		} 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 net_device *dev, u16 host_int ){	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 activity LED.	 *	 **************************************************************/u32 TLan_HandleRxEOF( struct net_device *dev, u16 host_int ){	TLanPrivateInfo	*priv = dev->priv;	u32		ack = 0;	int		eoc = 0;	u8		*head_buffer;	TLanList	*head_list;	struct sk_buff	*skb;	TLanList	*tail_list;	void		*t;	u32		frameSize;	u16		tmpCStat;	dma_addr_t	head_list_phys;	TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE:  Handling RX EOF (Head=%d Tail=%d)\n", priv->rxHead, priv->rxTail );	head_list = priv->rxList + priv->rxHead;	head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;		while (((tmpCStat = head_list->cStat) & TLAN_CSTAT_FRM_CMP) && (ack < 255)) {		frameSize = head_list->frameSize;		ack++;		if (tmpCStat & TLAN_CSTAT_EOC)			eoc = 1;				if (bbuf) {			skb = dev_alloc_skb(frameSize + 7);			if (skb == NULL)				printk(KERN_INFO "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, frameSize);						priv->stats.rx_bytes += head_list->frameSize;				memcpy( t, head_buffer, 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 ) {				skb = TLan_GetSKB(head_list);				pci_unmap_single(priv->pciDev, head_list->buffer[0].address, TLAN_MAX_FRAME_SIZE, PCI_DMA_FROMDEVICE);				skb_trim( skb, frameSize );				priv->stats.rx_bytes += frameSize;				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 = pci_map_single(priv->pciDev, new_skb->data, TLAN_MAX_FRAME_SIZE, PCI_DMA_FROMDEVICE);				head_list->buffer[8].address = (u32) t;				TLan_StoreSKB(head_list, new_skb);			} else 				printk(KERN_WARNING "TLAN:  Couldn't allocate memory for received data.\n" );		}		head_list->forward = 0;		head_list->cStat = 0;		tail_list = priv->rxList + priv->rxTail;		tail_list->forward = head_list_phys;		CIRC_INC( priv->rxHead, TLAN_NUM_RX_LISTS );		CIRC_INC( priv->rxTail, TLAN_NUM_RX_LISTS );		head_list = priv->rxList + priv->rxHead;		head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;	}	if (!ack)		printk(KERN_INFO "TLAN: Received interrupt for uncompleted RX frame.\n");		if ( eoc ) { 		TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE:  Handling RX EOC (Head=%d Tail=%d)\n", priv->rxHead, priv->rxTail );		head_list = priv->rxList + priv->rxHead;		head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;		outl(head_list_phys, 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 )  {			priv->timer.function = &TLan_Timer;			priv->timer.data = (unsigned long) dev;			priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;			priv->timerSetAt = jiffies;			priv->timerType = TLAN_TIMER_ACTIVITY;			add_timer(&priv->timer);		} 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 net_device *dev, u16 host_int ){	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 occurrences 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 net_device *dev, u16 host_int ){	TLanPrivateInfo	*priv = dev->priv;	TLanList		*head_list;	dma_addr_t		head_list_phys;	u32			ack = 1;		host_int = 0;	if ( priv->tlanRev < 0x30 ) {		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Handling TX EOC (Head=%d Tail=%d) -- IRQ\n", priv->txHead, priv->txTail );		head_list = priv->txList + priv->txHead;		head_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txHead;		if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {			netif_stop_queue(dev);			outl( head_list_phys, 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 net_device *dev, u16 host_int ){		TLanPrivateInfo	*priv = dev->priv;	u32		ack;	u32		error;	u8		net_sts;	u32		phy;	u16		tlphy_ctl;	u16		tlphy_sts;		ack = 1;	if ( host_int & TLAN_HI_IV_MASK ) {		netif_stop_queue( dev );		error = inl( dev->base_addr + TLAN_CH_PARM );		printk( "TLAN:  %s: Adaptor Error = 0x%x\n", dev->name, error );		TLan_ReadAndClearStats( dev, TLAN_RECORD );		outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );		schedule_work(&priv->tlan_tqueue);		netif_wake_queue(dev);		ack = 0;	} else {		TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Status Check\n", dev->name );		phy = priv->phy[priv->phyNum];		net_sts = TLan_DioRead8( dev->base_addr, TLAN_NET_STS );		if ( net_sts ) {			TLan_DioWrite8( dev->base_addr, TLAN_NET_STS, net_sts );			TLAN_DBG( TLAN_DEBUG_GNRL, "%s:    Net_Sts = %x\n", dev->name, (unsigned) net_sts );

⌨️ 快捷键说明

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