xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rtl8189es/hal/phydm/phydm_beamforming.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #include "mp_precomp.h"
3 #include "phydm_precomp.h"
4 
5 #if WPP_SOFTWARE_TRACE
6 #include "phydm_beamforming.tmh"
7 #endif
8 
9 #if (BEAMFORMING_SUPPORT == 1)
10 
11 u1Byte
Beamforming_GetHTNDPTxRate(IN PADAPTER Adapter,u1Byte CompSteeringNumofBFer)12 Beamforming_GetHTNDPTxRate(
13 	IN	PADAPTER	Adapter,
14 	u1Byte	CompSteeringNumofBFer
15 )
16 {
17 	u1Byte Nr_index = 0;
18 	u1Byte NDPTxRate;
19 	/*Find Nr*/
20 
21 	if(IS_HARDWARE_TYPE_8814A(Adapter))
22 		Nr_index = TxBF_Nr(halTxbf8814A_GetNtx(Adapter), CompSteeringNumofBFer);
23 	else
24 		Nr_index = TxBF_Nr(1, CompSteeringNumofBFer);
25 
26 	switch(Nr_index)
27 	{
28 		case 1:
29 		NDPTxRate = MGN_MCS8;
30 		break;
31 
32 		case 2:
33 		NDPTxRate = MGN_MCS16;
34 		break;
35 
36 		case 3:
37 		NDPTxRate = MGN_MCS24;
38 		break;
39 
40 		default:
41 		NDPTxRate = MGN_MCS8;
42 		break;
43 
44 	}
45 
46 return NDPTxRate;
47 
48 }
49 
50 u1Byte
Beamforming_GetVHTNDPTxRate(IN PADAPTER Adapter,u1Byte CompSteeringNumofBFer)51 Beamforming_GetVHTNDPTxRate(
52 	IN	PADAPTER	Adapter,
53 	u1Byte	CompSteeringNumofBFer
54 )
55 {
56 	u1Byte Nr_index = 0;
57 	u1Byte NDPTxRate;
58 	/*Find Nr*/
59 	if(IS_HARDWARE_TYPE_8814A(Adapter))
60 		Nr_index = TxBF_Nr(halTxbf8814A_GetNtx(Adapter), CompSteeringNumofBFer);
61 	else
62 		Nr_index = TxBF_Nr(1, CompSteeringNumofBFer);
63 
64 	switch(Nr_index)
65 	{
66 		case 1:
67 		NDPTxRate = MGN_VHT2SS_MCS0;
68 		break;
69 
70 		case 2:
71 		NDPTxRate = MGN_VHT3SS_MCS0;
72 		break;
73 
74 		case 3:
75 		NDPTxRate = MGN_VHT4SS_MCS0;
76 		break;
77 
78 		default:
79 		NDPTxRate = MGN_VHT2SS_MCS0;
80 		break;
81 
82 	}
83 
84 return NDPTxRate;
85 
86 }
87 
88 
89 PRT_BEAMFORMING_ENTRY
phydm_Beamforming_GetBFeeEntryByAddr(IN PVOID pDM_VOID,IN pu1Byte RA,OUT pu1Byte Idx)90 phydm_Beamforming_GetBFeeEntryByAddr(
91 	IN	PVOID		pDM_VOID,
92 	IN	pu1Byte		RA,
93 	OUT	pu1Byte		Idx
94 	)
95 {
96 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
97 	u1Byte	i = 0;
98 	PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
99 
100 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s ===>\n", __FUNCTION__));
101 
102 	for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
103 	{
104 		if(	pBeamInfo->BeamformeeEntry[i].bUsed &&
105 			(eqMacAddr(RA,pBeamInfo->BeamformeeEntry[i].MacAddr) ))
106 		{
107 			*Idx = i;
108 			return &(pBeamInfo->BeamformeeEntry[i]);
109 		}
110 	}
111 
112 	return NULL;
113 }
114 
115 PRT_BEAMFORMER_ENTRY
phydm_Beamforming_GetBFerEntryByAddr(IN PVOID pDM_VOID,IN pu1Byte TA,OUT pu1Byte Idx)116 phydm_Beamforming_GetBFerEntryByAddr(
117 	IN	PVOID	pDM_VOID,
118 	IN	pu1Byte 	TA,
119 	OUT	pu1Byte		Idx
120 	)
121 {
122 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
123 	u1Byte	i = 0;
124 	PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
125 
126 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s ===>\n", __FUNCTION__));
127 
128 	for(i = 0; i < BEAMFORMER_ENTRY_NUM; i++)
129 	{
130 		if(	pBeamInfo->BeamformerEntry[i].bUsed &&
131 			(eqMacAddr(TA,pBeamInfo->BeamformerEntry[i].MacAddr) ))
132 		{
133 			*Idx = i;
134 			return &(pBeamInfo->BeamformerEntry[i]);
135 		}
136 	}
137 
138 	return NULL;
139 }
140 
141 
142 PRT_BEAMFORMING_ENTRY
phydm_Beamforming_GetEntryByMacId(IN PVOID pDM_VOID,IN u1Byte MacId,OUT pu1Byte Idx)143 phydm_Beamforming_GetEntryByMacId(
144 	IN	PVOID		pDM_VOID,
145 	IN	u1Byte		MacId,
146 	OUT	pu1Byte		Idx
147 	)
148 {
149 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
150 	u1Byte	i = 0;
151 	PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
152 
153 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s ===>\n", __FUNCTION__));
154 
155 	for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
156 	{
157 		if(	pBeamInfo->BeamformeeEntry[i].bUsed &&
158 			(MacId == pBeamInfo->BeamformeeEntry[i].MacId))
159 		{
160 			*Idx = i;
161 			return &(pBeamInfo->BeamformeeEntry[i]);
162 		}
163 	}
164 
165 	return NULL;
166 }
167 
168 
169 BEAMFORMING_CAP
phydm_Beamforming_GetEntryBeamCapByMacId(IN PVOID pDM_VOID,IN u1Byte MacId)170 phydm_Beamforming_GetEntryBeamCapByMacId(
171 	IN	PVOID		pDM_VOID,
172 	IN	u1Byte		MacId
173 	)
174 {
175 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
176 	u1Byte	i = 0;
177 	PRT_BEAMFORMING_INFO	pBeamInfo = &pDM_Odm->BeamformingInfo;
178 	BEAMFORMING_CAP			BeamformEntryCap = BEAMFORMING_CAP_NONE;
179 
180 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s ===>\n", __FUNCTION__));
181 
182 	for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
183 	{
184 		if(	pBeamInfo->BeamformeeEntry[i].bUsed &&
185 			(MacId == pBeamInfo->BeamformeeEntry[i].MacId))
186 		{
187 			BeamformEntryCap =  pBeamInfo->BeamformeeEntry[i].BeamformEntryCap;
188 			i = BEAMFORMEE_ENTRY_NUM;
189 		}
190 	}
191 
192 	return BeamformEntryCap;
193 }
194 
195 
196 PRT_BEAMFORMING_ENTRY
phydm_Beamforming_GetFreeBFeeEntry(IN PVOID pDM_VOID,OUT pu1Byte Idx)197 phydm_Beamforming_GetFreeBFeeEntry(
198 	IN	PVOID		pDM_VOID,
199 	OUT	pu1Byte		Idx
200 	)
201 {
202 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
203 	u1Byte	i = 0;
204 	PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
205 
206 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s ===>\n", __FUNCTION__));
207 
208 	for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
209 	{
210 		if(pBeamInfo->BeamformeeEntry[i].bUsed == FALSE)
211 		{
212 			*Idx = i;
213 			return &(pBeamInfo->BeamformeeEntry[i]);
214 		}
215 	}
216 	return NULL;
217 }
218 
219 PRT_BEAMFORMER_ENTRY
phydm_Beamforming_GetFreeBFerEntry(IN PVOID pDM_VOID,OUT pu1Byte Idx)220 phydm_Beamforming_GetFreeBFerEntry(
221 	IN	PVOID		pDM_VOID,
222 	OUT	pu1Byte		Idx
223 	)
224 {
225 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
226 	u1Byte	i = 0;
227 	PRT_BEAMFORMING_INFO pBeamInfo = &pDM_Odm->BeamformingInfo;
228 
229 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s ===>\n", __FUNCTION__));
230 
231 	for(i = 0; i < BEAMFORMER_ENTRY_NUM; i++)
232 	{
233 		if(pBeamInfo->BeamformerEntry[i].bUsed == FALSE)
234 		{
235 			*Idx = i;
236 			return &(pBeamInfo->BeamformerEntry[i]);
237 		}
238 	}
239 	return NULL;
240 }
241 
242 
243 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)244 Beamforming_AddBFeeEntry(
245 	IN	PADAPTER			Adapter,
246 	IN	pu1Byte				RA,
247 	IN	u2Byte				AID,
248 	IN	u2Byte				MacID,
249 	IN	CHANNEL_WIDTH		BW,
250 	IN	BEAMFORMING_CAP	BeamformCap,
251 	IN	u1Byte				NumofSoundingDim,
252 	IN	u1Byte				CompSteeringNumofBFer,
253 	OUT	pu1Byte				Idx
254 	)
255 {
256 	HAL_DATA_TYPE			*pHalData = GET_HAL_DATA(Adapter);
257 	PDM_ODM_T				pDM_Odm = &pHalData->DM_OutSrc;
258 	PMGNT_INFO				pMgntInfo = &(Adapter->MgntInfo);
259 	PRT_BEAMFORMING_ENTRY	pEntry = phydm_Beamforming_GetFreeBFeeEntry(pDM_Odm, Idx);
260 
261 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__));
262 
263 	if(pEntry != NULL)
264 	{
265 		pEntry->bUsed = TRUE;
266 		pEntry->AID = AID;
267 		pEntry->MacId = MacID;
268 		pEntry->SoundBW = BW;
269 		if(ACTING_AS_AP(Adapter))
270 		{
271 			u2Byte BSSID = ((Adapter->CurrentAddress[5] & 0xf0) >> 4) ^
272 							(Adapter->CurrentAddress[5] & 0xf);	// BSSID[44:47] xor BSSID[40:43]
273 			pEntry->P_AID = (AID + BSSID * 32) & 0x1ff;		// (dec(A) + dec(B)*32) mod 512
274 			ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: BFee P_AID addressed to STA=%d\n", __FUNCTION__,pEntry->P_AID));
275 		}
276 		else if(ACTING_AS_IBSS(Adapter))	// Ad hoc mode
277 		{
278 			pEntry->P_AID = 0;
279 			ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: BFee P_AID as IBSS=%d\n", __FUNCTION__,pEntry->P_AID));
280 		}
281 		else	// client mode
282 		{
283 			pEntry->P_AID =  RA[5];						// BSSID[39:47]
284 			pEntry->P_AID = (pEntry->P_AID << 1) | (RA[4] >> 7 );
285 			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));
286 		}
287 		cpMacAddr(pEntry->MacAddr, RA);
288 		pEntry->bTxBF = FALSE;
289 		pEntry->bSound = FALSE;
290 
291 		//3 TODO SW/FW sound period
292 		pEntry->SoundPeriod = 400;
293 		pEntry->BeamformEntryCap = BeamformCap;
294 		pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
295 
296 /*		pEntry->LogSeq = 0xff;				// Move to Beamforming_AddBFerEntry*/
297 /*		pEntry->LogRetryCnt = 0;			// Move to Beamforming_AddBFerEntry*/
298 /*		pEntry->LogSuccessCnt = 0;		// Move to Beamforming_AddBFerEntry*/
299 
300 		pEntry->LogStatusFailCnt = 0;
301 
302 		pEntry->NumofSoundingDim = NumofSoundingDim;
303 		pEntry->CompSteeringNumofBFer = CompSteeringNumofBFer;
304 
305 		return pEntry;
306 	}
307 	else
308 		return NULL;
309 }
310 
311 PRT_BEAMFORMER_ENTRY
Beamforming_AddBFerEntry(IN PADAPTER Adapter,IN pu1Byte RA,IN u2Byte AID,IN BEAMFORMING_CAP BeamformCap,IN u1Byte NumofSoundingDim,OUT pu1Byte Idx)312 Beamforming_AddBFerEntry(
313 	IN	PADAPTER			Adapter,
314 	IN	pu1Byte				RA,
315 	IN	u2Byte				AID,
316 	IN	BEAMFORMING_CAP	BeamformCap,
317 	IN	u1Byte				NumofSoundingDim,
318 	OUT	pu1Byte				Idx
319 	)
320 {
321 	HAL_DATA_TYPE			*pHalData = GET_HAL_DATA(Adapter);
322 	PDM_ODM_T				pDM_Odm = &pHalData->DM_OutSrc;
323 	PMGNT_INFO				pMgntInfo = &(Adapter->MgntInfo);
324 	PRT_BEAMFORMER_ENTRY	pEntry = phydm_Beamforming_GetFreeBFerEntry(pDM_Odm, Idx);
325 
326 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__));
327 
328 	if(pEntry != NULL)
329 	{
330 		pEntry->bUsed = TRUE;
331 		if(ACTING_AS_AP(Adapter))
332 		{
333 			u2Byte BSSID = ((Adapter->CurrentAddress[5] & 0xf0) >> 4) ^
334 							(Adapter->CurrentAddress[5] & 0xf);	// BSSID[44:47] xor BSSID[40:43]
335 			pEntry->P_AID = (AID + BSSID * 32) & 0x1ff;		// (dec(A) + dec(B)*32) mod 512
336 		}
337 		else if(ACTING_AS_IBSS(Adapter))
338 		{
339 			pEntry->P_AID = 0;
340 		}
341 		else
342 		{
343 			pEntry->P_AID =  RA[5];						// BSSID[39:47]
344 			pEntry->P_AID = (pEntry->P_AID << 1) | (RA[4] >> 7 );
345 		}
346 
347 		cpMacAddr(pEntry->MacAddr, RA);
348 		pEntry->BeamformEntryCap = BeamformCap;
349 
350 		pEntry->LogSeq = 0xff;			// Modified by Jeffery @2014-10-29
351 		pEntry->LogRetryCnt = 0;		// Modified by Jeffery @2014-10-29
352 		pEntry->LogSuccessCnt = 0;		// Modified by Jeffery @2014-10-29
353 
354 		pEntry->NumofSoundingDim = NumofSoundingDim;
355 
356 		return pEntry;
357 	}
358 	else
359 		return NULL;
360 }
361 
362 
363 BOOLEAN
Beamforming_RemoveEntry(IN PADAPTER Adapter,IN pu1Byte RA,OUT pu1Byte Idx)364 Beamforming_RemoveEntry(
365 	IN	PADAPTER			Adapter,
366 	IN	pu1Byte		RA,
367 	OUT	pu1Byte		Idx
368 	)
369 {
370 	HAL_DATA_TYPE			*pHalData = GET_HAL_DATA(Adapter);
371 	PDM_ODM_T				pDM_Odm = &pHalData->DM_OutSrc;
372 
373 	PRT_BEAMFORMER_ENTRY	pBFerEntry = phydm_Beamforming_GetBFerEntryByAddr(pDM_Odm, RA, Idx);
374 	PRT_BEAMFORMING_ENTRY	pEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, Idx);
375 	BOOLEAN ret = FALSE;
376 
377 	RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s Start!\n", __FUNCTION__) );
378     RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s, pBFerEntry=0x%x \n", __FUNCTION__,pBFerEntry) );
379     RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s, pEntry=0x%x \n", __FUNCTION__,pEntry) );
380 
381 	if (pEntry != NULL) {
382 		pEntry->bUsed = FALSE;
383 		pEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE;
384 		/*pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;*/
385 		pEntry->bBeamformingInProgress = FALSE;
386 		ret = TRUE;
387 	}
388 	if (pBFerEntry != NULL) {
389 		pBFerEntry->bUsed = FALSE;
390 		pBFerEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE;
391 		ret = TRUE;
392 	}
393 	return ret;
394 
395 }
396 
397 /* Used for BeamformingStart_V1  */
398 VOID
phydm_Beamforming_NDPARate(IN PVOID pDM_VOID,CHANNEL_WIDTH BW,u1Byte Rate)399 phydm_Beamforming_NDPARate(
400 	IN	PVOID		pDM_VOID,
401 	CHANNEL_WIDTH 	BW,
402 	u1Byte			Rate
403 )
404 {
405 	u2Byte			NDPARate = Rate;
406 	PDM_ODM_T		pDM_Odm = (PDM_ODM_T)pDM_VOID;
407 
408 
409 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
410 
411 	if(NDPARate == 0)
412 	{
413 		if(pDM_Odm->RSSI_Min > 30) // link RSSI > 30%
414 			NDPARate = ODM_RATE24M;
415 		else
416 			NDPARate = ODM_RATE6M;
417 	}
418 
419 	if(NDPARate < ODM_RATEMCS0)
420 		BW = (CHANNEL_WIDTH)ODM_BW20M;
421 
422 	NDPARate = (NDPARate << 8) | BW;
423 	HalComTxbf_Set(pDM_Odm->Adapter, TXBF_SET_SOUNDING_RATE, (pu1Byte)&NDPARate);
424 
425 }
426 
427 
428 /* Used for BeamformingStart_SW and  BeamformingStart_FW */
429 VOID
phydm_Beamforming_DymNDPARate(IN PVOID pDM_VOID)430 phydm_Beamforming_DymNDPARate(
431 	IN	PVOID		pDM_VOID
432 )
433 {
434 	u2Byte			NDPARate = ODM_RATE6M, BW;
435 	PDM_ODM_T		pDM_Odm = (PDM_ODM_T)pDM_VOID;
436 
437 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
438 
439 	if(pDM_Odm->RSSI_Min > 30) // link RSSI > 30%
440 		NDPARate = ODM_RATE24M;
441 	else
442 		NDPARate = ODM_RATE6M;
443 
444 	BW = ODM_BW20M;
445 	NDPARate = NDPARate << 8 | BW;
446 	HalComTxbf_Set(pDM_Odm->Adapter, TXBF_SET_SOUNDING_RATE, (pu1Byte)&NDPARate);
447 
448 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s End, NDPA Rate = 0x%X \n", __FUNCTION__, NDPARate));
449 }
450 
451 /*
452 *	SW Sounding : SW Timer unit 1ms
453 *				 HW Timer unit (1/32000) s  32k is clock.
454 *	FW Sounding : FW Timer unit 10ms
455 */
456 VOID
Beamforming_DymPeriod(IN PVOID pDM_VOID,IN u8 status)457 Beamforming_DymPeriod(
458 	IN	PVOID		pDM_VOID,
459 	IN  u8          status
460 )
461 {
462 	u1Byte 					Idx;
463 	BOOLEAN					bChangePeriod = FALSE;
464 	u2Byte					SoundPeriod_SW, SoundPeriod_FW;
465 	PDM_ODM_T				pDM_Odm = (PDM_ODM_T)pDM_VOID;
466 	PADAPTER				Adapter = pDM_Odm->Adapter;
467 	PHAL_DATA_TYPE			pHalData = GET_HAL_DATA(Adapter);
468 
469 	PRT_BEAMFORMING_ENTRY	pBeamformEntry;
470 	PRT_BEAMFORMING_INFO 	pBeamInfo = GET_BEAMFORM_INFO((Adapter));
471 	PRT_SOUNDING_INFO		pSoundInfo = &(pBeamInfo->SoundingInfo);
472 
473     PRT_BEAMFORMING_ENTRY   pEntry = &(pBeamInfo->BeamformeeEntry[pBeamInfo->BeamformeeCurIdx]);
474 
475 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
476 
477 	//3 TODO  per-client throughput caculation.
478 
479 	if ((Adapter->TxStats.CurrentTxTP + Adapter->RxStats.CurrentRxTP > 2)&&((pEntry->LogStatusFailCnt <= 20) || status)){
480 		//-@ Modified by David
481 		SoundPeriod_SW = 40;	/* 32*20? */
482 		SoundPeriod_FW = 40;	/* From  H2C cmd, unit = 10ms */
483 
484 		RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s, current TRX TP>2, SoundPeriod_SW=%d, SoundPeriod_FW=%d\n",
485 		__FUNCTION__,
486 		SoundPeriod_SW,
487 		SoundPeriod_FW) );
488 	} else{
489 		//-@ Modified by David
490 		SoundPeriod_SW = 4000;/* 32*2000? */
491 		SoundPeriod_FW = 400;
492 
493 		RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s, current TRX TP<2, SoundPeriod_SW=%d, SoundPeriod_FW=%d\n",
494 		__FUNCTION__,
495 		SoundPeriod_SW,
496 		SoundPeriod_FW) );
497 	}
498 
499 	for(Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++)
500 	{
501 		pBeamformEntry = pBeamInfo->BeamformeeEntry+Idx;
502 
503 		if(pBeamformEntry->DefaultCSICnt > 20)
504 		{
505 			//-@ Modified by David
506 			SoundPeriod_SW = 4000;
507 			SoundPeriod_FW = 400;
508 		}
509 
510 		RT_DISP(FBEAM, FBEAM_FUN, ("@%s Period = %d\n", __FUNCTION__, SoundPeriod_SW));
511 		if(pBeamformEntry->BeamformEntryCap & (BEAMFORMER_CAP_HT_EXPLICIT |BEAMFORMER_CAP_VHT_SU))
512 		{
513 			if(pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER)
514 			{
515 				if(pBeamformEntry->SoundPeriod != SoundPeriod_FW)
516 				{
517 					pBeamformEntry->SoundPeriod = SoundPeriod_FW;
518 					bChangePeriod = TRUE;	// Only FW sounding need to send H2C packet to change sound period.
519 				}
520 			}
521 			else if(pBeamformEntry->SoundPeriod != SoundPeriod_SW)
522 			{
523 				pBeamformEntry->SoundPeriod = SoundPeriod_SW;
524 			}
525 		}
526 	}
527 
528 	if(bChangePeriod)
529 		HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_FW_NDPA, (pu1Byte)&Idx);
530 }
531 
532 
533 VOID
Beamforming_GidPAid(PADAPTER Adapter,PRT_TCB pTcb)534 Beamforming_GidPAid(
535 	PADAPTER	Adapter,
536 	PRT_TCB		pTcb
537 )
538 {
539 	u1Byte		Idx = 0;
540 	u1Byte		RA[6] ={0};
541 	PMGNT_INFO	pMgntInfo = &(Adapter->MgntInfo);
542 	pu1Byte		pHeader = GET_FRAME_OF_FIRST_FRAG(Adapter, pTcb);
543 
544 	if(Adapter->HardwareType < HARDWARE_TYPE_RTL8192EE)
545 		return;
546 	else if(IS_WIRELESS_MODE_N(Adapter) == FALSE)
547 		return;
548 
549 	GET_80211_HDR_ADDRESS1(pHeader, &RA);
550 
551 	// VHT SU PPDU carrying one or more group addressed MPDUs or
552 	// Transmitting a VHT NDP intended for multiple recipients
553 	if(	MacAddr_isBcst(RA) || MacAddr_isMulticast(RA)	||
554 		pTcb->macId == MAC_ID_STATIC_FOR_BROADCAST_MULTICAST)
555 	{
556 		pTcb->G_ID = 63;
557 		pTcb->P_AID = 0;
558 	}
559 	else if(ACTING_AS_AP(Adapter))
560 	{
561 		u2Byte	AID = (u2Byte) (MacIdGetOwnerAssociatedClientAID(Adapter, pTcb->macId) & 0x1ff); 		//AID[0:8]
562 
563 		pTcb->G_ID = 63;
564 
565 		if(AID == 0)	//A PPDU sent by an AP to a non associated STA
566 			pTcb->P_AID = 0;
567 		else
568 		{			//Sent by an AP and addressed to a STA associated with that AP
569 			u2Byte	BSSID = 0;
570 			GET_80211_HDR_ADDRESS2(pHeader, &RA);
571 			BSSID = ((RA[5] & 0xf0) >> 4) ^ (RA[5] & 0xf);	// BSSID[44:47] xor BSSID[40:43]
572 			pTcb->P_AID = (AID + BSSID * 32) & 0x1ff;		// (dec(A) + dec(B)*32) mod 512
573 		}
574 	}
575 	else if(ACTING_AS_IBSS(Adapter))
576 	{
577 		pTcb->G_ID = 63;
578 		// P_AID for infrasturcture mode; MACID for ad-hoc mode.
579 		pTcb->P_AID = pTcb->macId;
580 	}
581 	else if(MgntLinkStatusQuery(Adapter))
582 	{	// Addressed to AP
583 		pTcb->G_ID = 0;
584 		GET_80211_HDR_ADDRESS1(pHeader, &RA);
585 		pTcb->P_AID =  RA[5];						// RA[39:47]
586 		pTcb->P_AID = (pTcb->P_AID << 1) | (RA[4] >> 7 );
587 	}
588 	else
589 	{
590 		pTcb->G_ID = 63;
591 		pTcb->P_AID = 0;
592 	}
593 
594 	//RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End, G_ID=0x%X, P_AID=0x%X \n", __FUNCTION__, pTcb->G_ID, pTcb->P_AID) );
595 
596 }
597 
598 
599 RT_STATUS
Beamforming_GetReportFrame(IN PADAPTER Adapter,IN PRT_RFD pRfd,IN POCTET_STRING pPduOS)600 Beamforming_GetReportFrame(
601 	IN	PADAPTER		Adapter,
602 	IN	PRT_RFD			pRfd,
603 	IN	POCTET_STRING	pPduOS
604 	)
605 {
606 	HAL_DATA_TYPE				*pHalData = GET_HAL_DATA(Adapter);
607 	PDM_ODM_T					pDM_Odm = &pHalData->DM_OutSrc;
608 	PRT_BEAMFORMING_ENTRY		pBeamformEntry = NULL;
609 	PMGNT_INFO					pMgntInfo = &(Adapter->MgntInfo);
610 	pu1Byte						pMIMOCtrlField, pCSIReport, pCSIMatrix;
611 	u1Byte						Idx, Nc, Nr, CH_W;
612 	u2Byte						CSIMatrixLen = 0;
613 
614 	ACT_PKT_TYPE				pktType = ACT_PKT_TYPE_UNKNOWN;
615 
616 	//Memory comparison to see if CSI report is the same with previous one
617 	pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, Frame_Addr2(*pPduOS), &Idx);
618 
619 	if( pBeamformEntry == NULL )
620 	{
621 		RT_DISP(FBEAM, FBEAM_DATA, ("Beamforming_GetReportFrame: Cannot find entry by addr\n"));
622 		return RT_STATUS_FAILURE;
623 	}
624 
625 	pktType = PacketGetActionFrameType(pPduOS);
626 
627 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
628 
629 	//-@ Modified by David
630 	if(pktType == ACT_PKT_VHT_COMPRESSED_BEAMFORMING)
631 	{
632 		pMIMOCtrlField = pPduOS->Octet + 26;
633 		Nc = ((*pMIMOCtrlField) & 0x7) + 1;
634 		Nr = (((*pMIMOCtrlField) & 0x38) >> 3) + 1;
635 		CH_W =  (((*pMIMOCtrlField) & 0xC0) >> 6);
636 		pCSIMatrix = pMIMOCtrlField + 3 + Nc; //24+(1+1+3)+2  MAC header+(Category+ActionCode+MIMOControlField) +SNR(Nc=2)
637 		CSIMatrixLen = pPduOS->Length  - 26 -3 -Nc;
638 	}
639 	else if(pktType == ACT_PKT_HT_COMPRESSED_BEAMFORMING)
640 	{
641 		pMIMOCtrlField = pPduOS->Octet + 26;
642 		Nc = ((*pMIMOCtrlField) & 0x3) + 1;
643 		Nr =  (((*pMIMOCtrlField) & 0xC) >> 2) + 1;
644 		CH_W =  (((*pMIMOCtrlField) & 0x10) >> 4);
645 		pCSIMatrix = pMIMOCtrlField + 6 + Nr;	//24+(1+1+6)+2  MAC header+(Category+ActionCode+MIMOControlField) +SNR(Nc=2)
646 		CSIMatrixLen = pPduOS->Length  - 26 -6 -Nr;
647 	}
648 	else
649 		return RT_STATUS_SUCCESS;
650 
651 	if(pktType == ACT_PKT_VHT_COMPRESSED_BEAMFORMING)
652 	{
653 		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));
654 	}
655 	else if(pktType == ACT_PKT_HT_COMPRESSED_BEAMFORMING)
656 	{
657 		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));
658 	}
659 
660 
661 //	RT_DISP_DATA(FBEAM, FBEAM_DATA, "Beamforming_GetReportFrame \n", pMIMOCtrlField, pPduOS->Length - 26);
662 
663 	//-@ Modified by David - CSI buffer is not big enough, and comparison would result in blue screen
664 	/*
665 	if(pBeamformEntry->CSIMatrixLen != CSIMatrixLen)
666 		pBeamformEntry->DefaultCSICnt = 0;
667 	else if(PlatformCompareMemory(pBeamformEntry->CSIMatrix, pCSIMatrix, CSIMatrixLen))
668 	{
669 		pBeamformEntry->DefaultCSICnt = 0;
670 		RT_DISP(FBEAM, FBEAM_FUN, ("%s CSI report is NOT the same with previos one\n", __FUNCTION__));
671 	}
672 	else	if(pBeamformEntry->DefaultCSICnt <= 20)
673 	{
674 		pBeamformEntry->DefaultCSICnt ++;
675 		RT_DISP(FBEAM, FBEAM_FUN, ("%s CSI report is the SAME with previos one\n", __FUNCTION__));
676 	}
677 
678 	pBeamformEntry->CSIMatrixLen = CSIMatrixLen;
679 	PlatformMoveMemory(&pBeamformEntry->CSIMatrix, pCSIMatrix, CSIMatrixLen);
680 	*/
681 
682 	return RT_STATUS_SUCCESS;
683 }
684 
685 
686 VOID
Beamforming_GetNDPAFrame(IN PADAPTER Adapter,IN OCTET_STRING pduOS)687 Beamforming_GetNDPAFrame(
688 	IN	PADAPTER		Adapter,
689 	IN	OCTET_STRING	pduOS
690 )
691 {
692 	pu1Byte						TA ;
693 	u1Byte						Idx, Sequence;
694 	pu1Byte						pNDPAFrame = pduOS.Octet;
695 	PMGNT_INFO				pMgntInfo = &(Adapter->MgntInfo);
696 //	PRT_BEAMFORMING_ENTRY		pBeamformEntry = NULL;
697 	PRT_BEAMFORMER_ENTRY		pBeamformerEntry = NULL;		// Modified By Jeffery @2014-10-29
698 	HAL_DATA_TYPE				*pHalData = GET_HAL_DATA(Adapter);
699 	PDM_ODM_T					pDM_Odm = &pHalData->DM_OutSrc;
700 
701 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
702 	RT_DISP_DATA(FBEAM, FBEAM_DATA, "Beamforming_GetNDPAFrame\n", pduOS.Octet, pduOS.Length);
703 
704 	if(IsCtrlNDPA(pNDPAFrame) == FALSE){
705         RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s IsCtrlNDPA(pNDPAFrame) == FALSE\n", __FUNCTION__) );
706 		return;
707 
708     }
709 
710     else if( (IS_HARDWARE_TYPE_8812(Adapter) == FALSE)&&(IS_HARDWARE_TYPE_8821(Adapter) == FALSE) )
711     {
712         RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s IsCtrlNDPA(pNDPAFrame) == FALSE\n", __FUNCTION__) );
713 		return;
714     }
715 
716 	TA = Frame_Addr2(pduOS);
717 	// Remove signaling TA.
718 	TA[0] = TA[0] & 0xFE;
719 
720 //	pBeamformEntry = Beamforming_GetBFeeEntryByAddr(Adapter, TA, &Idx);
721 	pBeamformerEntry = phydm_Beamforming_GetBFerEntryByAddr(pDM_Odm, TA, &Idx);		// Modified By Jeffery @2014-10-29
722 
723         RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s After phydm_Beamforming_GetBFerEntryByAddr,pBeamformerEntry=0x%x\n", __FUNCTION__,pBeamformerEntry) );
724 
725 	if(pBeamformerEntry == NULL)
726 		return;
727 	else if(!(pBeamformerEntry->BeamformEntryCap & BEAMFORMEE_CAP_VHT_SU))
728 		return;
729 //	else if(pBeamformerEntry->LogSuccessCnt > 1)			//�Ȯɲ���,�קK�û��d���b�o�Ӫ��A
730 //		return;
731 
732 /*
733 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s begin, LogSeq=%d, LogRetryCnt=%d, LogSuccessCnt=%d\n",
734 	__FUNCTION__,
735 	pBeamformerEntry->LogSeq,
736 	pBeamformerEntry->LogRetryCnt,
737 	pBeamformerEntry->LogSuccessCnt) );
738 */
739 
740 	Sequence = (pNDPAFrame[16]) >> 2;
741 
742 
743 	if(pBeamformerEntry->LogSeq != Sequence){
744 		/* Previous frame doesn't retry when meet new sequence number */
745 		if(pBeamformerEntry->LogSeq != 0xff && pBeamformerEntry->LogRetryCnt == 0)
746 			pBeamformerEntry->LogSuccessCnt++;
747 
748 		pBeamformerEntry->LogSeq = Sequence;
749         pBeamformerEntry->PreLogSeq = pBeamformerEntry->LogSeq;
750 
751         /* break option for clcok reset, 2015-03-30, Jeffery */
752         if ((pBeamformerEntry->LogSeq != Sequence) && (pBeamformerEntry->PreLogSeq != pBeamformerEntry->LogSeq))
753 		pBeamformerEntry->LogRetryCnt = 0;
754 	} else { /* pBeamformerEntry->LogSeq == Sequence */
755         pBeamformerEntry->PreLogSeq = pBeamformerEntry->LogSeq;
756 
757         if (pBeamformerEntry->LogRetryCnt == 3){
758             RT_DISP(FBEAM, FBEAM_FUN, ("[Jeffery]@%s begin, Clock Reset!!!,PreLogSeq=%d, LogSeq=%d, LogRetryCnt=%d, LogSuccessCnt=%d\n",
759             __FUNCTION__,
760             pBeamformerEntry->PreLogSeq,
761             pBeamformerEntry->LogSeq,
762             pBeamformerEntry->LogRetryCnt));
763             pBeamformerEntry->LogRetryCnt = 0;
764             HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_CLK, NULL);
765 	}
766 	else
767             pBeamformerEntry->LogRetryCnt++;
768     }
769 
770 
771 
772 /*
773 	else
774 	{
775 		if(pBeamformerEntry->LogRetryCnt == 3)
776 			HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_CLK, NULL);
777 		else if(pBeamformerEntry->LogRetryCnt <= 3)
778 			pBeamformerEntry->LogRetryCnt++;
779 	}
780 */
781 
782 
783 /*	RT_DISP(FBEAM, FBEAM_FUN, ("%s End, LogSeq=%d, LogRetryCnt=%d, LogSuccessCnt=%d\n",
784 	__FUNCTION__,
785 	pBeamformerEntry->LogSeq,
786 	pBeamformerEntry->LogRetryCnt,
787 	pBeamformerEntry->LogSuccessCnt));*/
788 
789 }
790 
791 
792 VOID
ConstructHTNDPAPacket(PADAPTER Adapter,pu1Byte RA,pu1Byte Buffer,pu4Byte pLength,CHANNEL_WIDTH BW)793 ConstructHTNDPAPacket(
794 	PADAPTER		Adapter,
795 	pu1Byte			RA,
796 	pu1Byte			Buffer,
797 	pu4Byte			pLength,
798 	CHANNEL_WIDTH	BW
799 	)
800 {
801 	u2Byte					Duration= 0;
802 	PMGNT_INFO				pMgntInfo = &(Adapter->MgntInfo);
803 	PRT_HIGH_THROUGHPUT		pHTInfo = GET_HT_INFO(pMgntInfo);
804 	OCTET_STRING			pNDPAFrame,ActionContent;
805 	u1Byte					ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};
806 
807 	PlatformZeroMemory(Buffer, 32);
808 
809 	SET_80211_HDR_FRAME_CONTROL(Buffer,0);
810 
811 	SET_80211_HDR_ORDER(Buffer, 1);
812 	SET_80211_HDR_TYPE_AND_SUBTYPE(Buffer,Type_Action_No_Ack);
813 
814 	SET_80211_HDR_ADDRESS1(Buffer, RA);
815 	SET_80211_HDR_ADDRESS2(Buffer, Adapter->CurrentAddress);
816 	SET_80211_HDR_ADDRESS3(Buffer, pMgntInfo->Bssid);
817 
818 	Duration = 2*aSifsTime + 40;
819 
820 	if(BW== CHANNEL_WIDTH_40)
821 		Duration+= 87;
822 	else
823 		Duration+= 180;
824 
825 	SET_80211_HDR_DURATION(Buffer, Duration);
826 
827 	//HT control field
828 	SET_HT_CTRL_CSI_STEERING(Buffer+sMacHdrLng, 3);
829 	SET_HT_CTRL_NDP_ANNOUNCEMENT(Buffer+sMacHdrLng, 1);
830 
831 	FillOctetString(pNDPAFrame, Buffer, sMacHdrLng+sHTCLng);
832 
833 	FillOctetString(ActionContent, ActionHdr, 4);
834 	PacketAppendData(&pNDPAFrame, ActionContent);
835 
836 	*pLength = 32;
837 }
838 
839 
840 BOOLEAN
SendFWHTNDPAPacket(IN PADAPTER Adapter,IN pu1Byte RA,IN CHANNEL_WIDTH BW)841 SendFWHTNDPAPacket(
842 	IN	PADAPTER		Adapter,
843 	IN	pu1Byte			RA,
844 	IN	CHANNEL_WIDTH	BW
845 	)
846 {
847 	PRT_TCB 				pTcb;
848 	PRT_TX_LOCAL_BUFFER 	pBuf;
849 	BOOLEAN 				ret = TRUE;
850 	u4Byte					BufLen;
851 	pu1Byte					BufAddr;
852 	u1Byte					DescLen = 0, Idx = 0, NDPTxRate;
853 	PADAPTER				pDefAdapter = GetDefaultAdapter(Adapter);
854 	PRT_BEAMFORMING_INFO 	pBeamInfo = GET_BEAMFORM_INFO(Adapter);
855 	HAL_DATA_TYPE			*pHalData = GET_HAL_DATA(Adapter);
856 	PDM_ODM_T				pDM_Odm = &pHalData->DM_OutSrc;
857 	PRT_BEAMFORMING_ENTRY	pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);
858 
859 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
860 
861 	if(pBeamformEntry == NULL)
862 		return FALSE;
863 
864 	NDPTxRate = Beamforming_GetHTNDPTxRate(Adapter, pBeamformEntry->CompSteeringNumofBFer);
865 	RT_DISP(FBEAM, FBEAM_FUN, ("%s, NDPTxRate =%d\n", __FUNCTION__, NDPTxRate));
866 	PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
867 
868 	if(MgntGetFWBuffer(pDefAdapter, &pTcb, &pBuf))
869 	{
870 #if(DEV_BUS_TYPE != RT_PCI_INTERFACE)
871 		HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(Adapter);
872 
873 		DescLen = Adapter->HWDescHeadLength - pHalData->USBALLDummyLength;
874 #endif
875 		BufAddr = pBuf->Buffer.VirtualAddress + DescLen;
876 
877 		ConstructHTNDPAPacket(
878 				Adapter,
879 				RA,
880 				BufAddr,
881 				&BufLen,
882 				BW
883 				);
884 
885 		pTcb->PacketLength = BufLen + DescLen;
886 
887 		pTcb->bTxEnableSwCalcDur = TRUE;
888 
889 		pTcb->BWOfPacket = BW;
890 
891 		if(ACTING_AS_IBSS(Adapter) || ACTING_AS_AP(Adapter))
892 			pTcb->G_ID = 63;
893 
894 		pTcb->P_AID = pBeamformEntry->P_AID;
895 		pTcb->DataRate = NDPTxRate;	/*rate of NDP decide by Nr*/
896 
897 		Adapter->HalFunc.CmdSendPacketHandler(Adapter, pTcb, pBuf, pTcb->PacketLength, DESC_PACKET_TYPE_NORMAL, FALSE);
898 	}
899 	else
900 		ret = FALSE;
901 
902 	PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
903 
904 	if(ret)
905 		RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);
906 
907 	return ret;
908 }
909 
910 
911 BOOLEAN
SendSWHTNDPAPacket(IN PADAPTER Adapter,IN pu1Byte RA,IN CHANNEL_WIDTH BW)912 SendSWHTNDPAPacket(
913 	IN	PADAPTER		Adapter,
914 	IN	pu1Byte			RA,
915 	IN	CHANNEL_WIDTH	BW
916 	)
917 {
918 	PRT_TCB					pTcb;
919 	PRT_TX_LOCAL_BUFFER		pBuf;
920 	BOOLEAN					ret = TRUE;
921 	u1Byte					Idx = 0, NDPTxRate = 0;
922 	PRT_BEAMFORMING_INFO 	pBeamInfo = GET_BEAMFORM_INFO(Adapter);
923 	HAL_DATA_TYPE			*pHalData = GET_HAL_DATA(Adapter);
924 	PDM_ODM_T				pDM_Odm = &pHalData->DM_OutSrc;
925 	PRT_BEAMFORMING_ENTRY	pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);
926 
927 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
928 
929 	NDPTxRate = Beamforming_GetHTNDPTxRate(Adapter, pBeamformEntry->CompSteeringNumofBFer);
930 	RT_DISP(FBEAM, FBEAM_FUN, ("%s, NDPTxRate =%d\n", __FUNCTION__, NDPTxRate));
931 
932 	PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
933 
934 	if(MgntGetBuffer(Adapter, &pTcb, &pBuf))
935 	{
936 		ConstructHTNDPAPacket(
937 				Adapter,
938 				RA,
939 				pBuf->Buffer.VirtualAddress,
940 				&pTcb->PacketLength,
941 				BW
942 				);
943 
944 		pTcb->bTxEnableSwCalcDur = TRUE;
945 
946 		pTcb->BWOfPacket = BW;
947 
948 		MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, NDPTxRate);
949 	}
950 	else
951 		ret = FALSE;
952 
953 	PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
954 
955 	if(ret)
956 		RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);
957 
958 	return ret;
959 }
960 
961 
962 
963 
964 BOOLEAN
Beamforming_SendHTNDPAPacket(IN PADAPTER Adapter,IN pu1Byte RA,IN CHANNEL_WIDTH BW,IN u1Byte QIdx)965 Beamforming_SendHTNDPAPacket(
966 	IN	PADAPTER		Adapter,
967 	IN	pu1Byte			RA,
968 	IN	CHANNEL_WIDTH	BW,
969 	IN	u1Byte			QIdx
970 	)
971 {
972 	BOOLEAN		ret = TRUE;
973 
974 	if(QIdx == BEACON_QUEUE)
975 		ret = SendFWHTNDPAPacket(Adapter, RA, BW);
976 	else
977 		ret = SendSWHTNDPAPacket(Adapter, RA, BW);
978 
979 	return ret;
980 }
981 
982 
983 VOID
ConstructVHTNDPAPacket(PADAPTER Adapter,pu1Byte RA,u2Byte AID,pu1Byte Buffer,pu4Byte pLength,CHANNEL_WIDTH BW)984 ConstructVHTNDPAPacket(
985 	PADAPTER		Adapter,
986 	pu1Byte			RA,
987 	u2Byte			AID,
988 	pu1Byte			Buffer,
989 	pu4Byte			pLength,
990 	CHANNEL_WIDTH	BW
991 	)
992 {
993 	u2Byte					Duration= 0;
994 	u1Byte					Sequence = 0;
995 	pu1Byte					pNDPAFrame = Buffer;
996 	PMGNT_INFO				pMgntInfo = &(Adapter->MgntInfo);
997 	PRT_HIGH_THROUGHPUT		pHTInfo = GET_HT_INFO(pMgntInfo);
998 	RT_NDPA_STA_INFO		STAInfo;
999 
1000 	// Frame control.
1001 	SET_80211_HDR_FRAME_CONTROL(pNDPAFrame, 0);
1002 	SET_80211_HDR_TYPE_AND_SUBTYPE(pNDPAFrame, Type_NDPA);
1003 
1004 	SET_80211_HDR_ADDRESS1(pNDPAFrame, RA);
1005 	SET_80211_HDR_ADDRESS2(pNDPAFrame, Adapter->CurrentAddress);
1006 
1007 	Duration = 2*aSifsTime + 44;
1008 
1009 	if(BW == CHANNEL_WIDTH_80)
1010 		Duration += 40;
1011 	else if(BW == CHANNEL_WIDTH_40)
1012 		Duration+= 87;
1013 	else
1014 		Duration+= 180;
1015 
1016 	SET_80211_HDR_DURATION(pNDPAFrame, Duration);
1017 
1018 	Sequence = pMgntInfo->SoundingSequence << 2;
1019 	PlatformMoveMemory(pNDPAFrame+16, &Sequence,1);
1020 
1021 	if(	ACTING_AS_IBSS(Adapter) ||
1022 		(ACTING_AS_AP(Adapter) == FALSE))
1023 		AID = 0;
1024 
1025 	STAInfo.AID = AID;
1026 	STAInfo.FeedbackType = 0;
1027 	STAInfo.NcIndex = 0;
1028 
1029 	PlatformMoveMemory(pNDPAFrame+17, (pu1Byte)&STAInfo, 2);
1030 
1031 	*pLength = 19;
1032 }
1033 
1034 BOOLEAN
SendFWVHTNDPAPacket(IN PADAPTER Adapter,IN pu1Byte RA,IN u2Byte AID,IN CHANNEL_WIDTH BW)1035 SendFWVHTNDPAPacket(
1036 	IN	PADAPTER		Adapter,
1037 	IN	pu1Byte			RA,
1038 	IN	u2Byte			AID,
1039 	IN	CHANNEL_WIDTH	BW
1040 	)
1041 {
1042 	PRT_TCB					pTcb;
1043 	PRT_TX_LOCAL_BUFFER		pBuf;
1044 	BOOLEAN					ret = TRUE;
1045 	u4Byte					BufLen;
1046 	pu1Byte					BufAddr;
1047 	u1Byte					DescLen = 0, Idx = 0, NDPTxRate = 0;
1048 	PADAPTER				pDefAdapter = GetDefaultAdapter(Adapter);
1049 	PRT_BEAMFORMING_INFO 	pBeamInfo = GET_BEAMFORM_INFO(Adapter);
1050 	HAL_DATA_TYPE			*pHalData = GET_HAL_DATA(Adapter);
1051 	PDM_ODM_T				pDM_Odm = &pHalData->DM_OutSrc;
1052 	PRT_BEAMFORMING_ENTRY	pBeamformEntry =phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);
1053 
1054 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
1055 
1056 	if(pBeamformEntry == NULL)
1057 		return FALSE;
1058 
1059 	NDPTxRate = Beamforming_GetVHTNDPTxRate(Adapter, pBeamformEntry->CompSteeringNumofBFer);
1060 	RT_DISP(FBEAM, FBEAM_FUN, ("%s, NDPTxRate =%d\n", __FUNCTION__, NDPTxRate));
1061 
1062 	PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
1063 
1064 	if(MgntGetFWBuffer(pDefAdapter, &pTcb, &pBuf))
1065 	{
1066 #if(DEV_BUS_TYPE != RT_PCI_INTERFACE)
1067 		HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(Adapter);
1068 
1069 		DescLen = Adapter->HWDescHeadLength - pHalData->USBALLDummyLength;
1070 #endif
1071 		BufAddr = pBuf->Buffer.VirtualAddress + DescLen;
1072 
1073 		ConstructVHTNDPAPacket(
1074 				Adapter,
1075 				RA,
1076 				AID,
1077 				BufAddr,
1078 				&BufLen,
1079 				BW
1080 				);
1081 
1082 		pTcb->PacketLength = BufLen + DescLen;
1083 
1084 		pTcb->bTxEnableSwCalcDur = TRUE;
1085 
1086 		pTcb->BWOfPacket = BW;
1087 
1088 		if(ACTING_AS_IBSS(Adapter) || ACTING_AS_AP(Adapter))
1089 			pTcb->G_ID = 63;
1090 
1091 		pTcb->P_AID = pBeamformEntry->P_AID;
1092 		pTcb->DataRate = NDPTxRate;	/*decide by Nr*/
1093 
1094 		Adapter->HalFunc.CmdSendPacketHandler(Adapter, pTcb, pBuf, pTcb->PacketLength, DESC_PACKET_TYPE_NORMAL, FALSE);
1095 	}
1096 	else
1097 		ret = FALSE;
1098 
1099 	PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
1100 
1101 	RT_DISP(FBEAM, FBEAM_FUN, ("@%s End, ret=%d \n", __FUNCTION__,ret));
1102 
1103 	if(ret)
1104 		RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);
1105 
1106 	return ret;
1107 }
1108 
1109 
1110 BOOLEAN
SendSWVHTNDPAPacket(IN PADAPTER Adapter,IN pu1Byte RA,IN u2Byte AID,IN CHANNEL_WIDTH BW)1111 SendSWVHTNDPAPacket(
1112 	IN	PADAPTER		Adapter,
1113 	IN	pu1Byte			RA,
1114 	IN	u2Byte			AID,
1115 	IN	CHANNEL_WIDTH	BW
1116 	)
1117 {
1118 	PRT_TCB					pTcb;
1119 	PRT_TX_LOCAL_BUFFER		pBuf;
1120 	BOOLEAN					ret = TRUE;
1121 	u1Byte					Idx = 0, NDPTxRate = 0;
1122 	PRT_BEAMFORMING_INFO 	pBeamInfo = GET_BEAMFORM_INFO(Adapter);
1123 	HAL_DATA_TYPE			*pHalData = GET_HAL_DATA(Adapter);
1124 	PDM_ODM_T				pDM_Odm = &pHalData->DM_OutSrc;
1125 	PRT_BEAMFORMING_ENTRY	pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);
1126 
1127 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
1128 
1129 	NDPTxRate = Beamforming_GetVHTNDPTxRate(Adapter, pBeamformEntry->CompSteeringNumofBFer);
1130 	RT_DISP(FBEAM, FBEAM_FUN, ("%s, NDPTxRate =%d\n", __FUNCTION__, NDPTxRate));
1131 
1132 	PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
1133 
1134 	if(MgntGetBuffer(Adapter, &pTcb, &pBuf))
1135 	{
1136 		ConstructVHTNDPAPacket(
1137 				Adapter,
1138 				RA,
1139 				AID,
1140 				pBuf->Buffer.VirtualAddress,
1141 				&pTcb->PacketLength,
1142 				BW
1143 				);
1144 
1145 		pTcb->bTxEnableSwCalcDur = TRUE;
1146 		pTcb->BWOfPacket = BW;
1147 
1148 		/*rate of NDP decide by Nr*/
1149 		MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, NDPTxRate);
1150 	}
1151 	else
1152 		ret = FALSE;
1153 
1154 	PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
1155 
1156 	RT_DISP(FBEAM, FBEAM_FUN, ("%s\n", __FUNCTION__));
1157 
1158 	if(ret)
1159 		RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);
1160 
1161 	return ret;
1162 }
1163 
1164 
1165 
1166 BOOLEAN
Beamforming_SendVHTNDPAPacket(IN PADAPTER Adapter,IN pu1Byte RA,IN u2Byte AID,IN CHANNEL_WIDTH BW,IN u1Byte QIdx)1167 Beamforming_SendVHTNDPAPacket(
1168 	IN	PADAPTER		Adapter,
1169 	IN	pu1Byte			RA,
1170 	IN	u2Byte			AID,
1171 	IN	CHANNEL_WIDTH	BW,
1172 	IN	u1Byte			QIdx
1173 	)
1174 {
1175 	HAL_DATA_TYPE			*pHalData = GET_HAL_DATA(Adapter);
1176 	PDM_ODM_T				pDM_Odm = &pHalData->DM_OutSrc;
1177 	BOOLEAN					ret = TRUE;
1178 
1179 	HalComTxbf_Set(Adapter, TXBF_SET_GET_TX_RATE, NULL);
1180 
1181 	if ((pDM_Odm->TxBfDataRate >= ODM_RATEVHTSS3MCS7) && (pDM_Odm->TxBfDataRate <= ODM_RATEVHTSS3MCS9)) {
1182 		ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s: 3SS VHT 789 don't sounding\n", __func__));
1183 
1184 	} else {
1185 	if(QIdx == BEACON_QUEUE)
1186 		ret = SendFWVHTNDPAPacket(Adapter, RA, AID, BW);
1187 	else
1188 		ret = SendSWVHTNDPAPacket(Adapter, RA, AID, BW);
1189 
1190 }
1191 		return ret;
1192 }
1193 
1194 
1195 BEAMFORMING_NOTIFY_STATE
phydm_beamfomring_bSounding(IN PVOID pDM_VOID,PRT_BEAMFORMING_INFO pBeamInfo,pu1Byte Idx)1196 phydm_beamfomring_bSounding(
1197 	IN	PVOID				pDM_VOID,
1198 	PRT_BEAMFORMING_INFO 	pBeamInfo,
1199 	pu1Byte					Idx
1200 	)
1201 {
1202 	BEAMFORMING_NOTIFY_STATE	bSounding = BEAMFORMING_NOTIFY_NONE;
1203 	RT_BEAMFORMING_OID_INFO	BeamOidInfo = pBeamInfo->BeamformingOidInfo;
1204 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
1205 
1206 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
1207 
1208 //	if(( Beamforming_GetBeamCap(pBeamInfo) & BEAMFORMER_CAP) == 0)
1209 //		bSounding = BEAMFORMING_NOTIFY_RESET;
1210 	if(BeamOidInfo.SoundOidMode == SOUNDING_STOP_All_TIMER)
1211 		bSounding = BEAMFORMING_NOTIFY_RESET;
1212 	else
1213 	{
1214 		u1Byte i;
1215 
1216 		for(i=0;i<BEAMFORMEE_ENTRY_NUM;i++)
1217 		{
1218 			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));
1219 			if(pBeamInfo->BeamformeeEntry[i].bUsed && (!pBeamInfo->BeamformeeEntry[i].bSound))
1220 			{
1221 				ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: Add BFee entry %d\n", __FUNCTION__, i));
1222 				*Idx = i;
1223 				bSounding = BEAMFORMING_NOTIFY_ADD;
1224 			}
1225 
1226 			if((!pBeamInfo->BeamformeeEntry[i].bUsed) && pBeamInfo->BeamformeeEntry[i].bSound)
1227 			{
1228 				ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: Delete BFee entry %d\n", __FUNCTION__, i));
1229 				*Idx = i;
1230 				bSounding = BEAMFORMING_NOTIFY_DELETE;
1231 			}
1232 		}
1233 	}
1234 
1235 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s End, bSounding = %d\n", __FUNCTION__, bSounding) );
1236 	return bSounding;
1237 }
1238 
1239 
1240 //This function is unused
1241 u1Byte
phydm_beamforming_SoundingIdx(IN PVOID pDM_VOID,PRT_BEAMFORMING_INFO pBeamInfo)1242 phydm_beamforming_SoundingIdx(
1243 	IN	PVOID				pDM_VOID,
1244 	PRT_BEAMFORMING_INFO 		pBeamInfo
1245 	)
1246 {
1247 	u1Byte					Idx = 0;
1248 	RT_BEAMFORMING_ENTRY	BeamEntry;
1249 	RT_BEAMFORMING_OID_INFO	BeamOidInfo = pBeamInfo->BeamformingOidInfo;
1250 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
1251 
1252 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
1253 
1254 	if(	BeamOidInfo.SoundOidMode == SOUNDING_SW_HT_TIMER || BeamOidInfo.SoundOidMode == SOUNDING_SW_VHT_TIMER ||
1255 		BeamOidInfo.SoundOidMode == SOUNDING_HW_HT_TIMER || BeamOidInfo.SoundOidMode == SOUNDING_HW_VHT_TIMER)
1256 		Idx = BeamOidInfo.SoundOidIdx;
1257 	else
1258 	{
1259 		u1Byte	i;
1260 		for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
1261 		{
1262 			if( pBeamInfo->BeamformeeEntry[i].bUsed &&
1263 				(FALSE == pBeamInfo->BeamformeeEntry[i].bSound))
1264 			{
1265 				Idx = i;
1266 				break;
1267 			}
1268 		}
1269 	}
1270 
1271 	return Idx;
1272 }
1273 
1274 
1275 SOUNDING_MODE
phydm_beamforming_SoundingMode(IN PVOID pDM_VOID,PRT_BEAMFORMING_INFO pBeamInfo,u1Byte Idx)1276 phydm_beamforming_SoundingMode(
1277 	IN	PVOID				pDM_VOID,
1278 	PRT_BEAMFORMING_INFO 	pBeamInfo,
1279 	u1Byte					Idx
1280 	)
1281 {
1282 	PDM_ODM_T		pDM_Odm = (PDM_ODM_T)pDM_VOID;
1283 	u1Byte 			SupportInterface = pDM_Odm->SupportInterface;
1284 
1285 	RT_BEAMFORMING_ENTRY		BeamEntry = pBeamInfo->BeamformeeEntry[Idx];
1286 	RT_BEAMFORMING_OID_INFO		BeamOidInfo = pBeamInfo->BeamformingOidInfo;
1287 	SOUNDING_MODE				Mode = BeamOidInfo.SoundOidMode;
1288 
1289 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
1290 //	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s: OID mode is %d\n", __FUNCTION__, BeamOidInfo.SoundOidMode));
1291 
1292 	if(BeamOidInfo.SoundOidMode == SOUNDING_SW_VHT_TIMER || BeamOidInfo.SoundOidMode == SOUNDING_HW_VHT_TIMER)
1293 	{
1294 		if(BeamEntry.BeamformEntryCap & BEAMFORMER_CAP_VHT_SU)
1295 			Mode = BeamOidInfo.SoundOidMode;
1296 		else
1297 			Mode = SOUNDING_STOP_All_TIMER;
1298 	}
1299 	else if(BeamOidInfo.SoundOidMode == SOUNDING_SW_HT_TIMER || BeamOidInfo.SoundOidMode == SOUNDING_HW_HT_TIMER)
1300 	{
1301 		if(BeamEntry.BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT)
1302 			Mode = BeamOidInfo.SoundOidMode;
1303 		else
1304 			Mode = SOUNDING_STOP_All_TIMER;
1305 	}
1306 	else if(BeamEntry.BeamformEntryCap & BEAMFORMER_CAP_VHT_SU)
1307 	{
1308 		if((SupportInterface == ODM_ITRF_USB) && (pDM_Odm->SupportICType!= ODM_RTL8814A))
1309 			Mode = SOUNDING_FW_VHT_TIMER;
1310 		else
1311 			Mode = SOUNDING_SW_VHT_TIMER;
1312 	}
1313 	else if(BeamEntry.BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT)
1314 	{
1315 		if((SupportInterface == ODM_ITRF_USB) && (pDM_Odm->SupportICType != ODM_RTL8814A))
1316 		Mode = SOUNDING_FW_HT_TIMER;
1317 	else
1318 		Mode = SOUNDING_SW_HT_TIMER;
1319 	}
1320 	else
1321 		Mode = SOUNDING_STOP_All_TIMER;
1322 
1323 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End, SupportInterface=%d, Mode=%d \n", __FUNCTION__, SupportInterface, Mode));
1324 
1325 	return Mode;
1326 }
1327 
1328 
1329 u2Byte
phydm_beamforming_SoundingTime(IN PVOID pDM_VOID,PRT_BEAMFORMING_INFO pBeamInfo,SOUNDING_MODE Mode,u1Byte Idx)1330 phydm_beamforming_SoundingTime(
1331 	IN	PVOID				pDM_VOID,
1332 	PRT_BEAMFORMING_INFO 	pBeamInfo,
1333 	SOUNDING_MODE			Mode,
1334 	u1Byte					Idx
1335 	)
1336 {
1337 	u2Byte						SoundingTime = 0xffff;
1338 	RT_BEAMFORMING_ENTRY		BeamEntry = pBeamInfo->BeamformeeEntry[Idx];
1339 	RT_BEAMFORMING_OID_INFO	BeamOidInfo = pBeamInfo->BeamformingOidInfo;
1340 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
1341 
1342 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
1343 
1344 	if(Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_HW_VHT_TIMER)
1345 		SoundingTime = BeamOidInfo.SoundOidPeriod * 32;
1346 	else if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_SW_VHT_TIMER)
1347 		//-@ Modified by David
1348 		SoundingTime = BeamEntry.SoundPeriod; //100*32;  //BeamOidInfo.SoundOidPeriod;
1349 	else
1350 		SoundingTime = BeamEntry.SoundPeriod;
1351 
1352 	return SoundingTime;
1353 }
1354 
1355 
1356 CHANNEL_WIDTH
phydm_beamforming_SoundingBW(IN PVOID pDM_VOID,PRT_BEAMFORMING_INFO pBeamInfo,SOUNDING_MODE Mode,u1Byte Idx)1357 phydm_beamforming_SoundingBW(
1358 	IN	PVOID				pDM_VOID,
1359 	PRT_BEAMFORMING_INFO 	pBeamInfo,
1360 	SOUNDING_MODE			Mode,
1361 	u1Byte					Idx
1362 	)
1363 {
1364 	CHANNEL_WIDTH				SoundingBW = CHANNEL_WIDTH_20;
1365 	RT_BEAMFORMING_ENTRY		BeamEntry = pBeamInfo->BeamformeeEntry[Idx];
1366 	RT_BEAMFORMING_OID_INFO	BeamOidInfo = pBeamInfo->BeamformingOidInfo;
1367 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
1368 
1369 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
1370 
1371 	if(Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_HW_VHT_TIMER)
1372 		SoundingBW = BeamOidInfo.SoundOidBW;
1373 	else if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_SW_VHT_TIMER)
1374 		//-@ Modified by David
1375 		SoundingBW = BeamEntry.SoundBW;   //BeamOidInfo.SoundOidBW;
1376 	else
1377 		SoundingBW = BeamEntry.SoundBW;
1378 
1379 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, SoundingBW=0x%X \n", __FUNCTION__, SoundingBW) );
1380 
1381 	return SoundingBW;
1382 }
1383 
1384 
1385 BOOLEAN
phydm_Beamforming_SelectBeamEntry(IN PVOID pDM_VOID,PRT_BEAMFORMING_INFO pBeamInfo)1386 phydm_Beamforming_SelectBeamEntry(
1387 	IN	PVOID				pDM_VOID,
1388 	PRT_BEAMFORMING_INFO 	pBeamInfo
1389 	)
1390 {
1391 	PRT_SOUNDING_INFO		pSoundInfo = &(pBeamInfo->SoundingInfo);
1392 	PDM_ODM_T				pDM_Odm = (PDM_ODM_T)pDM_VOID;
1393 
1394 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
1395 
1396 	// pEntry.bSound is different between first and latter NDPA, and should not be used as BFee entry selection
1397 	// BTW, latter modification should sync to the selection mechanism of AP/ADSL instead of the fixed SoundIdx.
1398 	//pSoundInfo->SoundIdx = phydm_beamforming_SoundingIdx(pDM_Odm, pBeamInfo);
1399 	pSoundInfo->SoundIdx = 0;
1400 
1401 	if(pSoundInfo->SoundIdx < BEAMFORMEE_ENTRY_NUM)
1402 		pSoundInfo->SoundMode = phydm_beamforming_SoundingMode(pDM_Odm, pBeamInfo, pSoundInfo->SoundIdx);
1403 	else
1404 		pSoundInfo->SoundMode = SOUNDING_STOP_All_TIMER;
1405 
1406 	if(SOUNDING_STOP_All_TIMER == pSoundInfo->SoundMode)
1407 		return FALSE;
1408 	else
1409 	{
1410 		pSoundInfo->SoundBW = phydm_beamforming_SoundingBW(pDM_Odm, pBeamInfo, pSoundInfo->SoundMode, pSoundInfo->SoundIdx );
1411 		pSoundInfo->SoundPeriod = phydm_beamforming_SoundingTime(pDM_Odm, pBeamInfo, pSoundInfo->SoundMode, pSoundInfo->SoundIdx );
1412 		return TRUE;
1413 	}
1414 }
1415 
1416 
1417 BOOLEAN
phydm_beamforming_StartPeriod(IN PVOID pDM_VOID)1418 phydm_beamforming_StartPeriod(
1419 	IN	PVOID				pDM_VOID
1420 	)
1421 {
1422 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
1423 	PADAPTER					Adapter = pDM_Odm->Adapter;
1424 	BOOLEAN						Ret = TRUE;
1425 	PRT_BEAMFORMING_INFO 		pBeamInfo = &pDM_Odm->BeamformingInfo;
1426 	PRT_SOUNDING_INFO			pSoundInfo = &(pBeamInfo->SoundingInfo);
1427 
1428 
1429 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
1430 
1431 	phydm_Beamforming_DymNDPARate(pDM_Odm);
1432 
1433 	phydm_Beamforming_SelectBeamEntry(pDM_Odm, pBeamInfo);		// Modified
1434 
1435 
1436 	if(pSoundInfo->SoundMode == SOUNDING_SW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_SW_HT_TIMER)
1437 		ODM_SetTimer(pDM_Odm, &pBeamInfo->BeamformingTimer, pSoundInfo->SoundPeriod);
1438 	else if(pSoundInfo->SoundMode == SOUNDING_HW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_HW_HT_TIMER ||
1439 			pSoundInfo->SoundMode == SOUNDING_AUTO_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_AUTO_HT_TIMER)
1440 	{
1441 		HAL_HW_TIMER_TYPE TimerType = HAL_TIMER_TXBF;
1442 		u4Byte	val = (pSoundInfo->SoundPeriod | (TimerType<<16));
1443 
1444 		//HW timer stop: All IC has the same setting
1445 		Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_STOP,  (pu1Byte)(&TimerType));
1446 		//ODM_Write1Byte(pDM_Odm, 0x15F, 0);
1447 		//HW timer init: All IC has the same setting, but 92E & 8812A only write 2 bytes
1448 		Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_INIT,  (pu1Byte)(&val));
1449 		//ODM_Write1Byte(pDM_Odm, 0x164, 1);
1450 		//ODM_Write4Byte(pDM_Odm, 0x15C, val);
1451 		//HW timer start: All IC has the same setting
1452 		Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_START,  (pu1Byte)(&TimerType));
1453 		//ODM_Write1Byte(pDM_Odm, 0x15F, 0x5);
1454 	}
1455 	else if(pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER)
1456 	{
1457 		Ret = BeamformingStart_FW(Adapter, pSoundInfo->SoundIdx);
1458 	}
1459 	else
1460 		Ret = FALSE;
1461 
1462 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: SoundIdx=%d, SoundMode=%d, SoundBW=%d, SoundPeriod=%d\n", __FUNCTION__,
1463 			pSoundInfo->SoundIdx, pSoundInfo->SoundMode, pSoundInfo->SoundBW, pSoundInfo->SoundPeriod));
1464 
1465 	return Ret;
1466 }
1467 
1468 // Used after Beamforming_Leave, and will clear the setting of the "already deleted" entry
1469 VOID
phydm_beamforming_EndPeriod_SW(IN PVOID pDM_VOID)1470 phydm_beamforming_EndPeriod_SW(
1471 	IN	PVOID				pDM_VOID
1472 	)
1473 {
1474 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
1475 	PADAPTER					Adapter = pDM_Odm->Adapter;
1476 	u1Byte						Idx = 0;
1477 	PRT_BEAMFORMING_ENTRY		pBeamformEntry;
1478 	PRT_BEAMFORMING_INFO 		pBeamInfo = &pDM_Odm->BeamformingInfo;
1479 	PRT_SOUNDING_INFO			pSoundInfo = &(pBeamInfo->SoundingInfo);
1480 
1481 	HAL_HW_TIMER_TYPE TimerType = HAL_TIMER_TXBF;
1482 
1483 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
1484 
1485 	if(pSoundInfo->SoundMode == SOUNDING_SW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_SW_HT_TIMER)
1486 		ODM_CancelTimer(pDM_Odm, &pBeamInfo->BeamformingTimer);
1487 	else if(	pSoundInfo->SoundMode == SOUNDING_HW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_HW_HT_TIMER ||
1488 				pSoundInfo->SoundMode == SOUNDING_AUTO_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_AUTO_HT_TIMER)
1489 		//HW timer stop: All IC has the same setting
1490 		Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_STOP,  (pu1Byte)(&TimerType));
1491 		//ODM_Write1Byte(pDM_Odm, 0x15F, 0);
1492 }
1493 
1494 VOID
phydm_beamforming_EndPeriod_FW(IN PVOID pDM_VOID)1495 phydm_beamforming_EndPeriod_FW(
1496 	IN	PVOID				pDM_VOID
1497 	)
1498 {
1499 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
1500 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
1501 	phydm_Beamforming_End_FW(pDM_Odm);
1502 }
1503 
1504 
1505 
1506 VOID
phydm_beamforming_ClearEntry_SW(IN PVOID pDM_VOID,BOOLEAN IsDelete,u1Byte DeleteIdx)1507 phydm_beamforming_ClearEntry_SW(
1508 	IN	PVOID			pDM_VOID,
1509 	BOOLEAN				IsDelete,
1510 	u1Byte				DeleteIdx
1511 	)
1512 {
1513 	u1Byte						Idx = 0;
1514 	PRT_BEAMFORMING_ENTRY		pBeamformEntry = NULL;
1515 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
1516 	PRT_BEAMFORMING_INFO 		pBeamInfo = &pDM_Odm->BeamformingInfo;
1517 
1518 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
1519 
1520 	if(IsDelete)
1521 	{
1522 		if(DeleteIdx<BEAMFORMEE_ENTRY_NUM)
1523 		{
1524 			pBeamformEntry = pBeamInfo->BeamformeeEntry + DeleteIdx;
1525 
1526 			if(!((!pBeamformEntry->bUsed) && pBeamformEntry->bSound))
1527 			{
1528 				ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: SW DeleteIdx is wrong!!!!! \n",__FUNCTION__));
1529 				return;
1530 			}
1531 		}
1532 
1533 		ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: SW delete BFee entry %d \n", __FUNCTION__, DeleteIdx));
1534 		if(pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSING)
1535 		{
1536 			pBeamformEntry->bBeamformingInProgress = FALSE;
1537 			pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
1538 		}
1539 		else if(pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSED)
1540 		{
1541 			pBeamformEntry->BeamformEntryState  = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
1542 			HalComTxbf_Set(pDM_Odm->Adapter, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&DeleteIdx);
1543 		}
1544 
1545 		pBeamformEntry->bSound = FALSE;
1546 	}
1547 	else
1548 	{
1549 		for(Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++)
1550 		{
1551 			pBeamformEntry = pBeamInfo->BeamformeeEntry+Idx;
1552 
1553 			// Used after bSounding=RESET, and will clear the setting of "ever sounded" entry, which is not necessarily be deleted.
1554 			// This function is mainly used in case "BeamOidInfo.SoundOidMode == SOUNDING_STOP_All_TIMER".
1555 			// However, setting oid doesn't delete entries (bUsed is still TRUE), new entries may fail to be added in.
1556 
1557 			if(pBeamformEntry->bSound)
1558 			{
1559 				ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: SW reset BFee entry %d \n", __FUNCTION__, Idx));
1560 				/*
1561 				*	If End procedure is
1562 				*	1. Between (Send NDPA, C2H packet return), reset state to initialized.
1563 				*	After C2H packet return , status bit will be set to zero.
1564 				*
1565 				*	2. After C2H packet, then reset state to initialized and clear status bit.
1566 				*/
1567 
1568 				if (pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSING)
1569 					phydm_Beamforming_End_SW(pDM_Odm, 0);
1570 				else if (pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSED) {
1571 					pBeamformEntry->BeamformEntryState  = BEAMFORMING_ENTRY_STATE_INITIALIZED;
1572 					HalComTxbf_Set(pDM_Odm->Adapter, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&Idx);
1573 				}
1574 
1575 				pBeamformEntry->bSound = FALSE;
1576 			}
1577 		}
1578 	}
1579 }
1580 
1581 VOID
phydm_beamforming_ClearEntry_FW(IN PVOID pDM_VOID,BOOLEAN IsDelete,u1Byte DeleteIdx)1582 phydm_beamforming_ClearEntry_FW(
1583 	IN	PVOID			pDM_VOID,
1584 	BOOLEAN				IsDelete,
1585 	u1Byte				DeleteIdx
1586 	)
1587 {
1588 	u1Byte						Idx = 0;
1589 	PRT_BEAMFORMING_ENTRY		pBeamformEntry = NULL;
1590 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
1591 	PRT_BEAMFORMING_INFO 		pBeamInfo = &pDM_Odm->BeamformingInfo;
1592 
1593 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
1594 
1595 	if(IsDelete)
1596 	{
1597 		if(DeleteIdx<BEAMFORMEE_ENTRY_NUM)
1598 		{
1599 			pBeamformEntry = pBeamInfo->BeamformeeEntry + DeleteIdx;
1600 
1601 			if(!((!pBeamformEntry->bUsed) && pBeamformEntry->bSound))
1602 			{
1603 				ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: FW DeleteIdx is wrong!!!!! \n",__FUNCTION__));
1604 				return;
1605 			}
1606 		}
1607 
1608 		ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: FW delete BFee entry %d \n", __FUNCTION__, DeleteIdx));
1609 		pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
1610 		pBeamformEntry->bSound = FALSE;
1611 	}
1612 	else
1613 	{
1614 		for(Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++)
1615 		{
1616 			pBeamformEntry = pBeamInfo->BeamformeeEntry+Idx;
1617 
1618 			// Used after bSounding=RESET, and will clear the setting of "ever sounded" entry, which is not necessarily be deleted.
1619 			// This function is mainly used in case "BeamOidInfo.SoundOidMode == SOUNDING_STOP_All_TIMER".
1620 			// However, setting oid doesn't delete entries (bUsed is still TRUE), new entries may fail to be added in.
1621 
1622 			if(pBeamformEntry->bSound)
1623 			{
1624 				ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: FW reset BFee entry %d \n", __FUNCTION__, Idx));
1625 				/*
1626 				*	If End procedure is
1627 				*	1. Between (Send NDPA, C2H packet return), reset state to initialized.
1628 				*	After C2H packet return , status bit will be set to zero.
1629 				*
1630 				*	2. After C2H packet, then reset state to initialized and clear status bit.
1631 				*/
1632 
1633 				pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;
1634 				pBeamformEntry->bSound = FALSE;
1635 			}
1636 		}
1637 	}
1638 }
1639 
1640 /*
1641 * 	Called :
1642 *	1. Add and delete entry : Beamforming_Enter/Beamforming_Leave
1643 *	2. FW trigger :  Beamforming_SetTxBFen
1644 *	3. Set OID_RT_BEAMFORMING_PERIOD : BeamformingControl_V2
1645 */
1646 VOID
phydm_Beamforming_Notify(IN PVOID pDM_VOID)1647 phydm_Beamforming_Notify(
1648 	IN	PVOID			pDM_VOID
1649 	)
1650 {
1651 	u1Byte						Idx=BEAMFORMEE_ENTRY_NUM;
1652 	BEAMFORMING_NOTIFY_STATE	bSounding = BEAMFORMING_NOTIFY_NONE;
1653 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
1654 	PRT_BEAMFORMING_INFO 		pBeamInfo = &pDM_Odm->BeamformingInfo;
1655 	PRT_SOUNDING_INFO			pSoundInfo = &(pBeamInfo->SoundingInfo);
1656 
1657 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[Beamforming]%s Start!\n", __FUNCTION__) );
1658 
1659 	bSounding = phydm_beamfomring_bSounding(pDM_Odm, pBeamInfo, &Idx);
1660 
1661 	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));
1662 
1663 	if(pBeamInfo->BeamformState == BEAMFORMING_STATE_END)
1664 	{
1665 		if(bSounding==BEAMFORMING_NOTIFY_ADD)
1666 		{
1667 			if(phydm_beamforming_StartPeriod(pDM_Odm) == TRUE)
1668 				pBeamInfo->BeamformState = BEAMFORMING_STATE_START_1BFee;
1669 		}
1670 	}
1671 	else if(pBeamInfo->BeamformState == BEAMFORMING_STATE_START_1BFee)
1672 	{
1673 		if(bSounding==BEAMFORMING_NOTIFY_ADD)
1674 		{
1675 			if(phydm_beamforming_StartPeriod(pDM_Odm) == TRUE)
1676 				pBeamInfo->BeamformState = BEAMFORMING_STATE_START_2BFee;
1677 			else
1678 				pBeamInfo->BeamformState = BEAMFORMING_STATE_START_1BFee;
1679 		}
1680 		else if(bSounding==BEAMFORMING_NOTIFY_DELETE)
1681 		{
1682 			if(pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER)
1683 			{
1684 				phydm_beamforming_ClearEntry_FW(pDM_Odm, TRUE, Idx);		// Modified by Jeffery @ 2014-11-04
1685 				phydm_beamforming_EndPeriod_FW(pDM_Odm);
1686 			}
1687 			else
1688 			{
1689 				phydm_beamforming_ClearEntry_SW(pDM_Odm, TRUE, Idx);		// Modified by Jeffery @ 2014-11-04
1690 				phydm_beamforming_EndPeriod_SW(pDM_Odm);
1691 			}
1692 
1693 			pBeamInfo->BeamformState = BEAMFORMING_STATE_END;
1694 		}
1695 		else if(bSounding==BEAMFORMING_NOTIFY_RESET)
1696 		{
1697 			if(pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER)
1698 			{
1699 				phydm_beamforming_ClearEntry_FW(pDM_Odm, FALSE, Idx);		// Modified by Jeffery @ 2014-11-04
1700 				phydm_beamforming_EndPeriod_FW(pDM_Odm);
1701 			}
1702 			else
1703 			{
1704 				phydm_beamforming_ClearEntry_SW(pDM_Odm, FALSE, Idx);		// Modified by Jeffery @ 2014-11-04
1705 				phydm_beamforming_EndPeriod_SW(pDM_Odm);
1706 			}
1707 
1708 			pBeamInfo->BeamformState = BEAMFORMING_STATE_END;
1709 		}
1710 	}
1711 	else if(pBeamInfo->BeamformState == BEAMFORMING_STATE_START_2BFee)
1712 	{
1713 		if(bSounding==BEAMFORMING_NOTIFY_ADD)
1714 		{
1715 			RT_ASSERT(FALSE, ("[David]@%s: Should be blocked at InitEntry!!!!! \n", __FUNCTION__));
1716 		}
1717 		else if(bSounding==BEAMFORMING_NOTIFY_DELETE)
1718 		{
1719 			if(pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER)
1720 			{
1721 				phydm_beamforming_ClearEntry_FW(pDM_Odm, TRUE, Idx);		// Modified by Jeffery @ 2014-11-04
1722 				phydm_beamforming_EndPeriod_FW(pDM_Odm);
1723 			}
1724 			else
1725 			{
1726 				// For 2->1 entry, we should not cancel SW timer
1727 				phydm_beamforming_ClearEntry_SW(pDM_Odm, TRUE, Idx);
1728 			}
1729 
1730 			pBeamInfo->BeamformState = BEAMFORMING_STATE_START_1BFee;
1731 		}
1732 		else if(bSounding==BEAMFORMING_NOTIFY_RESET)
1733 		{
1734 			if(pSoundInfo->SoundMode == SOUNDING_FW_HT_TIMER || pSoundInfo->SoundMode == SOUNDING_FW_VHT_TIMER)
1735 			{
1736 				phydm_beamforming_ClearEntry_FW(pDM_Odm, FALSE, Idx);		// Modified by Jeffery @ 2014-11-04
1737 				phydm_beamforming_EndPeriod_FW(pDM_Odm);
1738 			}
1739 			else
1740 			{
1741 				phydm_beamforming_ClearEntry_SW(pDM_Odm, FALSE, Idx);		// Modified by Jeffery @ 2014-11-04
1742 				phydm_beamforming_EndPeriod_SW(pDM_Odm);
1743 			}
1744 
1745 			pBeamInfo->BeamformState = BEAMFORMING_STATE_END;
1746 		}
1747 	}
1748 	else
1749 		RT_ASSERT(FALSE, ("%s BeamformState %d\n", __FUNCTION__, pBeamInfo->BeamformState));
1750 
1751 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s End, after Notify, BeamformState =%d\n", __FUNCTION__, pBeamInfo->BeamformState));
1752 }
1753 
1754 
1755 
1756 BOOLEAN
Beamforming_InitEntry(PADAPTER Adapter,PRT_WLAN_STA pSTA,pu1Byte BFerBFeeIdx)1757 Beamforming_InitEntry(
1758 	PADAPTER		Adapter,
1759 	PRT_WLAN_STA	pSTA,
1760 	pu1Byte			BFerBFeeIdx
1761 	)
1762 {
1763 	PMGNT_INFO					pMgntInfo = &Adapter->MgntInfo;
1764 	PRT_HIGH_THROUGHPUT			pHTInfo = GET_HT_INFO(pMgntInfo);
1765 	PRT_VERY_HIGH_THROUGHPUT	pVHTInfo = GET_VHT_INFO(pMgntInfo);
1766 	PRT_BEAMFORMING_ENTRY		pBeamformEntry = NULL;
1767 	PRT_BEAMFORMER_ENTRY		pBeamformerEntry = NULL;
1768 	pu1Byte						RA;
1769 	u2Byte						AID, MacID;
1770 	WIRELESS_MODE				WirelessMode;
1771 	CHANNEL_WIDTH				BW = CHANNEL_WIDTH_20;
1772 	BEAMFORMING_CAP				BeamformCap = BEAMFORMING_CAP_NONE;
1773 	u1Byte						BFerIdx=0xF, BFeeIdx=0xF;
1774 	u1Byte						NumofSoundingDim = 0, CompSteeringNumofBFer = 0;
1775 	HAL_DATA_TYPE				*pHalData = GET_HAL_DATA(Adapter);
1776 	PDM_ODM_T					pDM_Odm = &pHalData->DM_OutSrc;
1777 
1778 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__));
1779 
1780 	// The current setting does not support Beaforming
1781 	if(BEAMFORMING_CAP_NONE == pHTInfo->HtBeamformCap && BEAMFORMING_CAP_NONE == pVHTInfo->VhtBeamformCap)
1782 	{
1783 		RT_DISP(FBEAM, FBEAM_ERROR, ("The configuration disabled Beamforming! Skip...\n"));
1784 		return FALSE;
1785 	}
1786 
1787 	// IBSS, AP mode
1788 	if(pSTA != NULL)
1789 	{
1790 		AID = pSTA->AID;
1791 		RA = pSTA->MacAddr;
1792 		MacID = pSTA->AssociatedMacId;
1793 		WirelessMode = pSTA->WirelessMode;
1794 		BW = pSTA->BandWidth;
1795 	}
1796 	else	// Client mode
1797 	{
1798 		AID = pMgntInfo->mAId;
1799 		RA = pMgntInfo->Bssid;
1800 		MacID = pMgntInfo->mMacId;
1801 		WirelessMode = pMgntInfo->dot11CurrentWirelessMode;
1802 		BW = pMgntInfo->dot11CurrentChannelBandWidth;
1803 	}
1804 
1805 	if(WirelessMode < WIRELESS_MODE_N_24G)
1806 		return FALSE;
1807 	else
1808 	{
1809 		//3 // HT
1810 		u1Byte CurBeamform;
1811 		u2Byte CurBeamformVHT;
1812 
1813 		if(pSTA != NULL)
1814 			CurBeamform = pSTA->HTInfo.HtCurBeamform;
1815 		else
1816 			CurBeamform = pHTInfo->HtCurBeamform;
1817 
1818 		// We are Beamformee because the STA is Beamformer
1819 		if(TEST_FLAG(CurBeamform, BEAMFORMING_HT_BEAMFORMER_ENABLE))
1820 		{
1821 			BeamformCap =(BEAMFORMING_CAP)(BeamformCap |BEAMFORMEE_CAP_HT_EXPLICIT);
1822 			NumofSoundingDim = (CurBeamform&BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP)>>6;
1823 		}
1824 
1825 		// We are Beamformer because the STA is Beamformee
1826 		if(	TEST_FLAG(CurBeamform, BEAMFORMING_HT_BEAMFORMEE_ENABLE) ||
1827 			TEST_FLAG(pHTInfo->HtBeamformCap, BEAMFORMING_HT_BEAMFORMER_TEST))
1828 		{
1829 			BeamformCap =(BEAMFORMING_CAP)(BeamformCap | BEAMFORMER_CAP_HT_EXPLICIT);
1830 			CompSteeringNumofBFer = (CurBeamform & BEAMFORMING_HT_BEAMFORMER_STEER_NUM)>>4;
1831 		}
1832 
1833 		RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s, CurBeamform=0x%X, BeamformCap=0x%X\n", __FUNCTION__, CurBeamform, BeamformCap));
1834 		RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s, NumofSoundingDim=%d, CompSteeringNumofBFer=%d\n", __FUNCTION__, NumofSoundingDim, CompSteeringNumofBFer));
1835 
1836 
1837 		if(WirelessMode == WIRELESS_MODE_AC_5G || WirelessMode == WIRELESS_MODE_AC_24G)
1838 		{
1839 			//3 // VHT
1840 			if(pSTA != NULL)
1841 				CurBeamformVHT = pSTA->VHTInfo.VhtCurBeamform;
1842 			else
1843 				CurBeamformVHT = pVHTInfo->VhtCurBeamform;
1844 
1845 			// We are Beamformee because the STA is Beamformer
1846 			if(TEST_FLAG(CurBeamformVHT, BEAMFORMING_VHT_BEAMFORMER_ENABLE))
1847 			{
1848 				BeamformCap =(BEAMFORMING_CAP)(BeamformCap |BEAMFORMEE_CAP_VHT_SU);
1849 				NumofSoundingDim = (CurBeamformVHT & BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM)>>12;
1850 			}
1851 			// We are Beamformer because the STA is Beamformee
1852 			if(	TEST_FLAG(CurBeamformVHT, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) ||
1853 				TEST_FLAG(pVHTInfo->VhtBeamformCap, BEAMFORMING_VHT_BEAMFORMER_TEST))
1854 			{
1855 				BeamformCap =(BEAMFORMING_CAP)(BeamformCap |BEAMFORMER_CAP_VHT_SU);
1856 				CompSteeringNumofBFer = (CurBeamformVHT & BEAMFORMING_VHT_BEAMFORMER_STS_CAP)>>8;
1857 			}
1858 
1859 			RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s, CurBeamformVHT=0x%X, BeamformCap=0x%X\n", __FUNCTION__, CurBeamformVHT, BeamformCap));
1860 			RT_DISP(FBEAM, FBEAM_FUN, ("%s, NumofSoundingDim=0x%X, CompSteeringNumofBFer=0x%X\n", __FUNCTION__, NumofSoundingDim, CompSteeringNumofBFer));
1861 
1862 		}
1863 	}
1864 
1865 
1866 	if(BeamformCap == BEAMFORMING_CAP_NONE)
1867 		return FALSE;
1868 
1869 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s, Self BF Entry Cap = 0x%02X\n", __FUNCTION__, BeamformCap));
1870 
1871 	// We are BFee, so the entry is BFer
1872 	if((BeamformCap & BEAMFORMEE_CAP_VHT_SU) || (BeamformCap & BEAMFORMEE_CAP_HT_EXPLICIT))
1873 	{
1874 		pBeamformerEntry = phydm_Beamforming_GetBFerEntryByAddr(pDM_Odm, RA, &BFerIdx);
1875 
1876 		if(pBeamformerEntry == NULL)
1877 		{
1878 			pBeamformerEntry = Beamforming_AddBFerEntry(Adapter, RA, AID, BeamformCap, NumofSoundingDim ,&BFerIdx);
1879 
1880 			if(pBeamformerEntry == NULL)
1881 				RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s: Not enough BFer entry!!!!! \n", __FUNCTION__));
1882 		}
1883 	}
1884 
1885 	// We are BFer, so the entry is BFee
1886 	if((BeamformCap & BEAMFORMER_CAP_VHT_SU) || (BeamformCap & BEAMFORMER_CAP_HT_EXPLICIT))
1887 	{
1888 		pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &BFeeIdx);
1889 
1890 		// �p�GBFeeIdx = 0xF �h�N��ثeentry���S���ۦP��MACID�b��
1891 		RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s: Get BFee entry 0x%X by address \n", __FUNCTION__, BFeeIdx));
1892 		if(pBeamformEntry == NULL)
1893 		{
1894 			pBeamformEntry = Beamforming_AddBFeeEntry(Adapter, RA, AID, MacID, BW, BeamformCap, NumofSoundingDim, CompSteeringNumofBFer, &BFeeIdx);
1895 
1896 			RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s: Add BFee entry %d \n", __FUNCTION__, BFeeIdx));
1897 
1898 			if(pBeamformEntry == NULL)
1899 				return FALSE;
1900 			else
1901 				pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZEING;
1902 		}
1903 		else
1904 		{
1905 			// Entry has been created. If entry is initialing or progressing then errors occur.
1906 			if(	pBeamformEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_INITIALIZED &&
1907 				pBeamformEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSED)
1908 			{
1909 				RT_ASSERT(TRUE, ("Error State of Beamforming"));
1910 				return FALSE;
1911 			}
1912 			else
1913 				pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZEING;
1914 		}
1915 
1916 		pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;
1917 
1918 	}
1919 
1920 	*BFerBFeeIdx = (BFerIdx<<4) | BFeeIdx;
1921 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End: BFerIdx=0x%X, BFeeIdx=0x%X, BFerBFeeIdx=0x%X \n", __FUNCTION__, BFerIdx, BFeeIdx, *BFerBFeeIdx));
1922 
1923 	return TRUE;
1924 }
1925 
1926 
1927 VOID
Beamforming_DeInitEntry(PADAPTER Adapter,pu1Byte RA)1928 Beamforming_DeInitEntry(
1929 	PADAPTER		Adapter,
1930 	pu1Byte			RA
1931 	)
1932 {
1933 	u1Byte					Idx = 0;
1934 	PMGNT_INFO				pMgntInfo = &(Adapter->MgntInfo);
1935 
1936         RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s Start!\n", __FUNCTION__) );
1937 
1938 	if(Beamforming_RemoveEntry(Adapter, RA, &Idx) == TRUE)
1939 	{
1940 		HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_LEAVE, (pu1Byte)&Idx);
1941 	}
1942 
1943 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End, Idx = 0x%X\n", __FUNCTION__, Idx));
1944 }
1945 
1946 
1947 VOID
Beamforming_Reset(PADAPTER Adapter)1948 Beamforming_Reset(
1949 	PADAPTER		Adapter
1950 	)
1951 {
1952 	u1Byte					Idx = 0;
1953 	PMGNT_INFO				pMgntInfo = &(Adapter->MgntInfo);
1954 	PRT_BEAMFORMING_INFO 	pBeamformingInfo = GET_BEAMFORM_INFO(Adapter);
1955 
1956 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
1957 
1958 	for(Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++)
1959 	{
1960 		if(pBeamformingInfo->BeamformeeEntry[Idx].bUsed == TRUE)
1961 		{
1962 			pBeamformingInfo->BeamformeeEntry[Idx].bUsed = FALSE;
1963 			pBeamformingInfo->BeamformeeEntry[Idx].BeamformEntryCap = BEAMFORMING_CAP_NONE;
1964 			//pBeamformingInfo->BeamformeeEntry[Idx].BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
1965 			//-@ Modified by David
1966 			pBeamformingInfo->BeamformeeEntry[Idx].bBeamformingInProgress = FALSE;
1967 			HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_LEAVE, (pu1Byte)&Idx);
1968 		}
1969 	}
1970 
1971 	for(Idx = 0; Idx < BEAMFORMER_ENTRY_NUM; Idx++)
1972 	{
1973 		pBeamformingInfo->BeamformerEntry[Idx].bUsed = FALSE;
1974 		RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s, Idx=%d, bUsed=%d \n", __FUNCTION__, Idx, pBeamformingInfo->BeamformerEntry[Idx].bUsed));
1975 	}
1976 
1977 }
1978 
1979 
1980 BOOLEAN
BeamformingStart_V1(PADAPTER Adapter,pu1Byte RA,BOOLEAN Mode,CHANNEL_WIDTH BW,u1Byte Rate)1981 BeamformingStart_V1(
1982 	PADAPTER		Adapter,
1983 	pu1Byte			RA,
1984 	BOOLEAN			Mode,
1985 	CHANNEL_WIDTH	BW,
1986 	u1Byte			Rate
1987 	)
1988 {
1989 	u1Byte					Idx = 0;
1990 	PRT_BEAMFORMING_ENTRY	pEntry;
1991 	BOOLEAN					ret = TRUE;
1992 	PMGNT_INFO				pMgntInfo = &(Adapter->MgntInfo);
1993 	PRT_BEAMFORMING_INFO 	pBeamInfo = GET_BEAMFORM_INFO(Adapter);
1994 	HAL_DATA_TYPE			*pHalData = GET_HAL_DATA(Adapter);
1995 	PDM_ODM_T				pDM_Odm = &pHalData->DM_OutSrc;
1996 
1997 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
1998 
1999 	pEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);
2000 
2001 	if(pEntry->bUsed == FALSE)
2002 	{
2003 		RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Skip Beamforming, no entry for addr = "), RA);
2004 		pEntry->bBeamformingInProgress = FALSE;
2005 		return FALSE;
2006 	}
2007 	else
2008 	{
2009 		 if(pEntry->bBeamformingInProgress)
2010 		 {
2011 		 	RT_DISP(FBEAM, FBEAM_ERROR, ("bBeamformingInProgress, skip...\n"));
2012 			return FALSE;
2013 		 }
2014 
2015 		pEntry->bBeamformingInProgress = TRUE;
2016 
2017 		if(Mode == 1)
2018 		{
2019 			if(!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT))
2020 			{
2021 				RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Skip Beamforming, entry without BEAMFORMEE_CAP_HT_EXPLICIT for addr = "), RA);
2022 				pEntry->bBeamformingInProgress = FALSE;
2023 				return FALSE;
2024 			}
2025 		}
2026 		else if(Mode == 0)
2027 		{
2028 			if(!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_VHT_SU))
2029 			{
2030 				RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Skip Beamforming, entry without BEAMFORMEE_CAP_VHT_SU for addr = "), RA);
2031 				pEntry->bBeamformingInProgress = FALSE;
2032 				return FALSE;
2033 			}
2034 
2035 		}
2036 		if(	pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_INITIALIZED &&
2037 			pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSED)
2038 		{
2039 			RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Skip Beamforming, state without (BEAMFORMING_STATE_INITIALIZED | BEAMFORMING_STATE_PROGRESSED) for addr = "), RA);
2040 			pEntry->bBeamformingInProgress = FALSE;
2041 			return FALSE;
2042 		}
2043 		else
2044 		{
2045 			pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSING;
2046 			pEntry->bSound = TRUE;
2047 		}
2048 	}
2049 
2050 	pEntry->SoundBW = BW;
2051 	pBeamInfo->BeamformeeCurIdx = Idx;
2052 	phydm_Beamforming_NDPARate(pDM_Odm, BW, Rate);
2053 	HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&Idx);
2054 
2055 	if(Mode == 1)
2056 		ret = Beamforming_SendHTNDPAPacket(Adapter,RA, BW, NORMAL_QUEUE);
2057 	else
2058 		ret = Beamforming_SendVHTNDPAPacket(Adapter,RA, pEntry->AID, BW, NORMAL_QUEUE);
2059 
2060 	if(ret == FALSE)
2061 	{
2062 		RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Beamforming_RemoveEntry because of failure sending NDPA for addr = "), RA);
2063 /*		Beamforming_RemoveEntry(Adapter, RA, &Idx);*/
2064 
2065                 RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s calls Beamforming_Leave, RA=0x%x \n", __FUNCTION__,RA) );
2066 		Beamforming_Leave(Adapter, RA);
2067 		pEntry->bBeamformingInProgress = FALSE;
2068 		return FALSE;
2069 	}
2070 
2071 	RT_DISP(FBEAM, FBEAM_FUN, ("%s  Idx %d\n", __FUNCTION__, Idx));
2072 	return TRUE;
2073 }
2074 
2075 
2076 BOOLEAN
BeamformingStart_SW(PADAPTER Adapter,u1Byte Idx,u1Byte Mode,CHANNEL_WIDTH BW)2077 BeamformingStart_SW(
2078 	PADAPTER		Adapter,
2079 	u1Byte			Idx,
2080 	u1Byte			Mode,
2081 	CHANNEL_WIDTH	BW
2082 	)
2083 {
2084 	pu1Byte					RA = NULL;
2085 	PRT_BEAMFORMING_ENTRY	pEntry;
2086 	BOOLEAN					ret = TRUE;
2087 	PMGNT_INFO				pMgntInfo = &(Adapter->MgntInfo);
2088 	PRT_BEAMFORMING_INFO 	pBeamInfo = GET_BEAMFORM_INFO(Adapter);
2089 
2090 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
2091 
2092 	pEntry = &(pBeamInfo->BeamformeeEntry[Idx]);
2093 
2094 	if(pEntry->bUsed == FALSE)
2095 	{
2096 		RT_DISP(FBEAM, FBEAM_ERROR, ("Skip Beamforming, no entry for Idx =%d\n", Idx));
2097 		pEntry->bBeamformingInProgress = FALSE;
2098 		return FALSE;
2099 	}
2100 	else
2101 	{
2102 		 if(pEntry->bBeamformingInProgress)
2103 		 {
2104 		 	RT_DISP(FBEAM, FBEAM_ERROR, ("bBeamformingInProgress, skip...\n"));
2105 			return FALSE;
2106 		 }
2107 
2108 		pEntry->bBeamformingInProgress = TRUE;
2109 
2110 		RA = pEntry->MacAddr;
2111 
2112 		if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_AUTO_HT_TIMER)
2113 		{
2114 			if(!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT))
2115 			{
2116 				RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Skip Beamforming, entry without BEAMFORMEE_CAP_HT_EXPLICIT for addr = "), RA);
2117 				pEntry->bBeamformingInProgress = FALSE;
2118 				return FALSE;
2119 			}
2120 		}
2121 		else if(Mode == SOUNDING_SW_VHT_TIMER || Mode == SOUNDING_HW_VHT_TIMER || Mode == SOUNDING_AUTO_VHT_TIMER)
2122 		{
2123 			if(!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_VHT_SU))
2124 			{
2125 				RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Skip Beamforming, entry without BEAMFORMEE_CAP_VHT_SU for addr = "), RA);
2126 				pEntry->bBeamformingInProgress = FALSE;
2127 				return FALSE;
2128 			}
2129 
2130 		}
2131 		if(	pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_INITIALIZED &&
2132 			pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSED)
2133 		{
2134 			RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Skip Beamforming, state without (BEAMFORMING_STATE_INITIALIZED | BEAMFORMING_STATE_PROGRESSED) for addr = "), RA);
2135 			pEntry->bBeamformingInProgress = FALSE;
2136 			return FALSE;
2137 		}
2138 		else
2139 		{
2140 			pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSING;
2141 			pEntry->bSound = TRUE;
2142 		}
2143 	}
2144 
2145 	pBeamInfo->BeamformeeCurIdx = Idx;
2146 //2014.12.22 Luke: Need to be checked
2147 	/*GET_TXBF_INFO(Adapter)->fTxbfSet(Adapter, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&Idx);*/
2148 
2149 	if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_AUTO_HT_TIMER)
2150 		ret = Beamforming_SendHTNDPAPacket(Adapter,RA, BW, NORMAL_QUEUE);
2151 	else
2152 		ret = Beamforming_SendVHTNDPAPacket(Adapter,RA, pEntry->AID, BW, NORMAL_QUEUE);
2153 
2154 	if(ret == FALSE)
2155 	{
2156 		RT_DISP_ADDR(FBEAM, FBEAM_ERROR, ("Beamforming_RemoveEntry because of failure sending NDPA for addr = "), RA);
2157                 RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s calls Beamforming_Leave, RA=0x%x \n", __FUNCTION__,RA) );
2158 		Beamforming_Leave(Adapter, RA);
2159 		pEntry->bBeamformingInProgress = FALSE;
2160 		return FALSE;
2161 	}
2162 
2163 	if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_AUTO_HT_TIMER)
2164 	{
2165 		RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s: Send HT NDPA for current idx=%d\n", __FUNCTION__, Idx));
2166 	}
2167 	else
2168 	{
2169 		RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s: Send VHT NDPA for current idx=%d\n", __FUNCTION__, Idx));
2170 	}
2171 
2172 	return TRUE;
2173 }
2174 
2175 
2176 BOOLEAN
BeamformingStart_FW(PADAPTER Adapter,u1Byte Idx)2177 BeamformingStart_FW(
2178 	PADAPTER		Adapter,
2179 	u1Byte			Idx
2180 	)
2181 {
2182 	pu1Byte					RA = NULL;
2183 	PRT_BEAMFORMING_ENTRY	pEntry;
2184 	BOOLEAN					ret = TRUE;
2185 	PMGNT_INFO				pMgntInfo = &(Adapter->MgntInfo);
2186 	PRT_BEAMFORMING_INFO 	pBeamInfo = GET_BEAMFORM_INFO(Adapter);
2187 
2188 	pEntry = &(pBeamInfo->BeamformeeEntry[Idx]);
2189 	if(pEntry->bUsed == FALSE)
2190 	{
2191 		RT_DISP(FBEAM, FBEAM_ERROR, ("Skip Beamforming, no entry for Idx =%d\n", Idx));
2192 		return FALSE;
2193 	}
2194 
2195 	pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSING;
2196 	pEntry->bSound = TRUE;
2197 	HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_FW_NDPA, (pu1Byte)&Idx);
2198 
2199 	RT_DISP(FBEAM, FBEAM_FUN, ("@%s End, Idx=0x%X \n", __FUNCTION__, Idx));
2200 	return TRUE;
2201 }
2202 
2203 VOID
Beamforming_CheckSoundingSuccess(PADAPTER Adapter,BOOLEAN Status)2204 Beamforming_CheckSoundingSuccess(
2205 	PADAPTER		Adapter,
2206 	BOOLEAN			Status
2207 )
2208 {
2209 	PMGNT_INFO				pMgntInfo = &(Adapter->MgntInfo);
2210 	PRT_BEAMFORMING_INFO 	pBeamInfo = GET_BEAMFORM_INFO(Adapter);
2211 	PRT_BEAMFORMING_ENTRY	pEntry = &(pBeamInfo->BeamformeeEntry[pBeamInfo->BeamformeeCurIdx]);
2212 	HAL_DATA_TYPE				*pHalData = GET_HAL_DATA(Adapter);
2213 	PDM_ODM_T					pDM_Odm = &pHalData->DM_OutSrc;
2214 
2215 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
2216 
2217 	if(Status == 1){
2218         if(pEntry->LogStatusFailCnt == 21)
2219             Beamforming_DymPeriod(pDM_Odm,Status);
2220 
2221 		pEntry->LogStatusFailCnt = 0;
2222 	}
2223     else if(pEntry->LogStatusFailCnt <= 20){
2224 		pEntry->LogStatusFailCnt++;
2225 		RT_DISP(FBEAM, FBEAM_ERROR, ("%s LogStatusFailCnt %d\n", __FUNCTION__, pEntry->LogStatusFailCnt));
2226 	}
2227 	if(pEntry->LogStatusFailCnt > 20){
2228             pEntry->LogStatusFailCnt = 21;
2229 		RT_DISP(FBEAM, FBEAM_ERROR, ("%s LogStatusFailCnt > 20, Stop SOUNDING\n", __FUNCTION__));
2230             Beamforming_DymPeriod(pDM_Odm,Status);
2231 	}
2232 }
2233 
2234 VOID
phydm_Beamforming_End_SW(IN PVOID pDM_VOID,BOOLEAN Status)2235 phydm_Beamforming_End_SW(
2236 	IN	PVOID		pDM_VOID,
2237 	BOOLEAN			Status
2238 	)
2239 {
2240 	PDM_ODM_T				pDM_Odm = (PDM_ODM_T)pDM_VOID;
2241 	PRT_BEAMFORMING_INFO 	pBeamInfo = &pDM_Odm->BeamformingInfo;
2242 	PRT_BEAMFORMING_ENTRY	pEntry = &(pBeamInfo->BeamformeeEntry[pBeamInfo->BeamformeeCurIdx]);
2243 
2244 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
2245 
2246 	if(pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSING)
2247 	{
2248 		ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s BeamformStatus %d\n", __FUNCTION__, pEntry->BeamformEntryState));
2249 		return;
2250 	}
2251 
2252 	if ((pDM_Odm->TxBfDataRate >= ODM_RATEVHTSS3MCS7) && (pDM_Odm->TxBfDataRate <= ODM_RATEVHTSS3MCS9))
2253 	{
2254 		ODM_RT_TRACE(pDM_Odm, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, VHT3SS 7,8,9, do not apply V matrix.\n", __func__));
2255 		pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;
2256 		HalComTxbf_Set(pDM_Odm->Adapter, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&(pBeamInfo->BeamformeeCurIdx));
2257 	} else if (Status == 1) {
2258 		pEntry->LogStatusFailCnt = 0;
2259 		pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSED;
2260 		HalComTxbf_Set(pDM_Odm->Adapter, TXBF_SET_SOUNDING_STATUS, (pu1Byte)&(pBeamInfo->BeamformeeCurIdx));
2261 	}
2262 	else
2263 	{
2264 		pEntry->LogStatusFailCnt++;
2265 		pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;
2266 		HalComTxbf_Set(pDM_Odm->Adapter, TXBF_SET_TX_PATH_RESET, (pu1Byte)&(pBeamInfo->BeamformeeCurIdx));
2267 		ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s LogStatusFailCnt %d\n", __FUNCTION__, pEntry->LogStatusFailCnt));
2268 	}
2269 	if(pEntry->LogStatusFailCnt > 50)
2270 	{
2271 		RT_DISP(FBEAM, FBEAM_ERROR, ("%s LogStatusFailCnt > 50, Stop SOUNDING\n", __FUNCTION__));
2272 		pEntry->bSound = FALSE;
2273 		Beamforming_DeInitEntry(pDM_Odm->Adapter, pEntry->MacAddr);
2274 
2275 		/*Modified by David - Every action of deleting entry should follow by Notify*/
2276 		phydm_Beamforming_Notify(pDM_Odm);
2277 	}
2278 	pEntry->bBeamformingInProgress = FALSE;
2279 
2280 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: Status=%d\n", __FUNCTION__, Status));
2281 }
2282 
2283 
2284 VOID
phydm_Beamforming_End_FW(IN PVOID pDM_VOID)2285 phydm_Beamforming_End_FW(
2286 	IN	PVOID				pDM_VOID
2287 	)
2288 {
2289 	u1Byte					Idx = 0;
2290 	PDM_ODM_T				pDM_Odm = (PDM_ODM_T)pDM_VOID;
2291 	PADAPTER				Adapter = pDM_Odm->Adapter;
2292 	PRT_BEAMFORMING_INFO 	pBeamInfo = &pDM_Odm->BeamformingInfo;
2293 
2294 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start! \n", __FUNCTION__) );
2295 	HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_FW_NDPA, (pu1Byte)&Idx);
2296 
2297 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s End! \n", __FUNCTION__));
2298 }
2299 
2300 
2301 VOID
Beamforming_TimerCallback(PADAPTER Adapter)2302 Beamforming_TimerCallback(
2303 	PADAPTER			Adapter
2304 	)
2305 {
2306 	BOOLEAN						ret = FALSE;
2307 	PMGNT_INFO					pMgntInfo = &(Adapter->MgntInfo);
2308 	PRT_BEAMFORMING_INFO 		pBeamInfo = GET_BEAMFORM_INFO(Adapter);
2309 	PRT_BEAMFORMING_ENTRY		pEntry = &(pBeamInfo->BeamformeeEntry[pBeamInfo->BeamformeeCurIdx]);
2310 	PRT_SOUNDING_INFO			pSoundInfo = &(pBeamInfo->SoundingInfo);
2311 	HAL_DATA_TYPE				*pHalData = GET_HAL_DATA(Adapter);
2312 	PDM_ODM_T					pDM_Odm = &pHalData->DM_OutSrc;
2313 
2314 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
2315 
2316 	if(pEntry->bBeamformingInProgress)
2317 	 {
2318 	 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("bBeamformingInProgress, reset it\n"));
2319 		phydm_Beamforming_End_SW(pDM_Odm, 0);
2320 	 }
2321 
2322 	ret = phydm_Beamforming_SelectBeamEntry(pDM_Odm, pBeamInfo);
2323 
2324 	if(ret)
2325 		ret = BeamformingStart_SW(Adapter,pSoundInfo->SoundIdx, pSoundInfo->SoundMode, pSoundInfo->SoundBW);
2326 
2327 	if(ret)
2328 		;
2329 	else
2330 	{
2331 		ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, Error value return from BeamformingStart_V2 \n", __FUNCTION__));
2332 	}
2333 
2334 	if(pBeamInfo->BeamformState >= BEAMFORMING_STATE_START_1BFee)
2335 	{
2336 		if(pSoundInfo->SoundMode == SOUNDING_SW_VHT_TIMER || pSoundInfo->SoundMode == SOUNDING_SW_HT_TIMER)
2337 			ODM_SetTimer(pDM_Odm, &pBeamInfo->BeamformingTimer, pSoundInfo->SoundPeriod);
2338 		else
2339 		{
2340 			u4Byte	val = (pSoundInfo->SoundPeriod << 16) | HAL_TIMER_TXBF;
2341 			Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_HW_REG_TIMER_RESTART, (pu1Byte)(&val));
2342 		}
2343 	}
2344 }
2345 
2346 
2347 VOID
Beamforming_SWTimerCallback(PRT_TIMER pTimer)2348 Beamforming_SWTimerCallback(
2349 	PRT_TIMER		pTimer
2350 	)
2351 {
2352 	PADAPTER	Adapter=(PADAPTER)pTimer->Adapter;
2353 
2354 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start!\n", __FUNCTION__) );
2355 
2356 	Beamforming_TimerCallback(Adapter);
2357 }
2358 
2359 
2360 VOID
phydm_Beamforming_Init(IN PVOID pDM_VOID)2361 phydm_Beamforming_Init(
2362 	IN	PVOID				pDM_VOID
2363 	)
2364 {
2365 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
2366 	PRT_BEAMFORMING_INFO 		pBeamInfo = &pDM_Odm->BeamformingInfo;
2367 	PHAL_TXBF_INFO				pTxbfInfo = &pBeamInfo->TxbfInfo;
2368 	PRT_BEAMFORMING_OID_INFO	pBeamOidInfo = &(pBeamInfo->BeamformingOidInfo);
2369 
2370 	RT_DISP(FBEAM, FBEAM_FUN, ("%s Start!\n", __FUNCTION__) );
2371 
2372 	pBeamOidInfo->SoundOidMode = SOUNDING_STOP_OID_TIMER;
2373 	RT_DISP(FBEAM, FBEAM_FUN, ("%s Mode (%d)\n", __FUNCTION__, pBeamOidInfo->SoundOidMode));
2374 }
2375 
2376 
2377 VOID
Beamforming_Enter(PADAPTER Adapter,PRT_WLAN_STA pSTA)2378 Beamforming_Enter(
2379 	PADAPTER		Adapter,
2380 	PRT_WLAN_STA	pSTA
2381 )
2382 {
2383 	u1Byte	BFerBFeeIdx = 0xff;
2384 
2385 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s Start! \n", __FUNCTION__) );
2386 
2387 	if(Beamforming_InitEntry(Adapter, pSTA, &BFerBFeeIdx))
2388 		HalComTxbf_Set(Adapter, TXBF_SET_SOUNDING_ENTER, (pu1Byte)&BFerBFeeIdx);
2389 
2390 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End! \n", __FUNCTION__) );
2391 }
2392 
2393 
2394 VOID
Beamforming_Leave(PADAPTER Adapter,pu1Byte RA)2395 Beamforming_Leave(
2396 	PADAPTER		Adapter,
2397 	pu1Byte			RA
2398 	)
2399 {
2400 	HAL_DATA_TYPE				*pHalData = GET_HAL_DATA(Adapter);
2401 	PDM_ODM_T					pDM_Odm = &pHalData->DM_OutSrc;
2402 
2403 	RT_DISP(FBEAM, FBEAM_FUN, ("[Beamforming]@%s Start! \n", __FUNCTION__) );
2404 
2405 	if(RA == NULL)
2406 		Beamforming_Reset(Adapter);
2407 	else
2408 		Beamforming_DeInitEntry(Adapter, RA);
2409 
2410 	phydm_Beamforming_Notify(pDM_Odm);
2411 
2412 	RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End!! \n", __FUNCTION__));
2413 }
2414 
2415 //Nobody calls this function
2416 VOID
phydm_Beamforming_SetTxBFen(IN PVOID pDM_VOID,u1Byte MacId,BOOLEAN bTxBF)2417 phydm_Beamforming_SetTxBFen(
2418 	IN	PVOID		pDM_VOID,
2419 	u1Byte			MacId,
2420 	BOOLEAN			bTxBF
2421 	)
2422 {
2423 	PDM_ODM_T				pDM_Odm = (PDM_ODM_T)pDM_VOID;
2424 	u1Byte					Idx = 0;
2425 	PRT_BEAMFORMING_ENTRY	pEntry;
2426 
2427 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
2428 
2429 	pEntry = phydm_Beamforming_GetEntryByMacId(pDM_Odm, MacId, &Idx);
2430 
2431 	if(pEntry == NULL)
2432 		return;
2433 	else
2434 		pEntry->bTxBF = bTxBF;
2435 
2436 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s MacId %d TxBF %d\n", __FUNCTION__, pEntry->MacId, pEntry->bTxBF));
2437 
2438 	phydm_Beamforming_Notify(pDM_Odm);
2439 }
2440 
2441 
2442 BEAMFORMING_CAP
phydm_Beamforming_GetBeamCap(IN PVOID pDM_VOID,IN PRT_BEAMFORMING_INFO pBeamInfo)2443 phydm_Beamforming_GetBeamCap(
2444 	IN	PVOID		pDM_VOID,
2445 	IN PRT_BEAMFORMING_INFO 	pBeamInfo
2446 	)
2447 {
2448 	u1Byte					i;
2449 	BOOLEAN 				bSelfBeamformer = FALSE;
2450 	BOOLEAN 				bSelfBeamformee = FALSE;
2451 	RT_BEAMFORMING_ENTRY	BeamformeeEntry;
2452 	RT_BEAMFORMER_ENTRY	BeamformerEntry;
2453 	BEAMFORMING_CAP 		BeamformCap = BEAMFORMING_CAP_NONE;
2454 	PDM_ODM_T				pDM_Odm = (PDM_ODM_T)pDM_VOID;
2455 
2456 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[Beamforming]%s Start!\n", __FUNCTION__) );
2457 
2458 	/*
2459 	for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
2460 	{
2461 		BeamformEntry = pBeamInfo->BeamformeeEntry[i];
2462 
2463 		if(BeamformEntry.bUsed)
2464 		{
2465 			if( (BeamformEntry.BeamformEntryCap & BEAMFORMEE_CAP_VHT_SU) ||
2466 				(BeamformEntry.BeamformEntryCap & BEAMFORMEE_CAP_HT_EXPLICIT))
2467 				bSelfBeamformee = TRUE;
2468 			if( (BeamformEntry.BeamformEntryCap & BEAMFORMER_CAP_VHT_SU) ||
2469 				(BeamformEntry.BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT))
2470 				bSelfBeamformer = TRUE;
2471 		}
2472 
2473 		if(bSelfBeamformer && bSelfBeamformee)
2474 			i = BEAMFORMEE_ENTRY_NUM;
2475 	}
2476 	*/
2477 
2478 	for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
2479 	{
2480 		BeamformeeEntry = pBeamInfo->BeamformeeEntry[i];
2481 
2482 		if(BeamformeeEntry.bUsed)
2483 		{
2484 			bSelfBeamformer = TRUE;
2485 			ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[Beamforming]%s: BFee entry %d bUsed=TRUE \n", __FUNCTION__, i));
2486 			break;
2487 		}
2488 
2489 	}
2490 
2491 	for(i = 0; i < BEAMFORMER_ENTRY_NUM; i++)
2492 	{
2493 		BeamformerEntry = pBeamInfo->BeamformerEntry[i];
2494 
2495 		if(BeamformerEntry.bUsed)
2496 		{
2497 			bSelfBeamformee = TRUE;
2498 			ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[Beamforming]%s: BFer entry %d bUsed=TRUE \n", __FUNCTION__, i));
2499 			break;
2500 		}
2501 	}
2502 
2503 	if(bSelfBeamformer)
2504 		BeamformCap = (BEAMFORMING_CAP)(BeamformCap | BEAMFORMER_CAP);
2505 	if(bSelfBeamformee)
2506 		BeamformCap = (BEAMFORMING_CAP)(BeamformCap | BEAMFORMEE_CAP);
2507 
2508 	return BeamformCap;
2509 }
2510 
2511 
2512 BOOLEAN
BeamformingControl_V1(PADAPTER Adapter,pu1Byte RA,u1Byte AID,u1Byte Mode,CHANNEL_WIDTH BW,u1Byte Rate)2513 BeamformingControl_V1(
2514 	PADAPTER		Adapter,
2515 	pu1Byte			RA,
2516 	u1Byte			AID,
2517 	u1Byte			Mode,
2518 	CHANNEL_WIDTH	BW,
2519 	u1Byte			Rate
2520 	)
2521 {
2522 	BOOLEAN		ret = TRUE;
2523 	HAL_DATA_TYPE			*pHalData = GET_HAL_DATA(Adapter);
2524 	PDM_ODM_T				pDM_Odm = &pHalData->DM_OutSrc;
2525 
2526 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
2527 
2528 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("AID (%d), Mode (%d), BW (%d)\n", AID, Mode, BW));
2529 
2530 	RT_DISP_ADDR(FBEAM, FBEAM_FUN, ("Addr = "), RA);
2531 
2532 	switch(Mode){
2533 	case 0:
2534 		ret = BeamformingStart_V1(Adapter, RA, 0, BW, Rate);
2535 		break;
2536 	case 1:
2537 		ret = BeamformingStart_V1(Adapter, RA, 1, BW, Rate);
2538 		break;
2539 	case 2:
2540 		phydm_Beamforming_NDPARate(pDM_Odm, BW, Rate);
2541 		ret = Beamforming_SendVHTNDPAPacket(Adapter,RA, AID, BW, NORMAL_QUEUE);
2542 		break;
2543 	case 3:
2544 		phydm_Beamforming_NDPARate(pDM_Odm, BW, Rate);
2545 		ret = Beamforming_SendHTNDPAPacket(Adapter, RA, BW, NORMAL_QUEUE);
2546 		break;
2547 	}
2548 	return ret;
2549 }
2550 
2551 //Only OID uses this function
2552 BOOLEAN
phydm_BeamformingControl_V2(IN PVOID pDM_VOID,u1Byte Idx,u1Byte Mode,CHANNEL_WIDTH BW,u2Byte Period)2553 phydm_BeamformingControl_V2(
2554 	IN	PVOID		pDM_VOID,
2555 	u1Byte			Idx,
2556 	u1Byte			Mode,
2557 	CHANNEL_WIDTH	BW,
2558 	u2Byte			Period
2559 	)
2560 {
2561 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
2562 	PRT_BEAMFORMING_INFO		pBeamInfo =  &pDM_Odm->BeamformingInfo;
2563 	PRT_BEAMFORMING_OID_INFO	pBeamOidInfo = &(pBeamInfo->BeamformingOidInfo);
2564 
2565 
2566 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
2567 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("Idx (%d), Mode (%d), BW (%d), Period (%d)\n", Idx, Mode, BW, Period));
2568 
2569 	pBeamOidInfo->SoundOidIdx = Idx;
2570 	pBeamOidInfo->SoundOidMode = (SOUNDING_MODE) Mode;
2571 	pBeamOidInfo->SoundOidBW = BW;
2572 	pBeamOidInfo->SoundOidPeriod = Period;
2573 
2574 	phydm_Beamforming_Notify(pDM_Odm);
2575 
2576 	return TRUE;
2577 }
2578 
2579 
2580 VOID
phydm_Beamforming_Watchdog(IN PVOID pDM_VOID)2581 phydm_Beamforming_Watchdog(
2582 	IN	PVOID		pDM_VOID
2583 )
2584 {
2585 	PDM_ODM_T					pDM_Odm = (PDM_ODM_T)pDM_VOID;
2586 	PRT_BEAMFORMING_INFO 		pBeamInfo = &pDM_Odm->BeamformingInfo;
2587 	PADAPTER					Adapter = pDM_Odm->Adapter;
2588 
2589 	ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Start!\n", __FUNCTION__) );
2590 
2591 	if(pBeamInfo->BeamformState < BEAMFORMING_STATE_START_1BFee)
2592 		return;
2593 
2594 	Beamforming_DymPeriod(pDM_Odm,0);
2595 	phydm_Beamforming_DymNDPARate(pDM_Odm);
2596 
2597 }
2598 
2599 
2600 #endif
2601