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

📄 gnlend.c

📁 vxwork平台下网卡驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:

/****************************************************************************************************
**	文件名: gnlEnd.c NPT driver for Galileo StrataSwitch 
**   Copyright (c) 2000-2002 烽火通信科技股份有限公司
**   创建人:  lirui
**   负责人:  lirui
**   日期:       2002-04-20
**   其他:
***************************************************************************************************/

#include "copyright_wrs.h"

/*
   modification history
   --------------------
   /*2002-6-12       llqiu       在gnlEndLoad中添加打开看门狗监控
   01i,09oct00,kw   netTupleGet had incorrect argument and OR in M_PKTHDR.
   01h,25sep00,kw   Added a debug set of defines.
   01h,17sep00,kw   The LS_RCV_HANDLING flag was not set in gnlEndInt receive
   routine, but was cleared in the handler routine later.
   This could cause a workQ overflow error in netJobAdd.
   01g,15sep00,twh  Change netTupleGet call back to TRUE
   01f,11sep00,kw   Pass the VLAN ID up in the pSpare variable.
   01e,21aug00,twh  Convert GNL_ defined names to HW_ so END will build...
   01d,07aug00,twh  Add hwApi.h and add ioctl support for EIOCGHWAPI
   01c,26jun00,twh  Modifies from pmEnd.c
   01b,16jun00,tf   Call netTupleGet with bestFit=FALSE (was TRUE)
   01a,05mar00,kw   Created
 */

/*
   DESCRIPTION
   This module implements the TMS Ethernet network interface driver.  The driver
   can be configured to support big-endian or little-endian architectures, and
   it contains error recovery code.

   This driver is designed to be moderately generic.  Thus, it operates 
   unmodified across the range of architectures and targets supported by 
   VxWorks.  To achieve this, the driver load routine requires an input 
   string consisting of several target-specific values.  The driver also 
   requires some external support routines.  These target-specific values 
   and the external support routines are described below.  If any of the 
   assumptions stated below are not true for your particular hardware, this 
   driver might not function correctly with that hardware.

   This driver is really only half of the real Switch Chip driver. This driver
   is the upper interface part for the complete driver and only deals with
   IP interface and MUX/NPT driver interface issues. Because this driver
   does not touch hardware it does not have routines to deal directly with
   the switch chip. This lower driver is called gnlEnd and contains routines
   that are specificly for the switch chip it manages. So this driver will
   collect packets from the lower layer to pass to the IP stack and other
   protocol (like 802.1D (STP) and 802.1Q (VLAN)). The lower layer expects
   this driver to pass the MBLK to the MUX interface.

   EXTERNAL INTERFACE
   The only external interface is the gnlEndLoad() routine, which expects
   the <initString> parameter as input.  This parameter passes in a 
   colon-delimited string of the format:

   "<unit>:<ToBeDecided>"

   \ml
   \m <unit>
   The unit number assigned to this gnlEnd device driver.
   \m <ToBeDecided>
   To Be Decided.
   \me

   SEE ALSO: muxLib, swEnd, apEnd, agEnd
 */

#include "vxWorks.h"
#include "wdLib.h"
#include "stdlib.h"
#include "taskLib.h"
#include "logLib.h"
#include "intLib.h"
#include "netLib.h"
#include "stdio.h"
#include "stdlib.h"
#include "sysLib.h"
#include "iv.h"
#include "memLib.h"
#include "semLib.h"
#include "cacheLib.h"
#include "sys/ioctl.h"
#include "etherLib.h"
/*lirui 2001-11-12 */
#include "dec21x4xEnd.h"

#ifndef DOC						/* don't include when building documentation */
#include "net/mbuf.h"
#endif /* DOC */

#include "net/protosw.h"
#include "sys/socket.h"
#include "errno.h"
#include "net/if.h"
#include "net/route.h"
#include "netinet/in.h"
#include "netinet/in_systm.h"
#include "netinet/in_var.h"
#include "netinet/ip.h"
#include "netinet/if_ether.h"
#include "net/if_subr.h"
#include "m2Lib.h"
#include "end.h"				/* Common END structures. */
#include "netBufLib.h"
#include "muxLib.h"
#include "switchLib.h"
#include "portLib.h"
#include "sgList.h"
#include "hwEndCommon.h"		/* Common defines. */
#include "gnlEnd.h"
#include "hwApi.h"
#include "etherMultiLib.h"		/* multicast stuff. */

/* NPT requires that we make this defined. */
#define END_MACROS
#include "endLib.h"
#include "lstLib.h"				/* Needed to maintain protocol list. */

/***** LOCAL DEFINITIONS *****/
#undef dbgEnabled
#ifdef dbgEnabled
LOCAL int dbgLevel = 1;

#define dbgPrintf(lvl, _x) if ( lvl == dbgLevel ) {printf _x;}
#else
#define dbgPrintf(lvl, _x)
#endif

#define ENABLE_PKT_SEND
#define ENABLE_PKT_RECV

#define GNL_SPEED       100000000

#define GNL_ALIGN_DATA  2
#define GNL_ADJUSTMENT  GNL_ALIGN_DATA

/* Cache macros */

#define GNL_CACHE_INVALIDATE(address, len) \
        CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))

#define GNL_CACHE_PHYS_TO_VIRT(address) \
        CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))

#define GNL_CACHE_VIRT_TO_PHYS(address) \
        CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))

/* A shortcut for getting the hardware address from the MIB II stuff. */
#define END_HADDR(pEnd)                                                 \
        ((pEnd)->pMib2Tbl->m2Data.mibIfTbl.ifPhysAddress.phyAddress)

#define END_HADDR_LEN(pEnd)                                             \
        ((pEnd)->pMib2Tbl->m2Data.mibIfTbl.ifPhysAddress.addrLength)

#define END_FLAGS_ISSET(pEnd, setBits) \
            ((pEnd)->flags & (setBits))
/*lirui */
#define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult)                       \
    {                                                                   \
    IMPORT STATUS intConnect();                                      \
    *pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec),\
			     (rtn), (int)(arg));                        \
    }

/*lirui 2001-11-12 */
#define RD_SIZ			sizeof(DEC_RD)
#define TD_SIZ			sizeof(DEC_TD)

/* Cache macros */
#define DEC_CACHE_INVALIDATE(address, len)                              \
        CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))

#define DEC_CACHE_VIRT_TO_PHYS(address)                                 \
        CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))

#define DEC_CACHE_PHYS_TO_VIRT(address)                                 \
        CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))

/* memory to PCI address translation macros */
#define PCI_TO_MEM_PHYS(pciAdrs)                                        \
	(((ULONG)(pciAdrs)) - (pDrvCtrl->pciMemBase))

#define MEM_TO_PCI_PHYS(memAdrs)                                        \
	(((ULONG)(memAdrs)) + (pDrvCtrl->pciMemBase))

#define DEC_VIRT_TO_PCI(vAdrs)                                          \
	MEM_TO_PCI_PHYS (DEC_CACHE_VIRT_TO_PHYS (vAdrs))

#define DEC_PCI_TO_VIRT(pciAdrs)                                        \
	DEC_CACHE_PHYS_TO_VIRT (PCI_TO_MEM_PHYS (pciAdrs))
/* Definitions for the flags field */

#define LS_POLLING              0x1
#define LS_RCV_HANDLING         0x2

/***** DEBUG MACROS *****/

#undef DRV_DEBUG

#ifdef  DRV_DEBUG
#define DRV_DEBUG_OFF       0x0000
#define DRV_DEBUG_RX        0x0001
#define DRV_DEBUG_TX        0x0002
#define DRV_DEBUG_INT       0x0004
#define DRV_DEBUG_LOAD      0x0008
#define DRV_DEBUG_IOCTL     0x0010
#define DRV_DEBUG_ALL       (                       \
                             DRV_DEBUG_RX | DRV_DEBUG_TX    \
                            )

#ifdef LOCAL
#undef LOCAL
#endif

#define LOCAL

int gnlDebug = DRV_DEBUG_ALL;	/* Turn it off initially. */

#define DRV_PRINT(FLG,X)  printf X;
/*    if (gnlDebug & FLG) printf X; */

#else /*DRV_DEBUG */

#ifndef LOCAL
#define LOCAL static
#endif

#define DRV_PRINT(FLG,X)

#endif /*DRV_DEBUG */

#ifndef SYS_GALNET302_INIT
#define SYS_GALNET302_INIT(pDrvCtrl)                             \
    {                                                                   \
    IMPORT STATUS sysGalnet302Init();                                    \
     sysGalnet302Init (pDrvCtrl);	                        \
    }
#endif

/***** LOCALS *****/

/* forward static functions */
IMPORT void *gnlInit ( /* int, */ END_OBJ * /*int */ );
IMPORT STATUS gnlPktSend (void *, M_BLK_ID, void *);

LOCAL void gnlEndReset (END_OBJ * pEnd);
LOCAL STATUS gnlEndRecvPacket (END_OBJ * pEnd, int param2, int param3,
	int param4, int param5);
LOCAL STATUS gnlEndRestartSetup (END_OBJ * pEnd);
LOCAL void gnlEndConfig (END_OBJ * pEnd);
LOCAL void gnlEndAddrFilterSet (END_OBJ * pEnd);

/* END Specific interfaces. */

/* This is the only externally visible interface. */
END_OBJ *gnlEndLoad (char *initString);

LOCAL STATUS gnlEndStart (END_OBJ * pEnd);
LOCAL STATUS gnlEndStop (END_OBJ * pEnd);
LOCAL STATUS gnlEndUnload (END_OBJ * pEnd);
LOCAL int gnlEndIoctl (END_OBJ * pEnd, int cmd, caddr_t data);
LOCAL STATUS gnlEndSend (END_OBJ * pEnd, M_BLK_ID pBuf, void *pSpare);
LOCAL STATUS gnlNptSend (END_OBJ * pEnd, M_BLK_ID pBuf, char *, long, void *);

LOCAL STATUS gnlPollSend (END_OBJ * pEnd, M_BLK_ID pBuf);
LOCAL STATUS gnlPollReceive (END_OBJ * pEnd, M_BLK_ID pBuf);

STATUS gnlEndMCastAddrAdd (END_OBJ * pEnd, char *pAddress);
LOCAL STATUS gnlEndMCastAddrDel (END_OBJ * pEnd, char *pAddress);
LOCAL STATUS gnlEndMCastAddrGet (END_OBJ * pEnd, MULTI_TABLE * pTable);

LOCAL STATUS gnlInitParse (GNLDEV_OBJ * pDrvCtrl, char *initString);
LOCAL STATUS gnlInitMem (GNLDEV_OBJ * pDrvCtrl);

STATUS gnlEndPoolShow (int unit);
void netPoolShow (NET_POOL_ID);
IMPORT int sysEnetAddrGet (char *, int, unsigned char *);
IMPORT void watchdog_enable ();	/*llqiu add for watchdog 2002-6-13 */
LOCAL STATUS GalNetipdslamSend (END_OBJ * pEnd, M_BLK_ID pBuf, char *, long,
	void *);
/*
 * Declare our function table.  This is static across all driver
 * instances.
 */
LOCAL NET_FUNCS gnlFuncTable = {
	(FUNCPTR) gnlEndStart,		/* Function to start the device. */
	(FUNCPTR) gnlEndStop,		/* Function to stop the device. */
	(FUNCPTR) gnlEndUnload,		/* Unloading function for the driver. */
	(FUNCPTR) gnlEndIoctl,		/* Ioctl function for the driver. */
	(FUNCPTR) GalNetipdslamSend,	/* Send function for the driver. *//*lirui modify 2003-2-20 for transmit */
	(FUNCPTR) gnlEndMCastAddrAdd,	/* Multicast address add */
	(FUNCPTR) gnlEndMCastAddrDel,	/* Multicast address delete */
	(FUNCPTR) gnlEndMCastAddrGet,	/* Multicast table retrieve */
	(FUNCPTR) gnlPollSend,		/* Polling send function for the driver. */
	(FUNCPTR) gnlPollReceive,	/* Polling receive function for the driver. */
	(void *) endEtherAddressForm,	/* Put address info into a packet.  */
	(FUNCPTR) endEtherPacketDataGet,	/* Get a pointer to packet data. */
	(FUNCPTR) endEtherPacketAddrGet,	/* Get packet addresses. */
	(FUNCPTR) NULL				/* bind routine. */
};

 /* 网络缓冲区的配置 */
#define GALNET48302_BUFSIZ      (ETHERMTU + ENET_HDR_REAL_SIZ + 22)

M_CL_CONFIG GalNet48302MclConfig =	/* mBlk配置表 */
{
	0, 0, NULL, 0
};

CL_DESC GalNet48302ClDescTbl[] =	/* 网络的cluster池配置表 */
{
	/* 
	   cluster的大小          cluster的数目 预分配的地址    预分配的大小
	   -----------               ----                    -------                -------
	 */
	{GALNET48302_BUFSIZ, 0, NULL, 0}
};

/* 上面的GalNet48302ClDescTbl中表项的个数 */
int GalNet48302ClDescTblNumEnt = (NELEMENTS (GalNet48302ClDescTbl));

extern NET_POOL_ID pgl_NetPool;
extern CL_POOL_ID pgl_pclPoolId;	/*lirui add 2003-1-9 for debug */

END_OBJ *gnlEnd;
GNLDEV_OBJ *gnlpDrvCtrl;

/*****************************************************************************
*
* gnlEndLoad - initialize the driver and device
*
* DESCRIPTION
* This routine initializes the driver and the device to the operational state.
* All of the device-specific parameters are passed in <initString>, which
* expects a string of the following format:
*
* "<unit>:<ClusterSize>,<ClusterCnt>:<ClusterSize>,<ClusterCnt>:..."
*
* This routine can be called in two modes. If it is called with an empty but
* allocated string, it places the name of this device (that is, "gnl") into 
* the <initString> and returns 0.
*
* If the string is allocated and not empty, the routine attempts to load
* the driver using the values specified in the string.
*
* RETURNS:
* An END object pointer, or NULL on error, or 0 and the name of the
* device if the <initString> was NULL.
*
* ERRNO: N/A
*/

END_OBJ *gnlEndLoad (char *initString	/* string to be parse by the driver */
	)
{
	GNLDEV_OBJ *pDrvCtrl;
	UINT32 data;
	char bucket[sizeof (ULONG)];
	char enetAddr[8];			/*lirui 2001-12-21 */

	/*printf("Loading 1 gnl...initString %08x\n", (UINT32)initString); */

	if (initString == NULL)
		return (NULL);

	DRV_PRINT (DRV_DEBUG_LOAD, ("Loading 2 gnl...initString[0] %02x\n",
			initString[0]));
	if (initString[0] == NULL)
	{
		DRV_PRINT (DRV_DEBUG_LOAD, ("Loading gnl...Set defaults\n"));
		bcopy ((char *) HW_DEVICE_NAME, initString, HW_DEVICE_NAME_LEN);
		return (0);
	}
	DRV_PRINT (DRV_DEBUG_LOAD, ("Allocate the device structure\n"));

	/* allocate the device structure */
	pDrvCtrl = (GNLDEV_OBJ *) calloc (1, sizeof (GNLDEV_OBJ));
	if (pDrvCtrl == NULL)
		goto errorExit;

	lstInit (&pDrvCtrl->endObj.multiList);	/*该函数将组波地址列表清空 */

	/* Copy the orignal NET_FUNCS table into the instance version. */
	*(NET_FUNCS *) & pDrvCtrl->funcTable = *(NET_FUNCS *) & gnlFuncTable;

	pDrvCtrl->adjustLength = GNL_ADJUSTMENT;

	/* parse the init string, filling in the device structure */

	DRV_PRINT (DRV_DEBUG_LOAD, ("Parse the initString\n"));
	if (gnlInitParse (pDrvCtrl, initString) == ERROR)
	{
		/*printf("\ngnlEndLoad: gnlInitParse  failed!\n "); */
		goto errorExit;
	}

	/* We left the send Send routine as NULL values, fill it in here.  */
/*pDrvCtrl->funcTable.send = (FUNCPTR) gnlNptSend; *//*lirui del 2003-2-20 */

	/* initialize the END and MIB2 parts of the structure, we currently
	 * do not use this MIB2 structure and it needs to change anyway. */

	if (vxMemProbe ((char *) pDrvCtrl->devAdrs, VX_READ,	/*vxMemProbe函数探测在给定的地址是否可以进行读写操作 */
			sizeof (ULONG), &bucket[0]) != OK)
	{
		/* printf(" gnlEndLoad :need MMU mapping for address !\n"); */
		return (NULL);
	}

	if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ *) pDrvCtrl, HW_DEVICE_NAME,
			pDrvCtrl->unit, &pDrvCtrl->funcTable,
			"GNL Network Driver") == ERROR)
	{
		/* printf("\ngnlEndLoad : END_OBJ_INIT failed!"); */
		goto errorExit;
	}

	get_default_mac_addr (enetAddr);	/*lirui add 2002-6-22 */
	if (END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd,
			(UINT8 *) enetAddr, EADDR_LEN, ETHERMTU, GNL_SPEED) == ERROR)
	{
		/*printf("END_MIB_INIT failed!\n"); */
		return (ERROR);
	}

	/*end lirui 2001-12-21 */
	DRV_PRINT (DRV_DEBUG_LOAD, ("Perform memory allocation\n"));

	/* Perform memory allocation */

	if (gnlInitMem (pDrvCtrl) == ERROR)
	{
		/* printf("\ngnlEndLoad: gnlInitMem failed!\n"); */
		goto errorExit;
	}

	DRV_PRINT (DRV_DEBUG_LOAD, ("Perform memory distribution\n"));

	/* Perform memory distribution and reset and reconfigure the device */

	if (gnlEndRestartSetup (&pDrvCtrl->endObj) == ERROR)
		goto errorExit;

	DRV_PRINT (DRV_DEBUG_LOAD, ("Set flags\n"));

	/* set the flags to indicate readiness */
	END_OBJ_READY (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX);	/*lirui 2001-12-21 */

	DRV_PRINT (DRV_DEBUG_LOAD, ("Done loading gnl...\n"));

	gnlInit (&pDrvCtrl->endObj);	/*lirui 2001-12-20 */

	gnlEnd = &pDrvCtrl->endObj;
	gnlpDrvCtrl = pDrvCtrl;

	return (&pDrvCtrl->endObj);

  errorExit:
	DRV_PRINT (DRV_DEBUG_LOAD, ("Left on a ERROR\n"));
	if (pDrvCtrl != NULL)
		free ((char *) pDrvCtrl);

	return NULL;
}

/*lirui 2001-11-12 */

/*******************************************************************************
*
* gnlInitParse - parse parameter values from initString
*
* Parse the input string.  Fill in values in the driver control structure.
*
* The initialization string format is:
* "<device addr>:<PCI addr>:<ivec>:<ilevel>:<mem base>:<mem size>:	\
*  <user flags>:<offset>"
*
* .IP <device addr>
* base address of hardware device registers
* .IP <PCI addr>
* main memory address over the PCI bus
* .IP <ivec>
* interrupt vector number
* .IP <ilevel>
* interrupt level
* .IP <mem base>
* base address of a DMA-able, cache free,pre-allocated  memory
* .IP <mem size>
* size of the pre-allocated memory
* .IP <user flags>
* User flags control the run-time characteristics of the chip
* .IP <offset>
* Memory offset for alignment
* .LP
*
* RETURNS: OK or ERROR for invalid arguments.
*/

LOCAL STATUS gnlInitParse (GNLDEV_OBJ * pDrvCtrl, char *initString)
{
	char *tok;
	char *pHolder = NULL;
	char *savedInitString;
	int i, numSubEnds;

	savedInitString = calloc (1, strlen (initString) + 1);
	strcpy (savedInitString, initString);

	/* Parse the initString */
	DRV_PRINT (DRV_DEBUG_LOAD, ("Processing all arugments (%s)\n", initString));

	/* Unit number. */
	tok = strtok_r (savedInitString, ":", &pHolder);
	if (tok == NULL)
		return ERROR;
	pDrvCtrl->unit = atoi (tok);
	DRV_PRINT (DRV_DEBUG_LOAD, ("Unit is %d\n", pDrvCtrl->unit));

	tok = strtok_r (NULL, ":", &pHolder);
	if (tok == NULL)
		return ERROR;
	numSubEnds = atoi (tok);

	if (numSubEnds == NULL)
	{
		printf ("gnl%d: Number of subEnds is ZERO\n", pDrvCtrl->unit);
		return ERROR;
	}
	/*else if ( subEndCreate( &pDrvCtrl->endObj, numSubEnds ) == ERROR )
	   {
	   printf("gnlEndInitParse: subEndCreate Failed\n");
	   return ERROR;

⌨️ 快捷键说明

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