/** * \fn twIf_Transact * \brief Issue a transaction * * This method is used by the Xfer modules to issue all transaction types. * Translate HW address according to bus partition and call twIf_SendTransaction(). * * \note * \param hTwIf - The module's object * \param pTxn - The transaction object * \return COMPLETE if the transaction was completed in this context, PENDING if not, ERROR if failed * \sa twIf_SendTransaction */ ETxnStatus twIf_Transact (TI_HANDLE hTwIf, TTxnStruct *pTxn) { TTwIfObj *pTwIf = (TTwIfObj*)hTwIf; /* Translate HW address for registers region */ if ((pTxn->uHwAddr >= pTwIf->uMemAddr2) && (pTxn->uHwAddr <= pTwIf->uMemAddr2 + pTwIf->uMemSize2)) { pTxn->uHwAddr = pTxn->uHwAddr - pTwIf->uMemAddr2 + pTwIf->uMemSize1; } /* Translate HW address for memory region */ else { pTxn->uHwAddr = pTxn->uHwAddr - pTwIf->uMemAddr1; } /* Regular transaction are not the last and are not single step (only ELP write is) */ TXN_PARAM_SET_MORE(pTxn, 1); TXN_PARAM_SET_SINGLE_STEP(pTxn, 0); /* Send the transaction to the TxnQ and update the SM if needed. */ return twIf_SendTransaction (pTwIf, pTxn); }
void twIf_SetPartition(TI_HANDLE hTwIf, TPartition * pPartition) { TTwIfObj *pTwIf = (TTwIfObj *) hTwIf; TPartitionRegTxn *pPartitionRegTxn; /* The partition transaction structure for one register */ TTxnStruct *pTxnHdr; /* The partition transaction header (as used in the TxnQ API) */ ETxnStatus eStatus; int i; /* Save partition information for translation and validation. */ pTwIf->uMemAddr1 = pPartition[0].uMemAdrr; pTwIf->uMemSize1 = pPartition[0].uMemSize; pTwIf->uMemAddr2 = pPartition[1].uMemAdrr; pTwIf->uMemSize2 = pPartition[1].uMemSize; pTwIf->uMemAddr3 = pPartition[2].uMemAdrr; pTwIf->uMemSize3 = pPartition[2].uMemSize; pTwIf->uMemAddr4 = pPartition[3].uMemAdrr; /* Allocate memory for the current 4 partition transactions */ pPartitionRegTxn = (TPartitionRegTxn *) os_memoryAlloc(pTwIf->hOs, 7 * sizeof(TPartitionRegTxn)); pTxnHdr = &(pPartitionRegTxn->tHdr); /* Zero the allocated memory to be certain that unused fields will be initialized */ os_memoryZero(pTwIf->hOs, pPartitionRegTxn, 7 * sizeof(TPartitionRegTxn)); /* Prepare partition transaction data */ pPartitionRegTxn[0].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemAddr1); pPartitionRegTxn[1].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemSize1); pPartitionRegTxn[2].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemAddr2); pPartitionRegTxn[3].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemSize2); pPartitionRegTxn[4].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemAddr3); pPartitionRegTxn[5].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemSize3); pPartitionRegTxn[6].tData = ENDIAN_HANDLE_LONG(pTwIf->uMemAddr4); /* Prepare partition Txn header */ for (i = 0; i < 7; i++) { pTxnHdr = &(pPartitionRegTxn[i].tHdr); TXN_PARAM_SET(pTxnHdr, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) TXN_PARAM_SET_MORE(pTxnHdr, 1); TXN_PARAM_SET_SINGLE_STEP(pTxnHdr, 0); } /* Memory address */ pTxnHdr = &(pPartitionRegTxn[0].tHdr); BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR + 4, &(pPartitionRegTxn[0].tData), REGISTER_SIZE, 0, 0) twIf_SendTransaction(pTwIf, pTxnHdr); /* Memory size */ pTxnHdr = &(pPartitionRegTxn[1].tHdr); BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR + 0, &(pPartitionRegTxn[1].tData), REGISTER_SIZE, 0, 0) twIf_SendTransaction(pTwIf, pTxnHdr); /* Registers address */ pTxnHdr = &(pPartitionRegTxn[2].tHdr); BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR + 12, &(pPartitionRegTxn[2].tData), REGISTER_SIZE, 0, 0) twIf_SendTransaction(pTwIf, pTxnHdr); /* Registers size */ pTxnHdr = &(pPartitionRegTxn[3].tHdr); BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR + 8, &(pPartitionRegTxn[3].tData), REGISTER_SIZE, 0, 0) eStatus = twIf_SendTransaction(pTwIf, pTxnHdr); /* Registers address */ pTxnHdr = &(pPartitionRegTxn[4].tHdr); BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR + 20, &(pPartitionRegTxn[4].tData), REGISTER_SIZE, 0, 0) twIf_SendTransaction(pTwIf, pTxnHdr); /* Registers size */ pTxnHdr = &(pPartitionRegTxn[5].tHdr); BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR + 16, &(pPartitionRegTxn[5].tData), REGISTER_SIZE, 0, 0) eStatus = twIf_SendTransaction(pTwIf, pTxnHdr); /* Registers address */ pTxnHdr = &(pPartitionRegTxn[6].tHdr); BUILD_TTxnStruct(pTxnHdr, PARTITION_REGISTERS_ADDR + 24, &(pPartitionRegTxn[6].tData), REGISTER_SIZE, twIf_PartitionTxnDoneCb, pTwIf) twIf_SendTransaction(pTwIf, pTxnHdr); /* If the transaction is done, free the allocated memory (otherwise freed in the partition CB) */ if (eStatus != TXN_STATUS_PENDING) { os_memoryFree(pTwIf->hOs, pPartitionRegTxn, 7 * sizeof(TPartitionRegTxn)); } }
/** * \fn twIf_Init * \brief Init module * * - Init required handles and module variables * - Create the TxnDone-queue * - Register to TxnQ * - Register to context module * * \note * \param hTwIf - The module's object * \param hXxx - Handles to other modules * \param fRecoveryCb - Callback function for recovery completed after TxnDone * \param hRecoveryCb - Handle for fRecoveryCb * \return void * \sa */ void twIf_Init(TI_HANDLE hTwIf, TI_HANDLE hReport, TI_HANDLE hContext, TI_HANDLE hTimer, TI_HANDLE hTxnQ, TRecoveryCb fRecoveryCb, TI_HANDLE hRecoveryCb) { TTwIfObj *pTwIf = (TTwIfObj *) hTwIf; TI_UINT32 uNodeHeaderOffset; TTxnStruct *pTxnHdr; /* The ELP transactions header (as used in the TxnQ API) */ pTwIf->hReport = hReport; pTwIf->hContext = hContext; pTwIf->hTimer = hTimer; pTwIf->hTxnQ = hTxnQ; pTwIf->fRecoveryCb = fRecoveryCb; pTwIf->hRecoveryCb = hRecoveryCb; /* Prepare ELP sleep transaction */ pTwIf->tElpTxnSleep.uElpData = ELP_CTRL_REG_SLEEP; pTxnHdr = &(pTwIf->tElpTxnSleep.tHdr); TXN_PARAM_SET(pTxnHdr, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) TXN_PARAM_SET_MORE(pTxnHdr, 0); /* Sleep is the last transaction! */ /* NOTE: Function id for single step will be replaced to 0 by the bus driver */ TXN_PARAM_SET_SINGLE_STEP(pTxnHdr, 1); /* ELP write is always single step (TxnQ is topped)! */ BUILD_TTxnStruct(pTxnHdr, ELP_CTRL_REG_ADDR, &(pTwIf->tElpTxnSleep.uElpData), sizeof(TI_UINT8), NULL, NULL) /* Prepare ELP awake transaction */ pTwIf->tElpTxnAwake.uElpData = ELP_CTRL_REG_AWAKE; pTxnHdr = &(pTwIf->tElpTxnAwake.tHdr); TXN_PARAM_SET(pTxnHdr, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) TXN_PARAM_SET_MORE(pTxnHdr, 1); /* NOTE: Function id for single step will be replaced to 0 by the bus driver */ TXN_PARAM_SET_SINGLE_STEP(pTxnHdr, 1); /* ELP write is always single step (TxnQ is topped)! */ BUILD_TTxnStruct(pTxnHdr, ELP_CTRL_REG_ADDR, &(pTwIf->tElpTxnAwake.uElpData), sizeof(TI_UINT8), NULL, NULL) /* Create the TxnDone queue. */ uNodeHeaderOffset = TI_FIELD_OFFSET(TTxnStruct, tTxnQNode); pTwIf->hTxnDoneQueue = que_Create(pTwIf->hOs, pTwIf->hReport, TXN_DONE_QUE_SIZE, uNodeHeaderOffset); if (pTwIf->hTxnDoneQueue == NULL) { TRACE0(pTwIf->hReport, REPORT_SEVERITY_ERROR, "twIf_Init: TxnDone queue creation failed!\n"); } /* Register to the context engine and get the client ID */ pTwIf->uContextId = context_RegisterClient(pTwIf->hContext, twIf_HandleTxnDone, hTwIf, TI_TRUE, "TWIF", sizeof("TWIF")); /* Allocate timer */ pTwIf->hPendRestartTimer = tmr_CreateTimer(hTimer); if (pTwIf->hPendRestartTimer == NULL) { TRACE0(pTwIf->hReport, REPORT_SEVERITY_ERROR, "twIf_Init: Failed to create PendRestartTimer!\n"); return; } pTwIf->bPendRestartTimerRunning = TI_FALSE; /* Register to TxnQ */ txnQ_Open(pTwIf->hTxnQ, TXN_FUNC_ID_WLAN, TXN_NUM_PRIORITYS, (TTxnQueueDoneCb) twIf_TxnDoneCb, hTwIf); /* Restart TwIf and TxnQ modules */ twIf_Restart(hTwIf); }