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