1 /* 2 * FwEvent.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 FwEvent.c 36 * \brief Handle firmware events 37 * 38 * 39 * \par Description 40 * Call the appropriate event handler. 41 * 42 * \see FwEvent.h 43 */ 44 45 #define __FILE_ID__ FILE_ID_104 46 #include "tidef.h" 47 #include "report.h" 48 #include "context.h" 49 #include "osApi.h" 50 #include "TWDriver.h" 51 #include "TWDriverInternal.h" 52 #include "txResult_api.h" 53 #include "CmdMBox_api.h" 54 #include "rxXfer_api.h" 55 #include "txXfer_api.h" 56 #include "txHwQueue_api.h" 57 #include "eventMbox_api.h" 58 #include "TwIf.h" 59 #include "public_host_int.h" 60 #include "FwEvent_api.h" 61 #ifdef TI_DBG 62 #include "tracebuf_api.h" 63 #endif 64 #include "bmtrace_api.h" 65 66 67 #ifdef _VLCT_ 68 extern int trigger_another_read; 69 #endif 70 71 72 #define FW_STATUS_ADDR (0x14FC0 + 0xA000) 73 74 #define ALL_EVENTS_VECTOR ACX_INTR_WATCHDOG | ACX_INTR_INIT_COMPLETE | ACX_INTR_EVENT_A |\ 75 ACX_INTR_EVENT_B | ACX_INTR_CMD_COMPLETE |ACX_INTR_HW_AVAILABLE |\ 76 ACX_INTR_DATA 77 78 #define ALL_EVENTS_VECTOR_NEGATE 0xFFFFFFC0 79 80 81 #define TXN_FW_EVENT_SET_MASK_ADDR(pFwEvent) pFwEvent->tMaskTxn.tTxnStruct.uHwAddr = HINT_MASK; 82 #define TXN_FW_EVENT_SET_UNMASK_ADDR(pFwEvent) pFwEvent->tUnMaskTxn.tTxnStruct.uHwAddr = HINT_MASK; 83 #define TXN_FW_EVENT_SET_FW_STAT_ADDR(pFwEvent) pFwEvent->tFwStatusTxn.tTxnStruct.uHwAddr = FW_STATUS_ADDR; 84 85 86 typedef enum 87 { 88 FW_EVENT_STATE_IDLE, 89 FW_EVENT_STATE_READING 90 91 } EFwEventState; 92 93 typedef struct 94 { 95 TTxnStruct tTxnStruct; 96 TI_UINT32 uData; 97 98 } TRegisterTxn; 99 100 typedef struct 101 { 102 TTxnStruct tTxnStruct; 103 FwStatus_t tFwStatus; 104 105 } TFwStatusTxn; 106 107 /* The FwEvent module's main structure */ 108 typedef struct 109 { 110 EFwEventState eFwEventState; /* State machine state */ 111 TI_UINT32 uEventMask; /* Static interrupt event mask */ 112 TI_UINT32 uEventVector; /* Saves the current active FW interrupts */ 113 TI_BOOL bIsActualFwInterrupt; /* Indicates that we are working on a real interrupt from the FW */ 114 TRegisterTxn tMaskTxn; 115 TRegisterTxn tUnMaskTxn; 116 TFwStatusTxn tFwStatusTxn; /* The FW status structure transaction (read from FW memory) */ 117 118 TI_UINT32 uFwTimeOffset; /* Offset in microseconds between driver and FW clocks */ 119 TI_BOOL bEmulateRxIntr; /* Indicate to call Rx interrupt handler even if not issued */ 120 121 /* Other modules handles */ 122 TI_HANDLE hOs; 123 TI_HANDLE hTWD; 124 TI_HANDLE hReport; 125 TI_HANDLE hContext; 126 TI_UINT32 uContextId; 127 TI_HANDLE hTwIf; 128 TI_HANDLE hHealthMonitor; 129 TI_HANDLE hEventMbox; 130 TI_HANDLE hCmdMbox; 131 TI_HANDLE hRxXfer; 132 TI_HANDLE hTxXfer; 133 TI_HANDLE hTxHwQueue; 134 TI_HANDLE hTxResult; 135 136 } TfwEvent; 137 138 139 static void fwEvent_CallHandler (TI_HANDLE hFwEvent); 140 static void fwEvent_Handle (TI_HANDLE hFwEvent); 141 static void fwEvent_ReadCompleteCb (TI_HANDLE hFwEvent); 142 143 144 145 146 /* 147 * \brief Create the FwEvent module object 148 * 149 * \param hOs - OS module object handle 150 * \return Handle to the created object 151 * 152 * \par Description 153 * Calling this function creates a FwEvent object 154 * 155 * \sa fwEvent_Destroy 156 */ 157 TI_HANDLE fwEvent_Create (TI_HANDLE hOs) 158 { 159 TfwEvent *pFwEvent; 160 161 pFwEvent = os_memoryAlloc (hOs, sizeof(TfwEvent)); 162 if (pFwEvent == NULL) 163 { 164 return NULL; 165 } 166 167 os_memoryZero (hOs, pFwEvent, sizeof(TfwEvent)); 168 169 pFwEvent->hOs = hOs; 170 171 return (TI_HANDLE)pFwEvent; 172 } 173 174 175 /* 176 * \brief Destroys the FwEvent object 177 * 178 * \param hFwEvent - The object to free 179 * \return TI_OK 180 * 181 * \par Description 182 * Calling this function destroys a FwEvent object 183 * 184 * \sa fwEvent_Create 185 */ 186 TI_STATUS fwEvent_Destroy (TI_HANDLE hFwEvent) 187 { 188 TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; 189 190 if (pFwEvent) 191 { 192 os_memoryFree (pFwEvent->hOs, pFwEvent, sizeof(TfwEvent)); 193 } 194 195 return TI_OK; 196 } 197 198 199 /* 200 * \brief Config the FwEvent module object 201 * 202 * \param hFwEvent - FwEvent Driver handle 203 * \param hTWD - Handle to TWD module 204 * \return TI_OK 205 * 206 * \par Description 207 * From hTWD we extract : hOs, hReport, hTwIf, hContext, 208 * hHealthMonitor, hEventMbox, hCmdMbox, hRxXfer, 209 * hTxHwQueue, hTxResult 210 * In this function we also register the FwEvent to the context engine 211 * 212 * \sa 213 */ 214 TI_STATUS fwEvent_Init (TI_HANDLE hFwEvent, TI_HANDLE hTWD) 215 { 216 TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; 217 TTwd *pTWD = (TTwd *)hTWD; 218 TTxnStruct* pTxn; 219 220 pFwEvent->hTWD = hTWD; 221 pFwEvent->hOs = pTWD->hOs; 222 pFwEvent->hReport = pTWD->hReport; 223 pFwEvent->hContext = pTWD->hContext; 224 pFwEvent->hTwIf = pTWD->hTwIf; 225 pFwEvent->hHealthMonitor = pTWD->hHealthMonitor; 226 pFwEvent->hEventMbox = pTWD->hEventMbox; 227 pFwEvent->hCmdMbox = pTWD->hCmdMbox; 228 pFwEvent->hRxXfer = pTWD->hRxXfer; 229 pFwEvent->hTxHwQueue = pTWD->hTxHwQueue; 230 pFwEvent->hTxXfer = pTWD->hTxXfer; 231 pFwEvent->hTxResult = pTWD->hTxResult; 232 233 pFwEvent->eFwEventState = FW_EVENT_STATE_IDLE; 234 pFwEvent->uEventMask = 0; 235 pFwEvent->uEventVector = 0; 236 pFwEvent->bIsActualFwInterrupt = TI_FALSE; 237 pFwEvent->bEmulateRxIntr = TI_FALSE; 238 239 pTxn = (TTxnStruct*)&pFwEvent->tMaskTxn.tTxnStruct; 240 TXN_PARAM_SET(pTxn, TXN_HIGH_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) 241 BUILD_TTxnStruct(pTxn, HINT_MASK, &pFwEvent->tMaskTxn.uData, REGISTER_SIZE, NULL, NULL) 242 243 pTxn = (TTxnStruct*)&pFwEvent->tUnMaskTxn.tTxnStruct; 244 TXN_PARAM_SET(pTxn, TXN_HIGH_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) 245 BUILD_TTxnStruct(pTxn, HINT_MASK, &pFwEvent->tUnMaskTxn.uData, REGISTER_SIZE, NULL, NULL) 246 247 248 pTxn = (TTxnStruct*)&pFwEvent->tFwStatusTxn.tTxnStruct; 249 TXN_PARAM_SET(pTxn, TXN_HIGH_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR) 250 BUILD_TTxnStruct(pTxn, FW_STATUS_ADDR, &pFwEvent->tFwStatusTxn.tFwStatus, sizeof(FwStatus_t), (TTxnDoneCb)fwEvent_ReadCompleteCb, hFwEvent) 251 252 /* 253 * Register the FwEvent to the context engine and get the client ID. 254 * The FwEvent() will be called from the context_DriverTask() after scheduled 255 * by a FW-Interrupt (see fwEvent_InterruptRequest()). 256 */ 257 pFwEvent->uContextId = context_RegisterClient (pFwEvent->hContext, 258 fwEvent_Handle, 259 hFwEvent, 260 TI_FALSE, 261 "FW_EVENT", 262 sizeof("FW_EVENT")); 263 264 return TI_OK; 265 } 266 267 268 /* 269 * \brief Call FwEvent client's event handler 270 * 271 * \param hFwEvent - FwEvent Driver handle 272 * \return void 273 * 274 * \par Description 275 * 276 * \sa fwEvent_ReadCompleteCb 277 */ 278 static void fwEvent_CallHandler (TI_HANDLE hFwEvent) 279 { 280 TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; 281 282 if (pFwEvent->uEventVector & ACX_INTR_WATCHDOG) 283 { 284 /* Fw watchdog timeout has occured */ 285 TWD_WdExpireEvent (pFwEvent->hTWD); 286 } 287 288 if (pFwEvent->uEventVector & ACX_INTR_INIT_COMPLETE) 289 { 290 TRACE0(pFwEvent->hReport, REPORT_SEVERITY_INFORMATION, "fwEvent_CallHandler: INIT_COMPLETE\n"); 291 } 292 /* Change to handle the command MBOX before the event MBOX to maintain order for WHA command response 293 * and follow command complete 294 */ 295 if (pFwEvent->uEventVector & ACX_INTR_CMD_COMPLETE) 296 { 297 /* Command Mbox completed */ 298 cmdMbox_CommandComplete(pFwEvent->hCmdMbox); 299 } 300 if (pFwEvent->uEventVector & ACX_INTR_EVENT_A) 301 { 302 eventMbox_Handle(pFwEvent->hEventMbox,&pFwEvent->tFwStatusTxn.tFwStatus); 303 } 304 if (pFwEvent->uEventVector & ACX_INTR_EVENT_B) 305 { 306 eventMbox_Handle(pFwEvent->hEventMbox,&pFwEvent->tFwStatusTxn.tFwStatus); 307 } 308 309 310 /* The DATA interrupt is shared by all data path events, so call all Tx and Rx clients */ 311 if (pFwEvent->uEventVector & ACX_INTR_DATA) 312 { 313 rxXfer_RxEvent (pFwEvent->hRxXfer, &pFwEvent->tFwStatusTxn.tFwStatus); 314 315 txHwQueue_UpdateFreeResources (pFwEvent->hTxHwQueue, &pFwEvent->tFwStatusTxn.tFwStatus); 316 317 txResult_TxCmpltIntrCb (pFwEvent->hTxResult, &pFwEvent->tFwStatusTxn.tFwStatus); 318 } 319 else if (pFwEvent->bEmulateRxIntr) 320 { 321 pFwEvent->bEmulateRxIntr = TI_FALSE; 322 rxXfer_RxEvent (pFwEvent->hRxXfer, &pFwEvent->tFwStatusTxn.tFwStatus); 323 } 324 325 /* After handling all raised bits, we can negate them */ 326 pFwEvent->tFwStatusTxn.tFwStatus.intrStatus &= pFwEvent->uEventMask; 327 } 328 329 330 /* 331 * \brief Requests the context engine to schedule the driver task 332 * 333 * \param hFwEvent - FwEvent Driver handle 334 * \return void 335 * 336 * \par Description 337 * Called by the FW-Interrupt ISR. 338 * Requests the context engine to schedule the driver task 339 * for handling the FW-Events (FwEvent callback). 340 * 341 * \sa 342 */ 343 void fwEvent_InterruptRequest (TI_HANDLE hFwEvent) 344 { 345 TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; 346 CL_TRACE_START_L1(); 347 348 /* Indicate that we are handling an actual FW interrupt (for FW time setting) */ 349 pFwEvent->bIsActualFwInterrupt = TI_TRUE; 350 351 /* Request switch to driver context for handling the FW-Interrupt event */ 352 context_RequestSchedule (pFwEvent->hContext, pFwEvent->uContextId); 353 354 CL_TRACE_END_L1("tiwlan_drv.ko", "FwEvent", "IRQ", ""); 355 } 356 357 358 /* 359 * \brief Handle the FW interrupts 360 * 361 * \param hFwEvent - FwEvent Driver handle 362 * \return void 363 * 364 * \par Description 365 * Called from context module upon receiving FW interrupt 366 * The function mask the interrupts and reads the FW status 367 * 368 * \sa 369 */ 370 371 static void fwEvent_Handle (TI_HANDLE hFwEvent) 372 { 373 TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; 374 ETxnStatus rc; 375 CL_TRACE_START_L2(); 376 377 if (pFwEvent->eFwEventState != FW_EVENT_STATE_IDLE) 378 { 379 if (pFwEvent->bIsActualFwInterrupt) 380 { 381 os_InterruptServiced (pFwEvent->hOs); 382 twIf_HwAvailable(pFwEvent->hTwIf); 383 } 384 CL_TRACE_END_L2("tiwlan_drv.ko", "FwEvent", "Handle", ""); 385 return; 386 } 387 388 pFwEvent->eFwEventState = FW_EVENT_STATE_READING; 389 390 twIf_Awake(pFwEvent->hTwIf); 391 if (pFwEvent->bIsActualFwInterrupt) 392 { 393 twIf_HwAvailable(pFwEvent->hTwIf); 394 } 395 396 /* Write HINT mask */ 397 pFwEvent->tMaskTxn.uData = ACX_INTR_ALL; 398 TXN_FW_EVENT_SET_MASK_ADDR(pFwEvent) 399 twIf_Transact(pFwEvent->hTwIf, &(pFwEvent->tMaskTxn.tTxnStruct)); 400 401 402 /* 403 * Read the Fw status 404 */ 405 TXN_FW_EVENT_SET_FW_STAT_ADDR(pFwEvent) 406 rc = twIf_TransactReadFWStatus(pFwEvent->hTwIf, &(pFwEvent->tFwStatusTxn.tTxnStruct)); 407 408 if (rc == TXN_STATUS_COMPLETE) 409 { 410 fwEvent_ReadCompleteCb(hFwEvent); 411 } 412 413 CL_TRACE_END_L2("tiwlan_drv.ko", "FwEvent", "Handle", ""); 414 } 415 416 417 /* 418 * \brief Handle the Fw Status information 419 * 420 * \param hFwEvent - FwEvent Driver handle 421 * \return void 422 * 423 * \par Description 424 * This function is called from fwEvent_Handle on a sync read, or from TwIf as a CB on an async read. 425 * It calls fwEvent_CallHandler to handle the triggered interrupts. 426 * 427 * \sa fwEvent_Handle 428 */ 429 static void fwEvent_ReadCompleteCb (TI_HANDLE hFwEvent) 430 { 431 TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; 432 433 os_InterruptServiced (pFwEvent->hOs); 434 435 /* If we were called because of an interrupt */ 436 if (pFwEvent->bIsActualFwInterrupt) 437 { 438 /* In case of level interrupt we need to clear the line */ 439 /*os_InterruptServiced(pFwEvent->hOs);*/ 440 441 /* 442 * Sync to fw time so we can update the tx packets 443 * on the delta time that they spent in the driver 444 */ 445 pFwEvent->uFwTimeOffset = (os_timeStampMs (pFwEvent->hOs) * 1000) - 446 ENDIAN_HANDLE_LONG (pFwEvent->tFwStatusTxn.tFwStatus.fwLocalTime); 447 448 pFwEvent->bIsActualFwInterrupt = TI_FALSE; 449 } 450 451 /* Save the interrupts status retreived from the FW */ 452 pFwEvent->uEventVector = pFwEvent->tFwStatusTxn.tFwStatus.intrStatus; 453 454 /* Mask unwanted interrupts */ 455 pFwEvent->uEventVector &= pFwEvent->uEventMask; 456 457 /* Call the interrupts handlers */ 458 fwEvent_CallHandler(hFwEvent); 459 460 /* Check if the state is changed in the context of the event callbacks */ 461 if (pFwEvent->eFwEventState == FW_EVENT_STATE_IDLE) 462 { 463 /* 464 * When fwEvent_stop is called state is changed to IDLE 465 * This is done in the context of the above events callbacks 466 * Don't send the UNMASK transaction because the driver stop process includes power off 467 */ 468 TRACE0(pFwEvent->hReport, REPORT_SEVERITY_WARNING, "fwEvent_ReadCompleteCb : State is IDLE ! don't send the UNMASK"); 469 return; 470 } 471 472 /* Write HINT unmask */ 473 pFwEvent->tUnMaskTxn.uData = ~pFwEvent->uEventMask; 474 TXN_FW_EVENT_SET_UNMASK_ADDR(pFwEvent) 475 twIf_Transact(pFwEvent->hTwIf, &(pFwEvent->tUnMaskTxn.tTxnStruct)); 476 477 twIf_Sleep(pFwEvent->hTwIf); 478 pFwEvent->eFwEventState = FW_EVENT_STATE_IDLE; 479 } 480 481 482 /* 483 * \brief Translate host to FW time (Usec) 484 * 485 * \param hFwEvent - FwEvent Driver handle 486 * \param uHostTime - The host time in MS to translate 487 * 488 * \return FW Time in Usec 489 * 490 * \par Description 491 * 492 * \sa 493 */ 494 TI_UINT32 fwEvent_TranslateToFwTime (TI_HANDLE hFwEvent, TI_UINT32 uHostTime) 495 { 496 TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; 497 498 return ((uHostTime * 1000) - pFwEvent->uFwTimeOffset); 499 } 500 501 502 /* 503 * \brief Unmask only cmd-cmplt and events interrupts (needed for init phase) 504 * 505 * \param hFwEvent - FwEvent Driver handle 506 * \return Event mask 507 * 508 * \par Description 509 * Unmask only cmd-cmplt and events interrupts (needed for init phase) 510 * and return interrupt enabled bit mask. 511 * 512 * \sa 513 */ 514 TI_UINT32 fwEvent_GetInitMask (TI_HANDLE hFwEvent) 515 { 516 TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; 517 518 /* Unmask only the interrupts needed for the FW configuration process. */ 519 pFwEvent->uEventMask = ACX_INTR_CMD_COMPLETE | ACX_INTR_EVENT_A | ACX_INTR_EVENT_B; 520 521 return pFwEvent->uEventMask; 522 } 523 524 525 /* 526 * \brief Stop & reset FwEvent (called by the driver stop process) 527 * 528 * \param hFwEvent - FwEvent Driver handle 529 * \return TI_OK 530 * 531 * \par Description 532 * 533 * \sa 534 */ 535 TI_STATUS fwEvent_Stop (TI_HANDLE hFwEvent) 536 { 537 TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; 538 539 pFwEvent->eFwEventState = FW_EVENT_STATE_IDLE; 540 pFwEvent->uEventMask = 0; 541 pFwEvent->bIsActualFwInterrupt = TI_FALSE; 542 pFwEvent->uEventVector = 0; 543 pFwEvent->bEmulateRxIntr = TI_FALSE; 544 545 return TI_OK; 546 } 547 548 549 /* 550 * \brief Unmask all interrupts, set Rx interrupt bit and call FwEvent_Handle 551 * 552 * \param hFwEvent - FwEvent Driver handle 553 * \return void 554 * 555 * \par Description 556 * Called when driver Start or recovery process is completed. 557 * Unmask all interrupts, set Rx interrupt bit and call FwEvent_Handle 558 * (in case we missed an Rx interrupt in a recovery process). 559 * 560 * \sa 561 */ 562 void fwEvent_EnableExternalEvents (TI_HANDLE hFwEvent) 563 { 564 TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; 565 566 /* Unmask all interrupts */ 567 pFwEvent->uEventMask = ALL_EVENTS_VECTOR; 568 569 /* Set flag to invoke Rx interrupt handler in case we missed it in a recovery/start process */ 570 pFwEvent->bEmulateRxIntr = TI_TRUE; 571 572 /* Handle interrupts including the Rx we've just set manually */ 573 fwEvent_Handle (hFwEvent); 574 } 575 576 577 /* 578 * \brief Disable the FwEvent client of the context thread handler 579 * 580 * \param hFwEvent - FwEvent Driver handle 581 * \return void 582 * 583 * \par Description 584 * 585 * \sa 586 */ 587 void fwEvent_DisableInterrupts(TI_HANDLE hFwEvent) 588 { 589 TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; 590 591 context_DisableClient (pFwEvent->hContext,pFwEvent->uContextId); 592 593 } 594 595 596 /* 597 * \brief Enable the FwEvent client of the context thread handler 598 * 599 * \param hFwEvent - FwEvent Driver handle 600 * \return void 601 * 602 * \par Description 603 * 604 * \sa 605 */ 606 void fwEvent_EnableInterrupts(TI_HANDLE hFwEvent) 607 { 608 TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; 609 610 context_EnableClient (pFwEvent->hContext,pFwEvent->uContextId); 611 612 } 613 614 615 616 #ifdef TI_DBG 617 618 void fwEvent_PrintStat (TI_HANDLE hFwEvent) 619 { 620 #ifdef REPORT_LOG 621 TfwEvent *pFwEvent = (TfwEvent *)hFwEvent; 622 FwStatus_t *fwStat = &pFwEvent->tFwStatusTxn.tFwStatus; 623 int i; 624 625 WLAN_OS_REPORT(("Print FW event module info\n")); 626 WLAN_OS_REPORT(("==========================\n")); 627 WLAN_OS_REPORT(("intrStatus = 0x%08x\n", pFwEvent->uEventVector)); 628 WLAN_OS_REPORT(("intrMask = 0x%08x\n", pFwEvent->uEventMask)); 629 WLAN_OS_REPORT(("counters = 0x%08x\n", fwStat->counters)); 630 for (i = 0; i < NUM_RX_PKT_DESC; i++) 631 { 632 WLAN_OS_REPORT(("rxPktsDesc[%1d] = 0x%08x\n", i, fwStat->rxPktsDesc[i])); 633 } 634 for (i = 0; i < NUM_TX_QUEUES; i++) 635 { 636 WLAN_OS_REPORT(("txReleasedBlks[%1d] = 0x%08x\n", i, fwStat->txReleasedBlks[i])); 637 } 638 WLAN_OS_REPORT(("fwLocalTime = 0x%08x\n", fwStat->fwLocalTime)); 639 #endif 640 } 641 642 #endif /* TI_DBG */ 643 644 645 646