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