Home | History | Annotate | Download | only in Ctrl_Interface
      1 /*
      2  * DrvMain.c
      3  *
      4  * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  *
     11  *  * Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  *  * Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in
     15  *    the documentation and/or other materials provided with the
     16  *    distribution.
     17  *  * Neither the name Texas Instruments nor the names of its
     18  *    contributors may be used to endorse or promote products derived
     19  *    from this software without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 
     35 /** \file   DrvMain.c
     36  *  \brief  The DrvMain module. Handles driver init, stop and recovery processes.
     37  *
     38  *  \see    DrvMain.h
     39  */
     40 
     41 #define __FILE_ID__  FILE_ID_49
     42 #include "tidef.h"
     43 #include "osApi.h"
     44 #include "report.h"
     45 #include "context.h"
     46 #include "timer.h"
     47 #include "CmdHndlr.h"
     48 #include "DrvMain.h"
     49 #include "scrApi.h"
     50 #include "EvHandler.h"
     51 #include "connApi.h"
     52 #include "siteMgrApi.h"
     53 #include "sme.h"
     54 #include "SoftGeminiApi.h"
     55 #include "roamingMngrApi.h"
     56 #include "qosMngr_API.h"
     57 #include "TrafficMonitor.h"
     58 #include "PowerMgr_API.h"
     59 #include "EvHandler.h"
     60 #include "apConn.h"
     61 #include "currBss.h"
     62 #include "SwitchChannelApi.h"
     63 #include "ScanCncn.h"
     64 #include "healthMonitor.h"
     65 #include "scanMngrApi.h"
     66 #include "regulatoryDomainApi.h"
     67 #include "measurementMgrApi.h"
     68 #ifdef XCC_MODULE_INCLUDED
     69 #include "XCCMngr.h"
     70 #endif
     71 #include "TxnQueue.h"
     72 #include "TWDriver.h"
     73 #include "debug.h"
     74 #include "host_platform.h"
     75 #include "StaCap.h"
     76 #include "WlanDrvCommon.h"
     77 #include "DrvMainModules.h"
     78 #include "CmdDispatcher.h"
     79 
     80 
     81 #define SM_WATCHDOG_TIME_MS     20000  /* SM processes timeout is 20 sec. */
     82 
     83 #define SDIO_CONNECT_THRESHOLD  8
     84 
     85 /* This is used to prevent endless recovery loops */
     86 #define MAX_NUM_OF_RECOVERY_TRIGGERS 5
     87 
     88 /* Handle failure status from the SM callbacks by triggering the SM with FAILURE event */
     89 #define HANDLE_CALLBACKS_FAILURE_STATUS(hDrvMain, eStatus)      \
     90             if (eStatus != TI_OK) { drvMain_SmEvent (hDrvMain, SM_EVENT_FAILURE);  return; }
     91 
     92 /* The DrvMain SM states */
     93 typedef enum
     94 {
     95     /*  0 */ SM_STATE_IDLE,
     96     /*  1 */ SM_STATE_WAIT_INI_FILE,
     97     /*  2 */ SM_STATE_WAIT_NVS_FILE,
     98     /*  3 */ SM_STATE_HW_INIT,
     99     /*  4 */ SM_STATE_DOWNLOAD_FW_FILE,
    100     /*  5 */ SM_STATE_WAIT_FW_FILE,
    101     /*  6 */ SM_STATE_FW_INIT,
    102     /*  7 */ SM_STATE_FW_CONFIG,
    103     /*  8 */ SM_STATE_OPERATIONAL,
    104     /*  9 */ SM_STATE_DISCONNECTING,
    105     /* 10 */ SM_STATE_STOPPING,
    106     /* 11 */ SM_STATE_STOPPED,
    107     /* 12 */ SM_STATE_STOPPING_ON_FAIL,
    108     /* 13 */ SM_STATE_FAILED
    109 
    110 } ESmState;
    111 
    112 /* The DrvMain SM events */
    113 typedef enum
    114 {
    115     /*  0 */ SM_EVENT_START,
    116     /*  1 */ SM_EVENT_INI_FILE_READY,
    117     /*  2 */ SM_EVENT_NVS_FILE_READY,
    118     /*  3 */ SM_EVENT_HW_INIT_COMPLETE,
    119     /*  4 */ SM_EVENT_FW_FILE_READY,
    120     /*  5 */ SM_EVENT_FW_INIT_COMPLETE,
    121     /*  6 */ SM_EVENT_FW_CONFIG_COMPLETE,
    122     /*  7 */ SM_EVENT_STOP,
    123     /*  8 */ SM_EVENT_RECOVERY,
    124     /*  9 */ SM_EVENT_DISCONNECTED,
    125     /* 10 */ SM_EVENT_STOP_COMPLETE,
    126     /* 11 */ SM_EVENT_FAILURE
    127 
    128 } ESmEvent;
    129 
    130 /* The module's object */
    131 typedef struct
    132 {
    133     TStadHandlesList  tStadHandles; /* All STAD modules handles (distributed in driver init process) */
    134 	TI_BOOL           bRecovery;    /* Indicates if we are during recovery process */
    135 	TI_UINT32         uNumOfRecoveryAttempts;    /* Indicates if we are during recovery process */
    136 	ESmState          eSmState;     /* The DrvMain SM state. */
    137 	ESmEvent          ePendingEvent;/* A pending event issued when the SM is busy */
    138     TI_UINT32         uPendingEventsCount; /* Counts the number of events pending for SM execution */
    139     TFileInfo         tFileInfo;    /* Information of last file retrieved by os_GetFile() */
    140     TI_UINT32         uContextId;   /* ID allocated to this module on registration to context module */
    141     EActionType       eAction;      /* The last action (start/stop) inserted to the driver */
    142     void             *hSignalObj;   /* The signal object used for waiting for action completion */
    143     TBusDrvCfg        tBusDrvCfg;   /* A union (struc per each supported bus type) for the bus driver configuration */
    144     TI_UINT32         uRxDmaBufLen; /* The bus driver Rx DMA buffer length (needed as a limit for Rx aggregation length) */
    145     TI_UINT32         uTxDmaBufLen; /* The bus driver Tx DMA buffer length (needed as a limit for Tx aggregation length) */
    146 
    147 } TDrvMain;
    148 
    149 
    150 static void drvMain_Init (TI_HANDLE hDrvMain);
    151 static void drvMain_InitHwCb (TI_HANDLE hDrvMain, TI_STATUS eStatus);
    152 static void drvMain_InitFwCb (TI_HANDLE hDrvMain, TI_STATUS eStatus);
    153 static void drvMain_ConfigFwCb (TI_HANDLE hDrvMain, TI_STATUS eStatus);
    154 static void drvMain_TwdStopCb (TI_HANDLE hDrvMain, TI_STATUS eStatus);
    155 static void drvMain_InitFailCb (TI_HANDLE hDrvMain, TI_STATUS eStatus);
    156 static void drvMain_InitLocals (TDrvMain *pDrvMain);
    157 /* static void drvMain_SmWatchdogTimeout (TI_HANDLE hDrvMain); */
    158 static void drvMain_SmEvent (TI_HANDLE hDrvMain, ESmEvent eEvent);
    159 static void drvMain_Sm (TI_HANDLE hDrvMain, ESmEvent eEvent);
    160 
    161 /* External functions prototypes */
    162 
    163 /** \brief WLAN Driver I/F Get file
    164  *
    165  * \param  hOs         - OS module object handle
    166  * \param  pFileInfo   - Pointer to output file information
    167  * \return TI_OK on success or TI_NOK on failure
    168  *
    169  * \par Description
    170  * This function provides access to a requested init file:
    171  * It provides the requested file information and call the requester callback.
    172  * Note that in Linux the files were previously loaded to driver memory by the loader
    173  *
    174  * \sa
    175  */
    176 extern int  wlanDrvIf_GetFile (TI_HANDLE hOs, TFileInfo *pFileInfo);
    177 /** \brief WLAN Driver I/F Update Driver State
    178  *
    179  * \param  hOs          - OS module object handle
    180  * \param  eDriverState - New Driver State
    181  * \return void
    182  *
    183  * \par Description
    184  * This function Update the driver state (Idle | Running | Stopped |Failed):
    185  *
    186  * \sa
    187  */
    188 extern void wlanDrvIf_UpdateDriverState (TI_HANDLE hOs, EDriverSteadyState eDriverState);
    189 /** \brief WLAN Driver I/F Set MAC Address
    190  *
    191  * \param  hOs          - OS module object handle
    192  * \param  pMacAddr     - Pointer to MAC address to set
    193  * \return void
    194  *
    195  * \par Description
    196  * This function Update the driver MAC address by copy it to the network interface structure
    197  *
    198  * \sa
    199  */
    200 extern void wlanDrvIf_SetMacAddress (TI_HANDLE hOs, TI_UINT8 *pMacAddr);
    201 /** \brief OS Init Table INI File
    202  *
    203  * \param  hOs              - OS module object handle
    204  * \param  InitTable        - Pointer to initialization table
    205  * \param  file_buf         - Pointer to Input buffer from INI file
    206  * \param  file_length      - Length of input buffer from INI file
    207  * \return void
    208  *
    209  * \par Description
    210  * This function perform Initializing of init table accrding to data from INI file and driver defaults
    211  *
    212  * \sa
    213  */
    214 extern int  osInitTable_IniFile (TI_HANDLE hOs, TInitTable *InitTable, char *file_buf, int file_length);
    215 
    216 
    217 
    218 /*
    219  * \fn     drvMain_Create
    220  * \brief  Create the driver modules
    221  *
    222  * Create all STAD and TWD modules.
    223  * Then call all modules init functions which initializes their handles and variables.
    224  *
    225  * \note
    226  * \param  hOs          - Handle to the Os Abstraction Layer
    227  * \param  pDrvMainHndl - Pointer for returning the DrvMain handle.
    228  * \param  pCmdHndlr    - Pointer for returning the CmdHndlr handle.
    229  * \param  pContext     - Pointer for returning the Context handle.
    230  * \param  pTxDataQ     - Pointer for returning the TxDataQ handle.
    231  * \param  pTxMgmtQ     - Pointer for returning the TxMgmtQ handle.
    232  * \param  pTxCtrl      - Pointer for returning the TxCtrl handle.
    233  * \param  pTwd         - Pointer for returning the TWD handle.
    234  * \param  pEvHandler   - Pointer for returning the EvHndler handle.
    235  * \return Handle to the DrvMain module (NULL if failed)
    236  * \sa
    237  */
    238 TI_STATUS drvMain_Create (TI_HANDLE  hOs,
    239                           TI_HANDLE *pDrvMainHndl,
    240                           TI_HANDLE *pCmdHndlr,
    241                           TI_HANDLE *pContext,
    242                           TI_HANDLE *pTxDataQ,
    243                           TI_HANDLE *pTxMgmtQ,
    244                           TI_HANDLE *pTxCtrl,
    245                           TI_HANDLE *pTwd,
    246                           TI_HANDLE *pEvHandler,
    247 		                  TI_HANDLE *pCmdDispatch,
    248                           TI_HANDLE *pReport)
    249 {
    250     /* Create the DrvMain module object. */
    251     TDrvMain *pDrvMain = (TDrvMain *) os_memoryAlloc (hOs, sizeof(TDrvMain));
    252 
    253     if (pDrvMain == NULL)
    254     {
    255         return TI_NOK;
    256     }
    257 
    258     os_memoryZero (hOs, (void *)pDrvMain, sizeof(TDrvMain));
    259 
    260     pDrvMain->tStadHandles.hDrvMain = (TI_HANDLE)pDrvMain;
    261     pDrvMain->tStadHandles.hOs = hOs;
    262 
    263 /*
    264  *   Create all driver modules
    265  *   =========================
    266  */
    267 
    268     pDrvMain->tStadHandles.hContext = context_Create (hOs);
    269     if (pDrvMain->tStadHandles.hContext == NULL)
    270     {
    271         drvMain_Destroy (pDrvMain);
    272         return TI_NOK;
    273     }
    274 
    275     pDrvMain->tStadHandles.hTimer = tmr_Create (hOs);
    276     if (pDrvMain->tStadHandles.hTimer == NULL)
    277     {
    278         drvMain_Destroy (pDrvMain);
    279         return TI_NOK;
    280     }
    281 
    282     pDrvMain->tStadHandles.hSCR = scr_create (hOs);
    283     if (pDrvMain->tStadHandles.hSCR == NULL)
    284     {
    285         drvMain_Destroy (pDrvMain);
    286         return TI_NOK;
    287     }
    288 
    289     pDrvMain->tStadHandles.hTxnQ = txnQ_Create (hOs);
    290     if (pDrvMain->tStadHandles.hTxnQ == NULL)
    291     {
    292         drvMain_Destroy (pDrvMain);
    293         return TI_NOK;
    294     }
    295 
    296     pDrvMain->tStadHandles.hEvHandler = EvHandler_Create (hOs);
    297     if (pDrvMain->tStadHandles.hEvHandler == NULL)
    298     {
    299         drvMain_Destroy (pDrvMain);
    300         return TI_NOK;
    301     }
    302 
    303     pDrvMain->tStadHandles.hReport = report_Create (hOs);
    304     if (pDrvMain->tStadHandles.hReport == NULL)
    305     {
    306         drvMain_Destroy (pDrvMain);
    307         return TI_NOK;
    308     }
    309 
    310     pDrvMain->tStadHandles.hConn = conn_create (hOs);
    311     if (pDrvMain->tStadHandles.hConn == NULL)
    312     {
    313         drvMain_Destroy (pDrvMain);
    314         return TI_NOK;
    315     }
    316 
    317     pDrvMain->tStadHandles.hScanCncn = scanCncn_Create (hOs);
    318     if (pDrvMain->tStadHandles.hScanCncn == NULL)
    319     {
    320         drvMain_Destroy (pDrvMain);
    321         return TI_NOK;
    322     }
    323 
    324     pDrvMain->tStadHandles.hSme = sme_Create (hOs);
    325     if (pDrvMain->tStadHandles.hSme == NULL)
    326     {
    327         drvMain_Destroy (pDrvMain);
    328         return TI_NOK;
    329     }
    330 
    331     pDrvMain->tStadHandles.hSiteMgr = siteMgr_create (hOs);
    332     if (pDrvMain->tStadHandles.hSiteMgr == NULL)
    333     {
    334         drvMain_Destroy (pDrvMain);
    335         return TI_NOK;
    336     }
    337 
    338     pDrvMain->tStadHandles.hMlmeSm = mlme_create (hOs);
    339     if (pDrvMain->tStadHandles.hMlmeSm == NULL)
    340     {
    341         drvMain_Destroy (pDrvMain);
    342         return TI_NOK;
    343     }
    344 
    345     pDrvMain->tStadHandles.hAuth = auth_create (hOs);
    346     if (pDrvMain->tStadHandles.hAuth == NULL)
    347     {
    348         drvMain_Destroy (pDrvMain);
    349         return TI_NOK;
    350     }
    351 
    352     pDrvMain->tStadHandles.hAssoc = assoc_create (hOs);
    353     if (pDrvMain->tStadHandles.hAssoc == NULL)
    354     {
    355         drvMain_Destroy (pDrvMain);
    356         return TI_NOK;
    357     }
    358 
    359     pDrvMain->tStadHandles.hRxData = rxData_create (hOs);
    360     if (pDrvMain->tStadHandles.hRxData == NULL)
    361     {
    362         drvMain_Destroy (pDrvMain);
    363         return TI_NOK;
    364     }
    365 
    366     pDrvMain->tStadHandles.hTxCtrl = txCtrl_Create (hOs);
    367     if (pDrvMain->tStadHandles.hTxCtrl == NULL)
    368     {
    369         drvMain_Destroy (pDrvMain);
    370         return TI_NOK;
    371     }
    372 
    373     pDrvMain->tStadHandles.hTxDataQ = txDataQ_Create(hOs);
    374     if (pDrvMain->tStadHandles.hTxDataQ == NULL)
    375     {
    376         drvMain_Destroy (pDrvMain);
    377         return TI_NOK;
    378     }
    379 
    380     pDrvMain->tStadHandles.hTxMgmtQ = txMgmtQ_Create(hOs);
    381     if (pDrvMain->tStadHandles.hTxMgmtQ == NULL)
    382     {
    383         drvMain_Destroy (pDrvMain);
    384         return TI_NOK;
    385     }
    386 
    387     pDrvMain->tStadHandles.hTxPort = txPort_create (hOs);
    388     if (pDrvMain->tStadHandles.hTxPort == NULL)
    389     {
    390         drvMain_Destroy (pDrvMain);
    391         return TI_NOK;
    392     }
    393 
    394     pDrvMain->tStadHandles.hCtrlData = ctrlData_create (hOs);
    395     if (pDrvMain->tStadHandles.hCtrlData == NULL)
    396     {
    397         drvMain_Destroy (pDrvMain);
    398         return TI_NOK;
    399     }
    400 
    401     pDrvMain->tStadHandles.hTrafficMon = TrafficMonitor_create (hOs);
    402     if (pDrvMain->tStadHandles.hTrafficMon == NULL)
    403     {
    404         drvMain_Destroy (pDrvMain);
    405         return TI_NOK;
    406     }
    407 
    408     pDrvMain->tStadHandles.hRsn = rsn_create (hOs);
    409     if (pDrvMain->tStadHandles.hRsn == NULL)
    410     {
    411         drvMain_Destroy (pDrvMain);
    412         return TI_NOK;
    413     }
    414 
    415     pDrvMain->tStadHandles.hRegulatoryDomain = regulatoryDomain_create (hOs);
    416     if (pDrvMain->tStadHandles.hRegulatoryDomain == NULL)
    417     {
    418         drvMain_Destroy (pDrvMain);
    419         return TI_NOK;
    420     }
    421 
    422     pDrvMain->tStadHandles.hMeasurementMgr = measurementMgr_create (hOs);
    423     if (pDrvMain->tStadHandles.hMeasurementMgr == NULL)
    424     {
    425         drvMain_Destroy (pDrvMain);
    426         return TI_NOK;
    427     }
    428 
    429     pDrvMain->tStadHandles.hSoftGemini = SoftGemini_create (hOs);
    430     if (pDrvMain->tStadHandles.hSoftGemini == NULL)
    431     {
    432         drvMain_Destroy (pDrvMain);
    433         return TI_NOK;
    434     }
    435 
    436 #ifdef XCC_MODULE_INCLUDED
    437     pDrvMain->tStadHandles.hXCCMngr = XCCMngr_create (hOs);
    438     if (pDrvMain->tStadHandles.hXCCMngr == NULL)
    439     {
    440         drvMain_Destroy (pDrvMain);
    441         return TI_NOK;
    442     }
    443 #else
    444     pDrvMain->tStadHandles.hXCCMngr = NULL;
    445 #endif
    446 
    447     pDrvMain->tStadHandles.hRoamingMngr = roamingMngr_create (hOs);
    448     if (pDrvMain->tStadHandles.hRoamingMngr == NULL)
    449     {
    450         drvMain_Destroy (pDrvMain);
    451         return TI_NOK;
    452     }
    453 
    454     pDrvMain->tStadHandles.hAPConnection = apConn_create (hOs);
    455     if (pDrvMain->tStadHandles.hAPConnection == NULL)
    456     {
    457         drvMain_Destroy (pDrvMain);
    458         return TI_NOK;
    459     }
    460 
    461     pDrvMain->tStadHandles.hCurrBss = currBSS_create (hOs);
    462     if (pDrvMain->tStadHandles.hCurrBss == NULL)
    463     {
    464         drvMain_Destroy (pDrvMain);
    465         return TI_NOK;
    466     }
    467 
    468     pDrvMain->tStadHandles.hQosMngr = qosMngr_create (hOs);
    469     if (pDrvMain->tStadHandles.hQosMngr == NULL)
    470     {
    471         drvMain_Destroy (pDrvMain);
    472         return TI_NOK;
    473     }
    474 
    475     pDrvMain->tStadHandles.hPowerMgr = PowerMgr_create (hOs);
    476     if (pDrvMain->tStadHandles.hPowerMgr == NULL)
    477     {
    478         drvMain_Destroy (pDrvMain);
    479         return TI_NOK;
    480     }
    481 
    482     pDrvMain->tStadHandles.hSwitchChannel = switchChannel_create (hOs);
    483     if (pDrvMain->tStadHandles.hSwitchChannel == NULL)
    484     {
    485         drvMain_Destroy (pDrvMain);
    486         return TI_NOK;
    487     }
    488 
    489     pDrvMain->tStadHandles.hScanMngr = scanMngr_create (hOs);
    490     if (NULL == pDrvMain->tStadHandles.hScanMngr)
    491     {
    492         drvMain_Destroy (pDrvMain);
    493         return TI_NOK;
    494     }
    495 
    496     pDrvMain->tStadHandles.hHealthMonitor = healthMonitor_create (hOs);
    497     if (NULL == pDrvMain->tStadHandles.hHealthMonitor)
    498     {
    499         drvMain_Destroy (pDrvMain);
    500         return TI_NOK;
    501     }
    502 
    503     pDrvMain->tStadHandles.hTWD = TWD_Create (hOs);
    504     if (pDrvMain->tStadHandles.hTWD == NULL)
    505     {
    506         drvMain_Destroy (pDrvMain);
    507         return TI_NOK;
    508     }
    509 
    510     pDrvMain->tStadHandles.hCmdHndlr = cmdHndlr_Create (hOs, pDrvMain->tStadHandles.hEvHandler);
    511     if (pDrvMain->tStadHandles.hCmdHndlr == NULL)
    512     {
    513         drvMain_Destroy (pDrvMain);
    514         return TI_NOK;
    515     }
    516 
    517     pDrvMain->tStadHandles.hCmdDispatch = cmdDispatch_Create (hOs);
    518     if (pDrvMain->tStadHandles.hCmdDispatch == NULL)
    519     {
    520         drvMain_Destroy (pDrvMain);
    521         return TI_NOK;
    522     }
    523 
    524     pDrvMain->tStadHandles.hStaCap = StaCap_Create (hOs);
    525     if (pDrvMain->tStadHandles.hStaCap == NULL)
    526     {
    527         drvMain_Destroy (pDrvMain);
    528         return TI_NOK;
    529     }
    530 
    531     /* Bind all modules handles */
    532     drvMain_Init ((TI_HANDLE)pDrvMain);
    533 
    534 
    535     /* Provide required handles to the OAL */
    536     *pDrvMainHndl = (TI_HANDLE)pDrvMain;
    537     *pCmdHndlr    = pDrvMain->tStadHandles.hCmdHndlr;
    538     *pContext     = pDrvMain->tStadHandles.hContext;
    539     *pTxDataQ     = pDrvMain->tStadHandles.hTxDataQ;
    540     *pTxMgmtQ     = pDrvMain->tStadHandles.hTxMgmtQ;
    541     *pTxCtrl      = pDrvMain->tStadHandles.hTxCtrl;
    542     *pTwd         = pDrvMain->tStadHandles.hTWD;
    543     *pEvHandler   = pDrvMain->tStadHandles.hEvHandler;
    544     *pReport      = pDrvMain->tStadHandles.hReport;
    545     *pCmdDispatch = pDrvMain->tStadHandles.hCmdDispatch;
    546 
    547     WLAN_INIT_REPORT (("drvMain_Create: success\n"));
    548 
    549     return TI_OK;
    550 }
    551 
    552 /*
    553  * \fn     drvMain_Destroy
    554  * \brief  Destroy driver
    555  *
    556  * Destroy all STAD and TWD modules and resources.
    557  *
    558  * \note
    559  * \param  hDrvMain - The DrvMain object
    560  * \return TI_OK if succeeded, TI_NOK if failed.
    561  * \sa     drvMain_Create
    562  */
    563 TI_STATUS drvMain_Destroy (TI_HANDLE  hDrvMain)
    564 {
    565     TDrvMain *pDrvMain = (TDrvMain *)hDrvMain;
    566 
    567     hPlatform_Wlan_Hardware_DeInit ();
    568 
    569     if (pDrvMain == NULL)
    570     {
    571         return TI_NOK;
    572     }
    573 
    574     if (pDrvMain->tStadHandles.hScanMngr != NULL)
    575     {
    576         scanMngr_unload (pDrvMain->tStadHandles.hScanMngr);
    577     }
    578 
    579     if (pDrvMain->tStadHandles.hSiteMgr != NULL)
    580     {
    581         siteMgr_unLoad (pDrvMain->tStadHandles.hSiteMgr);
    582     }
    583 
    584     if (pDrvMain->tStadHandles.hSme != NULL)
    585     {
    586         sme_Destroy (pDrvMain->tStadHandles.hSme);
    587     }
    588 
    589     if (pDrvMain->tStadHandles.hConn != NULL)
    590     {
    591         conn_unLoad (pDrvMain->tStadHandles.hConn);
    592     }
    593 
    594     if (pDrvMain->tStadHandles.hTWD != NULL)
    595     {
    596         TWD_Destroy (pDrvMain->tStadHandles.hTWD);
    597     }
    598 
    599     if (pDrvMain->tStadHandles.hScanCncn != NULL)
    600     {
    601         scanCncn_Destroy (pDrvMain->tStadHandles.hScanCncn);
    602     }
    603 
    604     if (pDrvMain->tStadHandles.hTrafficMon != NULL)
    605     {
    606         TrafficMonitor_Destroy (pDrvMain->tStadHandles.hTrafficMon);
    607     }
    608 
    609     if (pDrvMain->tStadHandles.hCtrlData != NULL)
    610     {
    611         ctrlData_unLoad (pDrvMain->tStadHandles.hCtrlData);
    612     }
    613 
    614     if (pDrvMain->tStadHandles.hTxCtrl != NULL)
    615     {
    616         txCtrl_Unload (pDrvMain->tStadHandles.hTxCtrl);
    617     }
    618 
    619     if (pDrvMain->tStadHandles.hTxDataQ != NULL)
    620     {
    621         txDataQ_Destroy (pDrvMain->tStadHandles.hTxDataQ);
    622     }
    623 
    624     if (pDrvMain->tStadHandles.hTxMgmtQ != NULL)
    625     {
    626         txMgmtQ_Destroy (pDrvMain->tStadHandles.hTxMgmtQ);
    627     }
    628 
    629     if (pDrvMain->tStadHandles.hTxPort != NULL)
    630     {
    631         txPort_unLoad (pDrvMain->tStadHandles.hTxPort);
    632     }
    633 
    634     if (pDrvMain->tStadHandles.hRxData != NULL)
    635     {
    636         rxData_unLoad (pDrvMain->tStadHandles.hRxData);
    637     }
    638 
    639     if (pDrvMain->tStadHandles.hAssoc != NULL)
    640     {
    641         assoc_unload (pDrvMain->tStadHandles.hAssoc);
    642     }
    643 
    644     if (pDrvMain->tStadHandles.hAuth != NULL)
    645     {
    646         auth_unload (pDrvMain->tStadHandles.hAuth);
    647     }
    648 
    649     if (pDrvMain->tStadHandles.hMlmeSm != NULL)
    650     {
    651         mlme_unload (pDrvMain->tStadHandles.hMlmeSm);
    652     }
    653 
    654     if (pDrvMain->tStadHandles.hSCR != NULL)
    655     {
    656         scr_release (pDrvMain->tStadHandles.hSCR);
    657     }
    658 
    659 
    660     if (pDrvMain->tStadHandles.hRsn != NULL)
    661     {
    662         rsn_unload (pDrvMain->tStadHandles.hRsn);
    663     }
    664 
    665     if (pDrvMain->tStadHandles.hRegulatoryDomain != NULL)
    666     {
    667         regulatoryDomain_destroy (pDrvMain->tStadHandles.hRegulatoryDomain);
    668     }
    669 
    670     if (pDrvMain->tStadHandles.hMeasurementMgr != NULL)
    671     {
    672         measurementMgr_destroy (pDrvMain->tStadHandles.hMeasurementMgr);
    673     }
    674 
    675     if (pDrvMain->tStadHandles.hSoftGemini != NULL)
    676     {
    677         SoftGemini_destroy (pDrvMain->tStadHandles.hSoftGemini);
    678     }
    679 
    680 #ifdef XCC_MODULE_INCLUDED
    681     if (pDrvMain->tStadHandles.hXCCMngr != NULL)
    682     {
    683         XCCMngr_unload (pDrvMain->tStadHandles.hXCCMngr);
    684     }
    685 #endif
    686 
    687     if (pDrvMain->tStadHandles.hRoamingMngr != NULL)
    688     {
    689         roamingMngr_unload (pDrvMain->tStadHandles.hRoamingMngr);
    690     }
    691 
    692     if (pDrvMain->tStadHandles.hQosMngr != NULL)
    693     {
    694         qosMngr_destroy (pDrvMain->tStadHandles.hQosMngr);
    695     }
    696 
    697     if (pDrvMain->tStadHandles.hPowerMgr != NULL)
    698     {
    699         PowerMgr_destroy (pDrvMain->tStadHandles.hPowerMgr);
    700     }
    701 
    702     if (pDrvMain->tStadHandles.hAPConnection != NULL)
    703     {
    704         apConn_unload (pDrvMain->tStadHandles.hAPConnection);
    705     }
    706 
    707     if (pDrvMain->tStadHandles.hCurrBss != NULL)
    708     {
    709         currBSS_unload (pDrvMain->tStadHandles.hCurrBss);
    710     }
    711 
    712     if (pDrvMain->tStadHandles.hSwitchChannel != NULL)
    713     {
    714         switchChannel_unload (pDrvMain->tStadHandles.hSwitchChannel);
    715     }
    716 
    717     if (pDrvMain->tStadHandles.hHealthMonitor != NULL)
    718     {
    719         healthMonitor_unload (pDrvMain->tStadHandles.hHealthMonitor);
    720     }
    721 
    722     if (pDrvMain->tStadHandles.hCmdHndlr && pDrvMain->tStadHandles.hEvHandler)
    723     {
    724         cmdHndlr_Destroy (pDrvMain->tStadHandles.hCmdHndlr, pDrvMain->tStadHandles.hEvHandler);
    725     }
    726 
    727     if (pDrvMain->tStadHandles.hEvHandler != NULL)
    728     {
    729          EvHandlerUnload (pDrvMain->tStadHandles.hEvHandler);
    730     }
    731 
    732     if (pDrvMain->tStadHandles.hCmdDispatch)
    733     {
    734         cmdDispatch_Destroy (pDrvMain->tStadHandles.hCmdDispatch);
    735     }
    736 
    737     if (pDrvMain->tStadHandles.hTxnQ != NULL)
    738     {
    739         txnQ_Destroy (pDrvMain->tStadHandles.hTxnQ);
    740     }
    741     /* Note: The Timer module must be destroyed last, so all created timers are already destroyed!! */
    742     if (pDrvMain->tStadHandles.hTimer != NULL)
    743     {
    744         tmr_Destroy (pDrvMain->tStadHandles.hTimer);
    745     }
    746 
    747     /* Note: Moved after timers for locks */
    748     if (pDrvMain->tStadHandles.hContext != NULL)
    749     {
    750         context_Destroy (pDrvMain->tStadHandles.hContext);
    751     }
    752 
    753     if (pDrvMain->tStadHandles.hStaCap != NULL)
    754     {
    755         StaCap_Destroy (pDrvMain->tStadHandles.hStaCap);
    756     }
    757 
    758     if (pDrvMain->tStadHandles.hReport != NULL)
    759     {
    760         report_Unload (pDrvMain->tStadHandles.hReport);
    761     }
    762 
    763     /* Destroy the DrvMain object */
    764     os_memoryFree (pDrvMain->tStadHandles.hOs, hDrvMain, sizeof(TDrvMain));
    765 
    766     return TI_OK;
    767 }
    768 
    769 void drvMain_SmeStop (TI_HANDLE hDrvMain)
    770 {
    771     drvMain_SmEvent (hDrvMain, SM_EVENT_DISCONNECTED);
    772 }
    773 
    774 
    775 /*
    776  * \fn     drvMain_Init
    777  * \brief  Init driver modules
    778  *
    779  * Called from OS context following the driver creation.
    780  * Calls all STAD and TWD modules Init functions, which are saving other modules handles,
    781  *     registering to other modules and initializing their variables.
    782  *
    783  * \note
    784  * \param  hDrvMain - The DrvMain object
    785  * \return void
    786  * \sa     drvMain_Create
    787  */
    788 static void drvMain_Init (TI_HANDLE hDrvMain)
    789 {
    790     TDrvMain    *pDrvMain = (TDrvMain *) hDrvMain;
    791     TStadHandlesList *pModules = &pDrvMain->tStadHandles; /* The STAD modules handles list */
    792 
    793     /*
    794      *  Init all modules handles, variables and registries
    795      */
    796     context_Init (pModules->hContext, pModules->hOs, pModules->hReport);
    797     tmr_Init (pModules->hTimer, pModules->hOs, pModules->hReport, pModules->hContext);
    798     txnQ_Init (pModules->hTxnQ, pModules->hOs, pModules->hReport, pModules->hContext);
    799     scr_init (pModules);
    800     conn_init (pModules);
    801     ctrlData_init (pModules,
    802                  #ifdef XCC_MODULE_INCLUDED
    803                    XCCMngr_LinkTestRetriesUpdate, pModules->hXCCMngr);
    804                  #else
    805                    NULL, NULL);
    806                  #endif
    807     siteMgr_init (pModules);
    808     regulatoryDomain_init (pModules);
    809     scanCncn_Init (pModules);
    810     auth_init (pModules);
    811     mlme_init (pModules);
    812     assoc_init (pModules);
    813     rxData_init (pModules);
    814     txCtrl_Init (pModules);
    815     txDataQ_Init (pModules);
    816     txMgmtQ_Init (pModules);
    817     txPort_init (pModules);
    818     TrafficMonitor_Init (pModules, 1000 /* pInitTable->trafficMonitorMinIntervalPercentage */);
    819     sme_Init (pModules);
    820     rsn_init (pModules);
    821     measurementMgr_init (pModules);
    822 #ifdef XCC_MODULE_INCLUDED
    823     XCCMngr_init (pModules);
    824 #endif
    825     scanMngr_init (pModules);
    826     currBSS_init (pModules);
    827     apConn_init (pModules);
    828     roamingMngr_init (pModules);
    829     qosMngr_init (pModules);
    830     switchChannel_init (pModules);
    831     healthMonitor_init (pModules);
    832     PowerMgr_init (pModules);
    833     SoftGemini_init (pModules);
    834     cmdDispatch_Init (pModules);
    835     StaCap_Init (pModules);
    836     cmdHndlr_Init (pModules);
    837 
    838     /* Init TWD component (handles, variables and registries) and provide callbacks for next steps */
    839     TWD_Init (pModules->hTWD,
    840               pModules->hReport,
    841               pModules->hDrvMain,
    842               pModules->hTimer,
    843               pModules->hContext,
    844               pModules->hTxnQ,
    845               (TTwdCallback)drvMain_InitHwCb,
    846               (TTwdCallback)drvMain_InitFwCb,
    847               (TTwdCallback)drvMain_ConfigFwCb,
    848               (TTwdCallback)drvMain_TwdStopCb,
    849               (TTwdCallback)drvMain_InitFailCb);
    850 
    851     /* Init DrvMain module local variables */
    852     drvMain_InitLocals (pDrvMain);
    853 }
    854 
    855 
    856 /*
    857  * \fn     drvMain_SetDefaults
    858  * \brief  Set driver default configuration
    859  *
    860  * Configure all STAD and TWD modules with their default settings from the ini-file.
    861  * Timers creation is also done at this stage.
    862  *
    863  * \note
    864  * \param  hDrvMain - The DrvMain object
    865  * \param  pBuf     - The ini-file data.
    866  * \param  uLength  - The ini-file length.
    867  * \return TI_OK if succeeded, TI_NOK if failed.
    868  * \sa     drvMain_Init
    869  */
    870 static TI_STATUS drvMain_SetDefaults (TI_HANDLE hDrvMain, TI_UINT8 *pBuf, TI_UINT32 uLength)
    871 {
    872     TDrvMain   *pDrvMain = (TDrvMain *) hDrvMain;
    873     TInitTable *pInitTable;
    874     TI_STATUS   eStatus;
    875 
    876     pInitTable = os_memoryAlloc (pDrvMain->tStadHandles.hOs, sizeof(TInitTable));
    877 
    878     /* Parse defaults */
    879     eStatus = osInitTable_IniFile (pDrvMain->tStadHandles.hOs, pInitTable, (char*)pBuf, (int)uLength);
    880 
    881     /*
    882      *  Configure modules with their default settings
    883      */
    884     report_SetDefaults (pDrvMain->tStadHandles.hReport, &pInitTable->tReport);
    885     context_SetDefaults (pDrvMain->tStadHandles.hContext, &pInitTable->tContextInitParams);
    886     TWD_SetDefaults (pDrvMain->tStadHandles.hTWD, &pInitTable->twdInitParams);
    887     conn_SetDefaults (pDrvMain->tStadHandles.hConn, &pInitTable->connInitParams);
    888     ctrlData_SetDefaults (pDrvMain->tStadHandles.hCtrlData, &pInitTable->ctrlDataInitParams);
    889     regulatoryDomain_SetDefaults (pDrvMain->tStadHandles.hRegulatoryDomain, &pInitTable->regulatoryDomainInitParams);
    890     scanCncn_SetDefaults (pDrvMain->tStadHandles.hScanCncn, &pInitTable->tScanCncnInitParams);
    891     auth_SetDefaults (pDrvMain->tStadHandles.hAuth, &pInitTable->authInitParams);
    892     assoc_SetDefaults (pDrvMain->tStadHandles.hAssoc, &pInitTable->assocInitParams);
    893     rxData_SetDefaults (pDrvMain->tStadHandles.hRxData, &pInitTable->rxDataInitParams);
    894     sme_SetDefaults (pDrvMain->tStadHandles.hSme, &pInitTable->tSmeModifiedInitParams, &pInitTable->tSmeInitParams);
    895     rsn_SetDefaults (pDrvMain->tStadHandles.hRsn, &pInitTable->rsnInitParams);
    896     measurementMgr_SetDefaults (pDrvMain->tStadHandles.hMeasurementMgr, &pInitTable->measurementInitParams);
    897 #ifdef XCC_MODULE_INCLUDED
    898     XCCMngr_SetDefaults (pDrvMain->tStadHandles.hXCCMngr, &pInitTable->XCCMngrParams);
    899 #endif /*XCC_MODULE_INCLUDED*/
    900     apConn_SetDefaults (pDrvMain->tStadHandles.hAPConnection, &pInitTable->apConnParams);
    901     qosMngr_SetDefaults (pDrvMain->tStadHandles.hQosMngr, &pInitTable->qosMngrInitParams);
    902     switchChannel_SetDefaults (pDrvMain->tStadHandles.hSwitchChannel, &pInitTable->SwitchChannelInitParams);
    903     healthMonitor_SetDefaults (pDrvMain->tStadHandles.hHealthMonitor, &pInitTable->healthMonitorInitParams);
    904     PowerMgr_SetDefaults (pDrvMain->tStadHandles.hPowerMgr, &pInitTable->PowerMgrInitParams);
    905     SoftGemini_SetDefaults (pDrvMain->tStadHandles.hSoftGemini, &pInitTable->SoftGeminiInitParams);
    906     txDataQ_SetDefaults (pDrvMain->tStadHandles.hTxDataQ, &pInitTable->txDataInitParams);
    907     txCtrl_SetDefaults (pDrvMain->tStadHandles.hTxCtrl, &pInitTable->txDataInitParams);
    908     currBSS_SetDefaults (pDrvMain->tStadHandles.hCurrBss, &pInitTable->tCurrBssInitParams);
    909     mlme_SetDefaults (pDrvMain->tStadHandles.hMlmeSm, &pInitTable->tMlmeInitParams);
    910 
    911     scanMngr_SetDefaults(pDrvMain->tStadHandles.hScanMngr, &pInitTable->tRoamScanMngrInitParams);
    912     roamingMngr_setDefaults(pDrvMain->tStadHandles.hRoamingMngr, &pInitTable->tRoamScanMngrInitParams);
    913 
    914     /* Note: The siteMgr_SetDefaults includes many settings that relate to other modules so keep it last!! */
    915     siteMgr_SetDefaults (pDrvMain->tStadHandles.hSiteMgr, &pInitTable->siteMgrInitParams);
    916 
    917     /* Set DrvMain local defaults */
    918     pDrvMain->tBusDrvCfg.tSdioCfg.uBlkSizeShift         = pInitTable->tDrvMainParams.uSdioBlkSizeShift;
    919     pDrvMain->tBusDrvCfg.tSdioCfg.uBusDrvThreadPriority = pInitTable->tDrvMainParams.uBusDrvThreadPriority;
    920     os_SetDrvThreadPriority (pDrvMain->tStadHandles.hOs, pInitTable->tDrvMainParams.uWlanDrvThreadPriority);
    921 
    922     /* Release the init table memory */
    923     os_memoryFree (pDrvMain->tStadHandles.hOs, pInitTable, sizeof(TInitTable));
    924 
    925     return eStatus;
    926 }
    927 
    928 
    929 /*
    930  * \fn     drvMain_xxx...Cb
    931  * \brief  Callback functions for the init/stop stages completion
    932  *
    933  * The following callback functions are called from other modules (most from TWD)
    934  *     when the current init/stop step is completed.
    935  * Note that the callbacks are called anyway, either in the original context (if completed), or
    936  *     in another context if pending.
    937  * The first case (same context) may lead to a recursion of the SM, so a special handling is added
    938  *     to the SM to prevent recursion (see drvMain_Sm).
    939  *
    940  * drvMain_InitHwCb   - HW init completion callback
    941  * drvMain_InitFwCb   - FW init (mainly download) completion callback
    942  * drvMain_ConfigFwCb - FW configuration completion callback
    943  * drvMain_TwdStopCb  - TWD stopping completion callback
    944  * drvMain_InitFailCb - FW init faulty completion callback
    945  * drvMain_SmeStopCb  - SME stopping completion callback
    946  * drvMain_GetFileCb  - Getting-file completion callback
    947  *
    948  * \note
    949  * \param  hDrvMain - The DrvMain object
    950  * \param  eStatus  - The process result (TI_OK if succeeded, TI_NOK if failed)
    951  * \return void
    952  * \sa     drvMain_Create
    953  */
    954 static void drvMain_InitHwCb (TI_HANDLE hDrvMain, TI_STATUS eStatus)
    955 {
    956     HANDLE_CALLBACKS_FAILURE_STATUS(hDrvMain, eStatus);
    957     drvMain_SmEvent (hDrvMain, SM_EVENT_HW_INIT_COMPLETE);
    958 }
    959 
    960 static void drvMain_InitFwCb (TI_HANDLE hDrvMain, TI_STATUS eStatus)
    961 {
    962     HANDLE_CALLBACKS_FAILURE_STATUS(hDrvMain, eStatus);
    963     drvMain_SmEvent (hDrvMain, SM_EVENT_FW_INIT_COMPLETE);
    964 }
    965 
    966 static void drvMain_ConfigFwCb (TI_HANDLE hDrvMain, TI_STATUS eStatus)
    967 {
    968     HANDLE_CALLBACKS_FAILURE_STATUS(hDrvMain, eStatus);
    969     drvMain_SmEvent (hDrvMain, SM_EVENT_FW_CONFIG_COMPLETE);
    970 }
    971 
    972 static void drvMain_TwdStopCb (TI_HANDLE hDrvMain, TI_STATUS eStatus)
    973 {
    974     HANDLE_CALLBACKS_FAILURE_STATUS(hDrvMain, eStatus);
    975     drvMain_SmEvent (hDrvMain, SM_EVENT_STOP_COMPLETE);
    976 }
    977 
    978 static void drvMain_InitFailCb (TI_HANDLE hDrvMain, TI_STATUS eStatus)
    979 {
    980     drvMain_SmEvent (hDrvMain, SM_EVENT_FAILURE);
    981     /*
    982      * Note that this call will pass the SM to the FAILED state, since this event
    983      *     is not handled by any state.
    984      */
    985 }
    986 
    987 static void drvMain_InvokeAction (TI_HANDLE hDrvMain)
    988 {
    989     TDrvMain *pDrvMain = (TDrvMain *)hDrvMain;
    990 
    991     switch (pDrvMain->eAction)
    992     {
    993     case ACTION_TYPE_START:
    994         drvMain_SmEvent (hDrvMain, SM_EVENT_START);
    995         break;
    996     case ACTION_TYPE_STOP:
    997         drvMain_SmEvent (hDrvMain, SM_EVENT_STOP);
    998         break;
    999         default:
   1000             TRACE1(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_ERROR , "drvMain_InvokeAction(): Action=%d\n", pDrvMain->eAction);
   1001     }
   1002 }
   1003 
   1004 static void drvMain_GetFileCb (TI_HANDLE hDrvMain)
   1005 {
   1006     TDrvMain *pDrvMain = (TDrvMain *)hDrvMain;
   1007     ESmEvent  eSmEvent;
   1008 
   1009     switch (pDrvMain->tFileInfo.eFileType)
   1010     {
   1011         case FILE_TYPE_INI:     eSmEvent = SM_EVENT_INI_FILE_READY;    break;
   1012         case FILE_TYPE_NVS:     eSmEvent = SM_EVENT_NVS_FILE_READY;    break;
   1013         case FILE_TYPE_FW:      eSmEvent = SM_EVENT_FW_FILE_READY;     break;
   1014         case FILE_TYPE_FW_NEXT: eSmEvent = SM_EVENT_FW_FILE_READY;     break;
   1015         default:
   1016             TRACE1(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_ERROR , "drvMain_GetFileCb(): Unknown eFileType=%d\n", pDrvMain->tFileInfo.eFileType);
   1017             return;
   1018     }
   1019     drvMain_SmEvent (hDrvMain, eSmEvent);
   1020 }
   1021 
   1022 
   1023 /*
   1024  * \fn     drvMain_InitLocals
   1025  * \brief  Init DrvMain module
   1026  *
   1027  * Init the DrvMain variables, register to other modules and set device power to off.
   1028  *
   1029  * \note
   1030  * \param  pDrvMain - The DrvMain object
   1031  * \return void
   1032  * \sa     drvMain_Init
   1033  */
   1034 static void drvMain_InitLocals (TDrvMain *pDrvMain)
   1035 {
   1036     /* Initialize the module's local varniables to default values */
   1037     pDrvMain->tFileInfo.eFileType   = FILE_TYPE_INI;
   1038     pDrvMain->tFileInfo.fCbFunc     = drvMain_GetFileCb;
   1039     pDrvMain->tFileInfo.hCbHndl     = (TI_HANDLE)pDrvMain;
   1040     pDrvMain->eSmState              = SM_STATE_IDLE;
   1041     pDrvMain->uPendingEventsCount   = 0;
   1042 	pDrvMain->bRecovery             = TI_FALSE;
   1043 	pDrvMain->uNumOfRecoveryAttempts = 0;
   1044 	pDrvMain->eAction               = ACTION_TYPE_NONE;
   1045 
   1046     /* Register the Action callback to the context engine and get the client ID */
   1047     pDrvMain->uContextId = context_RegisterClient (pDrvMain->tStadHandles.hContext,
   1048                                                    drvMain_InvokeAction,
   1049                                                    (TI_HANDLE)pDrvMain,
   1050                                                    TI_TRUE,
   1051                                                    "ACTION",
   1052                                                    sizeof("ACTION"));
   1053 
   1054     /* Platform specific HW preparations */
   1055 	hPlatform_Wlan_Hardware_Init(pDrvMain->tStadHandles.hOs);
   1056 
   1057     /* Insure that device power is off (expected to be) */
   1058     hPlatform_DevicePowerOff ();
   1059 }
   1060 
   1061 
   1062 /*
   1063  * \fn     drvMain_InitHw & drvMain_InitFw
   1064  * \brief  Init HW and Init FW sequences
   1065  *
   1066  * drvMain_InitHw - HW init sequence which writes and reads some HW registers
   1067  *                      that are needed prior to FW download.
   1068  * drvMain_InitFw - FW init sequence which downloads the FW image and waits for
   1069  *                      FW init-complete indication.
   1070  *
   1071  * \note
   1072  * \param  hDrvMain - The DrvMain object
   1073  * \param  pBuf     - The file data (NVS for HW-init, FW-Image for FW-init).
   1074  * \param  uLength  - The file length.
   1075  * \return TI_OK if succeeded, TI_NOK if failed.
   1076  * \sa
   1077  */
   1078 static TI_STATUS drvMain_InitHw (TI_HANDLE hDrvMain, TI_UINT8 *pbuf, TI_UINT32 uLength)
   1079 {
   1080     TDrvMain   *pDrvMain = (TDrvMain *) hDrvMain;
   1081 
   1082     return TWD_InitHw (pDrvMain->tStadHandles.hTWD, pbuf, uLength, pDrvMain->uRxDmaBufLen, pDrvMain->uTxDmaBufLen);
   1083 }
   1084 
   1085 static TI_STATUS drvMain_InitFw (TI_HANDLE hDrvMain, TFileInfo *pFileInfo)
   1086 {
   1087     TDrvMain   *pDrvMain = (TDrvMain *) hDrvMain;
   1088 
   1089     return TWD_InitFw (pDrvMain->tStadHandles.hTWD, pFileInfo);
   1090 }
   1091 
   1092 
   1093 /*
   1094  * \fn     drvMain_ConfigFw
   1095  * \brief  Configure the FW
   1096  *
   1097  * The step that follows the FW Init (mainly FW download).
   1098  * The Command-Mailbox interface is enabled here and the FW is configured.
   1099  *
   1100  * \note
   1101  * \param  pDrvMain - The DrvMain object
   1102  * \return TI_OK
   1103  * \sa     drvMain_Init
   1104  */
   1105 static TI_STATUS drvMain_ConfigFw (TI_HANDLE hDrvMain)
   1106 {
   1107     TDrvMain    *pDrvMain = (TDrvMain *) hDrvMain;
   1108 
   1109     /* get pointer to FW static info (already in driver memory) */
   1110     TFwInfo     *pFwInfo  = TWD_GetFWInfo (pDrvMain->tStadHandles.hTWD);
   1111     TI_UINT8    *pMacAddr = (TI_UINT8 *)pFwInfo->macAddress; /* STA MAC address */
   1112 
   1113     /* Update driver's MAC address */
   1114     wlanDrvIf_SetMacAddress (pDrvMain->tStadHandles.hOs, pMacAddr);
   1115 
   1116     /*
   1117      *  Exit from init mode should be before smeSM starts. this enable us to send
   1118      *  command to the MboxQueue(that store the command) while the interrupts are masked.
   1119      *  the interrupt would be enable at the end of the init process.
   1120      */
   1121     TWD_ExitFromInitMode (pDrvMain->tStadHandles.hTWD);
   1122 
   1123     /* Configure the FW from the TWD DB */
   1124     TWD_ConfigFw (pDrvMain->tStadHandles.hTWD);
   1125 
   1126     TRACE0(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_INIT , "EXIT FROM INIT\n");
   1127 
   1128     /* Print the driver and firmware version and the mac address */
   1129     os_printf("\n");
   1130     os_printf("-----------------------------------------------------\n");
   1131     os_printf("Driver Version  : %s\n", SW_VERSION_STR);
   1132     os_printf("Firmware Version: %s\n", pFwInfo->fwVer);
   1133     os_printf("Station ID      : %02X-%02X-%02X-%02X-%02X-%02X\n",
   1134               pMacAddr[0], pMacAddr[1], pMacAddr[2], pMacAddr[3], pMacAddr[4], pMacAddr[5]);
   1135     os_printf("-----------------------------------------------------\n");
   1136     os_printf("\n");
   1137 
   1138     return TI_OK;
   1139 }
   1140 
   1141 
   1142 /*
   1143  * \fn     drvMain_StopActivities
   1144  * \brief  Freeze driver activities
   1145  *
   1146  * Freeze all driver activities due to stop command or recovery process.
   1147  *
   1148  * \note
   1149  * \param  pDrvMain - The DrvMain object
   1150  * \return TI_OK if succeeded, TI_NOK if failed.
   1151  * \sa     drvMain_EnableActivities
   1152  */
   1153 static TI_STATUS drvMain_StopActivities (TDrvMain *pDrvMain)
   1154 {
   1155     txPort_suspendTx (pDrvMain->tStadHandles.hTxPort);
   1156 
   1157     /* Disable External Inputs (IRQs and commands) */
   1158     TWD_DisableInterrupts(pDrvMain->tStadHandles.hTWD);
   1159     cmdHndlr_Disable (pDrvMain->tStadHandles.hCmdHndlr);
   1160 
   1161     /* Initiate TWD Restart */
   1162     return TWD_Stop (pDrvMain->tStadHandles.hTWD);
   1163 }
   1164 
   1165 
   1166 /*
   1167  * \fn     drvMain_EnableActivities
   1168  * \brief  Enable driver activities
   1169  *
   1170  * Enable driver activities after init or recovery process completion.
   1171  *
   1172  * \note
   1173  * \param  pDrvMain - The DrvMain object
   1174  * \return void
   1175  * \sa     drvMain_StopActivities
   1176  */
   1177 static void drvMain_EnableActivities (TDrvMain *pDrvMain)
   1178 {
   1179     txPort_resumeTx (pDrvMain->tStadHandles.hTxPort);
   1180 
   1181    /* Enable External Inputs (IRQ is enabled elsewhere) */
   1182     cmdHndlr_Enable (pDrvMain->tStadHandles.hCmdHndlr);
   1183 
   1184     /* Enable external events from FW */
   1185     TWD_EnableExternalEvents (pDrvMain->tStadHandles.hTWD);
   1186 
   1187 
   1188 }
   1189 
   1190 
   1191 /*
   1192  * \fn     drvMain_ClearQueuedEvents
   1193  * \brief  Enable driver activities
   1194  *
   1195  * Clear all external events queues (Tx, commands and timers) upon driver stop.
   1196  *
   1197  * \note
   1198  * \param  pDrvMain - The DrvMain object
   1199  * \return void
   1200  * \sa
   1201  */
   1202 static void drvMain_ClearQueuedEvents (TDrvMain *pDrvMain)
   1203 {
   1204     txDataQ_ClearQueues (pDrvMain->tStadHandles.hTxDataQ);
   1205     txMgmtQ_ClearQueues (pDrvMain->tStadHandles.hTxMgmtQ);
   1206     cmdHndlr_ClearQueue (pDrvMain->tStadHandles.hCmdHndlr);
   1207     tmr_ClearOperQueue (pDrvMain->tStadHandles.hTimer);
   1208 }
   1209 
   1210 
   1211 /*
   1212  * \fn     drvMain_InsertAction
   1213  * \brief  Get start/stop action and trigger handling
   1214  *
   1215  * Get start or stop action command from OAL, save it and trigger driver task
   1216  *     for handling it.
   1217  * Wait on a signal object until the requested process is completed.
   1218  *
   1219  * \note
   1220  * \param  hDrvMain - The DrvMain object
   1221  * \param  eAction  - The requested action
   1222  * \return void
   1223  * \sa
   1224  */
   1225 TI_STATUS drvMain_InsertAction (TI_HANDLE hDrvMain, EActionType eAction)
   1226 {
   1227     TDrvMain *pDrvMain = (TDrvMain *) hDrvMain;
   1228 
   1229     context_EnterCriticalSection(pDrvMain->tStadHandles.hContext);
   1230     if (pDrvMain->eAction == eAction)
   1231     {
   1232         context_LeaveCriticalSection(pDrvMain->tStadHandles.hContext);
   1233         TRACE0(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_CONSOLE, "Action is identical to last action!\n");
   1234         WLAN_OS_REPORT(("Action %d is identical to last action!\n", eAction));
   1235         return TI_OK;
   1236     }
   1237 
   1238     /* Save the requested action */
   1239     pDrvMain->eAction = eAction;
   1240     context_LeaveCriticalSection(pDrvMain->tStadHandles.hContext);
   1241 
   1242     /* Create signal object */
   1243     /*
   1244      * Notice that we must create the signal object before asking for ReSchedule,
   1245      * because we might receive it immidiatly, and then we will be in a different context
   1246      * with null signal object.
   1247      */
   1248     pDrvMain->hSignalObj = os_SignalObjectCreate (pDrvMain->tStadHandles.hOs);
   1249     if (pDrvMain->hSignalObj == NULL)
   1250     {
   1251         TRACE0(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_ERROR , "drvMain_InsertAction(): Couldn't allocate signal object!\n");
   1252         return TI_NOK;
   1253     }
   1254 
   1255     /* Request driver task schedule for action handling */
   1256     context_RequestSchedule (pDrvMain->tStadHandles.hContext, pDrvMain->uContextId);
   1257 
   1258     /* Wait for the action processing completion */
   1259     os_SignalObjectWait (pDrvMain->tStadHandles.hOs, pDrvMain->hSignalObj);
   1260 
   1261     /* After "wait" - the action has already been processed in the driver's context */
   1262 
   1263     /* Free signalling object */
   1264     os_SignalObjectFree (pDrvMain->tStadHandles.hOs, pDrvMain->hSignalObj);
   1265     pDrvMain->hSignalObj = NULL;
   1266 
   1267     if (pDrvMain->eSmState == SM_STATE_FAILED)
   1268     return TI_NOK;
   1269 
   1270     return TI_OK;
   1271 }
   1272 
   1273 
   1274 /*
   1275  * \fn     drvMain_Recovery
   1276  * \brief  Initiate recovery process
   1277  *
   1278  * Initiate recovery process upon HW/FW error detection (in the Health-Monitor).
   1279  *
   1280  * \note
   1281  * \param  hDrvMain - The DrvMain object
   1282  * \return TI_OK if started recovery, TI_NOK if recovery is already in progress.
   1283  * \sa
   1284  */
   1285 TI_STATUS drvMain_Recovery (TI_HANDLE hDrvMain)
   1286 {
   1287     TDrvMain         *pDrvMain = (TDrvMain *) hDrvMain;
   1288 
   1289     if (!pDrvMain->bRecovery)
   1290     {
   1291         TRACE1(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_CONSOLE,".....drvMain_Recovery, ts=%d\n", os_timeStampMs(pDrvMain->tStadHandles.hOs));
   1292 #ifdef REPORT_LOG
   1293         WLAN_OS_REPORT((".....drvMain_Recovery, ts=%d\n", os_timeStampMs(pDrvMain->tStadHandles.hOs)));
   1294 #else
   1295         printk("%s\n",__func__);
   1296 #endif
   1297         pDrvMain->bRecovery = TI_TRUE;
   1298         drvMain_SmEvent (hDrvMain, SM_EVENT_RECOVERY);
   1299         return TI_OK;
   1300     }
   1301     else
   1302     {
   1303         TRACE0(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_ERROR, "drvMain_Recovery: ****  Recovery already in progress!  ****\n");
   1304 
   1305 		/* nesting recoveries... Try again */
   1306 		drvMain_SmEvent (hDrvMain, SM_EVENT_RECOVERY);
   1307         return TI_NOK;
   1308     }
   1309 }
   1310 
   1311 
   1312 /*
   1313  * \fn     drvMain_RecoveryNotify
   1314  * \brief  Notify STAD modules about recovery
   1315  *
   1316  * Notify the relevant STAD modules that recovery took place (after completed).
   1317  *
   1318  * \note
   1319  * \param  pDrvMain - The DrvMain object
   1320  * \return void
   1321  * \sa
   1322  */
   1323 static void drvMain_RecoveryNotify (TDrvMain *pDrvMain)
   1324 {
   1325     txCtrl_NotifyFwReset (pDrvMain->tStadHandles.hTxCtrl);
   1326     scr_notifyFWReset (pDrvMain->tStadHandles.hSCR);
   1327     PowerMgr_notifyFWReset (pDrvMain->tStadHandles.hPowerMgr);
   1328 
   1329     TRACE1(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_CONSOLE, ".....drvMain_RecoveryNotify: End Of Recovery, ts=%d\n", os_timeStampMs(pDrvMain->tStadHandles.hOs));
   1330     WLAN_OS_REPORT((".....drvMain_RecoveryNotify: End Of Recovery, ts=%d\n", os_timeStampMs(pDrvMain->tStadHandles.hOs)));
   1331 }
   1332 
   1333 
   1334 /*
   1335  * \fn     drvMain_SmWatchdogTimeout
   1336  * \brief  SM watchdog timer expiry handler
   1337  *
   1338  * This is the callback function called upon expiartion of the watchdog timer.
   1339  * It is called by the OS-API in timer expiry context, and it issues a failure event to the SM.
   1340  * Note that we can't switch to the driver task as for other timers, since we are using
   1341  *     this timer to protect the init processes, and anyway we just need to stop the driver.
   1342  *
   1343  * \note
   1344  * \param  hDrvMain - The DrvMain object
   1345  * \return void
   1346  * \sa
   1347  */
   1348 
   1349 #if 0
   1350 static void drvMain_SmWatchdogTimeout (TI_HANDLE hDrvMain)
   1351 {
   1352     TDrvMain *pDrvMain = (TDrvMain *)hDrvMain;
   1353 
   1354     TRACE1(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_ERROR , "drvMain_SmWatchdogTimeout():  State = %d\n", pDrvMain->eSmState);
   1355 
   1356     /* Send failure event directly to the SM (so the drvMain_SmEvent won't block it).  */
   1357 
   1358     drvMain_Sm ((TI_HANDLE)pDrvMain, SM_EVENT_FAILURE);
   1359 }
   1360 #endif
   1361 
   1362 /*
   1363  * \fn     drvMain_SmEvent
   1364  * \brief  Issue DrvMain SM event
   1365  *
   1366  * Each event that is handled by the DrvMain state machine, is introduced through this function.
   1367  * To prevent SM recursion, the SM is invoeked only if it's not already handling the
   1368  *      previous event.
   1369  * If the SM is busy, the current event is saved until the previous handling is completed.
   1370  *
   1371  * \note   Recursion may happen because some SM activities generate SM events in the same context.
   1372  * \param  hDrvMain - The DrvMain object
   1373  * \param  eEvent   - The event issued to the SM
   1374  * \return void
   1375  * \sa
   1376  */
   1377 static void drvMain_SmEvent (TI_HANDLE hDrvMain, ESmEvent eEvent)
   1378 {
   1379     TDrvMain *pDrvMain = (TDrvMain *)hDrvMain;
   1380 
   1381     /* Increment pending events counter and save last event. */
   1382     pDrvMain->uPendingEventsCount++;
   1383     pDrvMain->ePendingEvent = eEvent;
   1384 
   1385     /* If the SM is busy, save event and exit (will be handled when current event is finished) */
   1386     if (pDrvMain->uPendingEventsCount > 1)
   1387     {
   1388         /* Only one pending event is expected (in addition to the handled one, so two together). */
   1389         if (pDrvMain->uPendingEventsCount > 2)
   1390         {
   1391             TRACE3(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_ERROR , "drvMain_SmEvent():  Multiple pending events (%d), State = %d, Event = %d\n", pDrvMain->uPendingEventsCount, pDrvMain->eSmState, eEvent);
   1392         }
   1393 
   1394         /* Exit. The current event will be handled by the following while loop of the first instance. */
   1395         return;
   1396     }
   1397 
   1398     /* Invoke the SM with the current event and further events issued by the last SM invocation. */
   1399     while (pDrvMain->uPendingEventsCount > 0)
   1400     {
   1401         drvMain_Sm (hDrvMain, pDrvMain->ePendingEvent);
   1402 
   1403         /*
   1404          * Note: The SM may issue another event by calling this function and incrementing
   1405          *           the counter.
   1406          *       In this case, only the upper part of this function is run, and the pending
   1407          *           event is hanlded in the next while loo[.
   1408          */
   1409 
   1410         pDrvMain->uPendingEventsCount--;
   1411     }
   1412 }
   1413 
   1414 
   1415 /*
   1416  * \fn     drvMain_Sm
   1417  * \brief  The DrvMain state machine
   1418  *
   1419  * The DrvMain state machine, which handles all driver init, recovery and stop processes.
   1420  *
   1421  * \note   Since the SM may be called back from its own context, recursion is prevented
   1422  *             by postponing the last event.
   1423  * \param  hDrvMain - The DrvMain object
   1424  * \param  eEvent   - The event that triggers the SM
   1425  * \return void
   1426  * \sa
   1427  */
   1428 static void drvMain_Sm (TI_HANDLE hDrvMain, ESmEvent eEvent)
   1429 {
   1430     TDrvMain    *pDrvMain   = (TDrvMain *)hDrvMain;
   1431     TI_STATUS    eStatus    = TI_NOK;
   1432     TI_HANDLE    hOs        = pDrvMain->tStadHandles.hOs;
   1433     TI_UINT32    uSdioConIndex = 0;
   1434     TI_BOOL      tmpRecovery;
   1435 
   1436     TRACE2(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_INFORMATION , "drvMain_Sm():  State = %d, Event = %d\n", pDrvMain->eSmState, eEvent);
   1437 
   1438     /*
   1439      *  General explenations:
   1440      *  =====================
   1441      *  1) This SM calls some functions that may complete their processing in another context.
   1442      *     All of these functions (wlanDrvIf_GetFile, drvMain_InitHw, drvMain_InitFw, drvMain_ConfigFw,
   1443      *         drvMain_StopActivities, smeSm_start, smeSm_stop) are provided with a callback which
   1444      *         they always call upon completion, even if they are completed in the original (SM) context.
   1445      *     Since these callbacks are calling the SM, a simple mechanism is added to prevent
   1446      *         recursion, by postponing the last event if the SM is still in the previous event's context.
   1447      *  2) In any case of unexpected event, the eStatus remains TI_NOK, leading to the FAILED state!
   1448      *     FAILED state is also reached if any of the functions listed in note 1 returns TI_NOK.
   1449      *     Note that if these functions detect a failure in another context, they may call their callback
   1450      *         with the eStatus parameter set to TI_NOK, or call the drvMain_InitFailCb callback.
   1451      *     All these cases lead to FAILED state which terminates all driver activities and wait for destroy.
   1452      *  3) Note that the wlanDrvIf_GetFile is always completed in the original context, and the
   1453      *         option of completion in a later context is only for future use.
   1454      *  4) All processes (Start, Stop, Relcovery) are protected by a watchdog timer to let
   1455      *         the user free the driver in case of deadlock during the process.
   1456      */
   1457 
   1458     switch (pDrvMain->eSmState)
   1459     {
   1460     case SM_STATE_IDLE:
   1461         /*
   1462          * We get a START action after all modules are created and linked.
   1463          * Disable further actions, start watchdog timer and request for the ini-file.
   1464          */
   1465         if (eEvent == SM_EVENT_START)
   1466         {
   1467             pDrvMain->eSmState = SM_STATE_WAIT_INI_FILE;
   1468             context_DisableClient (pDrvMain->tStadHandles.hContext, pDrvMain->uContextId);
   1469             pDrvMain->tFileInfo.eFileType = FILE_TYPE_INI;
   1470             eStatus = wlanDrvIf_GetFile (hOs, &pDrvMain->tFileInfo);
   1471         }
   1472         break;
   1473     case SM_STATE_WAIT_INI_FILE:
   1474         /*
   1475          * We've got the ini-file.
   1476          * Set STAD and TWD modules defaults according to the ini-file,
   1477          *     turn on the device and request for the NVS file.
   1478          */
   1479         if (eEvent == SM_EVENT_INI_FILE_READY)
   1480         {
   1481             pDrvMain->eSmState = SM_STATE_WAIT_NVS_FILE;
   1482             drvMain_SetDefaults (hDrvMain, pDrvMain->tFileInfo.pBuffer, pDrvMain->tFileInfo.uLength);
   1483             hPlatform_DevicePowerOn ();
   1484 
   1485             pDrvMain->tFileInfo.eFileType = FILE_TYPE_NVS;
   1486             eStatus = wlanDrvIf_GetFile (hOs, &pDrvMain->tFileInfo);
   1487         }
   1488         break;
   1489 
   1490     case SM_STATE_WAIT_NVS_FILE:
   1491 
   1492         /* SDBus Connect connection validation  */
   1493         for(uSdioConIndex=0; (uSdioConIndex < SDIO_CONNECT_THRESHOLD) && (eStatus != TI_OK); uSdioConIndex++)
   1494         {
   1495 			/* : We should split the call to txnQ_ConnectBus to other state in order to support Async bus connection */
   1496             eStatus = txnQ_ConnectBus(pDrvMain->tStadHandles.hTxnQ, &pDrvMain->tBusDrvCfg, NULL, NULL, &pDrvMain->uRxDmaBufLen, &pDrvMain->uTxDmaBufLen);
   1497 
   1498             if((eStatus != TI_OK) &&
   1499 			   (uSdioConIndex < (SDIO_CONNECT_THRESHOLD - 1)))
   1500             {
   1501                      TRACE0(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_WARNING , "SDBus Connect Failed\n");
   1502                      WLAN_OS_REPORT(("Try to SDBus Connect again...\n"));
   1503                      if (uSdioConIndex > 1)
   1504 						hPlatform_DevicePowerOffSetLongerDelay();
   1505 					 else
   1506 						hPlatform_DevicePowerOff();
   1507                      hPlatform_DevicePowerOn();
   1508             }
   1509         }
   1510 
   1511         if(eStatus != TI_OK)
   1512         {
   1513 			WLAN_OS_REPORT(("SDBus Connect Failed, Set Object Event !!\r\n"));
   1514 			TRACE0(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_ERROR , "SDBus Connect Failed, Set Object Event !!\r\n");
   1515 			if (!pDrvMain->bRecovery)
   1516 			{
   1517 				os_SignalObjectSet(hOs, pDrvMain->hSignalObj);
   1518 			}
   1519         }
   1520         else /* SDBus Connect success */
   1521         {
   1522             /*
   1523              * We've got the NVS file.
   1524              * Start HW-Init process providing the NVS file.
   1525              */
   1526             if (eEvent == SM_EVENT_NVS_FILE_READY)
   1527             {
   1528                 pDrvMain->eSmState = SM_STATE_HW_INIT;
   1529                 eStatus = drvMain_InitHw (hDrvMain, pDrvMain->tFileInfo.pBuffer, pDrvMain->tFileInfo.uLength);
   1530             }
   1531         }
   1532         break;
   1533     case SM_STATE_HW_INIT:
   1534         /*
   1535          * HW-Init process is completed.
   1536          * Request for the FW image file.
   1537          */
   1538         if (eEvent == SM_EVENT_HW_INIT_COMPLETE)
   1539         {
   1540             pDrvMain->tFileInfo.eFileType = FILE_TYPE_FW;
   1541             pDrvMain->eSmState = SM_STATE_DOWNLOAD_FW_FILE;
   1542             eStatus = wlanDrvIf_GetFile (hOs, &pDrvMain->tFileInfo);
   1543         }
   1544         break;
   1545     case SM_STATE_DOWNLOAD_FW_FILE:
   1546         if (eEvent == SM_EVENT_FW_FILE_READY)
   1547         {
   1548             pDrvMain->tFileInfo.eFileType = FILE_TYPE_FW_NEXT;
   1549             if (pDrvMain->tFileInfo.bLast == TI_TRUE)
   1550             {
   1551             pDrvMain->eSmState = SM_STATE_FW_INIT;
   1552             }
   1553             else
   1554             {
   1555                 pDrvMain->eSmState = SM_STATE_WAIT_FW_FILE;
   1556             }
   1557             /*
   1558              * We've got the FW image file.
   1559              * Start FW-Init process (mainly FW image download) providing the FW image file.
   1560              */
   1561             eStatus = drvMain_InitFw (hDrvMain, &pDrvMain->tFileInfo);
   1562         }
   1563         break;
   1564     case SM_STATE_WAIT_FW_FILE:
   1565         if (eEvent == SM_EVENT_FW_INIT_COMPLETE)
   1566         {
   1567             pDrvMain->eSmState = SM_STATE_DOWNLOAD_FW_FILE;
   1568             eStatus = wlanDrvIf_GetFile (hOs, &pDrvMain->tFileInfo);
   1569         }
   1570         break;
   1571     case SM_STATE_FW_INIT:
   1572         /*
   1573          * FW-Init process is completed.
   1574          * Free the semaphore of the START action to enable the OS interface.
   1575          * Enable interrupts (or polling for debug).
   1576          * Start FW-Configuration process, and free the semaphore of the START action.
   1577          *
   1578          * Note that in some OSs, the semaphore must be released in order to enable the
   1579          *     interrupts, and the interrupts are needed for the configuration process!
   1580          */
   1581         if (eEvent == SM_EVENT_FW_INIT_COMPLETE)
   1582         {
   1583             pDrvMain->eSmState = SM_STATE_FW_CONFIG;
   1584             TWD_EnableInterrupts(pDrvMain->tStadHandles.hTWD);
   1585           #ifdef PRIODIC_INTERRUPT
   1586             /* Start periodic interrupts. It means that every period of time the FwEvent SM will be called */
   1587             os_periodicIntrTimerStart (hOs);
   1588           #endif
   1589             eStatus = drvMain_ConfigFw (hDrvMain);
   1590         }
   1591         break;
   1592     case SM_STATE_FW_CONFIG:
   1593         /*
   1594          * FW-configuration process is completed.
   1595          * Stop watchdog timer.
   1596          * For recovery, notify the relevant STAD modules.
   1597          * For regular start, start the SME which handles the connection process.
   1598          * Update timer and OAL about entering OPERATIONAL state (OAL ignores recovery)
   1599          * Enable driver activities and external events.
   1600          * Enable STOP action
   1601          * We are now in OPERATIONAL state, i.e. the driver is fully operational!
   1602          */
   1603 
   1604         tmpRecovery = pDrvMain->bRecovery;
   1605         if (eEvent == SM_EVENT_FW_CONFIG_COMPLETE)
   1606         {
   1607             pDrvMain->eSmState = SM_STATE_OPERATIONAL;
   1608             if (pDrvMain->bRecovery)
   1609             {
   1610                 pDrvMain->uNumOfRecoveryAttempts = 0;
   1611                 drvMain_RecoveryNotify (pDrvMain);
   1612                 pDrvMain->bRecovery = TI_FALSE;
   1613             }
   1614             else
   1615             {
   1616                 sme_Start (pDrvMain->tStadHandles.hSme);
   1617                 wlanDrvIf_UpdateDriverState (hOs, DRV_STATE_RUNNING);
   1618             }
   1619             tmr_UpdateDriverState (pDrvMain->tStadHandles.hTimer, TI_TRUE);
   1620             drvMain_EnableActivities (pDrvMain);
   1621             context_EnableClient (pDrvMain->tStadHandles.hContext, pDrvMain->uContextId);
   1622             eStatus = TI_OK;
   1623 
   1624         }
   1625         if (!tmpRecovery)
   1626         {
   1627             os_SignalObjectSet(hOs, pDrvMain->hSignalObj);
   1628         }
   1629         break;
   1630     case SM_STATE_OPERATIONAL:
   1631         /*
   1632          * Disable start/stop commands and start watchdog timer.
   1633          * Update timer and OAL about exiting OPERATIONAL state (OAL ignores recovery).
   1634          * For STOP, stop SME (handle disconnection) and move to DISCONNECTING state.
   1635          * For recovery, stop driver activities and move to STOPPING state.
   1636          * Note that driver-stop process may be Async if we are during Async bus transaction.
   1637          */
   1638 
   1639         context_DisableClient (pDrvMain->tStadHandles.hContext, pDrvMain->uContextId);
   1640         tmr_UpdateDriverState (pDrvMain->tStadHandles.hTimer, TI_FALSE);
   1641         if (eEvent == SM_EVENT_STOP)
   1642         {
   1643             pDrvMain->eSmState = SM_STATE_DISCONNECTING;
   1644             wlanDrvIf_UpdateDriverState (hOs, DRV_STATE_STOPING);
   1645             sme_Stop (pDrvMain->tStadHandles.hSme);
   1646             eStatus = TI_OK;
   1647         }
   1648         else if (eEvent == SM_EVENT_RECOVERY)
   1649         {
   1650             pDrvMain->eSmState = SM_STATE_STOPPING;
   1651             eStatus = drvMain_StopActivities (pDrvMain);
   1652         }
   1653 
   1654         break;
   1655     case SM_STATE_DISCONNECTING:
   1656         /*
   1657          * Note that this state is not relevant for recovery.
   1658          * SME stop is completed
   1659          * Stop driver activities and move to STOPPING state.
   1660          * Note that driver stop process may be Async if we are during Async bus transaction.
   1661          */
   1662 
   1663         if (eEvent == SM_EVENT_DISCONNECTED)
   1664         {
   1665             pDrvMain->eSmState = SM_STATE_STOPPING;
   1666             eStatus = drvMain_StopActivities (pDrvMain);
   1667         }
   1668         break;
   1669     case SM_STATE_STOPPING:
   1670         /*
   1671          * Driver stopping process is done.
   1672          * Turn device power off.
   1673          * For recovery, turn device power back on, request NVS file and continue with
   1674          *     the init process (recover back all the way to OPERATIONAL state).
   1675          * For STOP process, the driver is now fully stopped (STOPPED state), so stop watchdog timer,
   1676          *     clear all events queues, free the semaphore of the STOP action and enable START action.
   1677          */
   1678 
   1679         if (eEvent == SM_EVENT_STOP_COMPLETE)
   1680         {
   1681             txnQ_DisconnectBus (pDrvMain->tStadHandles.hTxnQ);
   1682             hPlatform_DevicePowerOff ();
   1683             if (pDrvMain->bRecovery)
   1684             {
   1685                 hPlatform_DevicePowerOn ();
   1686                 pDrvMain->eSmState = SM_STATE_WAIT_NVS_FILE;
   1687                 pDrvMain->tFileInfo.eFileType = FILE_TYPE_NVS;
   1688                 eStatus = wlanDrvIf_GetFile (hOs, &pDrvMain->tFileInfo);
   1689             }
   1690             else
   1691             {
   1692                 pDrvMain->eSmState = SM_STATE_STOPPED;
   1693                 drvMain_ClearQueuedEvents (pDrvMain);
   1694                 scr_notifyFWReset(pDrvMain->tStadHandles.hSCR);
   1695                 os_SignalObjectSet (hOs, pDrvMain->hSignalObj);
   1696                 context_EnableClient (pDrvMain->tStadHandles.hContext, pDrvMain->uContextId);
   1697                 wlanDrvIf_UpdateDriverState (hOs, DRV_STATE_STOPPED);
   1698                 eStatus = TI_OK;
   1699             }
   1700         }
   1701 
   1702         break;
   1703     case SM_STATE_STOPPED:
   1704         /*
   1705          * A START action command was inserted, so we go through the init process.
   1706          * Disable further actions, start watchdog timer, turn on device and request NVS file.
   1707          */
   1708 
   1709         context_DisableClient (pDrvMain->tStadHandles.hContext, pDrvMain->uContextId);
   1710         if (eEvent == SM_EVENT_START)
   1711         {
   1712             hPlatform_DevicePowerOn ();
   1713             pDrvMain->eSmState = SM_STATE_WAIT_NVS_FILE;
   1714             pDrvMain->tFileInfo.eFileType = FILE_TYPE_NVS;
   1715             eStatus = wlanDrvIf_GetFile (hOs, &pDrvMain->tFileInfo);
   1716         }
   1717         break;
   1718     case SM_STATE_STOPPING_ON_FAIL:
   1719         /*
   1720          * Driver stopping process upon failure is completed.
   1721          * Turn off the device and move to FAILED state.
   1722          */
   1723 
   1724         pDrvMain->eSmState = SM_STATE_FAILED;
   1725         txnQ_DisconnectBus (pDrvMain->tStadHandles.hTxnQ);
   1726         hPlatform_DevicePowerOff ();
   1727         if (!pDrvMain->bRecovery)
   1728         {
   1729             os_SignalObjectSet (hOs, pDrvMain->hSignalObj);
   1730         }
   1731         else if (pDrvMain->uNumOfRecoveryAttempts < MAX_NUM_OF_RECOVERY_TRIGGERS)
   1732         {
   1733             pDrvMain->uNumOfRecoveryAttempts++;
   1734             pDrvMain->eSmState = SM_STATE_STOPPING;
   1735             eStatus = drvMain_StopActivities (pDrvMain);
   1736         }
   1737         WLAN_OS_REPORT(("[WLAN] Exit application\n"));
   1738         pDrvMain->bRecovery = TI_FALSE;
   1739         break;
   1740     case SM_STATE_FAILED:
   1741         /* Nothing to do except waiting for Destroy */
   1742         break;
   1743     default:
   1744         TRACE2(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_ERROR , "drvMain_Sm: Unknown state, eEvent=%u at state=%u\n", eEvent, pDrvMain->eSmState);
   1745         /* Note: Handled below as a failure since the status remains TI_NOK */
   1746         break;
   1747     }
   1748 
   1749     /* Handle failures (status = NOK) if not handled yet */
   1750     if ((eStatus == TI_NOK) &&
   1751         (pDrvMain->eSmState != SM_STATE_FAILED) &&
   1752         (pDrvMain->eSmState != SM_STATE_STOPPING_ON_FAIL))
   1753     {
   1754         TRACE3(pDrvMain->tStadHandles.hReport, REPORT_SEVERITY_ERROR , "drvMain_Sm: eEvent=%u at state=%u, status=%d\n", eEvent, pDrvMain->eSmState, eStatus);
   1755         pDrvMain->eSmState = SM_STATE_STOPPING_ON_FAIL;
   1756         wlanDrvIf_UpdateDriverState (hOs, DRV_STATE_FAILED);
   1757 
   1758         /*
   1759          * Stop all activities. This may be completed in a different context if
   1760          *     we should wait for an Async bus transaction completion.
   1761          * The drvMain_TwdStopCb is called from the TWD in any case to pass
   1762          *     us to the SM_STATE_FAILED state (where we wait for Destroy).
   1763          */
   1764         eStatus = drvMain_StopActivities (pDrvMain);
   1765     }
   1766 }
   1767