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

📄 gnlend.c

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

	/* Decode the Number of MBLK's and number of Clusters */
	tok = strtok_r (NULL, ":", &pHolder);
	if (tok == NULL)
		return ERROR;
	pDrvCtrl->numMblks = atoi (tok);

	/* Number of MBLK's for the clusters */
	tok = strtok_r (NULL, ":", &pHolder);
	if (tok == NULL)
		return ERROR;
	pDrvCtrl->numClusters = atoi (tok);

	DRV_PRINT (DRV_DEBUG_LOAD, ("MBLK Count %d Cluster Count %d\n",
			pDrvCtrl->numMblks, pDrvCtrl->numClusters));

	for (i = 0; i < NUM_CLUSTER_POOLS; i++)
	{
		/* Cluster size value */
		tok = strtok_r (NULL, ":", &pHolder);
		if (tok == NULL)
			break;
		pDrvCtrl->clSizes[i].clSize = atoi (tok);
		/* Number of MBLK's for the clusters */
		tok = strtok_r (NULL, ":", &pHolder);
		if (tok == NULL)
			break;
		pDrvCtrl->clSizes[i].clNum = atoi (tok);

		DRV_PRINT (DRV_DEBUG_LOAD, ("Cluster %d Size %d Count %d\n", i,
				pDrvCtrl->clSizes[i].clSize, pDrvCtrl->clSizes[i].clNum));
	}

	DRV_PRINT (DRV_DEBUG_LOAD, ("Processed all arugments\n"));

	free (savedInitString);

	return OK;
}

/******************************************************************************
*
*
* gnlInitMem - initialize memory
*
* Using data in the control structure, setup and initialize the memory
* areas needed.  If the memory address is not already specified, then allocate
* cache safe memory.
*
* RETURNS: OK or ERROR
*/

LOCAL STATUS gnlInitMem (GNLDEV_OBJ * pDrvCtrl)
{
	int i;

	/* Copy the global structures to local structures. */

	for (i = 0; i < NUM_CLUSTER_POOLS; i++)
		pDrvCtrl->clDescTbl[i].clSize = pDrvCtrl->clSizes[i].clSize;

	/* Allocate receive buffers from our own private pool. */

	for (i = 0; i < NUM_CLUSTER_POOLS; i++)
		pDrvCtrl->clDescTbl[i].clNum = pDrvCtrl->clSizes[i].clNum;

	/* Allocate the number of mblk headers and cluster headers. */
	pDrvCtrl->mclConfig.clBlkNum = pDrvCtrl->numClusters;
	pDrvCtrl->mclConfig.mBlkNum = pDrvCtrl->numMblks;

	pDrvCtrl->mclConfig.memSize =
		(pDrvCtrl->mclConfig.mBlkNum * (MSIZE + sizeof (long))) +
		(pDrvCtrl->mclConfig.clBlkNum * (CL_BLK_SZ + sizeof (long)));

	DRV_PRINT (DRV_DEBUG_LOAD, ("pDrvCtrl->mclConfig.memSize %d\n",
			pDrvCtrl->mclConfig.memSize));

	pDrvCtrl->mclConfig.memArea =
		(char *) memalign (sizeof (long), pDrvCtrl->mclConfig.memSize);

	if (pDrvCtrl->mclConfig.memArea == NULL)
		return (ERROR);

	if (!CACHE_DMA_IS_WRITE_COHERENT ())
	{
		DRV_PRINT (DRV_DEBUG_LOAD,
			("gnl: device requires cache coherent memory\n"));
		return (ERROR);
	}

	pDrvCtrl->cacheFuncs = cacheDmaFuncs;

	/*
	 * Only allocate cluster blocks if there is a value. This could
	 * be that clusters are not allocated here, but the mblk headers
	 * are used from this driver for clusters in a driver below this one.
	 */
	if (pDrvCtrl->mclConfig.clBlkNum)
	{
		for (i = 0; i < NUM_CLUSTER_POOLS; i++)
		{
			pDrvCtrl->clDescTbl[i].memSize =
				(pDrvCtrl->clDescTbl[i].clNum * (pDrvCtrl->clSizes[i].clSize +
					8)) + sizeof (int);

			DRV_PRINT (DRV_DEBUG_LOAD, ("pDrvCtrl->clDescTbl[%d].memSize %d\n",
					i, pDrvCtrl->clDescTbl[i].memSize));

			pDrvCtrl->clDescTbl[i].memArea =
				(char *) cacheDmaMalloc (pDrvCtrl->clDescTbl[i].memSize);
			if ((int) pDrvCtrl->clDescTbl[i].memArea == NULL)
			{
				DRV_PRINT (DRV_DEBUG_LOAD, ("system memory unavailable\n"));
				return (ERROR);
			}
		}
	}

	if ((pDrvCtrl->endObj.pNetPool = calloc (1, sizeof (NET_POOL))) == NULL)
		return (ERROR);

	if (netPoolInit (pDrvCtrl->endObj.pNetPool, &pDrvCtrl->mclConfig,
			&pDrvCtrl->clDescTbl[0], NUM_CLUSTER_POOLS, NULL) == ERROR)
	{
		DRV_PRINT (DRV_DEBUG_LOAD, ("Could not init buffering\n"));
		return (ERROR);
	}

	/* Store the cluster pool id as others need it later. */
	for (i = 0; i < NUM_CLUSTER_POOLS; i++)
	{
		pDrvCtrl->pClPoolId[i] =
			clPoolIdGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->clSizes[i].clSize,
			FALSE);

		if (pDrvCtrl->pClPoolId[i] == NULL)
			return (ERROR);
	}

	pgl_NetPool = pDrvCtrl->endObj.pNetPool;
	pgl_pclPoolId = pDrvCtrl->pClPoolId[0];	/*lirui add 2003-1-9 for debug */
	return OK;
}

/*****************************************************************************
*
* gnlEndStart - Entry point to start the rest of the system.
*
* This function calls swDrv interface routines to initialize the switch
* driver.
*
* RETURNS: OK or ERROR
*
* ERRNO: N/A
*/

LOCAL STATUS gnlEndStart (END_OBJ * pEnd)
{
	GNLDEV_OBJ *pDrvCtrl = (GNLDEV_OBJ *) pEnd->devObject.pDevice;
	STATUS rc;

}

/*****************************************************************************
*
* gnlEndInt - handle receive interrupts.
*
* DESCRIPTION
* This routine is called at interrupt level in response to an interrupt from
* the controller. This routine supports the swDrv interrupt routine in
* passing the packet up to the next level.
*
* RETURNS: N/A
*/

STATUS gnlEndInt (END_OBJ * pEnd, M_BLK_ID pMblk, void *pSpare)
{
	GNLDEV_OBJ *pDrvCtrl;
	int oldLevel;

	dbgPrintf (0, ("gnlEndInt: pMblk %08x\n", (UINT) pMblk));
/*logMsg("gnlEndInt: pMblk %08x\n", (UINT)pMblk,0,0,0,0,0); *//* ofir */

	if ((pMblk->m_data == NULL) || ((int) pMblk->m_data & 1))
	{
		printf ("gnlEndInt(): m_data is invalid\r\n");
		taskSuspend (taskIdSelf ());
	}

#ifdef ENABLE_PKT_RECV
	/* Lock out interrupts. */
	oldLevel = intLock ();
	pDrvCtrl = (GNLDEV_OBJ *) pEnd->devObject.pDevice;

	pMblk->m_nextpkt = NULL;
	if (pDrvCtrl->recvQueueHead == NULL)
		pDrvCtrl->recvQueueHead = pMblk;
	else
		pDrvCtrl->recvQueueTail->m_nextpkt = pMblk;
	pDrvCtrl->recvQueueTail = pMblk;
	pDrvCtrl->recvCnt++;

	dbgPrintf (0, ("gnlEndInt: pMblk Queued\n"));
/* logMsg("gnlEndInt: pMblk Queued\n", 0,0,0,0,0,0); *//* ofir */
	if (!(pDrvCtrl->flags & LS_RCV_HANDLING))
	{

		/* Set the interlocking flag */
		pDrvCtrl->flags |= LS_RCV_HANDLING;

		intUnlock (oldLevel);

		dbgPrintf (0, ("gnlEndInt: Call netJobAdd\n"));
/*logMsg("gnlEndInt: Call netJobAdd\n", 0,0,0,0,0,0); *//* ofir */

		if (netJobAdd ((FUNCPTR) gnlEndRecvPacket, (int) pEnd, (int) pSpare, 0,
				0, 0) != OK)
		{
			dbgPrintf (0, ("gnlEndInt: netJobAdd Failed\n"));
/*logMsg("gnlEndInt: netJobAdd Failed\n", 0,0,0,0,0,0); *//* ofir */
			oldLevel = intLock ();
			while ((pMblk = pDrvCtrl->recvQueueHead))
			{
				pDrvCtrl->recvQueueHead = pMblk->m_nextpkt;
				pMblk->m_nextpkt = NULL;
				netMblkClChainFree (pMblk);
			}
			pDrvCtrl->recvQueueHead = NULL;
			pDrvCtrl->recvQueueTail = NULL;
			pDrvCtrl->recvCnt = NULL;
			intUnlock (oldLevel);
		}
	}
	else
		intUnlock (oldLevel);
#else
	/* Lock out interrupts. */
	oldLevel = intLock ();
	pDrvCtrl = (GNLDEV_OBJ *) pEnd->devObject.pDevice;

	while ((pMblk = pDrvCtrl->recvQueueHead))
	{
		pDrvCtrl->recvQueueHead = pMblk->m_nextpkt;
		pMblk->m_nextpkt = NULL;
		netMblkClChainFree (pMblk);
	}
	pDrvCtrl->recvQueueHead = NULL;
	pDrvCtrl->recvQueueTail = NULL;
	pDrvCtrl->recvCnt = NULL;

	intUnlock (oldLevel);
#endif /* ENABLE_PKT_RECV */

	dbgPrintf (0, ("gnlEndInt: Exit\n"));

	return OK;
}

/*****************************************************************************
*
* gnlEndRecvPacket - process the next incoming packet
*
* DESCRIPTION
* Handle one incoming packet from the swDrv routine.
*
* RETURNS: OK
*/
LOCAL STATUS gnlEndRecvPacket (END_OBJ * pEnd, int param2,	/* pSpare value for VLAN ID */
	int param3, int param4, int param5)
{
	GNLDEV_OBJ *pDrvCtrl = (GNLDEV_OBJ *) pEnd->devObject.pDevice;
	int oldLevel;
	M_BLK_ID pMblk;
	void *pSpare = (void *) param2;

	DRV_PRINT (DRV_DEBUG_RX, ("gnlEndRecvPacket: Entry\n"));
	for (;;)
	{							/*lirui 2001-12-20 */
		oldLevel = intLock ();

		if ((pMblk = pDrvCtrl->recvQueueHead) == NULL)
		{
			pDrvCtrl->flags &= ~LS_RCV_HANDLING;
			intUnlock (oldLevel);
			break;
		}
		pDrvCtrl->recvQueueHead = pMblk->m_nextpkt;
		pMblk->m_nextpkt = NULL;
		pDrvCtrl->recvCnt--;

		if (pDrvCtrl->recvQueueTail == pMblk)
			pDrvCtrl->recvQueueTail = NULL;

		intUnlock (oldLevel);

		if ((pMblk->m_data == NULL) || ((int) pMblk->m_data & 1))
		{
			/* printf("gnlEndRecvPacket(): m_data is invalid\r\n"); */
			taskSuspend (taskIdSelf ());
		}

		DRV_PRINT (DRV_DEBUG_RX, ("gnlEndREcvPacket: pMblk %08lx\n",
				(ulong_t) pMblk));

		if (pDrvCtrl->endObj.pMib2Tbl != NULL)
		{
			pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn (pDrvCtrl->endObj.pMib2Tbl,
				M2_PACKET_IN, pMblk->mBlkHdr.mData, pMblk->mBlkHdr.mLen);
		}

/*SUBEND_RCV_RTN_CALL(pEnd, pMblk, 0, 0, 0, pSpare); *//*lirui 2001-10-29 */

		END_RCV_RTN_CALL (pEnd, pMblk);
	}							/*lirui 2001-12-20 */
	DRV_PRINT (DRV_DEBUG_RX, ("gnlEndReceivePacket: Exit\n"));

	return (OK);
}

/*****************************************************************************
*
* _gnlNptSend - convenience function for gnlNptSend 
*
* DESCRIPTION
* Network protocol toolkit send routine.
*
* RETURNS: ERROR or the status from the sendRtn() function.
*/

LOCAL STATUS _gnlNptSend (END_OBJ * pEnd, M_BLK_ID pMblk,	/* Data to send */
	char *dstMacAddr,			/* destination MAC address */
	long netType,				/* type of the network service invoking us */
	void *pSpare,				/* any optional data passed */
	FUNCPTR sendRtn				/* send routine to call; regular or polled-mode */
	)
{
	GNLDEV_OBJ *pDrvCtrl = (GNLDEV_OBJ *) pEnd->devObject.pDevice;

	return ((*sendRtn) (pDrvCtrl, pMblk, pSpare));
}

/*****************************************************************************
*
* gnlNptSend - output packet to network interface device
*
* DESCRIPTION
* This routine takes a M_BLK_ID, the destination MAC address and the type
* of the network service requesting the send and forms the complete MAC packet
* before calling the old END type send routine to send the packet on the wire.
*
* muxTkSend() calls this routine each time it wants to send a packet.
* Errors are detected at interrupt level.
*
* RETURNS: OK or ERROR.
*/

LOCAL STATUS gnlNptSend (END_OBJ * pEnd,	/* pointer to END_OBJ structure */
	M_BLK_ID pMblk,				/* Data to send */
	char *dstMacAddr,			/* destination MAC address */
	long netType,				/* type of the network service invoking us */
	void *pSpare				/* any optional data passed */
	)
{
	return _gnlNptSend (pEnd, pMblk, dstMacAddr, netType, pSpare, gnlEndSend);
}

/*****************************************************************************
*
* gnlEndSend - the driver send routine
*
* DESCRIPTION
* This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
* The buffer must already have the addressing information properly installed
* in it.  This is done by a higher layer.  The last arguments are a free
* routine to be called when the device is done with the buffer and a pointer
* to the argument to pass to the free routine.  
*
* RETURNS: OK or ERROR.
*/

LOCAL STATUS gnlEndSend (END_OBJ * pEnd,	/* pointer to END_OBJ structure */
	M_BLK_ID pMblk,				/* data to send */
	void *pSpare)
{
	GNLDEV_OBJ *pDrvCtrl = (GNLDEV_OBJ *) pEnd->devObject.pDevice;
	STATUS rc;

	dbgPrintf (2, ("gnl%d: pSpare %08lx\n\r", pDrvCtrl->unit,
			(ulong_t) pSpare));
	/*
	 * Obtain exclusive access to transmitter.  This is necessary because
	 * we might have more than one stack transmitting at once.
	 */
	if (!(pDrvCtrl->flags & LS_POLLING))
		END_TX_SEM_TAKE (pEnd, WAIT_FOREVER);

	DRV_PRINT (DRV_DEBUG_TX, ("gnlEndSend%d: pSpare %08x\n", pDrvCtrl->unit,
			(int) pSpare));

#ifdef ENABLE_PKT_SEND
	rc = gnlPktSend (pDrvCtrl->pHwDrvCtrl, pMblk, pSpare);
#else
	netMblkClChainFree (pMblk);
#endif /* ENABLE_PKT_SEND */

	CACHE_PIPE_FLUSH ();

	if (!(pDrvCtrl->flags & LS_POLLING))
		END_TX_SEM_GIVE (pEnd);

	dbgPrintf (2, ("gnl%d: Exit\n\r", pDrvCtrl->unit));

	return rc;
}

/*****************************************************************************
*
* gnlEndIoctl - the driver I/O control routine
*
* DESCRIPTION
* Process an ioctl request.
*
* RETURNS: OK or ERROR
*/

LOCAL int gnlEndIoctl (END_OBJ * pEnd,	/* pointer to END_OBJ structure */
	int cmd, caddr_t data)
{
	int error;
	long value = 0;
	GNLDEV_OBJ *pDrvCtrl;
	char ifName[16];
	struct ifnet *pIf;

	pDrvCtrl = (GNLDEV_OBJ *) pEnd->devObject.pDevice;

	error = OK;

	switch (cmd)
	{
		case EIOCSADDR:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: EIOCSADDR\n"));
			break;

		case EIOCGADDR:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: EIOCGADDR\n"));
			/*lirui add 2003-1-28 for cpu mac */
			if (data == NULL)
				return (EINVAL);
			bcopy ((char *) &pEnd->mib2Tbl.ifPhysAddress.phyAddress,
				(char *) data, 6);
			/*end lirui add 200301028 */
			break;

		case EIOCSFLAGS:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: EIOCSFLAGS\n"));
			value = (long) data;
			if (value < 0)
			{
				value = -value;
				value--;		/* HELP: WHY ??? */
				END_FLAGS_CLR (pEnd, value);
			}
			else
			{
				END_FLAGS_SET (pEnd, value);
			}
			gnlEndConfig (pEnd);
			break;
		case EIOCGFLAGS:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: EIOCGFLAGS\n"));
			*(int *) data = END_FLAGS_GET (pEnd);
			break;

		case EIOCPOLLSTART:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: EIOCPOLLSTART\n"));
			return (EINVAL);
			break;

		case EIOCPOLLSTOP:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: EIOCPOLLSTOP\n"));
			return (EINVAL);
			break;

		case EIOCGMIB2:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: EIOCGMIB2\n"));
			if (data == NULL)
				return (EINVAL);
			bcopy ((char *) &pEnd->mib2Tbl, (char *) data,
				sizeof (pEnd->mib2Tbl));
			break;
		case EIOCGFBUF:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: EIOCGFBUF\n"));
			if (data == NULL)
				return (EINVAL);
			*(int *) data = HW_MIN_FBUF;
			break;
		case EIOCGMWIDTH:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: EIOCGMWIDTH\n"));
			if (data == NULL)
				return (EINVAL);
			*(int *) data = 1;
			break;
		case EIOCGHDRLEN:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: EIOCGHDRLEN\n"));
			if (data == NULL)
				return (EINVAL);
			/* TODO: Need to change this to use idb requests. */
			*(int *) data = 14;
			break;
		case EIOCMULTIADD:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: EIOCMULTIADD\n"));
			error = EINVAL;
			/* error = gnlEndMCastAddrAdd (pDrvCtrl, (char *) data); */
			break;
		case EIOCMULTIDEL:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: EIOCMULTIDEL\n"));
			error = EINVAL;
			/* error = gnlEndMCastAddrDel (pDrvCtrl, (char *) data); */
			break;
		case EIOCMULTIGET:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: EIOCMULTIGET\n"));
			error = EINVAL;
			/* error = gnlEndMCastAddrGet (pDrvCtrl, (MULTI_TABLE *) data); */
			break;
		case EIOCGHWAPI:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: EIOCGHWAPI\n"));
			if (data == NULL)
				return (EINVAL);
			pDrvCtrl = (GNLDEV_OBJ *) pEnd->devObject.pDevice;
			bcopy ((char *) &pDrvCtrl->pHwDrvCtrl, (char *) data,
				sizeof (void *));
			break;
		default:
			DRV_PRINT (DRV_DEBUG_IOCTL, ("gnlIoctl: ERROR %08x\n", cmd));
			error = EINVAL;

⌨️ 快捷键说明

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