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