/* * \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; }
/** * \fn busDrv_Transact * \brief Process transaction * * Called by the TxnQ module to initiate a new transaction. * Prepare the transaction parts (lower layer single transactions), * and send them one by one to the lower layer. * * \note It's assumed that this function is called only when idle (i.e. previous Txn is done). * \param hBusDrv - The module's object * \param pTxn - The transaction object * \return COMPLETE if Txn completed in this context, PENDING if not, ERROR if failed * \sa busDrv_PrepareTxnParts, busDrv_SendTxnParts */ ETxnStatus busDrv_Transact (TI_HANDLE hBusDrv, TTxnStruct *pTxn) { TBusDrvObj *pBusDrv = (TBusDrvObj*)hBusDrv; TI_BOOL bWithinAggregation; CL_TRACE_START_L4(); pBusDrv->pCurrTxn = pTxn; pBusDrv->uCurrTxnPartsCount = 0; pBusDrv->uCurrTxnPartsCountSync = 0; /* Set status OK in Txn struct (changed later to error if transaction fails) */ TXN_PARAM_SET_STATUS(pTxn, TXN_PARAM_STATUS_OK); /* Prepare the transaction parts in a table. */ bWithinAggregation = busDrv_PrepareTxnParts (pBusDrv, pTxn); /* If in the middle of Tx aggregation, return Complete (current Txn was coppied to buffer but not sent) */ if (bWithinAggregation) { TRACE1(pBusDrv->hReport, REPORT_SEVERITY_INFORMATION, "busDrv_Transact: In aggregation so exit, uTxnLength=%d\n", pBusDrv->uTxnLength); CL_TRACE_END_L4("tiwlan_drv.ko", "INHERIT", "TXN", ".Transact"); return TXN_STATUS_COMPLETE; } /* Send the prepared transaction parts. */ busDrv_SendTxnParts (pBusDrv); TRACE1(pBusDrv->hReport, REPORT_SEVERITY_INFORMATION, "busDrv_Transact: Status = %d\n", pBusDrv->eCurrTxnStatus); CL_TRACE_END_L4("tiwlan_drv.ko", "INHERIT", "TXN", ".Transact"); /* return transaction status - COMPLETE, PENDING or ERROR */ /* The status is updated in busDrv_SendTxnParts(). It is Async (pending) if not completed in this context */ return pBusDrv->eCurrTxnStatus; }
/* * \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) }