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 ****************************************************************************/
FwEvent_Create(TI_HANDLE hOs)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 ****************************************************************************/
FwEvent_Destroy(TI_HANDLE hFwEvent)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 ****************************************************************************/
FwEvent_Config(TI_HANDLE hFwEvent,TI_HANDLE hTnetwDrv)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 ****************************************************************************/
FwEvent_SetHwInfo(TI_HANDLE hFwEvent,ACXDataPathParamsResp_t * pDataPathParams)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 ****************************************************************************/
FwEvent_CallHandler(TI_HANDLE hFwEvent)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 ****************************************************************************/
FwEvent_StateMachine(TI_HANDLE hFwEvent,systemStatus_e rc)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 ****************************************************************************/
FwEvent(TI_HANDLE hFwEvent)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 ****************************************************************************/
FwEvent_BusReadyCB(TI_HANDLE hFwEvent,UINT8 module_id,TI_STATUS status)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 ****************************************************************************/
FwEvent_WriteMaskCB(TI_HANDLE hFwEvent,UINT8 moduleID,TI_STATUS status)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 ****************************************************************************/
FwEvent_WriteMuxCB(TI_HANDLE hFwEvent,UINT8 moduleID,TI_STATUS status)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 ****************************************************************************/
FwEvent_ReadRegCB(TI_HANDLE hFwEvent,UINT8 moduleID,TI_STATUS status)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 ****************************************************************************/
FwEvent_UpdateRxBits(TI_HANDLE hFwEvent)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 ****************************************************************************/
FwEvent_EventComplete(TI_HANDLE hFwEvent,systemStatus_e rc)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 ****************************************************************************/
FwEvent_Enable(TI_HANDLE hFwEvent,UINT32 uEventMask)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 ****************************************************************************/
FwEvent_Disable(TI_HANDLE hFwEvent,UINT32 uEventMask)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 ****************************************************************************/
FwEvent_GetEnabled(TI_HANDLE hFwEvent)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 ****************************************************************************/
FwEvent_EnableInterrupts(TI_HANDLE hFwEvent)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 ****************************************************************************/
FwEvent_DisableInterrupts(TI_HANDLE hFwEvent)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 ****************************************************************************/
FwEvent_CheckInterrupts(TI_HANDLE hFwEvent)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 ****************************************************************************/
FwEvent_ChangeState(TI_HANDLE hFwEvent,int State)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 ****************************************************************************/
FwEvent_StateChanged(TI_HANDLE hFwEvent)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 ****************************************************************************/
FwEvent_Stop(TI_HANDLE hFwEvent)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