예제 #1
0
void txnQ_testTx (handle_t hTxnQ, TTxnStruct *pTxn)
{
    TTxnQObj  *pTxnQ = (TTxnQObj*)hTxnQ;

	busDrv_Transact (pTxnQ->hBusDrv, pTxn);
}
예제 #2
0
파일: TxnQueue.c 프로젝트: aleho/ti_wilink
/** 
 * \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);
    }
}
예제 #3
0
/** 
 * \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;
}