diff options
Diffstat (limited to 'wilink_6_1/TWD/FW_Transfer/txResult.c')
-rw-r--r-- | wilink_6_1/TWD/FW_Transfer/txResult.c | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/wilink_6_1/TWD/FW_Transfer/txResult.c b/wilink_6_1/TWD/FW_Transfer/txResult.c new file mode 100644 index 0000000..ab33faf --- /dev/null +++ b/wilink_6_1/TWD/FW_Transfer/txResult.c @@ -0,0 +1,462 @@ +/* + * txResult.c + * + * Copyright(c) 1998 - 2009 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: txResult.c + * + * PURPOSE: Handle packets Tx results upon Tx-complete from the FW. + * + * DESCRIPTION: + * ============ + * This module is called upon Tx-complete from FW. + * It retrieves the transmitted packets results from the FW TxResult table and + * calls the upper layer callback function for each packet with its results. + * + ****************************************************************************/ + +#define __FILE_ID__ FILE_ID_107 +#include "tidef.h" +#include "osApi.h" +#include "report.h" +#include "TwIf.h" +#include "txCtrlBlk_api.h" +#include "txResult_api.h" +#include "TWDriver.h" +#include "FwEvent_api.h" + + + +#define TX_RESULT_QUEUE_DEPTH_MASK (TRQ_DEPTH - 1) + +#if (TX_RESULT_QUEUE_DEPTH_MASK & TRQ_DEPTH) + #error TRQ_DEPTH should be a power of 2 !! +#endif + + +/* Callback function definition for Tx sendPacketComplete */ +typedef void (* TSendPacketCompleteCb)(TI_HANDLE hCbObj, TxResultDescriptor_t *pTxResultInfo); + +/* Tx-Result SM states */ +typedef enum +{ + TX_RESULT_STATE_IDLE, + TX_RESULT_STATE_READING +} ETxResultState; + +/* The host Tx-results counter write transaction structure. */ +typedef struct +{ + TTxnStruct tTxnStruct; + TI_UINT32 uCounter; +} THostCounterWriteTxn; + +/* The Tx-results counters and table read transaction structure. */ +typedef struct +{ + TTxnStruct tTxnStruct; + TxResultInterface_t tTxResultInfo; +} TResultsInfoReadTxn; + +/* The TxResult module object. */ +typedef struct +{ + TI_HANDLE hOs; + TI_HANDLE hReport; + TI_HANDLE hTwIf; + + TI_UINT32 uTxResultInfoAddr; /* The HW Tx-Result Table address */ + TI_UINT32 uTxResultHostCounterAddr;/* The Tx-Result host counter address in SRAM */ + TI_UINT32 uHostResultsCounter; /* Number of results read by host from queue since FW-init (updated to FW) */ + ETxResultState eState; /* Current eState of SM */ + TSendPacketCompleteCb fSendPacketCompleteCb; /* Tx-Complete callback function */ + TI_HANDLE hSendPacketCompleteHndl; /* Tx-Complete callback function handle */ + THostCounterWriteTxn tHostCounterWriteTxn; /* The structure used for writing host results counter to FW */ + TResultsInfoReadTxn tResultsInfoReadTxn; /* The structure used for reading Tx-results counters and table from FW */ +#ifdef TI_DBG + TI_UINT32 uInterruptsCounter; /* Count number of Tx-results */ +#endif + +} TTxResultObj; + + +static void txResult_Restart (TTxResultObj *pTxResult); +static void txResult_HandleNewResults (TTxResultObj *pTxResult); +static void txResult_StateMachine (TI_HANDLE hTxResult); + + + +/**************************************************************************** + * txResult_Create() + **************************************************************************** + * DESCRIPTION: Create the Tx-Result object + * + * INPUTS: hOs + * + * OUTPUT: None + * + * RETURNS: The Created object + ****************************************************************************/ +TI_HANDLE txResult_Create(TI_HANDLE hOs) +{ + TTxResultObj *pTxResult; + + pTxResult = os_memoryAlloc(hOs, sizeof(TTxResultObj)); + if (pTxResult == NULL) + return NULL; + + os_memoryZero(hOs, pTxResult, sizeof(TTxResultObj)); + + pTxResult->hOs = hOs; + + return( (TI_HANDLE)pTxResult ); +} + + +/**************************************************************************** + * txResult_Destroy() + **************************************************************************** + * DESCRIPTION: Destroy the Tx-Result object + * + * INPUTS: hTxResult - The object to free + * + * OUTPUT: None + * + * RETURNS: TI_OK or TI_NOK + ****************************************************************************/ +TI_STATUS txResult_Destroy(TI_HANDLE hTxResult) +{ + TTxResultObj *pTxResult = (TTxResultObj *)hTxResult; + + if (pTxResult) + os_memoryFree(pTxResult->hOs, pTxResult, sizeof(TTxResultObj)); + + return TI_OK; +} + + +/**************************************************************************** + * txResult_Init() + **************************************************************************** + DESCRIPTION: + ============ + Initialize the txResult module. + ****************************************************************************/ +TI_STATUS txResult_Init(TI_HANDLE hTxResult, TI_HANDLE hReport, TI_HANDLE hTwIf) +{ + TTxResultObj *pTxResult = (TTxResultObj *)hTxResult; + TTxnStruct *pTxn; + + pTxResult->hReport = hReport; + pTxResult->hTwIf = hTwIf; + + /* Prepare Host-Results-Counter write transaction (HwAddr is filled before each transaction) */ + pTxn = &pTxResult->tHostCounterWriteTxn.tTxnStruct; + TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) + BUILD_TTxnStruct(pTxn, 0, &pTxResult->tHostCounterWriteTxn.uCounter, REGISTER_SIZE, NULL, NULL) + + /* Prepare Tx-Result counter and table read transaction (HwAddr is filled before each transaction) */ + pTxn = &pTxResult->tResultsInfoReadTxn.tTxnStruct; + TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR) + BUILD_TTxnStruct(pTxn, + 0, + &pTxResult->tResultsInfoReadTxn.tTxResultInfo, + sizeof(TxResultInterface_t), + (TTxnDoneCb)txResult_StateMachine, + hTxResult) + + txResult_Restart (pTxResult); + + return TI_OK; +} + + +/**************************************************************************** + * txResult_Restart() + **************************************************************************** + DESCRIPTION: + ============ + Restarts the Tx-Result module. + Called upon init and recovery. + Shouldn't be called upon disconnect, since the FW provides Tx-Complete + for all pending packets in FW!! + ****************************************************************************/ +static void txResult_Restart (TTxResultObj *pTxResult) +{ + pTxResult->uHostResultsCounter = 0; + pTxResult->eState = TX_RESULT_STATE_IDLE; +} + + +/**************************************************************************** + * txResult_setHwInfo() + **************************************************************************** + * DESCRIPTION: + * Called after the HW configuration upon init or recovery. + * Store the Tx-result table HW address. + ****************************************************************************/ +void txResult_setHwInfo(TI_HANDLE hTxResult, TDmaParams *pDmaParams) +{ + TTxResultObj *pTxResult = (TTxResultObj *)hTxResult; + + pTxResult->uTxResultInfoAddr = (TI_UINT32)(pDmaParams->fwTxResultInterface); + pTxResult->uTxResultHostCounterAddr = pTxResult->uTxResultInfoAddr + + TI_FIELD_OFFSET(TxResultControl_t, TxResultHostCounter); + + txResult_Restart (pTxResult); +} + + +/**************************************************************************** + * txResult_TxCmpltIntrCb() + **************************************************************************** + * DESCRIPTION: + * ============ + * Called upon DATA interrupt from the FW. + * If new Tx results are available, start handling them. + * + * INPUTS: hTxResult - the txResult object handle. + * pFwStatus - The FW status registers read by the FwEvent + * + * OUTPUT: None + * + * RETURNS: void + ***************************************************************************/ +void txResult_TxCmpltIntrCb (TI_HANDLE hTxResult, FwStatus_t *pFwStatus) +{ + TTxResultObj *pTxResult = (TTxResultObj *)hTxResult; + TI_UINT32 uTempCounters; + FwStatCntrs_t *pFwStatusCounters; + +#ifdef TI_DBG + pTxResult->uInterruptsCounter++; + + if (pTxResult->eState != TX_RESULT_STATE_IDLE) + { + TRACE1(pTxResult->hReport, REPORT_SEVERITY_INFORMATION, ": called in eState %d, so exit\n", pTxResult->eState); + return; + } +#endif + + /* If no new results - exit (may happen since Data interrupt is common to all Tx&Rx events) */ + uTempCounters = ENDIAN_HANDLE_LONG(pFwStatus->counters); + pFwStatusCounters = (FwStatCntrs_t *)&uTempCounters; + if (pFwStatusCounters->txResultsCntr == (TI_UINT8)pTxResult->uHostResultsCounter) + { + TRACE0(pTxResult->hReport, REPORT_SEVERITY_INFORMATION, ": No new Tx results\n"); + return; + } + + /* Call the SM to handle the new Tx results */ + txResult_StateMachine (hTxResult); +} + + +/**************************************************************************** + * txResult_StateMachine() + **************************************************************************** + * DESCRIPTION: + * + * The main SM of the module. Called in IDLE eState by txResult_TxCmpltIntrCb() on + * Data interrupt from the FW. + * If no new results - exit (may happen since Data interrupt is common to all Tx&Rx events) + * Read all Tx-Result cyclic table. + * Go over the new Tx-results and call the upper layer callback function for each packet result. + * At the end - write the new host counter to the FW. + * + * INPUTS: + * + * OUTPUT: + * + * RETURNS: None + ****************************************************************************/ +static void txResult_StateMachine (TI_HANDLE hTxResult) +{ + TTxResultObj *pTxResult = (TTxResultObj *)hTxResult; + ETxnStatus eTwifStatus = TXN_STATUS_COMPLETE; /* Last bus operation status: Complete (Sync) or Pending (Async). */ + TTxnStruct *pTxn = &(pTxResult->tResultsInfoReadTxn.tTxnStruct); + + /* Loop while processing is completed in current context (sync), or until fully completed */ + while (eTwifStatus == TXN_STATUS_COMPLETE) + { + TRACE2(pTxResult->hReport, REPORT_SEVERITY_INFORMATION, ": eState = %d, eTwifStatus = %d\n", pTxResult->eState, eTwifStatus); + + switch(pTxResult->eState) + { + case TX_RESULT_STATE_IDLE: + /* Read Tx-Result queue and counters. */ + pTxn->uHwAddr = pTxResult->uTxResultInfoAddr; + eTwifStatus = twIf_Transact (pTxResult->hTwIf, pTxn); + + pTxResult->eState = TX_RESULT_STATE_READING; + break; + + case TX_RESULT_STATE_READING: + /* Process new Tx results, call upper layers to handle them and update host-index in the FW. */ + txResult_HandleNewResults (pTxResult); + pTxResult->eState = TX_RESULT_STATE_IDLE; + return; /********* Exit after all processing is finished **********/ + + default: + TRACE1(pTxResult->hReport, REPORT_SEVERITY_ERROR, ": Unknown eState = %d\n", pTxResult->eState); + return; + } + } + + if (eTwifStatus == TXN_STATUS_ERROR) + { + TRACE2(pTxResult->hReport, REPORT_SEVERITY_ERROR, ": returning ERROR in eState %d, eTwifStatus=%d !!!\n", pTxResult->eState, eTwifStatus); + } +} + + +/**************************************************************************** + * txResult_HandleNewResults() + **************************************************************************** + * DESCRIPTION: + * ============ + * We now have the Tx Result table info from the FW so do as follows: + * 1. Find the number of new results (FW counter minus host counter), and if 0 exit. + * 2. Call the upper layers callback per Tx result. + * 3. Update Host-Counter to be equal to the FW-Counter, and write it to the FW. + ***************************************************************************/ +static void txResult_HandleNewResults (TTxResultObj *pTxResult) +{ + TI_UINT32 uNumNewResults; /* The number of new Tx-Result entries to be processed. */ + TI_UINT32 uFwResultsCounter; /* The FW current results counter (accumulated). */ + TI_UINT32 uTableIndex; + TI_UINT32 i; + TxResultDescriptor_t *pCurrentResult; + TTxnStruct *pTxn = &(pTxResult->tHostCounterWriteTxn.tTxnStruct); + + /* The uFwResultsCounter is the accumulated number of Tx-Results provided by the FW, and the + * uHostResultsCounter is the accumulated number of Tx-Results processed by the host. + * The delta is the number of new Tx-results in the queue, waiting for host processing. + * Since the difference is always a small positive number, a simple subtraction is good + * also for wrap around case. + */ + uFwResultsCounter = ENDIAN_HANDLE_LONG(pTxResult->tResultsInfoReadTxn.tTxResultInfo.TxResultControl.TxResultFwCounter); + uNumNewResults = uFwResultsCounter - pTxResult->uHostResultsCounter; + +#ifdef TI_DBG + /* Verify there are new entries (was already checked in txResult_TxCmpltIntrCb) */ + if (uNumNewResults == 0) + { +TRACE2(pTxResult->hReport, REPORT_SEVERITY_WARNING, ": No New Results although indicated by FwStatus!! HostCount=%d, FwCount=%d\n", pTxResult->uHostResultsCounter, uFwResultsCounter); + return; + } +#endif + + /* Update host results-counter in FW to be equal to the FW counter (all new results were processed). */ + pTxResult->tHostCounterWriteTxn.uCounter = ENDIAN_HANDLE_LONG(uFwResultsCounter); + pTxn->uHwAddr = pTxResult->uTxResultHostCounterAddr; + twIf_Transact(pTxResult->hTwIf, pTxn); + + TRACE3(pTxResult->hReport, REPORT_SEVERITY_INFORMATION, ": NumResults=%d, OriginalHostCount=%d, FwCount=%d\n", uNumNewResults, pTxResult->uHostResultsCounter, uFwResultsCounter); + + /* Loop over all new Tx-results and call Tx-complete callback with current entry pointer. */ + /* NOTE: THIS SHOULD COME LAST because it may lead to driver-stop process!! */ + for (i = 0; i < uNumNewResults; i++) + { + uTableIndex = pTxResult->uHostResultsCounter & TX_RESULT_QUEUE_DEPTH_MASK; + pCurrentResult = &(pTxResult->tResultsInfoReadTxn.tTxResultInfo.TxResultQueue[uTableIndex]); + pTxResult->uHostResultsCounter++; + + TRACE1(pTxResult->hReport, REPORT_SEVERITY_INFORMATION , ": call upper layer CB, Status = %d\n", pCurrentResult->status); + + pTxResult->fSendPacketCompleteCb (pTxResult->hSendPacketCompleteHndl, pCurrentResult); + } +} + + +/**************************************************************************** + * txResult_RegisterCb() + **************************************************************************** + * DESCRIPTION: Register the upper driver Tx-Result callback functions. + ****************************************************************************/ +void txResult_RegisterCb (TI_HANDLE hTxResult, TI_UINT32 uCallBackId, void *CBFunc, TI_HANDLE hCbObj) +{ + TTxResultObj* pTxResult = (TTxResultObj*)hTxResult; + + switch (uCallBackId) + { + /* Set Tx-Complete callback */ + case TWD_INT_SEND_PACKET_COMPLETE: + pTxResult->fSendPacketCompleteCb = (TSendPacketCompleteCb)CBFunc; + pTxResult->hSendPacketCompleteHndl = hCbObj; + break; + + default: + TRACE0(pTxResult->hReport, REPORT_SEVERITY_ERROR, ": Illegal value\n"); + return; + } +} + + +#ifdef TI_DBG /* Debug Functions */ + +/**************************************************************************** + * txResult_PrintInfo() + **************************************************************************** + * DESCRIPTION: Prints TX result debug information. + ****************************************************************************/ +void txResult_PrintInfo (TI_HANDLE hTxResult) +{ +#ifdef REPORT_LOG + TTxResultObj* pTxResult = (TTxResultObj*)hTxResult; + + WLAN_OS_REPORT(("Tx-Result Module Information:\n")); + WLAN_OS_REPORT(("=============================\n")); + WLAN_OS_REPORT(("uInterruptsCounter: %d\n", pTxResult->uInterruptsCounter)); + WLAN_OS_REPORT(("uHostResultsCounter: %d\n", pTxResult->uHostResultsCounter)); + WLAN_OS_REPORT(("=============================\n")); +#endif +} + + +/**************************************************************************** + * txResult_ClearInfo() + **************************************************************************** + * DESCRIPTION: Clears TX result debug information. + ****************************************************************************/ +void txResult_ClearInfo (TI_HANDLE hTxResult) +{ + TTxResultObj* pTxResult = (TTxResultObj*)hTxResult; + + pTxResult->uInterruptsCounter = 0; +} + +#endif /* TI_DBG */ + + |