--- /dev/null
+//============================================================\r
+// Description:\r
+//\r
+// This file is for TXBF interface mechanism\r
+//\r
+//============================================================\r
+#include "mp_precomp.h"\r
+#include "../phydm_precomp.h"\r
+\r
+#if (BEAMFORMING_SUPPORT == 1)\r
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
+VOID\r
+Beamforming_GidPAid(\r
+ PADAPTER Adapter,\r
+ PRT_TCB pTcb\r
+)\r
+{\r
+ u1Byte Idx = 0;\r
+ u1Byte RA[6] ={0};\r
+ pu1Byte pHeader = GET_FRAME_OF_FIRST_FRAG(Adapter, pTcb);\r
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);\r
+ PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+\r
+ if (Adapter->HardwareType < HARDWARE_TYPE_RTL8192EE)\r
+ return;\r
+ else if (IS_WIRELESS_MODE_N(Adapter) == FALSE)\r
+ return;\r
+\r
+#if (SUPPORT_MU_BF == 1)\r
+ if (pTcb->TxBFPktType == RT_BF_PKT_TYPE_BROADCAST_NDPA) { /* MU NDPA */\r
+#else\r
+ if (0) {\r
+#endif\r
+ /* Fill G_ID and P_AID */\r
+ pTcb->G_ID = 63;\r
+ if (pBeamInfo->FirstMUBFeeIndex < BEAMFORMEE_ENTRY_NUM) {\r
+ pTcb->P_AID = pBeamInfo->BeamformeeEntry[pBeamInfo->FirstMUBFeeIndex].P_AID; \r
+ RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End, G_ID=0x%X, P_AID=0x%X\n", __func__, pTcb->G_ID, pTcb->P_AID));\r
+ }\r
+ } else {\r
+ GET_80211_HDR_ADDRESS1(pHeader, &RA);\r
+\r
+ // VHT SU PPDU carrying one or more group addressed MPDUs or\r
+ // Transmitting a VHT NDP intended for multiple recipients\r
+ if (MacAddr_isBcst(RA) || MacAddr_isMulticast(RA) || pTcb->macId == MAC_ID_STATIC_FOR_BROADCAST_MULTICAST) {\r
+ pTcb->G_ID = 63;\r
+ pTcb->P_AID = 0;\r
+ } else if (ACTING_AS_AP(Adapter)) {\r
+ u2Byte AID = (u2Byte) (MacIdGetOwnerAssociatedClientAID(Adapter, pTcb->macId) & 0x1ff); /*AID[0:8]*/\r
+ \r
+ /*RT_DISP(FBEAM, FBEAM_FUN, ("@%s pTcb->macId=0x%X, AID=0x%X\n", __func__, pTcb->macId, AID));*/\r
+ pTcb->G_ID = 63;\r
+\r
+ if (AID == 0) /*A PPDU sent by an AP to a non associated STA*/\r
+ pTcb->P_AID = 0;\r
+ else { /*Sent by an AP and addressed to a STA associated with that AP*/\r
+ u2Byte BSSID = 0;\r
+ GET_80211_HDR_ADDRESS2(pHeader, &RA);\r
+ BSSID = ((RA[5] & 0xf0) >> 4) ^ (RA[5] & 0xf); /*BSSID[44:47] xor BSSID[40:43]*/\r
+ pTcb->P_AID = (AID + BSSID *32) & 0x1ff; /*(dec(A) + dec(B)*32) mod 512*/\r
+ }\r
+ } else if (ACTING_AS_IBSS(Adapter)) {\r
+ pTcb->G_ID = 63;\r
+ /*P_AID for infrasturcture mode; MACID for ad-hoc mode. */\r
+ pTcb->P_AID = pTcb->macId;\r
+ } else if (MgntLinkStatusQuery(Adapter)) { /*Addressed to AP*/\r
+ pTcb->G_ID = 0;\r
+ GET_80211_HDR_ADDRESS1(pHeader, &RA);\r
+ pTcb->P_AID = RA[5]; /*RA[39:47]*/\r
+ pTcb->P_AID = (pTcb->P_AID << 1) | (RA[4] >> 7 );\r
+ } else {\r
+ pTcb->G_ID = 63;\r
+ pTcb->P_AID = 0;\r
+ }\r
+ /*RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End, G_ID=0x%X, P_AID=0x%X\n", __func__, pTcb->G_ID, pTcb->P_AID));*/\r
+ }\r
+}\r
+\r
+\r
+RT_STATUS\r
+Beamforming_GetReportFrame(\r
+ IN PADAPTER Adapter,\r
+ IN PRT_RFD pRfd,\r
+ IN POCTET_STRING pPduOS\r
+ )\r
+{\r
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);\r
+ PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;\r
+ PRT_BEAMFORMEE_ENTRY pBeamformEntry = NULL;\r
+ pu1Byte pMIMOCtrlField, pCSIReport, pCSIMatrix;\r
+ u1Byte Idx, Nc, Nr, CH_W;\r
+ u2Byte CSIMatrixLen = 0;\r
+\r
+ ACT_PKT_TYPE pktType = ACT_PKT_TYPE_UNKNOWN;\r
+\r
+ //Memory comparison to see if CSI report is the same with previous one\r
+ pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, Frame_Addr2(*pPduOS), &Idx);\r
+\r
+ if (pBeamformEntry == NULL) {\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("Beamforming_GetReportFrame: Cannot find entry by addr\n"));\r
+ return RT_STATUS_FAILURE;\r
+ }\r
+\r
+ pktType = PacketGetActionFrameType(pPduOS);\r
+ \r
+ //-@ Modified by David\r
+ if (pktType == ACT_PKT_VHT_COMPRESSED_BEAMFORMING) {\r
+ pMIMOCtrlField = pPduOS->Octet + 26; \r
+ Nc = ((*pMIMOCtrlField) & 0x7) + 1;\r
+ Nr = (((*pMIMOCtrlField) & 0x38) >> 3) + 1;\r
+ CH_W = (((*pMIMOCtrlField) & 0xC0) >> 6);\r
+ pCSIMatrix = pMIMOCtrlField + 3 + Nc; //24+(1+1+3)+2 MAC header+(Category+ActionCode+MIMOControlField) +SNR(Nc=2)\r
+ CSIMatrixLen = pPduOS->Length - 26 -3 -Nc;\r
+ } else if (pktType == ACT_PKT_HT_COMPRESSED_BEAMFORMING) {\r
+ pMIMOCtrlField = pPduOS->Octet + 26; \r
+ Nc = ((*pMIMOCtrlField) & 0x3) + 1;\r
+ Nr = (((*pMIMOCtrlField) & 0xC) >> 2) + 1;\r
+ CH_W = (((*pMIMOCtrlField) & 0x10) >> 4);\r
+ pCSIMatrix = pMIMOCtrlField + 6 + Nr; //24+(1+1+6)+2 MAC header+(Category+ActionCode+MIMOControlField) +SNR(Nc=2)\r
+ CSIMatrixLen = pPduOS->Length - 26 -6 -Nr;\r
+ } else\r
+ return RT_STATUS_SUCCESS; \r
+ \r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] idx=%d, pkt type=%d, Nc=%d, Nr=%d, CH_W=%d\n", __func__, Idx, pktType, Nc, Nr, CH_W)); \r
+\r
+ return RT_STATUS_SUCCESS;\r
+}\r
+\r
+\r
+VOID\r
+ConstructHTNDPAPacket(\r
+ PADAPTER Adapter,\r
+ pu1Byte RA,\r
+ pu1Byte Buffer,\r
+ pu4Byte pLength,\r
+ CHANNEL_WIDTH BW\r
+ )\r
+{\r
+ u2Byte Duration= 0;\r
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);\r
+ OCTET_STRING pNDPAFrame,ActionContent;\r
+ u1Byte ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};\r
+\r
+ PlatformZeroMemory(Buffer, 32);\r
+\r
+ SET_80211_HDR_FRAME_CONTROL(Buffer,0);\r
+\r
+ SET_80211_HDR_ORDER(Buffer, 1);\r
+ SET_80211_HDR_TYPE_AND_SUBTYPE(Buffer,Type_Action_No_Ack);\r
+\r
+ SET_80211_HDR_ADDRESS1(Buffer, RA);\r
+ SET_80211_HDR_ADDRESS2(Buffer, Adapter->CurrentAddress);\r
+ SET_80211_HDR_ADDRESS3(Buffer, pMgntInfo->Bssid);\r
+\r
+ Duration = 2*aSifsTime + 40;\r
+ \r
+ if (BW == CHANNEL_WIDTH_40)\r
+ Duration+= 87;\r
+ else \r
+ Duration+= 180;\r
+\r
+ SET_80211_HDR_DURATION(Buffer, Duration);\r
+\r
+ //HT control field\r
+ SET_HT_CTRL_CSI_STEERING(Buffer+sMacHdrLng, 3);\r
+ SET_HT_CTRL_NDP_ANNOUNCEMENT(Buffer+sMacHdrLng, 1);\r
+ \r
+ FillOctetString(pNDPAFrame, Buffer, sMacHdrLng+sHTCLng);\r
+\r
+ FillOctetString(ActionContent, ActionHdr, 4);\r
+ PacketAppendData(&pNDPAFrame, ActionContent); \r
+\r
+ *pLength = 32;\r
+}\r
+\r
+\r
+\r
+\r
+BOOLEAN\r
+SendFWHTNDPAPacket(\r
+ IN PVOID pDM_VOID,\r
+ IN pu1Byte RA,\r
+ IN CHANNEL_WIDTH BW\r
+ )\r
+{\r
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+ PADAPTER Adapter = pDM_Odm->Adapter;\r
+ PRT_TCB pTcb;\r
+ PRT_TX_LOCAL_BUFFER pBuf;\r
+ BOOLEAN ret = TRUE;\r
+ u4Byte BufLen;\r
+ pu1Byte BufAddr;\r
+ u1Byte DescLen = 0, Idx = 0, NDPTxRate;\r
+ PADAPTER pDefAdapter = GetDefaultAdapter(Adapter);\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);\r
+ PRT_BEAMFORMEE_ENTRY pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
+\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));\r
+\r
+ if (pBeamformEntry == NULL)\r
+ return FALSE;\r
+\r
+ NDPTxRate = Beamforming_GetHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
+ PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
+\r
+ if (MgntGetFWBuffer(pDefAdapter, &pTcb, &pBuf)) {\r
+#if(DEV_BUS_TYPE != RT_PCI_INTERFACE)\r
+ DescLen = Adapter->HWDescHeadLength - pHalData->USBALLDummyLength;\r
+#endif\r
+ BufAddr = pBuf->Buffer.VirtualAddress + DescLen;\r
+\r
+ ConstructHTNDPAPacket(\r
+ Adapter, \r
+ RA,\r
+ BufAddr, \r
+ &BufLen,\r
+ BW\r
+ );\r
+\r
+ pTcb->PacketLength = BufLen + DescLen;\r
+\r
+ pTcb->bTxEnableSwCalcDur = TRUE;\r
+ \r
+ pTcb->BWOfPacket = BW;\r
+\r
+ if(ACTING_AS_IBSS(Adapter) || ACTING_AS_AP(Adapter))\r
+ pTcb->G_ID = 63;\r
+\r
+ pTcb->P_AID = pBeamformEntry->P_AID;\r
+ pTcb->DataRate = NDPTxRate; /*rate of NDP decide by Nr*/\r
+\r
+ Adapter->HalFunc.CmdSendPacketHandler(Adapter, pTcb, pBuf, pTcb->PacketLength, DESC_PACKET_TYPE_NORMAL, FALSE);\r
+ } else\r
+ ret = FALSE;\r
+\r
+ PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);\r
+ \r
+ if (ret)\r
+ RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+BOOLEAN\r
+SendSWHTNDPAPacket(\r
+ IN PVOID pDM_VOID,\r
+ IN pu1Byte RA,\r
+ IN CHANNEL_WIDTH BW\r
+ )\r
+{\r
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+ PADAPTER Adapter = pDM_Odm->Adapter;\r
+ PRT_TCB pTcb;\r
+ PRT_TX_LOCAL_BUFFER pBuf;\r
+ BOOLEAN ret = TRUE;\r
+ u1Byte Idx = 0, NDPTxRate = 0;\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+ PRT_BEAMFORMEE_ENTRY pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
+\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));\r
+\r
+ NDPTxRate = Beamforming_GetHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
+ \r
+ PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
+\r
+ if (MgntGetBuffer(Adapter, &pTcb, &pBuf)) {\r
+ ConstructHTNDPAPacket(\r
+ Adapter, \r
+ RA,\r
+ pBuf->Buffer.VirtualAddress, \r
+ &pTcb->PacketLength,\r
+ BW\r
+ );\r
+\r
+ pTcb->bTxEnableSwCalcDur = TRUE;\r
+\r
+ pTcb->BWOfPacket = BW;\r
+\r
+ MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, NDPTxRate);\r
+ } else\r
+ ret = FALSE;\r
+ \r
+ PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);\r
+\r
+ if (ret)\r
+ RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+\r
+VOID\r
+ConstructVHTNDPAPacket(\r
+ IN PDM_ODM_T pDM_Odm,\r
+ pu1Byte RA,\r
+ u2Byte AID,\r
+ pu1Byte Buffer,\r
+ pu4Byte pLength,\r
+ CHANNEL_WIDTH BW\r
+ )\r
+{\r
+ u2Byte Duration= 0;\r
+ u1Byte Sequence = 0;\r
+ pu1Byte pNDPAFrame = Buffer;\r
+ RT_NDPA_STA_INFO STAInfo;\r
+ PADAPTER Adapter = pDM_Odm->Adapter;\r
+ u1Byte Idx = 0;\r
+ PRT_BEAMFORMEE_ENTRY pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
+ // Frame control.\r
+ SET_80211_HDR_FRAME_CONTROL(pNDPAFrame, 0);\r
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pNDPAFrame, Type_NDPA);\r
+\r
+ SET_80211_HDR_ADDRESS1(pNDPAFrame, RA);\r
+ SET_80211_HDR_ADDRESS2(pNDPAFrame, pBeamformEntry->MyMacAddr);\r
+\r
+ Duration = 2*aSifsTime + 44;\r
+ \r
+ if (BW == CHANNEL_WIDTH_80)\r
+ Duration += 40;\r
+ else if(BW == CHANNEL_WIDTH_40)\r
+ Duration+= 87;\r
+ else \r
+ Duration+= 180;\r
+\r
+ SET_80211_HDR_DURATION(pNDPAFrame, Duration);\r
+\r
+ Sequence = *(pDM_Odm->pSoundingSeq) << 2;\r
+ ODM_MoveMemory(pDM_Odm, pNDPAFrame+16, &Sequence, 1);\r
+\r
+ if (phydm_actingDetermine(pDM_Odm, PhyDM_ACTING_AS_IBSS) || phydm_actingDetermine(pDM_Odm, PhyDM_ACTING_AS_AP) == FALSE)\r
+ AID = 0;\r
+\r
+ STAInfo.AID = AID;\r
+ STAInfo.FeedbackType = 0;\r
+ STAInfo.NcIndex = 0;\r
+ \r
+ ODM_MoveMemory(pDM_Odm, pNDPAFrame+17, (pu1Byte)&STAInfo, 2);\r
+\r
+ *pLength = 19;\r
+}\r
+\r
+\r
+BOOLEAN\r
+SendFWVHTNDPAPacket(\r
+ IN PVOID pDM_VOID,\r
+ IN pu1Byte RA,\r
+ IN u2Byte AID,\r
+ IN CHANNEL_WIDTH BW\r
+ )\r
+{\r
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+ PADAPTER Adapter = pDM_Odm->Adapter;\r
+ PRT_TCB pTcb;\r
+ PRT_TX_LOCAL_BUFFER pBuf;\r
+ BOOLEAN ret = TRUE;\r
+ u4Byte BufLen;\r
+ pu1Byte BufAddr;\r
+ u1Byte DescLen = 0, Idx = 0, NDPTxRate = 0;\r
+ PADAPTER pDefAdapter = GetDefaultAdapter(Adapter);\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);\r
+ PRT_BEAMFORMEE_ENTRY pBeamformEntry =phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
+\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));\r
+\r
+ if (pBeamformEntry == NULL)\r
+ return FALSE;\r
+\r
+ NDPTxRate = Beamforming_GetVHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
+ \r
+ PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
+\r
+ if (MgntGetFWBuffer(pDefAdapter, &pTcb, &pBuf)) {\r
+#if(DEV_BUS_TYPE != RT_PCI_INTERFACE)\r
+ DescLen = Adapter->HWDescHeadLength - pHalData->USBALLDummyLength;\r
+#endif\r
+ BufAddr = pBuf->Buffer.VirtualAddress + DescLen;\r
+\r
+ ConstructVHTNDPAPacket(\r
+ pDM_Odm, \r
+ RA,\r
+ AID,\r
+ BufAddr, \r
+ &BufLen,\r
+ BW\r
+ );\r
+ \r
+ pTcb->PacketLength = BufLen + DescLen;\r
+\r
+ pTcb->bTxEnableSwCalcDur = TRUE;\r
+ \r
+ pTcb->BWOfPacket = BW;\r
+\r
+ if (phydm_actingDetermine(pDM_Odm, PhyDM_ACTING_AS_IBSS) || phydm_actingDetermine(pDM_Odm, PhyDM_ACTING_AS_AP))\r
+ pTcb->G_ID = 63;\r
+\r
+ pTcb->P_AID = pBeamformEntry->P_AID;\r
+ pTcb->DataRate = NDPTxRate; /*decide by Nr*/\r
+\r
+ Adapter->HalFunc.CmdSendPacketHandler(Adapter, pTcb, pBuf, pTcb->PacketLength, DESC_PACKET_TYPE_NORMAL, FALSE);\r
+ } else\r
+ ret = FALSE;\r
+ \r
+ PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK); \r
+\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] End, ret=%d\n", __func__, ret));\r
+\r
+ if (ret)\r
+ RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+\r
+BOOLEAN\r
+SendSWVHTNDPAPacket(\r
+ IN PVOID pDM_VOID,\r
+ IN pu1Byte RA,\r
+ IN u2Byte AID,\r
+ IN CHANNEL_WIDTH BW\r
+ )\r
+{\r
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+ PADAPTER Adapter = pDM_Odm->Adapter;\r
+ PRT_TCB pTcb;\r
+ PRT_TX_LOCAL_BUFFER pBuf;\r
+ BOOLEAN ret = TRUE;\r
+ u1Byte Idx = 0, NDPTxRate = 0;\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+ PRT_BEAMFORMEE_ENTRY pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
+\r
+ NDPTxRate = Beamforming_GetVHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
+\r
+ PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
+\r
+ if (MgntGetBuffer(Adapter, &pTcb, &pBuf)) {\r
+ ConstructVHTNDPAPacket(\r
+ pDM_Odm, \r
+ RA,\r
+ AID,\r
+ pBuf->Buffer.VirtualAddress, \r
+ &pTcb->PacketLength,\r
+ BW\r
+ );\r
+\r
+ pTcb->bTxEnableSwCalcDur = TRUE;\r
+ pTcb->BWOfPacket = BW;\r
+\r
+ /*rate of NDP decide by Nr*/\r
+ MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, NDPTxRate);\r
+ } else\r
+ ret = FALSE;\r
+ \r
+ PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK); \r
+\r
+ if (ret)\r
+ RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
+\r
+ return ret;\r
+}\r
+\r
+#ifdef SUPPORT_MU_BF\r
+#if (SUPPORT_MU_BF == 1)\r
+/*\r
+// Description: On VHT GID management frame by an MU beamformee.\r
+//\r
+// 2015.05.20. Created by tynli.\r
+*/\r
+RT_STATUS\r
+Beamforming_GetVHTGIDMgntFrame(\r
+ IN PADAPTER Adapter,\r
+ IN PRT_RFD pRfd,\r
+ IN POCTET_STRING pPduOS\r
+ )\r
+{\r
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);\r
+ PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;\r
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;\r
+ pu1Byte pBuffer = NULL;\r
+ pu1Byte pRaddr = NULL;\r
+ u1Byte MemStatus[8] = {0}, UserPos[16] = {0};\r
+ u1Byte idx;\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+ PRT_BEAMFORMER_ENTRY pBeamformEntry = &pBeamInfo->BeamformerEntry[pBeamInfo->mu_ap_index];\r
+\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] On VHT GID mgnt frame!\n", __func__)); \r
+\r
+ /* Check length*/\r
+ if (pPduOS->Length < (FRAME_OFFSET_VHT_GID_MGNT_USER_POSITION_ARRAY+16)) { \r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("Beamforming_GetVHTGIDMgntFrame(): Invalid length (%d)\n", pPduOS->Length));\r
+ return RT_STATUS_INVALID_LENGTH;\r
+ }\r
+\r
+ /* Check RA*/\r
+ pRaddr = (pu1Byte)(pPduOS->Octet)+4;\r
+ if (!eqMacAddr(pRaddr, Adapter->CurrentAddress)) { \r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("Beamforming_GetVHTGIDMgntFrame(): Drop because of RA error.\n"));\r
+ return RT_STATUS_PKT_DROP;\r
+ }\r
+\r
+ RT_DISP_DATA(FBEAM, FBEAM_DATA, "On VHT GID Mgnt Frame ==>:\n", pPduOS->Octet, pPduOS->Length);\r
+\r
+ /*Parsing Membership Status Array*/\r
+ pBuffer = pPduOS->Octet + FRAME_OFFSET_VHT_GID_MGNT_MEMBERSHIP_STATUS_ARRAY;\r
+ for (idx = 0; idx < 8; idx++) {\r
+ MemStatus[idx] = GET_VHT_GID_MGNT_INFO_MEMBERSHIP_STATUS(pBuffer+idx);\r
+ pBeamformEntry->gid_valid[idx] = GET_VHT_GID_MGNT_INFO_MEMBERSHIP_STATUS(pBuffer+idx);\r
+ }\r
+\r
+ RT_DISP_DATA(FBEAM, FBEAM_DATA, "MemStatus: ", MemStatus, 8);\r
+\r
+ /* Parsing User Position Array*/\r
+ pBuffer = pPduOS->Octet + FRAME_OFFSET_VHT_GID_MGNT_USER_POSITION_ARRAY;\r
+ for (idx = 0; idx < 16; idx++) {\r
+ UserPos[idx] = GET_VHT_GID_MGNT_INFO_USER_POSITION(pBuffer+idx);\r
+ pBeamformEntry->user_position[idx] = GET_VHT_GID_MGNT_INFO_USER_POSITION(pBuffer+idx);\r
+ }\r
+\r
+ RT_DISP_DATA(FBEAM, FBEAM_DATA, "UserPos: ", UserPos, 16);\r
+\r
+ /* Group ID detail printed*/\r
+ {\r
+ u1Byte i, j;\r
+ u1Byte tmpVal;\r
+ u2Byte tmpVal2;\r
+\r
+ for (i = 0; i < 8; i++) {\r
+ tmpVal = MemStatus[i];\r
+ tmpVal2 = ((UserPos[i*2 + 1] << 8) & 0xFF00) + (UserPos[i * 2] & 0xFF);\r
+ for (j = 0; j < 8; j++) {\r
+ if ((tmpVal >> j) & BIT0) {\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("Use Group ID (%d), User Position (%d)\n",\r
+ (i*8+j), (tmpVal2 >> 2 * j)&0x3));\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /* Indicate GID frame to IHV service. */\r
+ {\r
+ u1Byte Indibuffer[24] = {0};\r
+ u1Byte Indioffset = 0;\r
+ \r
+ PlatformMoveMemory(Indibuffer + Indioffset, pBeamformEntry->gid_valid, 8);\r
+ Indioffset += 8;\r
+ PlatformMoveMemory(Indibuffer + Indioffset, pBeamformEntry->user_position, 16);\r
+ Indioffset += 16;\r
+\r
+ PlatformIndicateCustomStatus(\r
+ Adapter,\r
+ RT_CUSTOM_EVENT_VHT_RECV_GID_MGNT_FRAME,\r
+ RT_CUSTOM_INDI_TARGET_IHV,\r
+ Indibuffer,\r
+ Indioffset);\r
+ }\r
+\r
+ /* Config HW GID table */\r
+ halComTxbf_ConfigGtab(pDM_Odm);\r
+\r
+ return rtStatus;\r
+}\r
+\r
+/*\r
+// Description: Construct VHT Group ID (GID) management frame.\r
+//\r
+// 2015.05.20. Created by tynli.\r
+*/\r
+VOID\r
+ConstructVHTGIDMgntFrame(\r
+ IN PDM_ODM_T pDM_Odm,\r
+ IN pu1Byte RA,\r
+ IN PRT_BEAMFORMEE_ENTRY pBeamformEntry,\r
+ OUT pu1Byte Buffer,\r
+ OUT pu4Byte pLength\r
+ \r
+)\r
+{\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+ PADAPTER Adapter = pBeamInfo->SourceAdapter;\r
+ OCTET_STRING osFTMFrame, tmp;\r
+\r
+ FillOctetString(osFTMFrame, Buffer, 0);\r
+ *pLength = 0;\r
+\r
+ ConstructMaFrameHdr(\r
+ Adapter, \r
+ RA, \r
+ ACT_CAT_VHT, \r
+ ACT_VHT_GROUPID_MANAGEMENT, \r
+ &osFTMFrame);\r
+\r
+ /* Membership Status Array*/\r
+ FillOctetString(tmp, pBeamformEntry->gid_valid, 8);\r
+ PacketAppendData(&osFTMFrame, tmp);\r
+\r
+ /* User Position Array*/\r
+ FillOctetString(tmp, pBeamformEntry->user_position, 16);\r
+ PacketAppendData(&osFTMFrame, tmp);\r
+\r
+ *pLength = osFTMFrame.Length;\r
+\r
+ RT_DISP_DATA(FBEAM, FBEAM_DATA, "ConstructVHTGIDMgntFrame():\n", Buffer, *pLength);\r
+}\r
+\r
+BOOLEAN\r
+SendSWVHTGIDMgntFrame(\r
+ IN PVOID pDM_VOID,\r
+ IN pu1Byte RA,\r
+ IN u1Byte Idx\r
+ )\r
+{\r
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+ PRT_TCB pTcb;\r
+ PRT_TX_LOCAL_BUFFER pBuf;\r
+ BOOLEAN ret = TRUE;\r
+ u1Byte DataRate = 0;\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+ PRT_BEAMFORMEE_ENTRY pBeamformEntry = &pBeamInfo->BeamformeeEntry[Idx];\r
+ PADAPTER Adapter = pBeamInfo->SourceAdapter;\r
+\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));\r
+ \r
+ PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
+\r
+ if (MgntGetBuffer(Adapter, &pTcb, &pBuf)) {\r
+ ConstructVHTGIDMgntFrame(\r
+ pDM_Odm, \r
+ RA,\r
+ pBeamformEntry,\r
+ pBuf->Buffer.VirtualAddress, \r
+ &pTcb->PacketLength\r
+ );\r
+\r
+ pTcb->BWOfPacket = CHANNEL_WIDTH_20;\r
+ DataRate = MGN_6M;\r
+ MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, DataRate);\r
+ } else\r
+ ret = FALSE;\r
+ \r
+ PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);\r
+\r
+ if (ret)\r
+ RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+/*\r
+// Description: Construct VHT beamforming report poll.\r
+//\r
+// 2015.05.20. Created by tynli.\r
+*/\r
+VOID\r
+ConstructVHTBFReportPoll(\r
+ IN PDM_ODM_T pDM_Odm,\r
+ IN pu1Byte RA,\r
+ OUT pu1Byte Buffer,\r
+ OUT pu4Byte pLength\r
+)\r
+{\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+ PADAPTER Adapter = pBeamInfo->SourceAdapter;\r
+ pu1Byte pBFRptPoll = Buffer;\r
+ \r
+ /* Frame control*/\r
+ SET_80211_HDR_FRAME_CONTROL(pBFRptPoll, 0);\r
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pBFRptPoll, Type_Beamforming_Report_Poll);\r
+\r
+ /* Duration*/ \r
+ SET_80211_HDR_DURATION(pBFRptPoll, 100);\r
+\r
+ /* RA*/\r
+ SET_VHT_BF_REPORT_POLL_RA(pBFRptPoll, RA);\r
+\r
+ /* TA*/\r
+ SET_VHT_BF_REPORT_POLL_TA(pBFRptPoll, Adapter->CurrentAddress);\r
+\r
+ /* Feedback Segment Retransmission Bitmap*/\r
+ SET_VHT_BF_REPORT_POLL_FEEDBACK_SEG_RETRAN_BITMAP(pBFRptPoll, 0xFF);\r
+\r
+ *pLength = 17;\r
+\r
+ RT_DISP_DATA(FBEAM, FBEAM_DATA, "ConstructVHTBFReportPoll():\n", Buffer, *pLength);\r
+\r
+}\r
+\r
+BOOLEAN\r
+SendSWVHTBFReportPoll(\r
+ IN PVOID pDM_VOID,\r
+ IN pu1Byte RA,\r
+ IN BOOLEAN bFinalPoll\r
+ )\r
+{\r
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+ PRT_TCB pTcb;\r
+ PRT_TX_LOCAL_BUFFER pBuf;\r
+ BOOLEAN ret = TRUE;\r
+ u1Byte Idx = 0, DataRate = 0;\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+ PRT_BEAMFORMEE_ENTRY pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
+ PADAPTER Adapter = pBeamInfo->SourceAdapter;\r
+\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));\r
+\r
+ PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
+\r
+ if (MgntGetBuffer(Adapter, &pTcb, &pBuf)) {\r
+ ConstructVHTBFReportPoll(\r
+ pDM_Odm, \r
+ RA,\r
+ pBuf->Buffer.VirtualAddress, \r
+ &pTcb->PacketLength\r
+ );\r
+\r
+ pTcb->bTxEnableSwCalcDur = TRUE; /* <tynli_note> need?*/\r
+ pTcb->BWOfPacket = CHANNEL_WIDTH_20;\r
+\r
+ if (bFinalPoll)\r
+ pTcb->TxBFPktType = RT_BF_PKT_TYPE_FINAL_BF_REPORT_POLL;\r
+ else\r
+ pTcb->TxBFPktType = RT_BF_PKT_TYPE_BF_REPORT_POLL;\r
+ \r
+ DataRate = MGN_6M; /* Legacy OFDM rate*/\r
+ MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, DataRate);\r
+ } else\r
+ ret = FALSE;\r
+ \r
+ PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);\r
+\r
+ if (ret)\r
+ RT_DISP_DATA(FBEAM, FBEAM_DATA, "SendSWVHTBFReportPoll():\n", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
+\r
+ return ret;\r
+\r
+}\r
+\r
+\r
+/*\r
+// Description: Construct VHT MU NDPA packet.\r
+// <Note> We should combine this function with ConstructVHTNDPAPacket() in the future.\r
+//\r
+// 2015.05.21. Created by tynli.\r
+*/\r
+VOID\r
+ConstructVHTMUNDPAPacket(\r
+ IN PDM_ODM_T pDM_Odm,\r
+ IN CHANNEL_WIDTH BW,\r
+ OUT pu1Byte Buffer,\r
+ OUT pu4Byte pLength\r
+ )\r
+{ \r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+ PADAPTER Adapter = pBeamInfo->SourceAdapter;\r
+ u2Byte Duration = 0;\r
+ u1Byte Sequence = 0;\r
+ pu1Byte pNDPAFrame = Buffer;\r
+ RT_NDPA_STA_INFO STAInfo;\r
+ u1Byte idx;\r
+ u1Byte DestAddr[6] = {0};\r
+ PRT_BEAMFORMEE_ENTRY pEntry = NULL;\r
+\r
+ /* Fill the first MU BFee entry (STA1) MAC addr to destination address then\r
+ HW will change A1 to broadcast addr. 2015.05.28. Suggested by SD1 Chunchu. */\r
+ for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) { \r
+ pEntry = &(pBeamInfo->BeamformeeEntry[idx]);\r
+ if (pEntry->is_mu_sta) {\r
+ cpMacAddr(DestAddr, pEntry->MacAddr);\r
+ break;\r
+ }\r
+ }\r
+ if (pEntry == NULL)\r
+ return;\r
+ \r
+ /* Frame control.*/\r
+ SET_80211_HDR_FRAME_CONTROL(pNDPAFrame, 0);\r
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pNDPAFrame, Type_NDPA);\r
+\r
+ SET_80211_HDR_ADDRESS1(pNDPAFrame, DestAddr);\r
+ SET_80211_HDR_ADDRESS2(pNDPAFrame, pEntry->MyMacAddr);\r
+\r
+ /*--------------------------------------------*/\r
+ /* <Note> Need to modify "Duration" to MU consideration. */\r
+ Duration = 2*aSifsTime + 44;\r
+ \r
+ if (BW == CHANNEL_WIDTH_80)\r
+ Duration += 40;\r
+ else if(BW == CHANNEL_WIDTH_40)\r
+ Duration+= 87;\r
+ else \r
+ Duration+= 180;\r
+ /*--------------------------------------------*/\r
+\r
+ SET_80211_HDR_DURATION(pNDPAFrame, Duration);\r
+\r
+ Sequence = *(pDM_Odm->pSoundingSeq) << 2;\r
+ ODM_MoveMemory(pDM_Odm, pNDPAFrame + 16, &Sequence, 1);\r
+\r
+ *pLength = 17;\r
+\r
+ /* Construct STA info. for multiple STAs*/\r
+ for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) { \r
+ pEntry = &(pBeamInfo->BeamformeeEntry[idx]);\r
+ if (pEntry->is_mu_sta) {\r
+ STAInfo.AID = pEntry->AID;\r
+ STAInfo.FeedbackType = 1; /* 1'b1: MU*/\r
+ STAInfo.NcIndex = 0;\r
+\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Get BeamformeeEntry idx(%d), AID =%d\n", __func__, idx, pEntry->AID));\r
+ \r
+ ODM_MoveMemory(pDM_Odm, pNDPAFrame+(*pLength), (pu1Byte)&STAInfo, 2);\r
+ *pLength += 2;\r
+ }\r
+ }\r
+\r
+}\r
+\r
+BOOLEAN\r
+SendSWVHTMUNDPAPacket(\r
+ IN PVOID pDM_VOID,\r
+ IN CHANNEL_WIDTH BW\r
+ )\r
+{\r
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+ PRT_TCB pTcb;\r
+ PRT_TX_LOCAL_BUFFER pBuf;\r
+ BOOLEAN ret = TRUE;\r
+ u1Byte NDPTxRate = 0;\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+ PADAPTER Adapter = pBeamInfo->SourceAdapter;\r
+\r
+ NDPTxRate = MGN_VHT2SS_MCS0;\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
+\r
+ PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
+\r
+ if (MgntGetBuffer(Adapter, &pTcb, &pBuf)) {\r
+ ConstructVHTMUNDPAPacket(\r
+ pDM_Odm,\r
+ BW,\r
+ pBuf->Buffer.VirtualAddress, \r
+ &pTcb->PacketLength\r
+ );\r
+\r
+ pTcb->bTxEnableSwCalcDur = TRUE;\r
+ pTcb->BWOfPacket = BW;\r
+ pTcb->TxBFPktType = RT_BF_PKT_TYPE_BROADCAST_NDPA;\r
+\r
+ /*rate of NDP decide by Nr*/\r
+ MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, NDPTxRate);\r
+ } else\r
+ ret = FALSE;\r
+ \r
+ PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK); \r
+\r
+ if (ret)\r
+ RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+VOID\r
+DBG_ConstructVHTMUNDPAPacket(\r
+ IN PDM_ODM_T pDM_Odm,\r
+ IN CHANNEL_WIDTH BW,\r
+ OUT pu1Byte Buffer,\r
+ OUT pu4Byte pLength\r
+ )\r
+{ \r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+ PADAPTER Adapter = pBeamInfo->SourceAdapter;\r
+ u2Byte Duration = 0;\r
+ u1Byte Sequence = 0;\r
+ pu1Byte pNDPAFrame = Buffer;\r
+ RT_NDPA_STA_INFO STAInfo;\r
+ u1Byte idx;\r
+ u1Byte DestAddr[6] = {0};\r
+ PRT_BEAMFORMEE_ENTRY pEntry = NULL;\r
+\r
+ BOOLEAN is_STA1 = FALSE;\r
+\r
+\r
+ /* Fill the first MU BFee entry (STA1) MAC addr to destination address then\r
+ HW will change A1 to broadcast addr. 2015.05.28. Suggested by SD1 Chunchu. */\r
+ for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) { \r
+ pEntry = &(pBeamInfo->BeamformeeEntry[idx]);\r
+ if (pEntry->is_mu_sta) {\r
+ if (is_STA1 == FALSE) {\r
+ is_STA1 = TRUE;\r
+ continue;\r
+ } else {\r
+ cpMacAddr(DestAddr, pEntry->MacAddr);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ /* Frame control.*/\r
+ SET_80211_HDR_FRAME_CONTROL(pNDPAFrame, 0);\r
+ SET_80211_HDR_TYPE_AND_SUBTYPE(pNDPAFrame, Type_NDPA);\r
+\r
+ SET_80211_HDR_ADDRESS1(pNDPAFrame, DestAddr);\r
+ SET_80211_HDR_ADDRESS2(pNDPAFrame, pDM_Odm->CurrentAddress);\r
+\r
+ /*--------------------------------------------*/\r
+ /* <Note> Need to modify "Duration" to MU consideration. */\r
+ Duration = 2*aSifsTime + 44;\r
+ \r
+ if (BW == CHANNEL_WIDTH_80)\r
+ Duration += 40;\r
+ else if (BW == CHANNEL_WIDTH_40)\r
+ Duration += 87;\r
+ else \r
+ Duration += 180;\r
+ /*--------------------------------------------*/\r
+\r
+ SET_80211_HDR_DURATION(pNDPAFrame, Duration);\r
+\r
+ Sequence = *(pDM_Odm->pSoundingSeq) << 2;\r
+ ODM_MoveMemory(pDM_Odm, pNDPAFrame + 16, &Sequence, 1);\r
+\r
+ *pLength = 17;\r
+\r
+ /*STA2's STA Info*/\r
+ STAInfo.AID = pEntry->AID;\r
+ STAInfo.FeedbackType = 1; /* 1'b1: MU */\r
+ STAInfo.NcIndex = 0;\r
+\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Get BeamformeeEntry idx(%d), AID =%d\n", __func__, idx, pEntry->AID));\r
+ \r
+ ODM_MoveMemory(pDM_Odm, pNDPAFrame+(*pLength), (pu1Byte)&STAInfo, 2);\r
+ *pLength += 2;\r
+\r
+}\r
+\r
+BOOLEAN\r
+DBG_SendSWVHTMUNDPAPacket(\r
+ IN PVOID pDM_VOID,\r
+ IN CHANNEL_WIDTH BW\r
+ )\r
+{\r
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+ PRT_TCB pTcb;\r
+ PRT_TX_LOCAL_BUFFER pBuf;\r
+ BOOLEAN ret = TRUE;\r
+ u1Byte NDPTxRate = 0;\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+ PADAPTER Adapter = pBeamInfo->SourceAdapter;\r
+\r
+ NDPTxRate = MGN_VHT2SS_MCS0;\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
+\r
+ PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
+\r
+ if (MgntGetBuffer(Adapter, &pTcb, &pBuf)) {\r
+ DBG_ConstructVHTMUNDPAPacket(\r
+ pDM_Odm,\r
+ BW,\r
+ pBuf->Buffer.VirtualAddress, \r
+ &pTcb->PacketLength\r
+ );\r
+\r
+ pTcb->bTxEnableSwCalcDur = TRUE;\r
+ pTcb->BWOfPacket = BW;\r
+ pTcb->TxBFPktType = RT_BF_PKT_TYPE_UNICAST_NDPA;\r
+\r
+ /*rate of NDP decide by Nr*/\r
+ MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, NDPTxRate);\r
+ } else\r
+ ret = FALSE;\r
+ \r
+ PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK); \r
+\r
+ if (ret)\r
+ RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+#endif /*#if (SUPPORT_MU_BF == 1)*/\r
+#endif /*#ifdef SUPPORT_MU_BF*/\r
+\r
+\r
+#elif (DM_ODM_SUPPORT_TYPE == ODM_CE)\r
+\r
+u4Byte\r
+Beamforming_GetReportFrame(\r
+ IN PVOID pDM_VOID,\r
+ union recv_frame *precv_frame\r
+ )\r
+{\r
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+ u4Byte ret = _SUCCESS;\r
+ PRT_BEAMFORMEE_ENTRY pBeamformEntry = NULL;\r
+ pu1Byte pframe = precv_frame->u.hdr.rx_data;\r
+ u4Byte frame_len = precv_frame->u.hdr.len;\r
+ pu1Byte TA;\r
+ u1Byte Idx, offset;\r
+ \r
+\r
+ /*Memory comparison to see if CSI report is the same with previous one*/\r
+ TA = GetAddr2Ptr(pframe);\r
+ pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, TA, &Idx);\r
+ if(pBeamformEntry->BeamformEntryCap & BEAMFORMER_CAP_VHT_SU)\r
+ offset = 31; /*24+(1+1+3)+2 MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)*/\r
+ else if(pBeamformEntry->BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT)\r
+ offset = 34; /*24+(1+1+6)+2 MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)*/\r
+ else\r
+ return ret;\r
+\r
+ \r
+ return ret;\r
+}\r
+\r
+\r
+BOOLEAN\r
+SendFWHTNDPAPacket(\r
+ IN PVOID pDM_VOID,\r
+ IN pu1Byte RA,\r
+ IN CHANNEL_WIDTH BW\r
+ )\r
+{\r
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+ PADAPTER Adapter = pDM_Odm->Adapter;\r
+ struct xmit_frame *pmgntframe;\r
+ struct pkt_attrib *pattrib;\r
+ struct rtw_ieee80211_hdr *pwlanhdr;\r
+ struct xmit_priv *pxmitpriv = &(Adapter->xmitpriv);\r
+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;\r
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);\r
+ u1Byte ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};\r
+ u1Byte *pframe;\r
+ u2Byte *fctrl;\r
+ u2Byte duration = 0;\r
+ u1Byte aSifsTime = 0, NDPTxRate = 0, Idx = 0;\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+ PRT_BEAMFORMEE_ENTRY pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
+\r
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);\r
+ \r
+ if (pmgntframe == NULL) {\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, alloc mgnt frame fail\n", __func__));\r
+ return _FALSE;\r
+ }\r
+\r
+ //update attribute\r
+ pattrib = &pmgntframe->attrib;\r
+ update_mgntframe_attrib(Adapter, pattrib);\r
+\r
+ pattrib->qsel = QSLT_BEACON;\r
+ NDPTxRate = Beamforming_GetHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
+ pattrib->rate = NDPTxRate;\r
+ pattrib->bwmode = BW;\r
+ pattrib->order = 1;\r
+ pattrib->subtype = WIFI_ACTION_NOACK;\r
+\r
+ _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);\r
+\r
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;\r
+\r
+ pwlanhdr = (struct rtw_ieee80211_hdr*)pframe;\r
+\r
+ fctrl = &pwlanhdr->frame_ctl;\r
+ *(fctrl) = 0;\r
+\r
+ SetOrderBit(pframe);\r
+ SetFrameSubType(pframe, WIFI_ACTION_NOACK);\r
+\r
+ _rtw_memcpy(pwlanhdr->addr1, RA, ETH_ALEN);\r
+ _rtw_memcpy(pwlanhdr->addr2, pBeamformEntry->MyMacAddr, ETH_ALEN);\r
+ _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);\r
+\r
+ if( pmlmeext->cur_wireless_mode == WIRELESS_11B)\r
+ aSifsTime = 10;\r
+ else\r
+ aSifsTime = 16;\r
+\r
+ duration = 2*aSifsTime + 40;\r
+ \r
+ if(BW == CHANNEL_WIDTH_40)\r
+ duration+= 87;\r
+ else \r
+ duration+= 180;\r
+\r
+ SetDuration(pframe, duration);\r
+\r
+ //HT control field\r
+ SET_HT_CTRL_CSI_STEERING(pframe+24, 3);\r
+ SET_HT_CTRL_NDP_ANNOUNCEMENT(pframe+24, 1);\r
+\r
+ _rtw_memcpy(pframe+28, ActionHdr, 4);\r
+\r
+ pattrib->pktlen = 32;\r
+\r
+ pattrib->last_txcmdsz = pattrib->pktlen;\r
+\r
+ dump_mgntframe(Adapter, pmgntframe);\r
+\r
+ return _TRUE;\r
+}\r
+\r
+\r
+BOOLEAN\r
+SendSWHTNDPAPacket(\r
+ IN PVOID pDM_VOID,\r
+ IN pu1Byte RA,\r
+ IN CHANNEL_WIDTH BW\r
+ )\r
+{\r
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+ PADAPTER Adapter = pDM_Odm->Adapter;\r
+ struct xmit_frame *pmgntframe;\r
+ struct pkt_attrib *pattrib;\r
+ struct rtw_ieee80211_hdr *pwlanhdr;\r
+ struct xmit_priv *pxmitpriv = &(Adapter->xmitpriv);\r
+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;\r
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);\r
+ u1Byte ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};\r
+ pu1Byte pframe;\r
+ pu2Byte fctrl;\r
+ u2Byte duration = 0;\r
+ u1Byte aSifsTime = 0, NDPTxRate = 0, Idx = 0;\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+ PRT_BEAMFORMEE_ENTRY pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
+\r
+ NDPTxRate = Beamforming_GetHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
+ \r
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);\r
+ \r
+ if (pmgntframe == NULL) {\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, alloc mgnt frame fail\n", __func__));\r
+ return _FALSE;\r
+ }\r
+\r
+ /*update attribute*/\r
+ pattrib = &pmgntframe->attrib;\r
+ update_mgntframe_attrib(Adapter, pattrib);\r
+ pattrib->qsel = QSLT_MGNT;\r
+ pattrib->rate = NDPTxRate;\r
+ pattrib->bwmode = BW;\r
+ pattrib->order = 1;\r
+ pattrib->subtype = WIFI_ACTION_NOACK;\r
+\r
+ _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);\r
+\r
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;\r
+\r
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;\r
+\r
+ fctrl = &pwlanhdr->frame_ctl;\r
+ *(fctrl) = 0;\r
+\r
+ SetOrderBit(pframe);\r
+ SetFrameSubType(pframe, WIFI_ACTION_NOACK);\r
+\r
+ _rtw_memcpy(pwlanhdr->addr1, RA, ETH_ALEN);\r
+ _rtw_memcpy(pwlanhdr->addr2, pBeamformEntry->MyMacAddr, ETH_ALEN);\r
+ _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);\r
+\r
+ if (pmlmeext->cur_wireless_mode == WIRELESS_11B)\r
+ aSifsTime = 10;\r
+ else\r
+ aSifsTime = 16;\r
+\r
+ duration = 2*aSifsTime + 40;\r
+ \r
+ if (BW == CHANNEL_WIDTH_40)\r
+ duration += 87;\r
+ else \r
+ duration += 180;\r
+\r
+ SetDuration(pframe, duration);\r
+\r
+ /*HT control field*/\r
+ SET_HT_CTRL_CSI_STEERING(pframe+24, 3);\r
+ SET_HT_CTRL_NDP_ANNOUNCEMENT(pframe+24, 1);\r
+\r
+ _rtw_memcpy(pframe+28, ActionHdr, 4);\r
+\r
+ pattrib->pktlen = 32;\r
+\r
+ pattrib->last_txcmdsz = pattrib->pktlen;\r
+\r
+ dump_mgntframe(Adapter, pmgntframe);\r
+\r
+ return _TRUE;\r
+}\r
+\r
+\r
+BOOLEAN\r
+SendFWVHTNDPAPacket(\r
+ IN PVOID pDM_VOID,\r
+ IN pu1Byte RA,\r
+ IN u2Byte AID,\r
+ IN CHANNEL_WIDTH BW\r
+ )\r
+{\r
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+ PADAPTER Adapter = pDM_Odm->Adapter;\r
+ struct xmit_frame *pmgntframe;\r
+ struct pkt_attrib *pattrib;\r
+ struct rtw_ieee80211_hdr *pwlanhdr;\r
+ struct xmit_priv *pxmitpriv = &(Adapter->xmitpriv);\r
+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;\r
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);\r
+ struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);\r
+ pu1Byte pframe;\r
+ pu2Byte fctrl;\r
+ u2Byte duration = 0;\r
+ u1Byte sequence = 0, aSifsTime = 0, NDPTxRate= 0, Idx = 0;\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+ PRT_BEAMFORMEE_ENTRY pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
+ RT_NDPA_STA_INFO sta_info;\r
+\r
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);\r
+ \r
+ if (pmgntframe == NULL) {\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, alloc mgnt frame fail\n", __func__));\r
+ return _FALSE;\r
+ }\r
+\r
+ //update attribute\r
+ pattrib = &pmgntframe->attrib;\r
+ _rtw_memcpy(pattrib->ra, RA, ETH_ALEN);\r
+ update_mgntframe_attrib(Adapter, pattrib);\r
+\r
+ pattrib->qsel = QSLT_BEACON;\r
+ NDPTxRate = Beamforming_GetVHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
+ pattrib->rate = NDPTxRate;\r
+ pattrib->bwmode = BW;\r
+ pattrib->subtype = WIFI_NDPA;\r
+\r
+ _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);\r
+\r
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;\r
+\r
+ pwlanhdr = (struct rtw_ieee80211_hdr*)pframe;\r
+\r
+ fctrl = &pwlanhdr->frame_ctl;\r
+ *(fctrl) = 0;\r
+\r
+ SetFrameSubType(pframe, WIFI_NDPA);\r
+\r
+ _rtw_memcpy(pwlanhdr->addr1, RA, ETH_ALEN);\r
+ _rtw_memcpy(pwlanhdr->addr2, pBeamformEntry->MyMacAddr, ETH_ALEN);\r
+\r
+ if (IsSupported5G(pmlmeext->cur_wireless_mode) || IsSupportedHT(pmlmeext->cur_wireless_mode))\r
+ aSifsTime = 16;\r
+ else\r
+ aSifsTime = 10;\r
+\r
+ duration = 2*aSifsTime + 44;\r
+ \r
+ if(BW == CHANNEL_WIDTH_80)\r
+ duration += 40;\r
+ else if(BW == CHANNEL_WIDTH_40)\r
+ duration+= 87;\r
+ else \r
+ duration+= 180;\r
+\r
+ SetDuration(pframe, duration);\r
+\r
+ sequence = pBeamInfo->SoundingSequence<< 2;\r
+ if (pBeamInfo->SoundingSequence >= 0x3f)\r
+ pBeamInfo->SoundingSequence = 0;\r
+ else\r
+ pBeamInfo->SoundingSequence++;\r
+\r
+ _rtw_memcpy(pframe+16, &sequence,1);\r
+\r
+ if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))\r
+ AID = 0; \r
+\r
+ sta_info.AID = AID;\r
+ sta_info.FeedbackType = 0;\r
+ sta_info.NcIndex= 0;\r
+ \r
+ _rtw_memcpy(pframe+17, (u8 *)&sta_info, 2);\r
+\r
+ pattrib->pktlen = 19;\r
+\r
+ pattrib->last_txcmdsz = pattrib->pktlen;\r
+\r
+ dump_mgntframe(Adapter, pmgntframe);\r
+\r
+ return _TRUE;\r
+}\r
+\r
+\r
+\r
+BOOLEAN\r
+SendSWVHTNDPAPacket(\r
+ IN PVOID pDM_VOID,\r
+ IN pu1Byte RA,\r
+ IN u2Byte AID,\r
+ IN CHANNEL_WIDTH BW\r
+ )\r
+{\r
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+ PADAPTER Adapter = pDM_Odm->Adapter;\r
+ struct xmit_frame *pmgntframe;\r
+ struct pkt_attrib *pattrib;\r
+ struct rtw_ieee80211_hdr *pwlanhdr;\r
+ struct xmit_priv *pxmitpriv = &(Adapter->xmitpriv);\r
+ struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;\r
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);\r
+ struct mlme_priv *pmlmepriv = &(Adapter->mlmepriv);\r
+ RT_NDPA_STA_INFO ndpa_sta_info;\r
+ u1Byte NDPTxRate = 0, sequence = 0, aSifsTime = 0, Idx = 0;\r
+ pu1Byte pframe;\r
+ pu2Byte fctrl;\r
+ u2Byte duration = 0;\r
+ PRT_BEAMFORMING_INFO pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+ PRT_BEAMFORMEE_ENTRY pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
+\r
+ NDPTxRate = Beamforming_GetVHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
+\r
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);\r
+ \r
+ if (pmgntframe == NULL) {\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, alloc mgnt frame fail\n", __func__));\r
+ return _FALSE;\r
+ }\r
+ \r
+ /*update attribute*/\r
+ pattrib = &pmgntframe->attrib;\r
+ _rtw_memcpy(pattrib->ra, RA, ETH_ALEN);\r
+ update_mgntframe_attrib(Adapter, pattrib);\r
+ pattrib->qsel = QSLT_MGNT;\r
+ pattrib->rate = NDPTxRate;\r
+ pattrib->bwmode = BW;\r
+ pattrib->subtype = WIFI_NDPA;\r
+\r
+ _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);\r
+\r
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;\r
+\r
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;\r
+\r
+ fctrl = &pwlanhdr->frame_ctl;\r
+ *(fctrl) = 0;\r
+\r
+ SetFrameSubType(pframe, WIFI_NDPA);\r
+\r
+ _rtw_memcpy(pwlanhdr->addr1, RA, ETH_ALEN);\r
+ _rtw_memcpy(pwlanhdr->addr2, pBeamformEntry->MyMacAddr, ETH_ALEN);\r
+\r
+ if (IsSupported5G(pmlmeext->cur_wireless_mode) || IsSupportedHT(pmlmeext->cur_wireless_mode))\r
+ aSifsTime = 16;\r
+ else\r
+ aSifsTime = 10;\r
+\r
+ duration = 2*aSifsTime + 44;\r
+ \r
+ if (BW == CHANNEL_WIDTH_80)\r
+ duration += 40;\r
+ else if (BW == CHANNEL_WIDTH_40)\r
+ duration += 87;\r
+ else \r
+ duration += 180;\r
+\r
+ SetDuration(pframe, duration);\r
+ \r
+ sequence = pBeamInfo->SoundingSequence << 2;\r
+ if (pBeamInfo->SoundingSequence >= 0x3f)\r
+ pBeamInfo->SoundingSequence = 0;\r
+ else\r
+ pBeamInfo->SoundingSequence++;\r
+\r
+ _rtw_memcpy(pframe+16, &sequence, 1);\r
+ if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))\r
+ AID = 0; \r
+\r
+ ndpa_sta_info.AID = AID;\r
+ ndpa_sta_info.FeedbackType = 0;\r
+ ndpa_sta_info.NcIndex = 0;\r
+ \r
+ _rtw_memcpy(pframe+17, (u8 *)&ndpa_sta_info, 2);\r
+\r
+ pattrib->pktlen = 19;\r
+\r
+ pattrib->last_txcmdsz = pattrib->pktlen;\r
+\r
+ dump_mgntframe(Adapter, pmgntframe);\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] [%d]\n", __func__, __LINE__));\r
+ \r
+ return _TRUE;\r
+}\r
+\r
+\r
+#endif\r
+\r
+\r
+VOID\r
+Beamforming_GetNDPAFrame(\r
+ IN PVOID pDM_VOID,\r
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
+ IN OCTET_STRING pduOS\r
+#elif (DM_ODM_SUPPORT_TYPE == ODM_CE)\r
+ union recv_frame *precv_frame\r
+#endif\r
+)\r
+{\r
+ PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+ PADAPTER Adapter = pDM_Odm->Adapter;\r
+ pu1Byte TA ;\r
+ u1Byte Idx, Sequence;\r
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
+ pu1Byte pNDPAFrame = pduOS.Octet;\r
+#elif (DM_ODM_SUPPORT_TYPE == ODM_CE)\r
+ pu1Byte pNDPAFrame = precv_frame->u.hdr.rx_data;\r
+#endif\r
+ PRT_BEAMFORMER_ENTRY pBeamformerEntry = NULL; /*Modified By Jeffery @2014-10-29*/\r
+ \r
+\r
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
+ RT_DISP_DATA(FBEAM, FBEAM_DATA, "Beamforming_GetNDPAFrame\n", pduOS.Octet, pduOS.Length);\r
+ if (IsCtrlNDPA(pNDPAFrame) == FALSE)\r
+#elif (DM_ODM_SUPPORT_TYPE == ODM_CE)\r
+ if (GetFrameSubType(pNDPAFrame) != WIFI_NDPA)\r
+#endif\r
+ return;\r
+ else if (!(pDM_Odm->SupportICType & (ODM_RTL8812 | ODM_RTL8821))) {\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] not 8812 or 8821A, return\n", __func__));\r
+ return;\r
+ }\r
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
+ TA = Frame_Addr2(pduOS);\r
+#elif (DM_ODM_SUPPORT_TYPE == ODM_CE)\r
+ TA = GetAddr2Ptr(pNDPAFrame);\r
+#endif\r
+ /*Remove signaling TA. */\r
+ TA[0] = TA[0] & 0xFE;\r
+ \r
+ pBeamformerEntry = phydm_Beamforming_GetBFerEntryByAddr(pDM_Odm, TA, &Idx); // Modified By Jeffery @2014-10-29\r
+\r
+ /*Break options for Clock Reset*/ \r
+ if (pBeamformerEntry == NULL)\r
+ return;\r
+ else if (!(pBeamformerEntry->BeamformEntryCap & BEAMFORMEE_CAP_VHT_SU))\r
+ return;\r
+ /*LogSuccess: As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is NO LONGER needed !2015-04-10, Jeffery*/\r
+ /*ClockResetTimes: While BFer entry always doesn't receive our CSI, clock will reset again and again.So ClockResetTimes is limited to 5 times.2015-04-13, Jeffery*/\r
+ else if ((pBeamformerEntry->LogSuccess == 1) || (pBeamformerEntry->ClockResetTimes == 5)) {\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] LogSeq=%d, PreLogSeq=%d, LogRetryCnt=%d, LogSuccess=%d, ClockResetTimes=%d, clock reset is no longer needed.\n", \r
+ __func__, pBeamformerEntry->LogSeq, pBeamformerEntry->PreLogSeq, pBeamformerEntry->LogRetryCnt, pBeamformerEntry->LogSuccess, pBeamformerEntry->ClockResetTimes));\r
+\r
+ return;\r
+ }\r
+\r
+ Sequence = (pNDPAFrame[16]) >> 2;\r
+\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start, Sequence=%d, LogSeq=%d, PreLogSeq=%d, LogRetryCnt=%d, ClockResetTimes=%d, LogSuccess=%d\n", \r
+ __func__, Sequence, pBeamformerEntry->LogSeq, pBeamformerEntry->PreLogSeq, pBeamformerEntry->LogRetryCnt, pBeamformerEntry->ClockResetTimes, pBeamformerEntry->LogSuccess));\r
+\r
+ if ((pBeamformerEntry->LogSeq != 0) && (pBeamformerEntry->PreLogSeq != 0)) {\r
+ /*Success condition*/\r
+ if ((pBeamformerEntry->LogSeq != Sequence) && (pBeamformerEntry->PreLogSeq != pBeamformerEntry->LogSeq)) {\r
+ /* break option for clcok reset, 2015-03-30, Jeffery */\r
+ pBeamformerEntry->LogRetryCnt = 0;\r
+ /*As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is no longer needed.*/\r
+ /*That is, LogSuccess is NOT needed to be reset to zero, 2015-04-13, Jeffery*/\r
+ pBeamformerEntry->LogSuccess = 1;\r
+\r
+ } else {/*Fail condition*/\r
+\r
+ if (pBeamformerEntry->LogRetryCnt == 5) {\r
+ pBeamformerEntry->ClockResetTimes++;\r
+ pBeamformerEntry->LogRetryCnt = 0;\r
+\r
+ ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Clock Reset!!! ClockResetTimes=%d\n", \r
+ __func__, pBeamformerEntry->ClockResetTimes));\r
+ HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_CLK, NULL);\r
+\r
+ } else\r
+ pBeamformerEntry->LogRetryCnt++;\r
+ }\r
+ }\r
+\r
+ /*Update LogSeq & PreLogSeq*/\r
+ pBeamformerEntry->PreLogSeq = pBeamformerEntry->LogSeq;\r
+ pBeamformerEntry->LogSeq = Sequence;\r
+ \r
+}\r
+\r
+\r
+\r
+#endif\r