📄 gnlend.c
字号:
} */
/* 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 + -