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

📄 skge.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
		ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);		ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);		ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]);	}	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,		("SkGeClose: done "));	pAC->MaxPorts--;	pNet->Up = 0;	MOD_DEC_USE_COUNT;		return (0);} /* SkGeClose *//***************************************************************************** * * 	SkGeXmit - Linux frame transmit function * * Description: *	The system calls this function to send frames onto the wire. *	It puts the frame in the tx descriptor ring. If the ring is *	full then, the 'tbusy' flag is set. * * Returns: *	0, if everything is ok *	!=0, on error * WARNING: returning 1 in 'tbusy' case caused system crashes (double *	allocated skb's) !!! */static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev){DEV_NET		*pNet;SK_AC		*pAC;int			Rc;	/* return code of XmitFrame */	pNet = (DEV_NET*) dev->priv;	pAC = pNet->pAC;	if ((!skb_shinfo(skb)->nr_frags) || 		(pAC->GIni.GIChipId == CHIP_ID_GENESIS)) {		/* Don't activate scatter-gather and hardware checksum */		if (pAC->RlmtNets == 2)			Rc = XmitFrame(				pAC,				&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],				skb);		else			Rc = XmitFrame(				pAC,				&pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],				skb);	} else {		/* scatter-gather and hardware TCP checksumming anabled*/		if (pAC->RlmtNets == 2)			Rc = XmitFrameSG(				pAC,				&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],				skb);		else			Rc = XmitFrameSG(				pAC,				&pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],				skb);	}	/* Transmitter out of resources? */	if (Rc <= 0) {		netif_stop_queue(dev);	}	/* If not taken, give buffer ownership back to the	 * queueing layer.	 */	if (Rc < 0)		return (1);	dev->trans_start = jiffies;	return (0);} /* SkGeXmit *//***************************************************************************** * * 	XmitFrame - fill one socket buffer into the transmit ring * * Description: *	This function puts a message into the transmit descriptor ring *	if there is a descriptors left. *	Linux skb's consist of only one continuous buffer. *	The first step locks the ring. It is held locked *	all time to avoid problems with SWITCH_../PORT_RESET. *	Then the descriptoris allocated. *	The second part is linking the buffer to the descriptor. *	At the very last, the Control field of the descriptor *	is made valid for the BMU and a start TX command is given *	if necessary. * * Returns: *	> 0 - on succes: the number of bytes in the message *	= 0 - on resource shortage: this frame sent or dropped, now *		the ring is full ( -> set tbusy) *	< 0 - on failure: other problems ( -> return failure to upper layers) */static int XmitFrame(SK_AC 		*pAC,		/* pointer to adapter context */TX_PORT		*pTxPort,	/* pointer to struct of port to send to */struct sk_buff	*pMessage)	/* pointer to send-message */{TXD		*pTxd;		/* the rxd to fill */unsigned long	Flags;SK_U64		PhysAddr;int		BytesSend;	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,		("X"));	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);#ifndef USE_TX_COMPLETE	FreeTxDescriptors(pAC, pTxPort);#endif	if (pTxPort->TxdRingFree == 0) {		/* no enough free descriptors in ring at the moment */		FreeTxDescriptors(pAC, pTxPort);		if (pTxPort->TxdRingFree == 0) {			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);			SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,				SK_DBGCAT_DRV_TX_PROGRESS,				("XmitFrame failed\n"));			/* this message can not be sent now */			/* Because tbusy seems to be set, the message should not be freed here */			/* It will be used by the scheduler of the ethernet handler */			return (-1);		}	}	/* advance head counter behind descriptor needed for this frame */	pTxd = pTxPort->pTxdRingHead;	pTxPort->pTxdRingHead = pTxd->pNextTxd;	pTxPort->TxdRingFree--;	/* the needed descriptor is reserved now */		/* 	 * everything allocated ok, so add buffer to descriptor	 */#ifdef SK_DUMP_TX	DumpMsg(pMessage, "XmitFrame");#endif	/* set up descriptor and CONTROL dword */	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,		virt_to_page(pMessage->data),		((unsigned long) pMessage->data &		~PAGE_MASK),		pMessage->len,		PCI_DMA_TODEVICE);	pTxd->VDataLow = (SK_U32)  (PhysAddr & 0xffffffff);	pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);	pTxd->pMBuf = pMessage;	pTxd->TBControl = TX_CTRL_OWN_BMU | TX_CTRL_STF |		TX_CTRL_CHECK_DEFAULT | TX_CTRL_SOFTWARE |#ifdef USE_TX_COMPLETE		TX_CTRL_EOF | TX_CTRL_EOF_IRQ | pMessage->len;#else		TX_CTRL_EOF | pMessage->len;#endif		if ((pTxPort->pTxdRingPrev->TBControl & TX_CTRL_OWN_BMU) == 0) {		/* previous descriptor already done, so give tx start cmd */		/* StartTx(pAC, pTxPort->HwAddr); */		SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START);	}	pTxPort->pTxdRingPrev = pTxd;			BytesSend = pMessage->len;	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);	/* after releasing the lock, the skb may be immidiately freed */	if (pTxPort->TxdRingFree != 0)		return (BytesSend);	else		return (0);} /* XmitFrame *//***************************************************************************** * * 	XmitFrameSG - fill one socket buffer into the transmit ring *                (use SG and TCP/UDP hardware checksumming) * * Description: *	This function puts a message into the transmit descriptor ring *	if there is a descriptors left. * * Returns: *	> 0 - on succes: the number of bytes in the message *	= 0 - on resource shortage: this frame sent or dropped, now *		the ring is full ( -> set tbusy) *	< 0 - on failure: other problems ( -> return failure to upper layers) */static int XmitFrameSG(SK_AC 		*pAC,			/* pointer to adapter context */TX_PORT		*pTxPort,		/* pointer to struct of port to send to */struct sk_buff	*pMessage)	/* pointer to send-message */{	int 		i;	int			BytesSend;	int			hlength;	int			protocol;	skb_frag_t		*sk_frag;	TXD			*pTxd;	TXD			*pTxdFst;	TXD			*pTxdLst;	SK_U64		PhysAddr;	unsigned long	Flags;	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);#ifndef USE_TX_COMPLETE	FreeTxDescriptors(pAC, pTxPort);#endif	if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) {		FreeTxDescriptors(pAC, pTxPort);		if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) {			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);			SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,				SK_DBGCAT_DRV_TX_PROGRESS,				("XmitFrameSG failed - Ring full\n"));				/* this message can not be sent now */			return(-1);		}	}	pTxd = pTxPort->pTxdRingHead;	pTxdFst = pTxd;	pTxdLst = pTxd;	BytesSend = 0;	protocol = 0;	/* map first fragment (header) */	PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,			virt_to_page(pMessage->data),			((unsigned long) pMessage->data & ~PAGE_MASK),			skb_headlen(pMessage),			PCI_DMA_TODEVICE);	pTxd->VDataLow = (SK_U32)  (PhysAddr & 0xffffffff);	pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);	/* HW checksum? */	if (pMessage->ip_summed == CHECKSUM_HW) {		pTxd->TBControl = TX_CTRL_STF |				  TX_CTRL_ST_FWD |				  skb_headlen(pMessage);		/* We have to use the opcode for tcp here because the opcode for		udp is not working in the hardware yet (revision 2.0)*/		protocol = ((SK_U8)pMessage->data[23] & 0xf);		if ((protocol == 17) && (pAC->GIni.GIChipRev != 0))			pTxd->TBControl |=  BMU_UDP_CHECK;		else			pTxd->TBControl |= BMU_TCP_CHECK ;		hlength = ((SK_U8)pMessage->data[14] & 0xf) * 4;		pTxd->TcpSumOfs = 0; /* PH-Checksum already claculated */		pTxd->TcpSumSt = 14+hlength+16;		pTxd->TcpSumWr = 14+hlength;		} else {		pTxd->TBControl = TX_CTRL_CHECK_DEFAULT | 				  TX_CTRL_SOFTWARE |				  TX_CTRL_STF |				  skb_headlen(pMessage);	}	pTxd = pTxd->pNextTxd;	pTxPort->TxdRingFree--;	BytesSend += skb_headlen(pMessage);	/* Map SG fragments */	for (i = 0; i < skb_shinfo(pMessage)->nr_frags; i++) {		sk_frag = &skb_shinfo(pMessage)->frags[i];				/* we already have the proper value in entry */		PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,						 sk_frag->page,						 sk_frag->page_offset,						 sk_frag->size,						 PCI_DMA_TODEVICE);		pTxd->VDataLow = (SK_U32)  (PhysAddr & 0xffffffff);		pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);		pTxd->pMBuf = pMessage;				/* HW checksum */		if (pMessage->ip_summed == CHECKSUM_HW) {			pTxd->TBControl = TX_CTRL_OWN_BMU | 				  	  TX_CTRL_SOFTWARE |					  TX_CTRL_ST_FWD;			/* We have to use the opcode for tcp here because the opcode for			udp is not working in the hardware yet (revision 2.0)*/			if ((protocol == 17) && (pAC->GIni.GIChipRev != 0))				pTxd->TBControl |= BMU_UDP_CHECK ;			else				pTxd->TBControl |= BMU_TCP_CHECK ;		} else {			pTxd->TBControl = TX_CTRL_CHECK_DEFAULT |					  TX_CTRL_SOFTWARE |					  TX_CTRL_OWN_BMU;		}		/* Last fragment  */		if( (i+1) == skb_shinfo(pMessage)->nr_frags )  {#ifdef USE_TX_COMPLETE			pTxd->TBControl |= TX_CTRL_EOF |					   TX_CTRL_EOF_IRQ |					   sk_frag->size;#else			pTxd->TBControl |= TX_CTRL_EOF |					   sk_frag->size;#endif			pTxdFst->TBControl |= TX_CTRL_OWN_BMU |					      TX_CTRL_SOFTWARE; 		} else {			pTxd->TBControl |= sk_frag->size;		}		pTxdLst = pTxd;		pTxd = pTxd->pNextTxd;		pTxPort->TxdRingFree--;		BytesSend += sk_frag->size;	}	if ((pTxPort->pTxdRingPrev->TBControl & TX_CTRL_OWN_BMU) == 0) {		/* previous descriptor already done, so give tx start cmd */		/* StartTx(pAC, pTxPort->HwAddr); */		SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START);	}	pTxPort->pTxdRingPrev = pTxdLst;	pTxPort->pTxdRingHead = pTxd;	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);	if (pTxPort->TxdRingFree > 0)		return (BytesSend);	else		return (0);}void dump_frag( SK_U8 *data, int length){        int i;        printk("Length: %d\n", length);                        for( i=0; i < length; i++ ) {                printk(" %02x", (SK_U8)*(data + i) );                if( !((i+1) % 20) )                  printk("\n");        }        printk("\n\n");}/***************************************************************************** * * 	FreeTxDescriptors - release descriptors from the descriptor ring * * Description: *	This function releases descriptors from a transmit ring if they *	have been sent by the BMU. *	If a descriptors is sent, it can be freed and the message can *	be freed, too. *	The SOFTWARE controllable bit is used to prevent running around a *	completely free ring for ever. If this bit is no set in the *	frame (by XmitFrame), this frame has never been sent or is *	already freed. *	The Tx descriptor ring lock must be held while calling this function !!! * * Returns: *	none */static void FreeTxDescriptors(SK_AC	*pAC,		/* pointer to the adapter context */TX_PORT	*pTxPort)	/* pointer to destination port structure */{TXD	*pTxd;		/* pointer to the checked descriptor */TXD	*pNewTail;	/* pointer to 'end' of the ring */SK_U32	Control;	/* TBControl field of descriptor */SK_U64	PhysAddr;	/* address of DMA mapping */	pNewTail = pTxPort->pTxdRingTail;	pTxd = pNewTail;	/* 	 * loop forever; exits if TX_CTRL_SOFTWARE bit not set in start frame	 * or TX_CTRL_OWN_BMU bit set in any frame	 */	while (1) {		Control = pTxd->TBControl;		if ((Control & TX_CTRL_SOFTWARE) == 0) {			/* 			 * software controllable bit is set in first			 * fragment when given to BMU. Not set means that			 * this fragment was never sent or is already 			 * freed ( -> ring completely free now).			 */			pTxPort->pTxdRingTail = pTxd;			netif_start_queue(pAC->dev[pTxPort->PortIndex]);			return;		}		if (Control & TX_CTRL_OWN_BMU) {			pTxPort->pTxdRingTail = pTxd;			if (pTxPort->TxdRingFree > 0) {				netif_start_queue(pAC->dev[pTxPort->PortIndex]);			}			return;		}				/* release the DMA mapping */		PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32;		PhysAddr |= (SK_U64) pTxd->VDataLow;		pci_unmap_page(pAC->PciDev, PhysAddr,				 pTxd->pMBuf->len,				 PCI_DMA_TODEVICE);		if (Control & TX_CTRL_EOF)			DEV_KFREE_SKB_ANY(pTxd->pMBuf);	/* free message */		pTxPort->TxdRingFree++;		pTxd->TBControl &= ~TX_CTRL_SOFTWARE;		pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */	} /* while(forever) */} /* FreeTxDescriptors *//***************************************************************************** * * 	FillRxRing - fill the receive ring with valid descriptors * * Description: *	This function fills the receive ring descriptors with data *	segments and makes them valid for the BMU. *	The active ring is filled completely, if possible. *	The non-active ring is filled only partial to save memory. * * Description of rx ring structure: *	head - points to the descriptor which will be used next

⌨️ 快捷键说明

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