1 /*
2 * TwIf.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 TwIf.c
36 * \brief The TWD bottom API towards the Txn-Queue.
37 *
38 * The TwIf module is the lowest WLAN-specific layer and presents a common interface to all Xfer modules.
39 * As such, it is responsible for the common functionalities related to device access, which includes:
40 * - transactions submission
41 * - interface power control
42 * - address translation (paging) when needed (depends on bus attributes).
43 * The TwIf has no OS, platform or bus type dependencies.
44 *
45 * \see TwIf.h, TxnQueue.c, TxnQueue.h
46 */
47
48 #define __FILE_ID__ FILE_ID_121
49 #include "tidef.h"
50 #include "report.h"
51 #include "context.h"
52 #include "timer.h"
53 #include "TxnDefs.h"
54 #include "TxnQueue.h"
55 #include "TwIf.h"
56 #include "TWDriver.h"
57
58
59 /************************************************************************
60 * Defines
61 ************************************************************************/
62 #define TXN_DONE_QUE_SIZE QUE_UNLIMITED_SIZE
63 #define PEND_RESTART_TIMEOUT 100 /* timeout in msec for completion of last DMA transaction during restart */
64
65 /* Values to write to the ELP register for sleep/awake */
66 #define ELP_CTRL_REG_SLEEP 0
67 #define ELP_CTRL_REG_AWAKE 1
68
69 /*
70 * Device interface-control registers addresses (at the end ot the 17-bit address space):
71 */
72 #define PARTITION_REGISTERS_ADDR (0x1FFC0) /* Four 32 bit register: */
73 /* Memory region size (0x1FFC0) */
74 /* Memory region base address (0x1FFC4) */
75 /* Registers region size (0x1FFC8) */
76 /* Registers region base address (0x1FFCC) */
77
78 #define ELP_CTRL_REG_ADDR (0x1FFFC) /* ELP control register address */
79
80
81
82 /************************************************************************
83 * Types
84 ************************************************************************/
85
86 /* TwIf SM States */
87 typedef enum
88 {
89 SM_STATE_AWAKE, /* HW is awake and Txn-Queue is running */
90 SM_STATE_SLEEP, /* HW is asleep and Txn-Queue is stopped */
91 SM_STATE_WAIT_HW /* Waiting for HW to wake up (after triggering it), Txn-Queue is stopped */
92 } ESmState;
93
94 /* TwIf SM Events */
95 typedef enum
96 {
97 SM_EVENT_START, /* Need to wake up the device to handle transactions */
98 SM_EVENT_HW_AVAILABLE, /* The device woke up */
99 SM_EVENT_SLEEP /* Need to let the device go to sleep */
100 } ESmEvent;
101
102 /* The addresses partitioning configuration Txn data */
103 typedef struct
104 {
105 TI_UINT32 uMemSize; /* The HW memory region size. */
106 TI_UINT32 uMemAddr; /* The HW memory region address. */
107 TI_UINT32 uRegSize; /* The HW registers region size. */
108 TI_UINT32 uRegAddr; /* The HW registers region address. */
109
110 } TPartitionTxnData;
111
112 /* The addresses partitioning configuration Txn */
113 typedef struct
114 {
115 TTxnStruct tHdr; /* The generic transaction structure */
116 TPartitionTxnData tData; /* The addresses partitioning configuration data */
117
118 } TPartitionTxn;
119
120 /* The addresses partitioning configuration Txn */
121 typedef struct
122 {
123 TTxnStruct tHdr; /* The generic transaction structure */
124 TI_UINT32 tData; /* The addresses partitioning configuration data for one register */
125
126 } TPartitionRegTxn;
127
128 /* The addresses partitioning configuration Txn */
129 typedef struct
130 {
131 TTxnStruct tHdr; /* The generic transaction structure */
132 TI_UINT8 uElpData; /* The value to write to the ELP register */
133
134 } TElpTxn;
135
136 /* The TwIf module Object */
137 typedef struct _TTwIfObj
138 {
139 /* Other modules handles */
140 TI_HANDLE hOs;
141 TI_HANDLE hReport;
142 TI_HANDLE hContext;
143 TI_HANDLE hTimer;
144 TI_HANDLE hTxnQ;
145
146 ESmState eState; /* SM current state */
147 TI_HANDLE hTxnDoneQueue; /* Queue for completed transactions not reported yet to the upper layer */
148 TI_UINT32 uContextId; /* The ID allocated to this module on registration to context module */
149 TFailureEventCb fErrCb; /* The upper layer CB function for error handling */
150 TI_HANDLE hErrCb; /* The CB function handle */
151 TRecoveryCb fRecoveryCb; /* The upper layer CB for restart complete */
152 TI_HANDLE hRecoveryCb; /* The CB function handle */
153 TI_UINT32 uAwakeReqCount; /* Increment on awake requests and decrement on sleep requests */
154 TI_UINT32 uPendingTxnCount;/* Count pending transactions (sent to TxnQ and not completed yet) */
155 TElpTxn tElpTxnSleep; /* Transaction structure for writing sleep to ELP register */
156 TElpTxn tElpTxnAwake; /* Transaction structure for writing awake to ELP register */
157
158 /* HW Addresses partitioning */
159 TI_UINT32 uMemAddr1; /* The HW memory region start address. */
160 TI_UINT32 uMemSize1; /* The HW memory region end address. */
161 TI_UINT32 uMemAddr2; /* The HW registers region start address. */
162 TI_UINT32 uMemSize2; /* The HW registers region end address. */
163 TI_UINT32 uMemAddr3; /* The INT Status registers region start address. */
164 TI_UINT32 uMemSize3; /* The INT Status registers region end address. */
165 TI_UINT32 uMemAddr4; /* The FW Status mem registers region start address. */
166
167
168 #ifdef TI_DBG
169 /* Debug counters */
170 TI_UINT32 uDbgCountAwake; /* Count calls to twIf_Awake */
171 TI_UINT32 uDbgCountSleep; /* Count calls to twIf_Sleep */
172 TI_UINT32 uDbgCountTxn; /* Count calls to twIf_SendTransaction (including TwIf internal Txns) */
173 TI_UINT32 uDbgCountTxnPending; /* Count transactions that returned PENDING */
174 TI_UINT32 uDbgCountTxnComplete;/* Count transactions that returned COMPLETE */
175 TI_UINT32 uDbgCountTxnDoneCb; /* Count calls to twIf_TxnDoneCb */
176 #endif
177
178 TI_BOOL bTxnDoneInRecovery; /* Indicate that current TxnDone is within recovery process */
179 TI_BOOL bPendRestartTimerRunning;/* Indicate that the restart guard timer is running */
180 TI_HANDLE hPendRestartTimer; /* The restart process guard timer */
181
182 } TTwIfObj;
183
184
185 /************************************************************************
186 * Internal functions prototypes
187 ************************************************************************/
188 static void twIf_WriteElpReg (TTwIfObj *pTwIf, TI_UINT32 uValue);
189 static void twIf_PartitionTxnDoneCb (TI_HANDLE hTwIf, void *hTxn);
190 static ETxnStatus twIf_SendTransaction (TTwIfObj *pTwIf, TTxnStruct *pTxn);
191 static void twIf_HandleSmEvent (TTwIfObj *pTwIf, ESmEvent eEvent);
192 static void twIf_TxnDoneCb (TI_HANDLE hTwIf, TTxnStruct *pTxn);
193 static void twIf_HandleTxnDone (TI_HANDLE hTwIf);
194 static void twIf_ClearTxnDoneQueue (TI_HANDLE hTwIf);
195 static void twIf_PendRestratTimeout (TI_HANDLE hTwIf, TI_BOOL bTwdInitOccured);
196
197
198 /************************************************************************
199 *
200 * Module functions implementation
201 *
202 ************************************************************************/
203
204 /**
205 * \fn twIf_Create
206 * \brief Create the module
207 *
208 * Allocate and clear the module's object.
209 *
210 * \note
211 * \param hOs - Handle to Os Abstraction Layer
212 * \return Handle of the allocated object, NULL if allocation failed
213 * \sa twIf_Destroy
214 */
twIf_Create(TI_HANDLE hOs)215 TI_HANDLE twIf_Create (TI_HANDLE hOs)
216 {
217 TI_HANDLE hTwIf;
218 TTwIfObj *pTwIf;
219
220 hTwIf = os_memoryAlloc (hOs, sizeof(TTwIfObj));
221 if (hTwIf == NULL)
222 return NULL;
223
224 pTwIf = (TTwIfObj *)hTwIf;
225
226 os_memoryZero (hOs, hTwIf, sizeof(TTwIfObj));
227
228 pTwIf->hOs = hOs;
229
230 return pTwIf;
231 }
232
233
234 /**
235 * \fn twIf_Destroy
236 * \brief Destroy the module.
237 *
238 * Unregister from TxnQ and free the TxnDone-queue and the module's object.
239 *
240 * \note
241 * \param The module's object
242 * \return TI_OK on success or TI_NOK on failure
243 * \sa twIf_Create
244 */
twIf_Destroy(TI_HANDLE hTwIf)245 TI_STATUS twIf_Destroy (TI_HANDLE hTwIf)
246 {
247 TTwIfObj *pTwIf = (TTwIfObj*)hTwIf;
248
249 if (pTwIf)
250 {
251 txnQ_Close (pTwIf->hTxnQ, TXN_FUNC_ID_WLAN);
252 if (pTwIf->hTxnDoneQueue)
253 {
254 que_Destroy (pTwIf->hTxnDoneQueue);
255 }
256 if (pTwIf->hPendRestartTimer)
257 {
258 tmr_DestroyTimer (pTwIf->hPendRestartTimer);
259 }
260 os_memoryFree (pTwIf->hOs, pTwIf, sizeof(TTwIfObj));
261 }
262 return TI_OK;
263 }
264
265
266 /**
267 * \fn twIf_Init
268 * \brief Init module
269 *
270 * - Init required handles and module variables
271 * - Create the TxnDone-queue
272 * - Register to TxnQ
273 * - Register to context module
274 *
275 * \note
276 * \param hTwIf - The module's object
277 * \param hXxx - Handles to other modules
278 * \param fRecoveryCb - Callback function for recovery completed after TxnDone
279 * \param hRecoveryCb - Handle for fRecoveryCb
280 * \return void
281 * \sa
282 */
twIf_Init(TI_HANDLE hTwIf,TI_HANDLE hReport,TI_HANDLE hContext,TI_HANDLE hTimer,TI_HANDLE hTxnQ,TRecoveryCb fRecoveryCb,TI_HANDLE hRecoveryCb)283 void twIf_Init (TI_HANDLE hTwIf,
284 TI_HANDLE hReport,
285 TI_HANDLE hContext,
286 TI_HANDLE hTimer,
287 TI_HANDLE hTxnQ,
288 TRecoveryCb fRecoveryCb,
289 TI_HANDLE hRecoveryCb)
290 {
291 TTwIfObj *pTwIf = (TTwIfObj*)hTwIf;
292 TI_UINT32 uNodeHeaderOffset;
293 TTxnStruct *pTxnHdr; /* The ELP transactions header (as used in the TxnQ API) */
294
295 pTwIf->hReport = hReport;
296 pTwIf->hContext = hContext;
297 pTwIf->hTimer = hTimer;
298 pTwIf->hTxnQ = hTxnQ;
299 pTwIf->fRecoveryCb = fRecoveryCb;
300 pTwIf->hRecoveryCb = hRecoveryCb;
301
302 /* Prepare ELP sleep transaction */
303 pTwIf->tElpTxnSleep.uElpData = ELP_CTRL_REG_SLEEP;
304 pTxnHdr = &(pTwIf->tElpTxnSleep.tHdr);
305 TXN_PARAM_SET(pTxnHdr, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
306 TXN_PARAM_SET_MORE(pTxnHdr, 0); /* Sleep is the last transaction! */
307 /* NOTE: Function id for single step will be replaced to 0 by the bus driver */
308 TXN_PARAM_SET_SINGLE_STEP(pTxnHdr, 1); /* ELP write is always single step (TxnQ is topped)! */
309 BUILD_TTxnStruct(pTxnHdr, ELP_CTRL_REG_ADDR, &(pTwIf->tElpTxnSleep.uElpData), sizeof(TI_UINT8), NULL, NULL)
310
311 /* Prepare ELP awake transaction */
312 pTwIf->tElpTxnAwake.uElpData = ELP_CTRL_REG_AWAKE;
313 pTxnHdr = &(pTwIf->tElpTxnAwake.tHdr);
314 TXN_PARAM_SET(pTxnHdr, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
315 TXN_PARAM_SET_MORE(pTxnHdr, 1);
316 /* NOTE: Function id for single step will be replaced to 0 by the bus driver */
317 TXN_PARAM_SET_SINGLE_STEP(pTxnHdr, 1); /* ELP write is always single step (TxnQ is topped)! */
318 BUILD_TTxnStruct(pTxnHdr, ELP_CTRL_REG_ADDR, &(pTwIf->tElpTxnAwake.uElpData), sizeof(TI_UINT8), NULL, NULL)
319
320 /* Create the TxnDone queue. */
321 uNodeHeaderOffset = TI_FIELD_OFFSET(TTxnStruct, tTxnQNode);
322 pTwIf->hTxnDoneQueue = que_Create (pTwIf->hOs, pTwIf->hReport, TXN_DONE_QUE_SIZE, uNodeHeaderOffset);
323 if (pTwIf->hTxnDoneQueue == NULL)
324 {
325 TRACE0(pTwIf->hReport, REPORT_SEVERITY_ERROR, "twIf_Init: TxnDone queue creation failed!\n");
326 }
327
328 /* Register to the context engine and get the client ID */
329 pTwIf->uContextId = context_RegisterClient (pTwIf->hContext,
330 twIf_HandleTxnDone,
331 hTwIf,
332 TI_TRUE,
333 "TWIF",
334 sizeof("TWIF"));
335
336 /* Allocate timer */
337 pTwIf->hPendRestartTimer = tmr_CreateTimer (hTimer);
338 if (pTwIf->hPendRestartTimer == NULL)
339 {
340 TRACE0(pTwIf->hReport, REPORT_SEVERITY_ERROR, "twIf_Init: Failed to create PendRestartTimer!\n");
341 return;
342 }
343 pTwIf->bPendRestartTimerRunning = TI_FALSE;
344
345 /* Register to TxnQ */
346 txnQ_Open (pTwIf->hTxnQ, TXN_FUNC_ID_WLAN, TXN_NUM_PRIORITYS, (TTxnQueueDoneCb)twIf_TxnDoneCb, hTwIf);
347
348 /* Restart TwIf and TxnQ modules */
349 twIf_Restart (hTwIf);
350 }
351
352
353 /**
354 * \fn twIf_Restart
355 * \brief Restart module upon driver stop or recovery
356 *
357 * Called upon driver stop command or upon recovery.
358 * Calls txnQ_Restart to clear the WLAN queues and call the TxnDone CB on each tansaction.
359 * If no transaction in progress, the queues are cleared immediately.
360 * If a transaction is in progress, it is done upon TxnDone.
361 * The status in transactions that were dropped due to restart is TXN_STATUS_RECOVERY,
362 * and its originator (Xfer module) handles it if required (if its CB was written in the Txn).
363 *
364 * \note
365 * \param hTwIf - The module's object
366 * \return COMPLETE if the WLAN queues were restarted, PENDING if waiting for TxnDone to restart queues
367 * \sa
368 */
twIf_Restart(TI_HANDLE hTwIf)369 ETxnStatus twIf_Restart (TI_HANDLE hTwIf)
370 {
371 TTwIfObj *pTwIf = (TTwIfObj*)hTwIf;
372 ETxnStatus eStatus;
373
374 pTwIf->eState = SM_STATE_SLEEP;
375 pTwIf->uAwakeReqCount = 0;
376
377 pTwIf->uPendingTxnCount = 0;
378
379 /* Clear done queue */
380 twIf_ClearTxnDoneQueue(hTwIf);
381
382 /* Restart WLAN queues */
383 eStatus = txnQ_Restart (pTwIf->hTxnQ, TXN_FUNC_ID_WLAN);
384
385 /* If pending upon ongoing transaction, start guard timer in case SDIO does not call us back */
386 if (eStatus == TXN_STATUS_PENDING)
387 {
388 pTwIf->bPendRestartTimerRunning = TI_TRUE;
389 tmr_StartTimer (pTwIf->hPendRestartTimer, twIf_PendRestratTimeout, hTwIf, PEND_RESTART_TIMEOUT, TI_FALSE);
390 }
391
392 /* Return result (COMPLETE if completed or PENDING if will be completed in TxnDone context) */
393 return eStatus;
394 }
395
396
397 /**
398 * \fn twIf_RegisterErrCb
399 * \brief Register Error CB
400 *
401 * Register upper layer (health monitor) CB for bus error
402 *
403 * \note
404 * \param hTwIf - The module's object
405 * \param fErrCb - The upper layer CB function for error handling
406 * \param hErrCb - The CB function handle
407 * \return void
408 * \sa
409 */
twIf_RegisterErrCb(TI_HANDLE hTwIf,void * fErrCb,TI_HANDLE hErrCb)410 void twIf_RegisterErrCb (TI_HANDLE hTwIf, void *fErrCb, TI_HANDLE hErrCb)
411 {
412 TTwIfObj *pTwIf = (TTwIfObj*) hTwIf;
413
414 /* Save upper layer (health monitor) CB for bus error */
415 pTwIf->fErrCb = (TFailureEventCb)fErrCb;
416 pTwIf->hErrCb = hErrCb;
417 }
418
419
420 /**
421 * \fn twIf_WriteElpReg
422 * \brief write ELP register
423 *
424 * \note
425 * \param pTwIf - The module's object
426 * \param uValue - ELP_CTRL_REG_SLEEP or ELP_CTRL_REG_AWAKE
427 * \return void
428 * \sa
429 */
twIf_WriteElpReg(TTwIfObj * pTwIf,TI_UINT32 uValue)430 static void twIf_WriteElpReg (TTwIfObj *pTwIf, TI_UINT32 uValue)
431 {
432 TRACE1(pTwIf->hReport, REPORT_SEVERITY_INFORMATION, "twIf_WriteElpReg: ELP Txn data = 0x%x\n", uValue);
433 /* Send ELP (awake or sleep) transaction to TxnQ */
434 if (uValue == ELP_CTRL_REG_AWAKE)
435 {
436 txnQ_Transact (pTwIf->hTxnQ, &(pTwIf->tElpTxnAwake.tHdr));
437 }
438 else
439 {
440 txnQ_Transact (pTwIf->hTxnQ, &(pTwIf->tElpTxnSleep.tHdr));
441 }
442 }
443
444
445 /**
446 * \fn twIf_SetPartition
447 * \brief Set HW addresses partition
448 *
449 * Called by the HwInit module to set the HW address ranges for download or working access.
450 * Generate and configure the bus access address mapping table.
451 * The partition is split between register (fixed partition of 24KB size, exists in all modes),
452 * and memory (dynamically changed during init and gets constant value in run-time, 104KB size).
453 * The TwIf configures the memory mapping table on the device by issuing write transaction to
454 * table address (note that the TxnQ and bus driver see this as a regular transaction).
455 *
456 * \note In future versions, a specific bus may not support partitioning (as in wUART),
457 * In this case the HwInit module shall not call this function (will learn the bus
458 * configuration from the INI file).
459 *
460 * \param hTwIf - The module's object
461 * \param uMemAddr - The memory partition base address
462 * \param uMemSize - The memory partition size
463 * \param uRegAddr - The registers partition base address
464 * \param uRegSize - The register partition size
465 * \return void
466 * \sa
467 */
468
twIf_SetPartition(TI_HANDLE hTwIf,TPartition * pPartition)469 void twIf_SetPartition (TI_HANDLE hTwIf,
470 TPartition *pPartition)
471 {
472 TTwIfObj *pTwIf = (TTwIfObj*) hTwIf;
473 TPartitionRegTxn *pPartitionRegTxn;/* The partition transaction structure for one register */
474 TTxnStruct *pTxnHdr; /* The partition transaction header (as used in the TxnQ API) */
475 ETxnStatus eStatus;
476 int i;
477
478 /* Save partition information for translation and validation. */
479 pTwIf->uMemAddr1 = pPartition[0].uMemAdrr;
480 pTwIf->uMemSize1 = pPartition[0].uMemSize;
481 pTwIf->uMemAddr2 = pPartition[1].uMemAdrr;
482 pTwIf->uMemSize2 = pPartition[1].uMemSize;
483 pTwIf->uMemAddr3 = pPartition[2].uMemAdrr;
484 pTwIf->uMemSize3 = pPartition[2].uMemSize;
485 pTwIf->uMemAddr4 = pPartition[3].uMemAdrr;
486
487 /* Allocate memory for the current 4 partition transactions */
488 pPartitionRegTxn = (TPartitionRegTxn *) os_memoryAlloc (pTwIf->hOs, 7*sizeof(TPartitionRegTxn));
489 pTxnHdr = &(pPartitionRegTxn->tHdr);
490
491 /* Zero the allocated memory to be certain that unused fields will be initialized */
492 os_memoryZero(pTwIf->hOs, pPartitionRegTxn, 7*sizeof(TPartitionRegTxn));
493
494 /* Prepare partition transaction data */
495 pPartitionRegTxn[0].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemAddr1);
496 pPartitionRegTxn[1].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemSize1);
497 pPartitionRegTxn[2].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemAddr2);
498 pPartitionRegTxn[3].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemSize2);
499 pPartitionRegTxn[4].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemAddr3);
500 pPartitionRegTxn[5].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemSize3);
501 pPartitionRegTxn[6].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemAddr4);
502
503
504 /* Prepare partition Txn header */
505 for (i=0; i<7; i++)
506 {
507 pTxnHdr = &(pPartitionRegTxn[i].tHdr);
508 TXN_PARAM_SET(pTxnHdr, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
509 TXN_PARAM_SET_MORE(pTxnHdr, 1);
510 TXN_PARAM_SET_SINGLE_STEP(pTxnHdr, 0);
511 }
512
513
514 /* Memory address */
515 pTxnHdr = &(pPartitionRegTxn[0].tHdr);
516 BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR+4, &(pPartitionRegTxn[0].tData), REGISTER_SIZE, 0, 0)
517 twIf_SendTransaction (pTwIf, pTxnHdr);
518
519 /* Memory size */
520 pTxnHdr = &(pPartitionRegTxn[1].tHdr);
521 BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR+0, &(pPartitionRegTxn[1].tData), REGISTER_SIZE, 0, 0)
522 twIf_SendTransaction (pTwIf, pTxnHdr);
523
524 /* Registers address */
525 pTxnHdr = &(pPartitionRegTxn[2].tHdr);
526 BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR+12, &(pPartitionRegTxn[2].tData), REGISTER_SIZE, 0, 0)
527 twIf_SendTransaction (pTwIf, pTxnHdr);
528
529 /* Registers size */
530 pTxnHdr = &(pPartitionRegTxn[3].tHdr);
531 BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR+8, &(pPartitionRegTxn[3].tData), REGISTER_SIZE, 0, 0)
532 eStatus = twIf_SendTransaction (pTwIf, pTxnHdr);
533
534 /* Registers address */
535 pTxnHdr = &(pPartitionRegTxn[4].tHdr);
536 BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR+20, &(pPartitionRegTxn[4].tData), REGISTER_SIZE, 0, 0)
537 twIf_SendTransaction (pTwIf, pTxnHdr);
538
539 /* Registers size */
540 pTxnHdr = &(pPartitionRegTxn[5].tHdr);
541 BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR+16, &(pPartitionRegTxn[5].tData), REGISTER_SIZE, 0, 0)
542 eStatus = twIf_SendTransaction (pTwIf, pTxnHdr);
543
544 /* Registers address */
545 pTxnHdr = &(pPartitionRegTxn[6].tHdr);
546 BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR+24, &(pPartitionRegTxn[6].tData), REGISTER_SIZE, twIf_PartitionTxnDoneCb, pTwIf)
547 twIf_SendTransaction (pTwIf, pTxnHdr);
548
549 /* If the transaction is done, free the allocated memory (otherwise freed in the partition CB) */
550 if (eStatus != TXN_STATUS_PENDING)
551 {
552 os_memoryFree (pTwIf->hOs, pPartitionRegTxn,7*sizeof(TPartitionRegTxn));
553 }
554 }
555
556
twIf_PartitionTxnDoneCb(TI_HANDLE hTwIf,void * hTxn)557 static void twIf_PartitionTxnDoneCb (TI_HANDLE hTwIf, void *hTxn)
558 {
559 TTwIfObj *pTwIf = (TTwIfObj*) hTwIf;
560
561 /* Free the partition transaction buffer after completed (see transaction above) */
562 os_memoryFree (pTwIf->hOs,
563 (char *)hTxn - (6 * sizeof(TPartitionRegTxn)), /* Move back to the first Txn start */
564 7 * sizeof(TPartitionRegTxn));
565 }
566
567
568 /**
569 * \fn twIf_Awake
570 * \brief Request to keep the device awake
571 *
572 * Used by the Xfer modules to request to keep the device awake until twIf_Sleep() is called.
573 * Each call to this function increments AwakeReq counter. Once the device is awake (upon transaction),
574 * the TwIf SM keeps it awake as long as this counter is not zero.
575 *
576 * \note
577 * \param hTwIf - The module's object
578 * \return void
579 * \sa twIf_Sleep
580 */
twIf_Awake(TI_HANDLE hTwIf)581 void twIf_Awake (TI_HANDLE hTwIf)
582 {
583 TTwIfObj *pTwIf = (TTwIfObj*) hTwIf;
584
585 /* Increment awake requests counter */
586 pTwIf->uAwakeReqCount++;
587
588 #ifdef TI_DBG
589 pTwIf->uDbgCountAwake++;
590 TRACE1(pTwIf->hReport, REPORT_SEVERITY_INFORMATION, "twIf_Awake: uAwakeReqCount = %d\n", pTwIf->uAwakeReqCount);
591 #endif
592 }
593
594
595 /**
596 * \fn twIf_Sleep
597 * \brief Remove request to keep the device awake
598 *
599 * Each call to this function decrements AwakeReq counter.
600 * Once this counter is zeroed, if the TxnQ is empty (no WLAN transactions), the TwIf SM is
601 * invoked to stop the TxnQ and enable the device to sleep (write 0 to ELP register).
602 *
603 * \note
604 * \param hTwIf - The module's object
605 * \return void
606 * \sa twIf_Awake
607 */
twIf_Sleep(TI_HANDLE hTwIf)608 void twIf_Sleep (TI_HANDLE hTwIf)
609 {
610 TTwIfObj *pTwIf = (TTwIfObj*) hTwIf;
611
612 /* Decrement awake requests counter */
613 if (pTwIf->uAwakeReqCount > 0) /* in case of redundant call after recovery */
614 {
615 pTwIf->uAwakeReqCount--;
616 }
617
618 #ifdef TI_DBG
619 pTwIf->uDbgCountSleep++;
620 TRACE1(pTwIf->hReport, REPORT_SEVERITY_INFORMATION, "twIf_Sleep: uAwakeReqCount = %d\n", pTwIf->uAwakeReqCount);
621 #endif
622
623 /* If Awake not required and no pending transactions in TxnQ, issue Sleep event to SM */
624 if ((pTwIf->uAwakeReqCount == 0) && (pTwIf->uPendingTxnCount == 0))
625 {
626 twIf_HandleSmEvent (pTwIf, SM_EVENT_SLEEP);
627 }
628 }
629
630
631 /**
632 * \fn twIf_HwAvailable
633 * \brief The device is awake
634 *
635 * This is an indication from the FwEvent that the device is awake.
636 * Issue HW_AVAILABLE event to the SM.
637 *
638 * \note
639 * \param hTwIf - The module's object
640 * \return void
641 * \sa
642 */
twIf_HwAvailable(TI_HANDLE hTwIf)643 void twIf_HwAvailable (TI_HANDLE hTwIf)
644 {
645 TTwIfObj *pTwIf = (TTwIfObj*) hTwIf;
646
647 TRACE0(pTwIf->hReport, REPORT_SEVERITY_INFORMATION, "twIf_HwAvailable: HW is Available\n");
648
649 /* Issue HW_AVAILABLE event to the SM */
650 twIf_HandleSmEvent (pTwIf, SM_EVENT_HW_AVAILABLE);
651 }
652
653
654 /**
655 * \fn twIf_Transact
656 * \brief Issue a transaction
657 *
658 * This method is used by the Xfer modules to issue all transaction types.
659 * Translate HW address according to bus partition and call twIf_SendTransaction().
660 *
661 * \note
662 * \param hTwIf - The module's object
663 * \param pTxn - The transaction object
664 * \return COMPLETE if the transaction was completed in this context, PENDING if not, ERROR if failed
665 * \sa twIf_SendTransaction
666 */
twIf_Transact(TI_HANDLE hTwIf,TTxnStruct * pTxn)667 ETxnStatus twIf_Transact (TI_HANDLE hTwIf, TTxnStruct *pTxn)
668 {
669 TTwIfObj *pTwIf = (TTwIfObj*)hTwIf;
670
671 /* Translate HW address for registers region */
672 if ((pTxn->uHwAddr >= pTwIf->uMemAddr2) && (pTxn->uHwAddr <= pTwIf->uMemAddr2 + pTwIf->uMemSize2))
673 {
674 pTxn->uHwAddr = pTxn->uHwAddr - pTwIf->uMemAddr2 + pTwIf->uMemSize1;
675 }
676 /* Translate HW address for memory region */
677 else
678 {
679 pTxn->uHwAddr = pTxn->uHwAddr - pTwIf->uMemAddr1;
680 }
681
682 /* Regular transaction are not the last and are not single step (only ELP write is) */
683 TXN_PARAM_SET_MORE(pTxn, 1);
684 TXN_PARAM_SET_SINGLE_STEP(pTxn, 0);
685
686 /* Send the transaction to the TxnQ and update the SM if needed. */
687 return twIf_SendTransaction (pTwIf, pTxn);
688 }
689
twIf_TransactReadFWStatus(TI_HANDLE hTwIf,TTxnStruct * pTxn)690 ETxnStatus twIf_TransactReadFWStatus (TI_HANDLE hTwIf, TTxnStruct *pTxn)
691 {
692 TTwIfObj *pTwIf = (TTwIfObj*)hTwIf;
693
694 /* Regular transaction are not the last and are not single step (only ELP write is) */
695 TXN_PARAM_SET_MORE(pTxn, 1);
696 TXN_PARAM_SET_SINGLE_STEP(pTxn, 0);
697
698 /* Send the transaction to the TxnQ and update the SM if needed. */
699 return twIf_SendTransaction (pTwIf, pTxn);
700 }
701
702
703 /**
704 * \fn twIf_SendTransaction
705 * \brief Send a transaction to the device
706 *
707 * This method is used by the Xfer modules and the TwIf to send all transaction types to the device.
708 * Send the transaction to the TxnQ and update the SM if needed.
709 *
710 * \note
711 * \param pTwIf - The module's object
712 * \param pTxn - The transaction object
713 * \return COMPLETE if the transaction was completed in this context, PENDING if not, ERROR if failed
714 * \sa
715 */
twIf_SendTransaction(TTwIfObj * pTwIf,TTxnStruct * pTxn)716 static ETxnStatus twIf_SendTransaction (TTwIfObj *pTwIf, TTxnStruct *pTxn)
717 {
718 ETxnStatus eStatus;
719 #ifdef TI_DBG
720 TI_UINT32 data = 0;
721
722 /* Verify that the Txn HW-Address is 4-bytes aligned */
723 if (pTxn->uHwAddr & 0x3)
724 {
725 TRACE2(pTwIf->hReport, REPORT_SEVERITY_ERROR, "twIf_SendTransaction: Unaligned HwAddr! HwAddr=0x%x, Params=0x%x\n", pTxn->uHwAddr, pTxn->uTxnParams);
726 return TXN_STATUS_ERROR;
727 }
728 #endif
729
730 context_EnterCriticalSection (pTwIf->hContext);
731 /* increment pending Txn counter */
732 pTwIf->uPendingTxnCount++;
733 context_LeaveCriticalSection (pTwIf->hContext);
734
735 /* Send transaction to TxnQ */
736 eStatus = txnQ_Transact(pTwIf->hTxnQ, pTxn);
737
738 #ifdef TI_DBG
739 pTwIf->uDbgCountTxn++;
740 if (eStatus == TXN_STATUS_COMPLETE) { pTwIf->uDbgCountTxnComplete++; }
741 else if (eStatus == TXN_STATUS_PENDING ) { pTwIf->uDbgCountTxnPending++; }
742
743 COPY_WLAN_LONG(&data,&(pTxn->aBuf[0]));
744 TRACE8(pTwIf->hReport, REPORT_SEVERITY_INFORMATION, "twIf_SendTransaction: Status = %d, Params=0x%x, HwAddr=0x%x, Len0=%d, Len1=%d, Len2=%d, Len3=%d, Data=0x%x \n", eStatus, pTxn->uTxnParams, pTxn->uHwAddr, pTxn->aLen[0], pTxn->aLen[1], pTxn->aLen[2], pTxn->aLen[3],data);
745 #endif
746
747 /* If Txn status is PENDING issue Start event to the SM */
748 if (eStatus == TXN_STATUS_PENDING)
749 {
750 twIf_HandleSmEvent (pTwIf, SM_EVENT_START);
751 }
752
753 /* Else (COMPLETE or ERROR) */
754 else
755 {
756 context_EnterCriticalSection (pTwIf->hContext);
757 /* decrement pending Txn counter in case of sync transact*/
758 pTwIf->uPendingTxnCount--;
759 context_LeaveCriticalSection (pTwIf->hContext);
760
761 /* If Awake not required and no pending transactions in TxnQ, issue Sleep event to SM */
762 if ((pTwIf->uAwakeReqCount == 0) && (pTwIf->uPendingTxnCount == 0))
763 {
764 twIf_HandleSmEvent (pTwIf, SM_EVENT_SLEEP);
765 }
766
767 /* If Txn failed and error CB available, call it to initiate recovery */
768 if (eStatus == TXN_STATUS_ERROR)
769 {
770 TRACE6(pTwIf->hReport, REPORT_SEVERITY_ERROR, "twIf_SendTransaction: Txn failed!! Params=0x%x, HwAddr=0x%x, Len0=%d, Len1=%d, Len2=%d, Len3=%d\n", pTxn->uTxnParams, pTxn->uHwAddr, pTxn->aLen[0], pTxn->aLen[1], pTxn->aLen[2], pTxn->aLen[3]);
771
772 if (pTwIf->fErrCb)
773 {
774 pTwIf->fErrCb (pTwIf->hErrCb, BUS_FAILURE);
775 }
776 }
777 }
778
779 /* Return the Txn status (COMPLETE if completed in this context, PENDING if not, ERROR if failed) */
780 return eStatus;
781 }
782
783 /**
784 * \fn twIf_HandleSmEvent
785 * \brief The TwIf SM implementation
786 *
787 * Handle SM event.
788 * Control the device awake/sleep states and the TxnQ run/stop states according to the event.
789 *
790 * \note
791 * \param hTwIf - The module's object
792 * \return void
793 * \sa
794 */
twIf_HandleSmEvent(TTwIfObj * pTwIf,ESmEvent eEvent)795 static void twIf_HandleSmEvent (TTwIfObj *pTwIf, ESmEvent eEvent)
796 {
797 ESmState eState = pTwIf->eState; /* The state before handling the event */
798
799 /* Switch by current state and handle event */
800 switch (eState)
801 {
802 case SM_STATE_AWAKE:
803 /* SLEEP event: AWAKE ==> SLEEP, stop TxnQ and set ELP reg to sleep */
804 if (eEvent == SM_EVENT_SLEEP)
805 {
806 pTwIf->eState = SM_STATE_SLEEP;
807 txnQ_Stop (pTwIf->hTxnQ, TXN_FUNC_ID_WLAN);
808 twIf_WriteElpReg (pTwIf, ELP_CTRL_REG_SLEEP);
809 }
810 break;
811 case SM_STATE_SLEEP:
812 /* START event: SLEEP ==> WAIT_HW, set ELP reg to wake-up */
813 if (eEvent == SM_EVENT_START)
814 {
815 pTwIf->eState = SM_STATE_WAIT_HW;
816 twIf_WriteElpReg (pTwIf, ELP_CTRL_REG_AWAKE);
817 }
818 /* HW_AVAILABLE event: SLEEP ==> AWAKE, set ELP reg to wake-up and run TxnQ */
819 else if (eEvent == SM_EVENT_HW_AVAILABLE)
820 {
821 pTwIf->eState = SM_STATE_AWAKE;
822 twIf_WriteElpReg (pTwIf, ELP_CTRL_REG_AWAKE);
823 txnQ_Run (pTwIf->hTxnQ, TXN_FUNC_ID_WLAN);
824 }
825 break;
826 case SM_STATE_WAIT_HW:
827 /* HW_AVAILABLE event: WAIT_HW ==> AWAKE, run TxnQ */
828 if (eEvent == SM_EVENT_HW_AVAILABLE)
829 {
830 pTwIf->eState = SM_STATE_AWAKE;
831 txnQ_Run (pTwIf->hTxnQ, TXN_FUNC_ID_WLAN);
832 }
833 break;
834 }
835
836 TRACE3(pTwIf->hReport, REPORT_SEVERITY_INFORMATION, "twIf_HandleSmEvent: <currentState = %d, event = %d> --> nextState = %d\n", eState, eEvent, pTwIf->eState);
837 }
838
839
840 /**
841 * \fn twIf_TxnDoneCb
842 * \brief Transaction completion CB
843 *
844 * This callback is called by the TxnQ upon transaction completion, unless is was completed in
845 * the original context where it was issued.
846 * It may be called from bus driver external context (TxnDone ISR) or from WLAN driver context.
847 *
848 * \note
849 * \param hTwIf - The module's object
850 * \param pTxn - The completed transaction object
851 * \return void
852 * \sa twIf_HandleTxnDone
853 */
twIf_TxnDoneCb(TI_HANDLE hTwIf,TTxnStruct * pTxn)854 static void twIf_TxnDoneCb (TI_HANDLE hTwIf, TTxnStruct *pTxn)
855 {
856 TTwIfObj *pTwIf = (TTwIfObj*)hTwIf;
857
858 #ifdef TI_DBG
859 pTwIf->uDbgCountTxnDoneCb++;
860 TRACE6(pTwIf->hReport, REPORT_SEVERITY_INFORMATION, "twIf_TxnDoneCb: Params=0x%x, HwAddr=0x%x, Len0=%d, Len1=%d, Len2=%d, Len3=%d\n", pTxn->uTxnParams, pTxn->uHwAddr, pTxn->aLen[0], pTxn->aLen[1], pTxn->aLen[2], pTxn->aLen[3]);
861 #endif
862
863 /* In case of recovery flag, Call directly restart callback */
864 if (TXN_PARAM_GET_STATUS(pTxn) == TXN_PARAM_STATUS_RECOVERY)
865 {
866 if (pTwIf->fRecoveryCb)
867 {
868 TRACE0(pTwIf->hReport, REPORT_SEVERITY_INFORMATION, "twIf_TxnDoneCb: During Recovery\n");
869 pTwIf->bTxnDoneInRecovery = TI_TRUE;
870 /* Request schedule to continue handling in driver context (will call twIf_HandleTxnDone()) */
871 context_RequestSchedule (pTwIf->hContext, pTwIf->uContextId);
872 return;
873 }
874 }
875
876 /* If the completed Txn is ELP, nothing to do (not counted) so exit */
877 if (TXN_PARAM_GET_SINGLE_STEP(pTxn))
878 {
879 return;
880 }
881
882 if (pTxn->fTxnDoneCb)
883 {
884 TI_STATUS eStatus;
885
886 /* In critical section, enqueue the completed transaction in the TxnDoneQ. */
887 context_EnterCriticalSection (pTwIf->hContext);
888 eStatus = que_Enqueue (pTwIf->hTxnDoneQueue, (TI_HANDLE)pTxn);
889 if (eStatus != TI_OK)
890 {
891 TRACE3(pTwIf->hReport, REPORT_SEVERITY_ERROR, "twIf_TxnDoneCb(): Enqueue failed, pTxn=0x%x, HwAddr=0x%x, Len0=%d\n", pTxn, pTxn->uHwAddr, pTxn->aLen[0]);
892 }
893 context_LeaveCriticalSection (pTwIf->hContext);
894 }
895 else
896 {
897 context_EnterCriticalSection (pTwIf->hContext);
898 /* Decrement pending Txn counter, It's value will be checked in twIf_HandleTxnDone() */
899 if (pTwIf->uPendingTxnCount > 0) /* in case of callback on recovery after restart */
900 {
901 pTwIf->uPendingTxnCount--;
902 }
903 context_LeaveCriticalSection (pTwIf->hContext);
904
905 }
906
907 /* Request schedule to continue handling in driver context (will call twIf_HandleTxnDone()) */
908 context_RequestSchedule (pTwIf->hContext, pTwIf->uContextId);
909 }
910
911 /**
912 * \fn twIf_HandleTxnDone
913 * \brief Completed transactions handler
914 *
915 * The completed transactions handler, called upon TxnDone event, either from the context engine
916 * or directly from twIf_TxnDoneCb() if we are already in the WLAN driver's context.
917 * Dequeue all completed transactions in critical section, and call their callbacks if available.
918 * If awake is not required and no pending transactions in TxnQ, issue Sleep event to SM.
919 *
920 * \note
921 * \param hTwIf - The module's object
922 * \return void
923 * \sa
924 */
twIf_HandleTxnDone(TI_HANDLE hTwIf)925 static void twIf_HandleTxnDone (TI_HANDLE hTwIf)
926 {
927 TTwIfObj *pTwIf = (TTwIfObj*)hTwIf;
928 TTxnStruct *pTxn;
929
930 /* In case of recovery, call the recovery callback and exit */
931 if (pTwIf->bTxnDoneInRecovery)
932 {
933 TRACE0(pTwIf->hReport, REPORT_SEVERITY_INFORMATION, "twIf_HandleTxnDone: call RecoveryCb\n");
934 pTwIf->bTxnDoneInRecovery = TI_FALSE;
935 if (pTwIf->bPendRestartTimerRunning)
936 {
937 tmr_StopTimer (pTwIf->hPendRestartTimer);
938 pTwIf->bPendRestartTimerRunning = TI_FALSE;
939 }
940 pTwIf->fRecoveryCb(pTwIf->hRecoveryCb);
941 return;
942 }
943
944 /* Loop while there are completed transactions to handle */
945 while (1)
946 {
947 /* In critical section, dequeue completed transaction from the TxnDoneQ. */
948 context_EnterCriticalSection (pTwIf->hContext);
949 pTxn = (TTxnStruct *) que_Dequeue (pTwIf->hTxnDoneQueue);
950 context_LeaveCriticalSection (pTwIf->hContext);
951
952 /* If no more transactions to handle, exit */
953 if (pTxn != NULL)
954 {
955 context_EnterCriticalSection (pTwIf->hContext);
956 /* Decrement pending Txn counter */
957 if (pTwIf->uPendingTxnCount > 0) /* in case of callback on recovery after restart */
958 {
959 pTwIf->uPendingTxnCount--;
960 }
961 context_LeaveCriticalSection (pTwIf->hContext);
962
963 TRACE4(pTwIf->hReport, REPORT_SEVERITY_INFORMATION, "twIf_HandleTxnDone: Completed-Txn: Params=0x%x, HwAddr=0x%x, Len0=%d, fTxnDoneCb=0x%x\n", pTxn->uTxnParams, pTxn->uHwAddr, pTxn->aLen[0], pTxn->fTxnDoneCb);
964
965 /* If Txn failed and error CB available, call it to initiate recovery */
966 if (TXN_PARAM_GET_STATUS(pTxn) == TXN_PARAM_STATUS_ERROR)
967 {
968 TRACE6(pTwIf->hReport, REPORT_SEVERITY_ERROR, "twIf_HandleTxnDone: Txn failed!! Params=0x%x, HwAddr=0x%x, Len0=%d, Len1=%d, Len2=%d, Len3=%d\n", pTxn->uTxnParams, pTxn->uHwAddr, pTxn->aLen[0], pTxn->aLen[1], pTxn->aLen[2], pTxn->aLen[3]);
969
970 if (pTwIf->fErrCb)
971 {
972 pTwIf->fErrCb (pTwIf->hErrCb, BUS_FAILURE);
973 }
974 /* in error do not continue */
975 return;
976 }
977
978 /* If Txn specific CB available, call it (may free Txn resources and issue new Txns) */
979 if (pTxn->fTxnDoneCb != NULL)
980 {
981 ((TTxnDoneCb)(pTxn->fTxnDoneCb)) (pTxn->hCbHandle, pTxn);
982 }
983 }
984
985 /*If uPendingTxnCount == 0 and awake not required, issue Sleep event to SM */
986 if ((pTwIf->uAwakeReqCount == 0) && (pTwIf->uPendingTxnCount == 0))
987 {
988 twIf_HandleSmEvent (pTwIf, SM_EVENT_SLEEP);
989 }
990
991 if (pTxn == NULL)
992 {
993 return;
994 }
995 }
996 }
997
998 /**
999 * \fn twIf_ClearTxnDoneQueue
1000 * \brief Clean the DoneQueue
1001 *
1002 * Clear the specified done queue - don't call the callbacks.
1003 *
1004 * \note
1005 * \param hTwIf - The module's object
1006 * \return void
1007 * \sa
1008 */
twIf_ClearTxnDoneQueue(TI_HANDLE hTwIf)1009 static void twIf_ClearTxnDoneQueue (TI_HANDLE hTwIf)
1010 {
1011 TTwIfObj *pTwIf = (TTwIfObj*)hTwIf;
1012 TTxnStruct *pTxn;
1013
1014 /* Loop while there are completed transactions to handle */
1015 while (1)
1016 {
1017 /* In critical section, dequeue completed transaction from the TxnDoneQ. */
1018 context_EnterCriticalSection (pTwIf->hContext);
1019 pTxn = (TTxnStruct *) que_Dequeue (pTwIf->hTxnDoneQueue);
1020 context_LeaveCriticalSection (pTwIf->hContext);
1021
1022 /* If no more transactions to handle, exit */
1023 if (pTxn != NULL)
1024 {
1025 /* Decrement pending Txn counter */
1026 if (pTwIf->uPendingTxnCount > 0) /* in case of callback on recovery after restart */
1027 {
1028 pTwIf->uPendingTxnCount--;
1029 }
1030
1031 /*
1032 * Drop on Recovery
1033 * do not call pTxn->fTxnDoneCb (pTxn->hCbHandle, pTxn) callback
1034 */
1035 }
1036
1037 if (pTxn == NULL)
1038 {
1039 return;
1040 }
1041 }
1042 }
1043
1044
1045 /**
1046 * \fn twIf_PendRestratTimeout
1047 * \brief Pending restart process timeout handler
1048 *
1049 * Called if timer expires upon fail to complete the last bus transaction that was
1050 * pending during restart process.
1051 * Calls the recovery callback to continue the restart process.
1052 *
1053 * \note
1054 * \param hTwIf - The module's object
1055 * \return void
1056 * \sa
1057 */
twIf_PendRestratTimeout(TI_HANDLE hTwIf,TI_BOOL bTwdInitOccured)1058 static void twIf_PendRestratTimeout (TI_HANDLE hTwIf, TI_BOOL bTwdInitOccured)
1059 {
1060 TTwIfObj *pTwIf = (TTwIfObj*)hTwIf;
1061
1062 TRACE0(pTwIf->hReport, REPORT_SEVERITY_ERROR, "twIf_PendRestratTimeout: restart timer expired!\n");
1063
1064 pTwIf->bPendRestartTimerRunning = TI_FALSE;
1065
1066 /* Clear the Txn queues since TxnDone wasn't called so it wasn't done by the TxnQ module */
1067 txnQ_ClearQueues (pTwIf->hTxnQ, TXN_FUNC_ID_WLAN);
1068
1069 /* Call the recovery callback to continue the restart process */
1070 pTwIf->fRecoveryCb(pTwIf->hRecoveryCb);
1071 }
1072
1073
twIf_isValidMemoryAddr(TI_HANDLE hTwIf,TI_UINT32 Address,TI_UINT32 Length)1074 TI_BOOL twIf_isValidMemoryAddr(TI_HANDLE hTwIf, TI_UINT32 Address, TI_UINT32 Length)
1075 {
1076 TTwIfObj *pTwIf = (TTwIfObj*)hTwIf;
1077
1078 if ((Address >= pTwIf->uMemAddr1) &&
1079 (Address + Length < pTwIf->uMemAddr1 + pTwIf->uMemSize1 ))
1080 return TI_TRUE;
1081
1082 return TI_FALSE;
1083 }
1084
twIf_isValidRegAddr(TI_HANDLE hTwIf,TI_UINT32 Address,TI_UINT32 Length)1085 TI_BOOL twIf_isValidRegAddr(TI_HANDLE hTwIf, TI_UINT32 Address, TI_UINT32 Length)
1086 {
1087 TTwIfObj *pTwIf = (TTwIfObj*)hTwIf;
1088
1089 if ((Address >= pTwIf->uMemAddr2 ) &&
1090 ( Address < pTwIf->uMemAddr2 + pTwIf->uMemSize2 ))
1091 return TI_TRUE;
1092
1093 return TI_FALSE;
1094 }
1095
1096 /*******************************************************************************
1097 * DEBUG FUNCTIONS IMPLEMENTATION *
1098 ********************************************************************************/
1099
1100 #ifdef TI_DBG
1101
1102 /**
1103 * \fn twIf_PrintModuleInfo
1104 * \brief Print module's parameters (debug)
1105 *
1106 * This function prints the module's parameters.
1107 *
1108 * \note
1109 * \param hTwIf - The module's object
1110 * \return void
1111 * \sa
1112 */
twIf_PrintModuleInfo(TI_HANDLE hTwIf)1113 void twIf_PrintModuleInfo (TI_HANDLE hTwIf)
1114 {
1115 #ifdef REPORT_LOG
1116 TTwIfObj *pTwIf = (TTwIfObj*)hTwIf;
1117
1118 WLAN_OS_REPORT(("-------------- TwIf Module Info-- ------------------------\n"));
1119 WLAN_OS_REPORT(("==========================================================\n"));
1120 WLAN_OS_REPORT(("eSmState = %d\n", pTwIf->eState ));
1121 WLAN_OS_REPORT(("uContextId = %d\n", pTwIf->uContextId ));
1122 WLAN_OS_REPORT(("fErrCb = %d\n", pTwIf->fErrCb ));
1123 WLAN_OS_REPORT(("hErrCb = %d\n", pTwIf->hErrCb ));
1124 WLAN_OS_REPORT(("uAwakeReqCount = %d\n", pTwIf->uAwakeReqCount ));
1125 WLAN_OS_REPORT(("uPendingTxnCount = %d\n", pTwIf->uPendingTxnCount ));
1126 WLAN_OS_REPORT(("uMemAddr = 0x%x\n", pTwIf->uMemAddr1 ));
1127 WLAN_OS_REPORT(("uMemSize = 0x%x\n", pTwIf->uMemSize1 ));
1128 WLAN_OS_REPORT(("uRegAddr = 0x%x\n", pTwIf->uMemAddr2 ));
1129 WLAN_OS_REPORT(("uRegSize = 0x%x\n", pTwIf->uMemSize2 ));
1130 WLAN_OS_REPORT(("uDbgCountAwake = %d\n", pTwIf->uDbgCountAwake ));
1131 WLAN_OS_REPORT(("uDbgCountSleep = %d\n", pTwIf->uDbgCountSleep ));
1132 WLAN_OS_REPORT(("uDbgCountTxn = %d\n", pTwIf->uDbgCountTxn ));
1133 WLAN_OS_REPORT(("uDbgCountTxnPending = %d\n", pTwIf->uDbgCountTxnPending ));
1134 WLAN_OS_REPORT(("uDbgCountTxnComplete = %d\n", pTwIf->uDbgCountTxnComplete ));
1135 WLAN_OS_REPORT(("uDbgCountTxnDone = %d\n", pTwIf->uDbgCountTxnDoneCb ));
1136 WLAN_OS_REPORT(("==========================================================\n\n"));
1137 #endif
1138 }
1139
1140
twIf_PrintQueues(TI_HANDLE hTwIf)1141 void twIf_PrintQueues (TI_HANDLE hTwIf)
1142 {
1143 TTwIfObj *pTwIf = (TTwIfObj*)hTwIf;
1144
1145 txnQ_PrintQueues(pTwIf->hTxnQ);
1146 }
1147
1148 #endif /* TI_DBG */
1149