net: wireless: rockchip: add rtl8822be pcie wifi driver
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8822be / hal / phydm / txbf / haltxbfinterface.c
diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfinterface.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/txbf/haltxbfinterface.c
new file mode 100644 (file)
index 0000000..4fbad2d
--- /dev/null
@@ -0,0 +1,1502 @@
+//============================================================\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