Ejemplo n.º 1
0
TI_STATUS TWD_InitHw (TI_HANDLE hTWD,
                      TI_UINT8  *pbuf,
                      TI_UINT32 length,
                      TI_UINT32 uRxDmaBufLen,
                      TI_UINT32 uTxDmaBufLen)
{
    TTwd *pTWD = (TTwd *)hTWD;
    TI_STATUS eStatus;


    /* Provide bus related parameters to Xfer modules before any usage of the bus! */
    rxXfer_SetBusParams (pTWD->hRxXfer, uRxDmaBufLen);
    txXfer_SetBusParams (pTWD->hTxXfer, uTxDmaBufLen);

    hwInit_SetNvsImage (pTWD->hHwInit, pbuf, length);

    /*
     * Update the TwIf that the HW is awake
     * This will protect the initialization process from going to sleep
     * After the firmware initializations completed (TWD_EnableExternalEvents), the sleep will be enabled
     */
    twIf_Awake (pTWD->hTwIf);
    twIf_HwAvailable (pTWD->hTwIf);

    /* This initiates the HW init sequence */
    eStatus = hwInit_Boot(pTWD->hHwInit);
    if (eStatus == TXN_STATUS_ERROR)
    {
        return TI_NOK;
    }

    return TI_OK;
}
Ejemplo n.º 2
0
/*
 * \brief	FW-Event state machine
 * 
 * \param  hFwEvent  - FwEvent Driver handle
 * \return void
 * 
 * \par Description
 * 
 * Process the current FW events in a sequence that may progress in the same context,
 *     or exit if pending an Async transaction, which will call back the SM when finished.
 *
 * \sa
 */
static void fwEvent_StateMachine (TfwEvent *pFwEvent)
{
    ETxnStatus  eStatus = TXN_STATUS_ERROR; /* Set to error to detect if used uninitialized */
    CL_TRACE_START_L3();

	/* 
	 * Loop through the states sequence as long as the process is synchronous.
	 * Exit when finished or if an Asynchronous process is required. 
     * In this case the SM will be called back upon Async operation completion. 
	 */
	while (1)
	{
		switch (pFwEvent->eSmState)
		{
            /* IDLE: Update TwIf and read interrupt info from FW */
            case FWEVENT_STATE_IDLE:
            {
                CL_TRACE_START_L5();
                twIf_Awake(pFwEvent->hTwIf);
                eStatus = fwEvent_SmReadIntrInfo (pFwEvent);
                pFwEvent->eSmState = FWEVENT_STATE_WAIT_INTR_INFO;
                CL_TRACE_END_L5("tiwlan_drv.ko", "CONTEXT", "FwEvent", ".ReadInfo");
                break;
            }
            /* WAIT_INTR_INFO: We have the interrupt info so call the handlers accordingly */
            case FWEVENT_STATE_WAIT_INTR_INFO:
            {
                CL_TRACE_START_L5();
                eStatus = fwEvent_SmHandleEvents (pFwEvent);
                /* If state was changed to IDLE by recovery or stop process, exit (process terminated) */
                if (pFwEvent->eSmState == FWEVENT_STATE_IDLE) 
                {
                    CL_TRACE_END_L5("tiwlan_drv.ko", "CONTEXT", "FwEvent", ".HndlEvents");
                    CL_TRACE_END_L3("tiwlan_drv.ko", "CONTEXT", "FwEvent", "");
                    return;
                }
                pFwEvent->eSmState = FWEVENT_STATE_WAIT_HANDLE_COMPLT;
                CL_TRACE_END_L5("tiwlan_drv.ko", "CONTEXT", "FwEvent", ".HndlEvents");
                break;
            }
            /* WAIT_HANDLE_COMPLT: Current handling is completed. */
            case FWEVENT_STATE_WAIT_HANDLE_COMPLT:
            {
                /* If pending interrupt, read interrupt info (back to WAIT_INTR_INFO state) */
                if (pFwEvent->bIntrPending) 
                {
                    CL_TRACE_START_L5();
                    pFwEvent->bIntrPending = TI_FALSE;
                    eStatus = fwEvent_SmReadIntrInfo (pFwEvent);
                    pFwEvent->eSmState = FWEVENT_STATE_WAIT_INTR_INFO;
                    CL_TRACE_END_L5("tiwlan_drv.ko", "CONTEXT", "FwEvent", ".HndlCmplt");
                }
                /* Else - all done so release TwIf to sleep and exit */
                else 
                {
                    twIf_Sleep(pFwEvent->hTwIf);
                    pFwEvent->eSmState = FWEVENT_STATE_IDLE;

                    TRACE3(pFwEvent->hReport, REPORT_SEVERITY_INFORMATION, "fwEvent_StateMachine: Completed, NewState=%d, Status=%d, IntrPending=%d\n", pFwEvent->eSmState, eStatus, pFwEvent->bIntrPending);
                    CL_TRACE_END_L3("tiwlan_drv.ko", "CONTEXT", "FwEvent", "");

                    /**** Finished all current events handling so exit ****/
                    return;
                }
                break;
            }

        }  /* switch */

        TRACE3(pFwEvent->hReport, REPORT_SEVERITY_INFORMATION, "fwEvent_StateMachine: NewState=%d, Status=%d, IntrPending=%d\n", pFwEvent->eSmState, eStatus, pFwEvent->bIntrPending);
        
		/* If last status is Pending, exit the SM (to be called back upon Async operation completion) */
		if (eStatus == TXN_STATUS_PENDING)
		{
            CL_TRACE_END_L3("tiwlan_drv.ko", "CONTEXT", "FwEvent", "");
			return;
		}

        /* If error occured, stop the process and exit (should be cleaned by recovery process) */
		else if (eStatus == TXN_STATUS_ERROR)
		{
            TRACE5(pFwEvent->hReport, REPORT_SEVERITY_ERROR, "fwEvent_StateMachine: NewState=%d, Status=%d, IntrPending=%d, EventVector=0x%x, EventMask=0x%x\n", pFwEvent->eSmState, eStatus, pFwEvent->bIntrPending, pFwEvent->uEventVector, pFwEvent->uEventMask);
            CL_TRACE_END_L3("tiwlan_drv.ko", "CONTEXT", "FwEvent", "");
            fwEvent_Stop ((TI_HANDLE)pFwEvent);
			return;
		}

        /* If we got here the status is COMPLETE so continue in the while loop to the next state */

	}  /* while */
}
Ejemplo n.º 3
0
/*
 * \brief	Configure the CmdQueue object
 * 
 * \param  hCmdQueue - Handle to CmdQueue
 * \param  eCmdQueueEvent - The event that triggered the SM
 * \return TI_OK on success or TI_NOK on failure
 * 
 * \par Description
 * Handles the CmdQueue SM.
 * 
 * \sa cmdQueue_Push, cmdQueue_ResultReceived
 */
static TI_STATUS cmdQueue_SM (TI_HANDLE hCmdQueue, ECmdQueueSmEvents eCmdQueueEvent)
{   
    TCmdQueue     *pCmdQueue = (TCmdQueue*)hCmdQueue;
    TI_BOOL        bBreakWhile = TI_FALSE;
    TI_STATUS      rc = TI_OK, status;
    TCmdQueueNode *pHead;
    TI_UINT32      uReadLen, uWriteLen;

    while(!bBreakWhile)
    {
        switch (pCmdQueue->state)
        {
            case CMDQUEUE_STATE_IDLE:
                switch(eCmdQueueEvent)
                {
                    case CMDQUEUE_EVENT_RUN:
                        pCmdQueue->state = CMDQUEUE_STATE_WAIT_FOR_COMPLETION;

                        pHead = &pCmdQueue->aCmdQueue[pCmdQueue->head];

                        #ifdef CMDQUEUE_DEBUG_PRINT
                        TRACE4(pCmdQueue->hReport, REPORT_SEVERITY_CONSOLE, "cmdQueue_SM: Send Cmd: CmdType = %d(%d) Len = %d, NumOfCmd = %d", pHead->cmdType, (pHead->aParamsBuf) ?  *(TI_UINT16 *)pHead->aParamsBuf:0, pHead->uParamsLen, pCmdQueue->uNumberOfCommandInQueue);

                        WLAN_OS_REPORT(("cmdQueue_SM: Send Cmd: CmdType = %s(%s)\n"
                                        "Len = %d, NumOfCmd = %d \n",
                                        cmdQueue_GetCmdString(pHead->cmdType),
                                        (pHead->aParamsBuf) ?  cmdQueue_GetIEString(pHead->cmdType,*(TI_UINT16 *)pHead->aParamsBuf):"",
                                        pHead->uParamsLen, pCmdQueue->uNumberOfCommandInQueue));
                        #endif
                
                        #ifdef TI_DBG
                            pCmdQueue->uCmdSendCounter++;
                        #endif 

                        /* 
                         * if bAwake is true, then we reached here because there were more commands 
                         * in the queue after sending a previous command.
                         * There is no need to send another awake command to TwIf. 
                         */
                        if (pCmdQueue->bAwake == TI_FALSE)
                        {
                            /* Keep the device awake for the entire Cmd transaction */
                            twIf_Awake(pCmdQueue->hTwIf);
                            pCmdQueue->bAwake = TI_TRUE;
                        }

                        if (pHead->cmdType == CMD_INTERROGATE)
                        {
                            uWriteLen = CMDQUEUE_INFO_ELEM_HEADER_LEN;
                            /* Will be updated by CmdMbox to count the status response */
                            uReadLen = pHead->uParamsLen;
                        }
                        else if(pHead->cmdType == CMD_TEST)
                        {
                            /* CMD_TEST has configure & interrogate abillities together */
                            uWriteLen = pHead->uParamsLen;
                            /* Will be updated by CmdMbox to count the status response */
                            uReadLen = pHead->uParamsLen;
                        }
                        else if (pHead->cmdType == CMD_NOP)
                        {
                            /* NOP command is used for synchronizaiton purpose only, no FW transaction */
                            eCmdQueueEvent = CMDQUEUE_EVENT_COMPLETE;
                            break;
                        }
                        else /* CMD_CONFIGURE or others */
                        {
                            uWriteLen = pHead->uParamsLen;
                            /* Will be updated by CmdMbox to count the status response */
                            uReadLen = 0;

                        }
                        /* send the command to TNET */
                        rc = cmdMbox_SendCommand (pCmdQueue->hCmdMBox, 
                                              pHead->cmdType, 
                                              pHead->aParamsBuf, 
                                              uWriteLen,
                                              uReadLen);

                        bBreakWhile = TI_TRUE;

                        /* end of CMDQUEUE_EVENT_RUN */
                        break;

                    default:
                        TRACE1(pCmdQueue->hReport, REPORT_SEVERITY_ERROR, "cmdQueue_SM: ** ERROR **  No such event (%d) for state CMDQUEUE_STATE_IDLE\n",eCmdQueueEvent);
                        bBreakWhile = TI_TRUE;
                        rc =  TI_NOK;

                        break;
                }
                break;
            
            case CMDQUEUE_STATE_WAIT_FOR_COMPLETION:
                switch(eCmdQueueEvent)
                {
                    case CMDQUEUE_EVENT_RUN:
                        /* We are in the middle of other command transaction so there is nothing top be done */
                        bBreakWhile = TI_TRUE;
                        rc = TXN_STATUS_PENDING;
                        break;

                    case CMDQUEUE_EVENT_COMPLETE:
                        {
                            Command_e cmdType;
                            TI_UINT16        uParam;
                            void *fCb, *hCb, *pCb;
                            CommandStatus_e cmdStatus;

                            pHead = &pCmdQueue->aCmdQueue[pCmdQueue->head];
            
                            /* Keep callback parameters in temporary variables */
                            cmdType = pHead->cmdType;
                            uParam  = *(TI_UINT16 *)pHead->aParamsBuf;
                            fCb = pHead->fCb;
                            hCb = pHead->hCb;
                            pCb = pHead->pInterrogateBuf;
                            
                            /* 
                             * Delete the command from the queue before calling a callback 
                             * because there may be nested calls inside a callback
                             */
                            pCmdQueue->head ++;
                            if (pCmdQueue->head >= CMDQUEUE_QUEUE_DEPTH)
                                pCmdQueue->head = 0;                
                            pCmdQueue->uNumberOfCommandInQueue --;                
                
                        #ifdef TI_DBG
                            pCmdQueue->uCmdCompltCounter++;
                        #endif 

                            /* Read the latest command return status */
                            if (pHead->cmdType != CMD_NOP)
                            {
                                status = cmdMbox_GetStatus (pCmdQueue->hCmdMBox, &cmdStatus);
                            }
                            else
                            {
                                /* NOP command is used for synchronizaiton purpose only, no FW transaction */
                                status = TI_OK;
                            }
                            if (status != TI_OK)
                            {
                                if (cmdStatus == CMD_STATUS_REJECT_MEAS_SG_ACTIVE)
                                {
                                    /* return reject status in the callback */
                                    status = SG_REJECT_MEAS_SG_ACTIVE;
                                    pCmdQueue->bErrorFlag = TI_FALSE;
                                }
                                else
                                {
                                    WLAN_OS_REPORT(("cmdQueue_SM: ** ERROR **  Mbox status error %d, set bErrorFlag !!!!!\n", cmdStatus));
                                    TRACE1(pCmdQueue->hReport, REPORT_SEVERITY_ERROR, "cmdQueue_SM: ** ERROR **  Mbox status error %d, set bErrorFlag !!!!!\n", cmdStatus);
                                    pCmdQueue->bErrorFlag = TI_TRUE;
                                }
                            }
                            else
                            {
                                pCmdQueue->bErrorFlag = TI_FALSE;
                            }

                            /* If the command had a CB, then call it with the proper results buffer */
                            if (fCb)
                            {   
                                if (pCb)
                                {
                                    /* If pInterrogateBuf isn't NULL we need to copy the results */
                                    cmdMbox_GetCmdParams(pCmdQueue->hCmdMBox, pCb);
                                    /* Call the CB with the result buffer and the returned status */
                                    ((TCmdQueueInterrogateCb)fCb) (hCb, status, pCb); 
                                }
                                else
                                {
                                    /* Call the CB with only the returned status */
                                    ((TCmdQueueCb)fCb) (hCb, status);
                                }
                            }
                            else
                            {
                                /* Call the generic callback */
                                if (pCmdQueue->fCmdCompleteCb)
                                {
                                    pCmdQueue->fCmdCompleteCb (pCmdQueue->hCmdCompleteCb, cmdType, uParam, status);
                                }
                            }

                            /* Check if there are any more commands in queue */
                            if (pCmdQueue->uNumberOfCommandInQueue > 0)               
                            {
                                /* If queue isn't empty, send the next command */
                                pCmdQueue->state = CMDQUEUE_STATE_IDLE;
                                eCmdQueueEvent = CMDQUEUE_EVENT_RUN;
                            }
                            else	
                            {   
                                /* If queue is empty, we can permit TwIf to send sleep a command if neccesary */
                                twIf_Sleep(pCmdQueue->hTwIf);
                                pCmdQueue->bAwake = TI_FALSE;
                                pCmdQueue->state = CMDQUEUE_STATE_IDLE;

                                bBreakWhile = TI_TRUE;
                            }
                        /* end of CMDQUEUE_EVENT_COMPLETE */
                        }            
                        break;

                    default:
                        TRACE1(pCmdQueue->hReport, REPORT_SEVERITY_ERROR, "cmdQueue_SM: ** ERROR **  No such event (%d) for state CMDQUEUE_STATE_IDLE\n",eCmdQueueEvent);
                        bBreakWhile = TI_TRUE;
                        rc =  TI_NOK;

                        break;

                /* end of switch event */
                } 
                break;
        /* end of switch state */
        }
    /* end of while */
    }

    return rc;
}
Ejemplo n.º 4
0
/*
 * \brief	FW-Event state machine
 *
 * \param  hFwEvent  - FwEvent Driver handle
 * \return void
 *
 * \par Description
 *
 * Process the current FW events in a sequence that may progress in the same context,
 *     or exit if pending an Async transaction, which will call back the SM when finished.
 *
 * \sa
 */
static void fwEvent_StateMachine (TfwEvent *pFwEvent)
{
	ETxnStatus  eStatus = TXN_STATUS_ERROR; /* Set to error to detect if used uninitialized */

	/*
	 * Loop through the states sequence as long as the process is synchronous.
	 * Exit when finished or if an Asynchronous process is required.
	 * In this case the SM will be called back upon Async operation completion.
	 */
	while (1) {
		switch (pFwEvent->eSmState) {
			/* IDLE: Update TwIf and read interrupt info from FW */
		case FWEVENT_STATE_IDLE: {
			twIf_Awake(pFwEvent->hTwIf);
			eStatus = fwEvent_SmReadIntrInfo (pFwEvent);
			pFwEvent->eSmState = FWEVENT_STATE_WAIT_INTR_INFO;
			break;
		}
		/* WAIT_INTR_INFO: We have the interrupt info so call the handlers accordingly */
		case FWEVENT_STATE_WAIT_INTR_INFO: {
			eStatus = fwEvent_SmHandleEvents (pFwEvent);
			/* If state was changed to IDLE by recovery or stop process, exit (process terminated) */
			if (pFwEvent->eSmState == FWEVENT_STATE_IDLE) {
				return;
			}
			pFwEvent->eSmState = FWEVENT_STATE_WAIT_HANDLE_COMPLT;
			break;
		}
		/* WAIT_HANDLE_COMPLT: Current handling is completed. */
		case FWEVENT_STATE_WAIT_HANDLE_COMPLT: {
			/* If pending interrupt, read interrupt info (back to WAIT_INTR_INFO state) */
			if (pFwEvent->bIntrPending) {
				pFwEvent->bIntrPending = TI_FALSE;
				eStatus = fwEvent_SmReadIntrInfo (pFwEvent);
				pFwEvent->eSmState = FWEVENT_STATE_WAIT_INTR_INFO;
			}
			/* Else - all done so release TwIf to sleep and exit */
			else {
				twIf_Sleep(pFwEvent->hTwIf);
				pFwEvent->eSmState = FWEVENT_STATE_IDLE;


				/**** Finished all current events handling so exit ****/
				return;
			}
			break;
		}

		}  /* switch */


		/* If last status is Pending, exit the SM (to be called back upon Async operation completion) */
		if (eStatus == TXN_STATUS_PENDING) {
			return;
		}

		/* If error occured, stop the process and exit (should be cleaned by recovery process) */
		else if (eStatus == TXN_STATUS_ERROR) {
			fwEvent_Stop ((TI_HANDLE)pFwEvent);
			return;
		}

		/* If we got here the status is COMPLETE so continue in the while loop to the next state */

	}  /* while */
}
/*
 * \brief	This function is validating the SDIO lines by write / read / compare operations.
 * 
 * \param  hFwDebug    - Handle to FW Debug.
 * \param  uNumOfLoops - Number of times to run the validation test.
 * \param  uTxnSize    - Size of the transaction (in bytes) to use in the validation test.
 *
 * \return TI_STATUS
 * 
 * \par Description
 * This function is validating the SDIO lines by writing data to the chip
 * memory, and then reading it and compares it to the written data.
 * The following steps are taken:
 *  1. Disables ELP so the chip won't go to sleep.
 *  2. Disables all interrupts - This is done to disable Watchdog so no recovery will be done on the driver side.
 *  3. Halts the coretex.
 *  4. Make the read / write / compare - Most of this part is done by calling fwDbg_SdioValidationSM().
 * 
 * \sa 
 */
TI_STATUS fwDbg_ValidateSdio(TI_HANDLE hFwDebug, TI_UINT32 uNumOfLoops, TI_UINT32 uTxnSize)
{
    TFwDebug   *pFwDebug       = (TFwDebug *)hFwDebug;

    TI_UINT8    aDataBuffer[8] = { 'B', 'E', 'E', 'F', '4' ,'4' ,'7' ,'8' };  /* Constant data to fill in write buffer */
    TI_UINT32   uWriteBufIdx   = 0;                                           /* Index in write buffer - used to fill data inside */
    
    TTxnStruct *pTxn           = &pFwDebug->tTxn;




    WLAN_OS_REPORT(("----- SDIO Validation Test ----> Started [Performing %d iterations of %d bytes in transaction]. \n\n",
        uNumOfLoops, uTxnSize));



    /* Parameter range check - Make sure uTxnSize is in range */
    if( (uTxnSize == 0) || (uTxnSize > TWD_SDIO_VALIDATION_TXN_SIZE_MAX) )
    {
        WLAN_OS_REPORT(("fwDbg_ValidateSdio() - uTxnSize (%d) is out of range. Set to %d. \n", 
            uTxnSize, TWD_SDIO_VALIDATION_TXN_SIZE_DEFAULT));

        uTxnSize = TWD_SDIO_VALIDATION_TXN_SIZE_DEFAULT;
    }

    /* Parameter range check - Make sure uNumOfLoops is in range */
    if(uNumOfLoops > TWD_SDIO_VALIDATION_NUM_LOOPS_MAX)
    {
        WLAN_OS_REPORT(("fwDbg_ValidateSdio() - uNumOfLoops (%d) is out of range. Set to %d. \n", 
            uNumOfLoops, TWD_SDIO_VALIDATION_NUM_LOOPS_DEFAULT));
        
        uNumOfLoops = TWD_SDIO_VALIDATION_NUM_LOOPS_DEFAULT;
    }


    /* 
       1. Disable ELP:
          ------------
          - Call twIf_Awake() - it is not enough for disabling the ELP.
          - Only after the next transaction, it is promised that the chip will be awake (ELP disabled)
    */

    twIf_Awake(pFwDebug->hTwif);


    /* 2. Disable all interrupts */
    /*    ---------------------- */
    
    fwEvent_MaskAllFwInterrupts(pFwDebug->hFwEvent);


    /* 3. Halt Coretex */
    /*    ------------ */

    pFwDebug->uSdioTestZero = 0;

    TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
    BUILD_TTxnStruct(pTxn, ACX_REG_ECPU_CONTROL, &(pFwDebug->uSdioTestZero), REGISTER_SIZE, NULL, pFwDebug)
    
    twIf_Transact(pFwDebug->hTwif, pTxn);


    /* 4. Make the read / write / compare */
    /*    ------------------------------- */


    /* Allocate memory for pFwDebug->pSdioTestWriteBuf */
    pFwDebug->pSdioTestWriteBuf = (TI_UINT8 *)os_memoryAlloc(pFwDebug->hOs, uTxnSize);


    /* Assert Allocation */
    if(NULL == pFwDebug->pSdioTestWriteBuf)
    {
        WLAN_OS_REPORT(("fwDbg_ValidateSdio() - Allocation for write buffer failed! \n"));
    
        return TI_NOK;
    }


    /* Allocate memory for pFwDebug->pSdioTestReadBuf */
    pFwDebug->pSdioTestReadBuf = (TI_UINT8 *)os_memoryAlloc(pFwDebug->hOs, uTxnSize);

    /* Assert Allocation */
    if(NULL == pFwDebug->pSdioTestReadBuf)
    {
        WLAN_OS_REPORT(("fwDbg_ValidateSdio() - Allocation for read buffer failed! \n"));

        /* Free pre-allocated pFwDebug->pSdioTestWriteBuf */
        os_memoryFree(pFwDebug->hOs, pFwDebug->pSdioTestWriteBuf, uTxnSize);

        return TI_NOK;
    }

    /* Set pFwDebug struct fields */
    pFwDebug->uSdioTestTxnSize        = uTxnSize;
    pFwDebug->uSdioTestNumOfLoops     = uNumOfLoops;
    pFwDebug->uSdioTestCurrentLoopNum = 0;
    pFwDebug->eSdioTestState          = FWDEBUG_SDIO_TEST_STATE_WRITE_READ;
    pFwDebug->bSdioTestPassed         = TI_TRUE;



    /* Fill data in pFwDebug->pSdioTestWriteBuf */
    for(uWriteBufIdx = 0; uWriteBufIdx < uTxnSize; uWriteBufIdx++)
    {
        pFwDebug->pSdioTestWriteBuf[uWriteBufIdx] = aDataBuffer[uWriteBufIdx % sizeof(aDataBuffer)];
    }

    /* Call the SM function to perform the Read / Write / Compare test */
    fwDbg_SdioValidationSM(hFwDebug, NULL);


    return TI_OK;
}