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