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