示例#1
0
ETxnStatus txnQ_Transact (TI_HANDLE hTxnQ, TTxnStruct *pTxn)
{
    TTxnQObj    *pTxnQ   = (TTxnQObj*)hTxnQ;
    TI_UINT32    uFuncId = TXN_PARAM_GET_FUNC_ID(pTxn);
    ETxnStatus   rc;

    if (TXN_PARAM_GET_SINGLE_STEP(pTxn)) 
    {
        pTxnQ->aFuncInfo[uFuncId].pSingleStep = pTxn;
        TRACE0(pTxnQ->hReport, REPORT_SEVERITY_INFORMATION, "txnQ_Transact(): Single step Txn\n");
    }
    else 
    {
        TI_STATUS eStatus;
        TI_HANDLE hQueue = pTxnQ->aTxnQueues[uFuncId][TXN_PARAM_GET_PRIORITY(pTxn)];
        context_EnterCriticalSection (pTxnQ->hContext);
        eStatus = que_Enqueue (hQueue, (TI_HANDLE)pTxn);
        context_LeaveCriticalSection (pTxnQ->hContext);
        if (eStatus != TI_OK)
        {
            TRACE3(pTxnQ->hReport, REPORT_SEVERITY_ERROR, "txnQ_Transact(): Enqueue failed, pTxn=0x%x, HwAddr=0x%x, Len0=%d\n", pTxn, pTxn->uHwAddr, pTxn->aLen[0]);
            return TXN_STATUS_ERROR;
        }
        TRACE0(pTxnQ->hReport, REPORT_SEVERITY_INFORMATION, "txnQ_Transact(): Regular Txn\n");
    }

    /* Send queued transactions as possible */
    rc = txnQ_RunScheduler (pTxnQ, pTxn); 

    return rc;
}
/** 
 * \fn     txnQ_Transact
 * \brief  Issue a new transaction 
 * 
 * Called by the functional driver to initiate a new transaction.
 * In critical section save transaction and call scheduler.
 * 
 * \note   
 * \param  hTxnQ - The module's object
 * \param  pTxn  - The transaction object 
 * \return COMPLETE if input pTxn completed in this context, PENDING if not, ERROR if failed
 * \sa     
 */ 
ETxnStatus txnQ_Transact (handle_t hTxnQ, TTxnStruct *pTxn)
{
    TTxnQObj    *pTxnQ   = (TTxnQObj*)hTxnQ;
    McpU32    uFuncId = TXN_PARAM_GET_FUNC_ID(pTxn);
    ETxnStatus   rc;

    MCPF_ENTER_CRIT_SEC (pTxnQ->hMcpf);

    if (TXN_PARAM_GET_SINGLE_STEP(pTxn)) 
    {
        pTxnQ->aFuncInfo[uFuncId].pSingleStep = pTxn;
    }
    else 
    {
        handle_t hQueue = pTxnQ->aTxnQueues[uFuncId][TXN_PARAM_GET_PRIORITY(pTxn)];
        que_Enqueue (hQueue, (handle_t)pTxn);
    }

    /* Send queued transactions as possible */
    rc = txnQ_RunScheduler (pTxnQ, pTxn, MCP_FALSE); 

    MCPF_EXIT_CRIT_SEC (pTxnQ->hMcpf);

    return rc;
}
示例#3
0
/** 
 * \fn     twIf_TxnDoneCb
 * \brief  Transaction completion CB
 * 
 * This callback is called by the TxnQ upon transaction completion, unless is was completed in
 *     the original context where it was issued.
 * It may be called from bus driver external context (TxnDone ISR) or from WLAN driver context.
 *  
 * \note   
 * \param  hTwIf - The module's object
 * \param  pTxn  - The completed transaction object 
 * \return void
 * \sa     twIf_HandleTxnDone
 */
static void twIf_TxnDoneCb(TI_HANDLE hTwIf, TTxnStruct * pTxn)
{
	TTwIfObj *pTwIf = (TTwIfObj *) hTwIf;

#ifdef TI_DBG
	pTwIf->uDbgCountTxnDoneCb++;
	TRACE6(pTwIf->hReport, REPORT_SEVERITY_INFORMATION,
	       "twIf_TxnDoneCb: Params=0x%x, HwAddr=0x%x, Len0=%d, Len1=%d, Len2=%d, Len3=%d\n",
	       pTxn->uTxnParams, pTxn->uHwAddr, pTxn->aLen[0], pTxn->aLen[1],
	       pTxn->aLen[2], pTxn->aLen[3]);
#endif

	/* In case of recovery flag, Call directly restart callback */
	if (TXN_PARAM_GET_STATUS(pTxn) == TXN_PARAM_STATUS_RECOVERY) {
		if (pTwIf->fRecoveryCb) {
			TRACE0(pTwIf->hReport, REPORT_SEVERITY_INFORMATION,
			       "twIf_TxnDoneCb: During Recovery\n");
			pTwIf->bTxnDoneInRecovery = TI_TRUE;
			/* Request schedule to continue handling in driver context (will call twIf_HandleTxnDone()) */
			context_RequestSchedule(pTwIf->hContext,
						pTwIf->uContextId);
			return;
		}
	}

	/* If the completed Txn is ELP, nothing to do (not counted) so exit */
	if (TXN_PARAM_GET_SINGLE_STEP(pTxn)) {
		return;
	}

	if (pTxn->fTxnDoneCb) {
		TI_STATUS eStatus;

		/* In critical section, enqueue the completed transaction in the TxnDoneQ. */
		context_EnterCriticalSection(pTwIf->hContext);
		eStatus = que_Enqueue(pTwIf->hTxnDoneQueue, (TI_HANDLE) pTxn);
		if (eStatus != TI_OK) {
			TRACE3(pTwIf->hReport, REPORT_SEVERITY_ERROR,
			       "twIf_TxnDoneCb(): Enqueue failed, pTxn=0x%x, HwAddr=0x%x, Len0=%d\n",
			       pTxn, pTxn->uHwAddr, pTxn->aLen[0]);
		}
		context_LeaveCriticalSection(pTwIf->hContext);
	} else {
		context_EnterCriticalSection(pTwIf->hContext);
		/* Decrement pending Txn counter, It's value will be checked in twIf_HandleTxnDone() */
		if (pTwIf->uPendingTxnCount > 0) {	/* in case of callback on recovery after restart */
			pTwIf->uPendingTxnCount--;
		}
		context_LeaveCriticalSection(pTwIf->hContext);

	}

	/* Request schedule to continue handling in driver context (will call twIf_HandleTxnDone()) */
	context_RequestSchedule(pTwIf->hContext, pTwIf->uContextId);
}
示例#4
0
/** 
 * \fn     twIf_TxnDoneCb
 * \brief  Transaction completion CB
 * 
 * This callback is called by the TxnQ upon transaction completion, unless is was completed in
 *     the original context where it was issued.
 * It may be called from bus driver external context (TxnDone ISR) or from WLAN driver context.
 *  
 * \note   
 * \param  hTwIf - The module's object
 * \param  pTxn  - The completed transaction object 
 * \return void
 * \sa     twIf_HandleTxnDone
 */ 
static void twIf_TxnDoneCb (TI_HANDLE hTwIf, TTxnStruct *pTxn)
{
    TTwIfObj *pTwIf = (TTwIfObj*)hTwIf;

#ifdef TI_DBG
    pTwIf->uDbgCountTxnDoneCb++;
#endif

    /* In case of recovery flag, Call directly restart callback */
    if (TXN_PARAM_GET_STATUS(pTxn) == TXN_PARAM_STATUS_RECOVERY)
    {
        if (pTwIf->fRecoveryCb)
        {
            pTwIf->bTxnDoneInRecovery = TI_TRUE;
            /* Request schedule to continue handling in driver context (will call twIf_HandleTxnDone()) */
            context_RequestSchedule (pTwIf->hContext, pTwIf->uContextId);
            return;
        }
    }

    /* If the completed Txn is ELP, nothing to do (not counted) so exit */
    if (TXN_PARAM_GET_SINGLE_STEP(pTxn)) 
    {
        return;
    }

    if (pTxn->fTxnDoneCb)
    {
        TI_STATUS eStatus;

        /* In critical section, enqueue the completed transaction in the TxnDoneQ. */
        context_EnterCriticalSection (pTwIf->hContext);
        eStatus = que_Enqueue (pTwIf->hTxnDoneQueue, (TI_HANDLE)pTxn);
        context_LeaveCriticalSection (pTwIf->hContext);
    }
    else
    {
        context_EnterCriticalSection (pTwIf->hContext);
         /* Decrement pending Txn counter, It's value will be checked in twIf_HandleTxnDone() */
        if (pTwIf->uPendingTxnCount > 0) /* in case of callback on recovery after restart */
        {
            pTwIf->uPendingTxnCount--;
        }
        context_LeaveCriticalSection (pTwIf->hContext);

    }
    
    /* Request schedule to continue handling in driver context (will call twIf_HandleTxnDone()) */
    context_RequestSchedule (pTwIf->hContext, pTwIf->uContextId);
}
示例#5
0
ETxnStatus txnQ_Transact (TI_HANDLE hTxnQ, TTxnStruct *pTxn)
{
	TTxnQObj    *pTxnQ   = (TTxnQObj*)hTxnQ;
	TI_UINT32    uFuncId = TXN_PARAM_GET_FUNC_ID(pTxn);
	ETxnStatus   rc;

	if (TXN_PARAM_GET_SINGLE_STEP(pTxn)) {
		pTxnQ->aFuncInfo[uFuncId].pSingleStep = pTxn;
	} else {
		TI_STATUS eStatus;
		TI_HANDLE hQueue = pTxnQ->aTxnQueues[uFuncId][TXN_PARAM_GET_PRIORITY(pTxn)];
		context_EnterCriticalSection (pTxnQ->hContext);
		eStatus = que_Enqueue (hQueue, (TI_HANDLE)pTxn);
		context_LeaveCriticalSection (pTxnQ->hContext);
		if (eStatus != TI_OK) {
			return TXN_STATUS_ERROR;
		}
	}

	/* Send queued transactions as possible */
	rc = txnQ_RunScheduler (pTxnQ, pTxn);

	return rc;
}
/** 
 * \fn     busDrv_SendTxnParts
 * \brief  Send prepared transaction parts
 * 
 * Called first by busDrv_Transact(), and also from TxnDone CB after Async completion.
 * Sends the prepared transaction parts in a loop.
 * If a transaction part is Async, the loop continues later in the TxnDone ISR context.
 * When all parts are done, the upper layer TxnDone CB is called.
 * 
 * \note   
 * \param  pBusDrv - The module's object
 * \return void
 * \sa     busDrv_Transact, busDrv_PrepareTxnParts
 */ 
static void busDrv_SendTxnParts (TBusDrvObj *pBusDrv)
{
    ETxnStatus  eStatus;
    TTxnPart   *pTxnPart;
    TTxnStruct *pTxn = pBusDrv->pCurrTxn;

    /* While there are transaction parts to send */
    while (pBusDrv->uCurrTxnPartsCount < pBusDrv->uCurrTxnPartsNum)
    {
        pTxnPart = &(pBusDrv->aTxnParts[pBusDrv->uCurrTxnPartsCount]);
        pBusDrv->uCurrTxnPartsCount++;

        /* Assume pending to be ready in case we are preempted by the TxnDon CB !! */
        pBusDrv->eCurrTxnStatus = TXN_STATUS_PENDING;   

        /* If single step, send ELP byte */
        if (TXN_PARAM_GET_SINGLE_STEP(pTxn)) 
        {
            /* Overwrite the function id with function 0 - for ELP register !!!! */
            eStatus = sdioAdapt_TransactBytes (TXN_FUNC_ID_CTRL,
                                               pTxnPart->uHwAddr,
                                               pTxnPart->pHostAddr,
                                               pTxnPart->uLength,
                                               TXN_PARAM_GET_DIRECTION(pTxn),
                                               pTxnPart->bMore);

            /* If first write failed try once again (may happen once upon chip wakeup) */
            if (eStatus == TXN_STATUS_ERROR)
            {
                /* Overwrite the function id with function 0 - for ELP register !!!! */
                eStatus = sdioAdapt_TransactBytes (TXN_FUNC_ID_CTRL,
                                                   pTxnPart->uHwAddr,
                                                   pTxnPart->pHostAddr,
                                                   pTxnPart->uLength,
                                                   TXN_PARAM_GET_DIRECTION(pTxn),
                                                   pTxnPart->bMore);
                TRACE0(pBusDrv->hReport, REPORT_SEVERITY_WARNING, "busDrv_SendTxnParts: SDIO Single-Step transaction failed once so try again");
            }
        }
        else
        {
            eStatus = sdioAdapt_Transact (TXN_PARAM_GET_FUNC_ID(pTxn),
                                          pTxnPart->uHwAddr,
                                          pTxnPart->pHostAddr,
                                          pTxnPart->uLength,
                                          TXN_PARAM_GET_DIRECTION(pTxn),
                                          pTxnPart->bBlkMode,
                                          ((TXN_PARAM_GET_FIXED_ADDR(pTxn) == 1) ? 0 : 1),
                                          pTxnPart->bMore);
        }

        TRACE7(pBusDrv->hReport, REPORT_SEVERITY_INFORMATION, "busDrv_SendTxnParts: PartNum = %d, SingleStep = %d, Direction = %d, HwAddr = 0x%x, HostAddr = 0x%x, Length = %d, BlkMode = %d\n", pBusDrv->uCurrTxnPartsCount-1, TXN_PARAM_GET_SINGLE_STEP(pTxn), TXN_PARAM_GET_DIRECTION(pTxn), pTxnPart->uHwAddr, pTxnPart->pHostAddr, pTxnPart->uLength, pTxnPart->bBlkMode);

        /* If pending TxnDone (Async), continue this loop in the next TxnDone interrupt */
        if (eStatus == TXN_STATUS_PENDING)
        {
            return; 
        }

        /* Update current transaction status to deduce if it is all finished in the original context (Sync) or not. */
        pBusDrv->eCurrTxnStatus = eStatus;
        pBusDrv->uCurrTxnPartsCountSync++;

        /* If error, set error in Txn struct, call TxnDone CB if not fully sync, and exit */
        if (eStatus == TXN_STATUS_ERROR)
        {
            TXN_PARAM_SET_STATUS(pTxn, TXN_PARAM_STATUS_ERROR);
            if (pBusDrv->uCurrTxnPartsCountSync != pBusDrv->uCurrTxnPartsCount)
            {
                pBusDrv->fTxnDoneCb (pBusDrv->hCbHandle, pTxn);
            }
        	return;
        }
    }

    /* If we got here we sent all buffers and we don't pend transaction end */
    TRACE3(pBusDrv->hReport, REPORT_SEVERITY_INFORMATION, "busDrv_SendTxnParts: Txn finished successfully, Status = %d, PartsCount = %d, SyncCount = %d\n", pBusDrv->eCurrTxnStatus, pBusDrv->uCurrTxnPartsCount, pBusDrv->uCurrTxnPartsCountSync);

    /* For read transaction, copy the data from the DMA-able buffer to the host buffer(s) */
    if (TXN_PARAM_GET_DIRECTION(pTxn) == TXN_DIRECTION_READ)
    {
        TI_UINT32 uBufNum;
        TI_UINT32 uBufLen;
        TI_UINT8 *pDmaBuf = pBusDrv->pRxDmaBuf; /* After the read transaction the data is in the Rx DMA buffer */

        for (uBufNum = 0; uBufNum < MAX_XFER_BUFS; uBufNum++)
        {
            uBufLen = pTxn->aLen[uBufNum];

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

            os_memoryCopy (pBusDrv->hOs, pTxn->aBuf[uBufNum], pDmaBuf, uBufLen);
            pDmaBuf += uBufLen;
        }
    }

    /* If not fully sync, call TxnDone CB */
    if (pBusDrv->uCurrTxnPartsCountSync != pBusDrv->uCurrTxnPartsCount)
    {
        pBusDrv->fTxnDoneCb (pBusDrv->hCbHandle, pTxn);
    }
}
/** 
 * \fn     ifSlpMng_HandleRxEvent
 * \brief  Interface Sleep Manager state machine for Rx event
 * 
 * Process Rx event of Interface Sleep Manager state machine
 * 
 */ 
EIfSlpMngStatus ifSlpMng_HandleRxEvent (handle_t hIfSlpMng, TTxnStruct *pTxn) 
{
	TifSlpMngObj  * pIfSlpMng = (TifSlpMngObj *) hIfSlpMng;
	EIfSlpMngStatus eRes = IfSlpMng_ERR;
	McpBool			stateChanged = MCP_FALSE;

	if (TXN_PARAM_GET_SINGLE_STEP (pTxn))
	{
		/* IfSlpMng transaction is always single step, 
		 * get IfSlpMng opcode from transaction structure
		 */
		eRes = IfSlpMng_SLP_PKT_TYPE;

		switch (TXN_PARAM_GET_IFSLPMNG_OP (pTxn))
		{

		case TXN_PARAM_IFSLPMNG_OP_SLEEP:

			MCPF_REPORT_DEBUG_RX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleRxEvent: SLEEP_IND, state=%d\n",pIfSlpMng->eState));

			MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf);
			if (pIfSlpMng->eState == IFSLPMNG_STATE_AWAKE)
			{
				pIfSlpMng->eState = IFSLPMNG_STATE_WAIT_FOR_SLEEPACK_TX_COMPL;
				stateChanged = MCP_TRUE;
			}
			pIfSlpMng->stat.SleepInd_Rx++;
			MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf);

			if (stateChanged)
			{
				txnQ_Stop (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); 

				/* Prepare and send SleepAck request */
				TXN_PARAM_SET_IFSLPMNG_OP (pIfSlpMng->pMngTxn, TXN_PARAM_IFSLPMNG_OP_SLEEP_ACK);
				txnQ_Transact (pIfSlpMng->hTxnQ, pIfSlpMng->pMngTxn);
				pIfSlpMng->stat.SleepAck_Tx++;
			}
			break;

		case TXN_PARAM_IFSLPMNG_OP_SLEEP_ACK:
			MCPF_REPORT_ERROR (pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, 
							  ("%s: Not expected SleepAck received\n", __FUNCTION__));
			pIfSlpMng->stat.SleepAck_Rx++;
			break;

		case TXN_PARAM_IFSLPMNG_OP_AWAKE:
			{
				EIfSlpMngState  oldState;

				MCPF_REPORT_DEBUG_RX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleRxEvent: AWAKE_IND, state=%d\n",pIfSlpMng->eState));

				MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf);
				oldState = pIfSlpMng->eState;
				if ((pIfSlpMng->eState == IFSLPMNG_STATE_ASLEEP) ||
					(pIfSlpMng->eState == IFSLPMNG_STATE_WAIT_FOR_AWAKE_ACK))
				{
					pIfSlpMng->eState = IFSLPMNG_STATE_AWAKE;
					stateChanged = MCP_TRUE;
				}
				pIfSlpMng->stat.AwakeInd_Rx++;
				MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf);
	
				if (stateChanged)
				{
					switch (oldState)
					{
					case IFSLPMNG_STATE_ASLEEP:
	
						/* Prepare and send SleepAck request */
						TXN_PARAM_SET_IFSLPMNG_OP (pIfSlpMng->pMngTxn, TXN_PARAM_IFSLPMNG_OP_AWAKE_ACK);
						txnQ_Transact (pIfSlpMng->hTxnQ, pIfSlpMng->pMngTxn);
						txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); 
						pIfSlpMng->stat.AwakeAck_Tx++;
						break;
	
					case IFSLPMNG_STATE_WAIT_FOR_AWAKE_ACK:
	
						txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId); 
						break;

                    default:
                       break;
					}
				}
			}
			break;

		case TXN_PARAM_IFSLPMNG_OP_AWAKE_ACK:

			MCPF_REPORT_DEBUG_RX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleRxEvent: AWAKE_ACK, state=%d\n",pIfSlpMng->eState));

			MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf);
			if (pIfSlpMng->eState == IFSLPMNG_STATE_WAIT_FOR_AWAKE_ACK)
			{
				pIfSlpMng->eState =  IFSLPMNG_STATE_AWAKE;
				stateChanged = MCP_TRUE;
			}
			pIfSlpMng->stat.AwakeAck_Rx++;
			MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf);

			if (stateChanged)
			{
				txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId);
			}
			break;

		default:
			MCPF_REPORT_ERROR (pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, 
							  ("%s: Invalid IfSlpMng opcode=%u\n", __FUNCTION__, TXN_PARAM_GET_IFSLPMNG_OP (pTxn)));
			eRes = IfSlpMng_ERR;
			break;
		} /* Rx IFSLPMNG_OP */
	}
	else
	{
		/* Normal packet received */
		MCPF_ENTER_CRIT_SEC (pIfSlpMng->hMcpf);
		if (pIfSlpMng->eState == IFSLPMNG_STATE_ASLEEP)
		{
			pIfSlpMng->eState = IFSLPMNG_STATE_AWAKE;
			stateChanged = MCP_TRUE;
			pIfSlpMng->stat.AwakeAck_Tx++;
		}
		MCPF_EXIT_CRIT_SEC (pIfSlpMng->hMcpf);

		if (stateChanged)
		{
			/* Prepare and send SleepAck request */
			TXN_PARAM_SET_IFSLPMNG_OP (pIfSlpMng->pMngTxn, TXN_PARAM_IFSLPMNG_OP_AWAKE_ACK);
			txnQ_Transact (pIfSlpMng->hTxnQ, pIfSlpMng->pMngTxn);

			txnQ_Run (pIfSlpMng->hTxnQ, pIfSlpMng->uFuncId);

			MCPF_REPORT_DEBUG_RX(pIfSlpMng->hMcpf, IFSLPMNG_MODULE_LOG, ("ifSlpMng_HandleRxEvent: Normal RX, state=%d\n",pIfSlpMng->eState));
		}

		eRes = IfSlpMng_OK;
	}
	return eRes;
}