• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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