/*----------------------------------------------------------------------------*/
VOID
roamingFsmSteps (
    IN P_ADAPTER_T prAdapter,
    IN ENUM_ROAMING_STATE_T eNextState
    )
{
    P_ROAMING_INFO_T prRoamingFsmInfo;
    ENUM_ROAMING_STATE_T ePreviousState;
    BOOLEAN fgIsTransition = (BOOLEAN)FALSE;

    prRoamingFsmInfo = (P_ROAMING_INFO_T)&(prAdapter->rWifiVar.rRoamingInfo);

    do {

        /* Do entering Next State */
#if DBG
        DBGLOG(ROAMING, STATE, ("TRANSITION: [%s] -> [%s]\n",
                            apucDebugRoamingState[prRoamingFsmInfo->eCurrentState],
                            apucDebugRoamingState[eNextState]));
#else
        DBGLOG(ROAMING, STATE, ("[%d] TRANSITION: [%d] -> [%d]\n",
                            DBG_ROAMING_IDX,
                            prRoamingFsmInfo->eCurrentState,
                            eNextState));
#endif
        /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */
        ePreviousState = prRoamingFsmInfo->eCurrentState;
        prRoamingFsmInfo->eCurrentState = eNextState;

        fgIsTransition = (BOOLEAN)FALSE;

        /* Do tasks of the State that we just entered */
        switch (prRoamingFsmInfo->eCurrentState) {
        /* NOTE(Kevin): we don't have to rearrange the sequence of following
         * switch case. Instead I would like to use a common lookup table of array
         * of function pointer to speed up state search.
         */
        case ROAMING_STATE_IDLE:
        case ROAMING_STATE_DECISION:
        	  break;

        case ROAMING_STATE_DISCOVERY:
        	  {
        	      OS_SYSTIME rCurrentTime;

        	      GET_CURRENT_SYSTIME(&rCurrentTime);
                if (CHECK_FOR_TIMEOUT(rCurrentTime, prRoamingFsmInfo->rRoamingDiscoveryUpdateTime,
                                      SEC_TO_SYSTIME(ROAMING_DISCOVERY_TIMEOUT_SEC))) {
                    DBGLOG(ROAMING, LOUD, ("roamingFsmSteps: DiscoveryUpdateTime Timeout"));
                    aisFsmRunEventRoamingDiscovery(prAdapter, TRUE);
                }
                else {
                	  DBGLOG(ROAMING, LOUD, ("roamingFsmSteps: DiscoveryUpdateTime Updated"));
                	  aisFsmRunEventRoamingDiscovery(prAdapter, FALSE);
                }
            }
        	  break;

        case ROAMING_STATE_ROAM:
        	  break;

        default:
            ASSERT(0); /* Make sure we have handle all STATEs */
        }
    }
    while (fgIsTransition);

    return;

} /* end of roamingFsmSteps() */
/*----------------------------------------------------------------------------*/
BOOLEAN nicpmSetDriverOwn(IN P_ADAPTER_T prAdapter)
{
#define LP_OWN_BACK_TOTAL_DELAY_MS      2048    /* exponential of 2 */
#define LP_OWN_BACK_LOOP_DELAY_MS       1       /* exponential of 2 */
#define LP_OWN_BACK_CLR_OWN_ITERATION   256     /* exponential of 2 */
#define LP_OWN_BACK_FAILED_RETRY_CNT    5
#define LP_OWN_BACK_FAILED_LOG_SKIP_MS  2000
#define LP_OWN_BACK_FAILED_RESET_CNT    5

	BOOLEAN fgStatus = TRUE;
	UINT_32 i, u4CurrTick, u4RegValue = 0;
	BOOLEAN fgTimeout;

	ASSERT(prAdapter);

	if (prAdapter->fgIsFwOwn == FALSE)
		return fgStatus;

	DBGLOG(INIT, INFO, ("DRIVER OWN\n"));

	u4CurrTick = kalGetTimeTick();
	i = 0;
	while (1) {
		HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue);

		fgTimeout =
		    ((kalGetTimeTick() - u4CurrTick) > LP_OWN_BACK_TOTAL_DELAY_MS) ? TRUE : FALSE;

		if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) {
			prAdapter->fgIsFwOwn = FALSE;
            prAdapter->u4OwnFailedCount = 0;
            prAdapter->u4OwnFailedLogCount = 0;
			break;
        }
        else if((i > LP_OWN_BACK_FAILED_RETRY_CNT) && 
            (kalIsCardRemoved(prAdapter->prGlueInfo) || fgIsBusAccessFailed || fgTimeout || wlanIsChipNoAck(prAdapter))) {

            if ((prAdapter->u4OwnFailedCount == 0) || 
                CHECK_FOR_TIMEOUT(u4CurrTick, prAdapter->rLastOwnFailedLogTime, MSEC_TO_SYSTIME(LP_OWN_BACK_FAILED_LOG_SKIP_MS))) {
                      
                DBGLOG(INIT, ERROR, ("LP cannot be own back, Timeout[%u](%ums), BusAccessError[%u], Reseting[%u], CardRemoved[%u] NoAck[%u] Cnt[%u]\n",
                    fgTimeout,
                    kalGetTimeTick() - u4CurrTick,
                    fgIsBusAccessFailed,
                    kalIsResetting(),
                    kalIsCardRemoved(prAdapter->prGlueInfo),
                    wlanIsChipNoAck(prAdapter), 
                    prAdapter->u4OwnFailedCount));

                DBGLOG(INIT, INFO, ("Skip LP own back failed log for next %ums\n", LP_OWN_BACK_FAILED_LOG_SKIP_MS));

                prAdapter->u4OwnFailedLogCount++;
                if(prAdapter->u4OwnFailedLogCount > LP_OWN_BACK_FAILED_RESET_CNT) {
                    /* Trigger RESET */
#if CFG_CHIP_RESET_SUPPORT                    
                    glResetTrigger(prAdapter);
#endif
                }
                GET_CURRENT_SYSTIME(&prAdapter->rLastOwnFailedLogTime);
            }
            
            prAdapter->u4OwnFailedCount++;
			fgStatus = FALSE;
			break;
		} else {
			if ((i & (LP_OWN_BACK_CLR_OWN_ITERATION - 1)) == 0) {
				/* Software get LP ownership - per 256 iterations */
				HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR);
			}

			/* Delay for LP engine to complete its operation. */
			kalMsleep(LP_OWN_BACK_LOOP_DELAY_MS);
			i++;
		}
	}

	return fgStatus;
}