/* * txPort.c * * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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. * * Neither the name Texas Instruments nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * 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. */ /**************************************************************************** * * MODULE: txPort.c * * PURPOSE: Multiplexes between the management and data queues. * * DESCRIPTION: * ============ * The Tx port state machine multiplexes between the management and data queues * according to the management queues requests. * ****************************************************************************/ #define __FILE_ID__ FILE_ID_62 #include "commonTypes.h" #include "tidef.h" #include "osApi.h" #include "report.h" #include "DataCtrl_Api.h" #include "DrvMainModules.h" typedef enum { MUX_MGMT_QUEUES, /* The management queues have access to the Tx path. */ MUX_DATA_QUEUES /* The data queues have access to the Tx path. */ } EQueuesMuxState; typedef enum { QUEUE_ACTION_NONE, QUEUE_ACTION_STOP, QUEUE_ACTION_WAKE } EQueueAction; /* The txPort module object. */ typedef struct { TI_HANDLE hOs; TI_HANDLE hReport; TI_HANDLE hTxDataQ; TI_HANDLE hTxMgmtQ; EQueuesMuxState queuesMuxState; TI_BOOL txSuspended; TI_BOOL mgmtQueueEnabled; TI_BOOL dataQueueEnabled; } TTxPortObj; /* * The txPort local functions: */ static void updateQueuesStates(TTxPortObj *pTxPort); /**************************************************************************** * txPort_Create() **************************************************************************** * DESCRIPTION: Create the txPort module object * * INPUTS: None * * OUTPUT: None * * RETURNS: The Created object ****************************************************************************/ TI_HANDLE txPort_create(TI_HANDLE hOs) { TTxPortObj *pTxPort; pTxPort = os_memoryAlloc(hOs, sizeof(TTxPortObj)); if (pTxPort == NULL) return NULL; os_memoryZero(hOs, pTxPort, sizeof(TTxPortObj)); pTxPort->hOs = hOs; return( (TI_HANDLE)pTxPort ); } /**************************************************************************** * txPort_unLoad() **************************************************************************** * DESCRIPTION: Unload the txPort module object * * INPUTS: hTxPort - The object to free * * OUTPUT: None * * RETURNS: TI_OK ****************************************************************************/ TI_STATUS txPort_unLoad(TI_HANDLE hTxPort) { TTxPortObj *pTxPort = (TTxPortObj *)hTxPort; if (pTxPort) os_memoryFree(pTxPort->hOs, pTxPort, sizeof(TTxPortObj)); return TI_OK; } /**************************************************************************** * txPort_init() **************************************************************************** * DESCRIPTION: Configure the txPort module object * * INPUTS: The needed TI handles * * OUTPUT: None * * RETURNS: void ****************************************************************************/ void txPort_init (TStadHandlesList *pStadHandles) { TTxPortObj *pTxPort = (TTxPortObj *)(pStadHandles->hTxPort); pTxPort->hReport = pStadHandles->hReport; pTxPort->hTxDataQ = pStadHandles->hTxDataQ; pTxPort->hTxMgmtQ = pStadHandles->hTxMgmtQ; pTxPort->queuesMuxState = MUX_MGMT_QUEUES; pTxPort->txSuspended = TI_FALSE; pTxPort->mgmtQueueEnabled = TI_TRUE; pTxPort->dataQueueEnabled = TI_FALSE; } /**************************************************************************** * txPort_enableData() **************************************************************************** * DESCRIPTION: Called by the txMgmtQueue SM when the Tx path CAN be used by the * data-queues (i.e. it's not needed for mgmt). Update the queues accordingly. ****************************************************************************/ void txPort_enableData(TI_HANDLE hTxPort) { TTxPortObj *pTxPort = (TTxPortObj *)hTxPort; pTxPort->queuesMuxState = MUX_DATA_QUEUES; updateQueuesStates(pTxPort); } /**************************************************************************** * txPort_enableMgmt() **************************************************************************** * DESCRIPTION: Called by the txMgmtQueue SM when the Tx path CAN'T be used by the * data-queues (i.e. it's needed for mgmt). Update the queues accordingly. ****************************************************************************/ void txPort_enableMgmt(TI_HANDLE hTxPort) { TTxPortObj *pTxPort = (TTxPortObj *)hTxPort; pTxPort->queuesMuxState = MUX_MGMT_QUEUES; updateQueuesStates(pTxPort); } /**************************************************************************** * txPort_suspendTx() **************************************************************************** * DESCRIPTION: Used by STAD applications (e.g. recovery) to temporarily suspend the Tx path. ****************************************************************************/ void txPort_suspendTx(TI_HANDLE hTxPort) { TTxPortObj *pTxPort = (TTxPortObj *)hTxPort; pTxPort->txSuspended = TI_TRUE; updateQueuesStates(pTxPort); } /**************************************************************************** * txPort_resumeTx() **************************************************************************** * DESCRIPTION: Used by STAD applications (e.g. recovery) to resume Tx path after suspended. ****************************************************************************/ void txPort_resumeTx(TI_HANDLE hTxPort) { TTxPortObj *pTxPort = (TTxPortObj *)hTxPort; pTxPort->txSuspended = TI_FALSE; updateQueuesStates(pTxPort); } /**************************************************************************** * updateQueuesStates() **************************************************************************** * DESCRIPTION: Switch the Data-Queue and Mgmt-Queue Tx on/off (stop/wake) * according to the current port conditions. ****************************************************************************/ static void updateQueuesStates (TTxPortObj *pTxPort) { EQueueAction mgmtQueueAction = QUEUE_ACTION_NONE; EQueueAction dataQueueAction = QUEUE_ACTION_NONE; /* * If the Tx path is not suspended: */ if (!pTxPort->txSuspended) { /* If mgmt-queues should be enabled, set required actions (awake mgmt and stop data if needed). */ if (pTxPort->queuesMuxState == MUX_MGMT_QUEUES) { if ( !pTxPort->mgmtQueueEnabled ) mgmtQueueAction = QUEUE_ACTION_WAKE; if ( pTxPort->dataQueueEnabled ) dataQueueAction = QUEUE_ACTION_STOP; } /* If data-queues should be enabled, set required actions (stop mgmt and awake data if needed). */ else { if ( pTxPort->mgmtQueueEnabled ) mgmtQueueAction = QUEUE_ACTION_STOP; if ( !pTxPort->dataQueueEnabled ) dataQueueAction = QUEUE_ACTION_WAKE; } } /* * If the Tx path is not available (Xfer is busy or suspension is requested), * set required actions (stop mgmt and data if needed). */ else { if ( pTxPort->mgmtQueueEnabled ) mgmtQueueAction = QUEUE_ACTION_STOP; if ( pTxPort->dataQueueEnabled ) dataQueueAction = QUEUE_ACTION_STOP; } #ifdef TI_DBG TRACE1(pTxPort->hReport, REPORT_SEVERITY_INFORMATION, ": queuesMuxState = , TxSuspend = %d\n", pTxPort->txSuspended); TRACE2(pTxPort->hReport, REPORT_SEVERITY_INFORMATION, ": PrevMgmtEnabled = %d, PrevDataEnabled = %d, MgmtAction = , DataAction = \n", pTxPort->mgmtQueueEnabled, pTxPort->dataQueueEnabled); #endif /* TI_DBG */ /* * Execute the required actions. * Note: This is done at the end of this function because it may start a sequence that will call it again!! * Always do WAKE action after STOP action, since WAKE may lead to more activities!! */ if (mgmtQueueAction == QUEUE_ACTION_STOP) { pTxPort->mgmtQueueEnabled = TI_FALSE; txMgmtQ_StopAll (pTxPort->hTxMgmtQ); } if (dataQueueAction == QUEUE_ACTION_STOP) { pTxPort->dataQueueEnabled = TI_FALSE; txDataQ_StopAll (pTxPort->hTxDataQ); } if (mgmtQueueAction == QUEUE_ACTION_WAKE) { pTxPort->mgmtQueueEnabled = TI_TRUE; txMgmtQ_WakeAll (pTxPort->hTxMgmtQ); } if (dataQueueAction == QUEUE_ACTION_WAKE) { pTxPort->dataQueueEnabled = TI_TRUE; txDataQ_WakeAll (pTxPort->hTxDataQ); } }