diff options
Diffstat (limited to 'wl1271/TWD/FW_Transfer/FwEvent.c')
-rw-r--r-- | wl1271/TWD/FW_Transfer/FwEvent.c | 792 |
1 files changed, 0 insertions, 792 deletions
diff --git a/wl1271/TWD/FW_Transfer/FwEvent.c b/wl1271/TWD/FW_Transfer/FwEvent.c deleted file mode 100644 index 6672aea..0000000 --- a/wl1271/TWD/FW_Transfer/FwEvent.c +++ /dev/null @@ -1,792 +0,0 @@ -/* - * FwEvent.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. - */ - - -/** \file FwEvent.c - * \brief Handle firmware events - * - * - * \par Description - * Call the appropriate event handler. - * - * \see FwEvent.h - */ - -#define __FILE_ID__ FILE_ID_104 -#include "tidef.h" -#include "report.h" -#include "context.h" -#include "osApi.h" -#include "TWDriver.h" -#include "TWDriverInternal.h" -#include "txResult_api.h" -#include "CmdMBox_api.h" -#include "rxXfer_api.h" -#include "txXfer_api.h" -#include "txHwQueue_api.h" -#include "eventMbox_api.h" -#include "TwIf.h" -#include "public_host_int.h" -#include "FwEvent_api.h" -#ifdef TI_DBG - #include "tracebuf_api.h" -#endif -#include "bmtrace_api.h" - - -#ifdef _VLCT_ -extern int trigger_another_read; -#endif - - -/* - * Address of FW-Status structure in FW memory ==> Special mapping, see note!! - * - * Note: This structure actually includes two separate areas in the FW: - * 1) Interrupt-Status register - a 32 bit register (clear on read). - * 2) FW-Status structure - 64 bytes memory area - * The two areas are read in a single transaction thanks to a special memory - * partition that maps them as contiguous memory. - */ -#define FW_STATUS_ADDR 0x14FC0 + 0xA000 - - -#define ALL_EVENTS_VECTOR ACX_INTR_WATCHDOG | ACX_INTR_INIT_COMPLETE | ACX_INTR_EVENT_A |\ - ACX_INTR_EVENT_B | ACX_INTR_CMD_COMPLETE |ACX_INTR_HW_AVAILABLE |\ - ACX_INTR_DATA - -#define TXN_FW_EVENT_SET_MASK_ADDR(pFwEvent) pFwEvent->tMaskTxn.tTxnStruct.uHwAddr = HINT_MASK; -#define TXN_FW_EVENT_SET_FW_STAT_ADDR(pFwEvent) pFwEvent->tFwStatusTxn.tTxnStruct.uHwAddr = FW_STATUS_ADDR; - -#define UPDATE_PENDING_HANDLERS_NUMBER(eStatus) if (eStatus == TXN_STATUS_PENDING) {pFwEvent->uNumPendHndlrs++;} - - -typedef enum -{ - FWEVENT_STATE_IDLE, - FWEVENT_STATE_WAIT_INTR_INFO, - FWEVENT_STATE_WAIT_HANDLE_COMPLT - -} EFwEventState; - -typedef struct -{ - TTxnStruct tTxnStruct; - TI_UINT32 uData; - -} TRegisterTxn; - -typedef struct -{ - TTxnStruct tTxnStruct; - FwStatus_t tFwStatus; - -} TFwStatusTxn; - -/* The FwEvent module's main structure */ -typedef struct -{ - EFwEventState eSmState; /* State machine state */ - TI_UINT32 uEventMask; /* Static interrupt event mask */ - TI_UINT32 uEventVector; /* Saves the current active FW interrupts */ - TRegisterTxn tMaskTxn; /* The host mask register transaction */ - TFwStatusTxn tFwStatusTxn; /* The FW status structure transaction (read from FW memory) */ - TI_UINT32 uFwTimeOffset; /* Offset in microseconds between driver and FW clocks */ - TI_UINT32 uContextId; /* Client ID got upon registration to the context module */ - TI_BOOL bIntrPending; /* If TRUE a new interrupt is pending while handling the previous one */ - TI_UINT32 uNumPendHndlrs; /* Number of event handlers that didn't complete their event processing */ - - /* Other modules handles */ - TI_HANDLE hOs; - TI_HANDLE hTWD; - TI_HANDLE hReport; - TI_HANDLE hContext; - TI_HANDLE hTwIf; - TI_HANDLE hHealthMonitor; - TI_HANDLE hEventMbox; - TI_HANDLE hCmdMbox; - TI_HANDLE hRxXfer; - TI_HANDLE hTxXfer; - TI_HANDLE hTxHwQueue; - TI_HANDLE hTxResult; - -} TfwEvent; - - -static void fwEvent_NewEvent (TI_HANDLE hFwEvent); -static void fwEvent_StateMachine (TfwEvent *pFwEvent); -static ETxnStatus fwEvent_SmReadIntrInfo (TfwEvent *pFwEvent); -static ETxnStatus fwEvent_SmHandleEvents (TfwEvent *pFwEvent); -static ETxnStatus fwEvent_CallHandlers (TfwEvent *pFwEvent); - - -/* - * \brief Create the FwEvent module object - * - * \param hOs - OS module object handle - * \return Handle to the created object - * - * \par Description - * Calling this function creates a FwEvent object - * - * \sa fwEvent_Destroy - */ -TI_HANDLE fwEvent_Create (TI_HANDLE hOs) -{ - TfwEvent *pFwEvent; - - pFwEvent = os_memoryAlloc (hOs, sizeof(TfwEvent)); - if (pFwEvent == NULL) - { - return NULL; - } - - os_memoryZero (hOs, pFwEvent, sizeof(TfwEvent)); - - pFwEvent->hOs = hOs; - - return (TI_HANDLE)pFwEvent; -} - - -/* - * \brief Destroys the FwEvent object - * - * \param hFwEvent - The object to free - * \return TI_OK - * - * \par Description - * Calling this function destroys a FwEvent object - * - * \sa fwEvent_Create - */ -TI_STATUS fwEvent_Destroy (TI_HANDLE hFwEvent) -{ - TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; - - if (pFwEvent) - { - os_memoryFree (pFwEvent->hOs, pFwEvent, sizeof(TfwEvent)); - } - - return TI_OK; -} - - -/* - * \brief Config the FwEvent module object - * - * \param hFwEvent - FwEvent Driver handle - * \param hTWD - Handle to TWD module - * \return TI_OK - * - * \par Description - * From hTWD we extract : hOs, hReport, hTwIf, hContext, - * hHealthMonitor, hEventMbox, hCmdMbox, hRxXfer, - * hTxHwQueue, hTxResult - * In this function we also register the FwEvent to the context engine - * - * \sa - */ -TI_STATUS fwEvent_Init (TI_HANDLE hFwEvent, TI_HANDLE hTWD) -{ - TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; - TTwd *pTWD = (TTwd *)hTWD; - TTxnStruct* pTxn; - - pFwEvent->hTWD = hTWD; - pFwEvent->hOs = pTWD->hOs; - pFwEvent->hReport = pTWD->hReport; - pFwEvent->hContext = pTWD->hContext; - pFwEvent->hTwIf = pTWD->hTwIf; - pFwEvent->hHealthMonitor = pTWD->hHealthMonitor; - pFwEvent->hEventMbox = pTWD->hEventMbox; - pFwEvent->hCmdMbox = pTWD->hCmdMbox; - pFwEvent->hRxXfer = pTWD->hRxXfer; - pFwEvent->hTxHwQueue = pTWD->hTxHwQueue; - pFwEvent->hTxXfer = pTWD->hTxXfer; - pFwEvent->hTxResult = pTWD->hTxResult; - - pFwEvent->eSmState = FWEVENT_STATE_IDLE; - pFwEvent->bIntrPending = TI_FALSE; - pFwEvent->uNumPendHndlrs = 0; - pFwEvent->uEventMask = 0; - pFwEvent->uEventVector = 0; - - /* Prepare Interrupts Mask regiter Txn structure */ - /* - * Note!!: The mask transaction is sent in low priority because it is used in the - * init process which includes a long sequence of low priority transactions, - * and the order of this sequence is important so we must use the same priority - */ - pTxn = (TTxnStruct*)&pFwEvent->tMaskTxn.tTxnStruct; - TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) - BUILD_TTxnStruct(pTxn, HINT_MASK, &pFwEvent->tMaskTxn.uData, REGISTER_SIZE, NULL, NULL) - - /* Prepare FW status Txn structure (includes 4 bytes interrupt status reg and 64 bytes FW-status from memory area) */ - /* Note: This is the only transaction that is sent in high priority. - * The original reason was to lower the interrupt latency, but we may consider using the - * same priority as all other transaction for simplicity. - */ - pTxn = (TTxnStruct*)&pFwEvent->tFwStatusTxn.tTxnStruct; - TXN_PARAM_SET(pTxn, TXN_HIGH_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR) - BUILD_TTxnStruct(pTxn, FW_STATUS_ADDR, &pFwEvent->tFwStatusTxn.tFwStatus, sizeof(FwStatus_t), (TTxnDoneCb)fwEvent_StateMachine, hFwEvent) - - /* - * Register the FwEvent to the context engine and get the client ID. - * The FwEvent() will be called from the context_DriverTask() after scheduled - * by a FW-Interrupt (see fwEvent_InterruptRequest()). - */ - pFwEvent->uContextId = context_RegisterClient (pFwEvent->hContext, - fwEvent_NewEvent, - hFwEvent, - TI_FALSE, - "FW_EVENT", - sizeof("FW_EVENT")); - - return TI_OK; -} - - -/* - * \brief FW interrupt handler, just switch to WLAN context for handling - * - * \param hFwEvent - FwEvent Driver handle - * \return void - * - * \par Description - * Called by the FW-Interrupt ISR (external context!). - * Requests the context engine to schedule the driver task for handling the FW-Events. - * - * \sa - */ -void fwEvent_InterruptRequest (TI_HANDLE hFwEvent) -{ - TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; - CL_TRACE_START_L1(); - - TRACE0(pFwEvent->hReport, REPORT_SEVERITY_INFORMATION, "fwEvent_InterruptRequest()\n"); - - /* Request switch to driver context for handling the FW-Interrupt event */ - context_RequestSchedule (pFwEvent->hContext, pFwEvent->uContextId); - - CL_TRACE_END_L1("tiwlan_drv.ko", "IRQ", "FwEvent", ""); -} - - -/* - * \brief The CB called in the driver context upon new interrupt - * - * \param hFwEvent - FwEvent Driver handle - * \return void - * - * \par Description - * Called by the context module after scheduled by fwEvent_InterruptRequest(). - * If IDLE, start the SM, and if not just indicate pending event for later. - * - * \sa - */ -static void fwEvent_NewEvent (TI_HANDLE hFwEvent) -{ - TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; - CL_TRACE_START_L2(); - - /* If the SM is idle, call it to start handling new events */ - if (pFwEvent->eSmState == FWEVENT_STATE_IDLE) - { - TRACE0(pFwEvent->hReport, REPORT_SEVERITY_INFORMATION, "fwEvent_NewEvent: Start SM\n"); - - fwEvent_StateMachine (pFwEvent); - } - /* Else - SM is busy so set flag to handle it when finished with current events */ - else - { - TRACE0(pFwEvent->hReport, REPORT_SEVERITY_INFORMATION, "fwEvent_NewEvent: SM busy, set IntrPending flag\n"); - - pFwEvent->bIntrPending = TI_TRUE; - } - - CL_TRACE_END_L2("tiwlan_drv.ko", "CONTEXT", "FwEvent", ""); -} - - -/* - * \brief FW-Event state machine - * - * \param hFwEvent - FwEvent Driver handle - * \return void - * - * \par Description - * - * Process the current FW events in a sequence that may progress in the same context, - * or exit if pending an Async transaction, which will call back the SM when finished. - * - * \sa - */ -static void fwEvent_StateMachine (TfwEvent *pFwEvent) -{ - ETxnStatus eStatus = TXN_STATUS_ERROR; /* Set to error to detect if used uninitialized */ - CL_TRACE_START_L3(); - - /* - * Loop through the states sequence as long as the process is synchronous. - * Exit when finished or if an Asynchronous process is required. - * In this case the SM will be called back upon Async operation completion. - */ - while (1) - { - switch (pFwEvent->eSmState) - { - /* IDLE: Update TwIf and read interrupt info from FW */ - case FWEVENT_STATE_IDLE: - { - CL_TRACE_START_L5(); - twIf_Awake(pFwEvent->hTwIf); - eStatus = fwEvent_SmReadIntrInfo (pFwEvent); - pFwEvent->eSmState = FWEVENT_STATE_WAIT_INTR_INFO; - CL_TRACE_END_L5("tiwlan_drv.ko", "CONTEXT", "FwEvent", ".ReadInfo"); - break; - } - /* WAIT_INTR_INFO: We have the interrupt info so call the handlers accordingly */ - case FWEVENT_STATE_WAIT_INTR_INFO: - { - CL_TRACE_START_L5(); - eStatus = fwEvent_SmHandleEvents (pFwEvent); - /* If state was changed to IDLE by recovery or stop process, exit (process terminated) */ - if (pFwEvent->eSmState == FWEVENT_STATE_IDLE) - { - CL_TRACE_END_L5("tiwlan_drv.ko", "CONTEXT", "FwEvent", ".HndlEvents"); - CL_TRACE_END_L3("tiwlan_drv.ko", "CONTEXT", "FwEvent", ""); - return; - } - pFwEvent->eSmState = FWEVENT_STATE_WAIT_HANDLE_COMPLT; - CL_TRACE_END_L5("tiwlan_drv.ko", "CONTEXT", "FwEvent", ".HndlEvents"); - break; - } - /* WAIT_HANDLE_COMPLT: Current handling is completed. */ - case FWEVENT_STATE_WAIT_HANDLE_COMPLT: - { - /* If pending interrupt, read interrupt info (back to WAIT_INTR_INFO state) */ - if (pFwEvent->bIntrPending) - { - CL_TRACE_START_L5(); - pFwEvent->bIntrPending = TI_FALSE; - eStatus = fwEvent_SmReadIntrInfo (pFwEvent); - pFwEvent->eSmState = FWEVENT_STATE_WAIT_INTR_INFO; - CL_TRACE_END_L5("tiwlan_drv.ko", "CONTEXT", "FwEvent", ".HndlCmplt"); - } - /* Else - all done so release TwIf to sleep and exit */ - else - { - twIf_Sleep(pFwEvent->hTwIf); - pFwEvent->eSmState = FWEVENT_STATE_IDLE; - - TRACE3(pFwEvent->hReport, REPORT_SEVERITY_INFORMATION, "fwEvent_StateMachine: Completed, NewState=%d, Status=%d, IntrPending=%d\n", pFwEvent->eSmState, eStatus, pFwEvent->bIntrPending); - CL_TRACE_END_L3("tiwlan_drv.ko", "CONTEXT", "FwEvent", ""); - - /**** Finished all current events handling so exit ****/ - return; - } - break; - } - - } /* switch */ - - TRACE3(pFwEvent->hReport, REPORT_SEVERITY_INFORMATION, "fwEvent_StateMachine: NewState=%d, Status=%d, IntrPending=%d\n", pFwEvent->eSmState, eStatus, pFwEvent->bIntrPending); - - /* If last status is Pending, exit the SM (to be called back upon Async operation completion) */ - if (eStatus == TXN_STATUS_PENDING) - { - CL_TRACE_END_L3("tiwlan_drv.ko", "CONTEXT", "FwEvent", ""); - return; - } - - /* If error occured, stop the process and exit (should be cleaned by recovery process) */ - else if (eStatus == TXN_STATUS_ERROR) - { - TRACE5(pFwEvent->hReport, REPORT_SEVERITY_ERROR, "fwEvent_StateMachine: NewState=%d, Status=%d, IntrPending=%d, EventVector=0x%x, EventMask=0x%x\n", pFwEvent->eSmState, eStatus, pFwEvent->bIntrPending, pFwEvent->uEventVector, pFwEvent->uEventMask); - CL_TRACE_END_L3("tiwlan_drv.ko", "CONTEXT", "FwEvent", ""); - fwEvent_Stop ((TI_HANDLE)pFwEvent); - return; - } - - /* If we got here the status is COMPLETE so continue in the while loop to the next state */ - - } /* while */ -} - - -/* - * \brief Read interrupt info from FW - * - * \param hFwEvent - FwEvent Driver handle - * \return void - * - * \par Description - * - * Indicate the TwIf that HW is available and initiate transactions for reading - * the Interrupt status and the FW status. - * - * \sa - */ -static ETxnStatus fwEvent_SmReadIntrInfo (TfwEvent *pFwEvent) -{ - ETxnStatus eStatus; - CL_TRACE_START_L4(); - -#ifdef HOST_INTR_MODE_EDGE - /* Acknowledge the host interrupt for EDGE mode (must be before HINT_STT_CLR register clear on read) */ - os_InterruptServiced (pFwEvent->hOs); -#endif - - /* Indicate that the chip is awake (since it interrupted us) */ - twIf_HwAvailable(pFwEvent->hTwIf); - - /* - * Read FW-Status structure from HW ==> Special mapping, see note!! - * - * Note: This structure actually includes two separate areas in the FW: - * 1) Interrupt-Status register - a 32 bit register (clear on read). - * 2) FW-Status structure - 64 bytes memory area - * The two areas are read in a single transaction thanks to a special memory - * partition that maps them as contiguous memory. - */ - TXN_FW_EVENT_SET_FW_STAT_ADDR(pFwEvent) - eStatus = twIf_TransactReadFWStatus (pFwEvent->hTwIf, &(pFwEvent->tFwStatusTxn.tTxnStruct)); - - CL_TRACE_END_L4("tiwlan_drv.ko", "CONTEXT", "FwEvent", ""); - - /* Return the status of the FwStatus read (complete, pending or error) */ - return eStatus; -} - - -/* - * \brief Handle the Fw Status information - * - * \param hFwEvent - FwEvent Driver handle - * \return void - * - * \par Description - * This function is called from fwEvent_Handle on a sync read, or from TwIf as a CB on an async read. - * It calls fwEvent_CallHandlers to handle the triggered interrupts. - * - * \sa fwEvent_Handle - */ -static ETxnStatus fwEvent_SmHandleEvents (TfwEvent *pFwEvent) -{ - ETxnStatus eStatus; - CL_TRACE_START_L4(); - - /* Save delta between driver and FW time (needed for Tx packets lifetime) */ - pFwEvent->uFwTimeOffset = (os_timeStampMs (pFwEvent->hOs) * 1000) - - ENDIAN_HANDLE_LONG (pFwEvent->tFwStatusTxn.tFwStatus.fwLocalTime); - -#ifdef HOST_INTR_MODE_LEVEL - /* Acknowledge the host interrupt for LEVEL mode (must be after HINT_STT_CLR register clear on read) */ - os_InterruptServiced (pFwEvent->hOs); -#endif - - /* Save the interrupts status retreived from the FW */ - pFwEvent->uEventVector = pFwEvent->tFwStatusTxn.tFwStatus.intrStatus; - - /* Mask unwanted interrupts */ - pFwEvent->uEventVector &= pFwEvent->uEventMask; - - /* Call the interrupts handlers */ - eStatus = fwEvent_CallHandlers (pFwEvent); - - TRACE5(pFwEvent->hReport, REPORT_SEVERITY_INFORMATION, "fwEvent_SmHandleEvents: Status=%d, EventVector=0x%x, IntrPending=%d, NumPendHndlrs=%d, FwTimeOfst=%d\n", eStatus, pFwEvent->uEventVector, pFwEvent->bIntrPending, pFwEvent->uNumPendHndlrs, pFwEvent->uFwTimeOffset); - CL_TRACE_END_L4("tiwlan_drv.ko", "CONTEXT", "FwEvent", ""); - - /* Return the status of the handlers processing (complete, pending or error) */ - return eStatus; -} - - -/* - * \brief Call FwEvent clients event handlers - * - * \param hFwEvent - FwEvent Driver handle - * \return void - * - * \par Description - * - * \sa - */ -static ETxnStatus fwEvent_CallHandlers (TfwEvent *pFwEvent) -{ - ETxnStatus eStatus; - CL_TRACE_START_L4(); - - pFwEvent->uNumPendHndlrs = 0; - - if (pFwEvent->uEventVector & ACX_INTR_WATCHDOG) - { - /* Fw watchdog timeout has occured */ - eStatus = TWD_WdExpireEvent (pFwEvent->hTWD); - UPDATE_PENDING_HANDLERS_NUMBER(eStatus) - } - - if (pFwEvent->uEventVector & ACX_INTR_INIT_COMPLETE) - { - TRACE0(pFwEvent->hReport, REPORT_SEVERITY_INFORMATION, "fwEvent_CallHandlers: INIT_COMPLETE\n"); - } - /* Note: Handle Cmd-MBOX before Event-MBOX to keep command response and command complete order (for WHA) */ - if (pFwEvent->uEventVector & ACX_INTR_CMD_COMPLETE) - { - /* Command Mbox completed */ - eStatus = cmdMbox_CommandComplete(pFwEvent->hCmdMbox); - UPDATE_PENDING_HANDLERS_NUMBER(eStatus) - } - if (pFwEvent->uEventVector & ACX_INTR_EVENT_A) - { - eStatus = eventMbox_Handle(pFwEvent->hEventMbox,&pFwEvent->tFwStatusTxn.tFwStatus); - UPDATE_PENDING_HANDLERS_NUMBER(eStatus) - } - if (pFwEvent->uEventVector & ACX_INTR_EVENT_B) - { - eStatus = eventMbox_Handle(pFwEvent->hEventMbox,&pFwEvent->tFwStatusTxn.tFwStatus); - UPDATE_PENDING_HANDLERS_NUMBER(eStatus) - } - - /* The DATA interrupt is shared by all data path events, so call all Tx and Rx clients */ - if (pFwEvent->uEventVector & ACX_INTR_DATA) - { - eStatus = rxXfer_RxEvent (pFwEvent->hRxXfer, &pFwEvent->tFwStatusTxn.tFwStatus); - UPDATE_PENDING_HANDLERS_NUMBER(eStatus) - - eStatus = txHwQueue_UpdateFreeResources (pFwEvent->hTxHwQueue, &pFwEvent->tFwStatusTxn.tFwStatus); - UPDATE_PENDING_HANDLERS_NUMBER(eStatus) - - eStatus = txResult_TxCmpltIntrCb (pFwEvent->hTxResult, &pFwEvent->tFwStatusTxn.tFwStatus); - UPDATE_PENDING_HANDLERS_NUMBER(eStatus) - } - - CL_TRACE_END_L4("tiwlan_drv.ko", "CONTEXT", "FwEvent", ""); - - /* Return COMPLETE if all handlers completed, and PENDING if not. */ - return ((pFwEvent->uNumPendHndlrs == 0) ? TXN_STATUS_COMPLETE : TXN_STATUS_PENDING); -} - - -/* - * \brief Called by any handler that completed after pending - * - * \param hFwEvent - FwEvent Driver handle - * - * \par Description - * - * Decrement pending handlers counter and if 0 call the SM to complete its process. - * - * \sa - */ -void fwEvent_HandlerCompleted (TI_HANDLE hFwEvent) -{ - TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; - -#ifdef TI_DBG - TRACE2(pFwEvent->hReport, REPORT_SEVERITY_INFORMATION, "fwEvent_HandlerCompleted: state=%d, NumPendHndlrs=%d\n", pFwEvent->eSmState, pFwEvent->uNumPendHndlrs); - /* Verify that we really have pending handlers, otherwise it an error */ - if (pFwEvent->uNumPendHndlrs == 0) - { - TRACE0(pFwEvent->hReport, REPORT_SEVERITY_ERROR, "fwEvent_HandlerCompleted: Called while no handlers are pending\n"); - return; - } - /* Verify that we are in */ - if (pFwEvent->eSmState != FWEVENT_STATE_WAIT_HANDLE_COMPLT) - { - TRACE1(pFwEvent->hReport, REPORT_SEVERITY_ERROR, "fwEvent_HandlerCompleted: Called while not in WAIT_HANDLE_COMPLT state (state=%d)\n", pFwEvent->eSmState); - return; - } -#endif - - /* Decrement the pending handlers counter and if zero call the SM to complete the process */ - pFwEvent->uNumPendHndlrs--; - if (pFwEvent->uNumPendHndlrs == 0) - { - fwEvent_StateMachine (pFwEvent); - } -} - - -/* - * \brief Translate host to FW time (Usec) - * - * \param hFwEvent - FwEvent Driver handle - * \param uHostTime - The host time in MS to translate - * - * \return FW Time in Usec - * - * \par Description - * - * \sa - */ -TI_UINT32 fwEvent_TranslateToFwTime (TI_HANDLE hFwEvent, TI_UINT32 uHostTime) -{ - TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; - - return ((uHostTime * 1000) - pFwEvent->uFwTimeOffset); -} - - -/* - * \brief Unmask only cmd-cmplt and events interrupts (needed for init phase) - * - * \param hFwEvent - FwEvent Driver handle - * \return Event mask - * - * \par Description - * Unmask only cmd-cmplt and events interrupts (needed for init phase). - * - * \sa - */ -void fwEvent_SetInitMask (TI_HANDLE hFwEvent) -{ - TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; - - /* Unmask only the interrupts needed for the FW configuration process. */ - pFwEvent->uEventMask = ACX_INTR_CMD_COMPLETE | ACX_INTR_EVENT_A | ACX_INTR_EVENT_B; - pFwEvent->tMaskTxn.uData = ~pFwEvent->uEventMask; - TXN_FW_EVENT_SET_MASK_ADDR(pFwEvent) - twIf_Transact(pFwEvent->hTwIf, &(pFwEvent->tMaskTxn.tTxnStruct)); -} - - -/* - * \brief Stop & reset FwEvent (called by the driver stop process) - * - * \param hFwEvent - FwEvent Driver handle - * \return TI_OK - * - * \par Description - * - * \sa - */ -TI_STATUS fwEvent_Stop (TI_HANDLE hFwEvent) -{ - TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; - - pFwEvent->eSmState = FWEVENT_STATE_IDLE; - pFwEvent->bIntrPending = TI_FALSE; - pFwEvent->uNumPendHndlrs = 0; - pFwEvent->uEventMask = 0; - pFwEvent->uEventVector = 0; - - return TI_OK; -} - - -/* - * \brief Unmask all interrupts - * - * \param hFwEvent - FwEvent Driver handle - * \return void - * - * \par Description - * - * Called after driver Start or Recovery process are completed. - * Unmask all interrupts. - * - * \sa - */ -void fwEvent_EnableExternalEvents (TI_HANDLE hFwEvent) -{ - TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; - - /* Unmask all interrupts */ - pFwEvent->uEventMask = ALL_EVENTS_VECTOR; - pFwEvent->tMaskTxn.uData = ~pFwEvent->uEventMask; - TXN_FW_EVENT_SET_MASK_ADDR(pFwEvent) - twIf_Transact(pFwEvent->hTwIf, &(pFwEvent->tMaskTxn.tTxnStruct)); -} - - -/* - * \brief Disable the FwEvent client in the context handler - * - * \param hFwEvent - FwEvent Driver handle - * \return void - * - * \par Description - * - * \sa - */ -void fwEvent_DisableInterrupts(TI_HANDLE hFwEvent) -{ - TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; - - context_DisableClient (pFwEvent->hContext,pFwEvent->uContextId); -} - - -/* - * \brief Enable the FwEvent client in the context handler - * - * \param hFwEvent - FwEvent Driver handle - * \return void - * - * \par Description - * - * \sa - */ -void fwEvent_EnableInterrupts(TI_HANDLE hFwEvent) -{ - TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; - - context_EnableClient (pFwEvent->hContext,pFwEvent->uContextId); -} - - -#ifdef TI_DBG - -void fwEvent_PrintStat (TI_HANDLE hFwEvent) -{ -#ifdef REPORT_LOG - TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; - - WLAN_OS_REPORT(("Print FW event module info\n")); - WLAN_OS_REPORT(("==========================\n")); - WLAN_OS_REPORT(("uEventVector = 0x%x\n", pFwEvent->uEventVector)); - WLAN_OS_REPORT(("uEventMask = 0x%x\n", pFwEvent->uEventMask)); - WLAN_OS_REPORT(("eSmState = %d\n", pFwEvent->eSmState)); - WLAN_OS_REPORT(("bIntrPending = %d\n", pFwEvent->bIntrPending)); - WLAN_OS_REPORT(("uNumPendHndlrs = %d\n", pFwEvent->uNumPendHndlrs)); - WLAN_OS_REPORT(("uFwTimeOffset = %d\n", pFwEvent->uFwTimeOffset)); -#endif -} - -#endif /* TI_DBG */ - - - |