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

📄 skge.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
			*/			pTxPort->pTxdRingTail = pTxd;			netif_wake_queue(pAC->dev[pTxPort->PortIndex]);			return;		}		if (Control & BMU_OWN) {			pTxPort->pTxdRingTail = pTxd;			if (pTxPort->TxdRingFree > 0) {				netif_wake_queue(pAC->dev[pTxPort->PortIndex]);			}			return;		}				/* 		** release the DMA mapping, because until not unmapped		** this buffer is considered being under control of the		** adapter card!		*/		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 & BMU_EOF)			DEV_KFREE_SKB_ANY(pTxd->pMBuf);	/* free message */		pTxPort->TxdRingFree++;		pTxd->TBControl &= ~BMU_SW;		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 = BMU_OWN       | 			  BMU_STF       | 			  BMU_IRQ_EOF   | 			  BMU_TCP_CHECK | 			  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 = BMU_OWN       | 			  BMU_STF       |			  BMU_IRQ_EOF   | 			  BMU_TCP_CHECK | 			  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 */	SK_BOOL		SlowPathLock)	/* indicates if SlowPathLock is needed */{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 */	unsigned long	Flags;			/* for spin lock */int				PortIndex = pRxPort->PortIndex;unsigned int	Offset;unsigned int	NumBytes;unsigned int	ForRlmt;SK_BOOL			IsBc;SK_BOOL			IsMc;SK_BOOL  IsBadFrame; 			/* Bad frame */SK_U32			FrameStat;SK_U64			PhysAddr;rx_start:		/* do forever; exit if BMU_OWN 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 & BMU_OWN) != 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;		}                pAC->DynIrqModInfo.NbrProcessedDescr++;		/* get length of frame and check it */		FrameLength = Control & BMU_BBC;		if (FrameLength > pAC->RxBufSize) {			goto rx_failed;		}		/* check for STF and EOF */		if ((Control & (BMU_STF | BMU_EOF)) != (BMU_STF | BMU_EOF)) {			goto rx_failed;		}		/* here we have a complete frame in the ring */		pMsg = pRxd->pMBuf;		FrameStat = pRxd->FrameStat;		/* check for frame length mismatch */#define XMR_FS_LEN_SHIFT        18#define GMR_FS_LEN_SHIFT        16		if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {			if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) {				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,					SK_DBGCAT_DRV_RX_PROGRESS,					("skge: Frame length mismatch (%u/%u).\n",					FrameLength,					(SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));				goto rx_failed;			}		}		else {			if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) {				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,					SK_DBGCAT_DRV_RX_PROGRESS,					("skge: Frame length mismatch (%u/%u).\n",					FrameLength,					(SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));				goto rx_failed;			}		}		/* Set Rx Status */		if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {			IsBc = (FrameStat & XMR_FS_BC) != 0;			IsMc = (FrameStat & XMR_FS_MC) != 0;			IsBadFrame = (FrameStat &				(XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0;		} else {			IsBc = (FrameStat & GMR_FS_BC) != 0;			IsMc = (FrameStat & GMR_FS_MC) != 0;			IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) ||							((FrameStat & GMR_FS_RX_OK) == 0));		}		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 & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) {#if 0			(FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) {#endif			/* 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));			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			 */			/* use new skb and copy data */			skb_reserve(pNewMsg, 2);			skb_put(pNewMsg, FrameLength);			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;			PhysAddr |= (SK_U64) pRxd->VDataLow;			pci_dma_sync_single_for_cpu(pAC->PciDev,						    (dma_addr_t) PhysAddr,						    FrameLength,						    PCI_DMA_FROMDEVICE);			memcpy(pNewMsg->data, pMsg, FrameLength);			pci_dma_sync_single_for_device(pAC->PciDev,						       (dma_addr_t) PhysAddr,						       FrameLength,						       PCI_DMA_FROMDEVICE);			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_single(pAC->PciDev,					 PhysAddr,					 pAC->RxBufSize - 2,					 PCI_DMA_FROMDEVICE);			/* set length in message */			skb_put(pMsg, FrameLength);		} /* frame > SK_COPY_TRESHOLD */#ifdef USE_SK_RX_CHECKSUM		pMsg->csum = pRxd->TcpSums & 0xffff;		pMsg->ip_summed = CHECKSUM_HW;#else		pMsg->ip_summed = CHECKSUM_NONE;#endif		SK_DBG_MSG(NULL, SK_DBGMOD_DRV,	1,("V"));		ForRlmt = SK_RLMT_RX_PROTOCOL;#if 0		IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC;#endif		SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength,			IsBc, &Offset, &NumBytes);		if (NumBytes != 0) {#if 0			IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC;#endif			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);				/* SlowPathLock needed? */				if (SlowPathLock == SK_TRUE) {					spin_lock_irqsave(&pAC->SlowPathLock, Flags);					SkEventQueue(pAC, SKGE_RLMT,						SK_RLMT_PACKET_RECEIVED,						EvPara);					pAC->CheckQueue = SK_TRUE;					spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);				} else {					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 &				(IFF_PROMISC | IFF_ALLMULTI)) != 0 ||				(ForRlmt & SK_RLMT_RX_PROTOCOL) ==				SK_RLMT_RX_PROTOCOL) {				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 {				DEV_KFREE_SKB(pMsg);			}		} /* if packet for rlmt */	} /* for ..

⌨️ 快捷键说明

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