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