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

📄 skge.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	pRxPort->RxdRingFree--;	Length = pAC->RxBufSize;	PhysAddr = (SK_U64) pci_map_single(&pAC->PciDev,					   pMsgBlock->data,					   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 */	while (pRxPort->RxdRingFree < pAC->RxDescrPerRing) {		pRxd = pRxPort->pRxdRingHead;				Control = pRxd->RBControl;				/* check if this descriptor is ready */		if ((Control & RX_CTRL_OWN_BMU) != 0) {			/* this descriptor is not yet ready */			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;				/*		 * if short frame then copy data to reduce memory waste		 */		pNewMsg = NULL;		if (FrameLength < SK_COPY_THRESHOLD) {			pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC);			if (pNewMsg != NULL) {				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;			}		}		/*		 * if large frame, or SKB allocation failed, pass		 * the SKB directly to the networking		 */		if (pNewMsg == NULL) {			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);			/* 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);					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 */				FrameStat = pRxd->FrameStat;                if ((FrameStat & XMR_FS_LNG_ERR) != 0) {                        /* jumbo frame, count to correct statistic */                        SK_PNMI_CNT_RX_LONGFRAMES(pAC, pRxPort->PortIndex);                }		pRxd = pRxd->pNextRxd;		pRxPort->pRxdRingHead = pRxd;		pRxPort->RxdRingFree ++;		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,			("Received frame of length %d on port %d\n",			FrameLength, PortIndex));		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,			("Number of free rx descriptors: %d\n",			pRxPort->RxdRingFree));				if ((Control & RX_CTRL_STAT_VALID) == RX_CTRL_STAT_VALID &&			(FrameStat & XMR_FS_ANY_ERR) == 0) {			// was the following, changed to allow VLAN support			// (XMR_FS_ANY_ERR | XMR_FS_1L_VLAN | XMR_FS_2L_VLAN)			SK_DBG_MSG(NULL, SK_DBGMOD_DRV,				SK_DBGCAT_DRV_RX_PROGRESS,("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) {				/* send up only frames from active port */			    	if (PortIndex == pAC->ActivePort) {					/* frame for upper layer */					SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 						SK_DBGCAT_DRV_RX_PROGRESS,						("U"));#ifdef DUMP_RX					DumpMsg(pMsg, "Rx");#endif					pMsg->dev = pAC->dev;					pMsg->protocol = eth_type_trans(pMsg,						pAC->dev);					SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,						FrameLength);					netif_rx(pMsg);					pAC->dev->last_rx = jiffies;				}				else {					/* drop frame */					SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 						SK_DBGCAT_DRV_RX_PROGRESS,						("D"));					DEV_KFREE_SKB_IRQ(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->flags & 					(IFF_PROMISC | IFF_ALLMULTI)) != 0 ||					(ForRlmt & SK_RLMT_RX_PROTOCOL) == 					SK_RLMT_RX_PROTOCOL) { 					pMsg->dev = pAC->dev;					pMsg->protocol = eth_type_trans(pMsg,						pAC->dev);					netif_rx(pMsg);					pAC->dev->last_rx = jiffies;				}				else {					DEV_KFREE_SKB_IRQ(pMsg);				}			} /* if packet for rlmt */		} /* if valid frame */		else {			/* there is a receive error in this frame */			if ((FrameStat & XMR_FS_1L_VLAN) != 0) {				printk("%s: Received frame"					" with VLAN Level 1 header, check"					" switch configuration\n",					pAC->dev->name);			}			if ((FrameStat & XMR_FS_2L_VLAN) != 0) {				printk("%s: Received frame"					" with VLAN Level 2 header, check"					" switch configuration\n",					pAC->dev->name);			}			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));			DEV_KFREE_SKB_IRQ(pMsg);		}	} /* while */	FillRxRing(pAC, pRxPort);	/* do not start if called from Close */	if (pAC->BoardLevel > 0) {		ClearAndStartRx(pAC, PortIndex);	}	return;rx_failed:	/* remove error frame */	SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,		("Schrottdescriptor, length: 0x%x\n", FrameLength));	/* release the DMA mapping */	PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;	PhysAddr |= (SK_U64) pRxd->VDataLow;	pci_unmap_single(&pAC->PciDev,			 PhysAddr,			 pAC->RxBufSize - 2,			 PCI_DMA_FROMDEVICE);	DEV_KFREE_SKB_IRQ(pRxd->pMBuf);	pRxd->pMBuf = NULL;	pRxPort->RxdRingFree++;	pRxPort->pRxdRingHead = pRxd->pNextRxd;	goto rx_start;} /* ReceiveIrq *//***************************************************************************** * * 	ClearAndStartRx - give a start receive command to BMU, clear IRQ * * Description: *	This function sends a start command and a clear interrupt *	command for one receive queue to the BMU. * * Returns: N/A *	none */static void ClearAndStartRx(SK_AC	*pAC,		/* pointer to the adapter context */int	PortIndex)	/* index of the receive port (XMAC) */{	SK_OUT8(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_CTRL,		RX_Q_CTRL_START | RX_Q_CTRL_CLR_I_EOF);} /* ClearAndStartRx *//***************************************************************************** * * 	ClearTxIrq - give a clear transmit IRQ command to BMU * * Description: *	This function sends a clear tx IRQ command for one *	transmit queue to the BMU. * * Returns: N/A */static void ClearTxIrq(SK_AC	*pAC,		/* pointer to the adapter context */int	PortIndex,	/* index of the transmit port (XMAC) */int	Prio)		/* priority or normal queue */{	SK_OUT8(pAC->IoBase, TxQueueAddr[PortIndex][Prio]+TX_Q_CTRL,		TX_Q_CTRL_CLR_I_EOF);} /* ClearTxIrq *//***************************************************************************** * * 	ClearRxRing - remove all buffers from the receive ring * * Description: *	This function removes all receive buffers from the ring. *	The receive BMU must be stopped before calling this function. * * Returns: N/A */static void ClearRxRing(SK_AC	*pAC,		/* pointer to adapter context */RX_PORT	*pRxPort)	/* pointer to rx port struct */{RXD		*pRxd;	/* pointer to the current descriptor */unsigned int	Flags; SK_U64		PhysAddr;	if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) {		return;	}	spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);	pRxd = pRxPort->pRxdRingHead;	do {		if (pRxd->pMBuf != NULL) {			PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;			PhysAddr |= (SK_U64) pRxd->VDataLow;			pci_unmap_single(&pAC->PciDev,					 PhysAddr,					 pAC->RxBufSize - 2,					 PCI_DMA_FROMDEVICE);			DEV_KFREE_SKB(pRxd->pMBuf);			pRxd->pMBuf = NULL;		}		pRxd->RBControl &= RX_CTRL_OWN_BMU;		pRxd = pRxd->pNextRxd;		pRxPort->RxdRingFree++;	} while (pRxd != pRxPort->pRxdRingTail);	pRxPort->pRxdRingTail = pRxPort->pRxdRingHead;	spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);} /* ClearRxRing *//***************************************************************************** * *	ClearTxRing - remove all buffers from the transmit ring * * Description: *	This function removes all transmit buffers from the ring. *	The transmit BMU must be stopped before calling this function *	and transmitting at the upper level must be disabled. *	The BMU own bit of all descriptors is cleared, the rest is *	done by calling FreeTxDescriptors. * * Returns: N/A */static void ClearTxRing(SK_AC	*pAC,		/* pointer to adapter context */TX_PORT	*pTxPort)	/* pointer to tx prt struct */{TXD		*pTxd;		/* pointer to the current descriptor */int		i;unsigned int	Flags;	spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);	pTxd = pTxPort->pTxdRingHead;	for (i=0; i<pAC->TxDescrPerRing; i++) {		pTxd->TBControl &= ~TX_CTRL_OWN_BMU;		pTxd = pTxd->pNextTxd;	}	FreeTxDescriptors(pAC, pTxPort);	spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);} /* ClearTxRing *//***************************************************************************** * * 	SetQueueSizes - configure the sizes of rx and tx queues * * Description: *	This function assigns the sizes for active and passive port *	to the appropriate HWinit structure variables. *	The passive port(s) get standard values, all remaining RAM *	is giv

⌨️ 快捷键说明

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