1 /**************************************************************************** 2 **+-----------------------------------------------------------------------+** 3 **| |** 4 **| Copyright(c) 1998 - 2008 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 36 /**************************************************************************** 37 * 38 * MODULE: FwEvent.c 39 * 40 * PURPOSE: Handle firmware events 41 * 42 * DESCRIPTION: 43 * ============ 44 * Call the appropriate event handler. 45 * 46 ****************************************************************************/ 47 48 #include "osTIType.h" 49 #include "commonTypes.h" 50 #include "tnetwCommon.h" 51 #include "TNETWIF.h" 52 #include "TNETWArb.h" 53 #include "txResult_api.h" 54 #include "osApi.h" 55 #include "whalBus_Api.h" 56 #include "CmdMBox_api.h" 57 #include "TNETW_Driver.h" 58 #include "whalCtrl.h" 59 #include "shmBus.h" 60 #include "rxXfer_api.h" 61 #include "FwEvent.h" 62 #include "eventMbox_api.h" 63 64 #ifdef TI_DBG 65 #include "DebugTraceXfer_api.h" 66 #endif /* TI_DBG */ 67 68 /* for debug only */ 69 #undef DEBUG_INTERRUPTS_PRINT 70 71 /********************* static function declerations *************************/ 72 static void FwEvent_ReadRegCB (TI_HANDLE hFwEvent, UINT8 moduleID, TI_STATUS status); 73 static void FwEvent_WriteMaskCB (TI_HANDLE hFwEvent, UINT8 moduleID, TI_STATUS status); 74 static void FwEvent_WriteMuxCB (TI_HANDLE hFwEvent, UINT8 moduleID, TI_STATUS status); 75 static void FwEvent_UpdateRxBits (TI_HANDLE hFwEvent); 76 77 /* Client info structure */ 78 typedef struct 79 { 80 /* Client event bit in interrupt status register */ 81 UINT32 event; 82 /* Client handler */ 83 TI_STATUS (*func) (TI_HANDLE hclient); 84 /* Client corresponding trace message */ 85 char *trace; 86 } FwClient_t; 87 88 89 /* 90 * NOTE: Register clients in order of their priorities. 91 * The command mailbox priority is higher than that of event mailbox. 92 * This ensures the command complete callback always arrives before event. 93 */ 94 static const FwClient_t fwClient [MAX_EVENT_NUM] = 95 { 96 { ACX_INTR_RX0_DATA, rxXfer_RxEvent, "ACX_INTR_RX0_DATA" }, 97 { ACX_INTR_TX_RESULT, txResult_TxCmpltIntrCB, "ACX_INTR_TX_RESULT" }, 98 { ACX_INTR_RX1_DATA, rxXfer_RxEvent, "ACX_INTR_RX1_DATA" }, 99 { ACX_INTR_CMD_COMPLETE, CmdMBox_CmdCmplt, "ACX_INTR_CMD_COMPLETE" }, 100 { ACX_INTR_EVENT_A, eventMbox_Event, "ACX_INTR_EVENT_A" }, 101 { ACX_INTR_EVENT_B, eventMbox_Event, "ACX_INTR_EVENT_B" }, 102 #ifdef TI_DBG 103 { ACX_INTR_TRACE_A, debugTrace_Event, "ACX_INTR_TRACE_A" }, 104 { ACX_INTR_TRACE_B, debugTrace_Event, "ACX_INTR_TRACE_B" }, 105 #endif 106 }; 107 108 109 /**************************************************************************** 110 * FwEvent_Create() 111 **************************************************************************** 112 * DESCRIPTION: Create the FwEvent module object 113 * 114 * INPUTS: None 115 * 116 * OUTPUT: None 117 * 118 * RETURNS: The Created object 119 ****************************************************************************/ 120 TI_HANDLE FwEvent_Create (TI_HANDLE hOs) 121 { 122 FwEventObj_t *pFwEvent; 123 124 pFwEvent = os_memoryAlloc (hOs, sizeof(FwEventObj_t)); 125 if (pFwEvent == NULL) 126 { 127 return NULL; 128 } 129 130 os_memoryZero (hOs, pFwEvent, sizeof(FwEventObj_t)); 131 132 pFwEvent->hOs = hOs; 133 134 return (TI_HANDLE)pFwEvent; 135 } /* FwEvent_Create() */ 136 137 138 /**************************************************************************** 139 * FwEvent_Destroy() 140 **************************************************************************** 141 * DESCRIPTION: Destroy the FwEvent module object 142 * 143 * INPUTS: hFwEvent - The object to free 144 * 145 * OUTPUT: None 146 * 147 * RETURNS: OK 148 ****************************************************************************/ 149 TI_STATUS FwEvent_Destroy (TI_HANDLE hFwEvent) 150 { 151 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 152 153 if (pFwEvent) 154 { 155 os_memoryFree (pFwEvent->hOs, pFwEvent, sizeof(FwEventObj_t)); 156 } 157 158 return TNETWIF_OK; 159 } /* FwEvent_Destroy() */ 160 161 162 /**************************************************************************** 163 * FwEvent_Config() 164 **************************************************************************** 165 * DESCRIPTION: Config the FwEvent module object 166 * 167 * INPUTS: hTNETW_Driver - TNETW Driver handle 168 * hhFwEvent - FwEvent handle; 169 * 170 * OUTPUT: None 171 * 172 * RETURNS: None 173 ****************************************************************************/ 174 VOID FwEvent_Config (TI_HANDLE hFwEvent, TI_HANDLE hTnetwDrv) 175 { 176 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 177 TnetwDrv_t *pTnetwDrv = (TnetwDrv_t *)hTnetwDrv; 178 179 pFwEvent->hOs = pTnetwDrv->hOs; 180 pFwEvent->hReport = pTnetwDrv->hReport; 181 pFwEvent->hTNETWIF = pTnetwDrv->hTNETWIF; 182 183 /* Register clients in order of their priorities */ 184 pFwEvent->hClient[0] = pTnetwDrv->hRxXfer; 185 pFwEvent->hClient[1] = pTnetwDrv->hTxResult; 186 pFwEvent->hClient[2] = pTnetwDrv->hRxXfer; 187 pFwEvent->hClient[3] = pTnetwDrv->hCmdMBox; 188 pFwEvent->hClient[4] = pTnetwDrv->hEventMbox; 189 pFwEvent->hClient[5] = pTnetwDrv->hEventMbox; 190 #ifdef TI_DBG 191 pFwEvent->hClient[6] = pTnetwDrv->hDebugTrace; 192 pFwEvent->hClient[7] = pTnetwDrv->hDebugTrace; 193 #endif /* TI_DBG */ 194 195 pFwEvent->FwEventState = FW_EVENT_STATE_IDLE; 196 pFwEvent->EventMask = 0; 197 198 /* Setting the RxControlAddr to 0 indicates that it shouldn't be used */ 199 pFwEvent->RxControlAddr = 0; 200 pFwEvent->uNumOfRxHandled = 0; 201 /* Before reading the first Fw Rx counters act like there's no Rx. This is done for the init phase */ 202 pFwEvent->uFwRxCounter = 0; 203 } /* FwEvent_Config() */ 204 205 206 /**************************************************************************** 207 * FwEvent_SetHwInfo() 208 **************************************************************************** 209 * DESCRIPTION: Set the rx control address. This is the register to be read 210 for the Fw Rx counters. Before this function is called we don't 211 use that variable. 212 * 213 * INPUTS: hFwEvent - FwEvent handle; 214 * pDataPathParams - struct to read the Address from 215 * 216 * OUTPUT: None 217 * 218 * RETURNS: None 219 ****************************************************************************/ 220 void FwEvent_SetHwInfo (TI_HANDLE hFwEvent, ACXDataPathParamsResp_t *pDataPathParams) 221 { 222 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 223 224 pFwEvent->RxControlAddr = pDataPathParams->rxControlAddr; 225 226 WLAN_REPORT_INFORMATION (pFwEvent->hReport, FW_EVENT_MODULE_LOG, 227 ("%s: RxControlAddr=0x%x\n", __FUNCTION__, pFwEvent->RxControlAddr)); 228 } 229 230 231 /**************************************************************************** 232 * FwEvent_CallHandler() 233 **************************************************************************** 234 * DESCRIPTION: Call FwEvent client's event handler 235 * 236 * INPUTS: hFwEvent - The object 237 238 239 240 * 241 * OUTPUT: None 242 * 243 * RETURNS: NOK, TNETWIF_COMPLETE, TNETWIF_PENDING 244 ****************************************************************************/ 245 static TI_STATUS FwEvent_CallHandler (TI_HANDLE hFwEvent) 246 { 247 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 248 TI_STATUS rc; 249 250 if (pFwEvent->EventVector == 0) 251 { 252 return NOK; 253 } 254 255 while ((pFwEvent->EventNum < MAX_EVENT_NUM) && 256 (pFwEvent->EventVector & fwClient[pFwEvent->EventNum].event) == 0) 257 pFwEvent->EventNum ++; 258 259 if (pFwEvent->EventNum < MAX_EVENT_NUM) 260 { 261 /* Negate corresponding bit in event vector */ 262 pFwEvent->EventVector &= ~fwClient[pFwEvent->EventNum].event; 263 264 /* Call client handler */ 265 rc = fwClient[pFwEvent->EventNum].func (pFwEvent->hClient[pFwEvent->EventNum]); 266 267 WLAN_REPORT_INFORMATION (pFwEvent->hReport, FW_EVENT_MODULE_LOG, 268 ("FwEvent_CallHandler: %s, return=%u\n", fwClient[pFwEvent->EventNum].trace, rc)); 269 270 return rc; 271 } 272 273 return NOK; 274 275 } /* FwEvent_CallHandler */ 276 277 278 /**************************************************************************** 279 * FwEvent_StateMachine() 280 **************************************************************************** 281 * DESCRIPTION: Manage the FwEvent state machine 282 * 283 * INPUTS: hFwEvent - The object 284 * rc - Code passed FwEvent_EventComplete(), either OK or MORE 285 * 286 * OUTPUT: None 287 * 288 * RETURNS: None 289 ****************************************************************************/ 290 static void FwEvent_StateMachine (TI_HANDLE hFwEvent, systemStatus_e rc) 291 { 292 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 293 294 while (rc != TNETWIF_PENDING) 295 { 296 switch (pFwEvent->FwEventState) 297 { 298 case FW_EVENT_STATE_WAIT_BUS_I: 299 pFwEvent->PendingEvent = FALSE; 300 pFwEvent->FwEventState = FW_EVENT_STATE_WAIT_MASK; 301 /* 302 * We reach this state after TNETWIF_Start CB 303 * mask the interrupts in the FW 304 */ 305 rc = TNETWIF_WriteRegOpt (pFwEvent->hTNETWIF, 306 HINT_MASK, 307 ACX_INTR_ALL, 308 FW_EVENT_MODULE_ID, 309 FwEvent_WriteMaskCB, 310 hFwEvent); 311 312 break; 313 314 case FW_EVENT_STATE_WAIT_MASK: 315 pFwEvent->FwEventState = FW_EVENT_STATE_WAIT_UNMUX; 316 if (OK == TNETWIF_UnMux (pFwEvent->hTNETWIF)) 317 { 318 rc = TNETWIF_WriteELPOpt (pFwEvent->hTNETWIF, 319 0x1,/*ELPCTRL_WAKE_UP*/ 320 FW_EVENT_MODULE_ID, 321 FwEvent_WriteMuxCB, 322 hFwEvent, 323 TRUE); 324 } 325 else 326 { 327 rc = TNETWIF_COMPLETE; 328 } 329 break; 330 331 case FW_EVENT_STATE_WAIT_UNMUX: 332 case FW_EVENT_STATE_WAIT_BUS_II: 333 pFwEvent->LoopCounter++; 334 /* Read the rx counters if the Address was configured */ 335 if (pFwEvent->RxControlAddr) 336 { 337 pFwEvent->FwEventState = FW_EVENT_STATE_WAIT_HINT_READ; 338 } 339 /* Rx Address was not configured yet. Jump over the read counters state */ 340 else 341 { 342 pFwEvent->FwEventState = FW_EVENT_STATE_WAIT_READ_COUNTERS; 343 } 344 /* 345 * We reach this state after TNETWIF_Start CB 346 * mask the interrupts in the FW 347 */ 348 rc = TNETWIF_ReadRegOpt (pFwEvent->hTNETWIF, 349 ACX_REG_INTERRUPT_CLEAR, 350 &pFwEvent->EventVector, 351 FW_EVENT_MODULE_ID, 352 FwEvent_ReadRegCB, 353 hFwEvent); 354 355 break; 356 357 case FW_EVENT_STATE_WAIT_HINT_READ: 358 /* 359 * Read Fw rx counters. This is needed due to a BUG in the Rx bits which causes to loose bits in the 360 * EventVector, and therefore we can't relay on the HINT read. The BUG is Fw/Hw related 361 */ 362 pFwEvent->FwEventState = FW_EVENT_STATE_WAIT_READ_COUNTERS; 363 364 rc = TNETWIF_ReadMemOpt (pFwEvent->hTNETWIF, 365 pFwEvent->RxControlAddr, 366 PADREAD (&pFwEvent->uFwRxCounter), 367 sizeof(UINT32), 368 FW_EVENT_MODULE_ID, 369 FwEvent_ReadRegCB, 370 hFwEvent); 371 372 break; 373 374 case FW_EVENT_STATE_WAIT_READ_COUNTERS: 375 376 WLAN_REPORT_INFORMATION(pFwEvent->hReport,FW_EVENT_MODULE_LOG, 377 ("Reading HostIntRegister = 0x%x, FwRxCounter = 0x%x DriverRxCounter = 0x%x\n", 378 pFwEvent->EventVector, pFwEvent->uFwRxCounter, pFwEvent->uNumOfRxHandled)); 379 /* 380 * Mask unwanted interrupts. 381 */ 382 pFwEvent->EventVector &= pFwEvent->EventMask; 383 384 /* Work-around: check if there's a missing Rx bit (or 2 bits) in the Register */ 385 FwEvent_UpdateRxBits (hFwEvent); 386 387 if (pFwEvent->EventVector == 0) 388 { 389 #ifdef LEVEL_IRQ 390 /* if working level sensitive mode we must first enable IRQ source */ 391 os_enableIrq(pFwEvent->hOs); 392 #endif 393 pFwEvent->FwEventState = FW_EVENT_STATE_WAIT_UNMASK; 394 /* Unmask the interrupts in the FW */ 395 rc = TNETWIF_WriteRegOpt (pFwEvent->hTNETWIF, 396 HINT_MASK, 397 ~pFwEvent->EventMask, 398 FW_EVENT_MODULE_ID, 399 FwEvent_WriteMaskCB, 400 hFwEvent); 401 } 402 else 403 { 404 pFwEvent->FwEventState = FW_EVENT_STATE_HANDLE_EVENT; 405 406 rc = TNETWIF_COMPLETE; 407 } 408 409 break; 410 411 case FW_EVENT_STATE_HANDLE_EVENT: 412 if ((rc = FwEvent_CallHandler (hFwEvent)) == NOK) 413 { 414 /* All events have been handled, break the loop */ 415 if (pFwEvent->LoopCounter < NUM_OF_READ_REG_LOOPS) 416 { 417 /* Restart */ 418 pFwEvent->FwEventState = FW_EVENT_STATE_WAIT_BUS_II; 419 rc = TNETWIF_Restart (pFwEvent->hTNETWIF, 420 FW_EVENT_MODULE_ID, 421 hFwEvent, 422 FwEvent_BusReadyCB); 423 } 424 else 425 { 426 #ifdef LEVEL_IRQ 427 /* if working level sensitive mode we must first enable IRQ source */ 428 os_enableIrq(pFwEvent->hOs); 429 #endif 430 /* Unmask the interrupts in the FW */ 431 pFwEvent->FwEventState = FW_EVENT_STATE_WAIT_UNMASK; 432 rc = TNETWIF_WriteRegOpt (pFwEvent->hTNETWIF, 433 HINT_MASK, 434 ~pFwEvent->EventMask, 435 FW_EVENT_MODULE_ID, 436 FwEvent_WriteMaskCB, 437 hFwEvent); 438 } 439 } 440 break; 441 442 case FW_EVENT_STATE_WAIT_UNMASK: 443 /* We get here after unmask CB */ 444 if (pFwEvent->PendingEvent) 445 { 446 pFwEvent->PendingEvent = FALSE; 447 pFwEvent->FwEventState = FW_EVENT_STATE_WAIT_BUS_I; 448 TNETWIF_Restart (pFwEvent->hTNETWIF, 449 FW_EVENT_MODULE_ID, 450 hFwEvent, 451 FwEvent_BusReadyCB); 452 } 453 else 454 { 455 pFwEvent->FwEventState = FW_EVENT_STATE_IDLE; 456 TNETWIF_Finish (pFwEvent->hTNETWIF, FW_EVENT_MODULE_ID, NULL, NULL); 457 } 458 rc = TNETWIF_PENDING; 459 break; 460 461 case FW_EVENT_STATE_IDLE: 462 default: 463 WLAN_REPORT_ERROR (pFwEvent->hReport, FW_EVENT_MODULE_LOG, 464 ("FwEvent_StateMachine - invalid state\n")); 465 rc = TNETWIF_PENDING; 466 break; 467 468 } /* switch */ 469 470 if (TNETWIF_ERROR == rc) 471 { 472 WLAN_REPORT_ERROR (pFwEvent->hReport, FW_EVENT_MODULE_LOG, 473 ("FwEvent_StateMachine rc = TNETWIF_ERROR !!! in state = %d\n", 474 pFwEvent->FwEventState)); 475 } 476 477 } /* while */ 478 479 } /* FwEvent_StateMachine() */ 480 481 482 /**************************************************************************** 483 * FwEvent() 484 **************************************************************************** 485 * DESCRIPTION: Start FwEvent 486 * 487 * INPUTS: hFwEvent - The object 488 * 489 * OUTPUT: None 490 * 491 * RETURNS: OK - if in Idle NOK - else 492 ****************************************************************************/ 493 TI_STATUS FwEvent (TI_HANDLE hFwEvent) 494 { 495 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 496 497 /* NOTE: pFwEvent may be uninitialized at init stage */ 498 if (pFwEvent != NULL) 499 { 500 if (pFwEvent->FwEventState == FW_EVENT_STATE_IDLE) 501 { 502 pFwEvent->IntrState = STATE_DPC; 503 pFwEvent->EventVector = 0; 504 pFwEvent->LoopCounter = 0; 505 pFwEvent->FwEventState = FW_EVENT_STATE_WAIT_BUS_I; 506 507 /* NOTE: hTNETWIF may be uninitialized at init */ 508 if (pFwEvent->hTNETWIF != NULL) 509 { 510 TNETWIF_Start (pFwEvent->hTNETWIF, FW_EVENT_MODULE_ID, hFwEvent, FwEvent_BusReadyCB); 511 } 512 } 513 else if (pFwEvent->FwEventState == FW_EVENT_STATE_WAIT_UNMASK) 514 { 515 pFwEvent->LoopCounter = 0; 516 /* 517 * If an interrupt receiving while unmasking the previous, sign it as pending and exit. 518 * It will be handled in the next iteration after Restart. 519 */ 520 pFwEvent->PendingEvent = TRUE; 521 } 522 else 523 { 524 WLAN_REPORT_WARNING (pFwEvent->hReport, FW_EVENT_MODULE_LOG, 525 ("FwEvent() entering SM not in Idle !!! state: %d\n", 526 pFwEvent->FwEventState)); 527 528 return NOK; 529 } 530 } 531 532 return OK; 533 } /* FwEvent() */ 534 535 536 /**************************************************************************** 537 * FwEvent_BusReadyCB() 538 **************************************************************************** 539 * DESCRIPTION: FwEvent_BusReadyCB 540 * 541 * INPUTS: hFwEvent - The object 542 * 543 * OUTPUT: None 544 * 545 * RETURNS: None 546 ****************************************************************************/ 547 void FwEvent_BusReadyCB (TI_HANDLE hFwEvent, UINT8 module_id, TI_STATUS status) 548 { 549 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 550 551 if (pFwEvent->FwEventState == FW_EVENT_STATE_WAIT_BUS_I || 552 pFwEvent->FwEventState == FW_EVENT_STATE_WAIT_BUS_II) 553 { 554 /* 555 * NOTE: init the EventNum here for it take effect both for Start and Restart 556 */ 557 pFwEvent->EventNum = 0; 558 FwEvent_StateMachine (hFwEvent, TNETWIF_NONE); 559 } 560 else 561 { 562 WLAN_REPORT_ERROR (pFwEvent->hReport, FW_EVENT_MODULE_LOG, 563 ("FwEvent_BusReadyCB() state(%d) is not FW_EVENT_STATE_READ_REG\n", 564 pFwEvent->FwEventState)); 565 } 566 } /* FwEvent_BusReadyCB() */ 567 568 569 /**************************************************************************** 570 * FwEvent_WriteMaskCB() 571 **************************************************************************** 572 * DESCRIPTION: Write Mask CB 573 * 574 * INPUTS: hFwEvent - The object 575 * 576 * OUTPUT: None 577 * 578 * RETURNS: None 579 ****************************************************************************/ 580 void FwEvent_WriteMaskCB (TI_HANDLE hFwEvent, UINT8 moduleID, TI_STATUS status) 581 { 582 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 583 584 if (pFwEvent->FwEventState == FW_EVENT_STATE_WAIT_MASK || 585 pFwEvent->FwEventState == FW_EVENT_STATE_WAIT_UNMASK) 586 { 587 FwEvent_StateMachine (hFwEvent, TNETWIF_NONE); 588 } 589 else 590 { 591 WLAN_REPORT_ERROR (pFwEvent->hReport, FW_EVENT_MODULE_LOG, 592 ("FwEvent_WriteMaskCB() shouldn't be called with state(%d)\n", 593 pFwEvent->FwEventState)); 594 } 595 } /* FwEvent_WriteMaskCB() */ 596 597 598 /**************************************************************************** 599 * FwEvent_WriteMuxCB() 600 **************************************************************************** 601 * DESCRIPTION: Write Mask CB 602 * 603 * INPUTS: hFwEvent - The object 604 * 605 * OUTPUT: None 606 * 607 * RETURNS: None 608 ****************************************************************************/ 609 void FwEvent_WriteMuxCB (TI_HANDLE hFwEvent, UINT8 moduleID, TI_STATUS status) 610 { 611 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 612 613 if (pFwEvent->FwEventState == FW_EVENT_STATE_WAIT_UNMUX) 614 { 615 FwEvent_StateMachine (hFwEvent, TNETWIF_NONE); 616 } 617 else 618 { 619 WLAN_REPORT_ERROR (pFwEvent->hReport, FW_EVENT_MODULE_LOG, 620 ("FwEvent_WriteMaskCB() shouldn't be called with state(%d)\n", 621 pFwEvent->FwEventState)); 622 } 623 } /* FwEvent_WriteMaskCB() */ 624 625 626 /**************************************************************************** 627 * FwEvent_ReadRegCB() 628 **************************************************************************** 629 * DESCRIPTION: FwEvent_ReadRegCB 630 * 631 * INPUTS: hFwEvent - The object 632 * 633 * OUTPUT: None 634 * 635 * RETURNS: None 636 ****************************************************************************/ 637 void FwEvent_ReadRegCB (TI_HANDLE hFwEvent, UINT8 moduleID, TI_STATUS status) 638 { 639 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 640 641 if ((pFwEvent->FwEventState == FW_EVENT_STATE_WAIT_HINT_READ) || 642 (pFwEvent->FwEventState == FW_EVENT_STATE_WAIT_READ_COUNTERS)) 643 { 644 FwEvent_StateMachine (hFwEvent, TNETWIF_NONE); 645 } 646 else 647 { 648 WLAN_REPORT_ERROR (pFwEvent->hReport, FW_EVENT_MODULE_LOG, 649 ("FwEvent_ReadRegCB() is in state(%d)\n", 650 pFwEvent->FwEventState)); 651 } 652 } /* FwEvent_BusReadyCB() */ 653 654 655 /**************************************************************************** 656 * FwEvent_UpdateRxBits() 657 **************************************************************************** 658 * DESCRIPTION: Update the EventVector according to the Fw counter of Rx. 659 * The Rx bits from the EventVector are ignored and instead we are 660 * using the Fw counters in order to decide how many Rx should we read. 661 * Using this method is due to a Hw/Fw bug in which we miss some of the 662 * Rx bits in the EventVector. 663 * 664 * INPUTS: pFwEvent - The object 665 * 666 * OUTPUT: pFwEvent->EventVector - Add Rx bit if needed 667 * 668 * RETURNS: None 669 ****************************************************************************/ 670 void FwEvent_UpdateRxBits (TI_HANDLE hFwEvent) 671 { 672 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 673 UINT32 uFwDriverDiff = pFwEvent->uFwRxCounter - pFwEvent->uNumOfRxHandled; 674 675 /* use only the last 4 bits since the Fw is using 4 bits */ 676 uFwDriverDiff &= 0xf; 677 678 /* Use the diff to add the number of bits needed for handling */ 679 switch (uFwDriverDiff) 680 { 681 case 0: 682 /* Erase Rx bits */ 683 pFwEvent->EventVector &= ~ACX_INTR_RX0_DATA; 684 pFwEvent->EventVector &= ~ACX_INTR_RX1_DATA; 685 break; 686 case 1: 687 /* Add only one bit */ 688 pFwEvent->EventVector |= ACX_INTR_RX0_DATA; 689 pFwEvent->EventVector &= ~ACX_INTR_RX1_DATA; 690 break; 691 case 2: 692 /* Add the 2 bits */ 693 pFwEvent->EventVector |= ACX_INTR_RX0_DATA; 694 pFwEvent->EventVector |= ACX_INTR_RX1_DATA; 695 break; 696 default: 697 /* 698 * This is a very bad case were there is no synchronization between Driver & FW. In order to recover from this 699 * state we will use the the EventVector "as-is" and hope for the best... 700 */ 701 WLAN_REPORT_ERROR (pFwEvent->hReport, FW_EVENT_MODULE_LOG, 702 ("%s Fw = 0x%x Dr = 0x%x\n", __FUNCTION__, pFwEvent->uFwRxCounter, pFwEvent->uNumOfRxHandled)); 703 704 break; 705 } 706 707 /* This will make sure that next time we will be synchronized with the Fw */ 708 pFwEvent->uNumOfRxHandled = pFwEvent->uFwRxCounter; 709 710 } 711 712 /**************************************************************************** 713 * FwEvent_EventComplete() 714 **************************************************************************** 715 * DESCRIPTION: FwEvent_EventComplete 716 * 717 * INPUTS: hFwEvent - The object 718 * rc - OK or MORE 719 * 720 * OUTPUT: None 721 * 722 * RETURNS: None 723 ****************************************************************************/ 724 void FwEvent_EventComplete (TI_HANDLE hFwEvent, systemStatus_e rc) 725 { 726 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 727 728 if (pFwEvent->FwEventState == FW_EVENT_STATE_HANDLE_EVENT) 729 { 730 FwEvent_StateMachine (hFwEvent,rc); 731 } 732 else 733 { 734 WLAN_REPORT_ERROR (pFwEvent->hReport, FW_EVENT_MODULE_LOG, 735 ("FwEvent_EventComplete() state(%d) is not FW_EVENT_STATE_PENDING\n", 736 pFwEvent->FwEventState)); 737 } 738 } /* FwEvent_EventComplete() */ 739 740 741 /**************************************************************************** 742 * FwEvent_Enable() 743 **************************************************************************** 744 * DESCRIPTION: enable specific interrupt 745 * 746 * INPUTS: 747 * 748 * OUTPUT: 749 ****************************************************************************/ 750 void FwEvent_Enable (TI_HANDLE hFwEvent, UINT32 uEventMask) 751 { 752 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 753 754 pFwEvent->EventMask |= uEventMask; 755 756 WLAN_REPORT_INFORMATION (pFwEvent->hReport, FW_EVENT_MODULE_LOG, 757 ("%s: EventMask = 0x%x\n", __FUNCTION__, pFwEvent->EventMask)); 758 } 759 760 761 /**************************************************************************** 762 * FwEvent_Disable() 763 **************************************************************************** 764 * DESCRIPTION: disables specific interrupt 765 * 766 * INPUTS: 767 * 768 * OUTPUT: 769 ****************************************************************************/ 770 void FwEvent_Disable (TI_HANDLE hFwEvent, UINT32 uEventMask) 771 { 772 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 773 774 pFwEvent->EventMask &= ~uEventMask; 775 776 WLAN_REPORT_INFORMATION (pFwEvent->hReport, FW_EVENT_MODULE_LOG, 777 ("%s: EventMask = 0x%x\n", __FUNCTION__, pFwEvent->EventMask)); 778 } 779 780 781 /**************************************************************************** 782 * FwEvent_GetEnabled() 783 **************************************************************************** 784 * DESCRIPTION: returns interrupt enabled bit mask 785 * 786 * INPUTS: 787 * 788 * OUTPUT: 789 ****************************************************************************/ 790 UINT32 FwEvent_GetEnabled (TI_HANDLE hFwEvent) 791 { 792 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 793 794 return pFwEvent->EventMask; 795 } 796 797 /****************************************************************************************************** 798 * 799 * Functions originally located at whalHwIntr.c - Not used in the current version and might be removed 800 * 801 *******************************************************************************************************/ 802 803 804 /**************************************************************************** 805 * FwEvent_EnableInterrupts() 806 **************************************************************************** 807 * DESCRIPTION: Enable interrupts 808 * 809 * INPUTS: 810 * 811 * OUTPUT: None 812 * 813 * NOTE: Originally located at whalHwIntr.c . 814 ****************************************************************************/ 815 void FwEvent_EnableInterrupts (TI_HANDLE hFwEvent) 816 { 817 #ifdef USE_SYNC_API 818 819 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 820 821 /* Clearing all the interrupt status register sources */ 822 TNETWIF_WriteRegSync (pFwEvent->hTNETWIF, ACX_REG_INTERRUPT_MASK, ~pFwEvent->EventMask); 823 824 /* 825 * Setting the right operation of the interrupt 826 * bit 5 - enable interrupt 827 * bit 7 - active low 828 */ 829 TNETWIF_WriteRegSync (pFwEvent->hTNETWIF, HI_CFG, HI_CFG_DEF_VAL); 830 831 #ifdef DEBUG_INTERRUPTS_PRINT 832 WLAN_REPORT_INFORMATION (pFwEvent->hReport, 833 FW_EVENT_MODULE_LOG, 834 ("FwEvent_EnableInterrupts(0x%08X)", 835 pFwEvent->EventMask)); 836 #endif /* DEBUG_INTERRUPTS_PRINT */ 837 838 #if defined(HAL_ON_WIN) 839 /* (!!!) only in CardBus, add HostIfType parameter */ 840 /* Enable Interrupt on a CardBus */ 841 TNETWIF_WriteRegSync (pFwEvent->hTNETWIF, FEMR, 0x8000); 842 #endif 843 844 #endif /* USE_SYNC_API */ 845 846 } 847 848 /**************************************************************************** 849 * FwEvent_DisableInterrupts() 850 **************************************************************************** 851 * DESCRIPTION: Disable interrupts 852 * 853 * INPUTS: 854 * 855 * OUTPUT: None 856 * 857 * RETURNS: 858 ****************************************************************************/ 859 void FwEvent_DisableInterrupts (TI_HANDLE hFwEvent) 860 { 861 #ifdef USE_SYNC_API 862 863 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 864 865 TNETWIF_WriteRegSync (pFwEvent->hTNETWIF, ACX_REG_INTERRUPT_MASK, ACX_INTR_ALL ); 866 867 #ifdef DEBUG_INTERRUPTS_PRINT 868 WLAN_REPORT_INFORMATION (pFwEvent->hReport, 869 FW_EVENT_MODULE_LOG, 870 ("FwEvent_DisableInterrupts(0x%08X)", 871 ACX_INTR_ALL)); 872 #endif /* DEBUG_INTERRUPTS_PRINT */ 873 874 #endif /* USE_SYNC_API */ 875 } 876 877 878 /**************************************************************************** 879 * FwEvent_CheckInterrupts() 880 **************************************************************************** 881 * DESCRIPTION: Check if there is interrupts (only unmasked) 882 * 883 * INPUTS: 884 * 885 * OUTPUT: None 886 * 887 * RETURNS: 0 - no interrupts, otherwise - there are interrupts 888 ****************************************************************************/ 889 UINT32 FwEvent_CheckInterrupts (TI_HANDLE hFwEvent) 890 { 891 #ifdef USE_SYNC_API 892 893 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 894 register UINT32 CurrentIntr; 895 UINT32 interruptRegVal; 896 register UINT32 maskInterruptVal; 897 #ifdef DEBUG_INTERRUPTS_PRINT 898 UINT32 endReg; 899 #endif /* DEBUG_INTERRUPTS_PRINT */ 900 901 if (pFwEvent->IntrState != STATE_OPERATIONAL) 902 { 903 /* 904 ISR can't be called till the state will be operational again because the ISR 905 disable the interrupts of the TNET thus if this function is called then it need 906 to return 0!!! 907 */ 908 #ifdef DEBUG_INTERRUPTS_PRINT 909 WLAN_REPORT_WARNING (pFwEvent->hReport, 910 FW_EVENT_MODULE_LOG, 911 ("FwEvent_CheckInterrupts() - state isn't STATE_OPERATIONAL (=%d) - ABRTING!\n", 912 pFwEvent->IntrState)); 913 #endif /* DEBUG_INTERRUPTS_PRINT */ 914 } 915 916 #ifdef HW_ACCESS_DEBUG_ACCESS_VIOLATION 917 whal_hwAccess_setOverrideElpCheck ((TI_HANDLE)pFwEvent->hTNETWIF, TRUE); 918 #endif /* HW_ACCESS_DEBUG_ACCESS_VIOLATION */ 919 920 /*read the status register*/ 921 TNETWIF_ReadRegSync (pFwEvent->hTNETWIF, ACX_REG_INTERRUPT_NO_CLEAR, &interruptRegVal); 922 923 CurrentIntr = interruptRegVal; 924 925 /* 0xFFFF means that the card is disconnected !!! */ 926 if ((CurrentIntr & 0xffff) == 0xffff) /* error */ 927 CurrentIntr = 0; 928 929 /* check with the interrupt mask register */ 930 maskInterruptVal = pFwEvent->EventMask; 931 CurrentIntr &= maskInterruptVal; 932 if (interruptRegVal != CurrentIntr) 933 { 934 #ifdef DEBUG_INTERRUPTS_PRINT 935 WLAN_REPORT_ERROR(pFwEvent->hReport, 936 FW_EVENT_MODULE_LOG, 937 ("%s(%d) - interrupt vector include masked interrupts\n.\ 938 interruptRegVal = 0x%08X\n\ 939 hwMaskInterruptVal= 0x%08X\n\ 940 swMaskInterruptVal= 0x%08X\n\ 941 currrentInt = 0x%08X\n\ 942 diverse = 0x%08X\n\ 943 IntrState = %d\n", 944 __FILE__,__LINE__, 945 interruptRegVal, 946 maskInterruptVal, 947 pFwEvent->EventMask, 948 CurrentIntr, 949 (CurrentIntr ^ interruptRegVal), 950 pFwEvent->IntrState)); 951 #endif /* DEBUG_INTERRUPTS_PRINT */ 952 } 953 954 #ifdef ACK_ON_CHECK_PHASE 955 /* set ACK to the interrupts on the check phase */ 956 if (CurrentIntr != 0) 957 { 958 /* Save the occurring interrupts - to handle interrupt routine */ 959 pFwEvent->SaveIntrValue |= CurrentIntr; 960 HW_INTR_ACK(pFwEvent->hTNETWIF, CurrentIntr); 961 /* 962 state is now wait for DPC 963 */ 964 pFwEvent->IntrState = STATE_WAIT_FOR_DPC; 965 } 966 #endif /* ACK_ON_CHECK_PHASE */ 967 968 #ifdef DEBUG_INTERRUPTS_PRINT 969 970 TNETWIF_ReadRegSync (pFwEvent->hTNETWIF, ACX_REG_INTERRUPT_NO_CLEAR, &endReg); 971 WLAN_REPORT_INFORMATION(pFwEvent->hReport, 972 FW_EVENT_MODULE_LOG, 973 ("%s(%d) - finish ISR ,endReg... \n.\ 974 Intr = 0x%08X\n", 975 __FILE__,__LINE__, 976 endReg)); 977 #endif /* DEBUG_INTERRUPTS_PRINT */ 978 979 #ifdef HW_ACCESS_DEBUG_ACCESS_VIOLATION 980 whal_hwAccess_setOverrideElpCheck ((TI_HANDLE)pFwEvent->hTNETWIF, FALSE); 981 #endif /* HW_ACCESS_DEBUG_ACCESS_VIOLATION */ 982 983 /* (!!!1150) Reset the interrupt line*/ 984 TNETWIF_WriteRegSync (pFwEvent->hTNETWIF, PCI_STATUS_CLR_REG, 0x80000000 /*v2p_intr was asserted*/); 985 986 return CurrentIntr; 987 988 #else 989 990 return 0; 991 992 #endif /* USE_SYNC_API */ 993 } 994 995 996 /**************************************************************************** 997 * FwEvent_ChangeState() 998 **************************************************************************** 999 * DESCRIPTION: Disable interrupts 1000 * 1001 * INPUTS: 1002 * 1003 * OUTPUT: None 1004 * 1005 * RETURNS: 1006 ****************************************************************************/ 1007 void FwEvent_ChangeState (TI_HANDLE hFwEvent, int State) 1008 { 1009 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 1010 1011 pFwEvent->IntrState = State; 1012 } 1013 1014 1015 /**************************************************************************** 1016 * FwEvent_StateChanged() 1017 **************************************************************************** 1018 * DESCRIPTION: 1019 * StateChanged - change mask notification and 1020 * interrupt acknowledge. Used for SDIO driver 1021 * 1022 * RETURNS: None 1023 ****************************************************************************/ 1024 void FwEvent_StateChanged (TI_HANDLE hFwEvent) 1025 { 1026 #ifdef USE_SYNC_API 1027 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 1028 1029 TNETWIF_WriteRegSync (pFwEvent->hTNETWIF, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_STATE_CHANGED); 1030 #endif 1031 } 1032 1033 /**************************************************************************** 1034 * FwEvent_Stop() 1035 **************************************************************************** 1036 * DESCRIPTION: Stop & reser FwEvent (called by the recovery) 1037 * 1038 * INPUTS: 1039 * hhFwEvent - FwEvent handle; 1040 * 1041 * OUTPUT: None 1042 * 1043 * RETURNS: None 1044 ****************************************************************************/ 1045 VOID FwEvent_Stop(TI_HANDLE hFwEvent) 1046 { 1047 FwEventObj_t *pFwEvent = (FwEventObj_t *)hFwEvent; 1048 1049 pFwEvent->FwEventState = FW_EVENT_STATE_IDLE; 1050 1051 /* Setting the RxControlAddr to 0 indicates that it shouldn't be used */ 1052 pFwEvent->RxControlAddr = 0; 1053 pFwEvent->uNumOfRxHandled = 0; 1054 /* Before reading the first Fw Rx counters act like there's no Rx. This is done for the init phase */ 1055 pFwEvent->uFwRxCounter = 0; 1056 1057 } /* FwEvent_Stop() */ 1058 1059