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