Home | History | Annotate | Download | only in TwIf
      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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 
    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 
    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  */
    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  */
    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  */
    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  */
    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 
    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  */
    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  */
    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  */
    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  */
    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  */
   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  */
   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 
   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 
   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  */
   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 
   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