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

📄 sky2.c

📁 这是Marvell Technology Group Ltd. 4355 (rev 12)网卡在linux下的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************** * * Name:        sky2.c * Project:     Yukon2 specific functions and implementations * Version:     $Revision: 1.38.4.31 $ * Date:        $Date: 2008/03/20 14:31:37 $ * Purpose:     The main driver source module * *****************************************************************************//****************************************************************************** * *	(C)Copyright 1998-2002 SysKonnect GmbH. *	(C)Copyright 2002-2007 Marvell. * *	Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet  *      Server Adapters. * *	Address all question to: gr-msgg-linux@marvell.com * *      LICENSE: *      (C)Copyright Marvell. *       *      This program is free software; you can redistribute it and/or modify *      it under the terms of the GNU General Public License as published by *      the Free Software Foundation; either version 2 of the License, or *      (at your option) any later version. *       *      The information in this file is provided "AS IS" without warranty. *      /LICENSE * *****************************************************************************/#include "h/skdrv1st.h"#include "h/skdrv2nd.h"#include <linux/tcp.h>#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,14)#include <linux/ip.h>#endif/****************************************************************************** * * Local Function Prototypes * *****************************************************************************/static void InitPacketQueues(SK_AC *pAC,int Port);static void GiveTxBufferToHw(SK_AC *pAC,SK_IOC IoC,int Port);static void GiveRxBufferToHw(SK_AC *pAC,SK_IOC IoC,int Port,SK_PACKET *pPacket);#ifdef SK_EXTREMEstatic SK_BOOL HandleReceives(SK_AC *pAC,int Port,SK_U16 Len,SK_U32 FrameStatus,SK_U16 Tcp1,SK_U16 Tcp2,SK_U32 Tist,SK_U16 Vlan, SK_U32 ExtremeCsumResult);#elsestatic SK_BOOL HandleReceives(SK_AC *pAC,int Port,SK_U16 Len,SK_U32 FrameStatus,SK_U16 Tcp1,SK_U16 Tcp2,SK_U32 Tist,SK_U16 Vlan);#endifstatic void CheckForSendComplete(SK_AC *pAC,SK_IOC IoC,int Port,SK_PKT_QUEUE *pPQ,SK_LE_TABLE *pLETab,unsigned int Done);static void UnmapAndFreeTxPktBuffer(SK_AC *pAC,SK_PACKET *pSkPacket,int TxPort);static SK_BOOL AllocateAndInitLETables(SK_AC *pAC);static SK_BOOL AllocatePacketBuffersYukon2(SK_AC *pAC);static void FreeLETables(SK_AC *pAC);static void FreePacketBuffers(SK_AC *pAC);static SK_BOOL AllocAndMapRxBuffer(SK_AC *pAC,SK_PACKET *pSkPacket,int Port);#ifdef CONFIG_SK98LIN_NAPIstatic SK_BOOL HandleStatusLEs(SK_AC *pAC,int *WorkDone,int WorkToDo);#elsestatic SK_BOOL HandleStatusLEs(SK_AC *pAC);#endifextern void	SkGeCheckTimer		(DEV_NET *pNet);extern void	SkLocalEventQueue(	SK_AC *pAC,					SK_U32 Class,					SK_U32 Event,					SK_U32 Param1,					SK_U32 Param2,					SK_BOOL Flag);extern void	SkLocalEventQueue64(	SK_AC *pAC,					SK_U32 Class,					SK_U32 Event,					SK_U64 Param,					SK_BOOL Flag);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19)/* Need way to schedule device 0 even when it's offline. */static inline int __netif_rx_schedule_prep(struct net_device *dev){	return !test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state);}#endif#endif/****************************************************************************** * * Local Variables * *****************************************************************************/#define MAX_NBR_RX_BUFFERS_IN_HW	0x15static SK_U8 NbrRxBuffersInHW;#define FLUSH_OPC(le)/****************************************************************************** * * Global Functions * *****************************************************************************/int SkY2Xmit( struct sk_buff *skb, struct SK_NET_DEVICE *dev); void FillReceiveTableYukon2(SK_AC *pAC,SK_IOC IoC,int Port);/***************************************************************************** * * 	SkY2RestartStatusUnit - restarts teh status unit * * Description: *	Reenables the status unit after any De-Init (e.g. when altering  *	the sie of the MTU via 'ifconfig a.b.c.d mtu xxx') * * Returns:	N/A */void SkY2RestartStatusUnit(SK_AC  *pAC)  /* pointer to adapter control context */{	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,		("==> SkY2RestartStatusUnit\n"));	/*	** It might be that the TX timer is not started. Therefore	** it is initialized here -> to be more investigated!	*/	SK_OUT32(pAC->IoBase, STAT_TX_TIMER_INI, HW_MS_TO_TICKS(pAC,10));	pAC->StatusLETable.Done  = 0;	pAC->StatusLETable.Put   = 0;	pAC->StatusLETable.HwPut = 0;	SkGeY2InitStatBmu(pAC, pAC->IoBase, &pAC->StatusLETable);	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,		("<== SkY2RestartStatusUnit\n"));}/***************************************************************************** * * 	SkY2RlmtSend - sends out a single RLMT notification * * Description: *	This function sends out an RLMT frame * * Returns:	 *	> 0 - on succes: the number of bytes in the message *	= 0 - on resource shortage: this frame sent or dropped, now *	      the ring is full ( -> set tbusy) *	< 0 - on failure: other problems ( -> return failure to upper layers) */int SkY2RlmtSend (SK_AC          *pAC,       /* pointer to adapter control context           */int             PortNr,    /* index of port the packet(s) shall be send to */struct sk_buff *pMessage)  /* pointer to send-message                      */{	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,		("=== SkY2RlmtSend\n"));#if 0	return -1;   // temporarily do not send out RLMT frames#endif	skb_shinfo(pMessage)->nr_frags = (2*MAX_SKB_FRAGS) + PortNr;	return(SkY2Xmit(pMessage, pAC->dev[PortNr])); // SkY2Xmit needs device}/***************************************************************************** * * 	SkY2AllocateResources - Allocates all required resources for Yukon2 * * Description: *	This function allocates all memory needed for the Yukon2.  *	It maps also RX buffers to the LETables and initializes the *	status list element table. * * Returns:	 *	SK_TRUE, if all resources could be allocated and setup succeeded *	SK_FALSE, if an error  */SK_BOOL SkY2AllocateResources (SK_AC  *pAC)  /* pointer to adapter control context */{	int CurrMac;	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,		("==> SkY2AllocateResources\n"));	/*	** Initialize the packet queue variables first	*/	for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) {		InitPacketQueues(pAC, CurrMac);	}	/* 	** Get sufficient memory for the LETables	*/	if (!AllocateAndInitLETables(pAC)) {		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 			SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR,			("No memory for LETable.\n"));		return(SK_FALSE);	}	/*	** Allocate and intialize memory for both RX and TX 	** packet and fragment buffers. On an error, free 	** previously allocated LETable memory and quit.	*/	if (!AllocatePacketBuffersYukon2(pAC)) {		FreeLETables(pAC);		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, 			SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR,			("No memory for Packetbuffers.\n"));		return(SK_FALSE);	}	/* 	** Rx and Tx LE tables will be initialized in SkGeOpen() 	**	** It might be that the TX timer is not started. Therefore	** it is initialized here -> to be more investigated!	*/	SK_OUT32(pAC->IoBase, STAT_TX_TIMER_INI, HW_MS_TO_TICKS(pAC,10));	SkGeY2InitStatBmu(pAC, pAC->IoBase, &pAC->StatusLETable);	pAC->MaxUnusedRxLeWorking = MAX_UNUSED_RX_LE_WORKING;	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,		("<== SkY2AllocateResources\n"));	return (SK_TRUE);}/***************************************************************************** * * 	SkY2FreeResources - Frees previously allocated resources of Yukon2 * * Description: *	This function frees all previously allocated memory of the Yukon2.  * * Returns: N/A */void SkY2FreeResources (SK_AC  *pAC)  /* pointer to adapter control context */{	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,		("==> SkY2FreeResources\n"));	FreeLETables(pAC);	FreePacketBuffers(pAC);	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,		("<== SkY2FreeResources\n"));}/***************************************************************************** * * 	SkY2AllocateRxBuffers - Allocates the receive buffers for a port * * Description: *	This function allocated all the RX buffers of the Yukon2.  * * Returns: N/A */void SkY2AllocateRxBuffers (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_INIT,		("==> SkY2AllocateRxBuffers (Port %c)\n", Port));	FillReceiveTableYukon2(pAC, IoC, Port);	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,		("<== SkY2AllocateRxBuffers\n"));}/***************************************************************************** * * 	SkY2FreeRxBuffers - Free's all allocates RX buffers of * * Description: *	This function frees all RX buffers of the Yukon2 for a single port * * Returns: N/A */void SkY2FreeRxBuffers (SK_AC    *pAC,   /* pointer to adapter control context */SK_IOC    IoC,	 /* I/O control context                */int       Port)	 /* port index of RX                   */{	SK_PACKET     *pSkPacket;	unsigned long  Flags;   /* for POP/PUSH macros */	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,		("==> SkY2FreeRxBuffers (Port %c)\n", Port));	if (pAC->RxPort[Port].ReceivePacketTable   != NULL) {		POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket);		while (pSkPacket != NULL) {			if ((pSkPacket->pFrag) != NULL) {				pci_unmap_page(pAC->PciDev,				(dma_addr_t) pSkPacket->pFrag->pPhys,				pSkPacket->pFrag->FragLen - 2,				PCI_DMA_FROMDEVICE);				/* wipe out any rubbish data that may interfere */				skb_shinfo(pSkPacket->pMBuf)->nr_frags = 0;				skb_shinfo(pSkPacket->pMBuf)->frag_list = NULL;				DEV_KFREE_SKB_ANY(pSkPacket->pMBuf);				pSkPacket->pMBuf        = NULL;				pSkPacket->pFrag->pPhys = (SK_U64) 0;				pSkPacket->pFrag->pVirt = NULL;			}			PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket);			POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket);		}	}	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,		("<== SkY2FreeRxBuffers\n"));}/***************************************************************************** * * 	SkY2FreeTxBuffers - Free's any currently maintained Tx buffer * * Description: *	This function frees the TX buffers of the Yukon2 for a single port *	which might be in use by a transmit action * * Returns: N/A */void SkY2FreeTxBuffers (SK_AC    *pAC,   /* pointer to adapter control context */SK_IOC    IoC,	 /* I/O control context                */int       Port)	 /* port index of TX                   */{	SK_PACKET      *pSkPacket;	SK_FRAG        *pSkFrag;	unsigned long   Flags;	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,		("==> SkY2FreeTxBuffers (Port %c)\n", Port)); 	if (pAC->TxPort[Port][0].TransmitPacketTable != NULL) {		POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxAQ_working, pSkPacket);		while (pSkPacket != NULL) {			if ((pSkFrag = pSkPacket->pFrag) != NULL) {				UnmapAndFreeTxPktBuffer(pAC, pSkPacket, Port);			}			PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->TxPort[Port][0].TxQ_free, pSkPacket);			POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxAQ_working, pSkPacket);		}#ifdef USE_SYNC_TX_QUEUE		POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxSQ_working, pSkPacket);		while (pSkPacket != NULL) {			if ((pSkFrag = pSkPacket->pFrag) != NULL) {				UnmapAndFreeTxPktBuffer(pAC, pSkPacket, Port);			}			PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->TxPort[Port][0].TxQ_free, pSkPacket);			POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxSQ_working, pSkPacket);		}#endif	}	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,		("<== SkY2FreeTxBuffers\n"));}/***************************************************************************** * * 	SkY2Isr - handle a receive IRQ for all yukon2 cards * * Description: *	This function is called when a receive IRQ is set. (only for yukon2) *	HandleReceives does the deferred processing of all outstanding *	interrupt operations. * * Returns:	N/A */#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)SkIsrRetVar SkY2Isr (int              irq,     /* the irq we have received (might be shared!) */void            *dev_id)  /* current device id                           */#elseSkIsrRetVar SkY2Isr (int              irq,     /* the irq we have received (might be shared!) */void            *dev_id,  /* current device id                           */struct  pt_regs *ptregs)  /* not used by our driver                      */#endif{	struct SK_NET_DEVICE  *dev  = (struct SK_NET_DEVICE *)dev_id;	DEV_NET               *pNet = (DEV_NET*) dev->priv;	SK_AC                 *pAC  = pNet->pAC;#ifndef CONFIG_SK98LIN_NAPI	SK_BOOL                handledStatLE	= SK_FALSE;	unsigned long          Flags;#endif	SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,		("==> SkY2Isr\n"));	SK_IN32(pAC->IoBase, B0_Y2_SP_ISRC2, &pAC->InterruptSource);	if ((pAC->InterruptSource == 0) && (!pNet->NetConsoleMode)){		SK_OUT32(pAC->IoBase, B0_Y2_SP_ICR, 2);		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,			("No Interrupt\n ==> SkY2Isr\n"));		return SkIsrRetNone;	}#ifdef Y2_RECOVERY	if (pNet->InRecover) {		SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,			("Already in recover\n ==> SkY2Isr\n"));		SK_OUT32(pAC->IoBase, B0_Y2_SP_ICR, 2);		return SkIsrRetNone;	}#endif#ifdef CONFIG_SK98LIN_NAPI	/* Since both boards share one irq, they share one poll routine */	if (__netif_rx_schedule_prep(pAC->dev[0])) {		__netif_rx_schedule(pAC->dev[0]);	}#else	handledStatLE = HandleStatusLEs(pAC);

⌨️ 快捷键说明

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