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

📄 skge.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* StartTx(pAC, pTxPort->HwAddr); */		SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START);	}	pTxPort->pTxdRingPrev = pTxd;			BytesSend = pMessage->len;	/* after releasing the lock, the skb may be immidiately freed */	if (pTxPort->TxdRingFree != 0) {		spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);		return (BytesSend);	}	else {		/* ring full: set tbusy on return */		spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);		return (0);	}} /* XmitFrame *//***************************************************************************** * * 	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);		/* free message */		DEV_KFREE_SKB_ANY(pTxd->pMBuf);		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 by the BMU *	tail - points to the next descriptor to give to the BMU *	 * Returns:	N/A */static void FillRxRing(SK_AC		*pAC,		/* pointer to the adapter context */RX_PORT		*pRxPort)	/* ptr to port struct for which the ring				   should be filled */{unsigned long	Flags;	spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);	while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) {		if(!FillRxDescriptor(pAC, pRxPort))			break;	}	spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);} /* FillRxRing *//***************************************************************************** * * 	FillRxDescriptor - fill one buffer into the receive ring * * Description: *	The function allocates a new receive buffer and *	puts it into the next descriptor. * * Returns: *	SK_TRUE - a buffer was added to the ring *	SK_FALSE - a buffer could not be added */static SK_BOOL FillRxDescriptor(SK_AC		*pAC,		/* pointer to the adapter context struct */RX_PORT		*pRxPort)	/* ptr to port struct of ring to fill */{struct sk_buff	*pMsgBlock;	/* pointer to a new message block */RXD		*pRxd;		/* the rxd to fill */SK_U16		Length;		/* data fragment length */SK_U64		PhysAddr;	/* physical address of a rx buffer */	pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC);	if (pMsgBlock == NULL) {		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,			SK_DBGCAT_DRV_ENTRY,			("%s: Allocation of rx buffer failed !\n",			pAC->dev[pRxPort->PortIndex]->name));		SK_PNMI_CNT_NO_RX_BUF(pAC, pRxPort->PortIndex);		return(SK_FALSE);	}	skb_reserve(pMsgBlock, 2); /* to align IP frames */	/* skb allocated ok, so add buffer */	pRxd = pRxPort->pRxdRingTail;	pRxPort->pRxdRingTail = pRxd->pNextRxd;	pRxPort->RxdRingFree--;	Length = pAC->RxBufSize;	PhysAddr = (SK_U64) pci_map_page(&pAC->PciDev,					 virt_to_page(pMsgBlock->data),					 ((unsigned long) pMsgBlock->data &					  ~PAGE_MASK),					 pAC->RxBufSize - 2,					 PCI_DMA_FROMDEVICE);	pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);	pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32);	pRxd->pMBuf = pMsgBlock;	pRxd->RBControl = RX_CTRL_OWN_BMU | RX_CTRL_STF |		RX_CTRL_EOF_IRQ | RX_CTRL_CHECK_CSUM | Length;	return (SK_TRUE);} /* FillRxDescriptor *//***************************************************************************** * * 	ReQueueRxBuffer - fill one buffer back into the receive ring * * Description: *	Fill a given buffer back into the rx ring. The buffer *	has been previously allocated and aligned, and its phys. *	address calculated, so this is no more necessary. * * Returns: N/A */static void ReQueueRxBuffer(SK_AC		*pAC,		/* pointer to the adapter context struct */RX_PORT		*pRxPort,	/* ptr to port struct of ring to fill */struct sk_buff	*pMsg,		/* pointer to the buffer */SK_U32		PhysHigh,	/* phys address high dword */SK_U32		PhysLow)	/* phys address low dword */{RXD		*pRxd;		/* the rxd to fill */SK_U16		Length;		/* data fragment length */	pRxd = pRxPort->pRxdRingTail;	pRxPort->pRxdRingTail = pRxd->pNextRxd;	pRxPort->RxdRingFree--;	Length = pAC->RxBufSize;	pRxd->VDataLow = PhysLow;	pRxd->VDataHigh = PhysHigh;	pRxd->pMBuf = pMsg;	pRxd->RBControl = RX_CTRL_OWN_BMU | RX_CTRL_STF |		RX_CTRL_EOF_IRQ | RX_CTRL_CHECK_CSUM | Length;	return;} /* ReQueueRxBuffer *//***************************************************************************** * * 	ReceiveIrq - handle a receive IRQ * * Description: *	This function is called when a receive IRQ is set. *	It walks the receive descriptor ring and sends up all *	frames that are complete. * * Returns:	N/A */static void ReceiveIrq(SK_AC		*pAC,		/* pointer to adapter context */RX_PORT		*pRxPort)	/* pointer to receive port struct */{RXD		*pRxd;		/* pointer to receive descriptors */SK_U32		Control;	/* control field of descriptor */struct sk_buff	*pMsg;		/* pointer to message holding frame */struct sk_buff	*pNewMsg;	/* pointer to a new message for copying frame */int		FrameLength;	/* total length of received frame */SK_MBUF		*pRlmtMbuf;	/* ptr to a buffer for giving a frame to rlmt */SK_EVPARA	EvPara;		/* an event parameter union */	int		PortIndex = pRxPort->PortIndex;unsigned int	Offset;unsigned int	NumBytes;unsigned int	ForRlmt;SK_BOOL		IsBc;SK_BOOL		IsMc;SK_U32		FrameStat;unsigned short	Csum1;unsigned short	Csum2;unsigned short	Type;int		Result;SK_U64		PhysAddr;rx_start:		/* do forever; exit if RX_CTRL_OWN_BMU found */	for ( pRxd = pRxPort->pRxdRingHead ;		  pRxPort->RxdRingFree < pAC->RxDescrPerRing ;		  pRxd = pRxd->pNextRxd,		  pRxPort->pRxdRingHead = pRxd,		  pRxPort->RxdRingFree ++) {		/*		 * For a better understanding of this loop 		 * Go through every descriptor beginning at the head 		 * Please note: the ring might be completely received so the OWN bit		 * set is not a good crirteria to leave that loop.		 * Therefore the RingFree counter is used.		 * On entry of this loop pRxd is a pointer to the Rxd that needs		 * to be checked next.		 */		Control = pRxd->RBControl;			/* check if this descriptor is ready */		if ((Control & RX_CTRL_OWN_BMU) != 0) {			/* this descriptor is not yet ready */			/* This is the usual end of the loop */			/* We don't need to start the ring again */			FillRxRing(pAC, pRxPort);			return;		}		/* get length of frame and check it */		FrameLength = Control & RX_CTRL_LEN_MASK;		if (FrameLength > pAC->RxBufSize) {			goto rx_failed;		}		/* check for STF and EOF */		if ((Control & (RX_CTRL_STF | RX_CTRL_EOF)) !=			(RX_CTRL_STF | RX_CTRL_EOF)) {			goto rx_failed;		}				/* here we have a complete frame in the ring */		pMsg = pRxd->pMBuf;		FrameStat = pRxd->FrameStat;		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,			("Received frame of length %d on port %d\n",			FrameLength, PortIndex));		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,			("Number of free rx descriptors: %d\n",			pRxPort->RxdRingFree));		/*DumpMsg(pMsg, "Rx");	*/					if ((Control & RX_CTRL_STAT_VALID) != RX_CTRL_STAT_VALID ||			(FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) {			/* there is a receive error in this frame */			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,				SK_DBGCAT_DRV_RX_PROGRESS,				("skge: Error in received frame, dropped!\n"				"Control: %x\nRxStat: %x\n",				Control, FrameStat));			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;			PhysAddr |= (SK_U64) pRxd->VDataLow;			pci_dma_sync_single(&pAC->PciDev,					    (dma_addr_t) PhysAddr,					    FrameLength,					    PCI_DMA_FROMDEVICE);			ReQueueRxBuffer(pAC, pRxPort, pMsg,				pRxd->VDataHigh, pRxd->VDataLow);			continue;		}		/*		 * if short frame then copy data to reduce memory waste		 */		if ((FrameLength < SK_COPY_THRESHOLD) &&			((pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC)) != NULL)) {			/*			 * Short frame detected and allocation successfull			 */			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;			PhysAddr |= (SK_U64) pRxd->VDataLow;			/* use new skb and copy data */			skb_reserve(pNewMsg, 2);			skb_put(pNewMsg, FrameLength);			pci_dma_sync_single(&pAC->PciDev,					    (dma_addr_t) PhysAddr,					    FrameLength,					    PCI_DMA_FROMDEVICE);			eth_copy_and_sum(pNewMsg, pMsg->data,				FrameLength, 0);			ReQueueRxBuffer(pAC, pRxPort, pMsg,				pRxd->VDataHigh, pRxd->VDataLow);			pMsg = pNewMsg;		}		else {			/*			 * if large frame, or SKB allocation failed, pass			 * the SKB directly to the networking			 */			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;			PhysAddr |= (SK_U64) pRxd->VDataLow;			/* release the DMA mapping */			pci_unmap_page(&pAC->PciDev,				       PhysAddr,				       pAC->RxBufSize - 2,				       PCI_DMA_FROMDEVICE);			/* set length in message */			skb_put(pMsg, FrameLength);			/* hardware checksum */			Type = ntohs(*((short*)&pMsg->data[12]));			if (Type == 0x800) {				Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff);				Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff);				if ((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) {					Result = SkCsGetReceiveInfo(pAC,						&pMsg->data[14], 						Csum1, Csum2, pRxPort->PortIndex);					if (Result == 						SKCS_STATUS_IP_FRAGMENT ||						Result ==						SKCS_STATUS_IP_CSUM_OK ||						Result ==						SKCS_STATUS_TCP_CSUM_OK ||						Result ==						SKCS_STATUS_UDP_CSUM_OK) {						pMsg->ip_summed =						CHECKSUM_UNNECESSARY;					}				} /* checksum calculation valid */			} /* IP frame */		} /* frame > SK_COPY_TRESHOLD */				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,	1,("V"));		ForRlmt = SK_RLMT_RX_PROTOCOL;		IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC;		SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength,			IsBc, &Offset, &NumBytes);		if (NumBytes != 0) {			IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC;			SK_RLMT_LOOKAHEAD(pAC, PortIndex, 				&pMsg->data[Offset],				IsBc, IsMc, &ForRlmt);		}		if (ForRlmt == SK_RLMT_RX_PROTOCOL) {					SK_DBG_MSG(NULL, SK_DBGMOD_DRV,	1,("W"));			/* send up only frames from active port */			if ((PortIndex == pAC->ActivePort) ||				(pAC->RlmtNets == 2)) {				/* frame for upper layer */				SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U"));#ifdef xDEBUG				DumpMsg(pMsg, "Rx");#endif				SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,					FrameLength, pRxPort->PortIndex);				pMsg->dev = pAC->dev[pRxPort->PortIndex];				pMsg->protocol = eth_type_trans(pMsg,					pAC->dev[pRxPort->PortIndex]);				netif_rx(pMsg);				pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;			}			else {				/* drop frame */				SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 					SK_DBGCAT_DRV_RX_PROGRESS,					("D"));				DEV_KFREE_SKB(pMsg);			}					} /* if not for rlmt */		else {			/* packet for rlmt */			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 				SK_DBGCAT_DRV_RX_PROGRESS, ("R"));			pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC,				pAC->IoBase, FrameLength);			if (pRlmtMbuf != NULL) {				pRlmtMbuf->pNext = NULL;				pRlmtMbuf->Length = FrameLength;				pRlmtMbuf->PortIdx = PortIndex;				EvPara.pParaPtr = pRlmtMbuf;				memcpy((char*)(pRlmtMbuf->pData),					   (char*)(pMsg->data),					   FrameLength);				SkEventQueue(pAC, SKGE_RLMT,					SK_RLMT_PACKET_RECEIVED,					EvPara);				pAC->CheckQueue = SK_TRUE;				SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 					SK_DBGCAT_DRV_RX_PROGRESS,					("Q"));			}			if ((pAC->dev[pRxPort->PortIndex]->flags & 		

⌨️ 快捷键说明

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