net: wireless: rockchip: add rtl8822be pcie wifi driver
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8822be / hal / phydm / phydm_beamforming.c
diff --git a/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_beamforming.c b/drivers/net/wireless/rockchip_wlan/rtl8822be/hal/phydm/phydm_beamforming.c
new file mode 100644 (file)
index 0000000..790f150
--- /dev/null
@@ -0,0 +1,1896 @@
+#include "mp_precomp.h"\r
+#include "phydm_precomp.h"\r
+\r
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
+#if WPP_SOFTWARE_TRACE\r
+#include "phydm_beamforming.tmh"\r
+#endif\r
+#endif\r
+\r
+#if (BEAMFORMING_SUPPORT == 1)\r
+\r
+PRT_BEAMFORM_STAINFO\r
+phydm_staInfoInit(\r
+       IN PDM_ODM_T            pDM_Odm,\r
+       IN u2Byte                       staIdx\r
+       )\r
+{\r
+       PRT_BEAMFORMING_INFO            pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+       PRT_BEAMFORM_STAINFO            pEntry = &(pBeamInfo->BeamformSTAinfo);\r
+       PSTA_INFO_T                                     pSTA = pDM_Odm->pODM_StaInfo[staIdx];\r
+       PADAPTER                                        Adapter = pDM_Odm->Adapter;\r
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
+       PMGNT_INFO                                      pMgntInfo = &Adapter->MgntInfo;\r
+       PRT_HIGH_THROUGHPUT             pHTInfo = GET_HT_INFO(pMgntInfo);\r
+       PRT_VERY_HIGH_THROUGHPUT        pVHTInfo = GET_VHT_INFO(pMgntInfo);\r
+       u1Byte                                          iotpeer = 0;\r
+\r
+       iotpeer = pMgntInfo->IOTPeer;\r
+       ODM_MoveMemory(pDM_Odm, pEntry->MyMacAddr, Adapter->CurrentAddress, 6);\r
+       \r
+       if ((iotpeer == HT_IOT_PEER_ATHEROS) && !(pMgntInfo->RegUsbSafetySwitch & RT_UsbSafetySwitch_skip_bfer_For_QCA) )\r
+               {\r
+               pEntry->HtBeamformCap = pHTInfo->HtBeamformCap & (~BEAMFORMING_HT_BEAMFORMEE_ENABLE);\r
+               pEntry->VhtBeamformCap = pVHTInfo->VhtBeamformCap & (~BEAMFORMING_VHT_BEAMFORMEE_ENABLE);\r
+       } else {        \r
+               pEntry->HtBeamformCap = pHTInfo->HtBeamformCap;\r
+               pEntry->VhtBeamformCap = pVHTInfo->VhtBeamformCap;\r
+       }\r
+\r
+       /*IBSS, AP mode*/\r
+       if (staIdx != 0) {\r
+               pEntry->AID = pSTA->AID;\r
+               pEntry->RA = pSTA->MacAddr;\r
+               pEntry->MacID = pSTA->AssociatedMacId;\r
+               pEntry->WirelessMode = pSTA->WirelessMode;\r
+               pEntry->BW = pSTA->BandWidth;\r
+               pEntry->CurBeamform = pSTA->HTInfo.HtCurBeamform;\r
+       } else {/*client mode*/\r
+               pEntry->AID = pMgntInfo->mAId;\r
+               pEntry->RA = pMgntInfo->Bssid;\r
+               pEntry->MacID = pMgntInfo->mMacId;\r
+               pEntry->WirelessMode = pMgntInfo->dot11CurrentWirelessMode;\r
+               pEntry->BW = pMgntInfo->dot11CurrentChannelBandWidth;\r
+               pEntry->CurBeamform = pHTInfo->HtCurBeamform;\r
+       }       \r
+\r
+       if ((pEntry->WirelessMode & WIRELESS_MODE_AC_5G) || (pEntry->WirelessMode & WIRELESS_MODE_AC_24G)) {\r
+               if (staIdx != 0)\r
+                       pEntry->CurBeamformVHT = pSTA->VHTInfo.VhtCurBeamform;\r
+               else\r
+                       pEntry->CurBeamformVHT = pVHTInfo->VhtCurBeamform;      \r
+\r
+               if ((iotpeer == HT_IOT_PEER_ATHEROS) && !(pMgntInfo->RegUsbSafetySwitch & RT_UsbSafetySwitch_skip_bfer_For_QCA) )\r
+                       pEntry->CurBeamformVHT = pEntry->CurBeamformVHT & (~BEAMFORMING_VHT_BEAMFORMEE_ENABLE);\r
+               else    \r
+                       pEntry->CurBeamformVHT = pEntry->CurBeamformVHT;\r
+               \r
+       }\r
+       \r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("pSTA->wireless_mode = 0x%x, staidx = %d\n", pSTA->WirelessMode, staIdx));\r
+#elif (DM_ODM_SUPPORT_TYPE == ODM_CE)\r
+\r
+       if (!IS_STA_VALID(pSTA)) {\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s => sta_info(mac_id:%d) failed\n", __func__, staIdx));\r
+               rtw_warn_on(1);\r
+               return pEntry;\r
+       }\r
+\r
+       ODM_MoveMemory(pDM_Odm, pEntry->MyMacAddr, adapter_mac_addr(pSTA->padapter), 6);\r
+       pEntry->HtBeamformCap = pSTA->htpriv.beamform_cap;\r
+\r
+       pEntry->AID = pSTA->aid;\r
+       pEntry->RA = pSTA->hwaddr;\r
+       pEntry->MacID = pSTA->mac_id;\r
+       pEntry->WirelessMode = pSTA->wireless_mode;\r
+       pEntry->BW = pSTA->bw_mode;\r
+\r
+       pEntry->CurBeamform = pSTA->htpriv.beamform_cap;\r
+#if    ODM_IC_11AC_SERIES_SUPPORT\r
+       if ((pEntry->WirelessMode & WIRELESS_MODE_AC_5G) || (pEntry->WirelessMode & WIRELESS_MODE_AC_24G)) {\r
+               pEntry->CurBeamformVHT = pSTA->vhtpriv.beamform_cap;\r
+               pEntry->VhtBeamformCap = pSTA->vhtpriv.beamform_cap;\r
+       }\r
+#endif\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("pSTA->wireless_mode = 0x%x, staidx = %d\n", pSTA->wireless_mode, staIdx));\r
+#endif\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("pEntry->CurBeamform = 0x%x, pEntry->CurBeamformVHT = 0x%x\n", pEntry->CurBeamform, pEntry->CurBeamformVHT));\r
+       return pEntry;\r
+\r
+}\r
+void phydm_staInfoUpdate(\r
+       IN PDM_ODM_T                    pDM_Odm,\r
+       IN u2Byte                               staIdx,\r
+       PRT_BEAMFORMEE_ENTRY    pBeamformEntry\r
+       )\r
+{\r
+       PSTA_INFO_T pSTA = pDM_Odm->pODM_StaInfo[staIdx];\r
+       \r
+       if (!IS_STA_VALID(pSTA))\r
+               return;\r
+       \r
+#if (DM_ODM_SUPPORT_TYPE == ODM_CE)\r
+       pSTA->txbf_paid = pBeamformEntry->P_AID;\r
+       pSTA->txbf_gid = pBeamformEntry->G_ID;\r
+#endif \r
+}\r
+       \r
+PRT_BEAMFORMEE_ENTRY\r
+phydm_Beamforming_GetBFeeEntryByAddr(\r
+       IN      PVOID           pDM_VOID,\r
+       IN      pu1Byte         RA,\r
+       OUT     pu1Byte         Idx\r
+       )\r
+{\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       u1Byte  i = 0;\r
+       PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+       \r
+       for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {\r
+               if (pBeamInfo->BeamformeeEntry[i].bUsed && (eqMacAddr(RA, pBeamInfo->BeamformeeEntry[i].MacAddr))) {\r
+                       *Idx = i;\r
+                       return &(pBeamInfo->BeamformeeEntry[i]);\r
+               }\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+PRT_BEAMFORMER_ENTRY\r
+phydm_Beamforming_GetBFerEntryByAddr(\r
+       IN      PVOID   pDM_VOID,\r
+       IN      pu1Byte         TA,\r
+       OUT     pu1Byte Idx\r
+       )\r
+{\r
+       PDM_ODM_T       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       u1Byte          i = 0;\r
+       PRT_BEAMFORMING_INFO    pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+       \r
+       for (i = 0; i < BEAMFORMER_ENTRY_NUM; i++) {\r
+               if (pBeamInfo->BeamformerEntry[i].bUsed &&  (eqMacAddr(TA, pBeamInfo->BeamformerEntry[i].MacAddr))) {\r
+                       *Idx = i;\r
+                       return &(pBeamInfo->BeamformerEntry[i]);\r
+               }\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+\r
+PRT_BEAMFORMEE_ENTRY\r
+phydm_Beamforming_GetEntryByMacId(\r
+       IN      PVOID           pDM_VOID,\r
+       IN      u1Byte          MacId,\r
+       OUT     pu1Byte         Idx\r
+       )\r
+{\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       u1Byte  i = 0;\r
+       PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+       \r
+       for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {\r
+               if (pBeamInfo->BeamformeeEntry[i].bUsed && (MacId == pBeamInfo->BeamformeeEntry[i].MacId)) {\r
+                       *Idx = i;\r
+                       return &(pBeamInfo->BeamformeeEntry[i]);\r
+               }\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+\r
+BEAMFORMING_CAP\r
+phydm_Beamforming_GetEntryBeamCapByMacId(\r
+       IN      PVOID           pDM_VOID,\r
+       IN      u1Byte          MacId\r
+       )\r
+{\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       u1Byte  i = 0;\r
+       PRT_BEAMFORMING_INFO    pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+       BEAMFORMING_CAP                 BeamformEntryCap = BEAMFORMING_CAP_NONE;\r
+       \r
+       for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {\r
+               if (pBeamInfo->BeamformeeEntry[i].bUsed && (MacId == pBeamInfo->BeamformeeEntry[i].MacId)) {\r
+                       BeamformEntryCap =  pBeamInfo->BeamformeeEntry[i].BeamformEntryCap;\r
+                       i = BEAMFORMEE_ENTRY_NUM;\r
+               }\r
+       }\r
+\r
+       return BeamformEntryCap;\r
+}\r
+\r
+\r
+PRT_BEAMFORMEE_ENTRY\r
+phydm_Beamforming_GetFreeBFeeEntry(\r
+       IN      PVOID           pDM_VOID,\r
+       OUT     pu1Byte         Idx\r
+       )\r
+{\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       u1Byte  i = 0;\r
+       PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+\r
+       for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {\r
+               if (pBeamInfo->BeamformeeEntry[i].bUsed == FALSE) {\r
+                       *Idx = i;\r
+                       return &(pBeamInfo->BeamformeeEntry[i]);\r
+               }       \r
+       }\r
+       return NULL;\r
+}\r
+\r
+PRT_BEAMFORMER_ENTRY\r
+phydm_Beamforming_GetFreeBFerEntry(\r
+       IN      PVOID           pDM_VOID,\r
+       OUT     pu1Byte         Idx\r
+       )\r
+{\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       u1Byte  i = 0;\r
+       PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s ===>\n", __func__));\r
+\r
+       for (i = 0; i < BEAMFORMER_ENTRY_NUM; i++) {\r
+               if (pBeamInfo->BeamformerEntry[i].bUsed == FALSE) {\r
+                       *Idx = i;\r
+                       return &(pBeamInfo->BeamformerEntry[i]);\r
+               }       \r
+       }\r
+       return NULL;\r
+}\r
+\r
+/*\r
+// Description: Get the first entry index of MU Beamformee.\r
+//\r
+// Return Value: Index of the first MU sta.\r
+//\r
+// 2015.05.25. Created by tynli.\r
+//\r
+*/\r
+u1Byte\r
+phydm_Beamforming_GetFirstMUBFeeEntryIdx(\r
+       IN      PVOID           pDM_VOID\r
+       )\r
+{\r
+       PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       u1Byte                                  idx = 0xFF;\r
+       PRT_BEAMFORMING_INFO    pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+       BOOLEAN                                 bFound = FALSE;\r
+\r
+       for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) {\r
+               if (pBeamInfo->BeamformeeEntry[idx].bUsed && pBeamInfo->BeamformeeEntry[idx].is_mu_sta) {                       \r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] idx=%d!\n", __func__, idx));\r
+                       bFound = TRUE;\r
+                       break;\r
+               }       \r
+       }\r
+\r
+       if (!bFound)\r
+               idx = 0xFF;\r
+\r
+       return idx;\r
+}\r
+\r
+\r
+/*Add SU BFee and MU BFee*/\r
+PRT_BEAMFORMEE_ENTRY\r
+Beamforming_AddBFeeEntry(\r
+       IN      PVOID                                   pDM_VOID,\r
+       IN      PRT_BEAMFORM_STAINFO    pSTA,\r
+       IN      BEAMFORMING_CAP         BeamformCap,\r
+       IN      u1Byte                                  NumofSoundingDim,\r
+       IN      u1Byte                                  CompSteeringNumofBFer,\r
+       OUT     pu1Byte                                 Idx\r
+       )\r
+{\r
+       PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PRT_BEAMFORMEE_ENTRY    pEntry = phydm_Beamforming_GetFreeBFeeEntry(pDM_Odm, Idx);\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __func__));\r
+\r
+       if (pEntry != NULL) {   \r
+               pEntry->bUsed = TRUE;\r
+               pEntry->AID = pSTA->AID;\r
+               pEntry->MacId = pSTA->MacID;\r
+               pEntry->SoundBW = pSTA->BW;\r
+               ODM_MoveMemory(pDM_Odm, pEntry->MyMacAddr, pSTA->MyMacAddr, 6);\r
+               \r
+               if (phydm_actingDetermine(pDM_Odm, PhyDM_ACTING_AS_AP)) {\r
+                       /*BSSID[44:47] xor BSSID[40:43]*/\r
+                       u2Byte BSSID = ((pSTA->MyMacAddr[5] & 0xf0) >> 4) ^ (pSTA->MyMacAddr[5] & 0xf);\r
+                       /*(dec(A) + dec(B)*32) mod 512*/\r
+                       pEntry->P_AID = (pSTA->AID + BSSID * 32) & 0x1ff;\r
+                       pEntry->G_ID = 63;\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: BFee P_AID addressed to STA=%d\n", __func__, pEntry->P_AID));\r
+               } else if (phydm_actingDetermine(pDM_Odm, PhyDM_ACTING_AS_IBSS)) {\r
+                       /*ad hoc mode*/\r
+                       pEntry->P_AID = 0;\r
+                       pEntry->G_ID = 63;\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: BFee P_AID as IBSS=%d\n", __func__, pEntry->P_AID));\r
+               } else {\r
+                       /*client mode*/\r
+                       pEntry->P_AID =  pSTA->RA[5];\r
+                       /*BSSID[39:47]*/\r
+                       pEntry->P_AID = (pEntry->P_AID << 1) | (pSTA->RA[4] >> 7);\r
+                       pEntry->G_ID = 0;\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: BFee P_AID addressed to AP=0x%X\n", __func__, pEntry->P_AID));\r
+               }\r
+               cpMacAddr(pEntry->MacAddr, pSTA->RA);\r
+               pEntry->bTxBF = FALSE;\r
+               pEntry->bSound = FALSE;\r
+               pEntry->SoundPeriod = 400;\r
+               pEntry->BeamformEntryCap = BeamformCap;\r
+               pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;\r
+\r
+/*             pEntry->LogSeq = 0xff;                          Move to Beamforming_AddBFerEntry*/\r
+/*             pEntry->LogRetryCnt = 0;                        Move to Beamforming_AddBFerEntry*/\r
+/*             pEntry->LogSuccessCnt = 0;              Move to Beamforming_AddBFerEntry*/\r
+\r
+               pEntry->LogStatusFailCnt = 0;\r
+\r
+               pEntry->NumofSoundingDim = NumofSoundingDim;\r
+               pEntry->CompSteeringNumofBFer = CompSteeringNumofBFer;\r
+\r
+               if (BeamformCap & BEAMFORMER_CAP_VHT_MU) {\r
+                       pDM_Odm->BeamformingInfo.beamformee_mu_cnt += 1;\r
+                       pEntry->is_mu_sta = TRUE;\r
+                       pDM_Odm->BeamformingInfo.FirstMUBFeeIndex = phydm_Beamforming_GetFirstMUBFeeEntryIdx(pDM_Odm);\r
+               } else if  (BeamformCap & (BEAMFORMER_CAP_VHT_SU|BEAMFORMER_CAP_HT_EXPLICIT)) {\r
+                       pDM_Odm->BeamformingInfo.beamformee_su_cnt += 1;\r
+                       pEntry->is_mu_sta = FALSE;\r
+               }\r
+\r
+               return pEntry;\r
+       }\r
+       else\r
+               return NULL;\r
+}\r
+\r
+/*Add SU BFee and MU BFer*/\r
+PRT_BEAMFORMER_ENTRY\r
+Beamforming_AddBFerEntry(\r
+       IN      PVOID                                   pDM_VOID,\r
+       IN      PRT_BEAMFORM_STAINFO    pSTA,\r
+       IN      BEAMFORMING_CAP         BeamformCap,\r
+       IN      u1Byte                                  NumofSoundingDim,\r
+       OUT     pu1Byte                                 Idx\r
+       )\r
+{\r
+       PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PRT_BEAMFORMER_ENTRY    pEntry = phydm_Beamforming_GetFreeBFerEntry(pDM_Odm, Idx);\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __func__));\r
+\r
+       if (pEntry != NULL) {\r
+               pEntry->bUsed = TRUE;\r
+               ODM_MoveMemory(pDM_Odm, pEntry->MyMacAddr, pSTA->MyMacAddr, 6);\r
+               if (phydm_actingDetermine(pDM_Odm, PhyDM_ACTING_AS_AP)) {\r
+                       /*BSSID[44:47] xor BSSID[40:43]*/\r
+                       u2Byte BSSID = ((pSTA->MyMacAddr[5] & 0xf0) >> 4) ^ (pSTA->MyMacAddr[5] & 0xf);\r
+                       \r
+                       pEntry->P_AID = (pSTA->AID + BSSID * 32) & 0x1ff;\r
+                       pEntry->G_ID = 63;\r
+                       /*(dec(A) + dec(B)*32) mod 512*/\r
+               } else if (phydm_actingDetermine(pDM_Odm, PhyDM_ACTING_AS_IBSS)) {\r
+                       pEntry->P_AID = 0;\r
+                       pEntry->G_ID = 63;\r
+               } else {\r
+                       pEntry->P_AID =  pSTA->RA[5];\r
+                       /*BSSID[39:47]*/\r
+                       pEntry->P_AID = (pEntry->P_AID << 1) | (pSTA->RA[4] >> 7);\r
+                       pEntry->G_ID = 0;\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: P_AID addressed to AP=0x%X\n", __func__, pEntry->P_AID));\r
+               }\r
+               \r
+               cpMacAddr(pEntry->MacAddr, pSTA->RA);\r
+               pEntry->BeamformEntryCap = BeamformCap;\r
+\r
+               pEntry->PreLogSeq = 0;  /*Modified by Jeffery @2015-04-13*/\r
+               pEntry->LogSeq = 0;             /*Modified by Jeffery @2014-10-29*/\r
+               pEntry->LogRetryCnt = 0;        /*Modified by Jeffery @2014-10-29*/\r
+               pEntry->LogSuccess = 0; /*LogSuccess is NOT needed to be accumulated, so  LogSuccessCnt->LogSuccess, 2015-04-13, Jeffery*/\r
+               pEntry->ClockResetTimes = 0;    /*Modified by Jeffery @2015-04-13*/\r
+\r
+               pEntry->NumofSoundingDim = NumofSoundingDim;\r
+\r
+               if (BeamformCap & BEAMFORMEE_CAP_VHT_MU) {\r
+                       pDM_Odm->BeamformingInfo.beamformer_mu_cnt += 1;\r
+                       pEntry->is_mu_ap = TRUE;\r
+                       pEntry->AID = pSTA->AID;\r
+               } else if (BeamformCap & (BEAMFORMEE_CAP_VHT_SU|BEAMFORMEE_CAP_HT_EXPLICIT)) {\r
+                       pDM_Odm->BeamformingInfo.beamformer_su_cnt += 1;\r
+                       pEntry->is_mu_ap = FALSE;\r
+               }\r
+\r
+               return pEntry;\r
+       }\r
+       else\r
+               return NULL;\r
+}\r
+\r
+#if 0\r
+BOOLEAN\r
+Beamforming_RemoveEntry(\r
+       IN      PADAPTER                        Adapter,\r
+       IN      pu1Byte         RA,\r
+       OUT     pu1Byte         Idx\r
+       )\r
+{\r
+       HAL_DATA_TYPE                   *pHalData = GET_HAL_DATA(Adapter);\r
+       PDM_ODM_T                               pDM_Odm = &pHalData->DM_OutSrc;\r
+\r
+       PRT_BEAMFORMER_ENTRY    pBFerEntry = phydm_Beamforming_GetBFerEntryByAddr(pDM_Odm, RA, Idx);\r
+       PRT_BEAMFORMEE_ENTRY    pEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, Idx);\r
+       BOOLEAN ret = FALSE;\r
+    \r
+       RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s Start!\n", __func__));\r
+       RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s, pBFerEntry=0x%x\n", __func__, pBFerEntry));\r
+       RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s, pEntry=0x%x\n", __func__, pEntry));\r
+       \r
+       if (pEntry != NULL) {   \r
+               pEntry->bUsed = FALSE;\r
+               pEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE;\r
+               /*pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;*/\r
+               pEntry->bBeamformingInProgress = FALSE;\r
+               ret = TRUE;\r
+       } \r
+       if (pBFerEntry != NULL) {\r
+               pBFerEntry->bUsed = FALSE;\r
+               pBFerEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE;\r
+               ret = TRUE;\r
+       }\r
+       return ret;\r
+\r
+}\r
+#endif\r
+\r
+/* Used for BeamformingStart_V1  */\r
+VOID\r
+phydm_Beamforming_NDPARate(\r
+       IN      PVOID           pDM_VOID,\r
+       CHANNEL_WIDTH   BW, \r
+       u1Byte                  Rate\r
+)\r
+{\r
+       u2Byte                  NDPARate = Rate;\r
+       PDM_ODM_T               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       \r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __func__));\r
+\r
+       if (NDPARate == 0) {\r
+               if(pDM_Odm->RSSI_Min > 30) // link RSSI > 30%\r
+                       NDPARate = ODM_RATE24M;\r
+               else\r
+                       NDPARate = ODM_RATE6M;\r
+       }\r
+\r
+       if (NDPARate < ODM_RATEMCS0)\r
+               BW = (CHANNEL_WIDTH)ODM_BW20M;\r
+\r
+       NDPARate = (NDPARate << 8) | BW;\r
+       HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_RATE, (pu1Byte)&NDPARate);\r
+\r
+}\r
+\r
+\r
+/* Used for BeamformingStart_SW and  BeamformingStart_FW */\r
+VOID\r
+phydm_Beamforming_DymNDPARate(\r
+       IN      PVOID           pDM_VOID\r
+)\r
+{\r
+       u2Byte                  NDPARate = ODM_RATE6M, BW;\r
+       PDM_ODM_T               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __func__));\r
+\r
+       if (pDM_Odm->RSSI_Min > 30)     /*link RSSI > 30%*/\r
+               NDPARate = ODM_RATE24M;\r
+       else\r
+               NDPARate = ODM_RATE6M;\r
+\r
+       BW = ODM_BW20M;\r
+       NDPARate = NDPARate << 8 | BW;\r
+       HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_RATE, (pu1Byte)&NDPARate);\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s End, NDPA Rate = 0x%X\n", __func__, NDPARate));\r
+}\r
+\r
+/*     \r
+*      SW Sounding : SW Timer unit 1ms \r
+*                               HW Timer unit (1/32000) s  32k is clock. \r
+*      FW Sounding : FW Timer unit 10ms\r
+*/\r
+VOID\r
+Beamforming_DymPeriod(\r
+       IN      PVOID           pDM_VOID,\r
+       IN  u8          status\r
+)\r
+{\r
+       u1Byte                                  Idx;\r
+       BOOLEAN                                 bChangePeriod = FALSE;  \r
+       u2Byte                                  SoundPeriod_SW, SoundPeriod_FW;\r
+       PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+\r
+       PRT_BEAMFORMEE_ENTRY    pBeamformEntry;\r
+       PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+       PRT_SOUNDING_INFO               pSoundInfo = &(pBeamInfo->SoundingInfo);\r
+\r
+       PRT_BEAMFORMEE_ENTRY    pEntry = &(pBeamInfo->BeamformeeEntry[pBeamInfo->BeamformeeCurIdx]);\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));\r
+       \r
+       //3 TODO  per-client throughput caculation.\r
+\r
+       if ((*(pDM_Odm->pCurrentTxTP) + *(pDM_Odm->pCurrentRxTP) > 2) && ((pEntry->LogStatusFailCnt <= 20) || status)) {\r
+               SoundPeriod_SW = 40;    /* 40ms */\r
+               SoundPeriod_FW = 40;    /* From  H2C cmd, unit = 10ms */\r
+       } else {\r
+               SoundPeriod_SW = 4000;/* 4s */\r
+               SoundPeriod_FW = 400;\r
+       }\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s]SoundPeriod_SW=%d, SoundPeriod_FW=%d\n",     __func__, SoundPeriod_SW, SoundPeriod_FW));\r
+\r
+       for (Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++) {\r
+               pBeamformEntry = pBeamInfo->BeamformeeEntry+Idx;\r
+               \r
+               if (pBeamformEntry->DefaultCSICnt > 20) {\r
+                       /*Modified by David*/\r
+                       SoundPeriod_SW = 4000;\r
+                       SoundPeriod_FW = 400;\r
+               }\r
+               \r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Period = %d\n", __func__, SoundPeriod_SW));         \r
+               if (pBeamformEntry->BeamformEntryCap & (BEAMFORMER_CAP_HT_EXPLICIT | BEAMFORMER_CAP_VHT_SU)) {\r
+                       if (pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER) {                          \r
+                               if (pBeamformEntry->SoundPeriod != SoundPeriod_FW) {\r
+                                       pBeamformEntry->SoundPeriod = SoundPeriod_FW;\r
+                                       bChangePeriod = TRUE;           /*Only FW sounding need to send H2C packet to change sound period. */\r
+                               }\r
+                       } else if (pBeamformEntry->SoundPeriod != SoundPeriod_SW) {\r
+                               pBeamformEntry->SoundPeriod = SoundPeriod_SW;\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (bChangePeriod)\r
+               HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_FW_NDPA, (pu1Byte)&Idx);\r
+}\r
+\r
+\r
+\r
+\r
+BOOLEAN\r
+Beamforming_SendHTNDPAPacket(\r
+       IN      PVOID                   pDM_VOID,\r
+       IN      pu1Byte                 RA,\r
+       IN      CHANNEL_WIDTH   BW,\r
+       IN      u1Byte                  QIdx\r
+       )\r
+{\r
+       BOOLEAN         ret = TRUE;\r
+       PDM_ODM_T       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+\r
+       if (QIdx == BEACON_QUEUE)\r
+               ret = SendFWHTNDPAPacket(pDM_Odm, RA, BW);\r
+       else\r
+               ret = SendSWHTNDPAPacket(pDM_Odm, RA, BW);\r
+\r
+       return ret;\r
+}\r
+\r
+\r
+\r
+BOOLEAN\r
+Beamforming_SendVHTNDPAPacket(\r
+       IN      PVOID                   pDM_VOID,\r
+       IN      pu1Byte                 RA,\r
+       IN      u2Byte                  AID,\r
+       IN      CHANNEL_WIDTH   BW,\r
+       IN      u1Byte                  QIdx\r
+       )\r
+{\r
+       PDM_ODM_T       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       BOOLEAN         ret = TRUE;\r
+       PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+\r
+       HalComTxbf_Set(pDM_Odm, TXBF_SET_GET_TX_RATE, NULL);\r
+\r
+       if ((pDM_Odm->TxBfDataRate >= ODM_RATEVHTSS3MCS7) && (pDM_Odm->TxBfDataRate <= ODM_RATEVHTSS3MCS9) && (pBeamInfo->snding3SS == FALSE)) {\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s: 3SS VHT 789 don't sounding\n", __func__));\r
+\r
+       } else  {\r
+               if (QIdx == BEACON_QUEUE) /* Send to reserved page => FW NDPA */\r
+                       ret = SendFWVHTNDPAPacket(pDM_Odm, RA, AID, BW);\r
+               else {\r
+#ifdef SUPPORT_MU_BF\r
+               #if (SUPPORT_MU_BF == 1)\r
+                       pBeamInfo->is_mu_sounding = TRUE;\r
+                       ret = SendSWVHTMUNDPAPacket(pDM_Odm, BW);\r
+               #else\r
+                       pBeamInfo->is_mu_sounding = FALSE;\r
+                       ret = SendSWVHTNDPAPacket(pDM_Odm, RA, AID, BW);\r
+               #endif\r
+#else\r
+                       pBeamInfo->is_mu_sounding = FALSE;\r
+                       ret = SendSWVHTNDPAPacket(pDM_Odm, RA, AID, BW);\r
+#endif\r
+               }\r
+       }\r
+               return ret;\r
+}\r
+\r
+\r
+BEAMFORMING_NOTIFY_STATE\r
+phydm_beamfomring_bSounding(\r
+       IN      PVOID                           pDM_VOID,\r
+       PRT_BEAMFORMING_INFO    pBeamInfo,\r
+       pu1Byte                                 Idx\r
+       )\r
+{\r
+       BEAMFORMING_NOTIFY_STATE        bSounding = BEAMFORMING_NOTIFY_NONE;\r
+       RT_BEAMFORMING_OID_INFO BeamOidInfo = pBeamInfo->BeamformingOidInfo;\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __func__));\r
+\r
+       /*if(( Beamforming_GetBeamCap(pBeamInfo) & BEAMFORMER_CAP) == 0)*/\r
+       /*bSounding = BEAMFORMING_NOTIFY_RESET;*/\r
+       if (BeamOidInfo.SoundOidMode == SOUNDING_STOP_All_TIMER)\r
+               bSounding = BEAMFORMING_NOTIFY_RESET;\r
+       else {\r
+               u1Byte i;\r
+\r
+               for (i = 0 ; i < BEAMFORMEE_ENTRY_NUM ; i++) {\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s: BFee Entry %d bUsed=%d, bSound=%d\n", __func__, i, pBeamInfo->BeamformeeEntry[i].bUsed, pBeamInfo->BeamformeeEntry[i].bSound));\r
+                       if (pBeamInfo->BeamformeeEntry[i].bUsed && (!pBeamInfo->BeamformeeEntry[i].bSound)) {\r
+                               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: Add BFee entry %d\n", __func__, i));\r
+                               *Idx = i;\r
+                               if (pBeamInfo->BeamformeeEntry[i].is_mu_sta)\r
+                                       bSounding = BEAMFORMEE_NOTIFY_ADD_MU;\r
+                               else\r
+                                       bSounding = BEAMFORMEE_NOTIFY_ADD_SU;\r
+                       }\r
+\r
+                       if ((!pBeamInfo->BeamformeeEntry[i].bUsed) && pBeamInfo->BeamformeeEntry[i].bSound) {\r
+                               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: Delete BFee entry %d\n", __func__, i));\r
+                               *Idx = i;\r
+                               if (pBeamInfo->BeamformeeEntry[i].is_mu_sta)\r
+                                       bSounding = BEAMFORMEE_NOTIFY_DELETE_MU;\r
+                               else\r
+                                       bSounding = BEAMFORMEE_NOTIFY_DELETE_SU;\r
+                       }\r
+               }\r
+       }\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s End, bSounding = %d\n", __func__, bSounding));\r
+       return bSounding;\r
+}\r
+\r
+\r
+//This function is unused\r
+u1Byte\r
+phydm_beamforming_SoundingIdx(\r
+       IN      PVOID                           pDM_VOID,\r
+       PRT_BEAMFORMING_INFO            pBeamInfo\r
+       )\r
+{\r
+       u1Byte                                  Idx = 0;\r
+       RT_BEAMFORMING_OID_INFO BeamOidInfo = pBeamInfo->BeamformingOidInfo;\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __func__));\r
+\r
+       if (BeamOidInfo.SoundOidMode == SOUNDING_SW_HT_TIMER || BeamOidInfo.SoundOidMode == SOUNDING_SW_VHT_TIMER ||\r
+               BeamOidInfo.SoundOidMode == SOUNDING_HW_HT_TIMER || BeamOidInfo.SoundOidMode == SOUNDING_HW_VHT_TIMER)\r
+               Idx = BeamOidInfo.SoundOidIdx;\r
+       else {\r
+               u1Byte  i;\r
+               for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {\r
+                       if (pBeamInfo->BeamformeeEntry[i].bUsed && (FALSE == pBeamInfo->BeamformeeEntry[i].bSound)) {\r
+                               Idx = i;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+\r
+       return Idx;\r
+}\r
+\r
+\r
+SOUNDING_MODE\r
+phydm_beamforming_SoundingMode(\r
+       IN      PVOID                           pDM_VOID,\r
+       PRT_BEAMFORMING_INFO    pBeamInfo,\r
+       u1Byte                                  Idx\r
+       )\r
+{\r
+       PDM_ODM_T               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       u1Byte                  SupportInterface = pDM_Odm->SupportInterface;\r
+\r
+       RT_BEAMFORMEE_ENTRY             BeamEntry = pBeamInfo->BeamformeeEntry[Idx];\r
+       RT_BEAMFORMING_OID_INFO BeamOidInfo = pBeamInfo->BeamformingOidInfo;\r
+       SOUNDING_MODE                           Mode = BeamOidInfo.SoundOidMode;\r
+\r
+       if (BeamOidInfo.SoundOidMode == SOUNDING_SW_VHT_TIMER || BeamOidInfo.SoundOidMode == SOUNDING_HW_VHT_TIMER) {\r
+               if (BeamEntry.BeamformEntryCap & BEAMFORMER_CAP_VHT_SU)\r
+                       Mode = BeamOidInfo.SoundOidMode;\r
+               else \r
+                       Mode = SOUNDING_STOP_All_TIMER;\r
+       } else if (BeamOidInfo.SoundOidMode == SOUNDING_SW_HT_TIMER || BeamOidInfo.SoundOidMode == SOUNDING_HW_HT_TIMER) {\r
+               if (BeamEntry.BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT)\r
+                       Mode = BeamOidInfo.SoundOidMode;\r
+               else\r
+                       Mode = SOUNDING_STOP_All_TIMER;\r
+       } else if (BeamEntry.BeamformEntryCap & BEAMFORMER_CAP_VHT_SU) {\r
+               if ((SupportInterface == ODM_ITRF_USB) && !(pDM_Odm->SupportICType & (ODM_RTL8814A | ODM_RTL8822B)))\r
+                       Mode = SOUNDING_FW_VHT_TIMER;\r
+               else\r
+                       Mode = SOUNDING_SW_VHT_TIMER;\r
+       } else if (BeamEntry.BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT) {\r
+               if ((SupportInterface == ODM_ITRF_USB) && !(pDM_Odm->SupportICType & (ODM_RTL8814A | ODM_RTL8822B)))\r
+                       Mode = SOUNDING_FW_HT_TIMER;\r
+               else\r
+                       Mode = SOUNDING_SW_HT_TIMER;\r
+       } else \r
+               Mode = SOUNDING_STOP_All_TIMER;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] SupportInterface=%d, Mode=%d\n", __func__, SupportInterface, Mode));\r
+\r
+       return Mode;\r
+}\r
+\r
+\r
+u2Byte\r
+phydm_beamforming_SoundingTime(\r
+       IN      PVOID                           pDM_VOID,\r
+       PRT_BEAMFORMING_INFO    pBeamInfo,\r
+       SOUNDING_MODE                   Mode,\r
+       u1Byte                                  Idx\r
+       )\r
+{\r
+       u2Byte                                          SoundingTime = 0xffff;\r
+       RT_BEAMFORMEE_ENTRY             BeamEntry = pBeamInfo->BeamformeeEntry[Idx];\r
+       RT_BEAMFORMING_OID_INFO BeamOidInfo = pBeamInfo->BeamformingOidInfo;\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __func__));\r
+\r
+       if (Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_HW_VHT_TIMER)\r
+               SoundingTime = BeamOidInfo.SoundOidPeriod * 32;\r
+       else if (Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_SW_VHT_TIMER)\r
+               /*Modified by David*/\r
+               SoundingTime = BeamEntry.SoundPeriod;   /*BeamOidInfo.SoundOidPeriod;*/\r
+       else\r
+               SoundingTime = BeamEntry.SoundPeriod;\r
+\r
+       return SoundingTime;\r
+}\r
+\r
+\r
+CHANNEL_WIDTH\r
+phydm_beamforming_SoundingBW(\r
+       IN      PVOID                           pDM_VOID,\r
+       PRT_BEAMFORMING_INFO    pBeamInfo,\r
+       SOUNDING_MODE                   Mode,\r
+       u1Byte                                  Idx\r
+       )\r
+{\r
+       CHANNEL_WIDTH                           SoundingBW = CHANNEL_WIDTH_20;\r
+       RT_BEAMFORMEE_ENTRY             BeamEntry = pBeamInfo->BeamformeeEntry[Idx];\r
+       RT_BEAMFORMING_OID_INFO BeamOidInfo = pBeamInfo->BeamformingOidInfo;\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+\r
+       if (Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_HW_VHT_TIMER)\r
+               SoundingBW = BeamOidInfo.SoundOidBW;\r
+       else if (Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_SW_VHT_TIMER)\r
+               /*Modified by David*/\r
+               SoundingBW = BeamEntry.SoundBW;         /*BeamOidInfo.SoundOidBW;*/\r
+       else \r
+               SoundingBW = BeamEntry.SoundBW;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, SoundingBW=0x%X\n", __func__, SoundingBW));\r
+\r
+       return SoundingBW;\r
+}\r
+\r
+\r
+BOOLEAN\r
+phydm_Beamforming_SelectBeamEntry(\r
+       IN      PVOID                           pDM_VOID,\r
+       PRT_BEAMFORMING_INFO    pBeamInfo\r
+       )\r
+{\r
+       PRT_SOUNDING_INFO               pSoundInfo = &(pBeamInfo->SoundingInfo);\r
+       PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+\r
+       /*pEntry.bSound is different between first and latter NDPA, and should not be used as BFee entry selection*/\r
+       /*BTW, latter modification should sync to the selection mechanism of AP/ADSL instead of the fixed SoundIdx.*/\r
+       pSoundInfo->SoundIdx = phydm_beamforming_SoundingIdx(pDM_Odm, pBeamInfo);\r
+       /*pSoundInfo->SoundIdx = 0;*/\r
+\r
+       if (pSoundInfo->SoundIdx < BEAMFORMEE_ENTRY_NUM)\r
+               pSoundInfo->SoundMode = phydm_beamforming_SoundingMode(pDM_Odm, pBeamInfo, pSoundInfo->SoundIdx);\r
+       else\r
+               pSoundInfo->SoundMode = SOUNDING_STOP_All_TIMER;\r
+       \r
+       if (SOUNDING_STOP_All_TIMER == pSoundInfo->SoundMode) {\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Return because of SOUNDING_STOP_All_TIMER\n", __func__));\r
+               return FALSE;\r
+       } else {\r
+               pSoundInfo->SoundBW = phydm_beamforming_SoundingBW(pDM_Odm, pBeamInfo, pSoundInfo->SoundMode, pSoundInfo->SoundIdx );\r
+               pSoundInfo->SoundPeriod = phydm_beamforming_SoundingTime(pDM_Odm, pBeamInfo, pSoundInfo->SoundMode, pSoundInfo->SoundIdx );\r
+               return TRUE;\r
+       }\r
+}\r
+\r
+/*SU BFee Entry Only*/\r
+BOOLEAN\r
+phydm_beamforming_StartPeriod(\r
+       IN      PVOID                           pDM_VOID\r
+       )\r
+{\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PADAPTER                                        Adapter = pDM_Odm->Adapter;\r
+       BOOLEAN                                         Ret = TRUE;\r
+       PRT_BEAMFORMING_INFO            pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+       PRT_SOUNDING_INFO                       pSoundInfo = &(pBeamInfo->SoundingInfo); \r
+       \r
+       phydm_Beamforming_DymNDPARate(pDM_Odm);\r
+\r
+       phydm_Beamforming_SelectBeamEntry(pDM_Odm, pBeamInfo);          // Modified\r
+\r
+       if (pSoundInfo->SoundMode == SOUNDING_SW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_SW_HT_TIMER)\r
+               ODM_SetTimer(pDM_Odm, &pBeamInfo->BeamformingTimer, pSoundInfo->SoundPeriod);\r
+       else if (pSoundInfo->SoundMode == SOUNDING_HW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_HW_HT_TIMER ||\r
+                       pSoundInfo->SoundMode == SOUNDING_AUTO_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_AUTO_HT_TIMER) {\r
+               HAL_HW_TIMER_TYPE TimerType = HAL_TIMER_TXBF;\r
+               u4Byte  val = (pSoundInfo->SoundPeriod | (TimerType<<16));\r
+\r
+               //HW timer stop: All IC has the same setting\r
+               Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_STOP,  (pu1Byte)(&TimerType));\r
+               //ODM_Write1Byte(pDM_Odm, 0x15F, 0);\r
+               //HW timer init: All IC has the same setting, but 92E & 8812A only write 2 bytes\r
+               Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_INIT,  (pu1Byte)(&val));\r
+               //ODM_Write1Byte(pDM_Odm, 0x164, 1);\r
+               //ODM_Write4Byte(pDM_Odm, 0x15C, val);\r
+               //HW timer start: All IC has the same setting\r
+               Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_START,  (pu1Byte)(&TimerType));\r
+               //ODM_Write1Byte(pDM_Odm, 0x15F, 0x5);\r
+       } else if (pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER)\r
+               Ret = BeamformingStart_FW(pDM_Odm, pSoundInfo->SoundIdx);\r
+       else\r
+               Ret = FALSE;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] SoundIdx=%d, SoundMode=%d, SoundBW=%d, SoundPeriod=%d\n", __func__, \r
+                       pSoundInfo->SoundIdx, pSoundInfo->SoundMode, pSoundInfo->SoundBW, pSoundInfo->SoundPeriod));\r
+\r
+       return Ret;\r
+}\r
+\r
+// Used after Beamforming_Leave, and will clear the setting of the "already deleted" entry\r
+/*SU BFee Entry Only*/\r
+VOID\r
+phydm_beamforming_EndPeriod_SW(\r
+       IN      PVOID                           pDM_VOID\r
+       )\r
+{\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PADAPTER                                        Adapter = pDM_Odm->Adapter;\r
+       PRT_BEAMFORMING_INFO            pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+       PRT_SOUNDING_INFO                       pSoundInfo = &(pBeamInfo->SoundingInfo);\r
+       \r
+       HAL_HW_TIMER_TYPE TimerType = HAL_TIMER_TXBF;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __func__));\r
+\r
+       if (pSoundInfo->SoundMode == SOUNDING_SW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_SW_HT_TIMER)\r
+               ODM_CancelTimer(pDM_Odm, &pBeamInfo->BeamformingTimer);\r
+       else if (pSoundInfo->SoundMode == SOUNDING_HW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_HW_HT_TIMER ||\r
+                               pSoundInfo->SoundMode == SOUNDING_AUTO_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_AUTO_HT_TIMER)\r
+               /*HW timer stop: All IC has the same setting*/\r
+               Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_STOP,  (pu1Byte)(&TimerType));\r
+               /*ODM_Write1Byte(pDM_Odm, 0x15F, 0);*/\r
+}\r
+\r
+VOID\r
+phydm_beamforming_EndPeriod_FW(\r
+       IN      PVOID                           pDM_VOID\r
+       )\r
+{\r
+       PDM_ODM_T                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       u1Byte                          Idx = 0;\r
+\r
+       HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_FW_NDPA, (pu1Byte)&Idx);\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s]\n", __func__));\r
+}\r
+\r
+\r
+/*SU BFee Entry Only*/\r
+VOID \r
+phydm_beamforming_ClearEntry_SW(\r
+       IN      PVOID                   pDM_VOID,\r
+       BOOLEAN                         IsDelete,\r
+       u1Byte                          DeleteIdx\r
+       )\r
+{\r
+       u1Byte                                          Idx = 0;\r
+       PRT_BEAMFORMEE_ENTRY            pBeamformEntry = NULL;\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PRT_BEAMFORMING_INFO            pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+\r
+       if (IsDelete) {\r
+               if (DeleteIdx < BEAMFORMEE_ENTRY_NUM) {\r
+                       pBeamformEntry = pBeamInfo->BeamformeeEntry + DeleteIdx;\r
+                       if (!((!pBeamformEntry->bUsed) && pBeamformEntry->bSound)) {\r
+                               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] SW DeleteIdx is wrong!!!!!\n", __func__));\r
+                               return;\r
+                       }\r
+               }\r
+\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] SW delete BFee entry %d\n", __func__, DeleteIdx));\r
+               if (pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSING) {\r
+                       pBeamformEntry->bBeamformingInProgress = FALSE;\r
+                       pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;\r
+               } else if (pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSED) {\r
+                       pBeamformEntry->BeamformEntryState  = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;\r
+                       HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&DeleteIdx);\r
+               }\r
+               pBeamformEntry->bSound = FALSE;\r
+       } else {\r
+               for (Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++) {\r
+                       pBeamformEntry = pBeamInfo->BeamformeeEntry+Idx;\r
+\r
+                       /*Used after bSounding=RESET, and will clear the setting of "ever sounded" entry, which is not necessarily be deleted.*/\r
+                       /*This function is mainly used in case "BeamOidInfo.SoundOidMode == SOUNDING_STOP_All_TIMER".*/\r
+                       /*However, setting oid doesn't delete entries (bUsed is still TRUE), new entries may fail to be added in.*/\r
+               \r
+                       if (pBeamformEntry->bSound) {\r
+                               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] SW reset BFee entry %d\n", __func__, Idx));\r
+                               /*      \r
+                               *       If End procedure is \r
+                               *       1. Between (Send NDPA, C2H packet return), reset state to initialized.\r
+                               *       After C2H packet return , status bit will be set to zero. \r
+                               *\r
+                               *       2. After C2H packet, then reset state to initialized and clear status bit.\r
+                               */\r
+\r
+                               if (pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSING)\r
+                                       phydm_Beamforming_End_SW(pDM_Odm, 0);\r
+                               else if (pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSED) {\r
+                                       pBeamformEntry->BeamformEntryState  = BEAMFORMING_ENTRY_STATE_INITIALIZED;\r
+                                       HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&Idx);\r
+                               }\r
+\r
+                               pBeamformEntry->bSound = FALSE;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+VOID\r
+phydm_beamforming_ClearEntry_FW(\r
+       IN      PVOID                   pDM_VOID,\r
+       BOOLEAN                         IsDelete,\r
+       u1Byte                          DeleteIdx\r
+       )\r
+{\r
+       u1Byte                                          Idx = 0;\r
+       PRT_BEAMFORMEE_ENTRY            pBeamformEntry = NULL;\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PRT_BEAMFORMING_INFO            pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+\r
+       if (IsDelete) {\r
+               if (DeleteIdx < BEAMFORMEE_ENTRY_NUM) {\r
+                       pBeamformEntry = pBeamInfo->BeamformeeEntry + DeleteIdx;\r
+\r
+                       if (!((!pBeamformEntry->bUsed) && pBeamformEntry->bSound)) {\r
+                               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] FW DeleteIdx is wrong!!!!!\n", __func__));\r
+                               return;\r
+                       }\r
+               }\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: FW delete BFee entry %d\n", __func__, DeleteIdx));\r
+               pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;\r
+               pBeamformEntry->bSound = FALSE;\r
+       } else {\r
+               for (Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++) {\r
+                       pBeamformEntry = pBeamInfo->BeamformeeEntry+Idx;\r
+\r
+                       /*Used after bSounding=RESET, and will clear the setting of "ever sounded" entry, which is not necessarily be deleted.*/\r
+                       /*This function is mainly used in case "BeamOidInfo.SoundOidMode == SOUNDING_STOP_All_TIMER".*/\r
+                       /*However, setting oid doesn't delete entries (bUsed is still TRUE), new entries may fail to be added in.*/\r
+               \r
+                       if (pBeamformEntry->bSound) {\r
+                               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s]FW reset BFee entry %d\n", __func__, Idx));\r
+                               /*      \r
+                               *       If End procedure is \r
+                               *       1. Between (Send NDPA, C2H packet return), reset state to initialized.\r
+                               *       After C2H packet return , status bit will be set to zero. \r
+                               *\r
+                               *       2. After C2H packet, then reset state to initialized and clear status bit.\r
+                               */\r
+                               \r
+                               pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;\r
+                               pBeamformEntry->bSound = FALSE;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+/*\r
+*      Called : \r
+*      1. Add and delete entry : Beamforming_Enter/Beamforming_Leave\r
+*      2. FW trigger :  Beamforming_SetTxBFen\r
+*      3. Set OID_RT_BEAMFORMING_PERIOD : BeamformingControl_V2\r
+*/\r
+VOID\r
+phydm_Beamforming_Notify(\r
+       IN      PVOID                   pDM_VOID\r
+       )\r
+{\r
+       u1Byte                                          Idx=BEAMFORMEE_ENTRY_NUM;\r
+       BEAMFORMING_NOTIFY_STATE        bSounding = BEAMFORMING_NOTIFY_NONE;\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PRT_BEAMFORMING_INFO            pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+       PRT_SOUNDING_INFO                       pSoundInfo = &(pBeamInfo->SoundingInfo);\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __func__));\r
+\r
+       bSounding = phydm_beamfomring_bSounding(pDM_Odm, pBeamInfo, &Idx);\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, Before notify, bSounding=%d, Idx=%d\n", __func__, bSounding, Idx));\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: pBeamInfo->beamformee_su_cnt = %d\n", __func__, pBeamInfo->beamformee_su_cnt));\r
+       \r
+\r
+       switch (bSounding) {\r
+       case BEAMFORMEE_NOTIFY_ADD_SU:\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: BEAMFORMEE_NOTIFY_ADD_SU\n", __func__));\r
+               phydm_beamforming_StartPeriod(pDM_Odm);\r
+       break;\r
+\r
+       case BEAMFORMEE_NOTIFY_DELETE_SU:\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: BEAMFORMEE_NOTIFY_DELETE_SU\n", __func__));\r
+               if (pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER) {\r
+                       phydm_beamforming_ClearEntry_FW(pDM_Odm, TRUE, Idx);\r
+                       if (pBeamInfo->beamformee_su_cnt == 0) { /* For 2->1 entry, we should not cancel SW timer */\r
+                               phydm_beamforming_EndPeriod_FW(pDM_Odm);\r
+                               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: No BFee left\n", __func__));\r
+                       }\r
+               } else {\r
+                       phydm_beamforming_ClearEntry_SW(pDM_Odm, TRUE, Idx);\r
+                       if (pBeamInfo->beamformee_su_cnt == 0) { /* For 2->1 entry, we should not cancel SW timer */\r
+                               phydm_beamforming_EndPeriod_SW(pDM_Odm);\r
+                               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: No BFee left\n", __func__));\r
+                       }\r
+               }\r
+       break;\r
+\r
+       case BEAMFORMEE_NOTIFY_ADD_MU:\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: BEAMFORMEE_NOTIFY_ADD_MU\n", __func__));\r
+               if (pBeamInfo->beamformee_mu_cnt == 2) {\r
+                       /*if (pSoundInfo->SoundMode == SOUNDING_SW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_SW_HT_TIMER)\r
+                               ODM_SetTimer(pDM_Odm, &pBeamInfo->BeamformingTimer, pSoundInfo->SoundPeriod);*/\r
+                       ODM_SetTimer(pDM_Odm, &pBeamInfo->BeamformingTimer, 1000); /*Do MU sounding every 1sec*/\r
+               } else\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: Less or larger than 2 MU STAs, not to set timer\n", __func__));\r
+       break;\r
+\r
+       case BEAMFORMEE_NOTIFY_DELETE_MU:\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: BEAMFORMEE_NOTIFY_DELETE_MU\n", __func__));\r
+               if (pBeamInfo->beamformee_mu_cnt == 1) {\r
+                       /*if (pSoundInfo->SoundMode == SOUNDING_SW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_SW_HT_TIMER)*/{\r
+                               ODM_CancelTimer(pDM_Odm, &pBeamInfo->BeamformingTimer);\r
+                               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: Less than 2 MU STAs, stop sounding\n", __func__));\r
+                       }\r
+               }\r
+       break;\r
+\r
+       case BEAMFORMING_NOTIFY_RESET:\r
+               if (pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER) {  \r
+                       phydm_beamforming_ClearEntry_FW(pDM_Odm, FALSE, Idx);\r
+                       phydm_beamforming_EndPeriod_FW(pDM_Odm);\r
+               } else {\r
+                       phydm_beamforming_ClearEntry_SW(pDM_Odm, FALSE, Idx);\r
+                       phydm_beamforming_EndPeriod_SW(pDM_Odm);\r
+               }\r
+\r
+       break;\r
+\r
+       default:\r
+       break;\r
+       }\r
+\r
+}\r
+\r
+\r
+\r
+BOOLEAN\r
+Beamforming_InitEntry(\r
+       IN      PVOID           pDM_VOID,\r
+       IN      u2Byte          staIdx,\r
+       pu1Byte                 BFerBFeeIdx\r
+       )\r
+{\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PRT_BEAMFORMEE_ENTRY            pBeamformEntry = NULL;\r
+       PRT_BEAMFORMER_ENTRY            pBeamformerEntry = NULL;\r
+       PRT_BEAMFORM_STAINFO            pSTA = NULL;\r
+       BEAMFORMING_CAP                 BeamformCap = BEAMFORMING_CAP_NONE;\r
+       u1Byte                                          BFerIdx=0xF, BFeeIdx=0xF;\r
+       u1Byte                                          NumofSoundingDim = 0, CompSteeringNumofBFer = 0;\r
+\r
+       pSTA = phydm_staInfoInit(pDM_Odm, staIdx);\r
+\r
+       /*The current setting does not support Beaforming*/\r
+       if (BEAMFORMING_CAP_NONE == pSTA->HtBeamformCap && BEAMFORMING_CAP_NONE == pSTA->VhtBeamformCap) {\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("The configuration disabled Beamforming! Skip...\n"));            \r
+               return FALSE;\r
+       }\r
+\r
+       if (pSTA->WirelessMode < WIRELESS_MODE_N_24G)\r
+               return FALSE;\r
+       else {\r
+               if (pSTA->WirelessMode & WIRELESS_MODE_N_5G || pSTA->WirelessMode & WIRELESS_MODE_N_24G) {/*HT*/\r
+                       if (TEST_FLAG(pSTA->CurBeamform, BEAMFORMING_HT_BEAMFORMER_ENABLE)) {/*We are Beamformee because the STA is Beamformer*/\r
+                               BeamformCap = (BEAMFORMING_CAP)(BeamformCap | BEAMFORMEE_CAP_HT_EXPLICIT);\r
+                               NumofSoundingDim = (pSTA->CurBeamform&BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP)>>6;\r
+                       }\r
+                       /*We are Beamformer because the STA is Beamformee*/\r
+                       if (TEST_FLAG(pSTA->CurBeamform, BEAMFORMING_HT_BEAMFORMEE_ENABLE) ||\r
+                               TEST_FLAG(pSTA->HtBeamformCap, BEAMFORMING_HT_BEAMFORMER_TEST)) {\r
+                               BeamformCap = (BEAMFORMING_CAP)(BeamformCap | BEAMFORMER_CAP_HT_EXPLICIT);\r
+                               CompSteeringNumofBFer = (pSTA->CurBeamform & BEAMFORMING_HT_BEAMFORMER_STEER_NUM)>>4;\r
+                       }\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] HT CurBeamform=0x%X, BeamformCap=0x%X\n", __func__, pSTA->CurBeamform, BeamformCap));\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] HT NumofSoundingDim=%d, CompSteeringNumofBFer=%d\n", __func__, NumofSoundingDim, CompSteeringNumofBFer));\r
+               }\r
+#if    (ODM_IC_11AC_SERIES_SUPPORT == 1)\r
+               if (pSTA->WirelessMode & WIRELESS_MODE_AC_5G || pSTA->WirelessMode & WIRELESS_MODE_AC_24G) {    /*VHT*/ \r
+\r
+                       /* We are Beamformee because the STA is SU Beamformer*/\r
+                       if (TEST_FLAG(pSTA->CurBeamformVHT, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) {\r
+                               BeamformCap =(BEAMFORMING_CAP)(BeamformCap |BEAMFORMEE_CAP_VHT_SU);\r
+                               NumofSoundingDim = (pSTA->CurBeamformVHT & BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM)>>12;\r
+                       }\r
+                       /* We are Beamformer because the STA is SU Beamformee*/\r
+                       if (TEST_FLAG(pSTA->CurBeamformVHT, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) ||\r
+                               TEST_FLAG(pSTA->VhtBeamformCap, BEAMFORMING_VHT_BEAMFORMER_TEST)) {\r
+                               BeamformCap =(BEAMFORMING_CAP)(BeamformCap |BEAMFORMER_CAP_VHT_SU);\r
+                               CompSteeringNumofBFer = (pSTA->CurBeamformVHT & BEAMFORMING_VHT_BEAMFORMER_STS_CAP)>>8;\r
+                       }\r
+                       /* We are Beamformee because the STA is MU Beamformer*/\r
+                       if (TEST_FLAG(pSTA->CurBeamformVHT, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)) {\r
+                               BeamformCap = (BEAMFORMING_CAP)(BeamformCap | BEAMFORMEE_CAP_VHT_MU);\r
+                               NumofSoundingDim = (pSTA->CurBeamformVHT & BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM)>>12;\r
+                       }\r
+                       /* We are Beamformer because the STA is MU Beamformee*/\r
+                       if (phydm_actingDetermine(pDM_Odm, PhyDM_ACTING_AS_AP)) { /* Only AP mode supports to act an MU beamformer */\r
+                               if (TEST_FLAG(pSTA->CurBeamformVHT, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE) ||\r
+                                       TEST_FLAG(pSTA->VhtBeamformCap, BEAMFORMING_VHT_BEAMFORMER_TEST)) {\r
+                                       BeamformCap = (BEAMFORMING_CAP)(BeamformCap | BEAMFORMER_CAP_VHT_MU);\r
+                                       CompSteeringNumofBFer = (pSTA->CurBeamformVHT & BEAMFORMING_VHT_BEAMFORMER_STS_CAP)>>8;\r
+                               }\r
+                       }\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s]VHT CurBeamformVHT=0x%X, BeamformCap=0x%X\n", __func__, pSTA->CurBeamformVHT, BeamformCap));\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s]VHT NumofSoundingDim=0x%X, CompSteeringNumofBFer=0x%X\n", __func__, NumofSoundingDim, CompSteeringNumofBFer));\r
+                       \r
+               }\r
+#endif\r
+       }\r
+\r
+\r
+       if(BeamformCap == BEAMFORMING_CAP_NONE)\r
+               return FALSE;\r
+       \r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Self BF Entry Cap = 0x%02X\n", __func__, BeamformCap));\r
+\r
+       /*We are BFee, so the entry is BFer*/\r
+       if (BeamformCap & (BEAMFORMEE_CAP_VHT_MU | BEAMFORMEE_CAP_VHT_SU | BEAMFORMEE_CAP_HT_EXPLICIT)) {\r
+               pBeamformerEntry = phydm_Beamforming_GetBFerEntryByAddr(pDM_Odm, pSTA->RA, &BFerIdx);\r
+               \r
+               if (pBeamformerEntry == NULL) {\r
+                       pBeamformerEntry = Beamforming_AddBFerEntry(pDM_Odm, pSTA, BeamformCap, NumofSoundingDim , &BFerIdx);\r
+                       if (pBeamformerEntry == NULL)\r
+                               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s]Not enough BFer entry!!!!!\n", __func__));\r
+               }\r
+       }\r
+\r
+       /*We are BFer, so the entry is BFee*/\r
+       if (BeamformCap & (BEAMFORMER_CAP_VHT_MU | BEAMFORMER_CAP_VHT_SU | BEAMFORMER_CAP_HT_EXPLICIT)) {\r
+               pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, pSTA->RA, &BFeeIdx);\r
+\r
+               /*¦pªGBFeeIdx = 0xF Â«hÂ¥Nªí¥Ø«eentry·í¤¤¨S¦³¬Û¦PªºMACID¦b¤º*/\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Get BFee entry 0x%X by address\n", __func__, BFeeIdx));\r
+               if (pBeamformEntry == NULL) {\r
+                       pBeamformEntry = Beamforming_AddBFeeEntry(pDM_Odm, pSTA, BeamformCap, NumofSoundingDim, CompSteeringNumofBFer, &BFeeIdx);\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s]: pSTA->AID=%d, pSTA->MacID=%d\n", __func__, pSTA->AID, pSTA->MacID));\r
+\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s]: Add BFee entry %d\n", __func__, BFeeIdx));\r
+\r
+                       if (pBeamformEntry == NULL)\r
+                               return FALSE;\r
+                       else\r
+                               pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZEING;\r
+               } else {\r
+                       /*Entry has been created. If entry is initialing or progressing then errors occur.*/\r
+                       if (pBeamformEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_INITIALIZED && \r
+                               pBeamformEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSED) {\r
+                               return FALSE;\r
+                       } else\r
+                               pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZEING;\r
+               }\r
+               pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;\r
+               phydm_staInfoUpdate(pDM_Odm, staIdx, pBeamformEntry);\r
+       }\r
+\r
+       *BFerBFeeIdx = (BFerIdx<<4) | BFeeIdx;\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] End: BFerIdx=0x%X, BFeeIdx=0x%X, BFerBFeeIdx=0x%X\n", __func__, BFerIdx, BFeeIdx, *BFerBFeeIdx));\r
+\r
+       return TRUE;\r
+}\r
+\r
+\r
+VOID\r
+Beamforming_DeInitEntry(\r
+       IN      PVOID           pDM_VOID,\r
+       pu1Byte                 RA\r
+       )\r
+{\r
+       PDM_ODM_T                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       u1Byte                          Idx = 0;\r
+\r
+       PRT_BEAMFORMER_ENTRY    pBFerEntry = phydm_Beamforming_GetBFerEntryByAddr(pDM_Odm, RA, &Idx);\r
+       PRT_BEAMFORMEE_ENTRY    pBFeeEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
+       BOOLEAN ret = FALSE;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n",  __func__));\r
+       \r
+       if (pBFeeEntry != NULL) {\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, pBFeeEntry\n", __func__));\r
+               pBFeeEntry->bUsed = FALSE;\r
+               pBFeeEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE;\r
+               pBFeeEntry->bBeamformingInProgress = FALSE;\r
+               if (pBFeeEntry->is_mu_sta) {\r
+                       pDM_Odm->BeamformingInfo.beamformee_mu_cnt -= 1;\r
+                       pDM_Odm->BeamformingInfo.FirstMUBFeeIndex = phydm_Beamforming_GetFirstMUBFeeEntryIdx(pDM_Odm);\r
+               } else {\r
+                       pDM_Odm->BeamformingInfo.beamformee_su_cnt -= 1;\r
+               }\r
+               ret = TRUE;\r
+       } \r
+       \r
+       if (pBFerEntry != NULL) {\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, pBFerEntry\n", __func__));\r
+               pBFerEntry->bUsed = FALSE;\r
+               pBFerEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE;\r
+               if (pBFerEntry->is_mu_ap)\r
+                       pDM_Odm->BeamformingInfo.beamformer_mu_cnt -= 1;\r
+               else\r
+                       pDM_Odm->BeamformingInfo.beamformer_su_cnt -= 1;\r
+               ret = TRUE;\r
+       }\r
+\r
+       if (ret == TRUE)\r
+               HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_LEAVE, (pu1Byte)&Idx);\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s End, Idx = 0x%X\n", __func__, Idx));\r
+}\r
+\r
+\r
+BOOLEAN\r
+BeamformingStart_V1(\r
+       IN      PVOID           pDM_VOID,\r
+       pu1Byte                 RA,\r
+       BOOLEAN                 Mode,\r
+       CHANNEL_WIDTH   BW,\r
+       u1Byte                  Rate\r
+       )\r
+{\r
+       PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       u1Byte                                  Idx = 0;\r
+       PRT_BEAMFORMEE_ENTRY    pEntry;\r
+       BOOLEAN                                 ret = TRUE;\r
+       PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+       \r
+       pEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
+\r
+       if (pEntry->bUsed == FALSE) {\r
+               pEntry->bBeamformingInProgress = FALSE;\r
+               return FALSE;\r
+       } else {\r
+               if (pEntry->bBeamformingInProgress)\r
+                       return FALSE;\r
+\r
+               pEntry->bBeamformingInProgress = TRUE;\r
+\r
+               if (Mode == 1) {        \r
+                       if (!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT)) {\r
+                               pEntry->bBeamformingInProgress = FALSE;\r
+                               return FALSE;\r
+                       }\r
+               } else if (Mode == 0) {\r
+                       if (!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_VHT_SU)) {\r
+                               pEntry->bBeamformingInProgress = FALSE;\r
+                               return FALSE;\r
+                       }\r
+               }\r
+\r
+               if (pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_INITIALIZED && pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSED) {\r
+                       pEntry->bBeamformingInProgress = FALSE;\r
+                       return FALSE;\r
+               } else {\r
+                       pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSING;\r
+                       pEntry->bSound = TRUE;\r
+               }\r
+       }\r
+\r
+       pEntry->SoundBW = BW;\r
+       pBeamInfo->BeamformeeCurIdx = Idx;\r
+       phydm_Beamforming_NDPARate(pDM_Odm, BW, Rate);\r
+       HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&Idx);\r
+\r
+       if (Mode == 1)\r
+               ret = Beamforming_SendHTNDPAPacket(pDM_Odm, RA, BW, NORMAL_QUEUE);      \r
+       else\r
+               ret = Beamforming_SendVHTNDPAPacket(pDM_Odm, RA, pEntry->AID, BW, NORMAL_QUEUE);\r
+\r
+       if (ret == FALSE) {\r
+               Beamforming_Leave(pDM_Odm, RA);\r
+               pEntry->bBeamformingInProgress = FALSE;\r
+               return FALSE;\r
+       }\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s  Idx %d\n", __func__, Idx));\r
+       return TRUE;\r
+}\r
+\r
+\r
+BOOLEAN\r
+BeamformingStart_SW(\r
+       IN      PVOID           pDM_VOID,\r
+       u1Byte                  Idx,\r
+       u1Byte                  Mode, \r
+       CHANNEL_WIDTH   BW\r
+       )\r
+{\r
+       pu1Byte                                 RA = NULL;\r
+       PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PRT_BEAMFORMEE_ENTRY    pEntry;\r
+       BOOLEAN                                 ret = TRUE;\r
+       PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+\r
+       if (pBeamInfo->is_mu_sounding) {\r
+               pBeamInfo->is_mu_sounding_in_progress = TRUE;\r
+               pEntry = &(pBeamInfo->BeamformeeEntry[Idx]);\r
+               RA = pEntry->MacAddr;\r
+\r
+       } else {\r
+               pEntry = &(pBeamInfo->BeamformeeEntry[Idx]);\r
+\r
+               if (pEntry->bUsed == FALSE) {\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("Skip Beamforming, no entry for Idx =%d\n", Idx));\r
+                       pEntry->bBeamformingInProgress = FALSE;\r
+                       return FALSE;\r
+               } else {\r
+                       if (pEntry->bBeamformingInProgress) {\r
+                               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("bBeamformingInProgress, skip...\n"));\r
+                               return FALSE;\r
+                       }\r
+\r
+                       pEntry->bBeamformingInProgress = TRUE;\r
+                       RA = pEntry->MacAddr;\r
+                       \r
+                       if (Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_AUTO_HT_TIMER) {   \r
+                               if (!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT)) {\r
+                                       pEntry->bBeamformingInProgress = FALSE;\r
+                                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Return by not support BEAMFORMER_CAP_HT_EXPLICIT <==\n", __func__));\r
+                                       return FALSE;\r
+                               }\r
+                       } else if (Mode == SOUNDING_SW_VHT_TIMER || Mode == SOUNDING_HW_VHT_TIMER || Mode == SOUNDING_AUTO_VHT_TIMER) {\r
+                               if (!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_VHT_SU)) {\r
+                                       pEntry->bBeamformingInProgress = FALSE;\r
+                                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Return by not support BEAMFORMER_CAP_VHT_SU <==\n", __func__));\r
+                                       return FALSE;\r
+                               }\r
+                       }\r
+                       if (pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_INITIALIZED && pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSED) {\r
+                               pEntry->bBeamformingInProgress = FALSE;\r
+                               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Return by incorrect BeamformEntryState(%d) <==\n", __func__, pEntry->BeamformEntryState));\r
+                               return FALSE;\r
+                       } else {\r
+                               pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSING;\r
+                               pEntry->bSound = TRUE;\r
+                       }\r
+               }\r
+\r
+               pBeamInfo->BeamformeeCurIdx = Idx;\r
+       }\r
+       \r
+       /*2014.12.22 Luke: Need to be checked*/\r
+       /*GET_TXBF_INFO(Adapter)->fTxbfSet(Adapter, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&Idx);*/\r
+\r
+       if (Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_AUTO_HT_TIMER)\r
+               ret = Beamforming_SendHTNDPAPacket(pDM_Odm, RA , BW, NORMAL_QUEUE);     \r
+       else\r
+               ret = Beamforming_SendVHTNDPAPacket(pDM_Odm, RA , pEntry->AID, BW, NORMAL_QUEUE);\r
+\r
+       if (ret == FALSE) {\r
+               Beamforming_Leave(pDM_Odm, RA);\r
+               pEntry->bBeamformingInProgress = FALSE;\r
+               return FALSE;\r
+       }\r
+\r
+       \r
+       /*--------------------------\r
+       // Send BF Report Poll for MU BF\r
+       --------------------------*/\r
+#ifdef SUPPORT_MU_BF\r
+#if (SUPPORT_MU_BF == 1)\r
+{\r
+       u1Byte                          idx, PollSTACnt = 0;\r
+       BOOLEAN                         bGetFirstBFee = FALSE;\r
+       \r
+       if (pBeamInfo->beamformee_mu_cnt > 1) { /* More than 1 MU STA*/\r
+       \r
+               for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) {\r
+                       pEntry = &(pBeamInfo->BeamformeeEntry[idx]);\r
+                       if (pEntry->is_mu_sta) {\r
+                               if (bGetFirstBFee) {\r
+                                       PollSTACnt++;\r
+                                       if (PollSTACnt == (pBeamInfo->beamformee_mu_cnt - 1))/* The last STA*/\r
+                                               SendSWVHTBFReportPoll(pDM_Odm, pEntry->MacAddr, TRUE);\r
+                                       else\r
+                                               SendSWVHTBFReportPoll(pDM_Odm, pEntry->MacAddr, FALSE);\r
+                               } else {\r
+                                       bGetFirstBFee = TRUE;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+}\r
+#endif\r
+#endif\r
+       return TRUE;\r
+}\r
+\r
+\r
+BOOLEAN\r
+BeamformingStart_FW(\r
+       IN PVOID                pDM_VOID,\r
+       u1Byte                  Idx\r
+       )\r
+{\r
+       PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PRT_BEAMFORMEE_ENTRY    pEntry;\r
+       PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+\r
+       pEntry = &(pBeamInfo->BeamformeeEntry[Idx]);\r
+       if (pEntry->bUsed == FALSE) {\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("Skip Beamforming, no entry for Idx =%d\n", Idx));\r
+               return FALSE;\r
+       }\r
+\r
+       pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSING;\r
+       pEntry->bSound = TRUE;\r
+       HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_FW_NDPA, (pu1Byte)&Idx);\r
+       \r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] End, Idx=0x%X\n", __func__, Idx));\r
+       return TRUE;\r
+}\r
+\r
+VOID\r
+Beamforming_CheckSoundingSuccess(\r
+       IN PVOID                        pDM_VOID,\r
+       BOOLEAN                 Status  \r
+)\r
+{\r
+       PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+       PRT_BEAMFORMEE_ENTRY    pEntry = &(pBeamInfo->BeamformeeEntry[pBeamInfo->BeamformeeCurIdx]);\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[David]@%s Start!\n", __func__));\r
+\r
+       if (Status == 1) {\r
+               if (pEntry->LogStatusFailCnt == 21)\r
+                       Beamforming_DymPeriod(pDM_Odm, Status);\r
+               pEntry->LogStatusFailCnt = 0;\r
+       } else if (pEntry->LogStatusFailCnt <= 20) {\r
+               pEntry->LogStatusFailCnt++;\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s LogStatusFailCnt %d\n", __func__, pEntry->LogStatusFailCnt));\r
+       }\r
+       if (pEntry->LogStatusFailCnt > 20) {\r
+               pEntry->LogStatusFailCnt = 21;\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s LogStatusFailCnt > 20, Stop SOUNDING\n", __func__));\r
+               Beamforming_DymPeriod(pDM_Odm, Status);\r
+       }\r
+}\r
+\r
+VOID\r
+phydm_Beamforming_End_SW(\r
+       IN PVOID                pDM_VOID,\r
+       BOOLEAN                 Status  \r
+       )\r
+{\r
+       PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PRT_BEAMFORMING_INFO    pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+       PRT_BEAMFORMEE_ENTRY    pEntry = &(pBeamInfo->BeamformeeEntry[pBeamInfo->BeamformeeCurIdx]);\r
+\r
+       if (pBeamInfo->is_mu_sounding) {\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: MU sounding done\n", __func__));\r
+               pBeamInfo->is_mu_sounding_in_progress = FALSE;\r
+               HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&(pBeamInfo->BeamformeeCurIdx));\r
+       } else {\r
+               if (pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSING) {\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] BeamformStatus %d\n", __func__, pEntry->BeamformEntryState));\r
+                       return;\r
+               }\r
+\r
+               if ((pDM_Odm->TxBfDataRate >= ODM_RATEVHTSS3MCS7) && (pDM_Odm->TxBfDataRate <= ODM_RATEVHTSS3MCS9) && (pBeamInfo->snding3SS == FALSE)) {\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] VHT3SS 7,8,9, do not apply V matrix.\n", __func__));\r
+                       pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;\r
+                       HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&(pBeamInfo->BeamformeeCurIdx));\r
+               } else if (Status == 1) {\r
+                       pEntry->LogStatusFailCnt = 0;\r
+                       pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSED;\r
+                       HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&(pBeamInfo->BeamformeeCurIdx));\r
+               } else {\r
+                       pEntry->LogStatusFailCnt++;\r
+                       pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;\r
+                       HalComTxbf_Set(pDM_Odm, TXBF_SET_TX_PATH_RESET, (pu1Byte)&(pBeamInfo->BeamformeeCurIdx));\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] LogStatusFailCnt %d\n", __func__, pEntry->LogStatusFailCnt));\r
+               }\r
+               \r
+               if (pEntry->LogStatusFailCnt > 50) {\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s LogStatusFailCnt > 50, Stop SOUNDING\n", __func__));\r
+                       pEntry->bSound = FALSE;\r
+                       Beamforming_DeInitEntry(pDM_Odm, pEntry->MacAddr); \r
+\r
+                       /*Modified by David - Every action of deleting entry should follow by Notify*/\r
+                       phydm_Beamforming_Notify(pDM_Odm);\r
+               }       \r
+               \r
+               pEntry->bBeamformingInProgress = FALSE;\r
+       }\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: Status=%d\n", __func__, Status));\r
+}      \r
+\r
+\r
+VOID\r
+Beamforming_TimerCallback(\r
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
+       IN PVOID                        pDM_VOID\r
+#elif(DM_ODM_SUPPORT_TYPE == ODM_CE)\r
+       IN PVOID            pContext\r
+#endif\r
+       )\r
+{\r
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PADAPTER                                        Adapter = pDM_Odm->Adapter;\r
+#elif(DM_ODM_SUPPORT_TYPE == ODM_CE)\r
+       PADAPTER                                        Adapter = (PADAPTER)pContext;\r
+       PHAL_DATA_TYPE                          pHalData = GET_HAL_DATA(Adapter);\r
+       PDM_ODM_T                                       pDM_Odm = &pHalData->odmpriv;\r
+#endif\r
+       BOOLEAN                                         ret = FALSE;\r
+       PRT_BEAMFORMING_INFO            pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
+       PRT_BEAMFORMEE_ENTRY            pEntry = &(pBeamInfo->BeamformeeEntry[pBeamInfo->BeamformeeCurIdx]);\r
+       PRT_SOUNDING_INFO                       pSoundInfo = &(pBeamInfo->SoundingInfo);\r
+       BOOLEAN                                 bBeamformingInProgress;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __func__));\r
+\r
+       if (pBeamInfo->is_mu_sounding)\r
+               bBeamformingInProgress = pBeamInfo->is_mu_sounding_in_progress;\r
+       else\r
+               bBeamformingInProgress = pEntry->bBeamformingInProgress;\r
+\r
+       if (bBeamformingInProgress) {\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("bBeamformingInProgress, reset it\n"));\r
+               phydm_Beamforming_End_SW(pDM_Odm, 0);\r
+        }\r
+\r
+       ret = phydm_Beamforming_SelectBeamEntry(pDM_Odm, pBeamInfo);\r
+#if (SUPPORT_MU_BF == 1)\r
+       if (ret && pBeamInfo->beamformee_mu_cnt > 1)\r
+               ret = 1;\r
+       else\r
+               ret = 0;\r
+#endif\r
+       if (ret)\r
+               ret = BeamformingStart_SW(pDM_Odm, pSoundInfo->SoundIdx, pSoundInfo->SoundMode, pSoundInfo->SoundBW);\r
+       else\r
+               ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, Error value return from BeamformingStart_V2\n", __func__));\r
+\r
+       if ((pBeamInfo->beamformee_su_cnt != 0) || (pBeamInfo->beamformee_mu_cnt > 1)) {\r
+               if (pSoundInfo->SoundMode == SOUNDING_SW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_SW_HT_TIMER)\r
+                       ODM_SetTimer(pDM_Odm, &pBeamInfo->BeamformingTimer, pSoundInfo->SoundPeriod);\r
+               else {\r
+                       u4Byte  val = (pSoundInfo->SoundPeriod << 16) | HAL_TIMER_TXBF;\r
+                       Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_RESTART, (pu1Byte)(&val));\r
+               }\r
+       }\r
+}\r
+\r
+\r
+VOID\r
+Beamforming_SWTimerCallback(\r
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
+       PRT_TIMER               pTimer\r
+#elif(DM_ODM_SUPPORT_TYPE == ODM_CE)\r
+       void *FunctionContext\r
+#endif\r
+       )\r
+{\r
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
+       PADAPTER                Adapter = (PADAPTER)pTimer->Adapter;\r
+       HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(Adapter);\r
+       PDM_ODM_T               pDM_Odm = &pHalData->DM_OutSrc;\r
+       \r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));\r
+       Beamforming_TimerCallback(pDM_Odm);\r
+#elif(DM_ODM_SUPPORT_TYPE == ODM_CE)\r
+       PDM_ODM_T       pDM_Odm = (PDM_ODM_T)FunctionContext;\r
+       PADAPTER        Adapter = pDM_Odm->Adapter;\r
+\r
+       if (Adapter->net_closed == TRUE)\r
+               return;\r
+       rtw_run_in_thread_cmd(Adapter, Beamforming_TimerCallback, Adapter);\r
+#endif\r
+       \r
+}\r
+\r
+\r
+VOID\r
+phydm_Beamforming_Init(\r
+       IN PVOID                        pDM_VOID\r
+       )\r
+{\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PRT_BEAMFORMING_INFO            pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+       PRT_BEAMFORMING_OID_INFO        pBeamOidInfo = &(pBeamInfo->BeamformingOidInfo);\r
+       \r
+       pBeamOidInfo->SoundOidMode = SOUNDING_STOP_OID_TIMER;\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Mode (%d)\n", __func__, pBeamOidInfo->SoundOidMode));\r
+\r
+       pBeamInfo->beamformee_su_cnt = 0;\r
+       pBeamInfo->beamformer_su_cnt = 0;\r
+       pBeamInfo->beamformee_mu_cnt = 0;\r
+       pBeamInfo->beamformer_mu_cnt = 0;\r
+       pBeamInfo->beamformee_mu_reg_maping = 0;\r
+       pBeamInfo->mu_ap_index = 0;\r
+       pBeamInfo->is_mu_sounding = FALSE;\r
+       pBeamInfo->FirstMUBFeeIndex = 0xFF;\r
+       pBeamInfo->applyVmatrix = TRUE;\r
+       pBeamInfo->snding3SS = FALSE;\r
+       \r
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)   \r
+       pBeamInfo->SourceAdapter = pDM_Odm->Adapter;\r
+#endif\r
+       halComTxbf_beamformInit(pDM_Odm);\r
+}      \r
+\r
+\r
+BOOLEAN\r
+phydm_actingDetermine(\r
+       IN PVOID                        pDM_VOID,\r
+       IN PHYDM_ACTING_TYPE    type\r
+       )\r
+{\r
+       PDM_ODM_T       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       BOOLEAN         ret = FALSE;\r
+#if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
+       PADAPTER        Adapter = pDM_Odm->BeamformingInfo.SourceAdapter;\r
+#else\r
+       PADAPTER        Adapter = pDM_Odm->Adapter;\r
+#endif\r
+\r
+#if (DM_ODM_SUPPORT_TYPE & ODM_WIN)\r
+       if (type == PhyDM_ACTING_AS_AP)\r
+               ret = ACTING_AS_AP(Adapter);\r
+       else if (type == PhyDM_ACTING_AS_IBSS)\r
+               ret = ACTING_AS_IBSS(Adapter);\r
+#elif (DM_ODM_SUPPORT_TYPE & ODM_CE)\r
+       struct mlme_priv                        *pmlmepriv = &(Adapter->mlmepriv);\r
+\r
+       if (type == PhyDM_ACTING_AS_AP)\r
+               ret = check_fwstate(pmlmepriv, WIFI_AP_STATE);\r
+       else if (type == PhyDM_ACTING_AS_IBSS)\r
+               ret = check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);\r
+#endif\r
+\r
+       return ret;\r
+\r
+}\r
+\r
+VOID\r
+Beamforming_Enter(\r
+       IN PVOID                        pDM_VOID,\r
+       IN u2Byte               staIdx\r
+)\r
+{\r
+       PDM_ODM_T               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       u1Byte                  BFerBFeeIdx = 0xff;\r
+       \r
+       if (Beamforming_InitEntry(pDM_Odm, staIdx, &BFerBFeeIdx))\r
+               HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_ENTER, (pu1Byte)&BFerBFeeIdx);\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] End!\n", __func__));\r
+}\r
+\r
+\r
+VOID\r
+Beamforming_Leave(\r
+       IN PVOID                        pDM_VOID,\r
+       pu1Byte                 RA\r
+       )\r
+{\r
+       PDM_ODM_T               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+\r
+       if (RA != NULL) {\r
+               Beamforming_DeInitEntry(pDM_Odm, RA);\r
+               phydm_Beamforming_Notify(pDM_Odm);\r
+       }\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] End!!\n", __func__));\r
+}\r
+\r
+#if 0\r
+//Nobody calls this function\r
+VOID\r
+phydm_Beamforming_SetTxBFen(\r
+       IN      PVOID           pDM_VOID,\r
+       u1Byte                  MacId,\r
+       BOOLEAN                 bTxBF\r
+       )\r
+{\r
+       PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       u1Byte                                  Idx = 0;\r
+       PRT_BEAMFORMEE_ENTRY    pEntry;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __func__));\r
+\r
+       pEntry = phydm_Beamforming_GetEntryByMacId(pDM_Odm, MacId, &Idx);\r
+\r
+       if(pEntry == NULL)\r
+               return;\r
+       else\r
+               pEntry->bTxBF = bTxBF;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s MacId %d TxBF %d\n", __func__, pEntry->MacId, pEntry->bTxBF));\r
+\r
+       phydm_Beamforming_Notify(pDM_Odm);\r
+}\r
+#endif\r
+\r
+BEAMFORMING_CAP\r
+phydm_Beamforming_GetBeamCap(\r
+       IN PVOID                                                pDM_VOID,\r
+       IN PRT_BEAMFORMING_INFO         pBeamInfo\r
+       )\r
+{\r
+       u1Byte                                  i;\r
+       BOOLEAN                                 bSelfBeamformer = FALSE;\r
+       BOOLEAN                                 bSelfBeamformee = FALSE;\r
+       RT_BEAMFORMEE_ENTRY     BeamformeeEntry;\r
+       RT_BEAMFORMER_ENTRY     BeamformerEntry;\r
+       BEAMFORMING_CAP                 BeamformCap = BEAMFORMING_CAP_NONE;\r
+       PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));\r
+\r
+       for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {\r
+               BeamformeeEntry = pBeamInfo->BeamformeeEntry[i];\r
+\r
+               if (BeamformeeEntry.bUsed) {\r
+                       bSelfBeamformer = TRUE;\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] BFee entry %d bUsed=TRUE\n", __func__, i));\r
+                       break;\r
+               }\r
+       }\r
+\r
+       for (i = 0; i < BEAMFORMER_ENTRY_NUM; i++) {\r
+               BeamformerEntry = pBeamInfo->BeamformerEntry[i];\r
+\r
+               if (BeamformerEntry.bUsed) {\r
+                       bSelfBeamformee = TRUE;\r
+                       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s]: BFer entry %d bUsed=TRUE\n", __func__, i));\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if (bSelfBeamformer)\r
+               BeamformCap = (BEAMFORMING_CAP)(BeamformCap | BEAMFORMER_CAP);\r
+       if (bSelfBeamformee)\r
+               BeamformCap = (BEAMFORMING_CAP)(BeamformCap | BEAMFORMEE_CAP);\r
+\r
+       return BeamformCap;\r
+}\r
+\r
+\r
+BOOLEAN\r
+BeamformingControl_V1(\r
+       IN PVOID                        pDM_VOID,\r
+       pu1Byte                 RA,\r
+       u1Byte                  AID,\r
+       u1Byte                  Mode, \r
+       CHANNEL_WIDTH   BW,\r
+       u1Byte                  Rate\r
+       )\r
+{\r
+       PDM_ODM_T       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       BOOLEAN         ret = TRUE;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __func__));\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("AID (%d), Mode (%d), BW (%d)\n", AID, Mode, BW));\r
+\r
+       switch (Mode) { \r
+       case 0:\r
+       ret = BeamformingStart_V1(pDM_Odm, RA, 0, BW, Rate);\r
+       break;\r
+       case 1:\r
+       ret = BeamformingStart_V1(pDM_Odm, RA, 1, BW, Rate);\r
+       break;\r
+       case 2:\r
+       phydm_Beamforming_NDPARate(pDM_Odm, BW, Rate);\r
+       ret = Beamforming_SendVHTNDPAPacket(pDM_Odm, RA, AID, BW, NORMAL_QUEUE);\r
+       break;\r
+       case 3:\r
+       phydm_Beamforming_NDPARate(pDM_Odm, BW, Rate);\r
+       ret = Beamforming_SendHTNDPAPacket(pDM_Odm, RA, BW, NORMAL_QUEUE);\r
+       break;\r
+       }\r
+       return ret;\r
+}\r
+\r
+/*Only OID uses this function*/\r
+BOOLEAN\r
+phydm_BeamformingControl_V2(\r
+       IN      PVOID           pDM_VOID,\r
+       u1Byte                  Idx,\r
+       u1Byte                  Mode, \r
+       CHANNEL_WIDTH   BW,\r
+       u2Byte                  Period\r
+       )\r
+{\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PRT_BEAMFORMING_INFO            pBeamInfo =  &pDM_Odm->BeamformingInfo;\r
+       PRT_BEAMFORMING_OID_INFO        pBeamOidInfo = &(pBeamInfo->BeamformingOidInfo);\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __func__));\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("Idx (%d), Mode (%d), BW (%d), Period (%d)\n", Idx, Mode, BW, Period));\r
+\r
+       pBeamOidInfo->SoundOidIdx = Idx;\r
+       pBeamOidInfo->SoundOidMode = (SOUNDING_MODE) Mode;\r
+       pBeamOidInfo->SoundOidBW = BW;\r
+       pBeamOidInfo->SoundOidPeriod = Period;\r
+\r
+       phydm_Beamforming_Notify(pDM_Odm);\r
+\r
+       return TRUE;\r
+}\r
+\r
+\r
+VOID\r
+phydm_Beamforming_Watchdog(\r
+       IN      PVOID           pDM_VOID\r
+)\r
+{\r
+       PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
+       PRT_BEAMFORMING_INFO            pBeamInfo = &pDM_Odm->BeamformingInfo;\r
+\r
+       ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_TRACE, ("%s Start!\n", __func__));\r
+\r
+       if (pBeamInfo->beamformee_su_cnt == 0)\r
+               return;\r
+\r
+       Beamforming_DymPeriod(pDM_Odm,0);\r
+       phydm_Beamforming_DymNDPARate(pDM_Odm);\r
+\r
+}\r
+\r
+\r
+#endif\r