blob: eeba41fd9e13d15613bba187e2fb32424d90cd13 [file] [log] [blame]
/*
* 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);
}
}