ixethaccdataplane.c

来自「有关ARM开发板上的IXP400网络驱动程序的源码以。」· C语言 代码 · 共 2,320 行 · 第 1/5 页

C
2,320
字号
		     "ixEthAccRxPortFreeReplenish:Error: %u\n", 		     qStatus, 0, 0, 0, 0, 0);	    }        }    }    else     {	RX_INC(portId,rxUnexpectedError);	IX_ETH_ACC_FATAL_LOG(	    "ixEthAccRxPortFreeReplenish:Error: qStatus = %u\n", 	    (UINT32)qStatus, 0, 0, 0, 0, 0);        return(IX_ETH_ACC_FAIL);    }    return (IX_ETH_ACC_SUCCESS);}IX_ETH_ACC_PUBLICIxEthAccStatus ixEthAccTxSchedulingDisciplineSetPriv(IxEthAccPortId portId, 						 IxEthAccSchedulerDiscipline						 sched){	    if (!IX_ETH_ACC_IS_PORT_VALID(portId))    {	return (IX_ETH_ACC_INVALID_PORT);    }    if (!IX_ETH_IS_PORT_INITIALIZED(portId))    {	return (IX_ETH_ACC_PORT_UNINITIALIZED);    }    if (sched != FIFO_PRIORITY && sched != FIFO_NO_PRIORITY)    {	return (IX_ETH_ACC_INVALID_ARG);    }    ixEthAccPortData[portId].ixEthAccTxData.schDiscipline = sched;    return (IX_ETH_ACC_SUCCESS);}IX_ETH_ACC_PUBLICIxEthAccStatus ixEthAccRxSchedulingDisciplineSetPriv(IxEthAccSchedulerDiscipline						 sched){    int port;    /* cannot change the scheduling discipline while any port is active */    for (port = 0; port < IX_ETH_ACC_NUMBER_OF_PORTS; port++)    {        if (ixEthAccMacState[port].portDisableState == ACTIVE)        {            return IX_ETH_ACC_FAIL;        }    }    switch(sched)    {        case  FIFO_PRIORITY:            /* priority scheduling discipline not supported on IXP42X A0 HW */            if( (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X == ixFeatureCtrlDeviceRead ())                && (IX_FEATURE_CTRL_SILICON_TYPE_A0 ==               (ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK)))            {	        return (IX_ETH_ACC_FAIL);            }             if(ixEthAccDataInfo.rxQMCbTypeSet == NORMAL)            {                ixEthAccQMgrRxCallbacksRegister(                             (IxQMgrCallback)ixEthRxPriorityPoll,                             IX_ETH_ACC_MAX_RX_MBUF_CONSUME_PER_CALLBACK);            }            else if(ixEthAccDataInfo.rxQMCbTypeSet == MULTIBUFFER)            {                ixEthAccQMgrRxCallbacksRegister(                             (IxQMgrCallback)ixEthRxMultiBufferPriorityPoll,                             IX_ETH_ACC_MAX_RX_MBUF_CONSUME_PER_CALLBACK);            }            /* enable sticky interrupts */            ixQMgrStickyInterruptRegEnable();            break;        case FIFO_NO_PRIORITY:            if(ixEthAccDataInfo.rxQMCbTypeSet == NORMAL)            {                ixEthAccQMgrRxCallbacksRegister(ixEthRxFrameQMCallback,0);                                         }            else if(ixEthAccDataInfo.rxQMCbTypeSet == MULTIBUFFER)            {                ixEthAccQMgrRxCallbacksRegister(ixEthRxMultiBufferQMCallback,0);            }            break;        default:	    return (IX_ETH_ACC_INVALID_ARG);    }    ixEthAccDataInfo.schDiscipline = sched;    return (IX_ETH_ACC_SUCCESS);}/** * @fn ixEthRxFrameProcess(IxEthAccPortId portId, IX_OSAL_MBUF *mbufPtr) * * @brief process incoming frame :  * * @param @ref IxQMgrCallback IxQMgrMultiBufferCallback * * @return none * * @internal * */IX_ETH_ACC_PRIVATE BOOL ixEthRxFrameProcess(IxEthAccPortId portId, IX_OSAL_MBUF *mbufPtr){	    UINT32 flags;    IxEthDBStatus result;#ifndef NDEBUG    /* Prudent to at least check the port is within range */    if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS)    {	ixEthAccDataStats.unexpectedError++;	IX_ETH_ACC_FATAL_LOG(	     "ixEthRxFrameProcess: Illegal port: %u\n", 	     (UINT32)portId, 0, 0, 0, 0, 0);	return FALSE;    }#endif    /* convert fields from mbuf header */    ixEthAccMbufFromRxQ(mbufPtr);    /* check about any special processing for this frame */    flags = IX_ETHACC_NE_FLAGS(mbufPtr);    if ((flags & (IX_ETHACC_NE_FILTERMASK | IX_ETHACC_NE_NEWSRCMASK)) == 0)    {	/* "best case" scenario : nothing special to do for this frame */	return TRUE;    }    /* if a new source MAC address is detected by the NPE,      * update IxEthDB with the portId and the MAC address.     */    if ((flags & IX_ETHACC_NE_NEWSRCMASK & ixEthAccNewSrcMask) != 0)    {        result = ixEthDBFilteringDynamicEntryProvision(portId,                          (IxEthDBMacAddr *) IX_ETHACC_NE_SOURCEMAC(mbufPtr));	if (result != IX_ETH_DB_SUCCESS && result != IX_ETH_DB_FEATURE_UNAVAILABLE)	{            if ((ixEthAccMacState[portId].portDisableState == ACTIVE) && (result != IX_ETH_DB_BUSY))            {	        RX_STATS_INC(portId, rxUnexpectedError);                IX_ETH_ACC_FATAL_LOG("ixEthRxFrameProcess: Failed to add source MAC to the Learning/Filtering database\n", 0, 0, 0, 0, 0, 0);             }            else            {                /* we expect this to fail during PortDisable, as EthDB is disabled for                 * that port and will refuse to learn new addresses 		 */            }	}	else	{	    RX_STATS_INC(portId, rxUnlearnedMacAddress);	}    }    /* check if this frame should have been filtered     * by the NPE and take the appropriate action      */    if (((flags & IX_ETHACC_NE_FILTERMASK) != 0)        && (ixEthAccMacState[portId].portDisableState == ACTIVE))    {        /* If the mbuf was allocated with a small data size, or the current data pointer is not         * within the allocated data area, then the buffer is non-standard and has to be          * replenished with the minimum size only         */        if( (IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr) < IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN)           || ((UINT8 *)IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr) > IX_OSAL_MBUF_MDATA(mbufPtr))           || ((UINT8 *)(IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr) +              IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr))               < IX_OSAL_MBUF_MDATA(mbufPtr)) )        {            /* set to minimum length */            IX_OSAL_MBUF_MLEN(mbufPtr) = IX_OSAL_MBUF_PKT_LEN(mbufPtr) =                IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN;        }        else        {            /* restore original length */            IX_OSAL_MBUF_MLEN(mbufPtr) = IX_OSAL_MBUF_PKT_LEN(mbufPtr) =                ( IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr) -                 (IX_OSAL_MBUF_MDATA(mbufPtr) - (UINT8 *)IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr)) );        }        /* replenish from here */        if (ixEthAccPortRxFreeReplenish(portId, mbufPtr) != IX_ETH_ACC_SUCCESS)        {                IX_ETH_ACC_FATAL_LOG("ixEthRxFrameProcess: Failed to replenish with filtered frame\                                      on port %d\n", portId, 0, 0, 0, 0, 0);        }        RX_STATS_INC(portId, rxFiltered);        /* indicate that frame should not be subjected to further processing */        return FALSE;    }    return TRUE;}/** * @fn ixEthRxPriorityPoll  * * @brief RX routine to get limited entries from priority queues * * Routine may be called by user, or used as RX QM callback. * Receive queues are processed in priority order. * * @param reserved : placeholder for QM callback usage, ignored *        maxQEntries : maximum number of q entries to process  * * @return : number of frames processed * * @internal * * Design notes :  * While processing the entry X, entry X+1 is preloaded * into memory to reduce the number of stall cycles * */UINT32 ixEthRxPriorityPoll(UINT32 reserved, UINT32 maxQEntries){	    IX_OSAL_MBUF    *mbufPtr;    IX_OSAL_MBUF    *nextMbufPtr;    IxQMgrQId  qId;    UINT32     qIndex;    UINT32     qEntry;    UINT32     nextQEntry;    UINT32     *qEntryPtr;    UINT32     portId;    UINT32     destPortId;    UINT32     rxQReadStatus;    UINT32     qEntriesProcessed = 0;    /*     * Design note : entries are read in a buffer, This buffer contains     * an extra zeroed entry so the loop will     * always terminate on a null entry, whatever the result of Burst read is.     */    UINT32 rxQEntry[IX_ETH_ACC_MAX_RX_MBUF_CONSUME_PER_CALLBACK + 1];        /*      * Indication of the number of times the callback is used.     */    IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackCounter);    for(qId = ixEthAccDataInfo.rxQueues[qIndex = 0];         qId < IX_QMGR_MAX_NUM_QUEUES && qEntriesProcessed < maxQEntries;         qId = ixEthAccDataInfo.rxQueues[++qIndex])     {        UINT32 qReadCount = maxQEntries - qEntriesProcessed;	/* 	 * Indication of the number of times the queue is drained	 */	IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackBurstRead);	/* ensure the last entry of the array contains a zeroed value */	qEntryPtr = rxQEntry;	qEntryPtr[qReadCount] = 0;		rxQReadStatus = ixQMgrQBurstRead(qId, 		 qReadCount, 		 qEntryPtr);#ifndef NDEBUG	if ((rxQReadStatus != IX_QMGR_Q_UNDERFLOW)	    && (rxQReadStatus != IX_SUCCESS))	{	    ixEthAccDataStats.unexpectedError++;	    /*major error*/	    IX_ETH_ACC_FATAL_LOG(		"ixEthRxPriorityPoll:Error: %u\n", 		(UINT32)rxQReadStatus, 0, 0, 0, 0, 0);	    return qEntriesProcessed;	}#endif	/* convert and preload the next entry	 * (the conversion function takes care about null pointers which	 * are used to mark the end of the loop)	 */	nextQEntry = *qEntryPtr;	nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry, 			  IX_ETHNPE_QM_Q_RXENET_ADDR_MASK);	while(nextQEntry != 0)	{	    /* get the next entry */	    qEntry = nextQEntry;	    mbufPtr = nextMbufPtr;#ifndef NDEBUG	    if (mbufPtr == NULL)	    {		ixEthAccDataStats.unexpectedError++;		IX_ETH_ACC_FATAL_LOG(		    "ixEthRxPriorityPoll: Null Mbuf Ptr\n",		    0, 0, 0, 0, 0, 0);		return qEntriesProcessed;	    }#endif            	    /* convert the next entry	     * (the conversion function takes care about null pointers which	     * are used to mark the end of the loop)	     */	    nextQEntry = *(++qEntryPtr);	    nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry, 			      IX_ETHNPE_QM_Q_RXENET_ADDR_MASK);	    /*	     * Get Port ID from message.	     */	    	    portId = IX_ETHNPE_NODE_AND_PORT_TO_PHYSICAL_ID(IX_ETHNPE_QM_Q_RXENET_NPEID_VAL(qEntry),IX_ETHNPE_QM_Q_PID_VAL(qEntry));	    /* process frame, check the return code and skip the remaining of	     * the loop if the frame is to be filtered out 	     */            if (ixEthRxFrameProcess(portId, mbufPtr))            {	        /* destination portId for this packet */	        destPortId = IX_ETHACC_NE_DESTPORTID(mbufPtr);                if (destPortId != IX_ETH_DB_UNKNOWN_PORT)                {                    destPortId = IX_ETHNPE_LOGICAL_ID_TO_PHYSICAL_ID(destPortId);                }	        /* 	        * increment priority stats 	        */	        RX_STATS_INC(portId,rxPriority[IX_ETHACC_NE_QOS(mbufPtr)]);	        /*	        * increment callback count stats	        */	        RX_STATS_INC(portId,rxFrameClientCallback);	        /* 	        * Call user level callback.	        */	        ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn(		    ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag, 		    mbufPtr,		    destPortId);                /*increment total number of entries processed*/                qEntriesProcessed++;            }	}    }    return qEntriesProcessed;}/** * @fn ixEthRxMultiBufferPriorityPoll  * * @brief RX routine to get limited entries from priority queues * * Routine may be called by user, or used as RX QM callback. * Receive queues are processed in priority order. * Buffers are passed as an array to the user callback * * @param reserved : placeholder for QM callback usage, ignored *        maxQEntries : maximum number of q entries to process  * * @return : number of frames processed * * @internal * * Design notes :  * While processing the entry X, entry X+1 is preloaded * into memory to reduce the number of stall cycles * */UINT32 ixEthRxMultiBufferPriorityPoll(UINT32 reserved, UINT32 maxQEntries){	    IX_OSAL_MBUF    *mbufPtr;    IX_OSAL_MBUF    *nextMbufPtr;    IxQMgrQId  qId;    UINT32     qIndex;    UINT32     qEntry;    UINT32     nextQEntry;    UINT32     *qEntryPtr;    UINT32     portId;    UINT32     rxQReadStatus;    UINT32     qEntriesProcessed = 0;    /*     * Design note : entries are read in a buffer, This buffer contains     * an extra zeroed entry so the loop will     * always terminate on a null entry, whatever the result of Burst read is.     */    UINT32 rxQEntry[IX_ETH_ACC_MAX_RX_MBUF_CONSUME_PER_CALLBACK + 1];    static IX_OSAL_MBUF *rxMbufPortArray[IX_ETH_ACC_NUMBER_OF_PORTS][IX_ETH_ACC_MAX_RX_MBUF_CONSUME_PER_CALLBACK + 1];    IX_OSAL_MBUF **rxMbufPtr[IX_ETH_ACC_NUMBER_OF_PORTS];    for (portId = 0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++)    {        rxMbufPtr[portId] = rxMbufPortArray[portId];    }        /*      * Indication of the number of times the callback is used.     */    IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackCounter);    for(qId = ixEthAccDataInfo.rxQueues[qIndex = 0];         qId < IX_QMGR_MAX_NUM_QUEUES && qEntriesProcessed < maxQEntries;         qId = ixEthAccDataInfo.rxQueues[++qIndex])     {        UINT32 qReadCount = maxQEntries - qEntriesProcessed;	/* 	 * Indication of the number of times the queue is drained	 */	IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackBurstRead);	/* ensure the last entry of the array contains a zeroed value */	qEntryPtr = rxQEntry;	qEntryPtr[qReadCount] = 0;		rxQReadStatus = ixQMgrQBurstRead(qId, 		 qReadCount, 		 qEntryPtr);#ifndef NDEBUG	if ((rxQReadStatus != IX_QMGR_Q_UNDERFLOW)	    && (rxQReadStatus != IX_SUCCESS))	{	    ixEthAccDataStats.unexpectedError++;	    /*major error*/	    IX_ETH_ACC_FATAL_LOG(		"ixEthRxMultiBufferPriorityPoll:Error: %u\n", 		(UINT32)rxQReadStatus, 0, 0, 0, 0, 0);	    return qEntriesProcessed;	}#endif	/* convert and preload the next entry	 * (the conversion function takes care about null pointers which	 * are used to mark the end of the loop)	 */	nextQEntry = *qEntryPtr;	nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry, 			  IX_ETHNPE_QM_Q_RXENET_ADDR_MASK);	while(nextQEntry != 0)	{	    /* get the next entry */	    qEntry = nextQEntry;	    mbufPtr = nextMbufPtr;

⌨️ 快捷键说明

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