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

📄 ixethaccdataplane.c

📁 有关ARM开发板上的IXP400网络驱动程序的源码以。
💻 C
📖 第 1 页 / 共 5 页
字号:
	    IX_ETHACC_NE_LEN(ptr) = IX_OSAL_SWAP_BE_SHARED_LONG(len);	    /* flush shared header after all address conversions */	    IX_ETHACC_NE_CACHE_FLUSH(ptr);	    /* remove shared header cache line */	    IX_ETHACC_NE_CACHE_INVALIDATE(ptr);	    /* next mbuf in the chain */	    ptr = nextPtr;	}	while(ptr != NULL);    }    /* virt2phys mbuf itself */    qbuf = (UINT32)IX_OSAL_MMU_VIRT_TO_PHYS(		  IX_ETHACC_NE_SHARED(mbuf));    /* Ensure the bits which are reserved to exchange information with     * the NPE are cleared      *     * If the mbuf address is not correctly aligned, or from an     * incompatible memory range, there is no point to continue     */    IX_OSAL_ENSURE(((qbuf & ~IX_ETHNPE_QM_Q_RXENET_ADDR_MASK) == 0), 	      "Invalid address range");    return qbuf;}/* Convert the mbuf header after NPE transmission  * Since there is nothing changed by the NPE, there is no need  * to process anything but the update of internal stats * when they are enabled*/PRIVATE void ixEthAccMbufFromTxQ(IX_OSAL_MBUF *mbuf){#ifndef NDEBUG    /* test for unchained mbufs */    if (IX_ETHACC_NE_NEXT(mbuf) == 0)    {	/* unchained mbufs : update the stats */	IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedTxDoneMBufs);    }    else    {	/* chained mbufs : walk the chain and update the stats */	IX_OSAL_MBUF *ptr = mbuf;	do	{	    IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedTxDoneMBufs);	    ptr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr);	}	while (ptr != NULL);    }#endif}/* Convert the mbuf header after NPE reception */PRIVATE void ixEthAccMbufFromRxQ(IX_OSAL_MBUF *mbuf){    UINT32 len;    /* endianess swap for tci and flags       note: this is done only once, even for chained buffers */    IX_ETHACC_NE_FLAGS(mbuf)   = IX_OSAL_SWAP_BE_SHARED_SHORT(IX_ETHACC_NE_FLAGS(mbuf));    IX_ETHACC_NE_VLANTCI(mbuf) = IX_OSAL_SWAP_BE_SHARED_SHORT(IX_ETHACC_NE_VLANTCI(mbuf));    /* test for unchained mbufs */    if (IX_ETHACC_NE_NEXT(mbuf) == 0)    {	/* unchained mbufs */	IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedRxMBufs);    	/* get the frame length. it is the same than the buffer length */	len = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(mbuf));	len &= IX_ETHNPE_ACC_PKTLENGTH_MASK;	IX_OSAL_MBUF_PKT_LEN(mbuf) = IX_OSAL_MBUF_MLEN(mbuf) = len;	        /* clears the next packet field */	IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbuf) = NULL;    }    else    {	IX_OSAL_MBUF *ptr = mbuf;	IX_OSAL_MBUF *nextPtr;	UINT32 frmLen;	/* convert the frame length */	frmLen = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(mbuf));	IX_OSAL_MBUF_PKT_LEN(mbuf) = (frmLen & IX_ETHNPE_ACC_PKTLENGTH_MASK);	        /* chained mbufs */	do	{	    IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedRxMBufs);    	    /* convert the length */	    len = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(ptr));	    IX_OSAL_MBUF_MLEN(ptr) = (len >> IX_ETHNPE_ACC_LENGTH_OFFSET);	                /* get the next pointer */	     	    PTR_NPE2VIRT(IX_OSAL_MBUF *,IX_ETHACC_NE_NEXT(ptr), nextPtr);	    if (nextPtr != NULL)	    {		nextPtr = (IX_OSAL_MBUF *)((UINT8 *)nextPtr - offsetof(IX_OSAL_MBUF,ix_ne));	    }	    /* set the next pointer */	    IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr) = nextPtr;	    	    /* move to the next buffer */	    ptr = nextPtr;	}	while (ptr != NULL);    }}/* write to qmgr if possible and report an overflow if not possible  * Use a fast lock to protect the queue write. * This way, the tx feature is reentrant. */PRIVATE IX_STATUSixEthAccQmgrLockTxWrite(IxEthAccPortId portId, UINT32 qBuffer){    IX_STATUS qStatus;    /* Try a lock on this port's TX queue      */    if (ixOsalFastMutexTryLock(&txWriteMutex[portId]) \         == IX_SUCCESS)    {	qStatus = ixQMgrQWrite(	       IX_ETH_ACC_PORT_TO_TX_Q_ID(portId),	       &qBuffer);#ifndef NDEBUG  	if (qStatus != IX_SUCCESS)	{	    TX_STATS_INC(portId, txOverflow);   	}#endif	ixOsalFastMutexUnlock(&txWriteMutex[portId]);    }    else    {	TX_STATS_INC(portId, txLock);	qStatus = IX_QMGR_Q_OVERFLOW;    }    return qStatus;}/* write to qmgr if possible and report an overflow if not possible  * Use a fast lock to protect the queue write. * This way, the Rx feature is reentrant. */PRIVATE IX_STATUSixEthAccQmgrLockRxWrite(IxEthAccPortId portId, UINT32 qBuffer){    IX_STATUS qStatus;    if (ixOsalFastMutexTryLock(&rxWriteMutex[portId]) == IX_SUCCESS)    {	qStatus = ixQMgrQWrite(	       IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId),	       &qBuffer);	    #ifndef NDEBUG  	if (qStatus != IX_SUCCESS)	{	    RX_STATS_INC(portId, rxFreeOverflow);	    	}#endif	ixOsalFastMutexUnlock(&rxWriteMutex[portId]);    }    else    {	RX_STATS_INC(portId, rxFreeLock);	qStatus = IX_QMGR_Q_OVERFLOW;    }    return qStatus;}/*  * Set the priority and write to a qmgr queue. */PRIVATE IX_STATUSixEthAccQmgrTxWrite(IxEthAccPortId portId, UINT32 qBuffer, UINT32 priority){    /* fill the priority field */    qBuffer |= (priority << IX_ETHNPE_QM_Q_FIELD_PRIOR_R);    return ixEthAccQmgrLockTxWrite(portId, qBuffer);	    }/** * * @brief This function will discover the highest priority S/W Tx Q that *        has entries in it * * @param portId - (in) the id of the port whose S/W Tx queues are to be searched *        priorityPtr - (out) the priority of the highest priority occupied q will be written *                      here * * @return IX_ETH_ACC_SUCCESS if an occupied Q is found *         IX_ETH_ACC_FAIL if no Q has entries * * @internal */PRIVATE IxEthAccStatusixEthAccTxSwQHighestPriorityGet(IxEthAccPortId portId,				IxEthAccTxPriority *priorityPtr){    if (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline 	== FIFO_NO_PRIORITY)    {	if(IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId].	       ixEthAccTxData.txQ[IX_ETH_ACC_TX_DEFAULT_PRIORITY]))	{	    return IX_ETH_ACC_FAIL;	}	else	{	    *priorityPtr = IX_ETH_ACC_TX_DEFAULT_PRIORITY;	    TX_STATS_INC(portId,txPriority[*priorityPtr]);	    return IX_ETH_ACC_SUCCESS;	}    }    else    {	IxEthAccTxPriority highestPriority = IX_ETH_ACC_TX_PRIORITY_7;       	while(1)	{	    if(!IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId].	       ixEthAccTxData.txQ[highestPriority]))	    {		*priorityPtr = highestPriority;		TX_STATS_INC(portId,txPriority[highestPriority]);		return IX_ETH_ACC_SUCCESS;	    }	    if (highestPriority == IX_ETH_ACC_TX_PRIORITY_0)	    {		return IX_ETH_ACC_FAIL;	    }	    highestPriority--;	}    }}/** * * @brief This function will take a buffer from a TX S/W Q and attempt *        to add it to the relevant TX H/W Q * * @param portId - the port whose TX queue is to be written to *        priority - identifies the queue from which the entry is to be read * * @internal */PRIVATE IxEthAccStatusixEthAccTxFromSwQ(IxEthAccPortId portId,		  IxEthAccTxPriority priority){    IX_OSAL_MBUF        *mbuf;    IX_STATUS	   qStatus;    IX_OSAL_ENSURE((UINT32)priority <= (UINT32)7, "Invalid priority");    IX_ETH_ACC_DATAPLANE_REMOVE_MBUF_FROM_Q_HEAD(	ixEthAccPortData[portId].ixEthAccTxData.txQ[priority], 	mbuf);        if (mbuf != NULL)    {	/*	 * Add the Tx buffer to the H/W Tx Q  	 * We do not need to flush here as it is already done	 * in TxFrameSubmit().	 */	qStatus = ixEthAccQmgrTxWrite(	      portId, 	      IX_OSAL_MMU_VIRT_TO_PHYS((UINT32)IX_ETHACC_NE_SHARED(mbuf)),	      priority);		if (qStatus == IX_SUCCESS)	{	    TX_STATS_INC(portId,txFromSwQOK);	    return IX_SUCCESS;	}	else if (qStatus == IX_QMGR_Q_OVERFLOW)	{	    /*	     * H/W Q overflow, need to save the buffer 	     * back on the s/w Q.	     * we must put it back on the head of the q to avoid 	     * reordering packet tx	     */	    TX_STATS_INC(portId,txFromSwQDelayed);	    IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD(		ixEthAccPortData[portId].ixEthAccTxData.txQ[priority], 		mbuf);	    /*enable Q notification*/	    qStatus = ixQMgrNotificationEnable(		IX_ETH_ACC_PORT_TO_TX_Q_ID(portId),		IX_ETH_ACC_PORT_TO_TX_Q_SOURCE(portId));                    if (qStatus != IX_SUCCESS && qStatus != IX_QMGR_WARNING)            {		TX_INC(portId,txUnexpectedError);		IX_ETH_ACC_FATAL_LOG(	            "ixEthAccTxFromSwQ:Unexpected Error: %u\n", 	            qStatus, 0, 0, 0, 0, 0);            }	}	else 	{	    TX_INC(portId,txUnexpectedError);	    /* recovery attempt */	    IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD(		ixEthAccPortData[portId].ixEthAccTxData.txQ[priority], 		mbuf);	    	    IX_ETH_ACC_FATAL_LOG(		"ixEthAccTxFromSwQ:Error: unexpected QM status 0x%08X\n", 		qStatus, 0, 0, 0, 0, 0);		}    }    else    {	/* sw queue is empty */    }    return IX_ETH_ACC_FAIL;}/** * * @brief This function will take a buffer from a RXfree S/W Q and attempt *        to add it to the relevant RxFree H/W Q * * @param portId - the port whose RXFree queue is to be written to * * @internal */PRIVATE IxEthAccStatusixEthAccRxFreeFromSwQ(IxEthAccPortId portId){    IX_OSAL_MBUF        *mbuf;    IX_STATUS	   qStatus = IX_SUCCESS;    IX_ETH_ACC_DATAPLANE_REMOVE_MBUF_FROM_Q_HEAD(	  ixEthAccPortData[portId].ixEthAccRxData.freeBufferList, 	  mbuf);    if (mbuf != NULL)    {	/*	 * Add The Rx Buffer to the H/W Free buffer Q if possible  	 */	qStatus = ixEthAccQmgrLockRxWrite(portId, 		  IX_OSAL_MMU_VIRT_TO_PHYS(			 (UINT32)IX_ETHACC_NE_SHARED(mbuf)));	if (qStatus == IX_SUCCESS)	{	    RX_STATS_INC(portId,rxFreeRepFromSwQOK);	    /*	     * Buffer added to h/w Q.	     */	    return IX_SUCCESS;	}	else if (qStatus == IX_QMGR_Q_OVERFLOW)	{	    /*	     * H/W Q overflow, need to save the buffer back on the s/w Q.	     */	    RX_STATS_INC(portId,rxFreeRepFromSwQDelayed);	    IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD(		   ixEthAccPortData[portId].ixEthAccRxData.freeBufferList, 		   mbuf);	}	else 	{	    /* unexpected qmgr error */	    RX_INC(portId,rxUnexpectedError);	    IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD(		    ixEthAccPortData[portId].ixEthAccRxData.freeBufferList, 		    mbuf);	    IX_ETH_ACC_FATAL_LOG("IxEthAccRxFreeFromSwQ:Error: unexpected QM status 0x%08X\n", 				 qStatus, 0, 0, 0, 0, 0);	}    }    else    {	/* sw queue is empty */    }    return IX_ETH_ACC_FAIL;}IX_ETH_ACC_PUBLICIxEthAccStatus ixEthAccInitDataPlane(){	    IxEthNpePhysicalId physicalId;        /*      * Initialize the service and register callback to other services.     */    IX_ETH_ACC_MEMSET(&ixEthAccDataStats, 		      0, 		      sizeof(ixEthAccDataStats));    /* init port data */    for(physicalId=0; physicalId < IX_ETH_ACC_NUMBER_OF_PORTS; physicalId++)    {	ixOsalFastMutexInit(&txWriteMutex[physicalId]);	ixOsalFastMutexInit(&rxWriteMutex[physicalId]);	IX_ETH_ACC_MEMSET(&ixEthAccPortData[physicalId], 			  0, 			  sizeof(ixEthAccPortData[physicalId]));	ixEthAccPortData[physicalId].ixEthAccTxData.schDiscipline = FIFO_NO_PRIORITY;    }    ixEthAccDataInfo.schDiscipline = FIFO_NO_PRIORITY;    ixEthAccDataInfo.rxQMCbTypeSet = UNREGISTERED;    ixEthAccDataInfo.npeCount = 0;    return (IX_ETH_ACC_SUCCESS);}IX_ETH_ACC_PUBLICIxEthAccStatus ixEthAccPortTxDoneCallbackRegister(IxEthAccPortId portId, 						  IxEthAccPortTxDoneCallback						  txCallbackFn, 						  UINT32 callbackTag){	    if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())    {	return (IX_ETH_ACC_FAIL);    }    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 (txCallbackFn == 0)	/* Check for null function pointer here. */    {	return (IX_ETH_ACC_INVALID_ARG);    }    ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn = txCallbackFn;    ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag = callbackTag;    return (IX_ETH_ACC_SUCCESS);}

⌨️ 快捷键说明

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