Beispiel #1
0
/**
 * \fn     txnQ_SelectTxn
 * \brief  Select transaction to send
 *
 * Called from txnQ_RunScheduler() which is protected in critical section.
 * Select the next enabled transaction by priority.
 *
 * \note
 * \param  pTxnQ - The module's object
 * \return The selected transaction to send (NULL if none available)
 * \sa
 */
static TTxnStruct *txnQ_SelectTxn (TTxnQObj *pTxnQ)
{
	TTxnStruct *pSelectedTxn;
	TI_UINT32   uFunc;
	TI_UINT32   uPrio;

#ifdef TI_DBG
	/* If within Tx aggregation, dequeue Txn from same queue, and if not NULL return it */
	if (pTxnQ->pAggregQueue) {
		pSelectedTxn = (TTxnStruct *) que_Dequeue (pTxnQ->pAggregQueue);
		if (pSelectedTxn != NULL) {
			/* If aggregation ended, reset the aggregation-queue pointer */
			if (TXN_PARAM_GET_AGGREGATE(pSelectedTxn) == TXN_AGGREGATE_OFF) {
				pTxnQ->pAggregQueue = NULL;
			}
			return pSelectedTxn;
		}
		return NULL;
	}
#endif

	/* For all functions, if single-step Txn waiting, return it (sent even if function is stopped) */
	for (uFunc = pTxnQ->uMinFuncId; uFunc <= pTxnQ->uMaxFuncId; uFunc++) {
		pSelectedTxn = pTxnQ->aFuncInfo[uFunc].pSingleStep;
		if (pSelectedTxn != NULL) {
			pTxnQ->aFuncInfo[uFunc].pSingleStep = NULL;
			return pSelectedTxn;
		}
	}

	/* For all priorities from high to low */
	for (uPrio = 0; uPrio < MAX_PRIORITY; uPrio++) {
		/* For all functions */
		for (uFunc = pTxnQ->uMinFuncId; uFunc <= pTxnQ->uMaxFuncId; uFunc++) {
			/* If function running and uses this priority */
			if (pTxnQ->aFuncInfo[uFunc].eState == FUNC_STATE_RUNNING  &&
			        pTxnQ->aFuncInfo[uFunc].uNumPrios > uPrio) {
				/* Dequeue Txn from current func and priority queue, and if not NULL return it */
				pSelectedTxn = (TTxnStruct *) que_Dequeue (pTxnQ->aTxnQueues[uFunc][uPrio]);
				if (pSelectedTxn != NULL) {
#ifdef TI_DBG
					/* If aggregation begins, save the aggregation-queue pointer to ensure continuity */
					if (TXN_PARAM_GET_AGGREGATE(pSelectedTxn) == TXN_AGGREGATE_ON) {
						pTxnQ->pAggregQueue = pTxnQ->aTxnQueues[uFunc][uPrio];
					}
#endif
					return pSelectedTxn;
				}
			}
		}
	}

	/* If no transaction was selected, return NULL */
	return NULL;
}
/** 
 * \fn     busDrv_PrepareTxnParts
 * \brief  Prepare write or read transaction parts
 * 
 * Called by busDrv_Transact().
 * Prepares the actual sequence of SDIO bus transactions in a table.
 * Use a DMA-able buffer for the bus transaction, so all data is copied
 *     to it from the host buffer(s) before write transactions,
 *     or copied from it to the host buffers after read transactions.
 * 
 * \note   
 * \param  pBusDrv - The module's object
 * \param  pTxn    - The transaction object 
 * \return TRUE if we are in the middle of a Tx aggregation
 * \sa     busDrv_Transact, busDrv_SendTxnParts, 
 */ 
static TI_BOOL busDrv_PrepareTxnParts (TBusDrvObj *pBusDrv, TTxnStruct *pTxn)
{
    TI_UINT32 uPartNum     = 0;
    TI_UINT32 uCurrHwAddr  = pTxn->uHwAddr;
    TI_BOOL   bFixedHwAddr = TXN_PARAM_GET_FIXED_ADDR(pTxn);
    TI_BOOL   bWrite       = (TXN_PARAM_GET_DIRECTION(pTxn) == TXN_DIRECTION_WRITE) ? TI_TRUE : TI_FALSE;
    TI_UINT8 *pHostBuf     = bWrite ? pBusDrv->pTxDmaBuf : pBusDrv->pRxDmaBuf; /* Use DMA buffer (Rx or Tx) for actual transaction */
    TI_UINT32 uBufNum;
    TI_UINT32 uBufLen;
    TI_UINT32 uRemainderLen;

    /* Go over the transaction buffers */
    for (uBufNum = 0; uBufNum < MAX_XFER_BUFS; uBufNum++) 
    {
        uBufLen = pTxn->aLen[uBufNum];

        /* If no more buffers, exit the loop */
        if (uBufLen == 0)
        {
            break;
        }

        /* For write transaction, copy the data to the DMA buffer */
        if (bWrite)
        {
            os_memoryCopy (pBusDrv->hOs, pHostBuf + pBusDrv->uTxnLength, pTxn->aBuf[uBufNum], uBufLen);
        }

        /* Add buffer length to total transaction length */
        pBusDrv->uTxnLength += uBufLen;
    }

    /* If in a Tx aggregation, return TRUE (need to accumulate all parts before sending the transaction) */
    if (TXN_PARAM_GET_AGGREGATE(pTxn) == TXN_AGGREGATE_ON)
    {
        TRACE6(pBusDrv->hReport, REPORT_SEVERITY_INFORMATION, "busDrv_PrepareTxnParts: In aggregation so exit, uTxnLength=%d, bWrite=%d, Len0=%d, Len1=%d, Len2=%d, Len3=%d\n", pBusDrv->uTxnLength, bWrite, pTxn->aLen[0], pTxn->aLen[1], pTxn->aLen[2], pTxn->aLen[3]);
        return TI_TRUE;
    }

    /* If current buffer has a remainder, prepare its transaction part */
    uRemainderLen = pBusDrv->uTxnLength & pBusDrv->uBlkSizeMask;
    if (uRemainderLen > 0)
    {
        pBusDrv->aTxnParts[uPartNum].bBlkMode  = TI_FALSE;
        pBusDrv->aTxnParts[uPartNum].uLength   = uRemainderLen;
        pBusDrv->aTxnParts[uPartNum].uHwAddr   = uCurrHwAddr;
        pBusDrv->aTxnParts[uPartNum].pHostAddr = (void *)pHostBuf;
        pBusDrv->aTxnParts[uPartNum].bMore     = TI_TRUE;

        /* If not fixed HW address, increment it by this part's size */
        if (!bFixedHwAddr)
        {
            uCurrHwAddr += uRemainderLen;
        }

        uPartNum++;
    }

#ifdef  DISABLE_SDIO_MULTI_BLK_MODE

    /* SDIO multi-block mode is disabled so split to 512 bytes blocks */
    {
        TI_UINT32 uLen;

        for (uLen = uRemainderLen; uLen < pBusDrv->uTxnLength; uLen += pBusDrv->uBlkSize)
        {
            pBusDrv->aTxnParts[uPartNum].bBlkMode  = TI_FALSE;
            pBusDrv->aTxnParts[uPartNum].uLength   = pBusDrv->uBlkSize;
            pBusDrv->aTxnParts[uPartNum].uHwAddr   = uCurrHwAddr;
            pBusDrv->aTxnParts[uPartNum].pHostAddr = (void *)(pHostBuf + uLen);
            pBusDrv->aTxnParts[uPartNum].bMore     = TI_TRUE;

            /* If not fixed HW address, increment it by this part's size */
            if (!bFixedHwAddr)
            {
                uCurrHwAddr += pBusDrv->uBlkSize;
            }

            uPartNum++;
        }
    }

#else  /* Use SDIO block mode (this is the default behavior) */

    /* If current buffer has full SDIO blocks, prepare a block-mode transaction part */
    if (pBusDrv->uTxnLength >= pBusDrv->uBlkSize)
    {
        pBusDrv->aTxnParts[uPartNum].bBlkMode  = TI_TRUE;
        pBusDrv->aTxnParts[uPartNum].uLength   = pBusDrv->uTxnLength - uRemainderLen;
        pBusDrv->aTxnParts[uPartNum].uHwAddr   = uCurrHwAddr;
        pBusDrv->aTxnParts[uPartNum].pHostAddr = (void *)(pHostBuf + uRemainderLen);
        pBusDrv->aTxnParts[uPartNum].bMore     = TI_TRUE;

        uPartNum++;
    }

#endif /* DISABLE_SDIO_MULTI_BLK_MODE */

    /* Set last More flag as specified for the whole Txn */
    pBusDrv->aTxnParts[uPartNum - 1].bMore = TXN_PARAM_GET_MORE(pTxn);
    pBusDrv->uCurrTxnPartsNum = uPartNum;

    TRACE9(pBusDrv->hReport, REPORT_SEVERITY_INFORMATION, "busDrv_PrepareTxnParts: Txn prepared, PartsNum=%d, bWrite=%d, uTxnLength=%d, uRemainderLen=%d, uHwAddr=0x%x, Len0=%d, Len1=%d, Len2=%d, Len3=%d\n", uPartNum, bWrite, pBusDrv->uTxnLength, uRemainderLen, pTxn->uHwAddr, pTxn->aLen[0], pTxn->aLen[1], pTxn->aLen[2], pTxn->aLen[3]);

    pBusDrv->uTxnLength = 0;

    /* Return FALSE to indicate that we are not in the middle of a Tx aggregation so the Txn is ready to send */
    return TI_FALSE;
}