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

📄 sky2.c

📁 这是Marvell Technology Group Ltd. 4355 (rev 12)网卡在linux下的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	*/	if (SkGeInitPort(pAC, IoC, Port)) {		if (Port == 0) {			printk("%s: SkGeInitPort A failed.\n",pAC->dev[0]->name);		} else {			printk("%s: SkGeInitPort B failed.\n",pAC->dev[1]->name);		}	}		if (IS_GMAC(pAC)) {		/* disable Rx GMAC FIFO Flush Mode */		SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8) GMF_RX_F_FL_OFF);	}	/*	** Initialize the MC addresses	*/	SkAddrMcUpdate(pAC,IoC, Port);	SkMacRxTxEnable(pAC, IoC,Port);					SkGeRxCsum(pAC, IoC, Port, SK_TRUE);		GET_RX_LE(pLE, &pAC->RxPort[Port].RxLET);	RXLE_SET_STACS1(pLE, pAC->CsOfs1);	RXLE_SET_STACS2(pLE, pAC->CsOfs2);	RXLE_SET_CTRL(pLE, 0);	RXLE_SET_OPC(pLE, OP_TCPSTART | HW_OWNER);	FLUSH_OPC(pLE);	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);	}	DWord = GET_PUT_IDX(&pAC->RxPort[Port].RxLET);	SK_OUT32(IoC, PrefetchReg, DWord);	UPDATE_HWPUT_IDX(&pAC->RxPort[Port].RxLET);	pAC->GIni.GP[Port].PState = SK_PRT_RUN;	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,		("<== SkY2PortStart()\n"));}#ifdef USE_ASF_DASH_FW/* LC Packet fields. */#define	SK_LLC_DSAP			0x00#define	SK_LLC_SSAP			0x00#define SK_LLC_CTRL			0xE3    /* LLC Test*/#define SK_LLC_INDICATOR0		0x00#define SK_LLC_INDICATOR1		0x00	#define SK_LLC_INDICATOR2		0x00	#define SK_LLC_INDICATOR3		0x00	#define SK_LLC_INDICATOR4		0x00	#define SK_LLC_INDICATOR5		0x00	#define SK_LLC_INDICATOR6		0x00	#define SK_LLC_PACKET_VERSION		0#define SK_LLC_MIN_PACKET_SIZE		34#define SK_LLC_MAX_PACKET_SIZE		64#define SK_LLC_PACKET_DATA_LEN		(SK_LLC_MAX_PACKET_SIZE - SK_LLC_MIN_PACKET_SIZE - 4)/* LLC packet.  Length: SK_LLC_MAX_PACKET_SIZE (64) bytes. */typedef struct s_LLCPacket {	SK_U8	DstAddr[SK_MAC_ADDR_LEN];	SK_U8	SrcAddr[SK_MAC_ADDR_LEN];	SK_U8	TypeLen[2];	SK_U8	DSap;	SK_U8	SSap;	SK_U8	Ctrl;	SK_U8	Indicator[7];	SK_U8	LLCPacketType[2];	SK_U8	Align1[2];	SK_U8	Random[4];	SK_U8	LLCPacketVersion[2];	/* LLC Packet version. */	SK_U8	Data[SK_LLC_PACKET_DATA_LEN];	SK_U32  CheckSum;} SK_LLC_PACKET;#ifdef SK_LITTLE_ENDIAN#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \	SK_U8	*_Addr = (SK_U8*)(Addr); \	SK_U16	_Val = (SK_U16)(Val); \	*_Addr++ = (SK_U8)(_Val >> 8); \	*_Addr = (SK_U8)(_Val & 0xFF); \}#endif#ifdef SK_BIG_ENDIAN#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val))#endif/***************************************************************************** * *	SkDrvAllocLLCMbuf - allocate an LLC mbuf * * Description: *	This routine returns an LLC mbuf or NULL. The LLC Mbuf structure *	is embedded into a socket buff data area. * * Context: *	runtime * * Returns: *	NULL or pointer to Mbuf. */SK_MBUF *SkDrvAllocLLCMbuf(SK_AC		*pAC,		/* pointer to adapter context */SK_IOC		IoC,		/* the IO-context */unsigned	BufferSize)	/* size of the requested buffer */{SK_MBUF		*pLLCMbuf;	/* pointer to a new LLC-mbuf structure */struct sk_buff	*pMsgBlock;	/* pointer to a new message block */	pMsgBlock = alloc_skb(BufferSize + sizeof(SK_MBUF), GFP_ATOMIC);	if (pMsgBlock == NULL) {		return (NULL);	}	pLLCMbuf = (SK_MBUF*) pMsgBlock->data;	skb_reserve(pMsgBlock, sizeof(SK_MBUF));	pLLCMbuf->pNext = NULL;	pLLCMbuf->pOs = pMsgBlock;	pLLCMbuf->pData = pMsgBlock->data;	/* Data buffer. */	pLLCMbuf->Size = BufferSize;		/* Data buffer size. */	pLLCMbuf->Length = 0;		/* Length of packet (<= Size). */	return (pLLCMbuf);} /* SkDrvAllocLLCMbuf *//****************************************************************************** * *	SkLLCBuildPacket - build an LLC packet * * Description: *	This routine sets up an LLC packet. * * Context: *	runtime, pageable? * * Returns: *	NULL or pointer to LLC mbuf */SK_MBUF	*SkLLCBuildPacket(SK_AC		*pAC,		/* Adapter Context */SK_IOC		IoC,		/* I/O Context */SK_U32		PortNumber,	/* Sending port */SK_U16		PacketType,	/* Packet type */SK_MAC_ADDR	*SrcAddr,	/* Source address */SK_MAC_ADDR	*DestAddr)	/* Destination address */{	int		i;	SK_U16		Length;	SK_MBUF		*pMb;	SK_LLC_PACKET	*pPacket;#ifdef DEBUG	SK_U8	CheckSrc  = 0;	SK_U8	CheckDest = 0;		for (i = 0; i < SK_MAC_ADDR_LEN; ++i) {		CheckSrc  |= SrcAddr->a[i];		CheckDest |= DestAddr->a[i];	}	if ((CheckSrc == 0) || (CheckDest == 0)) {		SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR,			("SkBuildLLCPacket: Invalid %s%saddr.\n",			 (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : "")));	}#endif	if ((pMb = SkDrvAllocLLCMbuf(pAC, IoC, SK_LLC_MAX_PACKET_SIZE)) != NULL) {		pPacket = (SK_LLC_PACKET*)pMb->pData;		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {			pPacket->DstAddr[i] = DestAddr->a[i];			pPacket->SrcAddr[i] = SrcAddr->a[i];		}		pPacket->DSap = SK_LLC_DSAP;		pPacket->SSap = SK_LLC_SSAP;		pPacket->Ctrl = SK_LLC_CTRL;		pPacket->Indicator[0] = SK_LLC_INDICATOR0;		pPacket->Indicator[1] = SK_LLC_INDICATOR1;		pPacket->Indicator[2] = SK_LLC_INDICATOR2;		pPacket->Indicator[3] = SK_LLC_INDICATOR3;		pPacket->Indicator[4] = SK_LLC_INDICATOR4;		pPacket->Indicator[5] = SK_LLC_INDICATOR5;		pPacket->Indicator[6] = SK_LLC_INDICATOR6;		pPacket->LLCPacketType[0] = 0x00;		pPacket->LLCPacketType[1] = 0x00;		// SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->LLCPacketType[0]);		pPacket->Align1[0] = 0x00;		pPacket->Align1[1] = 0x00;		for (i = 0; i < 4; i++) {			pPacket->Random[i] = 0x00;		}				pPacket->LLCPacketVersion[0] = 0x00;		pPacket->LLCPacketVersion[1] = 0x00;		SK_U16_TO_NETWORK_ORDER(			SK_LLC_PACKET_VERSION, &pPacket->LLCPacketVersion[0]);		for (i = 0; i < SK_LLC_PACKET_DATA_LEN; i++) {			pPacket->Data[i] = 0x00;		}		Length = SK_LLC_MAX_PACKET_SIZE;	/* Or smaller. */		pMb->Length = Length;		pMb->PortIdx = PortNumber;		Length -= 14;		SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]);		pPacket->CheckSum = 0xFFFFFFFF; /* Inverse of 0 */#if 0		if (PacketType == SK_PACKET_ALIVE) {			pAC->Rlmt.Port[PortNumber].TxHelloCts++;		}#endif	}	return (pMb);}	/* SkBuildLLCPacket */void SkSendLLCPacket(SK_AC		*pAC,		/* Adapter Context */SK_IOC		IoC,		/* I/O Context */SK_U32		PortNumber	/* Sending port */){	SK_U16 PacketType = 0x02;	SK_MAC_ADDR SkLLCMcAddr = {{0x01,  0x00,  0x5A,  0x52,  0x4C, 0x4D}};	SK_MBUF *pLLCMbuf;	struct sk_buff *pMsg;	pLLCMbuf = SkLLCBuildPacket(pAC, IoC, 			  PortNumber,                           PacketType,			  &pAC->Addr.Port[PortNumber].CurrentMacAddress,			  &SkLLCMcAddr);	pMsg = (struct sk_buff*) pLLCMbuf->pOs;	skb_put(pMsg, pLLCMbuf->Length);	skb_shinfo(pMsg)->nr_frags = (2*MAX_SKB_FRAGS) + PortNumber;	SkY2Xmit(pMsg, pAC->dev[PortNumber]); // SkY2Xmit needs device}	/* SkSendLLCPacket */#endif/****************************************************************************** * * Local Functions * *****************************************************************************//***************************************************************************** * *	InitPacketQueues - initialize SW settings of packet queues * * Description: *	This function will initialize the packet queues for a port. * * Returns: N/A */static void InitPacketQueues(SK_AC  *pAC,   /* pointer to adapter control context */int     Port)  /* index of port to be initialized    */{	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,		("==> InitPacketQueues(Port %c)\n", 'A' + Port));		pAC->RxPort[Port].RxQ_working.pHead = NULL;	pAC->RxPort[Port].RxQ_working.pTail = NULL;	spin_lock_init(&pAC->RxPort[Port].RxQ_working.QueueLock);		pAC->RxPort[Port].RxQ_waiting.pHead = NULL;	pAC->RxPort[Port].RxQ_waiting.pTail = NULL;	spin_lock_init(&pAC->RxPort[Port].RxQ_waiting.QueueLock);		pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.pHead = NULL;	pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.pTail = NULL;	spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.QueueLock);	pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.pHead = NULL;	pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.pTail = NULL;	spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.QueueLock);		pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.pHead = NULL;	pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.pTail = NULL;	spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.QueueLock);	#ifdef USE_SYNC_TX_QUEUE	pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.pHead = NULL;	pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.pTail = NULL;	spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.QueueLock);	pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.pHead = NULL;	pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.pTail = NULL;	spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.QueueLock);#endif		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,		("<== InitPacketQueues(Port %c)\n", 'A' + Port));}	/* InitPacketQueues *//***************************************************************************** * *	GiveTxBufferToHw - commits a previously allocated DMA area to HW * * Description: *	This functions gives transmit 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 GiveTxBufferToHw(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_HWLE         *pLE;	SK_PACKET       *pSkPacket;	SK_FRAG         *pFrag;	SK_PKT_QUEUE    *pWorkQueue;   /* corresponding TX queue */	SK_PKT_QUEUE    *pWaitQueue; 	SK_LE_TABLE     *pLETab;       /* corresponding LETable  */ 	SK_BOOL          SetOpcodePacketFlag;	SK_U32           HighAddress;	SK_U32           LowAddress;	SK_U16           TcpSumStart = 0; 	SK_U16           TcpSumWrite = 0;	SK_U8            OpCode;	SK_U8            Ctrl;	unsigned long    Flags;	unsigned long    LockFlag;	int              Protocol;#ifdef NETIF_F_TSO	SK_U16           Mss;	int              TcpOptLen;	int              IpTcpLen;#endif	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,		("==> GiveTxBufferToHw\n"));	if (HW_FEATURE(pAC, HWF_WA_DEV_510)) {		SK_OUT32(pAC->IoBase, TBMU_TEST, TBMU_TEST_BMU_TX_CHK_AUTO_OFF);	}	if (IS_Q_EMPTY(&(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting))) {		return;	}	spin_lock_irqsave(&pAC->TxQueueLock, LockFlag);	/*	** Initialize queue settings	*/	pWorkQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working);	pWaitQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting);	pLETab     = &(pAC->TxPort[Port][TX_PRIO_LOW].TxALET);	POP_FIRST_PKT_FROM_QUEUE(pWaitQueue, pSkPacket);	while (pSkPacket != NULL) {		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,			("\tWe have a packet to send %p\n", pSkPacket));		/* 		** the first frag of a packet gets opcode OP_PACKET 		*/		SetOpcodePacketFlag	= SK_TRUE;		pFrag			= pSkPacket->pFrag;		/* 		** fill list elements with data from fragments 		*/		while (pFrag != NULL) {			SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,				("\tGet LE\n"));#ifdef NETIF_F_TSO#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)			Mss = skb_shinfo(pSkPacket->pMBuf)->gso_size;#else			Mss = skb_shinfo(pSkPacket->pMBuf)->tso_size;#endif			if (Mss) {#ifdef SK_EXTREME				if (!HW_IS_EXT_LE_FORMAT(pAC)) {#endif#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)				       struct iphdr *iph = ip_hdr(pSkPacket->pMBuf);					struct tcphdr *tcph = tcp_hdr(pSkPacket->pMBuf);										TcpOptLen = ((tcph->doff - 5) * 4);					IpTcpLen  = ((iph->ihl * 4) + sizeof(struct tcphdr));#else					TcpOptLen = ((pSkPacket->pMBuf->h.th->doff - 5) * 4);					IpTcpLen  = ((pSkPacket->pMBuf->nh.iph->ihl * 4) + 						sizeof(struct tcphdr));#endif					Mss += (TcpOptLen + IpTcpLen + C_LEN_ETHERMAC_HEADER);#ifdef SK_EXTREME				}#endif			}			if (pLETab->Bmu.RxTx.MssValue != Mss) {				pLETab->Bmu.RxTx.MssValue = Mss;				/* Take a new LE for TSO from the table */				GET_TX_LE(pLE, pLETab);#ifdef SK_EXTREME				if (HW_IS_EXT_LE_FORMAT(pAC)) {					TXLE_SET_OPC(pLE, OP_MSS | HW_OWNER);					TXLE_SET_MSSVAL(pLE, pLETab->Bmu.RxTx.MssValue);				} else {#endif					TXLE_SET_OPC(pLE, OP_LRGLEN | HW_OWNER);					TXLE_SET_LSLEN(pLE, pLETab->Bmu.RxTx.MssValue);#ifdef SK_EXTREME				}

⌨️ 快捷键说明

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