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