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

📄 sky2.c

📁 这是Marvell Technology Group Ltd. 4355 (rev 12)网卡在linux下的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif				FLUSH_OPC(pLE) ;			}#endif			GET_TX_LE(pLE, pLETab);			Ctrl = 0;			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,				("\tGot empty LE %p idx %d\n", pLE, GET_PUT_IDX(pLETab)));			SK_DBG_DUMP_TX_LE(pLE);			LowAddress  = (SK_U32) (pFrag->pPhys & 0xffffffff);			HighAddress = (SK_U32) (pFrag->pPhys >> 32);			if (HighAddress != pLETab->BufHighAddr) {				/* set opcode high part of the address in one LE */				OpCode = OP_ADDR64 | HW_OWNER;					/* Set now the 32 high bits of the address */				TXLE_SET_ADDR( pLE, HighAddress);					/* Set the opcode into the LE */				TXLE_SET_OPC(pLE, OpCode);					/* Flush the LE to memory */				FLUSH_OPC(pLE);					/* remember the HighAddress we gave to the Hardware */				pLETab->BufHighAddr = HighAddress;								/* get a new LE because we filled one with high address */				GET_TX_LE(pLE, pLETab);			}				/*			** TCP checksum offload			*/#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)			if ((pSkPacket->pMBuf->ip_summed == CHECKSUM_PARTIAL) && #else			if ((pSkPacket->pMBuf->ip_summed == CHECKSUM_HW) && #endif			    (SetOpcodePacketFlag         == SK_TRUE)) {				Protocol = ((SK_U8)pSkPacket->pMBuf->data[C_OFFSET_IPPROTO] & 0xff);				/* if (Protocol & C_PROTO_ID_IP) { Ctrl = 0; } */				// Yukon Extreme B0				if (HW_FEATURE(pAC, HWF_WA_DEV_510)) {					if (Protocol & C_PROTO_ID_TCP) {						Ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;						/* TCP Checksum Calculation Start Position */						TcpSumStart = C_LEN_ETHERMAC_HEADER + IP_HDR_LEN;						/* TCP Checksum Write Position */						TcpSumWrite = TcpSumStart + TCP_CSUM_OFFS;					} else {						Ctrl = UDPTCP | CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;						/* TCP Checksum Calculation Start Position */						TcpSumStart = ETHER_MAC_HDR_LEN + IP_HDR_LEN;						/* UDP Checksum Write Position */						TcpSumWrite = TcpSumStart + UDP_CSUM_OFFS;					}				}				// Yukon 2, Yukon Extreme besides B0				else {					if (Protocol & C_PROTO_ID_TCP) {#ifdef SK_EXTREME						if (!HW_IS_EXT_LE_FORMAT(pAC)) {#endif							Ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;							/* TCP Checksum Calculation Start Position */							TcpSumStart = C_LEN_ETHERMAC_HEADER + IP_HDR_LEN;							/* TCP Checksum Write Position */							TcpSumWrite = TcpSumStart + TCP_CSUM_OFFS;#ifdef SK_EXTREME						} else {							Ctrl = CALSUM;						}#endif					} else {#ifdef SK_EXTREME						if (!HW_IS_EXT_LE_FORMAT(pAC)) {#endif							Ctrl = UDPTCP | CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;							/* TCP Checksum Calculation Start Position */							TcpSumStart = ETHER_MAC_HDR_LEN + IP_HDR_LEN;							/* UDP Checksum Write Position */							TcpSumWrite = TcpSumStart + UDP_CSUM_OFFS;#ifdef SK_EXTREME						} else {							Ctrl = CALSUM;						}#endif					}				}					if ((Ctrl) && (pLETab->Bmu.RxTx.TcpWp != TcpSumWrite)) {					/* Update the last value of the write position */					pLETab->Bmu.RxTx.TcpWp = TcpSumWrite;						/* Set the Lock field for this LE: */					/* Checksum calculation for one packet only */					TXLE_SET_LCKCS(pLE, 1);						/* Set the start position for checksum. */					TXLE_SET_STACS(pLE, TcpSumStart);						/* Set the position where the checksum will be writen */					TXLE_SET_WRICS(pLE, TcpSumWrite);						/* Set the initial value for checksum */					/* PseudoHeader CS passed from Linux -> 0! */					TXLE_SET_INICS(pLE, 0);						/* Set the opcode for tcp checksum */					TXLE_SET_OPC(pLE, OP_TCPLISW | HW_OWNER);						/* Flush the LE to memory */					FLUSH_OPC(pLE);						/* get a new LE because we filled one with data for checksum */					GET_TX_LE(pLE, pLETab);				}			} /* end TCP offload handling */				TXLE_SET_ADDR(pLE, LowAddress);			TXLE_SET_LEN(pLE, pFrag->FragLen);				if (SetOpcodePacketFlag){#ifdef NETIF_F_TSO				if (Mss) {					OpCode = OP_LARGESEND | HW_OWNER;				} else {#endif					OpCode = OP_PACKET | HW_OWNER;#ifdef NETIF_F_TSO				}#endif				SetOpcodePacketFlag = SK_FALSE;			} else {				/* Follow packet in a sequence has always OP_BUFFER */				OpCode = OP_BUFFER | HW_OWNER;			}			/* Check if the low address is near the upper limit. */			CHECK_LOW_ADDRESS(pLETab->BufHighAddr, LowAddress, pFrag->FragLen);			pFrag = pFrag->pNext;			if (pFrag == NULL) {				/* mark last fragment */				Ctrl |= EOP;			}			TXLE_SET_CTRL(pLE, Ctrl);			TXLE_SET_OPC(pLE, OpCode);			FLUSH_OPC(pLE);			SK_DBG_DUMP_TX_LE(pLE);		}				/* 		** Remember next LE for tx complete 		*/		pSkPacket->NextLE = GET_PUT_IDX(pLETab);		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,			("\tNext LE for pkt %p is %d\n", pSkPacket, pSkPacket->NextLE));		/* 		** Add packet to working packets queue 		*/		PUSH_PKT_AS_LAST_IN_QUEUE(pWorkQueue, pSkPacket);		/* 		** give transmit start command		*/		if (HW_FEATURE(pAC, HWF_WA_DEV_42)) {			spin_lock(&pAC->SetPutIndexLock);			SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_XA1,0), &pAC->TxPort[0][0].TxALET);			spin_unlock(&pAC->SetPutIndexLock);		} else {			/* write put index */			if (Port == 0) { 				SK_OUT32(pAC->IoBase, 					Y2_PREF_Q_ADDR(Q_XA1,PREF_UNIT_PUT_IDX_REG), 					GET_PUT_IDX(&pAC->TxPort[0][0].TxALET)); 				UPDATE_HWPUT_IDX(&pAC->TxPort[0][0].TxALET);			} else {				SK_OUT32(pAC->IoBase, 					Y2_PREF_Q_ADDR(Q_XA2, PREF_UNIT_PUT_IDX_REG), 					GET_PUT_IDX(&pAC->TxPort[1][0].TxALET)); 				UPDATE_HWPUT_IDX(&pAC->TxPort[1][0].TxALET);			}		}			if (IS_Q_EMPTY(&(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting))) {			break; /* get out of while */		}		POP_FIRST_PKT_FROM_QUEUE(pWaitQueue, pSkPacket);	} /* while (pSkPacket != NULL) */	spin_unlock_irqrestore(&pAC->TxQueueLock, LockFlag);	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,		("<== GiveTxBufferToHw\n"));	return;}	/* GiveTxBufferToHw *//*********************************************************************** * *	GiveRxBufferToHw - commits a previously allocated DMA area to HW * * Description: *	This functions gives receive buffers to HW. If no list elements *	are available the buffers will be queued.  * * Notes: *       This function can run only once in a system at one time. * * Returns: N/A */static void GiveRxBufferToHw(SK_AC      *pAC,      /* pointer to adapter control context         */SK_IOC      IoC,      /* I/O control context (address of registers) */int         Port,     /* port index for which the buffer is used    */SK_PACKET  *pPacket)  /* receive buffer(s)                          */{	SK_HWLE         *pLE;	SK_LE_TABLE     *pLETab;	SK_BOOL         Done = SK_FALSE;  /* at least on LE changed? */	SK_U32          LowAddress;	SK_U32          HighAddress;	SK_U32          PrefetchReg;      /* register for Put index  */	unsigned        NumFree;	unsigned        Required;	unsigned long   Flags;	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,	("==> GiveRxBufferToHw(Port %c, Packet %p)\n", 'A' + Port, pPacket));	pLETab	= &pAC->RxPort[Port].RxLET;	if (Port == 0) {		PrefetchReg = Y2_PREF_Q_ADDR(Q_R1, PREF_UNIT_PUT_IDX_REG);	} else {		PrefetchReg = Y2_PREF_Q_ADDR(Q_R2, PREF_UNIT_PUT_IDX_REG);	} 	if (pPacket != NULL) {		/*		** For the time being, we have only one packet passed		** to this function which might be changed in future!		*/		PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);	}	/* 	** now pPacket contains the very first waiting packet	*/	POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);	while (pPacket != NULL) {		if (HW_FEATURE(pAC, HWF_WA_DEV_420)) {			if (NbrRxBuffersInHW >= MAX_NBR_RX_BUFFERS_IN_HW) {				PUSH_PKT_AS_FIRST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,					("<== GiveRxBufferToHw()\n"));				return;			} 			NbrRxBuffersInHW++;		}		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,			("Try to add packet %p\n", pPacket));		/* 		** Check whether we have enough listelements:		**		** we have to take into account that each fragment 		** may need an additional list element for the high 		** part of the address here I simplified it by 		** using MAX_FRAG_OVERHEAD maybe it's worth to split 		** this constant for Rx and Tx or to calculate the		** real number of needed LE's		*/		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,			("\tNum %d Put %d Done %d Free %d %d\n",			pLETab->Num, pLETab->Put, pLETab->Done,			NUM_FREE_LE_IN_TABLE(pLETab),			(NUM_FREE_LE_IN_TABLE(pLETab))));		Required = pPacket->NumFrags + MAX_FRAG_OVERHEAD;		NumFree = NUM_FREE_LE_IN_TABLE(pLETab);		if (NumFree) {			NumFree--;		}		if (Required > NumFree ) {			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 				SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR,				("\tOut of LEs have %d need %d\n",				NumFree, Required));			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,				("\tWaitQueue starts with packet %p\n", pPacket));			PUSH_PKT_AS_FIRST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);			if (Done) {				/*				** write Put index to BMU or Polling Unit and make the LE's				** available for the hardware				*/				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,					("\tWrite new Put Idx\n"));				SK_OUT32(IoC, PrefetchReg, GET_PUT_IDX(pLETab));				UPDATE_HWPUT_IDX(pLETab);			}			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,				("<== GiveRxBufferToHw()\n"));			return;		} else {			if (!AllocAndMapRxBuffer(pAC, pPacket, Port)) {				/*				** Failure while allocating sk_buff might				** be due to temporary short of resources				** Maybe next time buffers are available.				** Until this, the packet remains in the 				** RX waiting queue...				*/				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 					SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR,					("Failed to allocate Rx buffer\n"));				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,					("WaitQueue starts with packet %p\n", pPacket));				PUSH_PKT_AS_FIRST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);				if (Done) {					/*					** write Put index to BMU or Polling 					** Unit and make the LE's					** available for the hardware					*/					SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,						("\tWrite new Put Idx\n"));						SK_OUT32(IoC, PrefetchReg, GET_PUT_IDX(pLETab));					UPDATE_HWPUT_IDX(pLETab);				}				SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,					("<== GiveRxBufferToHw()\n"));				return;			}		}		Done = SK_TRUE;		LowAddress = (SK_U32) (pPacket->pFrag->pPhys & 0xffffffff);		HighAddress = (SK_U32) (pPacket->pFrag->pPhys >> 32);		if (HighAddress != pLETab->BufHighAddr) {			/* get a new LE for high address */			GET_RX_LE(pLE, pLETab);			/* Set now the 32 high bits of the address */			RXLE_SET_ADDR(pLE, HighAddress);			/* Set the control bits of the address */			RXLE_SET_CTRL(pLE, 0);			/* Set the opcode into the LE */			RXLE_SET_OPC(pLE, (OP_ADDR64 | HW_OWNER));			/* Flush the LE to memory */			FLUSH_OPC(pLE);			/* remember the HighAddress we gave to the Hardware */			pLETab->BufHighAddr = HighAddress;		}		/*		** Fill data into listelement		*/		GET_RX_LE(pLE, pLETab);		RXLE_SET_ADDR(pLE, LowAddress);		RXLE_SET_LEN(pLE, pPacket->pFrag->FragLen);		RXLE_SET_CTRL(pLE, 0);		RXLE_SET_OPC(pLE, (OP_PACKET | HW_OWNER));		FLUSH_OPC(pLE);		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,			("=== LE filled\n"));		SK_DBG_DUMP_RX_LE(pLE);		/* 		** Remember next LE for rx complete 		*/		pPacket->NextLE = GET_PUT_IDX(pLETab);		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,			("\tPackets Next LE is %d\n", pPacket->NextLE));		/* 		** Add packet to working receive buffer queue and get		** any next packet out of the waiting queue		*/		PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_working, pPacket);		if (IS_Q_EMPTY(&(pAC->RxPort[Port].RxQ_waiting))) {			break; /* get out of while processing */		}		POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);	}	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,		("\tWaitQueue is empty\n"));	if (Done) {		/*		** write Put index to BMU or Polling Unit and make the LE's		** available for the hardware		*/		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,			("\tWrite new Put Idx\n"));		/* Speed enhancement for a2 chipsets */		if (HW_FEATURE(pAC, HWF_WA_DEV_42)) {			spin_lock_irqsave(&pAC->SetPutIndexLock, Flags);			SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_R1,0), pLETab);			spin_unlock_irqrestore(&pAC->SetPutIndexLock, Flags);		} else {			/* write put index */			if (Port == 0) { 				SK_OUT32(IoC, 					Y2_PREF_Q_ADDR(Q_R1, PREF_UNIT_PUT_IDX_REG), 					GET_PUT_IDX(pLETab)); 			} else {

⌨️ 快捷键说明

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