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 */ 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 */ 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 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 */ 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 */ 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 */ 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 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 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 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 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 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 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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