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

📄 ixethaccdataplane.c

📁 AMCC POWERPC 44X系列的U-BOOT文件
💻 C
📖 第 1 页 / 共 5 页
字号:
/** * @file IxEthDataPlane.c * * @author Intel Corporation * @date 12-Feb-2002 * * @brief This file contains the implementation of the IXPxxx * Ethernet Access Data plane component * * Design Notes: * * @par * IXP400 SW Release version 2.0 * * -- Copyright Notice -- * * @par * Copyright 2001-2005, Intel Corporation. * All rights reserved. * * @par * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the Intel Corporation nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * @par * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @par * -- End of Copyright Notice -- */#include "IxNpeMh.h"#include "IxEthAcc.h"#include "IxEthDB.h"#include "IxOsal.h"#include "IxEthDBPortDefs.h"#include "IxFeatureCtrl.h"#include "IxEthAcc_p.h"#include "IxEthAccQueueAssign_p.h"extern PUBLIC IxEthAccMacState ixEthAccMacState[];extern PUBLIC UINT32 ixEthAccNewSrcMask;/** * private functions prototype */PRIVATE IX_OSAL_MBUF *ixEthAccEntryFromQConvert(UINT32 qEntry, UINT32 mask);PRIVATE UINT32ixEthAccMbufRxQPrepare(IX_OSAL_MBUF *mbuf);PRIVATE UINT32ixEthAccMbufTxQPrepare(IX_OSAL_MBUF *mbuf);PRIVATE IxEthAccStatusixEthAccTxSwQHighestPriorityGet(IxEthAccPortId portId,				IxEthAccTxPriority *priorityPtr);PRIVATE IxEthAccStatusixEthAccTxFromSwQ(IxEthAccPortId portId,		  IxEthAccTxPriority priority);PRIVATE IxEthAccStatusixEthAccRxFreeFromSwQ(IxEthAccPortId portId);PRIVATE voidixEthAccMbufFromTxQ(IX_OSAL_MBUF *mbuf);PRIVATE voidixEthAccMbufFromRxQ(IX_OSAL_MBUF *mbuf);PRIVATE IX_STATUSixEthAccQmgrLockTxWrite(IxEthAccPortId portId,			UINT32 qBuffer);PRIVATE IX_STATUSixEthAccQmgrLockRxWrite(IxEthAccPortId portId,			UINT32 qBuffer);PRIVATE IX_STATUSixEthAccQmgrTxWrite(IxEthAccPortId portId,		    UINT32 qBuffer,		    UINT32 priority);/** * @addtogroup IxEthAccPri *@{ *//* increment a counter only when stats are enabled */#define TX_STATS_INC(port,field) \        IX_ETH_ACC_STATS_INC(ixEthAccPortData[port].ixEthAccTxData.stats.field)#define RX_STATS_INC(port,field) \        IX_ETH_ACC_STATS_INC(ixEthAccPortData[port].ixEthAccRxData.stats.field)/* always increment the counter (mainly used for unexpected errors) */#define TX_INC(port,field) \        ixEthAccPortData[port].ixEthAccTxData.stats.field++#define RX_INC(port,field) \        ixEthAccPortData[port].ixEthAccRxData.stats.field++PRIVATE IxEthAccDataPlaneStats     ixEthAccDataStats;extern IxEthAccPortDataInfo   ixEthAccPortData[];extern IxEthAccInfo   ixEthAccDataInfo;PRIVATE IxOsalFastMutex txWriteMutex[IX_ETH_ACC_NUMBER_OF_PORTS];PRIVATE IxOsalFastMutex rxWriteMutex[IX_ETH_ACC_NUMBER_OF_PORTS];/** * * @brief Mbuf header conversion macros : they implement the *  different conversions using a temporary value. They also double-check *  that the parameters can be converted to/from NPE format. * */#if defined(__wince) && !defined(IN_KERNEL)#define PTR_VIRT2NPE(ptrSrc,dst) \  do { UINT32 temp; \      IX_OSAL_ENSURE(sizeof(ptrSrc) == sizeof(UINT32), "Wrong parameter type"); \      IX_OSAL_ENSURE(sizeof(dst) == sizeof(UINT32), "Wrong parameter type"); \      temp = (UINT32)IX_OSAL_MBUF_MBUF_VIRTUAL_TO_PHYSICAL_TRANSLATION((IX_OSAL_MBUF*)ptrSrc); \      (dst) = IX_OSAL_SWAP_BE_SHARED_LONG(temp); } \  while(0)#define PTR_NPE2VIRT(type,src,ptrDst) \  do { void *temp; \      IX_OSAL_ENSURE(sizeof(type) == sizeof(UINT32), "Wrong parameter type"); \      IX_OSAL_ENSURE(sizeof(src) == sizeof(UINT32), "Wrong parameter type"); \      IX_OSAL_ENSURE(sizeof(ptrDst) == sizeof(UINT32), "Wrong parameter type"); \      temp = (void *)IX_OSAL_SWAP_BE_SHARED_LONG(src); \      (ptrDst) = (type)IX_OSAL_MBUF_MBUF_PHYSICAL_TO_VIRTUAL_TRANSLATION(temp); } \  while(0)#else#define PTR_VIRT2NPE(ptrSrc,dst) \  do { UINT32 temp; \      IX_OSAL_ENSURE(sizeof(ptrSrc) == sizeof(UINT32), "Wrong parameter type"); \      IX_OSAL_ENSURE(sizeof(dst) == sizeof(UINT32), "Wrong parameter type"); \      temp = (UINT32)IX_OSAL_MMU_VIRT_TO_PHYS(ptrSrc); \      (dst) = IX_OSAL_SWAP_BE_SHARED_LONG(temp); } \  while(0)#define PTR_NPE2VIRT(type,src,ptrDst) \  do { void *temp; \      IX_OSAL_ENSURE(sizeof(type) == sizeof(UINT32), "Wrong parameter type"); \      IX_OSAL_ENSURE(sizeof(src) == sizeof(UINT32), "Wrong parameter type"); \      IX_OSAL_ENSURE(sizeof(ptrDst) == sizeof(UINT32), "Wrong parameter type"); \      temp = (void *)IX_OSAL_SWAP_BE_SHARED_LONG(src); \      (ptrDst) = (type)IX_OSAL_MMU_PHYS_TO_VIRT(temp); } \  while(0)#endif/** * * @brief Mbuf payload pointer conversion macros : Wince has its own *  method to convert the buffer pointers */#if defined(__wince) && !defined(IN_KERNEL)#define DATAPTR_VIRT2NPE(ptrSrc,dst) \  do { UINT32 temp; \      temp = (UINT32)IX_OSAL_MBUF_DATA_VIRTUAL_TO_PHYSICAL_TRANSLATION(ptrSrc); \      (dst) = IX_OSAL_SWAP_BE_SHARED_LONG(temp); } \  while(0)#else#define DATAPTR_VIRT2NPE(ptrSrc,dst) PTR_VIRT2NPE(IX_OSAL_MBUF_MDATA(ptrSrc),dst)#endif/* Flush the shared part of the mbuf header */#define IX_ETHACC_NE_CACHE_FLUSH(mbufPtr) \  do { \      IX_OSAL_CACHE_FLUSH(IX_ETHACC_NE_SHARED(mbufPtr), \			      sizeof(IxEthAccNe)); \    } \  while(0)/* Invalidate the shared part of the mbuf header */#define IX_ETHACC_NE_CACHE_INVALIDATE(mbufPtr) \  do { \      IX_OSAL_CACHE_INVALIDATE(IX_ETHACC_NE_SHARED(mbufPtr), \				   sizeof(IxEthAccNe)); \    } \  while(0)/* Preload one cache line (shared mbuf headers are aligned * and their size is 1 cache line) * * IX_OSAL_CACHED  is defined when the mbuf headers are * allocated from cached memory. * * Other processor on emulation environment may not implement * preload function */#ifdef IX_OSAL_CACHED	#if (CPU!=SIMSPARCSOLARIS) && !defined (__wince)		#define IX_ACC_DATA_CACHE_PRELOAD(ptr) \		do { /* preload a cache line (Xscale Processor) */ \			__asm__ (" pld [%0]\n": : "r" (ptr)); \		} \		while(0)	#else		/* preload not implemented on different processor */		#define IX_ACC_DATA_CACHE_PRELOAD(mbufPtr) \		do { /* nothing */ } while (0)	#endif#else	/* preload not needed if cache is not enabled */	#define IX_ACC_DATA_CACHE_PRELOAD(mbufPtr) \	do { /* nothing */ } while (0)#endif/** * * @brief function to retrieve the correct pointer from * a queue entry posted by the NPE * * @param qEntry : entry from qmgr queue *        mask : applicable mask for this queue *        (4 most significant bits are used for additional informations) * * @return IX_OSAL_MBUF * pointer to mbuf header * * @internal */PRIVATE IX_OSAL_MBUF *ixEthAccEntryFromQConvert(UINT32 qEntry, UINT32 mask){    IX_OSAL_MBUF *mbufPtr;    if (qEntry != 0)    {        /* mask NPE bits (e.g. priority, port ...) */        qEntry &= mask;#if IX_ACC_DRAM_PHYS_OFFSET != 0        /* restore the original address pointer (if PHYS_OFFSET is not 0) */        qEntry |= (IX_ACC_DRAM_PHYS_OFFSET & ~IX_ETHNPE_QM_Q_RXENET_ADDR_MASK);#endif        /* get the mbuf pointer address from the npe-shared address */        qEntry -= offsetof(IX_OSAL_MBUF,ix_ne);        /* phys2virt mbuf */        mbufPtr = (IX_OSAL_MBUF *)IX_OSAL_MMU_PHYS_TO_VIRT(qEntry);        /* preload the cacheline shared with NPE */        IX_ACC_DATA_CACHE_PRELOAD(IX_ETHACC_NE_SHARED(mbufPtr));        /* preload the cacheline used by xscale */        IX_ACC_DATA_CACHE_PRELOAD(mbufPtr);    }    else    {	mbufPtr = NULL;    }    return mbufPtr;}/* Convert the mbuf header for NPE transmission */PRIVATE UINT32ixEthAccMbufTxQPrepare(IX_OSAL_MBUF *mbuf){    UINT32 qbuf;    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_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbuf) == NULL)    {	/* "best case" scenario : unchained mbufs */	IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedTxMBufs);	/* payload pointer conversion */	DATAPTR_VIRT2NPE(mbuf, IX_ETHACC_NE_DATA(mbuf));	/* unchained mbufs : the frame length is the mbuf length	 * and the 2 identical lengths are stored in the same	 * word.	 */	len = IX_OSAL_MBUF_MLEN(mbuf);	/* set the length in both length and pktLen 16-bits fields */	len |= (len << IX_ETHNPE_ACC_LENGTH_OFFSET);	IX_ETHACC_NE_LEN(mbuf) = IX_OSAL_SWAP_BE_SHARED_LONG(len);	/* unchained mbufs : next contains 0 */	IX_ETHACC_NE_NEXT(mbuf) = 0;	/* flush shared header after all address conversions */	IX_ETHACC_NE_CACHE_FLUSH(mbuf);    }    else    {	/* chained mbufs */	IX_OSAL_MBUF *ptr = mbuf;	IX_OSAL_MBUF *nextPtr;	UINT32 frmLen;	/* get the frame length from the header of the first buffer */	frmLen = IX_OSAL_MBUF_PKT_LEN(mbuf);	do	{	    IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedTxMBufs);	    /* payload pointer */	    DATAPTR_VIRT2NPE(ptr,IX_ETHACC_NE_DATA(ptr));	    /* Buffer length and frame length are stored in the same word */	    len = IX_OSAL_MBUF_MLEN(ptr);	    len = frmLen | (len << IX_ETHNPE_ACC_LENGTH_OFFSET);	    IX_ETHACC_NE_LEN(ptr) = IX_OSAL_SWAP_BE_SHARED_LONG(len);	    /* get the virtual next chain pointer */	    nextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr);	    if (nextPtr != NULL)	    {		/* shared pointer of the next buffer is chained */		PTR_VIRT2NPE(IX_ETHACC_NE_SHARED(nextPtr),			     IX_ETHACC_NE_NEXT(ptr));	    }	    else	    {		IX_ETHACC_NE_NEXT(ptr) = 0;	    }	    /* flush shared header after all address conversions */	    IX_ETHACC_NE_CACHE_FLUSH(ptr);	    /* move to next buffer */	    ptr = nextPtr;	    /* the frame length field is set only in the first buffer	     * and is zeroed in the next buffers	     */	    frmLen = 0;	}	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_TXENET_ADDR_MASK) == 0),	      "Invalid address range");    return qbuf;}/* Convert the mbuf header for NPE reception */PRIVATE UINT32ixEthAccMbufRxQPrepare(IX_OSAL_MBUF *mbuf){    UINT32 len;    UINT32 qbuf;    if (IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbuf) == NULL)    {	/* "best case" scenario : unchained mbufs */	IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedRxFreeMBufs);	/* unchained mbufs : payload pointer */	DATAPTR_VIRT2NPE(mbuf, IX_ETHACC_NE_DATA(mbuf));	/* unchained mbufs : set the buffer length	* and the frame length field is zeroed	*/	len = (IX_OSAL_MBUF_MLEN(mbuf) << IX_ETHNPE_ACC_LENGTH_OFFSET);	IX_ETHACC_NE_LEN(mbuf) = IX_OSAL_SWAP_BE_SHARED_LONG(len);	/* unchained mbufs : next pointer is null */	IX_ETHACC_NE_NEXT(mbuf) = 0;	/* flush shared header after all address conversions */	IX_ETHACC_NE_CACHE_FLUSH(mbuf);	/* remove shared header cache line */	IX_ETHACC_NE_CACHE_INVALIDATE(mbuf);    }    else    {	/* chained mbufs */	IX_OSAL_MBUF *ptr = mbuf;	IX_OSAL_MBUF *nextPtr;	do	{	    /* chained mbufs */	    IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedRxFreeMBufs);	    /* we must save virtual next chain pointer */	    nextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr);	    if (nextPtr != NULL)	    {		/* chaining pointer for NPE */		PTR_VIRT2NPE(IX_ETHACC_NE_SHARED(nextPtr),			     IX_ETHACC_NE_NEXT(ptr));	    }	    else	    {		IX_ETHACC_NE_NEXT(ptr) = 0;	    }	    /* payload pointer */	    DATAPTR_VIRT2NPE(ptr,IX_ETHACC_NE_DATA(ptr));	    /* buffer length */	    len = (IX_OSAL_MBUF_MLEN(ptr) << IX_ETHNPE_ACC_LENGTH_OFFSET);	    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;}

⌨️ 快捷键说明

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