📄 ixethaccmac.c
字号:
/** * @file IxEthAccMac.c * * @author Intel Corporation * @date * * @brief MAC control functions * * 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 "IxOsal.h"#include "IxNpeMh.h"#ifdef CONFIG_IXP425_COMPONENT_ETHDB#include "IxEthDB.h"#endif#include "IxEthDBPortDefs.h"#include "IxEthNpe.h"#include "IxEthAcc.h"#include "IxEthAccDataPlane_p.h"#include "IxEthAcc_p.h"#include "IxEthAccMac_p.h"/* Maximum number of retries during ixEthAccPortDisable, which * is approximately 10 seconds*/#define IX_ETH_ACC_MAX_RETRY 500/* Maximum number of retries during ixEthAccPortDisable when expecting * timeout */#define IX_ETH_ACC_MAX_RETRY_TIMEOUT 5#define IX_ETH_ACC_VALIDATE_PORT_ID(portId) \ do \ { \ if(!IX_ETH_ACC_IS_PORT_VALID(portId)) \ { \ return IX_ETH_ACC_INVALID_PORT; \ } \ } while(0)PUBLIC IxEthAccMacState ixEthAccMacState[IX_ETH_ACC_NUMBER_OF_PORTS];PRIVATE UINT32 ixEthAccMacBase[IX_ETH_ACC_NUMBER_OF_PORTS];/*Forward function declarations*/PRIVATE voidixEthAccPortDisableRx (IxEthAccPortId portId, IX_OSAL_MBUF * mBufPtr, BOOL useMultiBufferCallback);PRIVATE voidixEthAccPortDisableRxAndReplenish (IxEthAccPortId portId, IX_OSAL_MBUF * mBufPtr, BOOL useMultiBufferCallback);PRIVATE voidixEthAccPortDisableTxDone (UINT32 cbTag, IX_OSAL_MBUF *mbuf);PRIVATE voidixEthAccPortDisableTxDoneAndSubmit (UINT32 cbTag, IX_OSAL_MBUF *mbuf);PRIVATE voidixEthAccPortDisableRxCallback (UINT32 cbTag, IX_OSAL_MBUF * mBufPtr, UINT32 learnedPortId);PRIVATE voidixEthAccPortDisableMultiBufferRxCallback (UINT32 cbTag, IX_OSAL_MBUF **mBufPtr);PRIVATE IxEthAccStatusixEthAccPortDisableTryTransmit(UINT32 portId);PRIVATE IxEthAccStatusixEthAccPortDisableTryReplenish(UINT32 portId);PRIVATE IxEthAccStatusixEthAccPortMulticastMacAddressGet (IxEthAccPortId portId, IxEthAccMacAddr *macAddr);PRIVATE IxEthAccStatusixEthAccPortMulticastMacFilterGet (IxEthAccPortId portId, IxEthAccMacAddr *macAddr);PRIVATE voidixEthAccMacNpeStatsMessageCallback (IxNpeMhNpeId npeId, IxNpeMhMessage msg);PRIVATE voidixEthAccMacNpeStatsResetMessageCallback (IxNpeMhNpeId npeId, IxNpeMhMessage msg);PRIVATE voidixEthAccNpeLoopbackMessageCallback (IxNpeMhNpeId npeId, IxNpeMhMessage msg);PRIVATE voidixEthAccMulticastAddressSet(IxEthAccPortId portId);PRIVATE BOOLixEthAccMacEqual(IxEthAccMacAddr *macAddr1, IxEthAccMacAddr *macAddr2);PRIVATE voidixEthAccMacPrint(IxEthAccMacAddr *m);PRIVATE voidixEthAccMacStateUpdate(IxEthAccPortId portId);IxEthAccStatusixEthAccMacMemInit(void){ ixEthAccMacBase[IX_ETH_PORT_1] = (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_0_BASE, IX_OSAL_IXP400_ETHA_MAP_SIZE); ixEthAccMacBase[IX_ETH_PORT_2] = (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_1_BASE, IX_OSAL_IXP400_ETHB_MAP_SIZE);#ifdef __ixp46X ixEthAccMacBase[IX_ETH_PORT_3] = (UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_2_BASE, IX_OSAL_IXP400_ETH_NPEA_MAP_SIZE); if (ixEthAccMacBase[IX_ETH_PORT_3] == 0) { ixOsalLog(IX_OSAL_LOG_LVL_FATAL, IX_OSAL_LOG_DEV_STDOUT, "EthAcc: Could not map MAC I/O memory\n", 0, 0, 0, 0, 0 ,0); return IX_ETH_ACC_FAIL; }#endif if (ixEthAccMacBase[IX_ETH_PORT_1] == 0 || ixEthAccMacBase[IX_ETH_PORT_2] == 0) { ixOsalLog(IX_OSAL_LOG_LVL_FATAL, IX_OSAL_LOG_DEV_STDOUT, "EthAcc: Could not map MAC I/O memory\n", 0, 0, 0, 0, 0 ,0); return IX_ETH_ACC_FAIL; } return IX_ETH_ACC_SUCCESS;}voidixEthAccMacUnload(void){ IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_1]); IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_2]);#ifdef __ixp46X IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_3]); ixEthAccMacBase[IX_ETH_PORT_3] = 0;#endif ixEthAccMacBase[IX_ETH_PORT_2] = 0; ixEthAccMacBase[IX_ETH_PORT_1] = 0;}IxEthAccStatusixEthAccPortEnablePriv(IxEthAccPortId portId){ IX_ETH_ACC_VALIDATE_PORT_ID(portId); if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) { IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable port.\n",(INT32)portId,0,0,0,0,0); return IX_ETH_ACC_SUCCESS ; } if (!IX_ETH_IS_PORT_INITIALIZED(portId)) { printf("EthAcc: (Mac) cannot enable port %d, port not initialized\n", portId); return (IX_ETH_ACC_PORT_UNINITIALIZED); } if (ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn == NULL) { /* TxDone callback not registered */ printf("EthAcc: (Mac) cannot enable port %d, TxDone callback not registered\n", portId); return (IX_ETH_ACC_PORT_UNINITIALIZED); } if ((ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn == NULL) && (ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn == NULL)) { /* Receive callback not registered */ printf("EthAcc: (Mac) cannot enable port %d, Rx callback not registered\n", portId); return (IX_ETH_ACC_PORT_UNINITIALIZED); } if(!ixEthAccMacState[portId].initDone) { printf("EthAcc: (Mac) cannot enable port %d, MAC address not set\n", portId); return (IX_ETH_ACC_MAC_UNINITIALIZED); } /* if the state is being set to what it is already at, do nothing*/ if (ixEthAccMacState[portId].enabled) { return IX_ETH_ACC_SUCCESS; }#ifdef CONFIG_IXP425_COMPONENT_ETHDB /* enable ethernet database for this port */ if (ixEthDBPortEnable(portId) != IX_ETH_DB_SUCCESS) { printf("EthAcc: (Mac) cannot enable port %d, EthDB failure\n", portId); return IX_ETH_ACC_FAIL; }#endif /* set the MAC core registers */ REG_WRITE(ixEthAccMacBase[portId], IX_ETH_ACC_MAC_TX_CNTRL2, IX_ETH_ACC_TX_CNTRL2_RETRIES_MASK); REG_WRITE(ixEthAccMacBase[portId], IX_ETH_ACC_MAC_RANDOM_SEED, IX_ETH_ACC_RANDOM_SEED_DEFAULT); REG_WRITE(ixEthAccMacBase[portId], IX_ETH_ACC_MAC_THRESH_P_EMPTY, IX_ETH_ACC_MAC_THRESH_P_EMPTY_DEFAULT); REG_WRITE(ixEthAccMacBase[portId], IX_ETH_ACC_MAC_THRESH_P_FULL, IX_ETH_ACC_MAC_THRESH_P_FULL_DEFAULT); REG_WRITE(ixEthAccMacBase[portId], IX_ETH_ACC_MAC_TX_DEFER, IX_ETH_ACC_MAC_TX_DEFER_DEFAULT); REG_WRITE(ixEthAccMacBase[portId], IX_ETH_ACC_MAC_TX_TWO_DEFER_1, IX_ETH_ACC_MAC_TX_TWO_DEFER_1_DEFAULT); REG_WRITE(ixEthAccMacBase[portId], IX_ETH_ACC_MAC_TX_TWO_DEFER_2, IX_ETH_ACC_MAC_TX_TWO_DEFER_2_DEFAULT); REG_WRITE(ixEthAccMacBase[portId], IX_ETH_ACC_MAC_SLOT_TIME, IX_ETH_ACC_MAC_SLOT_TIME_DEFAULT); REG_WRITE(ixEthAccMacBase[portId], IX_ETH_ACC_MAC_INT_CLK_THRESH, IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT); REG_WRITE(ixEthAccMacBase[portId], IX_ETH_ACC_MAC_BUF_SIZE_TX, IX_ETH_ACC_MAC_BUF_SIZE_TX_DEFAULT); REG_WRITE(ixEthAccMacBase[portId], IX_ETH_ACC_MAC_TX_CNTRL1, IX_ETH_ACC_TX_CNTRL1_DEFAULT); REG_WRITE(ixEthAccMacBase[portId], IX_ETH_ACC_MAC_RX_CNTRL1, IX_ETH_ACC_RX_CNTRL1_DEFAULT); /* set the global state */ ixEthAccMacState[portId].portDisableState = ACTIVE; ixEthAccMacState[portId].enabled = TRUE; /* rewrite the setup (including mac filtering) depending * on current options */ ixEthAccMacStateUpdate(portId); return IX_ETH_ACC_SUCCESS;}/* * PortDisable local variables. They contain the intermediate steps * while the port is being disabled and the buffers being drained out * of the NPE. */typedef void (*IxEthAccPortDisableRx)(IxEthAccPortId portId, IX_OSAL_MBUF * mBufPtr, BOOL useMultiBufferCallback);static IxEthAccPortRxCallbackixEthAccPortDisableFn[IX_ETH_ACC_NUMBER_OF_PORTS];static IxEthAccPortMultiBufferRxCallbackixEthAccPortDisableMultiBufferFn[IX_ETH_ACC_NUMBER_OF_PORTS];static IxEthAccPortDisableRxixEthAccPortDisableRxTable[IX_ETH_ACC_NUMBER_OF_PORTS];static UINT32ixEthAccPortDisableCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];static UINT32ixEthAccPortDisableMultiBufferCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];static IxEthAccPortTxDoneCallbackixEthAccPortDisableTxDoneFn[IX_ETH_ACC_NUMBER_OF_PORTS];static UINT32ixEthAccPortDisableTxDoneCbTag[IX_ETH_ACC_NUMBER_OF_PORTS];static UINT32ixEthAccPortDisableUserBufferCount[IX_ETH_ACC_NUMBER_OF_PORTS];/* * PortDisable private callbacks functions. They handle the user * traffic, and the special buffers (one for tx, one for rx) used * in portDisable. */PRIVATE voidixEthAccPortDisableTxDone(UINT32 cbTag, IX_OSAL_MBUF *mbuf){ IxEthAccPortId portId = (IxEthAccPortId)cbTag; volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState; /* check for the special mbuf used in portDisable */ if (mbuf == ixEthAccMacState[portId].portDisableTxMbufPtr) { *txState = TRANSMIT_DONE; } else { /* increment the count of user traffic during portDisable */ ixEthAccPortDisableUserBufferCount[portId]++; /* call client TxDone function */ ixEthAccPortDisableTxDoneFn[portId](ixEthAccPortDisableTxDoneCbTag[portId], mbuf); }}PRIVATE IxEthAccStatusixEthAccPortDisableTryTransmit(UINT32 portId){ int key; IxEthAccStatus status = IX_ETH_ACC_SUCCESS; volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState; /* transmit the special buffer again if it is transmitted * and update the txState * This section is protected because the portDisable context * run an identical code, so the system keeps transmitting at the * maximum rate. */ key = ixOsalIrqLock(); if (*txState == TRANSMIT_DONE) { IX_OSAL_MBUF *mbufTxPtr = ixEthAccMacState[portId].portDisableTxMbufPtr; *txState = TRANSMIT; status = ixEthAccPortTxFrameSubmit(portId, mbufTxPtr, IX_ETH_ACC_TX_DEFAULT_PRIORITY); } ixOsalIrqUnlock(key); return status;}PRIVATE voidixEthAccPortDisableTxDoneAndSubmit(UINT32 cbTag, IX_OSAL_MBUF *mbuf){ IxEthAccPortId portId = (IxEthAccPortId)cbTag; /* call the callback which forwards the traffic to the client */ ixEthAccPortDisableTxDone(cbTag, mbuf); /* try to transmit the buffer used in portDisable * if seen in TxDone */ ixEthAccPortDisableTryTransmit(portId);}PRIVATE voidixEthAccPortDisableRx (IxEthAccPortId portId, IX_OSAL_MBUF * mBufPtr, BOOL useMultiBufferCallback){ volatile IxEthAccPortDisableState *rxState = &ixEthAccMacState[portId].rxState; IX_OSAL_MBUF *mNextPtr; while (mBufPtr) { mNextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mBufPtr); IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mBufPtr) = NULL; /* check for the special mbuf used in portDisable */ if (mBufPtr == ixEthAccMacState[portId].portDisableRxMbufPtr) { *rxState = RECEIVE; } else { /* increment the count of user traffic during portDisable */ ixEthAccPortDisableUserBufferCount[portId]++; /* reset the received payload length during portDisable */ IX_OSAL_MBUF_MLEN(mBufPtr) = 0; IX_OSAL_MBUF_PKT_LEN(mBufPtr) = 0; if (useMultiBufferCallback) { /* call the user callback with one unchained * buffer, without payload. A small array is built * to be used as a parameter (the user callback expects * to receive an array ended by a NULL pointer. */ IX_OSAL_MBUF *mBufPtrArray[2]; mBufPtrArray[0] = mBufPtr; mBufPtrArray[1] = NULL; ixEthAccPortDisableMultiBufferFn[portId]( ixEthAccPortDisableMultiBufferCbTag[portId], mBufPtrArray); } else { /* call the user callback with a unchained
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -