/** * \fn twIf_SendTransaction * \brief Send a transaction to the device * * This method is used by the Xfer modules and the TwIf to send all transaction types to the device. * Send the transaction to the TxnQ and update the SM if needed. * * \note * \param pTwIf - 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 */ static ETxnStatus twIf_SendTransaction (TTwIfObj *pTwIf, TTxnStruct *pTxn) { ETxnStatus eStatus; TI_UINT32 data=0; #ifdef TI_DBG /* Verify that the Txn HW-Address is 4-bytes aligned */ if (pTxn->uHwAddr & 0x3) { return TXN_STATUS_ERROR; } #endif context_EnterCriticalSection (pTwIf->hContext); /* increment pending Txn counter */ pTwIf->uPendingTxnCount++; context_LeaveCriticalSection (pTwIf->hContext); /* Send transaction to TxnQ */ eStatus = txnQ_Transact(pTwIf->hTxnQ, pTxn); #ifdef TI_DBG pTwIf->uDbgCountTxn++; if (eStatus == TXN_STATUS_COMPLETE) { pTwIf->uDbgCountTxnComplete++; } else if (eStatus == TXN_STATUS_PENDING ) { pTwIf->uDbgCountTxnPending++; } COPY_WLAN_LONG(&data,&(pTxn->aBuf[0])); #endif /* If Txn status is PENDING issue Start event to the SM */ if (eStatus == TXN_STATUS_PENDING) { twIf_HandleSmEvent (pTwIf, SM_EVENT_START); } /* Else (COMPLETE or ERROR) */ else { context_EnterCriticalSection (pTwIf->hContext); /* decrement pending Txn counter in case of sync transact*/ pTwIf->uPendingTxnCount--; context_LeaveCriticalSection (pTwIf->hContext); /* If Awake not required and no pending transactions in TxnQ, issue Sleep event to SM */ if ((pTwIf->uAwakeReqCount == 0) && (pTwIf->uPendingTxnCount == 0)) { twIf_HandleSmEvent (pTwIf, SM_EVENT_SLEEP); } /* If Txn failed and error CB available, call it to initiate recovery */ if (eStatus == TXN_STATUS_ERROR) { if (pTwIf->fErrCb) { pTwIf->fErrCb (pTwIf->hErrCb, BUS_FAILURE); } } } /* Return the Txn status (COMPLETE if completed in this context, PENDING if not, ERROR if failed) */ return eStatus; }
/** * \fn twIf_SendTransaction * \brief Send a transaction to the device * * This method is used by the Xfer modules and the TwIf to send all transaction types to the device. * Send the transaction to the TxnQ and update the SM if needed. * * \note * \param pTwIf - 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 */ static ETxnStatus twIf_SendTransaction(TTwIfObj * pTwIf, TTxnStruct * pTxn) { ETxnStatus eStatus; #ifdef TI_DBG TI_UINT32 data = 0; /* Verify that the Txn HW-Address is 4-bytes aligned */ if (pTxn->uHwAddr & 0x3) { TRACE2(pTwIf->hReport, REPORT_SEVERITY_ERROR, "twIf_SendTransaction: Unaligned HwAddr! HwAddr=0x%x, Params=0x%x\n", pTxn->uHwAddr, pTxn->uTxnParams); return TXN_STATUS_ERROR; } #endif context_EnterCriticalSection(pTwIf->hContext); /* increment pending Txn counter */ pTwIf->uPendingTxnCount++; context_LeaveCriticalSection(pTwIf->hContext); /* Send transaction to TxnQ */ eStatus = txnQ_Transact(pTwIf->hTxnQ, pTxn); #ifdef TI_DBG pTwIf->uDbgCountTxn++; if (eStatus == TXN_STATUS_COMPLETE) { pTwIf->uDbgCountTxnComplete++; } else if (eStatus == TXN_STATUS_PENDING) { pTwIf->uDbgCountTxnPending++; } COPY_WLAN_LONG(&data, &(pTxn->aBuf[0])); 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); #endif /* If Txn status is PENDING issue Start event to the SM */ if (eStatus == TXN_STATUS_PENDING) { twIf_HandleSmEvent(pTwIf, SM_EVENT_START); } /* Else (COMPLETE or ERROR) */ else { context_EnterCriticalSection(pTwIf->hContext); /* decrement pending Txn counter in case of sync transact */ pTwIf->uPendingTxnCount--; context_LeaveCriticalSection(pTwIf->hContext); /* If Awake not required and no pending transactions in TxnQ, issue Sleep event to SM */ if ((pTwIf->uAwakeReqCount == 0) && (pTwIf->uPendingTxnCount == 0)) { twIf_HandleSmEvent(pTwIf, SM_EVENT_SLEEP); } /* If Txn failed and error CB available, call it to initiate recovery */ if (eStatus == TXN_STATUS_ERROR) { 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]); if (pTwIf->fErrCb) { pTwIf->fErrCb(pTwIf->hErrCb, BUS_FAILURE); } } } /* Return the Txn status (COMPLETE if completed in this context, PENDING if not, ERROR if failed) */ return eStatus; }
/** * \fn StaCap_GetHtCapabilitiesIe * \brief Get the desired STA HT capabilities IE. get the physical HT capabilities from TWD * and build HT capabilities IE. * * \note * \param hStaCap - The module object * \param pRequest - pointer to request buffer\n * \param len - size of returned IE\n * \return TI_OK on success or TI_NOK on failure * \sa */ TI_STATUS StaCap_GetHtCapabilitiesIe (TI_HANDLE hStaCap, TI_UINT8 *pRequest, TI_UINT32 *pLen) { TStaCap *pStaCap = (TStaCap *)hStaCap; TTwdHtCapabilities *pTwdHtCapabilities; TI_UINT8 *pDataBuf = pRequest; TStaCapHtCapabilities tHtCapabilities; TI_BOOL bWmeEnable; /* verify that WME flag enable */ qosMngr_GetWmeEnableFlag (pStaCap->hQosMngr, &bWmeEnable); if (bWmeEnable == TI_FALSE) { *pLen = 0; return TI_OK; } TWD_GetTwdHtCapabilities (pStaCap->hTWD, &pTwdHtCapabilities); /* verify that 802.11n flag enable */ if (pTwdHtCapabilities->b11nEnable == TI_FALSE) { *pLen = 0; return TI_OK; } /* * set TWD values to HT capabilities structure * * Note: all numbers after "<<" represent the position of the values in the filed according * to 11n SPEC. */ tHtCapabilities.uHtCapabilitiesInfo = ((pTwdHtCapabilities->uChannelWidth << 1) | (pTwdHtCapabilities->uRxSTBC << 8) | (pTwdHtCapabilities->uMaxAMSDU << 11)| (DSSS_CCK_MODE << 12)); tHtCapabilities.uHtCapabilitiesInfo |= ((((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_LDPC_CODING) ? 1 : 0) << 0) | (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_GREENFIELD_FRAME_FORMAT) ? 1 : 0) << 4) | (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_SHORT_GI_FOR_20MHZ_PACKETS) ? 1 : 0) << 5) | (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_SHORT_GI_FOR_40MHZ_PACKETS) ? 1 : 0) << 6) | (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_SUPPORT_FOR_STBC_IN_TRANSMISSION) ? 1 : 0) << 7) | (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_DELAYED_BLOCK_ACK) ? 1 : 0) << 10) | (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_DSSS_CCK_IN_40_MHZ) ? 1 : 0) << 12) | (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_LSIG_TXOP_PROTECTION) ? 1 : 0) << 15)); tHtCapabilities.uAMpduParam = ((pTwdHtCapabilities->uMaxAMPDU << 0) | (pTwdHtCapabilities->uAMPDUSpacing << 2)); /* copy RX supported MCS rates */ os_memoryCopy (pStaCap->hOs, tHtCapabilities.tSuppMcsSet.aRxMscBitmask, pTwdHtCapabilities->aRxMCS, RX_TX_MCS_BITMASK_SIZE); tHtCapabilities.tSuppMcsSet.uHighestSupportedDataRate = pTwdHtCapabilities->uRxMaxDataRate; /* check if supported MCS rates identical to TX and RX */ if( 0 == os_memoryCompare(pStaCap->hOs, pTwdHtCapabilities->aRxMCS, pTwdHtCapabilities->aTxMCS, RX_TX_MCS_BITMASK_SIZE)) { tHtCapabilities.tSuppMcsSet.uTxRxSetting = ((TX_MCS_SET_YES << 0) | /* set supported TX MCS rate */ (TX_RX_NOT_EQUAL_NO << 1)); /* set TX&RX MCS rate are equal */ } /* in case supported MCS rates TX different from the RX */ else { TI_UINT32 i; /* check if there are TX MCS rates supported */ for (i = 0; i <= (RX_TX_MCS_BITMASK_SIZE - 1); ++i) { if (pTwdHtCapabilities->aTxMCS[i] != 0) { break; } } /* TX MCS supported */ if(i <= (RX_TX_MCS_BITMASK_SIZE -1)) { tHtCapabilities.tSuppMcsSet.uTxRxSetting = ((TX_MCS_SET_YES << 0) | /* set supported TX MCS rates */ (TX_RX_NOT_EQUAL_YES << 1)); /* set TX&RX MCS rates different */ } /* TX MCS not supported */ else { tHtCapabilities.tSuppMcsSet.uTxRxSetting = (TX_MCS_SET_NO << 0); /* set no supported TX MCS rates */ } } tHtCapabilities.uExteCapabilities = (((pTwdHtCapabilities->uHTCapabilitiesBitMask & CAP_BIT_MASK_PCO) ? 1 : 0) << 0); if (tHtCapabilities.uExteCapabilities != 0) { tHtCapabilities.uExteCapabilities |= (pTwdHtCapabilities->uPCOTransTime << 1); } tHtCapabilities.uExteCapabilities |= ((pTwdHtCapabilities->uMCSFeedback << 8) | (HTC_SUPPORT_NO << 10)); tHtCapabilities.uTxBfCapabilities = ((IMPLICIT_TXBF_REC_CAPABLE << 0) | (TRANSMIT_STAGGERED_SOUNDING_CAPABLE << 2)); tHtCapabilities.uAselCapabilities = 0x0; /* build IE */ *pDataBuf = HT_CAPABILITIES_IE_ID; *(pDataBuf + 1) = DOT11_HT_CAPABILITIES_ELE_LEN; COPY_WLAN_WORD(pDataBuf + 2, &(tHtCapabilities.uHtCapabilitiesInfo)); *(pDataBuf + 4) = tHtCapabilities.uAMpduParam; os_memoryCopy (pStaCap->hOs, pDataBuf + 5, tHtCapabilities.tSuppMcsSet.aRxMscBitmask, RX_TX_MCS_BITMASK_SIZE); COPY_WLAN_WORD(pDataBuf + 15, &(tHtCapabilities.tSuppMcsSet.uHighestSupportedDataRate)); *(pDataBuf + 17) = tHtCapabilities.tSuppMcsSet.uTxRxSetting; /* clear the reserved bytes */ os_memoryZero (pStaCap->hOs, (pDataBuf + 18), 3); COPY_WLAN_WORD(pDataBuf + 21, &(tHtCapabilities.uExteCapabilities)); COPY_WLAN_LONG(pDataBuf + 23, &(tHtCapabilities.uTxBfCapabilities)); *(pDataBuf + 27) = tHtCapabilities.uAselCapabilities; *pLen = DOT11_HT_CAPABILITIES_ELE_LEN + sizeof(dot11_eleHdr_t); return TI_OK; }