void txnQ_testTx (handle_t hTxnQ, TTxnStruct *pTxn) { TTxnQObj *pTxnQ = (TTxnQObj*)hTxnQ; busDrv_Transact (pTxnQ->hBusDrv, pTxn); }
/** * \fn txnQ_Scheduler * \brief Send queued transactions * * Issue transactions as long as they are available and the bus is not occupied. * Call CBs of completed transactions, except completion of pInputTxn (covered by the return value). * Note that this function is called from either internal or external (TxnDone) context. * However, the txnQ_RunScheduler which calls it, prevents scheduler reentry. * * \note * \param pTxnQ - The module's object * \param pInputTxn - The transaction inserted in the current context (NULL if none) * \return COMPLETE if pInputTxn completed in this context, PENDING if not, ERROR if failed * \sa txnQ_RunScheduler */ static ETxnStatus txnQ_Scheduler (TTxnQObj *pTxnQ, TTxnStruct *pInputTxn) { ETxnStatus eInputTxnStatus; /* Use as return value the status of the input transaction (PENDING unless sent and completed here) */ eInputTxnStatus = TXN_STATUS_PENDING; /* if a previous transaction is in progress, return PENDING */ if (pTxnQ->pCurrTxn) { TRACE1(pTxnQ->hReport, REPORT_SEVERITY_INFORMATION, "txnQ_Scheduler(): pCurrTxn isn't null (0x%x) so exit\n", pTxnQ->pCurrTxn); return TXN_STATUS_PENDING; } /* Loop while transactions are available and can be sent to bus driver */ while (1) { TTxnStruct *pSelectedTxn; ETxnStatus eStatus; /* Get next enabled transaction by priority. If none, exit loop. */ context_EnterCriticalSection (pTxnQ->hContext); pSelectedTxn = txnQ_SelectTxn (pTxnQ); context_LeaveCriticalSection (pTxnQ->hContext); if (pSelectedTxn == NULL) { break; } /* Save transaction in case it will be async (to indicate that the bus driver is busy) */ pTxnQ->pCurrTxn = pSelectedTxn; /* Send selected transaction to bus driver */ eStatus = busDrv_Transact (pTxnQ->hBusDrv, pSelectedTxn); /* If we've just sent the input transaction, use the status as the return value */ if (pSelectedTxn == pInputTxn) { eInputTxnStatus = eStatus; } TRACE3(pTxnQ->hReport, REPORT_SEVERITY_INFORMATION, "txnQ_Scheduler(): Txn 0x%x sent, status = %d, eInputTxnStatus = %d\n", pSelectedTxn, eStatus, eInputTxnStatus); /* If transaction completed */ if (eStatus != TXN_STATUS_PENDING) { pTxnQ->pCurrTxn = NULL; /* If it's not the input transaction, enqueue it in TxnDone queue */ if (pSelectedTxn != pInputTxn) { TI_STATUS eStatus; context_EnterCriticalSection (pTxnQ->hContext); eStatus = que_Enqueue (pTxnQ->hTxnDoneQueue, (TI_HANDLE)pSelectedTxn); if (eStatus != TI_OK) { TRACE3(pTxnQ->hReport, REPORT_SEVERITY_ERROR, "txnQ_Scheduler(): Enqueue failed, pTxn=0x%x, HwAddr=0x%x, Len0=%d\n", pSelectedTxn, pSelectedTxn->uHwAddr, pSelectedTxn->aLen[0]); } context_LeaveCriticalSection (pTxnQ->hContext); } } /* If pending Exit loop! */ else { break; } } /* Dequeue completed transactions and call their functional driver CB */ /* Note that it's the functional driver CB and not the specific CB in the Txn! */ while (1) { TTxnStruct *pCompletedTxn; TI_UINT32 uFuncId; TTxnQueueDoneCb fTxnQueueDoneCb; TI_HANDLE hCbHandle; context_EnterCriticalSection (pTxnQ->hContext); pCompletedTxn = (TTxnStruct *) que_Dequeue (pTxnQ->hTxnDoneQueue); context_LeaveCriticalSection (pTxnQ->hContext); if (pCompletedTxn == NULL) { /* Return the status of the input transaction (PENDING unless sent and completed here) */ return eInputTxnStatus; } TRACE1(pTxnQ->hReport, REPORT_SEVERITY_INFORMATION, "txnQ_Scheduler(): Calling TxnDone for Txn 0x%x\n", pCompletedTxn); uFuncId = TXN_PARAM_GET_FUNC_ID(pCompletedTxn); fTxnQueueDoneCb = pTxnQ->aFuncInfo[uFuncId].fTxnQueueDoneCb; hCbHandle = pTxnQ->aFuncInfo[uFuncId].hCbHandle; fTxnQueueDoneCb (hCbHandle, pCompletedTxn); } }
/** * \fn txnQ_RunScheduler * \brief Send queued transactions * * Issue transactions as long as they are available and the bus is not occupied. * Call CBs of completed transactions, except conpletion of pCurrTxn (covered by the return value). * Note that this function can't be preempted, since it is always called in critical section * See txnQ_Transact(), txnQ_SendCtrlByte(), txnQ_Run() and txnQ_TxnDoneCb(). * * \note * \param pTxnQ - The module's object * \param pCurrTxn - The transaction inserted in the current context (NULL if none) * \param bExternalContext - TRUE if called in external context (TxnDone) * \return COMPLETE if pCurrTxn completed in this context, PENDING if not, ERROR if failed * \sa */ static ETxnStatus txnQ_RunScheduler (TTxnQObj *pTxnQ, TTxnStruct *pInputTxn, McpBool bExternalContext) { /* Use as return value the status of the input transaction (PENDING unless sent and completed here) */ ETxnStatus eInputTxnStatus = TXN_STATUS_PENDING; McpBool loopCond = MCP_TRUE; /* if a previous transaction is in progress, return PENDING */ if (pTxnQ->pCurrTxn) { return TXN_STATUS_PENDING; } /* Loop while transactions are available and can be sent to bus driver */ while (loopCond) { TTxnStruct *pSelectedTxn; ETxnStatus eStatus; #ifdef TRAN_DBG #define TXN_MAX_LOOP_ITERATES 100 int loopIterates = 0; if (loopIterates++ >= TXN_MAX_LOOP_ITERATES) { MCPF_REPORT_WARNING (pTxnQ->hMcpf, QUEUE_MODULE_LOG, ("txnQ_RunScheduler loop reached max iterates=%d\n", loopIterates)); } #endif /* Get next enabled transaction by priority. If none, exit loop. */ pSelectedTxn = txnQ_SelectTxn (pTxnQ); if (pSelectedTxn == NULL) { break; } /* Send selected transaction to bus driver */ eStatus = busDrv_Transact (pTxnQ->hBusDrv, pSelectedTxn); /* If we've just sent the input transaction, use the status as the return value */ if (pSelectedTxn == pInputTxn) { eInputTxnStatus = eStatus; } /* If transaction completed */ if (eStatus == TXN_STATUS_COMPLETE) { /* If it's not the input transaction, enqueue it in TxnDone queue */ if (pSelectedTxn != pInputTxn) { que_Enqueue (pTxnQ->hTxnDoneQueue, (handle_t)pSelectedTxn); } } /* If pending or error */ else { /* If transaction pending, save it to indicate that the bus driver is busy */ if (eStatus == TXN_STATUS_PENDING) { pTxnQ->pCurrTxn = pSelectedTxn; } /* Exit loop! */ break; } } /* Dequeue completed transactions and call their functional driver CB */ /* Note that it's the functional driver CB and not the specific CB in the Txn! */ while (loopCond) { TTxnStruct *pCompletedTxn; McpU32 uFuncId; TTxnQueueDoneCb fTxnQueueDoneCb; handle_t hCbHandle; pCompletedTxn = (TTxnStruct *) que_Dequeue (pTxnQ->hTxnDoneQueue); if (pCompletedTxn == NULL) { /* Return the status of the input transaction (PENDING unless sent and completed here) */ return eInputTxnStatus; } uFuncId = TXN_PARAM_GET_FUNC_ID(pCompletedTxn); fTxnQueueDoneCb = pTxnQ->aFuncInfo[uFuncId].fTxnQueueDoneCb; hCbHandle = pTxnQ->aFuncInfo[uFuncId].hCbHandle; fTxnQueueDoneCb (hCbHandle, pCompletedTxn, bExternalContext); } return TXN_STATUS_PENDING; }