
Since the driver itself is licensed under GPLv2+, we can manage it in public git repository Signed-off-by: Jens Rehsack <sno@netbsd.org>
2600 lines
76 KiB
C
2600 lines
76 KiB
C
#include "mp_precomp.h"
|
||
#include "phydm_precomp.h"
|
||
|
||
#if WPP_SOFTWARE_TRACE
|
||
#include "phydm_beamforming.tmh"
|
||
#endif
|
||
|
||
#if (BEAMFORMING_SUPPORT == 1)
|
||
|
||
u1Byte
|
||
Beamforming_GetHTNDPTxRate(
|
||
IN PADAPTER Adapter,
|
||
u1Byte CompSteeringNumofBFer
|
||
)
|
||
{
|
||
u1Byte Nr_index = 0;
|
||
u1Byte NDPTxRate;
|
||
/*Find Nr*/
|
||
|
||
if(IS_HARDWARE_TYPE_8814A(Adapter))
|
||
Nr_index = TxBF_Nr(halTxbf8814A_GetNtx(Adapter), CompSteeringNumofBFer);
|
||
else
|
||
Nr_index = TxBF_Nr(1, CompSteeringNumofBFer);
|
||
|
||
switch(Nr_index)
|
||
{
|
||
case 1:
|
||
NDPTxRate = MGN_MCS8;
|
||
break;
|
||
|
||
case 2:
|
||
NDPTxRate = MGN_MCS16;
|
||
break;
|
||
|
||
case 3:
|
||
NDPTxRate = MGN_MCS24;
|
||
break;
|
||
|
||
default:
|
||
NDPTxRate = MGN_MCS8;
|
||
break;
|
||
|
||
}
|
||
|
||
return NDPTxRate;
|
||
|
||
}
|
||
|
||
u1Byte
|
||
Beamforming_GetVHTNDPTxRate(
|
||
IN PADAPTER Adapter,
|
||
u1Byte CompSteeringNumofBFer
|
||
)
|
||
{
|
||
u1Byte Nr_index = 0;
|
||
u1Byte NDPTxRate;
|
||
/*Find Nr*/
|
||
if(IS_HARDWARE_TYPE_8814A(Adapter))
|
||
Nr_index = TxBF_Nr(halTxbf8814A_GetNtx(Adapter), CompSteeringNumofBFer);
|
||
else
|
||
Nr_index = TxBF_Nr(1, CompSteeringNumofBFer);
|
||
|
||
switch(Nr_index)
|
||
{
|
||
case 1:
|
||
NDPTxRate = MGN_VHT2SS_MCS0;
|
||
break;
|
||
|
||
case 2:
|
||
NDPTxRate = MGN_VHT3SS_MCS0;
|
||
break;
|
||
|
||
case 3:
|
||
NDPTxRate = MGN_VHT4SS_MCS0;
|
||
break;
|
||
|
||
default:
|
||
NDPTxRate = MGN_VHT2SS_MCS0;
|
||
break;
|
||
|
||
}
|
||
|
||
return NDPTxRate;
|
||
|
||
}
|
||
|
||
|
||
PRT_BEAMFORMING_ENTRY
|
||
phydm_Beamforming_GetBFeeEntryByAddr(
|
||
IN PVOID pDM_VOID,
|
||
IN pu1Byte RA,
|
||
OUT pu1Byte Idx
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
u1Byte i = 0;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s ===>\n", __FUNCTION__));
|
||
|
||
for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
|
||
{
|
||
if( pBeamInfo->BeamformeeEntry[i].bUsed &&
|
||
(eqMacAddr(RA,pBeamInfo->BeamformeeEntry[i].MacAddr) ))
|
||
{
|
||
*Idx = i;
|
||
return &(pBeamInfo->BeamformeeEntry[i]);
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
PRT_BEAMFORMER_ENTRY
|
||
phydm_Beamforming_GetBFerEntryByAddr(
|
||
IN PVOID pDM_VOID,
|
||
IN pu1Byte TA,
|
||
OUT pu1Byte Idx
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
u1Byte i = 0;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s ===>\n", __FUNCTION__));
|
||
|
||
for(i = 0; i < BEAMFORMER_ENTRY_NUM; i++)
|
||
{
|
||
if( pBeamInfo->BeamformerEntry[i].bUsed &&
|
||
(eqMacAddr(TA,pBeamInfo->BeamformerEntry[i].MacAddr) ))
|
||
{
|
||
*Idx = i;
|
||
return &(pBeamInfo->BeamformerEntry[i]);
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
PRT_BEAMFORMING_ENTRY
|
||
phydm_Beamforming_GetEntryByMacId(
|
||
IN PVOID pDM_VOID,
|
||
IN u1Byte MacId,
|
||
OUT pu1Byte Idx
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
u1Byte i = 0;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s ===>\n", __FUNCTION__));
|
||
|
||
for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
|
||
{
|
||
if( pBeamInfo->BeamformeeEntry[i].bUsed &&
|
||
(MacId == pBeamInfo->BeamformeeEntry[i].MacId))
|
||
{
|
||
*Idx = i;
|
||
return &(pBeamInfo->BeamformeeEntry[i]);
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
BEAMFORMING_CAP
|
||
phydm_Beamforming_GetEntryBeamCapByMacId(
|
||
IN PVOID pDM_VOID,
|
||
IN u1Byte MacId
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
u1Byte i = 0;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
BEAMFORMING_CAP BeamformEntryCap = BEAMFORMING_CAP_NONE;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s ===>\n", __FUNCTION__));
|
||
|
||
for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
|
||
{
|
||
if( pBeamInfo->BeamformeeEntry[i].bUsed &&
|
||
(MacId == pBeamInfo->BeamformeeEntry[i].MacId))
|
||
{
|
||
BeamformEntryCap = pBeamInfo->BeamformeeEntry[i].BeamformEntryCap;
|
||
i = BEAMFORMEE_ENTRY_NUM;
|
||
}
|
||
}
|
||
|
||
return BeamformEntryCap;
|
||
}
|
||
|
||
|
||
PRT_BEAMFORMING_ENTRY
|
||
phydm_Beamforming_GetFreeBFeeEntry(
|
||
IN PVOID pDM_VOID,
|
||
OUT pu1Byte Idx
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
u1Byte i = 0;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s ===>\n", __FUNCTION__));
|
||
|
||
for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
|
||
{
|
||
if(pBeamInfo->BeamformeeEntry[i].bUsed == FALSE)
|
||
{
|
||
*Idx = i;
|
||
return &(pBeamInfo->BeamformeeEntry[i]);
|
||
}
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
PRT_BEAMFORMER_ENTRY
|
||
phydm_Beamforming_GetFreeBFerEntry(
|
||
IN PVOID pDM_VOID,
|
||
OUT pu1Byte Idx
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
u1Byte i = 0;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s ===>\n", __FUNCTION__));
|
||
|
||
for(i = 0; i < BEAMFORMER_ENTRY_NUM; i++)
|
||
{
|
||
if(pBeamInfo->BeamformerEntry[i].bUsed == FALSE)
|
||
{
|
||
*Idx = i;
|
||
return &(pBeamInfo->BeamformerEntry[i]);
|
||
}
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
|
||
PRT_BEAMFORMING_ENTRY
|
||
Beamforming_AddBFeeEntry(
|
||
IN PADAPTER Adapter,
|
||
IN pu1Byte RA,
|
||
IN u2Byte AID,
|
||
IN u2Byte MacID,
|
||
IN CHANNEL_WIDTH BW,
|
||
IN BEAMFORMING_CAP BeamformCap,
|
||
IN u1Byte NumofSoundingDim,
|
||
IN u1Byte CompSteeringNumofBFer,
|
||
OUT pu1Byte Idx
|
||
)
|
||
{
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
|
||
PRT_BEAMFORMING_ENTRY pEntry = phydm_Beamforming_GetFreeBFeeEntry(pDM_Odm, Idx);
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__));
|
||
|
||
if(pEntry != NULL)
|
||
{
|
||
pEntry->bUsed = TRUE;
|
||
pEntry->AID = AID;
|
||
pEntry->MacId = MacID;
|
||
pEntry->SoundBW = BW;
|
||
if(ACTING_AS_AP(Adapter))
|
||
{
|
||
u2Byte BSSID = ((Adapter->CurrentAddress[5] & 0xf0) >> 4) ^
|
||
(Adapter->CurrentAddress[5] & 0xf); // BSSID[44:47] xor BSSID[40:43]
|
||
pEntry->P_AID = (AID + BSSID * 32) & 0x1ff; // (dec(A) + dec(B)*32) mod 512
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: BFee P_AID addressed to STA=%d\n", __FUNCTION__,pEntry->P_AID));
|
||
}
|
||
else if(ACTING_AS_IBSS(Adapter)) // Ad hoc mode
|
||
{
|
||
pEntry->P_AID = 0;
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: BFee P_AID as IBSS=%d\n", __FUNCTION__,pEntry->P_AID));
|
||
}
|
||
else // client mode
|
||
{
|
||
pEntry->P_AID = RA[5]; // BSSID[39:47]
|
||
pEntry->P_AID = (pEntry->P_AID << 1) | (RA[4] >> 7 );
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: BFee P_AID addressed to AP=0x%X\n", __FUNCTION__,pEntry->P_AID));
|
||
}
|
||
cpMacAddr(pEntry->MacAddr, RA);
|
||
pEntry->bTxBF = FALSE;
|
||
pEntry->bSound = FALSE;
|
||
|
||
//3 TODO SW/FW sound period
|
||
pEntry->SoundPeriod = 400;
|
||
pEntry->BeamformEntryCap = BeamformCap;
|
||
pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
|
||
|
||
/* pEntry->LogSeq = 0xff; // Move to Beamforming_AddBFerEntry*/
|
||
/* pEntry->LogRetryCnt = 0; // Move to Beamforming_AddBFerEntry*/
|
||
/* pEntry->LogSuccessCnt = 0; // Move to Beamforming_AddBFerEntry*/
|
||
|
||
pEntry->LogStatusFailCnt = 0;
|
||
|
||
pEntry->NumofSoundingDim = NumofSoundingDim;
|
||
pEntry->CompSteeringNumofBFer = CompSteeringNumofBFer;
|
||
|
||
return pEntry;
|
||
}
|
||
else
|
||
return NULL;
|
||
}
|
||
|
||
PRT_BEAMFORMER_ENTRY
|
||
Beamforming_AddBFerEntry(
|
||
IN PADAPTER Adapter,
|
||
IN pu1Byte RA,
|
||
IN u2Byte AID,
|
||
IN BEAMFORMING_CAP BeamformCap,
|
||
IN u1Byte NumofSoundingDim,
|
||
OUT pu1Byte Idx
|
||
)
|
||
{
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
|
||
PRT_BEAMFORMER_ENTRY pEntry = phydm_Beamforming_GetFreeBFerEntry(pDM_Odm, Idx);
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__));
|
||
|
||
if(pEntry != NULL)
|
||
{
|
||
pEntry->bUsed = TRUE;
|
||
if(ACTING_AS_AP(Adapter))
|
||
{
|
||
u2Byte BSSID = ((Adapter->CurrentAddress[5] & 0xf0) >> 4) ^
|
||
(Adapter->CurrentAddress[5] & 0xf); // BSSID[44:47] xor BSSID[40:43]
|
||
pEntry->P_AID = (AID + BSSID * 32) & 0x1ff; // (dec(A) + dec(B)*32) mod 512
|
||
}
|
||
else if(ACTING_AS_IBSS(Adapter))
|
||
{
|
||
pEntry->P_AID = 0;
|
||
}
|
||
else
|
||
{
|
||
pEntry->P_AID = RA[5]; // BSSID[39:47]
|
||
pEntry->P_AID = (pEntry->P_AID << 1) | (RA[4] >> 7 );
|
||
}
|
||
|
||
cpMacAddr(pEntry->MacAddr, RA);
|
||
pEntry->BeamformEntryCap = BeamformCap;
|
||
|
||
pEntry->LogSeq = 0xff; // Modified by Jeffery @2014-10-29
|
||
pEntry->LogRetryCnt = 0; // Modified by Jeffery @2014-10-29
|
||
pEntry->LogSuccessCnt = 0; // Modified by Jeffery @2014-10-29
|
||
|
||
pEntry->NumofSoundingDim = NumofSoundingDim;
|
||
|
||
return pEntry;
|
||
}
|
||
else
|
||
return NULL;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
Beamforming_RemoveEntry(
|
||
IN PADAPTER Adapter,
|
||
IN pu1Byte RA,
|
||
OUT pu1Byte Idx
|
||
)
|
||
{
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
|
||
PRT_BEAMFORMER_ENTRY pBFerEntry = phydm_Beamforming_GetBFerEntryByAddr(pDM_Odm, RA, Idx);
|
||
PRT_BEAMFORMING_ENTRY pEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, Idx);
|
||
BOOLEAN ret = FALSE;
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s Start!\n", __FUNCTION__) );
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s, pBFerEntry=0x%x \n", __FUNCTION__,pBFerEntry) );
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s, pEntry=0x%x \n", __FUNCTION__,pEntry) );
|
||
|
||
if (pEntry != NULL) {
|
||
pEntry->bUsed = FALSE;
|
||
pEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE;
|
||
/*pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;*/
|
||
pEntry->bBeamformingInProgress = FALSE;
|
||
ret = TRUE;
|
||
}
|
||
if (pBFerEntry != NULL) {
|
||
pBFerEntry->bUsed = FALSE;
|
||
pBFerEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE;
|
||
ret = TRUE;
|
||
}
|
||
return ret;
|
||
|
||
}
|
||
|
||
/* Used for BeamformingStart_V1 */
|
||
VOID
|
||
phydm_Beamforming_NDPARate(
|
||
IN PVOID pDM_VOID,
|
||
CHANNEL_WIDTH BW,
|
||
u1Byte Rate
|
||
)
|
||
{
|
||
u2Byte NDPARate = Rate;
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
if(NDPARate == 0)
|
||
{
|
||
if(pDM_Odm->RSSI_Min > 30) // link RSSI > 30%
|
||
NDPARate = ODM_RATE24M;
|
||
else
|
||
NDPARate = ODM_RATE6M;
|
||
}
|
||
|
||
if(NDPARate < ODM_RATEMCS0)
|
||
BW = (CHANNEL_WIDTH)ODM_BW20M;
|
||
|
||
NDPARate = (NDPARate << 8) | BW;
|
||
HalComTxbf_Set(pDM_Odm->Adapter, TXBF_SET_SOUNDING_RATE, (pu1Byte)&NDPARate);
|
||
|
||
}
|
||
|
||
|
||
/* Used for BeamformingStart_SW and BeamformingStart_FW */
|
||
VOID
|
||
phydm_Beamforming_DymNDPARate(
|
||
IN PVOID pDM_VOID
|
||
)
|
||
{
|
||
u2Byte NDPARate = ODM_RATE6M, BW;
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
if(pDM_Odm->RSSI_Min > 30) // link RSSI > 30%
|
||
NDPARate = ODM_RATE24M;
|
||
else
|
||
NDPARate = ODM_RATE6M;
|
||
|
||
BW = ODM_BW20M;
|
||
NDPARate = NDPARate << 8 | BW;
|
||
HalComTxbf_Set(pDM_Odm->Adapter, TXBF_SET_SOUNDING_RATE, (pu1Byte)&NDPARate);
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s End, NDPA Rate = 0x%X \n", __FUNCTION__, NDPARate));
|
||
}
|
||
|
||
/*
|
||
* SW Sounding : SW Timer unit 1ms
|
||
* HW Timer unit (1/32000) s 32k is clock.
|
||
* FW Sounding : FW Timer unit 10ms
|
||
*/
|
||
VOID
|
||
Beamforming_DymPeriod(
|
||
IN PVOID pDM_VOID,
|
||
IN u8 status
|
||
)
|
||
{
|
||
u1Byte Idx;
|
||
BOOLEAN bChangePeriod = FALSE;
|
||
u2Byte SoundPeriod_SW, SoundPeriod_FW;
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
PADAPTER Adapter = pDM_Odm->Adapter;
|
||
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
|
||
|
||
PRT_BEAMFORMING_ENTRY pBeamformEntry;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = GET_BEAMFORM_INFO((Adapter));
|
||
PRT_SOUNDING_INFO pSoundInfo = &(pBeamInfo->SoundingInfo);
|
||
|
||
PRT_BEAMFORMING_ENTRY pEntry = &(pBeamInfo->BeamformeeEntry[pBeamInfo->BeamformeeCurIdx]);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
|
||
|
||
//3 TODO per-client throughput caculation.
|
||
|
||
if ((Adapter->TxStats.CurrentTxTP + Adapter->RxStats.CurrentRxTP > 2)&&((pEntry->LogStatusFailCnt <= 20) || status)){
|
||
//-@ Modified by David
|
||
SoundPeriod_SW = 40; /* 32*20? */
|
||
SoundPeriod_FW = 40; /* From H2C cmd, unit = 10ms */
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s, current TRX TP>2, SoundPeriod_SW=%d, SoundPeriod_FW=%d\n",
|
||
__FUNCTION__,
|
||
SoundPeriod_SW,
|
||
SoundPeriod_FW) );
|
||
} else{
|
||
//-@ Modified by David
|
||
SoundPeriod_SW = 4000;/* 32*2000? */
|
||
SoundPeriod_FW = 400;
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s, current TRX TP<2, SoundPeriod_SW=%d, SoundPeriod_FW=%d\n",
|
||
__FUNCTION__,
|
||
SoundPeriod_SW,
|
||
SoundPeriod_FW) );
|
||
}
|
||
|
||
for(Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++)
|
||
{
|
||
pBeamformEntry = pBeamInfo->BeamformeeEntry+Idx;
|
||
|
||
if(pBeamformEntry->DefaultCSICnt > 20)
|
||
{
|
||
//-@ Modified by David
|
||
SoundPeriod_SW = 4000;
|
||
SoundPeriod_FW = 400;
|
||
}
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("@%s Period = %d\n", __FUNCTION__, SoundPeriod_SW));
|
||
if(pBeamformEntry->BeamformEntryCap & (BEAMFORMER_CAP_HT_EXPLICIT |BEAMFORMER_CAP_VHT_SU))
|
||
{
|
||
if(pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER)
|
||
{
|
||
if(pBeamformEntry->SoundPeriod != SoundPeriod_FW)
|
||
{
|
||
pBeamformEntry->SoundPeriod = SoundPeriod_FW;
|
||
bChangePeriod = TRUE; // Only FW sounding need to send H2C packet to change sound period.
|
||
}
|
||
}
|
||
else if(pBeamformEntry->SoundPeriod != SoundPeriod_SW)
|
||
{
|
||
pBeamformEntry->SoundPeriod = SoundPeriod_SW;
|
||
}
|
||
}
|
||
}
|
||
|
||
if(bChangePeriod)
|
||
HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_FW_NDPA, (pu1Byte)&Idx);
|
||
}
|
||
|
||
|
||
VOID
|
||
Beamforming_GidPAid(
|
||
PADAPTER Adapter,
|
||
PRT_TCB pTcb
|
||
)
|
||
{
|
||
u1Byte Idx = 0;
|
||
u1Byte RA[6] ={0};
|
||
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
|
||
pu1Byte pHeader = GET_FRAME_OF_FIRST_FRAG(Adapter, pTcb);
|
||
|
||
if(Adapter->HardwareType < HARDWARE_TYPE_RTL8192EE)
|
||
return;
|
||
else if(IS_WIRELESS_MODE_N(Adapter) == FALSE)
|
||
return;
|
||
|
||
GET_80211_HDR_ADDRESS1(pHeader, &RA);
|
||
|
||
// VHT SU PPDU carrying one or more group addressed MPDUs or
|
||
// Transmitting a VHT NDP intended for multiple recipients
|
||
if( MacAddr_isBcst(RA) || MacAddr_isMulticast(RA) ||
|
||
pTcb->macId == MAC_ID_STATIC_FOR_BROADCAST_MULTICAST)
|
||
{
|
||
pTcb->G_ID = 63;
|
||
pTcb->P_AID = 0;
|
||
}
|
||
else if(ACTING_AS_AP(Adapter))
|
||
{
|
||
u2Byte AID = (u2Byte) (MacIdGetOwnerAssociatedClientAID(Adapter, pTcb->macId) & 0x1ff); //AID[0:8]
|
||
|
||
pTcb->G_ID = 63;
|
||
|
||
if(AID == 0) //A PPDU sent by an AP to a non associated STA
|
||
pTcb->P_AID = 0;
|
||
else
|
||
{ //Sent by an AP and addressed to a STA associated with that AP
|
||
u2Byte BSSID = 0;
|
||
GET_80211_HDR_ADDRESS2(pHeader, &RA);
|
||
BSSID = ((RA[5] & 0xf0) >> 4) ^ (RA[5] & 0xf); // BSSID[44:47] xor BSSID[40:43]
|
||
pTcb->P_AID = (AID + BSSID * 32) & 0x1ff; // (dec(A) + dec(B)*32) mod 512
|
||
}
|
||
}
|
||
else if(ACTING_AS_IBSS(Adapter))
|
||
{
|
||
pTcb->G_ID = 63;
|
||
// P_AID for infrasturcture mode; MACID for ad-hoc mode.
|
||
pTcb->P_AID = pTcb->macId;
|
||
}
|
||
else if(MgntLinkStatusQuery(Adapter))
|
||
{ // Addressed to AP
|
||
pTcb->G_ID = 0;
|
||
GET_80211_HDR_ADDRESS1(pHeader, &RA);
|
||
pTcb->P_AID = RA[5]; // RA[39:47]
|
||
pTcb->P_AID = (pTcb->P_AID << 1) | (RA[4] >> 7 );
|
||
}
|
||
else
|
||
{
|
||
pTcb->G_ID = 63;
|
||
pTcb->P_AID = 0;
|
||
}
|
||
|
||
//RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End, G_ID=0x%X, P_AID=0x%X \n", __FUNCTION__, pTcb->G_ID, pTcb->P_AID) );
|
||
|
||
}
|
||
|
||
|
||
RT_STATUS
|
||
Beamforming_GetReportFrame(
|
||
IN PADAPTER Adapter,
|
||
IN PRT_RFD pRfd,
|
||
IN POCTET_STRING pPduOS
|
||
)
|
||
{
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
PRT_BEAMFORMING_ENTRY pBeamformEntry = NULL;
|
||
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
|
||
pu1Byte pMIMOCtrlField, pCSIReport, pCSIMatrix;
|
||
u1Byte Idx, Nc, Nr, CH_W;
|
||
u2Byte CSIMatrixLen = 0;
|
||
|
||
ACT_PKT_TYPE pktType = ACT_PKT_TYPE_UNKNOWN;
|
||
|
||
//Memory comparison to see if CSI report is the same with previous one
|
||
pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, Frame_Addr2(*pPduOS), &Idx);
|
||
|
||
if( pBeamformEntry == NULL )
|
||
{
|
||
RT_DISP(FBEAM, FBEAM_DATA, ("Beamforming_GetReportFrame: Cannot find entry by addr\n"));
|
||
return RT_STATUS_FAILURE;
|
||
}
|
||
|
||
pktType = PacketGetActionFrameType(pPduOS);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
|
||
|
||
//-@ Modified by David
|
||
if(pktType == ACT_PKT_VHT_COMPRESSED_BEAMFORMING)
|
||
{
|
||
pMIMOCtrlField = pPduOS->Octet + 26;
|
||
Nc = ((*pMIMOCtrlField) & 0x7) + 1;
|
||
Nr = (((*pMIMOCtrlField) & 0x38) >> 3) + 1;
|
||
CH_W = (((*pMIMOCtrlField) & 0xC0) >> 6);
|
||
pCSIMatrix = pMIMOCtrlField + 3 + Nc; //24+(1+1+3)+2 MAC header+(Category+ActionCode+MIMOControlField) +SNR(Nc=2)
|
||
CSIMatrixLen = pPduOS->Length - 26 -3 -Nc;
|
||
}
|
||
else if(pktType == ACT_PKT_HT_COMPRESSED_BEAMFORMING)
|
||
{
|
||
pMIMOCtrlField = pPduOS->Octet + 26;
|
||
Nc = ((*pMIMOCtrlField) & 0x3) + 1;
|
||
Nr = (((*pMIMOCtrlField) & 0xC) >> 2) + 1;
|
||
CH_W = (((*pMIMOCtrlField) & 0x10) >> 4);
|
||
pCSIMatrix = pMIMOCtrlField + 6 + Nr; //24+(1+1+6)+2 MAC header+(Category+ActionCode+MIMOControlField) +SNR(Nc=2)
|
||
CSIMatrixLen = pPduOS->Length - 26 -6 -Nr;
|
||
}
|
||
else
|
||
return RT_STATUS_SUCCESS;
|
||
|
||
if(pktType == ACT_PKT_VHT_COMPRESSED_BEAMFORMING)
|
||
{
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@BF_GetReportFrame: idx=%d, pkt type=VHT_Cprssed_BF, Nc=%d, Nr=%d, CH_W=%d\n", Idx, Nc, Nr, CH_W));
|
||
}
|
||
else if(pktType == ACT_PKT_HT_COMPRESSED_BEAMFORMING)
|
||
{
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@BF_GetReportFrame: idx=%d, pkt type=HT_Cprssed_BF, Nc=%d, Nr=%d, CH_W=%d\n", Idx, Nc, Nr, CH_W));
|
||
}
|
||
|
||
|
||
// RT_DISP_DATA(FBEAM, FBEAM_DATA, "Beamforming_GetReportFrame \n", pMIMOCtrlField, pPduOS->Length - 26);
|
||
|
||
//-@ Modified by David - CSI buffer is not big enough, and comparison would result in blue screen
|
||
/*
|
||
if(pBeamformEntry->CSIMatrixLen != CSIMatrixLen)
|
||
pBeamformEntry->DefaultCSICnt = 0;
|
||
else if(PlatformCompareMemory(pBeamformEntry->CSIMatrix, pCSIMatrix, CSIMatrixLen))
|
||
{
|
||
pBeamformEntry->DefaultCSICnt = 0;
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("%s CSI report is NOT the same with previos one\n", __FUNCTION__));
|
||
}
|
||
else if(pBeamformEntry->DefaultCSICnt <= 20)
|
||
{
|
||
pBeamformEntry->DefaultCSICnt ++;
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("%s CSI report is the SAME with previos one\n", __FUNCTION__));
|
||
}
|
||
|
||
pBeamformEntry->CSIMatrixLen = CSIMatrixLen;
|
||
PlatformMoveMemory(&pBeamformEntry->CSIMatrix, pCSIMatrix, CSIMatrixLen);
|
||
*/
|
||
|
||
return RT_STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
VOID
|
||
Beamforming_GetNDPAFrame(
|
||
IN PADAPTER Adapter,
|
||
IN OCTET_STRING pduOS
|
||
)
|
||
{
|
||
pu1Byte TA ;
|
||
u1Byte Idx, Sequence;
|
||
pu1Byte pNDPAFrame = pduOS.Octet;
|
||
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
|
||
// PRT_BEAMFORMING_ENTRY pBeamformEntry = NULL;
|
||
PRT_BEAMFORMER_ENTRY pBeamformerEntry = NULL; // Modified By Jeffery @2014-10-29
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
|
||
RT_DISP_DATA(FBEAM, FBEAM_DATA, "Beamforming_GetNDPAFrame\n", pduOS.Octet, pduOS.Length);
|
||
|
||
if(IsCtrlNDPA(pNDPAFrame) == FALSE){
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s IsCtrlNDPA(pNDPAFrame) == FALSE\n", __FUNCTION__) );
|
||
return;
|
||
|
||
}
|
||
|
||
else if( (IS_HARDWARE_TYPE_8812(Adapter) == FALSE)&&(IS_HARDWARE_TYPE_8821(Adapter) == FALSE) )
|
||
{
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s IsCtrlNDPA(pNDPAFrame) == FALSE\n", __FUNCTION__) );
|
||
return;
|
||
}
|
||
|
||
TA = Frame_Addr2(pduOS);
|
||
// Remove signaling TA.
|
||
TA[0] = TA[0] & 0xFE;
|
||
|
||
// pBeamformEntry = Beamforming_GetBFeeEntryByAddr(Adapter, TA, &Idx);
|
||
pBeamformerEntry = phydm_Beamforming_GetBFerEntryByAddr(pDM_Odm, TA, &Idx); // Modified By Jeffery @2014-10-29
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s After phydm_Beamforming_GetBFerEntryByAddr,pBeamformerEntry=0x%x\n", __FUNCTION__,pBeamformerEntry) );
|
||
|
||
if(pBeamformerEntry == NULL)
|
||
return;
|
||
else if(!(pBeamformerEntry->BeamformEntryCap & BEAMFORMEE_CAP_VHT_SU))
|
||
return;
|
||
// else if(pBeamformerEntry->LogSuccessCnt > 1) //<2F>Ȯɲ<C8AE><C9B2><EFBFBD>,<2C>קK<D7A7>û<EFBFBD><C3BB>d<EFBFBD><64><EFBFBD>b<EFBFBD>o<EFBFBD>Ӫ<EFBFBD><D3AA>A
|
||
// return;
|
||
|
||
/*
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s begin, LogSeq=%d, LogRetryCnt=%d, LogSuccessCnt=%d\n",
|
||
__FUNCTION__,
|
||
pBeamformerEntry->LogSeq,
|
||
pBeamformerEntry->LogRetryCnt,
|
||
pBeamformerEntry->LogSuccessCnt) );
|
||
*/
|
||
|
||
Sequence = (pNDPAFrame[16]) >> 2;
|
||
|
||
|
||
if(pBeamformerEntry->LogSeq != Sequence){
|
||
/* Previous frame doesn't retry when meet new sequence number */
|
||
if(pBeamformerEntry->LogSeq != 0xff && pBeamformerEntry->LogRetryCnt == 0)
|
||
pBeamformerEntry->LogSuccessCnt++;
|
||
|
||
pBeamformerEntry->LogSeq = Sequence;
|
||
pBeamformerEntry->PreLogSeq = pBeamformerEntry->LogSeq;
|
||
|
||
/* break option for clcok reset, 2015-03-30, Jeffery */
|
||
if ((pBeamformerEntry->LogSeq != Sequence) && (pBeamformerEntry->PreLogSeq != pBeamformerEntry->LogSeq))
|
||
pBeamformerEntry->LogRetryCnt = 0;
|
||
} else { /* pBeamformerEntry->LogSeq == Sequence */
|
||
pBeamformerEntry->PreLogSeq = pBeamformerEntry->LogSeq;
|
||
|
||
if (pBeamformerEntry->LogRetryCnt == 3){
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[Jeffery]@%s begin, Clock Reset!!!,PreLogSeq=%d, LogSeq=%d, LogRetryCnt=%d, LogSuccessCnt=%d\n",
|
||
__FUNCTION__,
|
||
pBeamformerEntry->PreLogSeq,
|
||
pBeamformerEntry->LogSeq,
|
||
pBeamformerEntry->LogRetryCnt));
|
||
pBeamformerEntry->LogRetryCnt = 0;
|
||
HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_CLK, NULL);
|
||
}
|
||
else
|
||
pBeamformerEntry->LogRetryCnt++;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
else
|
||
{
|
||
if(pBeamformerEntry->LogRetryCnt == 3)
|
||
HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_CLK, NULL);
|
||
else if(pBeamformerEntry->LogRetryCnt <= 3)
|
||
pBeamformerEntry->LogRetryCnt++;
|
||
}
|
||
*/
|
||
|
||
|
||
/* RT_DISP(FBEAM, FBEAM_FUN, ("%s End, LogSeq=%d, LogRetryCnt=%d, LogSuccessCnt=%d\n",
|
||
__FUNCTION__,
|
||
pBeamformerEntry->LogSeq,
|
||
pBeamformerEntry->LogRetryCnt,
|
||
pBeamformerEntry->LogSuccessCnt));*/
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
ConstructHTNDPAPacket(
|
||
PADAPTER Adapter,
|
||
pu1Byte RA,
|
||
pu1Byte Buffer,
|
||
pu4Byte pLength,
|
||
CHANNEL_WIDTH BW
|
||
)
|
||
{
|
||
u2Byte Duration= 0;
|
||
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
|
||
PRT_HIGH_THROUGHPUT pHTInfo = GET_HT_INFO(pMgntInfo);
|
||
OCTET_STRING pNDPAFrame,ActionContent;
|
||
u1Byte ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};
|
||
|
||
PlatformZeroMemory(Buffer, 32);
|
||
|
||
SET_80211_HDR_FRAME_CONTROL(Buffer,0);
|
||
|
||
SET_80211_HDR_ORDER(Buffer, 1);
|
||
SET_80211_HDR_TYPE_AND_SUBTYPE(Buffer,Type_Action_No_Ack);
|
||
|
||
SET_80211_HDR_ADDRESS1(Buffer, RA);
|
||
SET_80211_HDR_ADDRESS2(Buffer, Adapter->CurrentAddress);
|
||
SET_80211_HDR_ADDRESS3(Buffer, pMgntInfo->Bssid);
|
||
|
||
Duration = 2*aSifsTime + 40;
|
||
|
||
if(BW== CHANNEL_WIDTH_40)
|
||
Duration+= 87;
|
||
else
|
||
Duration+= 180;
|
||
|
||
SET_80211_HDR_DURATION(Buffer, Duration);
|
||
|
||
//HT control field
|
||
SET_HT_CTRL_CSI_STEERING(Buffer+sMacHdrLng, 3);
|
||
SET_HT_CTRL_NDP_ANNOUNCEMENT(Buffer+sMacHdrLng, 1);
|
||
|
||
FillOctetString(pNDPAFrame, Buffer, sMacHdrLng+sHTCLng);
|
||
|
||
FillOctetString(ActionContent, ActionHdr, 4);
|
||
PacketAppendData(&pNDPAFrame, ActionContent);
|
||
|
||
*pLength = 32;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
SendFWHTNDPAPacket(
|
||
IN PADAPTER Adapter,
|
||
IN pu1Byte RA,
|
||
IN CHANNEL_WIDTH BW
|
||
)
|
||
{
|
||
PRT_TCB pTcb;
|
||
PRT_TX_LOCAL_BUFFER pBuf;
|
||
BOOLEAN ret = TRUE;
|
||
u4Byte BufLen;
|
||
pu1Byte BufAddr;
|
||
u1Byte DescLen = 0, Idx = 0, NDPTxRate;
|
||
PADAPTER pDefAdapter = GetDefaultAdapter(Adapter);
|
||
PRT_BEAMFORMING_INFO pBeamInfo = GET_BEAMFORM_INFO(Adapter);
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
PRT_BEAMFORMING_ENTRY pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
|
||
|
||
if(pBeamformEntry == NULL)
|
||
return FALSE;
|
||
|
||
NDPTxRate = Beamforming_GetHTNDPTxRate(Adapter, pBeamformEntry->CompSteeringNumofBFer);
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("%s, NDPTxRate =%d\n", __FUNCTION__, NDPTxRate));
|
||
PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
|
||
|
||
if(MgntGetFWBuffer(pDefAdapter, &pTcb, &pBuf))
|
||
{
|
||
#if(DEV_BUS_TYPE != RT_PCI_INTERFACE)
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
|
||
DescLen = Adapter->HWDescHeadLength - pHalData->USBALLDummyLength;
|
||
#endif
|
||
BufAddr = pBuf->Buffer.VirtualAddress + DescLen;
|
||
|
||
ConstructHTNDPAPacket(
|
||
Adapter,
|
||
RA,
|
||
BufAddr,
|
||
&BufLen,
|
||
BW
|
||
);
|
||
|
||
pTcb->PacketLength = BufLen + DescLen;
|
||
|
||
pTcb->bTxEnableSwCalcDur = TRUE;
|
||
|
||
pTcb->BWOfPacket = BW;
|
||
|
||
if(ACTING_AS_IBSS(Adapter) || ACTING_AS_AP(Adapter))
|
||
pTcb->G_ID = 63;
|
||
|
||
pTcb->P_AID = pBeamformEntry->P_AID;
|
||
pTcb->DataRate = NDPTxRate; /*rate of NDP decide by Nr*/
|
||
|
||
Adapter->HalFunc.CmdSendPacketHandler(Adapter, pTcb, pBuf, pTcb->PacketLength, DESC_PACKET_TYPE_NORMAL, FALSE);
|
||
}
|
||
else
|
||
ret = FALSE;
|
||
|
||
PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
|
||
|
||
if(ret)
|
||
RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
SendSWHTNDPAPacket(
|
||
IN PADAPTER Adapter,
|
||
IN pu1Byte RA,
|
||
IN CHANNEL_WIDTH BW
|
||
)
|
||
{
|
||
PRT_TCB pTcb;
|
||
PRT_TX_LOCAL_BUFFER pBuf;
|
||
BOOLEAN ret = TRUE;
|
||
u1Byte Idx = 0, NDPTxRate = 0;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = GET_BEAMFORM_INFO(Adapter);
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
PRT_BEAMFORMING_ENTRY pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
|
||
|
||
NDPTxRate = Beamforming_GetHTNDPTxRate(Adapter, pBeamformEntry->CompSteeringNumofBFer);
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("%s, NDPTxRate =%d\n", __FUNCTION__, NDPTxRate));
|
||
|
||
PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
|
||
|
||
if(MgntGetBuffer(Adapter, &pTcb, &pBuf))
|
||
{
|
||
ConstructHTNDPAPacket(
|
||
Adapter,
|
||
RA,
|
||
pBuf->Buffer.VirtualAddress,
|
||
&pTcb->PacketLength,
|
||
BW
|
||
);
|
||
|
||
pTcb->bTxEnableSwCalcDur = TRUE;
|
||
|
||
pTcb->BWOfPacket = BW;
|
||
|
||
MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, NDPTxRate);
|
||
}
|
||
else
|
||
ret = FALSE;
|
||
|
||
PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
|
||
|
||
if(ret)
|
||
RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
|
||
|
||
BOOLEAN
|
||
Beamforming_SendHTNDPAPacket(
|
||
IN PADAPTER Adapter,
|
||
IN pu1Byte RA,
|
||
IN CHANNEL_WIDTH BW,
|
||
IN u1Byte QIdx
|
||
)
|
||
{
|
||
BOOLEAN ret = TRUE;
|
||
|
||
if(QIdx == BEACON_QUEUE)
|
||
ret = SendFWHTNDPAPacket(Adapter, RA, BW);
|
||
else
|
||
ret = SendSWHTNDPAPacket(Adapter, RA, BW);
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
VOID
|
||
ConstructVHTNDPAPacket(
|
||
PADAPTER Adapter,
|
||
pu1Byte RA,
|
||
u2Byte AID,
|
||
pu1Byte Buffer,
|
||
pu4Byte pLength,
|
||
CHANNEL_WIDTH BW
|
||
)
|
||
{
|
||
u2Byte Duration= 0;
|
||
u1Byte Sequence = 0;
|
||
pu1Byte pNDPAFrame = Buffer;
|
||
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
|
||
PRT_HIGH_THROUGHPUT pHTInfo = GET_HT_INFO(pMgntInfo);
|
||
RT_NDPA_STA_INFO STAInfo;
|
||
|
||
// Frame control.
|
||
SET_80211_HDR_FRAME_CONTROL(pNDPAFrame, 0);
|
||
SET_80211_HDR_TYPE_AND_SUBTYPE(pNDPAFrame, Type_NDPA);
|
||
|
||
SET_80211_HDR_ADDRESS1(pNDPAFrame, RA);
|
||
SET_80211_HDR_ADDRESS2(pNDPAFrame, Adapter->CurrentAddress);
|
||
|
||
Duration = 2*aSifsTime + 44;
|
||
|
||
if(BW == CHANNEL_WIDTH_80)
|
||
Duration += 40;
|
||
else if(BW == CHANNEL_WIDTH_40)
|
||
Duration+= 87;
|
||
else
|
||
Duration+= 180;
|
||
|
||
SET_80211_HDR_DURATION(pNDPAFrame, Duration);
|
||
|
||
Sequence = pMgntInfo->SoundingSequence << 2;
|
||
PlatformMoveMemory(pNDPAFrame+16, &Sequence,1);
|
||
|
||
if( ACTING_AS_IBSS(Adapter) ||
|
||
(ACTING_AS_AP(Adapter) == FALSE))
|
||
AID = 0;
|
||
|
||
STAInfo.AID = AID;
|
||
STAInfo.FeedbackType = 0;
|
||
STAInfo.NcIndex = 0;
|
||
|
||
PlatformMoveMemory(pNDPAFrame+17, (pu1Byte)&STAInfo, 2);
|
||
|
||
*pLength = 19;
|
||
}
|
||
|
||
BOOLEAN
|
||
SendFWVHTNDPAPacket(
|
||
IN PADAPTER Adapter,
|
||
IN pu1Byte RA,
|
||
IN u2Byte AID,
|
||
IN CHANNEL_WIDTH BW
|
||
)
|
||
{
|
||
PRT_TCB pTcb;
|
||
PRT_TX_LOCAL_BUFFER pBuf;
|
||
BOOLEAN ret = TRUE;
|
||
u4Byte BufLen;
|
||
pu1Byte BufAddr;
|
||
u1Byte DescLen = 0, Idx = 0, NDPTxRate = 0;
|
||
PADAPTER pDefAdapter = GetDefaultAdapter(Adapter);
|
||
PRT_BEAMFORMING_INFO pBeamInfo = GET_BEAMFORM_INFO(Adapter);
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
PRT_BEAMFORMING_ENTRY pBeamformEntry =phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
|
||
|
||
if(pBeamformEntry == NULL)
|
||
return FALSE;
|
||
|
||
NDPTxRate = Beamforming_GetVHTNDPTxRate(Adapter, pBeamformEntry->CompSteeringNumofBFer);
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("%s, NDPTxRate =%d\n", __FUNCTION__, NDPTxRate));
|
||
|
||
PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
|
||
|
||
if(MgntGetFWBuffer(pDefAdapter, &pTcb, &pBuf))
|
||
{
|
||
#if(DEV_BUS_TYPE != RT_PCI_INTERFACE)
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
|
||
DescLen = Adapter->HWDescHeadLength - pHalData->USBALLDummyLength;
|
||
#endif
|
||
BufAddr = pBuf->Buffer.VirtualAddress + DescLen;
|
||
|
||
ConstructVHTNDPAPacket(
|
||
Adapter,
|
||
RA,
|
||
AID,
|
||
BufAddr,
|
||
&BufLen,
|
||
BW
|
||
);
|
||
|
||
pTcb->PacketLength = BufLen + DescLen;
|
||
|
||
pTcb->bTxEnableSwCalcDur = TRUE;
|
||
|
||
pTcb->BWOfPacket = BW;
|
||
|
||
if(ACTING_AS_IBSS(Adapter) || ACTING_AS_AP(Adapter))
|
||
pTcb->G_ID = 63;
|
||
|
||
pTcb->P_AID = pBeamformEntry->P_AID;
|
||
pTcb->DataRate = NDPTxRate; /*decide by Nr*/
|
||
|
||
Adapter->HalFunc.CmdSendPacketHandler(Adapter, pTcb, pBuf, pTcb->PacketLength, DESC_PACKET_TYPE_NORMAL, FALSE);
|
||
}
|
||
else
|
||
ret = FALSE;
|
||
|
||
PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("@%s End, ret=%d \n", __FUNCTION__,ret));
|
||
|
||
if(ret)
|
||
RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
SendSWVHTNDPAPacket(
|
||
IN PADAPTER Adapter,
|
||
IN pu1Byte RA,
|
||
IN u2Byte AID,
|
||
IN CHANNEL_WIDTH BW
|
||
)
|
||
{
|
||
PRT_TCB pTcb;
|
||
PRT_TX_LOCAL_BUFFER pBuf;
|
||
BOOLEAN ret = TRUE;
|
||
u1Byte Idx = 0, NDPTxRate = 0;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = GET_BEAMFORM_INFO(Adapter);
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
PRT_BEAMFORMING_ENTRY pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
|
||
|
||
NDPTxRate = Beamforming_GetVHTNDPTxRate(Adapter, pBeamformEntry->CompSteeringNumofBFer);
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("%s, NDPTxRate =%d\n", __FUNCTION__, NDPTxRate));
|
||
|
||
PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
|
||
|
||
if(MgntGetBuffer(Adapter, &pTcb, &pBuf))
|
||
{
|
||
ConstructVHTNDPAPacket(
|
||
Adapter,
|
||
RA,
|
||
AID,
|
||
pBuf->Buffer.VirtualAddress,
|
||
&pTcb->PacketLength,
|
||
BW
|
||
);
|
||
|
||
pTcb->bTxEnableSwCalcDur = TRUE;
|
||
pTcb->BWOfPacket = BW;
|
||
|
||
/*rate of NDP decide by Nr*/
|
||
MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, NDPTxRate);
|
||
}
|
||
else
|
||
ret = FALSE;
|
||
|
||
PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("%s\n", __FUNCTION__));
|
||
|
||
if(ret)
|
||
RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
|
||
BOOLEAN
|
||
Beamforming_SendVHTNDPAPacket(
|
||
IN PADAPTER Adapter,
|
||
IN pu1Byte RA,
|
||
IN u2Byte AID,
|
||
IN CHANNEL_WIDTH BW,
|
||
IN u1Byte QIdx
|
||
)
|
||
{
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
BOOLEAN ret = TRUE;
|
||
|
||
HalComTxbf_Set(Adapter, TXBF_SET_GET_TX_RATE, NULL);
|
||
|
||
if ((pDM_Odm->TxBfDataRate >= ODM_RATEVHTSS3MCS7) && (pDM_Odm->TxBfDataRate <= ODM_RATEVHTSS3MCS9)) {
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s: 3SS VHT 789 don't sounding\n", __func__));
|
||
|
||
} else {
|
||
if(QIdx == BEACON_QUEUE)
|
||
ret = SendFWVHTNDPAPacket(Adapter, RA, AID, BW);
|
||
else
|
||
ret = SendSWVHTNDPAPacket(Adapter, RA, AID, BW);
|
||
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
|
||
BEAMFORMING_NOTIFY_STATE
|
||
phydm_beamfomring_bSounding(
|
||
IN PVOID pDM_VOID,
|
||
PRT_BEAMFORMING_INFO pBeamInfo,
|
||
pu1Byte Idx
|
||
)
|
||
{
|
||
BEAMFORMING_NOTIFY_STATE bSounding = BEAMFORMING_NOTIFY_NONE;
|
||
RT_BEAMFORMING_OID_INFO BeamOidInfo = pBeamInfo->BeamformingOidInfo;
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
// if(( Beamforming_GetBeamCap(pBeamInfo) & BEAMFORMER_CAP) == 0)
|
||
// bSounding = BEAMFORMING_NOTIFY_RESET;
|
||
if(BeamOidInfo.SoundOidMode == SOUNDING_STOP_All_TIMER)
|
||
bSounding = BEAMFORMING_NOTIFY_RESET;
|
||
else
|
||
{
|
||
u1Byte i;
|
||
|
||
for(i=0;i<BEAMFORMEE_ENTRY_NUM;i++)
|
||
{
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s: BFee Entry %d bUsed=%d, bSound=%d \n", __FUNCTION__, i, pBeamInfo->BeamformeeEntry[i].bUsed, pBeamInfo->BeamformeeEntry[i].bSound));
|
||
if(pBeamInfo->BeamformeeEntry[i].bUsed && (!pBeamInfo->BeamformeeEntry[i].bSound))
|
||
{
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: Add BFee entry %d\n", __FUNCTION__, i));
|
||
*Idx = i;
|
||
bSounding = BEAMFORMING_NOTIFY_ADD;
|
||
}
|
||
|
||
if((!pBeamInfo->BeamformeeEntry[i].bUsed) && pBeamInfo->BeamformeeEntry[i].bSound)
|
||
{
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: Delete BFee entry %d\n", __FUNCTION__, i));
|
||
*Idx = i;
|
||
bSounding = BEAMFORMING_NOTIFY_DELETE;
|
||
}
|
||
}
|
||
}
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s End, bSounding = %d\n", __FUNCTION__, bSounding) );
|
||
return bSounding;
|
||
}
|
||
|
||
|
||
//This function is unused
|
||
u1Byte
|
||
phydm_beamforming_SoundingIdx(
|
||
IN PVOID pDM_VOID,
|
||
PRT_BEAMFORMING_INFO pBeamInfo
|
||
)
|
||
{
|
||
u1Byte Idx = 0;
|
||
RT_BEAMFORMING_ENTRY BeamEntry;
|
||
RT_BEAMFORMING_OID_INFO BeamOidInfo = pBeamInfo->BeamformingOidInfo;
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
if( BeamOidInfo.SoundOidMode == SOUNDING_SW_HT_TIMER || BeamOidInfo.SoundOidMode == SOUNDING_SW_VHT_TIMER ||
|
||
BeamOidInfo.SoundOidMode == SOUNDING_HW_HT_TIMER || BeamOidInfo.SoundOidMode == SOUNDING_HW_VHT_TIMER)
|
||
Idx = BeamOidInfo.SoundOidIdx;
|
||
else
|
||
{
|
||
u1Byte i;
|
||
for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
|
||
{
|
||
if( pBeamInfo->BeamformeeEntry[i].bUsed &&
|
||
(FALSE == pBeamInfo->BeamformeeEntry[i].bSound))
|
||
{
|
||
Idx = i;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return Idx;
|
||
}
|
||
|
||
|
||
SOUNDING_MODE
|
||
phydm_beamforming_SoundingMode(
|
||
IN PVOID pDM_VOID,
|
||
PRT_BEAMFORMING_INFO pBeamInfo,
|
||
u1Byte Idx
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
u1Byte SupportInterface = pDM_Odm->SupportInterface;
|
||
|
||
RT_BEAMFORMING_ENTRY BeamEntry = pBeamInfo->BeamformeeEntry[Idx];
|
||
RT_BEAMFORMING_OID_INFO BeamOidInfo = pBeamInfo->BeamformingOidInfo;
|
||
SOUNDING_MODE Mode = BeamOidInfo.SoundOidMode;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
// RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s: OID mode is %d\n", __FUNCTION__, BeamOidInfo.SoundOidMode));
|
||
|
||
if(BeamOidInfo.SoundOidMode == SOUNDING_SW_VHT_TIMER || BeamOidInfo.SoundOidMode == SOUNDING_HW_VHT_TIMER)
|
||
{
|
||
if(BeamEntry.BeamformEntryCap & BEAMFORMER_CAP_VHT_SU)
|
||
Mode = BeamOidInfo.SoundOidMode;
|
||
else
|
||
Mode = SOUNDING_STOP_All_TIMER;
|
||
}
|
||
else if(BeamOidInfo.SoundOidMode == SOUNDING_SW_HT_TIMER || BeamOidInfo.SoundOidMode == SOUNDING_HW_HT_TIMER)
|
||
{
|
||
if(BeamEntry.BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT)
|
||
Mode = BeamOidInfo.SoundOidMode;
|
||
else
|
||
Mode = SOUNDING_STOP_All_TIMER;
|
||
}
|
||
else if(BeamEntry.BeamformEntryCap & BEAMFORMER_CAP_VHT_SU)
|
||
{
|
||
if((SupportInterface == ODM_ITRF_USB) && (pDM_Odm->SupportICType!= ODM_RTL8814A))
|
||
Mode = SOUNDING_FW_VHT_TIMER;
|
||
else
|
||
Mode = SOUNDING_SW_VHT_TIMER;
|
||
}
|
||
else if(BeamEntry.BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT)
|
||
{
|
||
if((SupportInterface == ODM_ITRF_USB) && (pDM_Odm->SupportICType != ODM_RTL8814A))
|
||
Mode = SOUNDING_FW_HT_TIMER;
|
||
else
|
||
Mode = SOUNDING_SW_HT_TIMER;
|
||
}
|
||
else
|
||
Mode = SOUNDING_STOP_All_TIMER;
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End, SupportInterface=%d, Mode=%d \n", __FUNCTION__, SupportInterface, Mode));
|
||
|
||
return Mode;
|
||
}
|
||
|
||
|
||
u2Byte
|
||
phydm_beamforming_SoundingTime(
|
||
IN PVOID pDM_VOID,
|
||
PRT_BEAMFORMING_INFO pBeamInfo,
|
||
SOUNDING_MODE Mode,
|
||
u1Byte Idx
|
||
)
|
||
{
|
||
u2Byte SoundingTime = 0xffff;
|
||
RT_BEAMFORMING_ENTRY BeamEntry = pBeamInfo->BeamformeeEntry[Idx];
|
||
RT_BEAMFORMING_OID_INFO BeamOidInfo = pBeamInfo->BeamformingOidInfo;
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
if(Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_HW_VHT_TIMER)
|
||
SoundingTime = BeamOidInfo.SoundOidPeriod * 32;
|
||
else if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_SW_VHT_TIMER)
|
||
//-@ Modified by David
|
||
SoundingTime = BeamEntry.SoundPeriod; //100*32; //BeamOidInfo.SoundOidPeriod;
|
||
else
|
||
SoundingTime = BeamEntry.SoundPeriod;
|
||
|
||
return SoundingTime;
|
||
}
|
||
|
||
|
||
CHANNEL_WIDTH
|
||
phydm_beamforming_SoundingBW(
|
||
IN PVOID pDM_VOID,
|
||
PRT_BEAMFORMING_INFO pBeamInfo,
|
||
SOUNDING_MODE Mode,
|
||
u1Byte Idx
|
||
)
|
||
{
|
||
CHANNEL_WIDTH SoundingBW = CHANNEL_WIDTH_20;
|
||
RT_BEAMFORMING_ENTRY BeamEntry = pBeamInfo->BeamformeeEntry[Idx];
|
||
RT_BEAMFORMING_OID_INFO BeamOidInfo = pBeamInfo->BeamformingOidInfo;
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
if(Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_HW_VHT_TIMER)
|
||
SoundingBW = BeamOidInfo.SoundOidBW;
|
||
else if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_SW_VHT_TIMER)
|
||
//-@ Modified by David
|
||
SoundingBW = BeamEntry.SoundBW; //BeamOidInfo.SoundOidBW;
|
||
else
|
||
SoundingBW = BeamEntry.SoundBW;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, SoundingBW=0x%X \n", __FUNCTION__, SoundingBW) );
|
||
|
||
return SoundingBW;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
phydm_Beamforming_SelectBeamEntry(
|
||
IN PVOID pDM_VOID,
|
||
PRT_BEAMFORMING_INFO pBeamInfo
|
||
)
|
||
{
|
||
PRT_SOUNDING_INFO pSoundInfo = &(pBeamInfo->SoundingInfo);
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
// pEntry.bSound is different between first and latter NDPA, and should not be used as BFee entry selection
|
||
// BTW, latter modification should sync to the selection mechanism of AP/ADSL instead of the fixed SoundIdx.
|
||
//pSoundInfo->SoundIdx = phydm_beamforming_SoundingIdx(pDM_Odm, pBeamInfo);
|
||
pSoundInfo->SoundIdx = 0;
|
||
|
||
if(pSoundInfo->SoundIdx < BEAMFORMEE_ENTRY_NUM)
|
||
pSoundInfo->SoundMode = phydm_beamforming_SoundingMode(pDM_Odm, pBeamInfo, pSoundInfo->SoundIdx);
|
||
else
|
||
pSoundInfo->SoundMode = SOUNDING_STOP_All_TIMER;
|
||
|
||
if(SOUNDING_STOP_All_TIMER == pSoundInfo->SoundMode)
|
||
return FALSE;
|
||
else
|
||
{
|
||
pSoundInfo->SoundBW = phydm_beamforming_SoundingBW(pDM_Odm, pBeamInfo, pSoundInfo->SoundMode, pSoundInfo->SoundIdx );
|
||
pSoundInfo->SoundPeriod = phydm_beamforming_SoundingTime(pDM_Odm, pBeamInfo, pSoundInfo->SoundMode, pSoundInfo->SoundIdx );
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
phydm_beamforming_StartPeriod(
|
||
IN PVOID pDM_VOID
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
PADAPTER Adapter = pDM_Odm->Adapter;
|
||
BOOLEAN Ret = TRUE;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
PRT_SOUNDING_INFO pSoundInfo = &(pBeamInfo->SoundingInfo);
|
||
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
phydm_Beamforming_DymNDPARate(pDM_Odm);
|
||
|
||
phydm_Beamforming_SelectBeamEntry(pDM_Odm, pBeamInfo); // Modified
|
||
|
||
|
||
if(pSoundInfo->SoundMode == SOUNDING_SW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_SW_HT_TIMER)
|
||
ODM_SetTimer(pDM_Odm, &pBeamInfo->BeamformingTimer, pSoundInfo->SoundPeriod);
|
||
else if(pSoundInfo->SoundMode == SOUNDING_HW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_HW_HT_TIMER ||
|
||
pSoundInfo->SoundMode == SOUNDING_AUTO_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_AUTO_HT_TIMER)
|
||
{
|
||
HAL_HW_TIMER_TYPE TimerType = HAL_TIMER_TXBF;
|
||
u4Byte val = (pSoundInfo->SoundPeriod | (TimerType<<16));
|
||
|
||
//HW timer stop: All IC has the same setting
|
||
Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_STOP, (pu1Byte)(&TimerType));
|
||
//ODM_Write1Byte(pDM_Odm, 0x15F, 0);
|
||
//HW timer init: All IC has the same setting, but 92E & 8812A only write 2 bytes
|
||
Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_INIT, (pu1Byte)(&val));
|
||
//ODM_Write1Byte(pDM_Odm, 0x164, 1);
|
||
//ODM_Write4Byte(pDM_Odm, 0x15C, val);
|
||
//HW timer start: All IC has the same setting
|
||
Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_START, (pu1Byte)(&TimerType));
|
||
//ODM_Write1Byte(pDM_Odm, 0x15F, 0x5);
|
||
}
|
||
else if(pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER)
|
||
{
|
||
Ret = BeamformingStart_FW(Adapter, pSoundInfo->SoundIdx);
|
||
}
|
||
else
|
||
Ret = FALSE;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: SoundIdx=%d, SoundMode=%d, SoundBW=%d, SoundPeriod=%d\n", __FUNCTION__,
|
||
pSoundInfo->SoundIdx, pSoundInfo->SoundMode, pSoundInfo->SoundBW, pSoundInfo->SoundPeriod));
|
||
|
||
return Ret;
|
||
}
|
||
|
||
// Used after Beamforming_Leave, and will clear the setting of the "already deleted" entry
|
||
VOID
|
||
phydm_beamforming_EndPeriod_SW(
|
||
IN PVOID pDM_VOID
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
PADAPTER Adapter = pDM_Odm->Adapter;
|
||
u1Byte Idx = 0;
|
||
PRT_BEAMFORMING_ENTRY pBeamformEntry;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
PRT_SOUNDING_INFO pSoundInfo = &(pBeamInfo->SoundingInfo);
|
||
|
||
HAL_HW_TIMER_TYPE TimerType = HAL_TIMER_TXBF;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
if(pSoundInfo->SoundMode == SOUNDING_SW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_SW_HT_TIMER)
|
||
ODM_CancelTimer(pDM_Odm, &pBeamInfo->BeamformingTimer);
|
||
else if( pSoundInfo->SoundMode == SOUNDING_HW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_HW_HT_TIMER ||
|
||
pSoundInfo->SoundMode == SOUNDING_AUTO_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_AUTO_HT_TIMER)
|
||
//HW timer stop: All IC has the same setting
|
||
Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_STOP, (pu1Byte)(&TimerType));
|
||
//ODM_Write1Byte(pDM_Odm, 0x15F, 0);
|
||
}
|
||
|
||
VOID
|
||
phydm_beamforming_EndPeriod_FW(
|
||
IN PVOID pDM_VOID
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
phydm_Beamforming_End_FW(pDM_Odm);
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
phydm_beamforming_ClearEntry_SW(
|
||
IN PVOID pDM_VOID,
|
||
BOOLEAN IsDelete,
|
||
u1Byte DeleteIdx
|
||
)
|
||
{
|
||
u1Byte Idx = 0;
|
||
PRT_BEAMFORMING_ENTRY pBeamformEntry = NULL;
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
if(IsDelete)
|
||
{
|
||
if(DeleteIdx<BEAMFORMEE_ENTRY_NUM)
|
||
{
|
||
pBeamformEntry = pBeamInfo->BeamformeeEntry + DeleteIdx;
|
||
|
||
if(!((!pBeamformEntry->bUsed) && pBeamformEntry->bSound))
|
||
{
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: SW DeleteIdx is wrong!!!!! \n",__FUNCTION__));
|
||
return;
|
||
}
|
||
}
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: SW delete BFee entry %d \n", __FUNCTION__, DeleteIdx));
|
||
if(pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSING)
|
||
{
|
||
pBeamformEntry->bBeamformingInProgress = FALSE;
|
||
pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
|
||
}
|
||
else if(pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSED)
|
||
{
|
||
pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
|
||
HalComTxbf_Set(pDM_Odm->Adapter, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&DeleteIdx);
|
||
}
|
||
|
||
pBeamformEntry->bSound = FALSE;
|
||
}
|
||
else
|
||
{
|
||
for(Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++)
|
||
{
|
||
pBeamformEntry = pBeamInfo->BeamformeeEntry+Idx;
|
||
|
||
// Used after bSounding=RESET, and will clear the setting of "ever sounded" entry, which is not necessarily be deleted.
|
||
// This function is mainly used in case "BeamOidInfo.SoundOidMode == SOUNDING_STOP_All_TIMER".
|
||
// However, setting oid doesn't delete entries (bUsed is still TRUE), new entries may fail to be added in.
|
||
|
||
if(pBeamformEntry->bSound)
|
||
{
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: SW reset BFee entry %d \n", __FUNCTION__, Idx));
|
||
/*
|
||
* If End procedure is
|
||
* 1. Between (Send NDPA, C2H packet return), reset state to initialized.
|
||
* After C2H packet return , status bit will be set to zero.
|
||
*
|
||
* 2. After C2H packet, then reset state to initialized and clear status bit.
|
||
*/
|
||
|
||
if (pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSING)
|
||
phydm_Beamforming_End_SW(pDM_Odm, 0);
|
||
else if (pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSED) {
|
||
pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;
|
||
HalComTxbf_Set(pDM_Odm->Adapter, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&Idx);
|
||
}
|
||
|
||
pBeamformEntry->bSound = FALSE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
VOID
|
||
phydm_beamforming_ClearEntry_FW(
|
||
IN PVOID pDM_VOID,
|
||
BOOLEAN IsDelete,
|
||
u1Byte DeleteIdx
|
||
)
|
||
{
|
||
u1Byte Idx = 0;
|
||
PRT_BEAMFORMING_ENTRY pBeamformEntry = NULL;
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
if(IsDelete)
|
||
{
|
||
if(DeleteIdx<BEAMFORMEE_ENTRY_NUM)
|
||
{
|
||
pBeamformEntry = pBeamInfo->BeamformeeEntry + DeleteIdx;
|
||
|
||
if(!((!pBeamformEntry->bUsed) && pBeamformEntry->bSound))
|
||
{
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: FW DeleteIdx is wrong!!!!! \n",__FUNCTION__));
|
||
return;
|
||
}
|
||
}
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: FW delete BFee entry %d \n", __FUNCTION__, DeleteIdx));
|
||
pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
|
||
pBeamformEntry->bSound = FALSE;
|
||
}
|
||
else
|
||
{
|
||
for(Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++)
|
||
{
|
||
pBeamformEntry = pBeamInfo->BeamformeeEntry+Idx;
|
||
|
||
// Used after bSounding=RESET, and will clear the setting of "ever sounded" entry, which is not necessarily be deleted.
|
||
// This function is mainly used in case "BeamOidInfo.SoundOidMode == SOUNDING_STOP_All_TIMER".
|
||
// However, setting oid doesn't delete entries (bUsed is still TRUE), new entries may fail to be added in.
|
||
|
||
if(pBeamformEntry->bSound)
|
||
{
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: FW reset BFee entry %d \n", __FUNCTION__, Idx));
|
||
/*
|
||
* If End procedure is
|
||
* 1. Between (Send NDPA, C2H packet return), reset state to initialized.
|
||
* After C2H packet return , status bit will be set to zero.
|
||
*
|
||
* 2. After C2H packet, then reset state to initialized and clear status bit.
|
||
*/
|
||
|
||
pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;
|
||
pBeamformEntry->bSound = FALSE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Called :
|
||
* 1. Add and delete entry : Beamforming_Enter/Beamforming_Leave
|
||
* 2. FW trigger : Beamforming_SetTxBFen
|
||
* 3. Set OID_RT_BEAMFORMING_PERIOD : BeamformingControl_V2
|
||
*/
|
||
VOID
|
||
phydm_Beamforming_Notify(
|
||
IN PVOID pDM_VOID
|
||
)
|
||
{
|
||
u1Byte Idx=BEAMFORMEE_ENTRY_NUM;
|
||
BEAMFORMING_NOTIFY_STATE bSounding = BEAMFORMING_NOTIFY_NONE;
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
PRT_SOUNDING_INFO pSoundInfo = &(pBeamInfo->SoundingInfo);
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[Beamforming]%s Start!\n", __FUNCTION__) );
|
||
|
||
bSounding = phydm_beamfomring_bSounding(pDM_Odm, pBeamInfo, &Idx);
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[Beamforming]%s, Before notify, BeamformState=%d, bSounding=%d, Idx=%d\n", __FUNCTION__, pBeamInfo->BeamformState, bSounding, Idx));
|
||
|
||
if(pBeamInfo->BeamformState == BEAMFORMING_STATE_END)
|
||
{
|
||
if(bSounding==BEAMFORMING_NOTIFY_ADD)
|
||
{
|
||
if(phydm_beamforming_StartPeriod(pDM_Odm) == TRUE)
|
||
pBeamInfo->BeamformState = BEAMFORMING_STATE_START_1BFee;
|
||
}
|
||
}
|
||
else if(pBeamInfo->BeamformState == BEAMFORMING_STATE_START_1BFee)
|
||
{
|
||
if(bSounding==BEAMFORMING_NOTIFY_ADD)
|
||
{
|
||
if(phydm_beamforming_StartPeriod(pDM_Odm) == TRUE)
|
||
pBeamInfo->BeamformState = BEAMFORMING_STATE_START_2BFee;
|
||
else
|
||
pBeamInfo->BeamformState = BEAMFORMING_STATE_START_1BFee;
|
||
}
|
||
else if(bSounding==BEAMFORMING_NOTIFY_DELETE)
|
||
{
|
||
if(pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER)
|
||
{
|
||
phydm_beamforming_ClearEntry_FW(pDM_Odm, TRUE, Idx); // Modified by Jeffery @ 2014-11-04
|
||
phydm_beamforming_EndPeriod_FW(pDM_Odm);
|
||
}
|
||
else
|
||
{
|
||
phydm_beamforming_ClearEntry_SW(pDM_Odm, TRUE, Idx); // Modified by Jeffery @ 2014-11-04
|
||
phydm_beamforming_EndPeriod_SW(pDM_Odm);
|
||
}
|
||
|
||
pBeamInfo->BeamformState = BEAMFORMING_STATE_END;
|
||
}
|
||
else if(bSounding==BEAMFORMING_NOTIFY_RESET)
|
||
{
|
||
if(pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER)
|
||
{
|
||
phydm_beamforming_ClearEntry_FW(pDM_Odm, FALSE, Idx); // Modified by Jeffery @ 2014-11-04
|
||
phydm_beamforming_EndPeriod_FW(pDM_Odm);
|
||
}
|
||
else
|
||
{
|
||
phydm_beamforming_ClearEntry_SW(pDM_Odm, FALSE, Idx); // Modified by Jeffery @ 2014-11-04
|
||
phydm_beamforming_EndPeriod_SW(pDM_Odm);
|
||
}
|
||
|
||
pBeamInfo->BeamformState = BEAMFORMING_STATE_END;
|
||
}
|
||
}
|
||
else if(pBeamInfo->BeamformState == BEAMFORMING_STATE_START_2BFee)
|
||
{
|
||
if(bSounding==BEAMFORMING_NOTIFY_ADD)
|
||
{
|
||
RT_ASSERT(FALSE, ("[David]@%s: Should be blocked at InitEntry!!!!! \n", __FUNCTION__));
|
||
}
|
||
else if(bSounding==BEAMFORMING_NOTIFY_DELETE)
|
||
{
|
||
if(pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER)
|
||
{
|
||
phydm_beamforming_ClearEntry_FW(pDM_Odm, TRUE, Idx); // Modified by Jeffery @ 2014-11-04
|
||
phydm_beamforming_EndPeriod_FW(pDM_Odm);
|
||
}
|
||
else
|
||
{
|
||
// For 2->1 entry, we should not cancel SW timer
|
||
phydm_beamforming_ClearEntry_SW(pDM_Odm, TRUE, Idx);
|
||
}
|
||
|
||
pBeamInfo->BeamformState = BEAMFORMING_STATE_START_1BFee;
|
||
}
|
||
else if(bSounding==BEAMFORMING_NOTIFY_RESET)
|
||
{
|
||
if(pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER)
|
||
{
|
||
phydm_beamforming_ClearEntry_FW(pDM_Odm, FALSE, Idx); // Modified by Jeffery @ 2014-11-04
|
||
phydm_beamforming_EndPeriod_FW(pDM_Odm);
|
||
}
|
||
else
|
||
{
|
||
phydm_beamforming_ClearEntry_SW(pDM_Odm, FALSE, Idx); // Modified by Jeffery @ 2014-11-04
|
||
phydm_beamforming_EndPeriod_SW(pDM_Odm);
|
||
}
|
||
|
||
pBeamInfo->BeamformState = BEAMFORMING_STATE_END;
|
||
}
|
||
}
|
||
else
|
||
RT_ASSERT(FALSE, ("%s BeamformState %d\n", __FUNCTION__, pBeamInfo->BeamformState));
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s End, after Notify, BeamformState =%d\n", __FUNCTION__, pBeamInfo->BeamformState));
|
||
}
|
||
|
||
|
||
|
||
BOOLEAN
|
||
Beamforming_InitEntry(
|
||
PADAPTER Adapter,
|
||
PRT_WLAN_STA pSTA,
|
||
pu1Byte BFerBFeeIdx
|
||
)
|
||
{
|
||
PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
|
||
PRT_HIGH_THROUGHPUT pHTInfo = GET_HT_INFO(pMgntInfo);
|
||
PRT_VERY_HIGH_THROUGHPUT pVHTInfo = GET_VHT_INFO(pMgntInfo);
|
||
PRT_BEAMFORMING_ENTRY pBeamformEntry = NULL;
|
||
PRT_BEAMFORMER_ENTRY pBeamformerEntry = NULL;
|
||
pu1Byte RA;
|
||
u2Byte AID, MacID;
|
||
WIRELESS_MODE WirelessMode;
|
||
CHANNEL_WIDTH BW = CHANNEL_WIDTH_20;
|
||
BEAMFORMING_CAP BeamformCap = BEAMFORMING_CAP_NONE;
|
||
u1Byte BFerIdx=0xF, BFeeIdx=0xF;
|
||
u1Byte NumofSoundingDim = 0, CompSteeringNumofBFer = 0;
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__));
|
||
|
||
// The current setting does not support Beaforming
|
||
if(BEAMFORMING_CAP_NONE == pHTInfo->HtBeamformCap && BEAMFORMING_CAP_NONE == pVHTInfo->VhtBeamformCap)
|
||
{
|
||
RT_DISP(FBEAM, FBEAM_ERROR, ("The configuration disabled Beamforming! Skip...\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
// IBSS, AP mode
|
||
if(pSTA != NULL)
|
||
{
|
||
AID = pSTA->AID;
|
||
RA = pSTA->MacAddr;
|
||
MacID = pSTA->AssociatedMacId;
|
||
WirelessMode = pSTA->WirelessMode;
|
||
BW = pSTA->BandWidth;
|
||
}
|
||
else // Client mode
|
||
{
|
||
AID = pMgntInfo->mAId;
|
||
RA = pMgntInfo->Bssid;
|
||
MacID = pMgntInfo->mMacId;
|
||
WirelessMode = pMgntInfo->dot11CurrentWirelessMode;
|
||
BW = pMgntInfo->dot11CurrentChannelBandWidth;
|
||
}
|
||
|
||
if(WirelessMode < WIRELESS_MODE_N_24G)
|
||
return FALSE;
|
||
else
|
||
{
|
||
//3 // HT
|
||
u1Byte CurBeamform;
|
||
u2Byte CurBeamformVHT;
|
||
|
||
if(pSTA != NULL)
|
||
CurBeamform = pSTA->HTInfo.HtCurBeamform;
|
||
else
|
||
CurBeamform = pHTInfo->HtCurBeamform;
|
||
|
||
// We are Beamformee because the STA is Beamformer
|
||
if(TEST_FLAG(CurBeamform, BEAMFORMING_HT_BEAMFORMER_ENABLE))
|
||
{
|
||
BeamformCap =(BEAMFORMING_CAP)(BeamformCap |BEAMFORMEE_CAP_HT_EXPLICIT);
|
||
NumofSoundingDim = (CurBeamform&BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP)>>6;
|
||
}
|
||
|
||
// We are Beamformer because the STA is Beamformee
|
||
if( TEST_FLAG(CurBeamform, BEAMFORMING_HT_BEAMFORMEE_ENABLE) ||
|
||
TEST_FLAG(pHTInfo->HtBeamformCap, BEAMFORMING_HT_BEAMFORMER_TEST))
|
||
{
|
||
BeamformCap =(BEAMFORMING_CAP)(BeamformCap | BEAMFORMER_CAP_HT_EXPLICIT);
|
||
CompSteeringNumofBFer = (CurBeamform & BEAMFORMING_HT_BEAMFORMER_STEER_NUM)>>4;
|
||
}
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s, CurBeamform=0x%X, BeamformCap=0x%X\n", __FUNCTION__, CurBeamform, BeamformCap));
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s, NumofSoundingDim=%d, CompSteeringNumofBFer=%d\n", __FUNCTION__, NumofSoundingDim, CompSteeringNumofBFer));
|
||
|
||
|
||
if(WirelessMode == WIRELESS_MODE_AC_5G || WirelessMode == WIRELESS_MODE_AC_24G)
|
||
{
|
||
//3 // VHT
|
||
if(pSTA != NULL)
|
||
CurBeamformVHT = pSTA->VHTInfo.VhtCurBeamform;
|
||
else
|
||
CurBeamformVHT = pVHTInfo->VhtCurBeamform;
|
||
|
||
// We are Beamformee because the STA is Beamformer
|
||
if(TEST_FLAG(CurBeamformVHT, BEAMFORMING_VHT_BEAMFORMER_ENABLE))
|
||
{
|
||
BeamformCap =(BEAMFORMING_CAP)(BeamformCap |BEAMFORMEE_CAP_VHT_SU);
|
||
NumofSoundingDim = (CurBeamformVHT & BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM)>>12;
|
||
}
|
||
// We are Beamformer because the STA is Beamformee
|
||
if( TEST_FLAG(CurBeamformVHT, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) ||
|
||
TEST_FLAG(pVHTInfo->VhtBeamformCap, BEAMFORMING_VHT_BEAMFORMER_TEST))
|
||
{
|
||
BeamformCap =(BEAMFORMING_CAP)(BeamformCap |BEAMFORMER_CAP_VHT_SU);
|
||
CompSteeringNumofBFer = (CurBeamformVHT & BEAMFORMING_VHT_BEAMFORMER_STS_CAP)>>8;
|
||
}
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s, CurBeamformVHT=0x%X, BeamformCap=0x%X\n", __FUNCTION__, CurBeamformVHT, BeamformCap));
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("%s, NumofSoundingDim=0x%X, CompSteeringNumofBFer=0x%X\n", __FUNCTION__, NumofSoundingDim, CompSteeringNumofBFer));
|
||
|
||
}
|
||
}
|
||
|
||
|
||
if(BeamformCap == BEAMFORMING_CAP_NONE)
|
||
return FALSE;
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s, Self BF Entry Cap = 0x%02X\n", __FUNCTION__, BeamformCap));
|
||
|
||
// We are BFee, so the entry is BFer
|
||
if((BeamformCap & BEAMFORMEE_CAP_VHT_SU) || (BeamformCap & BEAMFORMEE_CAP_HT_EXPLICIT))
|
||
{
|
||
pBeamformerEntry = phydm_Beamforming_GetBFerEntryByAddr(pDM_Odm, RA, &BFerIdx);
|
||
|
||
if(pBeamformerEntry == NULL)
|
||
{
|
||
pBeamformerEntry = Beamforming_AddBFerEntry(Adapter, RA, AID, BeamformCap, NumofSoundingDim ,&BFerIdx);
|
||
|
||
if(pBeamformerEntry == NULL)
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s: Not enough BFer entry!!!!! \n", __FUNCTION__));
|
||
}
|
||
}
|
||
|
||
// We are BFer, so the entry is BFee
|
||
if((BeamformCap & BEAMFORMER_CAP_VHT_SU) || (BeamformCap & BEAMFORMER_CAP_HT_EXPLICIT))
|
||
{
|
||
pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &BFeeIdx);
|
||
|
||
// <20>p<EFBFBD>GBFeeIdx = 0xF <20>h<EFBFBD>N<EFBFBD><4E><EFBFBD>ثeentry<72><79><EFBFBD><EFBFBD><EFBFBD>S<EFBFBD><53><EFBFBD>ۦP<DBA6><50>MACID<49>b<EFBFBD><62>
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s: Get BFee entry 0x%X by address \n", __FUNCTION__, BFeeIdx));
|
||
if(pBeamformEntry == NULL)
|
||
{
|
||
pBeamformEntry = Beamforming_AddBFeeEntry(Adapter, RA, AID, MacID, BW, BeamformCap, NumofSoundingDim, CompSteeringNumofBFer, &BFeeIdx);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s: Add BFee entry %d \n", __FUNCTION__, BFeeIdx));
|
||
|
||
if(pBeamformEntry == NULL)
|
||
return FALSE;
|
||
else
|
||
pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZEING;
|
||
}
|
||
else
|
||
{
|
||
// Entry has been created. If entry is initialing or progressing then errors occur.
|
||
if( pBeamformEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_INITIALIZED &&
|
||
pBeamformEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSED)
|
||
{
|
||
RT_ASSERT(TRUE, ("Error State of Beamforming"));
|
||
return FALSE;
|
||
}
|
||
else
|
||
pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZEING;
|
||
}
|
||
|
||
pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;
|
||
|
||
}
|
||
|
||
*BFerBFeeIdx = (BFerIdx<<4) | BFeeIdx;
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End: BFerIdx=0x%X, BFeeIdx=0x%X, BFerBFeeIdx=0x%X \n", __FUNCTION__, BFerIdx, BFeeIdx, *BFerBFeeIdx));
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
VOID
|
||
Beamforming_DeInitEntry(
|
||
PADAPTER Adapter,
|
||
pu1Byte RA
|
||
)
|
||
{
|
||
u1Byte Idx = 0;
|
||
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s Start!\n", __FUNCTION__) );
|
||
|
||
if(Beamforming_RemoveEntry(Adapter, RA, &Idx) == TRUE)
|
||
{
|
||
HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_LEAVE, (pu1Byte)&Idx);
|
||
}
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End, Idx = 0x%X\n", __FUNCTION__, Idx));
|
||
}
|
||
|
||
|
||
VOID
|
||
Beamforming_Reset(
|
||
PADAPTER Adapter
|
||
)
|
||
{
|
||
u1Byte Idx = 0;
|
||
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
|
||
PRT_BEAMFORMING_INFO pBeamformingInfo = GET_BEAMFORM_INFO(Adapter);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
|
||
|
||
for(Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++)
|
||
{
|
||
if(pBeamformingInfo->BeamformeeEntry[Idx].bUsed == TRUE)
|
||
{
|
||
pBeamformingInfo->BeamformeeEntry[Idx].bUsed = FALSE;
|
||
pBeamformingInfo->BeamformeeEntry[Idx].BeamformEntryCap = BEAMFORMING_CAP_NONE;
|
||
//pBeamformingInfo->BeamformeeEntry[Idx].BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
|
||
//-@ Modified by David
|
||
pBeamformingInfo->BeamformeeEntry[Idx].bBeamformingInProgress = FALSE;
|
||
HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_LEAVE, (pu1Byte)&Idx);
|
||
}
|
||
}
|
||
|
||
for(Idx = 0; Idx < BEAMFORMER_ENTRY_NUM; Idx++)
|
||
{
|
||
pBeamformingInfo->BeamformerEntry[Idx].bUsed = FALSE;
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s, Idx=%d, bUsed=%d \n", __FUNCTION__, Idx, pBeamformingInfo->BeamformerEntry[Idx].bUsed));
|
||
}
|
||
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
BeamformingStart_V1(
|
||
PADAPTER Adapter,
|
||
pu1Byte RA,
|
||
BOOLEAN Mode,
|
||
CHANNEL_WIDTH BW,
|
||
u1Byte Rate
|
||
)
|
||
{
|
||
u1Byte Idx = 0;
|
||
PRT_BEAMFORMING_ENTRY pEntry;
|
||
BOOLEAN ret = TRUE;
|
||
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
|
||
PRT_BEAMFORMING_INFO pBeamInfo = GET_BEAMFORM_INFO(Adapter);
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
|
||
|
||
pEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);
|
||
|
||
if(pEntry->bUsed == FALSE)
|
||
{
|
||
RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Skip Beamforming, no entry for addr = "), RA);
|
||
pEntry->bBeamformingInProgress = FALSE;
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
if(pEntry->bBeamformingInProgress)
|
||
{
|
||
RT_DISP(FBEAM, FBEAM_ERROR, ("bBeamformingInProgress, skip...\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
pEntry->bBeamformingInProgress = TRUE;
|
||
|
||
if(Mode == 1)
|
||
{
|
||
if(!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT))
|
||
{
|
||
RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Skip Beamforming, entry without BEAMFORMEE_CAP_HT_EXPLICIT for addr = "), RA);
|
||
pEntry->bBeamformingInProgress = FALSE;
|
||
return FALSE;
|
||
}
|
||
}
|
||
else if(Mode == 0)
|
||
{
|
||
if(!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_VHT_SU))
|
||
{
|
||
RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Skip Beamforming, entry without BEAMFORMEE_CAP_VHT_SU for addr = "), RA);
|
||
pEntry->bBeamformingInProgress = FALSE;
|
||
return FALSE;
|
||
}
|
||
|
||
}
|
||
if( pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_INITIALIZED &&
|
||
pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSED)
|
||
{
|
||
RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Skip Beamforming, state without (BEAMFORMING_STATE_INITIALIZED | BEAMFORMING_STATE_PROGRESSED) for addr = "), RA);
|
||
pEntry->bBeamformingInProgress = FALSE;
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSING;
|
||
pEntry->bSound = TRUE;
|
||
}
|
||
}
|
||
|
||
pEntry->SoundBW = BW;
|
||
pBeamInfo->BeamformeeCurIdx = Idx;
|
||
phydm_Beamforming_NDPARate(pDM_Odm, BW, Rate);
|
||
HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&Idx);
|
||
|
||
if(Mode == 1)
|
||
ret = Beamforming_SendHTNDPAPacket(Adapter,RA, BW, NORMAL_QUEUE);
|
||
else
|
||
ret = Beamforming_SendVHTNDPAPacket(Adapter,RA, pEntry->AID, BW, NORMAL_QUEUE);
|
||
|
||
if(ret == FALSE)
|
||
{
|
||
RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Beamforming_RemoveEntry because of failure sending NDPA for addr = "), RA);
|
||
/* Beamforming_RemoveEntry(Adapter, RA, &Idx);*/
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s calls Beamforming_Leave, RA=0x%x \n", __FUNCTION__,RA) );
|
||
Beamforming_Leave(Adapter, RA);
|
||
pEntry->bBeamformingInProgress = FALSE;
|
||
return FALSE;
|
||
}
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("%s Idx %d\n", __FUNCTION__, Idx));
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
BeamformingStart_SW(
|
||
PADAPTER Adapter,
|
||
u1Byte Idx,
|
||
u1Byte Mode,
|
||
CHANNEL_WIDTH BW
|
||
)
|
||
{
|
||
pu1Byte RA = NULL;
|
||
PRT_BEAMFORMING_ENTRY pEntry;
|
||
BOOLEAN ret = TRUE;
|
||
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
|
||
PRT_BEAMFORMING_INFO pBeamInfo = GET_BEAMFORM_INFO(Adapter);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
|
||
|
||
pEntry = &(pBeamInfo->BeamformeeEntry[Idx]);
|
||
|
||
if(pEntry->bUsed == FALSE)
|
||
{
|
||
RT_DISP(FBEAM, FBEAM_ERROR, ("Skip Beamforming, no entry for Idx =%d\n", Idx));
|
||
pEntry->bBeamformingInProgress = FALSE;
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
if(pEntry->bBeamformingInProgress)
|
||
{
|
||
RT_DISP(FBEAM, FBEAM_ERROR, ("bBeamformingInProgress, skip...\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
pEntry->bBeamformingInProgress = TRUE;
|
||
|
||
RA = pEntry->MacAddr;
|
||
|
||
if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_AUTO_HT_TIMER)
|
||
{
|
||
if(!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT))
|
||
{
|
||
RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Skip Beamforming, entry without BEAMFORMEE_CAP_HT_EXPLICIT for addr = "), RA);
|
||
pEntry->bBeamformingInProgress = FALSE;
|
||
return FALSE;
|
||
}
|
||
}
|
||
else if(Mode == SOUNDING_SW_VHT_TIMER || Mode == SOUNDING_HW_VHT_TIMER || Mode == SOUNDING_AUTO_VHT_TIMER)
|
||
{
|
||
if(!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_VHT_SU))
|
||
{
|
||
RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Skip Beamforming, entry without BEAMFORMEE_CAP_VHT_SU for addr = "), RA);
|
||
pEntry->bBeamformingInProgress = FALSE;
|
||
return FALSE;
|
||
}
|
||
|
||
}
|
||
if( pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_INITIALIZED &&
|
||
pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSED)
|
||
{
|
||
RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Skip Beamforming, state without (BEAMFORMING_STATE_INITIALIZED | BEAMFORMING_STATE_PROGRESSED) for addr = "), RA);
|
||
pEntry->bBeamformingInProgress = FALSE;
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSING;
|
||
pEntry->bSound = TRUE;
|
||
}
|
||
}
|
||
|
||
pBeamInfo->BeamformeeCurIdx = Idx;
|
||
//2014.12.22 Luke: Need to be checked
|
||
/*GET_TXBF_INFO(Adapter)->fTxbfSet(Adapter, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&Idx);*/
|
||
|
||
if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_AUTO_HT_TIMER)
|
||
ret = Beamforming_SendHTNDPAPacket(Adapter,RA, BW, NORMAL_QUEUE);
|
||
else
|
||
ret = Beamforming_SendVHTNDPAPacket(Adapter,RA, pEntry->AID, BW, NORMAL_QUEUE);
|
||
|
||
if(ret == FALSE)
|
||
{
|
||
RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Beamforming_RemoveEntry because of failure sending NDPA for addr = "), RA);
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s calls Beamforming_Leave, RA=0x%x \n", __FUNCTION__,RA) );
|
||
Beamforming_Leave(Adapter, RA);
|
||
pEntry->bBeamformingInProgress = FALSE;
|
||
return FALSE;
|
||
}
|
||
|
||
if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_AUTO_HT_TIMER)
|
||
{
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s: Send HT NDPA for current idx=%d\n", __FUNCTION__, Idx));
|
||
}
|
||
else
|
||
{
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s: Send VHT NDPA for current idx=%d\n", __FUNCTION__, Idx));
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
BeamformingStart_FW(
|
||
PADAPTER Adapter,
|
||
u1Byte Idx
|
||
)
|
||
{
|
||
pu1Byte RA = NULL;
|
||
PRT_BEAMFORMING_ENTRY pEntry;
|
||
BOOLEAN ret = TRUE;
|
||
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
|
||
PRT_BEAMFORMING_INFO pBeamInfo = GET_BEAMFORM_INFO(Adapter);
|
||
|
||
pEntry = &(pBeamInfo->BeamformeeEntry[Idx]);
|
||
if(pEntry->bUsed == FALSE)
|
||
{
|
||
RT_DISP(FBEAM, FBEAM_ERROR, ("Skip Beamforming, no entry for Idx =%d\n", Idx));
|
||
return FALSE;
|
||
}
|
||
|
||
pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSING;
|
||
pEntry->bSound = TRUE;
|
||
HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_FW_NDPA, (pu1Byte)&Idx);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("@%s End, Idx=0x%X \n", __FUNCTION__, Idx));
|
||
return TRUE;
|
||
}
|
||
|
||
VOID
|
||
Beamforming_CheckSoundingSuccess(
|
||
PADAPTER Adapter,
|
||
BOOLEAN Status
|
||
)
|
||
{
|
||
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
|
||
PRT_BEAMFORMING_INFO pBeamInfo = GET_BEAMFORM_INFO(Adapter);
|
||
PRT_BEAMFORMING_ENTRY pEntry = &(pBeamInfo->BeamformeeEntry[pBeamInfo->BeamformeeCurIdx]);
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
|
||
|
||
if(Status == 1){
|
||
if(pEntry->LogStatusFailCnt == 21)
|
||
Beamforming_DymPeriod(pDM_Odm,Status);
|
||
|
||
pEntry->LogStatusFailCnt = 0;
|
||
}
|
||
else if(pEntry->LogStatusFailCnt <= 20){
|
||
pEntry->LogStatusFailCnt++;
|
||
RT_DISP(FBEAM, FBEAM_ERROR, ("%s LogStatusFailCnt %d\n", __FUNCTION__, pEntry->LogStatusFailCnt));
|
||
}
|
||
if(pEntry->LogStatusFailCnt > 20){
|
||
pEntry->LogStatusFailCnt = 21;
|
||
RT_DISP(FBEAM, FBEAM_ERROR, ("%s LogStatusFailCnt > 20, Stop SOUNDING\n", __FUNCTION__));
|
||
Beamforming_DymPeriod(pDM_Odm,Status);
|
||
}
|
||
}
|
||
|
||
VOID
|
||
phydm_Beamforming_End_SW(
|
||
IN PVOID pDM_VOID,
|
||
BOOLEAN Status
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
PRT_BEAMFORMING_ENTRY pEntry = &(pBeamInfo->BeamformeeEntry[pBeamInfo->BeamformeeCurIdx]);
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
if(pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSING)
|
||
{
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s BeamformStatus %d\n", __FUNCTION__, pEntry->BeamformEntryState));
|
||
return;
|
||
}
|
||
|
||
if ((pDM_Odm->TxBfDataRate >= ODM_RATEVHTSS3MCS7) && (pDM_Odm->TxBfDataRate <= ODM_RATEVHTSS3MCS9))
|
||
{
|
||
ODM_RT_TRACE(pDM_Odm, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, VHT3SS 7,8,9, do not apply V matrix.\n", __func__));
|
||
pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;
|
||
HalComTxbf_Set(pDM_Odm->Adapter, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&(pBeamInfo->BeamformeeCurIdx));
|
||
} else if (Status == 1) {
|
||
pEntry->LogStatusFailCnt = 0;
|
||
pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSED;
|
||
HalComTxbf_Set(pDM_Odm->Adapter, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&(pBeamInfo->BeamformeeCurIdx));
|
||
}
|
||
else
|
||
{
|
||
pEntry->LogStatusFailCnt++;
|
||
pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;
|
||
HalComTxbf_Set(pDM_Odm->Adapter, TXBF_SET_TX_PATH_RESET, (pu1Byte)&(pBeamInfo->BeamformeeCurIdx));
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s LogStatusFailCnt %d\n", __FUNCTION__, pEntry->LogStatusFailCnt));
|
||
}
|
||
if(pEntry->LogStatusFailCnt > 50)
|
||
{
|
||
RT_DISP(FBEAM, FBEAM_ERROR, ("%s LogStatusFailCnt > 50, Stop SOUNDING\n", __FUNCTION__));
|
||
pEntry->bSound = FALSE;
|
||
Beamforming_DeInitEntry(pDM_Odm->Adapter, pEntry->MacAddr);
|
||
|
||
/*Modified by David - Every action of deleting entry should follow by Notify*/
|
||
phydm_Beamforming_Notify(pDM_Odm);
|
||
}
|
||
pEntry->bBeamformingInProgress = FALSE;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: Status=%d\n", __FUNCTION__, Status));
|
||
}
|
||
|
||
|
||
VOID
|
||
phydm_Beamforming_End_FW(
|
||
IN PVOID pDM_VOID
|
||
)
|
||
{
|
||
u1Byte Idx = 0;
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
PADAPTER Adapter = pDM_Odm->Adapter;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start! \n", __FUNCTION__) );
|
||
HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_FW_NDPA, (pu1Byte)&Idx);
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s End! \n", __FUNCTION__));
|
||
}
|
||
|
||
|
||
VOID
|
||
Beamforming_TimerCallback(
|
||
PADAPTER Adapter
|
||
)
|
||
{
|
||
BOOLEAN ret = FALSE;
|
||
PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
|
||
PRT_BEAMFORMING_INFO pBeamInfo = GET_BEAMFORM_INFO(Adapter);
|
||
PRT_BEAMFORMING_ENTRY pEntry = &(pBeamInfo->BeamformeeEntry[pBeamInfo->BeamformeeCurIdx]);
|
||
PRT_SOUNDING_INFO pSoundInfo = &(pBeamInfo->SoundingInfo);
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
if(pEntry->bBeamformingInProgress)
|
||
{
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("bBeamformingInProgress, reset it\n"));
|
||
phydm_Beamforming_End_SW(pDM_Odm, 0);
|
||
}
|
||
|
||
ret = phydm_Beamforming_SelectBeamEntry(pDM_Odm, pBeamInfo);
|
||
|
||
if(ret)
|
||
ret = BeamformingStart_SW(Adapter,pSoundInfo->SoundIdx, pSoundInfo->SoundMode, pSoundInfo->SoundBW);
|
||
|
||
if(ret)
|
||
;
|
||
else
|
||
{
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, Error value return from BeamformingStart_V2 \n", __FUNCTION__));
|
||
}
|
||
|
||
if(pBeamInfo->BeamformState >= BEAMFORMING_STATE_START_1BFee)
|
||
{
|
||
if(pSoundInfo->SoundMode == SOUNDING_SW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_SW_HT_TIMER)
|
||
ODM_SetTimer(pDM_Odm, &pBeamInfo->BeamformingTimer, pSoundInfo->SoundPeriod);
|
||
else
|
||
{
|
||
u4Byte val = (pSoundInfo->SoundPeriod << 16) | HAL_TIMER_TXBF;
|
||
Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_RESTART, (pu1Byte)(&val));
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
Beamforming_SWTimerCallback(
|
||
PRT_TIMER pTimer
|
||
)
|
||
{
|
||
PADAPTER Adapter=(PADAPTER)pTimer->Adapter;
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
|
||
|
||
Beamforming_TimerCallback(Adapter);
|
||
}
|
||
|
||
|
||
VOID
|
||
phydm_Beamforming_Init(
|
||
IN PVOID pDM_VOID
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
PHAL_TXBF_INFO pTxbfInfo = &pBeamInfo->TxbfInfo;
|
||
PRT_BEAMFORMING_OID_INFO pBeamOidInfo = &(pBeamInfo->BeamformingOidInfo);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
pBeamOidInfo->SoundOidMode = SOUNDING_STOP_OID_TIMER;
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("%s Mode (%d)\n", __FUNCTION__, pBeamOidInfo->SoundOidMode));
|
||
}
|
||
|
||
|
||
VOID
|
||
Beamforming_Enter(
|
||
PADAPTER Adapter,
|
||
PRT_WLAN_STA pSTA
|
||
)
|
||
{
|
||
u1Byte BFerBFeeIdx = 0xff;
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start! \n", __FUNCTION__) );
|
||
|
||
if(Beamforming_InitEntry(Adapter, pSTA, &BFerBFeeIdx))
|
||
HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_ENTER, (pu1Byte)&BFerBFeeIdx);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End! \n", __FUNCTION__) );
|
||
}
|
||
|
||
|
||
VOID
|
||
Beamforming_Leave(
|
||
PADAPTER Adapter,
|
||
pu1Byte RA
|
||
)
|
||
{
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s Start! \n", __FUNCTION__) );
|
||
|
||
if(RA == NULL)
|
||
Beamforming_Reset(Adapter);
|
||
else
|
||
Beamforming_DeInitEntry(Adapter, RA);
|
||
|
||
phydm_Beamforming_Notify(pDM_Odm);
|
||
|
||
RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End!! \n", __FUNCTION__));
|
||
}
|
||
|
||
//Nobody calls this function
|
||
VOID
|
||
phydm_Beamforming_SetTxBFen(
|
||
IN PVOID pDM_VOID,
|
||
u1Byte MacId,
|
||
BOOLEAN bTxBF
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
u1Byte Idx = 0;
|
||
PRT_BEAMFORMING_ENTRY pEntry;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
pEntry = phydm_Beamforming_GetEntryByMacId(pDM_Odm, MacId, &Idx);
|
||
|
||
if(pEntry == NULL)
|
||
return;
|
||
else
|
||
pEntry->bTxBF = bTxBF;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s MacId %d TxBF %d\n", __FUNCTION__, pEntry->MacId, pEntry->bTxBF));
|
||
|
||
phydm_Beamforming_Notify(pDM_Odm);
|
||
}
|
||
|
||
|
||
BEAMFORMING_CAP
|
||
phydm_Beamforming_GetBeamCap(
|
||
IN PVOID pDM_VOID,
|
||
IN PRT_BEAMFORMING_INFO pBeamInfo
|
||
)
|
||
{
|
||
u1Byte i;
|
||
BOOLEAN bSelfBeamformer = FALSE;
|
||
BOOLEAN bSelfBeamformee = FALSE;
|
||
RT_BEAMFORMING_ENTRY BeamformeeEntry;
|
||
RT_BEAMFORMER_ENTRY BeamformerEntry;
|
||
BEAMFORMING_CAP BeamformCap = BEAMFORMING_CAP_NONE;
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[Beamforming]%s Start!\n", __FUNCTION__) );
|
||
|
||
/*
|
||
for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
|
||
{
|
||
BeamformEntry = pBeamInfo->BeamformeeEntry[i];
|
||
|
||
if(BeamformEntry.bUsed)
|
||
{
|
||
if( (BeamformEntry.BeamformEntryCap & BEAMFORMEE_CAP_VHT_SU) ||
|
||
(BeamformEntry.BeamformEntryCap & BEAMFORMEE_CAP_HT_EXPLICIT))
|
||
bSelfBeamformee = TRUE;
|
||
if( (BeamformEntry.BeamformEntryCap & BEAMFORMER_CAP_VHT_SU) ||
|
||
(BeamformEntry.BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT))
|
||
bSelfBeamformer = TRUE;
|
||
}
|
||
|
||
if(bSelfBeamformer && bSelfBeamformee)
|
||
i = BEAMFORMEE_ENTRY_NUM;
|
||
}
|
||
*/
|
||
|
||
for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
|
||
{
|
||
BeamformeeEntry = pBeamInfo->BeamformeeEntry[i];
|
||
|
||
if(BeamformeeEntry.bUsed)
|
||
{
|
||
bSelfBeamformer = TRUE;
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[Beamforming]%s: BFee entry %d bUsed=TRUE \n", __FUNCTION__, i));
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
for(i = 0; i < BEAMFORMER_ENTRY_NUM; i++)
|
||
{
|
||
BeamformerEntry = pBeamInfo->BeamformerEntry[i];
|
||
|
||
if(BeamformerEntry.bUsed)
|
||
{
|
||
bSelfBeamformee = TRUE;
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[Beamforming]%s: BFer entry %d bUsed=TRUE \n", __FUNCTION__, i));
|
||
break;
|
||
}
|
||
}
|
||
|
||
if(bSelfBeamformer)
|
||
BeamformCap = (BEAMFORMING_CAP)(BeamformCap | BEAMFORMER_CAP);
|
||
if(bSelfBeamformee)
|
||
BeamformCap = (BEAMFORMING_CAP)(BeamformCap | BEAMFORMEE_CAP);
|
||
|
||
return BeamformCap;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
BeamformingControl_V1(
|
||
PADAPTER Adapter,
|
||
pu1Byte RA,
|
||
u1Byte AID,
|
||
u1Byte Mode,
|
||
CHANNEL_WIDTH BW,
|
||
u1Byte Rate
|
||
)
|
||
{
|
||
BOOLEAN ret = TRUE;
|
||
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
|
||
PDM_ODM_T pDM_Odm = &pHalData->DM_OutSrc;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("AID (%d), Mode (%d), BW (%d)\n", AID, Mode, BW));
|
||
|
||
RT_DISP_ADDR(FBEAM, FBEAM_FUN, ("Addr = "), RA);
|
||
|
||
switch(Mode){
|
||
case 0:
|
||
ret = BeamformingStart_V1(Adapter, RA, 0, BW, Rate);
|
||
break;
|
||
case 1:
|
||
ret = BeamformingStart_V1(Adapter, RA, 1, BW, Rate);
|
||
break;
|
||
case 2:
|
||
phydm_Beamforming_NDPARate(pDM_Odm, BW, Rate);
|
||
ret = Beamforming_SendVHTNDPAPacket(Adapter,RA, AID, BW, NORMAL_QUEUE);
|
||
break;
|
||
case 3:
|
||
phydm_Beamforming_NDPARate(pDM_Odm, BW, Rate);
|
||
ret = Beamforming_SendHTNDPAPacket(Adapter, RA, BW, NORMAL_QUEUE);
|
||
break;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
//Only OID uses this function
|
||
BOOLEAN
|
||
phydm_BeamformingControl_V2(
|
||
IN PVOID pDM_VOID,
|
||
u1Byte Idx,
|
||
u1Byte Mode,
|
||
CHANNEL_WIDTH BW,
|
||
u2Byte Period
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
PRT_BEAMFORMING_OID_INFO pBeamOidInfo = &(pBeamInfo->BeamformingOidInfo);
|
||
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("Idx (%d), Mode (%d), BW (%d), Period (%d)\n", Idx, Mode, BW, Period));
|
||
|
||
pBeamOidInfo->SoundOidIdx = Idx;
|
||
pBeamOidInfo->SoundOidMode = (SOUNDING_MODE) Mode;
|
||
pBeamOidInfo->SoundOidBW = BW;
|
||
pBeamOidInfo->SoundOidPeriod = Period;
|
||
|
||
phydm_Beamforming_Notify(pDM_Odm);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
VOID
|
||
phydm_Beamforming_Watchdog(
|
||
IN PVOID pDM_VOID
|
||
)
|
||
{
|
||
PDM_ODM_T pDM_Odm = (PDM_ODM_T)pDM_VOID;
|
||
PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
|
||
PADAPTER Adapter = pDM_Odm->Adapter;
|
||
|
||
ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
|
||
|
||
if(pBeamInfo->BeamformState < BEAMFORMING_STATE_START_1BFee)
|
||
return;
|
||
|
||
Beamforming_DymPeriod(pDM_Odm,0);
|
||
phydm_Beamforming_DymNDPARate(pDM_Odm);
|
||
|
||
}
|
||
|
||
|
||
#endif
|