📄 ixatmmdatapath.c
字号:
/** * @file IxAtmmDataPath.c * @author Intel Corporation * @date 1-MAR-2002 * * @brief IxAtmm data path sub component (AtmmDataPath) APIs. * No rollback in initialization if any part of initialization fails. * Assumptions: * - DemandUpdate callback from IxAtmd is serialized per VC. * - TxLow callback from IxAtmd will occur in an IRQ context * - VcDemandUpdate callback from IxAtmd can occur in IRQ or task context * => TxLow callback can interrupt VcDemandUpdate callback * => TxLow callback cannot interrupt VcDemandUpdate callback * - No OS calls made in IxAtmmPortTxProcess, i.e. safe to intLock * * * @par * IXP400 SW Release version 2.1 * * -- Copyright Notice -- * * @par * Copyright (c) 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 -- *//* * Put the system defined include files required *//* * Put the user defined include files required */#include "IxOsal.h"#include "IxAtmTypes.h"#include "IxAtmm.h"#include "IxAtmdAccCtrl.h"#include "IxAtmSch.h"#include "IxAtmmDataPath_p.h"/* * #defines and macros used in this file. *//* * Process Tx Done queue every 1/2 second to ensure queue gets cleared out * when idle/low traffic. */#define IX_ATMM_TX_DONE_PERIOD_MSECS 500/* * Process Rx low priority queue every 20 msecs */#define IX_ATMM_RX_LO_PRIORITY_PERIOD_MSECS 20/* * Tx Vc Q fast mutexes, one Q per port. */#define IX_ATMM_TX_MUTEX_TRY_LOCK(port) ixOsalFastMutexTryLock (&ixAtmmTxBusyFastMutex[(port)])#define IX_ATMM_TX_MUTEX_UNLOCK(port) (void)ixOsalFastMutexUnlock (&ixAtmmTxBusyFastMutex[(port)])/* * Port State fast mutexes, one per port. */#define IX_ATMM_PORT_MUTEX_TRY_LOCK(port) ixOsalFastMutexTryLock (&ixAtmmPortFastMutex[(port)])#define IX_ATMM_PORT_MUTEX_UNLOCK(port) (void)ixOsalFastMutexUnlock (&ixAtmmPortFastMutex[(port)])/* * Tx timer based *//* * Typedefs whose scope is limited to this file. */typedef struct { IxOsalThread rxLoPriorityId; IxOsalThread txDoneId;} IxAtmmTaskIds;/* * Variable declarations global to this file only. Externs are followed by * static variables. */static IxAtmmTaskIds ixAtmmTaskIds;/* * VC query callback registered by IxAtmm.c */static IxAtmmVcQueryCallback vcQueryCallback = NULL;/* * Fast muxtexs, initialized later */static IxOsalFastMutex ixAtmmTxBusyFastMutex[IX_UTOPIA_MAX_PORTS];static IxOsalFastMutex ixAtmmPortFastMutex[IX_UTOPIA_MAX_PORTS];/* * TX Vc Q size, needed when system goes IDLE -> BUSY */static unsigned ixAtmmTxQSize[IX_UTOPIA_MAX_PORTS];/* * Variables are moved here since they are required while doing un-init * Scheduling Init done array used by ixAtmmTxSchedulingInitDone and txSchedulingUninit */static BOOL ixAtmmTxSchedulingInitDone[IX_UTOPIA_MAX_PORTS];/* Flag used by ixAtmmTxDoneInit and ixAtmmTxDoneUninit */static BOOL ixAtmmTxDoneInitDone = FALSE;/* Flags used by Rx Init and Rx Uninit */static BOOL ixAtmmRxHiPriorityInitDone = FALSE;static BOOL ixAtmmRxLoPriorityInitDone = FALSE;/* * Static function prototypes */PRIVATE IX_STATUSixAtmmTxDoneInit (void);PRIVATE IX_STATUSixAtmmTxSchedulingInit (IxAtmLogicalPort port);PRIVATE IX_STATUSixAtmmRxHiPriorityInit (void);PRIVATE IX_STATUSixAtmmRxLoPriorityInit (void);PRIVATE voidixAtmmTxLowHandle (IxAtmLogicalPort port, unsigned numRemainingCells);PRIVATE IX_STATUSixAtmmTxDoneHandle (unsigned numOfPdusToProcess, unsigned *reservedPtr);PRIVATE IX_STATUSixAtmmVcDemandUpdate (IxAtmLogicalPort port, IxAtmSchedulerVcId vcId, unsigned numberOfCells);PRIVATE voidixAtmmVcQueueClear (IxAtmLogicalPort port, IxAtmSchedulerVcId vcId);PRIVATE IX_STATUS ixAtmmVcIdGet (IxAtmLogicalPort port, unsigned vpi, unsigned vci, IxAtmConnId connId, IxAtmSchedulerVcId *vcId);PRIVATE IX_STATUSixAtmmTxDoneLoop (void* arg, void** retArgObj);PRIVATE IX_STATUSixAtmmRxLoPriorityLoop (void* arg, void** ptrRetObj);PRIVATE IX_STATUSixAtmmTxSchedulingUninit (IxAtmLogicalPort port);PRIVATE IX_STATUSixAtmmTxDoneUninit (void);PRIVATE IX_STATUSixAtmmRxHiPriorityUninit (void);PRIVATE IX_STATUSixAtmmRxLoPriorityUninit (void);/* * Function definitons */voidixAtmmVcQueryCallbackRegister ( IxAtmmVcQueryCallback callback){ /* NULL callback not supported */ IX_OSAL_ASSERT(callback != NULL); vcQueryCallback = callback;}voidixAtmmVcQueryCallbackUnregister(void){ /* Reset the vcQueryCallback */ vcQueryCallback = NULL;}PRIVATE IX_STATUSixAtmmTxDoneLoop (void* arg, void** retArgObj){ unsigned dummyPtr; IX_STATUS retval; while (ixAtmmTxDoneInitDone) { /* * Sleep for the timer duration */ ixOsalSleep (IX_ATMM_TX_DONE_PERIOD_MSECS); /* * Service Tx Done, process all the queue * but release the fast mutex to allow interrupts * running and service tx done when it is really needed. */ retval = ixAtmmTxDoneHandle (IX_ATMDACC_ALLPDUS, &dummyPtr); IX_OSAL_ENSURE(retval == IX_SUCCESS, "Call to ixAtmmTxDoneHandle() failed"); } ixOsalSleep (50); return IX_SUCCESS;}PRIVATE IX_STATUSixAtmmRxLoPriorityLoop (void* arg, void** ptrRetObj){ unsigned dummyPtr; IX_STATUS retval; while (ixAtmmRxLoPriorityInitDone) { /* * Sleep for the timer duration */ ixOsalSleep (IX_ATMM_RX_LO_PRIORITY_PERIOD_MSECS); /* * Service Rx low priority queue, process all in Q */ retval = ixAtmdAccRxDispatch ( IX_ATM_RX_B, IX_ATMDACC_ALLPDUS, &dummyPtr); IX_OSAL_ENSURE(retval == IX_SUCCESS, "Call to ixAtmdAccRxDispatch() failed"); } ixOsalSleep (50); return IX_SUCCESS; }PUBLIC IX_STATUSixAtmmPortEnable (IxAtmLogicalPort port){ unsigned int maxTxCells; UINT32 lockKey; IX_STATUS retval; retval = ixAtmdAccPortEnable(port); if (retval == IX_SUCCESS) { /* ensure no interrupt is running */ lockKey = ixOsalIrqLock(); retval = ixAtmdAccPortTxFreeEntriesQuery(port, &maxTxCells); if(retval == IX_SUCCESS) { IX_ATMM_PORT_MUTEX_UNLOCK(port); if (maxTxCells == ixAtmmTxQSize[port]) { /* there are no entries in the TX queue, it is necessary to restart the transmission of cells */ ixAtmmTxLowHandle (port, maxTxCells); } else { /* there are cells in the tx queue : the NPE will consume them and this will trigger a tx Low interrupt. The TX traffic will start again */ } } ixOsalIrqUnlock(lockKey); } else if (retval == IX_ATMDACC_WARNING) { /* the port is already up */ retval = IX_SUCCESS; } else { retval = IX_FAIL; } return retval;}PUBLIC IX_STATUSixAtmmPortDisable (IxAtmLogicalPort port){ IX_STATUS retval; UINT32 lockKey; /* ensure no interrupt is running (scheduling and transmission is done under interrupts) */ lockKey = ixOsalIrqLock(); IX_ATMM_PORT_MUTEX_TRY_LOCK(port); /* now, cell transmission is stopped */ ixOsalIrqUnlock(lockKey); /* tell the NPE to stop draining the TX queue */ retval = ixAtmdAccPortDisable(port); if (retval == IX_SUCCESS) { /* wait until a Disable is complete */ while (ixAtmdAccPortDisableComplete(port) == FALSE) { /* since TX done is processing the response, the time to wait is linked to the TxDone polling time */ ixOsalSleep(IX_ATMM_TX_DONE_PERIOD_MSECS/2 ); } } else if (retval == IX_ATMDACC_WARNING) { /* the port is already down */ retval = IX_SUCCESS; } else { retval = IX_FAIL; } IX_ATMM_PORT_MUTEX_UNLOCK(port); return retval;}IX_STATUSixAtmmDataPathSetup (IxAtmLogicalPort port){ IX_STATUS retval = IX_SUCCESS; /* * Initialize Tx Scheduling control */ retval = ixAtmmTxSchedulingInit (port); if (retval == IX_SUCCESS) { /* * Initialize Tx Done control */ retval = ixAtmmTxDoneInit (); } if (retval == IX_SUCCESS) { /* * Initialize Rx High Priority control */ retval = ixAtmmRxHiPriorityInit (); } if (retval == IX_SUCCESS) { /* * Initialize Rx Low Priority control */ retval = ixAtmmRxLoPriorityInit (); } return retval;}IX_STATUSixAtmmDataPathUninit (IxAtmLogicalPort port){ IX_STATUS retval = IX_SUCCESS; /* * Uninitialize Rx Low Priority control */ retval = ixAtmmRxLoPriorityUninit (); if (IX_SUCCESS == retval) { /* * Uninitialize Rx High Priority control */ retval = ixAtmmRxHiPriorityUninit (); } if (IX_SUCCESS == retval) { /* * Uninitialize Tx Done control */ retval = ixAtmmTxDoneUninit (); } if (IX_SUCCESS == retval) { /* * Uninitialize Tx Scheduling control */ retval = ixAtmmTxSchedulingUninit (port); } return retval;}PRIVATE IX_STATUSixAtmmTxSchedulingInit (IxAtmLogicalPort port){ static BOOL firstInitDone = FALSE; IX_STATUS retval = IX_SUCCESS; UINT32 i; /* Clear InitDone flags on first initialization */ if (!firstInitDone) { for (i=0; i < (sizeof(ixAtmmTxSchedulingInitDone) / sizeof(BOOL)); i++) { ixAtmmTxSchedulingInitDone[i] = FALSE; } firstInitDone = TRUE; } /* Only initialize each port once */ if (ixAtmmTxSchedulingInitDone[port]) { retval = IX_ATMM_RET_ALREADY_INITIALIZED; } if (retval == IX_SUCCESS) { /* * Put Atmm in scheduling mode, this registers Atmm callbacks. */ retval = ixAtmdAccPortTxScheduledModeEnable (port, ixAtmmVcDemandUpdate, ixAtmmVcQueueClear, ixAtmmVcIdGet); } if (retval == IX_SUCCESS) { /* * Get depth of tx Q for case when system goes IDLE -> BUSY */ retval = ixAtmdAccPortTxFreeEntriesQuery (port, &ixAtmmTxQSize[port]); } if (retval == IX_SUCCESS) { /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -