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 */
93typedef 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 */
113typedef 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 */
131typedef 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
150static void drvMain_Init (TI_HANDLE hDrvMain);
151static void drvMain_InitHwCb (TI_HANDLE hDrvMain, TI_STATUS eStatus);
152static void drvMain_InitFwCb (TI_HANDLE hDrvMain, TI_STATUS eStatus);
153static void drvMain_ConfigFwCb (TI_HANDLE hDrvMain, TI_STATUS eStatus);
154static void drvMain_TwdStopCb (TI_HANDLE hDrvMain, TI_STATUS eStatus);
155static void drvMain_InitFailCb (TI_HANDLE hDrvMain, TI_STATUS eStatus);
156static void drvMain_InitLocals (TDrvMain *pDrvMain);
157/* static void drvMain_SmWatchdogTimeout (TI_HANDLE hDrvMain); */
158static void drvMain_SmEvent (TI_HANDLE hDrvMain, ESmEvent eEvent);
159static 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 */
176extern 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 */
188extern 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 */
200extern 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 */
214extern 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 */
238TI_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 */
563TI_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
769void 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 */
788static 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 */
870static 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 */
954static 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
960static 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
966static 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
972static 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
978static 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
987static 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
1004static 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 */
1034static 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 */
1078static 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
1085static 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 */
1105static 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 */
1153static 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 */
1177static 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 */
1202static 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 */
1225TI_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 */
1285TI_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 */
1323static 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
1350static 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 */
1377static 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 */
1428static 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