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

📄 sky2.c

📁 这是Marvell Technology Group Ltd. 4355 (rev 12)网卡在linux下的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				SK_OUT32(IoC, 					Y2_PREF_Q_ADDR(Q_R2, PREF_UNIT_PUT_IDX_REG), 					GET_PUT_IDX(pLETab)); 			}			/* Update put index */			UPDATE_HWPUT_IDX(pLETab);		}	}	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,		("<== GiveRxBufferToHw()\n"));}       /* GiveRxBufferToHw *//*********************************************************************** * *	FillReceiveTableYukon2 - map any waiting RX buffers to HW * * Description: *	If the list element table contains more empty elements than  *	specified this function tries to refill them. * * Notes: *       This function can run only once per port in a system at one time. * * Returns: N/A */void FillReceiveTableYukon2(SK_AC   *pAC,   /* pointer to adapter control context */SK_IOC   IoC,   /* I/O control context                */int      Port)  /* port index of RX                   */{	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,		("==> FillReceiveTableYukon2 (Port %c)\n", 'A' + Port));	if (NUM_FREE_LE_IN_TABLE(&pAC->RxPort[Port].RxLET) >		pAC->MaxUnusedRxLeWorking) {		/* 		** Give alle waiting receive buffers down 		** The queue holds all RX packets that		** need a fresh allocation of the sk_buff.		*/		if (pAC->RxPort[Port].RxQ_waiting.pHead != NULL) {			SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,			("Waiting queue is not empty -> give it to HW"));			GiveRxBufferToHw(pAC, IoC, Port, NULL);		}	}	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,		("<== FillReceiveTableYukon2 ()\n"));}	/* FillReceiveTableYukon2 *//****************************************************************************** * * *	HandleReceives - will pass any ready RX packet to kernel * * Description: *	This functions handles a received packet. It checks wether it is *	valid, updates the receive list element table and gives the receive *	buffer to Linux * * Notes: *	This function can run only once per port at one time in the system. * * Returns: N/A */static SK_BOOL HandleReceives(SK_AC  *pAC,          /* adapter control context                     */int     Port,         /* port on which a packet has been received    */SK_U16  FrameLength,  /* number of bytes which was actually received */SK_U32  FrameStatus,  /* MAC frame status word                       */SK_U16  Tcp1,         /* first hw checksum                           */SK_U16  Tcp2,         /* second hw checksum                          */SK_U32  Tist,         /* timestamp                                   */SK_U16  Vlan          /* Vlan Id                                     */#ifdef SK_EXTREME, SK_U32  ExtremeCsumResult#endif){	SK_PACKET       *pSkPacket;	SK_LE_TABLE     *pLETab;	SK_MBUF         *pRlmtMbuf;  /* buffer for giving RLMT frame */	struct sk_buff  *pMsg;       /* ptr to message holding frame */#ifdef __ia64__	struct sk_buff  *pNewMsg;    /* used when IP aligning        */#endif	SK_BOOL         IsGoodPkt;	SK_BOOL         IsBc;	SK_BOOL         IsMc;	SK_EVPARA       EvPara;      /* an event parameter union     */	SK_I16          LenToFree;   /* must be signed integer       */	unsigned long   Flags;       /* for spin lock                */	unsigned int    RlmtNotifier;	unsigned short  Type;	int             IpFrameLength;	int             HeaderLength;	int             NumBytes; 	int             Result;	int             Offset = 0;	SK_U16          HighVal;	SK_BOOL         CheckBcMc = SK_FALSE;#ifdef Y2_SYNC_CHECK	SK_U16		MyTcp;#endif#ifdef USE_ASF_DASH_FW	static SK_U8    CntNetWUPP = 0; /* Count Network Stack Wake Up Packet Passes */	SK_U8           ret8;#endif	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,		("==> HandleReceives (Port %c)\n", 'A' + Port));	if (HW_FEATURE(pAC, HWF_WA_DEV_521)) {		HighVal = (SK_U16)(((FrameStatus) & GMR_FS_LEN_MSK) >> GMR_FS_LEN_SHIFT);		if ((HighVal > ETH_MAX_LEN) || (FrameStatus == 0x7ffc0001)) {			FrameStatus = 0;		}		else if (HighVal != FrameLength) {				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,					("521: We take pkt len %x stat: %x\n", FrameLength, FrameStatus));				/*				** Try to recover the status word. The multicast and broadcast bits				** from status word are set when we have a valid packet header.				*/				FrameStatus = 0;				/* Set the ReceiveOK bit. */				FrameStatus |= GMR_FS_RX_OK;				/* Set now the length into the status word */				FrameStatus |= (FrameLength << GMR_FS_LEN_SHIFT);				/* Insure that bit 31 is reset */				FrameStatus &= ~GMR_FS_LKUP_BIT2;				CheckBcMc = SK_TRUE;		}	}	/* 	** Check whether we want to receive this packet 	*/	SK_Y2_RXSTAT_CHECK_PKT(FrameLength, FrameStatus, IsGoodPkt);	/*	** Take first receive buffer out of working queue 	*/	POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket);	if (pSkPacket == NULL) { 		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 			SK_DBGCAT_DRV_ERROR,			("Packet not available. NULL pointer.\n"));		return(SK_TRUE);	}	if (HW_FEATURE(pAC, HWF_WA_DEV_420)) {		NbrRxBuffersInHW--;	}	/* 	** Verify the received length of the frame! Note that having 	** multiple RxBuffers being aware of one single receive packet	** (one packet spread over multiple RxBuffers) is not supported 	** by this driver!	*/	if ((FrameLength > pAC->RxPort[Port].RxBufSize) || 		(FrameLength > (SK_U16) pSkPacket->PacketLen)) {		IsGoodPkt = SK_FALSE;	}	/* 	** Initialize vars for selected port 	*/	pLETab = &pAC->RxPort[Port].RxLET;	/* 	** Reset own bit in LE's between old and new Done index	** This is not really necessary but makes debugging easier 	*/	CLEAR_LE_OWN_FROM_DONE_TO(pLETab, pSkPacket->NextLE);	/* 	** Free the list elements for new Rx buffers 	*/	SET_DONE_INDEX(pLETab, pSkPacket->NextLE);	pMsg = pSkPacket->pMBuf;	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,		("Received frame of length %d on port %d\n",FrameLength, Port));	if (!IsGoodPkt) {		/* 		** release the DMA mapping 		*/#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) 		pci_dma_sync_single(pAC->PciDev,				(dma_addr_t) pSkPacket->pFrag->pPhys,				pSkPacket->pFrag->FragLen,				PCI_DMA_FROMDEVICE);#else		pci_dma_sync_single_for_cpu(pAC->PciDev,				(dma_addr_t) pSkPacket->pFrag->pPhys,				pSkPacket->pFrag->FragLen,				PCI_DMA_FROMDEVICE);#endif		DEV_KFREE_SKB_ANY(pSkPacket->pMBuf);		PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket);		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,			("<== HandleReceives (Port %c)\n", 'A' + Port));		/*		** Sanity check for RxBuffer overruns...		*/		LenToFree = FrameLength - (pSkPacket->pFrag->FragLen);		while (LenToFree > 0) {			POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket);			if (HW_FEATURE(pAC, HWF_WA_DEV_420)) {				NbrRxBuffersInHW--;			}			CLEAR_LE_OWN_FROM_DONE_TO(pLETab, pSkPacket->NextLE);			SET_DONE_INDEX(pLETab, pSkPacket->NextLE);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)			pci_dma_sync_single(pAC->PciDev,					(dma_addr_t) pSkPacket->pFrag->pPhys,					pSkPacket->pFrag->FragLen,					PCI_DMA_FROMDEVICE);#else			pci_dma_sync_single_for_device(pAC->PciDev,					(dma_addr_t) pSkPacket->pFrag->pPhys,					pSkPacket->pFrag->FragLen,					PCI_DMA_FROMDEVICE); #endif			DEV_KFREE_SKB_ANY(pSkPacket->pMBuf);			PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket);			LenToFree = LenToFree - ((SK_I16)(pSkPacket->pFrag->FragLen));						SK_DBG_MSG(pAC, SK_DBGMOD_DRV,				SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR,				("<==HandleReceives (Port %c) drop faulty len pkt(2)\n",'A'+Port));		}		return(SK_TRUE);	} else {		/* 		** Release the DMA mapping 		*/		pci_unmap_single(pAC->PciDev,				 pSkPacket->pFrag->pPhys,				 pAC->RxPort[Port].RxBufSize,				 PCI_DMA_FROMDEVICE);		skb_put(pMsg, FrameLength);		/* set message len */		pMsg->ip_summed = CHECKSUM_NONE;	/* initial default */#ifdef Y2_SYNC_CHECK		pAC->FramesWithoutSyncCheck++;		if (pAC->FramesWithoutSyncCheck > Y2_RESYNC_WATERMARK) {			if ((Tcp1 != 1) || (Tcp2 != 0)) {				pAC->FramesWithoutSyncCheck = 0;				MyTcp = (SK_U16) SkCsCalculateChecksum(						&pMsg->data[14],						FrameLength - 14);				if (MyTcp != Tcp1) {					/* Queue port reset event */					SkLocalEventQueue(pAC, SKGE_DRV,					SK_DRV_RECOVER,Port,-1,SK_FALSE);				}			}		}#endif		if (pAC->RxPort[Port].UseRxCsum) {#ifdef SK_EXTREME			if (HW_IS_EXT_LE_FORMAT(pAC)) {				/* Checksum calculation for Yukon Extreme */				if (CSS_IS_IPV4(ExtremeCsumResult) && CSS_IPV4_CSUM_OK(ExtremeCsumResult)) {        				pMsg->ip_summed = CHECKSUM_UNNECESSARY;				} else {        				pMsg->ip_summed = CHECKSUM_NONE;				}			} else {#endif				Type = ntohs(*((short*)&pMsg->data[12]));				if (Type == 0x800) {					*((char *)&(IpFrameLength)) = pMsg->data[16];					*(((char *)&(IpFrameLength))+1) = pMsg->data[17];					IpFrameLength = ntohs(IpFrameLength);					HeaderLength  = FrameLength - IpFrameLength;					if (HeaderLength == 0xe) {						Result = 						    SkCsGetReceiveInfo(pAC,&pMsg->data[14],Tcp1,Tcp2, Port, IpFrameLength);						if ((Result == SKCS_STATUS_IP_FRAGMENT) ||						    (Result == SKCS_STATUS_IP_CSUM_OK)  ||						    (Result == SKCS_STATUS_TCP_CSUM_OK) ||						    (Result == SKCS_STATUS_UDP_CSUM_OK)) {#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)							pMsg->ip_summed = CHECKSUM_COMPLETE;							pMsg->csum = Tcp1 & 0xffff;#else							pMsg->ip_summed = CHECKSUM_UNNECESSARY;#endif						} else if ((Result == SKCS_STATUS_TCP_CSUM_ERROR)    ||						           (Result == SKCS_STATUS_UDP_CSUM_ERROR)    ||						           (Result == SKCS_STATUS_IP_CSUM_ERROR_UDP) ||						           (Result == SKCS_STATUS_IP_CSUM_ERROR_TCP) ||						           (Result == SKCS_STATUS_IP_CSUM_ERROR)) {							SK_DBG_MSG(NULL, SK_DBGMOD_DRV,								SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR,								("skge: CRC error. Frame dropped!\n"));							DEV_KFREE_SKB_ANY(pMsg);							PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket);							SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_RX_PROGRESS,								("<==HandleReceives(Port %c)\n",'A'+Port));							return(SK_TRUE);						} else {							pMsg->ip_summed = CHECKSUM_NONE;						}					} /* end if (HeaderLength == valid) */				} /* end if (Type == 0x800) -> IP frame */#ifdef SK_EXTREME			} /* if (HW_IS_EXT_LE_FORMAT(pAC)) */#endif		} /* end if (pRxPort->UseRxCsum) */				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,			SK_DBGCAT_DRV_RX_PROGRESS,("V"));		RlmtNotifier = SK_RLMT_RX_PROTOCOL;		if (CheckBcMc == SK_TRUE) {			/* Check if this is a broadcast packet */			if (SK_ADDR_EQUAL(pMsg->data, "\xFF\xFF\xFF\xFF\xFF\xFF")) {				/* Broadcast packet */				FrameStatus |= GMR_FS_BC;			}			else if (pMsg->data[0] & 0x01) {				/* Multicast packet */				FrameStatus |= GMR_FS_MC;			}		}		IsBc = (FrameStatus & GMR_FS_BC) ? SK_TRUE : SK_FALSE;		SK_RLMT_PRE_LOOKAHEAD(pAC,Port,FrameLength,					IsBc,&Offset,&NumBytes);		if (NumBytes != 0) {			IsMc = (FrameStatus & GMR_FS_MC) ? SK_TRUE : SK_FALSE;			SK_RLMT_LOOKAHEAD(pAC,Port,&pMsg->data[Offset],						IsBc,IsMc,&RlmtNotifier);		}		if (RlmtNotifier == SK_RLMT_RX_PROTOCOL) {			SK_DBG_MSG(NULL,SK_DBGMOD_DRV,				SK_DBGCAT_DRV_RX_PROGRESS,("W"));			if ((Port == pAC->ActivePort)||(pAC->RlmtNets == 2)) {				/* send up only frames from active port */				SK_DBG_MSG(NULL, SK_DBGMOD_DRV,					SK_DBGCAT_DRV_RX_PROGRESS,("U"));#ifdef SK_ASF#ifdef USE_ASF_DASH_FW				pAC->ReceivedPacket = SK_TRUE;				if ( (pAC->SendWolPattern == SK_TRUE) && (pAC->MaxPorts > 0) )				{					CntNetWUPP++;					if (CntNetWUPP > 5) {						printk("sk98lin: Wakeup packet could not be passed to protocol stack (more than 5 retries)\n");						pAC->SendWolPattern = SK_FALSE;						CntNetWUPP = 0;					} else {						/* Read pattern from ASF Fifo and send it up the stack. */						SetRamAddr(pAC, SK_ST_FIFOTYPE, SK_ST_BUFADDR_LOW, SK_ST_BUFADDR_HIGH);						ret8 = AccessRamBuf(pAC, SK_ST_BUFSIZE, SK_TRUE);						if (ret8 == 0) {							pAC->SendWolPattern = SK_FALSE;							printk("sk98lin: Wakeup packet passed to protocol stack (%u retries)\n", (CntNetWUPP-1) );							CntNetWUPP = 0;						}						if (ret8 == 2) {							pAC->SendWolPattern = SK_FALSE;							printk("sk98lin: No wakeup packet passed to protocol stack (other reason)\n");							CntNetWUPP = 0;						}					}				}#endif#endif#ifdef xDEBUG				DumpMsg(pMsg, "Rx");#endif				SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,					FrameLength, Port);#ifdef __ia64__				pNewMsg = alloc_skb(pMsg->len, GFP_ATOMIC);				skb_reserve(pNewMsg, 2); /* to align IP */				SK_MEMCPY(pNewMsg->data,pMsg->data,pMsg->len);				pNewMsg->ip_summed = pMsg->ip_summed;				skb_put(pNewMsg, pMsg->len);				DEV_KFREE_SKB_ANY(pMsg);				pMsg = pNewMsg;#endif				pMsg->dev = pAC->dev[Port];				pMsg->protocol = eth_type_trans(pMsg,					pAC->dev[Port]);#ifdef CONFIG_SK98LIN_NAPI				netif_receive_skb(pMsg);#else				netif_rx(pMsg);#endif				pAC->dev[Port]->last_rx = jiffies;			} else { /* drop frame */				SK_DBG_MSG(NULL,SK_DBGMOD_DRV,					SK_DBGCAT_DRV_RX_PROGRESS,("D"));				DEV_KFREE_SKB_ANY(pMsg);			}		} else { /* This is an RLMT-packet! */

⌨️ 快捷键说明

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