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

📄 tms380tr.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
			/* Parm[0-3]: adapter internal register R13-R15 */			break;		default:			printk(KERN_INFO "%s: Unknown status", dev->name);			break;	}	if(tms380tr_chipset_init(dev) == 1)	{		/* Restart of firmware successful */		tp->AdapterOpenFlag = 1;	}	return;}/* * Internal adapter pointer to RAM data are copied from adapter into * host system. */static int tms380tr_read_ptr(struct net_device *dev){	struct net_local *tp = netdev_priv(dev);	unsigned short adapterram;	tms380tr_read_ram(dev, (unsigned char *)&tp->intptrs.BurnedInAddrPtr,			ADAPTER_INT_PTRS, 16);	tms380tr_read_ram(dev, (unsigned char *)&adapterram,			cpu_to_be16((unsigned short)tp->intptrs.AdapterRAMPtr), 2);	return be16_to_cpu(adapterram); }/* * Reads a number of bytes from adapter to system memory. */static void tms380tr_read_ram(struct net_device *dev, unsigned char *Data,				unsigned short Address, int Length){	int i;	unsigned short old_sifadx, old_sifadr, InWord;	/* Save the current values */	old_sifadx = SIFREADW(SIFADX);	old_sifadr = SIFREADW(SIFADR);	/* Page number of adapter memory */	SIFWRITEW(0x0001, SIFADX);	/* Address offset in adapter RAM */        SIFWRITEW(Address, SIFADR);	/* Copy len byte from adapter memory to system data area. */	i = 0;	for(;;)	{		InWord = SIFREADW(SIFINC);		*(Data + i) = HIBYTE(InWord);	/* Write first byte */		if(++i == Length)		/* All is done break */			break;		*(Data + i) = LOBYTE(InWord);	/* Write second byte */		if (++i == Length)		/* All is done break */			break;	}	/* Restore original values */	SIFWRITEW(old_sifadx, SIFADX);	SIFWRITEW(old_sifadr, SIFADR);	return;}/* * Cancel all queued packets in the transmission queue. */static void tms380tr_cancel_tx_queue(struct net_local* tp){	TPL *tpl;	/*	 * NOTE: There must not be an active TRANSMIT command pending, when	 * this function is called.	 */	if(tp->TransmitCommandActive)		return;	for(;;)	{		tpl = tp->TplBusy;		if(!tpl->BusyFlag)			break;		/* "Remove" TPL from busy list. */		tp->TplBusy = tpl->NextTPLPtr;		tms380tr_write_tpl_status(tpl, 0);	/* Clear VALID bit */		tpl->BusyFlag = 0;		/* "free" TPL */		printk(KERN_INFO "Cancel tx (%08lXh).\n", (unsigned long)tpl);		if (tpl->DMABuff)			dma_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, DMA_TO_DEVICE);		dev_kfree_skb_any(tpl->Skb);	}	return;}/* * This function is called whenever a transmit interrupt is generated by the * adapter. For a command complete interrupt, it is checked if we have to * issue a new transmit command or not. */static void tms380tr_tx_status_irq(struct net_device *dev){	struct net_local *tp = netdev_priv(dev);	unsigned char HighByte, HighAc, LowAc;	TPL *tpl;	/* NOTE: At this point the SSB from TRANSMIT STATUS is no longer	 * available, because the CLEAR SSB command has already been issued.	 *	 * Process all complete transmissions.	 */	for(;;)	{		tpl = tp->TplBusy;		if(!tpl->BusyFlag || (tpl->Status			& (TX_VALID | TX_FRAME_COMPLETE))			!= TX_FRAME_COMPLETE)		{			break;		}		/* "Remove" TPL from busy list. */		tp->TplBusy = tpl->NextTPLPtr ;		/* Check the transmit status field only for directed frames*/		if(DIRECTED_FRAME(tpl) && (tpl->Status & TX_ERROR) == 0)		{			HighByte = GET_TRANSMIT_STATUS_HIGH_BYTE(tpl->Status);			HighAc   = GET_FRAME_STATUS_HIGH_AC(HighByte);			LowAc    = GET_FRAME_STATUS_LOW_AC(HighByte);			if((HighAc != LowAc) || (HighAc == AC_NOT_RECOGNIZED))			{				printk(KERN_DEBUG "%s: (DA=%08lX not recognized)\n",					dev->name,					*(unsigned long *)&tpl->MData[2+2]);			}			else			{				if(tms380tr_debug > 3)					printk(KERN_DEBUG "%s: Directed frame tx'd\n", 						dev->name);			}		}		else		{			if(!DIRECTED_FRAME(tpl))			{				if(tms380tr_debug > 3)					printk(KERN_DEBUG "%s: Broadcast frame tx'd\n",						dev->name);			}		}		tp->MacStat.tx_packets++;		if (tpl->DMABuff)			dma_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, DMA_TO_DEVICE);		dev_kfree_skb_irq(tpl->Skb);		tpl->BusyFlag = 0;	/* "free" TPL */	}	if(!tp->TplFree->NextTPLPtr->BusyFlag)		netif_wake_queue(dev);	return;}/* * Called if a frame receive interrupt is generated by the adapter. * Check if the frame is valid and indicate it to system. */static void tms380tr_rcv_status_irq(struct net_device *dev){	struct net_local *tp = netdev_priv(dev);	unsigned char *ReceiveDataPtr;	struct sk_buff *skb;	unsigned int Length, Length2;	RPL *rpl;	RPL *SaveHead;	dma_addr_t dmabuf;	/* NOTE: At this point the SSB from RECEIVE STATUS is no longer	 * available, because the CLEAR SSB command has already been issued.	 *	 * Process all complete receives.	 */	for(;;)	{		rpl = tp->RplHead;		if(rpl->Status & RX_VALID)			break;		/* RPL still in use by adapter */		/* Forward RPLHead pointer to next list. */		SaveHead = tp->RplHead;		tp->RplHead = rpl->NextRPLPtr;		/* Get the frame size (Byte swap for Intel).		 * Do this early (see workaround comment below)		 */		Length = be16_to_cpu((unsigned short)rpl->FrameSize);		/* Check if the Frame_Start, Frame_End and		 * Frame_Complete bits are set.		 */		if((rpl->Status & VALID_SINGLE_BUFFER_FRAME)			== VALID_SINGLE_BUFFER_FRAME)		{			ReceiveDataPtr = rpl->MData;			/* Workaround for delayed write of FrameSize on ISA			 * (FrameSize is false but valid-bit is reset)			 * Frame size is set to zero when the RPL is freed.			 * Length2 is there because there have also been			 * cases where the FrameSize was partially written			 */			Length2 = be16_to_cpu((unsigned short)rpl->FrameSize);			if(Length == 0 || Length != Length2)			{				tp->RplHead = SaveHead;				break;	/* Return to tms380tr_interrupt */			}			tms380tr_update_rcv_stats(tp,ReceiveDataPtr,Length);			  			if(tms380tr_debug > 3)				printk(KERN_DEBUG "%s: Packet Length %04X (%d)\n",					dev->name, Length, Length);			  			/* Indicate the received frame to system the			 * adapter does the Source-Routing padding for 			 * us. See: OpenOptions in tms380tr_init_opb()			 */			skb = rpl->Skb;			if(rpl->SkbStat == SKB_UNAVAILABLE)			{				/* Try again to allocate skb */				skb = dev_alloc_skb(tp->MaxPacketSize);				if(skb == NULL)				{					/* Update Stats ?? */				}				else				{					skb->dev	= dev;					skb_put(skb, tp->MaxPacketSize);					rpl->SkbStat 	= SKB_DATA_COPY;					ReceiveDataPtr 	= rpl->MData;				}			}			if(skb && (rpl->SkbStat == SKB_DATA_COPY				|| rpl->SkbStat == SKB_DMA_DIRECT))			{				if(rpl->SkbStat == SKB_DATA_COPY)					memcpy(skb->data, ReceiveDataPtr, Length);				/* Deliver frame to system */				rpl->Skb = NULL;				skb_trim(skb,Length);				skb->protocol = tr_type_trans(skb,dev);				netif_rx(skb);				dev->last_rx = jiffies;			}		}		else	/* Invalid frame */		{			if(rpl->Skb != NULL)				dev_kfree_skb_irq(rpl->Skb);			/* Skip list. */			if(rpl->Status & RX_START_FRAME)				/* Frame start bit is set -> overflow. */				tp->MacStat.rx_errors++;		}		if (rpl->DMABuff)			dma_unmap_single(tp->pdev, rpl->DMABuff, tp->MaxPacketSize, DMA_TO_DEVICE);		rpl->DMABuff = 0;		/* Allocate new skb for rpl */		rpl->Skb = dev_alloc_skb(tp->MaxPacketSize);		/* skb == NULL ? then use local buffer */		if(rpl->Skb == NULL)		{			rpl->SkbStat = SKB_UNAVAILABLE;			rpl->FragList[0].DataAddr = htonl(((char *)tp->LocalRxBuffers[rpl->RPLIndex] - (char *)tp) + tp->dmabuffer);			rpl->MData = tp->LocalRxBuffers[rpl->RPLIndex];		}		else	/* skb != NULL */		{			rpl->Skb->dev = dev;			skb_put(rpl->Skb, tp->MaxPacketSize);			/* Data unreachable for DMA ? then use local buffer */			dmabuf = dma_map_single(tp->pdev, rpl->Skb->data, tp->MaxPacketSize, DMA_FROM_DEVICE);			if(tp->dmalimit && (dmabuf + tp->MaxPacketSize > tp->dmalimit))			{				rpl->SkbStat = SKB_DATA_COPY;				rpl->FragList[0].DataAddr = htonl(((char *)tp->LocalRxBuffers[rpl->RPLIndex] - (char *)tp) + tp->dmabuffer);				rpl->MData = tp->LocalRxBuffers[rpl->RPLIndex];			}			else			{				/* DMA directly in skb->data */				rpl->SkbStat = SKB_DMA_DIRECT;				rpl->FragList[0].DataAddr = htonl(dmabuf);				rpl->MData = rpl->Skb->data;				rpl->DMABuff = dmabuf;			}		}		rpl->FragList[0].DataCount = cpu_to_be16((unsigned short)tp->MaxPacketSize);		rpl->FrameSize = 0;		/* Pass the last RPL back to the adapter */		tp->RplTail->FrameSize = 0;		/* Reset the CSTAT field in the list. */		tms380tr_write_rpl_status(tp->RplTail, RX_VALID | RX_FRAME_IRQ);		/* Current RPL becomes last one in list. */		tp->RplTail = tp->RplTail->NextRPLPtr;		/* Inform adapter about RPL valid. */		tms380tr_exec_sifcmd(dev, CMD_RX_VALID);	}	return;}/* * This function should be used whenever the status of any RPL must be * modified by the driver, because the compiler may otherwise change the * order of instructions such that writing the RPL status may be executed * at an undesireable time. When this function is used, the status is * always written when the function is called. */static void tms380tr_write_rpl_status(RPL *rpl, unsigned int Status){	rpl->Status = Status;	return;}/* * The function updates the statistic counters in mac->MacStat. * It differtiates between directed and broadcast/multicast ( ==functional) * frames. */static void tms380tr_update_rcv_stats(struct net_local *tp, unsigned char DataPtr[],					unsigned int Length){	tp->MacStat.rx_packets++;	tp->MacStat.rx_bytes += Length;		/* Test functional bit */	if(DataPtr[2] & GROUP_BIT)		tp->MacStat.multicast++;	return;}static int tms380tr_set_mac_address(struct net_device *dev, void *addr){	struct net_local *tp = netdev_priv(dev);	struct sockaddr *saddr = addr;		if (tp->AdapterOpenFlag || tp->AdapterVirtOpenFlag) {		printk(KERN_WARNING "%s: Cannot set MAC/LAA address while card is open\n", dev->name);		return -EIO;	}	memcpy(dev->dev_addr, saddr->sa_data, dev->addr_len);	return 0;}#if TMS380TR_DEBUG > 0/* * Dump Packet (data) */static void tms380tr_dump(unsigned char *Data, int length){	int i, j;	for (i = 0, j = 0; i < length / 8; i++, j += 8)	{		printk(KERN_DEBUG "%02x %02x %02x %02x %02x %02x %02x %02x\n",		       Data[j+0],Data[j+1],Data[j+2],Data[j+3],		       Data[j+4],Data[j+5],Data[j+6],Data[j+7]);	}	return;}#endifvoid tmsdev_term(struct net_device *dev){	struct net_local *tp;	tp = netdev_priv(dev);	dma_unmap_single(tp->pdev, tp->dmabuffer, sizeof(struct net_local),		DMA_BIDIRECTIONAL);}int tmsdev_init(struct net_device *dev, struct device *pdev){	struct net_local *tms_local;	memset(dev->priv, 0, sizeof(struct net_local));	tms_local = netdev_priv(dev);	init_waitqueue_head(&tms_local->wait_for_tok_int);	if (pdev->dma_mask)		tms_local->dmalimit = *pdev->dma_mask;	else		return -ENOMEM;	tms_local->pdev = pdev;	tms_local->dmabuffer = dma_map_single(pdev, (void *)tms_local,	    sizeof(struct net_local), DMA_BIDIRECTIONAL);	if (tms_local->dmabuffer + sizeof(struct net_local) > 			tms_local->dmalimit)	{		printk(KERN_INFO "%s: Memory not accessible for DMA\n",			dev->name);		tmsdev_term(dev);		return -ENOMEM;	}		/* These can be overridden by the card driver if needed */	dev->open		= tms380tr_open;	dev->stop		= tms380tr_close;	dev->do_ioctl		= NULL; 	dev->hard_start_xmit	= tms380tr_send_packet;	dev->tx_timeout		= tms380tr_timeout;	dev->watchdog_timeo	= HZ;	dev->get_stats		= tms380tr_get_stats;	dev->set_multicast_list = &tms380tr_set_multicast_list;	dev->set_mac_address	= tms380tr_set_mac_address;	return 0;}EXPORT_SYMBOL(tms380tr_open);EXPORT_SYMBOL(tms380tr_close);EXPORT_SYMBOL(tms380tr_interrupt);EXPORT_SYMBOL(tmsdev_init);EXPORT_SYMBOL(tmsdev_term);EXPORT_SYMBOL(tms380tr_wait);#ifdef MODULEstatic struct module *TMS380_module = NULL;int init_module(void){	printk(KERN_DEBUG "%s", version);		TMS380_module = &__this_module;	return 0;}void cleanup_module(void){	TMS380_module = NULL;}#endifMODULE_LICENSE("GPL");

⌨️ 快捷键说明

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