net: wireless: rockchip: add rtl8822be pcie wifi driver
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8822be / hal / phydm / txbf / haltxbfinterface.c
1 //============================================================\r
2 // Description:\r
3 //\r
4 // This file is for TXBF interface mechanism\r
5 //\r
6 //============================================================\r
7 #include "mp_precomp.h"\r
8 #include "../phydm_precomp.h"\r
9 \r
10 #if (BEAMFORMING_SUPPORT == 1)\r
11 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
12 VOID\r
13 Beamforming_GidPAid(\r
14         PADAPTER        Adapter,\r
15         PRT_TCB         pTcb\r
16 )\r
17 {\r
18         u1Byte          Idx = 0;\r
19         u1Byte          RA[6] ={0};\r
20         pu1Byte         pHeader = GET_FRAME_OF_FIRST_FRAG(Adapter, pTcb);\r
21         HAL_DATA_TYPE                   *pHalData = GET_HAL_DATA(Adapter);\r
22         PDM_ODM_T                               pDM_Odm = &pHalData->DM_OutSrc;\r
23         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
24 \r
25         if (Adapter->HardwareType < HARDWARE_TYPE_RTL8192EE)\r
26                 return;\r
27         else if (IS_WIRELESS_MODE_N(Adapter) == FALSE)\r
28                 return;\r
29 \r
30 #if (SUPPORT_MU_BF == 1)\r
31         if (pTcb->TxBFPktType == RT_BF_PKT_TYPE_BROADCAST_NDPA) { /* MU NDPA */\r
32 #else\r
33         if (0) {\r
34 #endif\r
35                 /* Fill G_ID and P_AID */\r
36                 pTcb->G_ID = 63;\r
37                 if (pBeamInfo->FirstMUBFeeIndex < BEAMFORMEE_ENTRY_NUM) {\r
38                         pTcb->P_AID = pBeamInfo->BeamformeeEntry[pBeamInfo->FirstMUBFeeIndex].P_AID;                    \r
39                         RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End, G_ID=0x%X, P_AID=0x%X\n", __func__, pTcb->G_ID, pTcb->P_AID));\r
40                 }\r
41         } else {\r
42                 GET_80211_HDR_ADDRESS1(pHeader, &RA);\r
43 \r
44                 // VHT SU PPDU carrying one or more group addressed MPDUs or\r
45                 // Transmitting a VHT NDP intended for multiple recipients\r
46                 if (MacAddr_isBcst(RA) || MacAddr_isMulticast(RA)       || pTcb->macId == MAC_ID_STATIC_FOR_BROADCAST_MULTICAST) {\r
47                         pTcb->G_ID = 63;\r
48                         pTcb->P_AID = 0;\r
49                 } else if (ACTING_AS_AP(Adapter)) {\r
50                         u2Byte  AID = (u2Byte) (MacIdGetOwnerAssociatedClientAID(Adapter, pTcb->macId) & 0x1ff);                /*AID[0:8]*/\r
51         \r
52                         /*RT_DISP(FBEAM, FBEAM_FUN, ("@%s  pTcb->macId=0x%X, AID=0x%X\n", __func__, pTcb->macId, AID));*/\r
53                         pTcb->G_ID = 63;\r
54 \r
55                         if (AID == 0)           /*A PPDU sent by an AP to a non associated STA*/\r
56                                 pTcb->P_AID = 0;\r
57                         else {                          /*Sent by an AP and addressed to a STA associated with that AP*/\r
58                                 u2Byte  BSSID = 0;\r
59                                 GET_80211_HDR_ADDRESS2(pHeader, &RA);\r
60                                 BSSID = ((RA[5] & 0xf0) >> 4) ^ (RA[5] & 0xf);  /*BSSID[44:47] xor BSSID[40:43]*/\r
61                                 pTcb->P_AID = (AID + BSSID *32) & 0x1ff;                /*(dec(A) + dec(B)*32) mod 512*/\r
62                         }\r
63                 } else if (ACTING_AS_IBSS(Adapter)) {\r
64                         pTcb->G_ID = 63;\r
65                         /*P_AID for infrasturcture mode; MACID for ad-hoc mode. */\r
66                         pTcb->P_AID = pTcb->macId;\r
67                 } else if (MgntLinkStatusQuery(Adapter)) {                              /*Addressed to AP*/\r
68                         pTcb->G_ID = 0;\r
69                         GET_80211_HDR_ADDRESS1(pHeader, &RA);\r
70                         pTcb->P_AID =  RA[5];                                                   /*RA[39:47]*/\r
71                         pTcb->P_AID = (pTcb->P_AID << 1) | (RA[4] >> 7 );\r
72                 } else {\r
73                         pTcb->G_ID = 63;\r
74                         pTcb->P_AID = 0;\r
75                 }\r
76                 /*RT_DISP(FBEAM, FBEAM_FUN, ("[David]@%s End, G_ID=0x%X, P_AID=0x%X\n", __func__, pTcb->G_ID, pTcb->P_AID));*/\r
77         }\r
78 }\r
79 \r
80 \r
81 RT_STATUS\r
82 Beamforming_GetReportFrame(\r
83         IN      PADAPTER                Adapter,\r
84         IN      PRT_RFD                 pRfd,\r
85         IN      POCTET_STRING   pPduOS\r
86         )\r
87 {\r
88         HAL_DATA_TYPE                           *pHalData = GET_HAL_DATA(Adapter);\r
89         PDM_ODM_T                                       pDM_Odm = &pHalData->DM_OutSrc;\r
90         PRT_BEAMFORMEE_ENTRY            pBeamformEntry = NULL;\r
91         pu1Byte                                         pMIMOCtrlField, pCSIReport, pCSIMatrix;\r
92         u1Byte                                          Idx, Nc, Nr, CH_W;\r
93         u2Byte                                          CSIMatrixLen = 0;\r
94 \r
95         ACT_PKT_TYPE                            pktType = ACT_PKT_TYPE_UNKNOWN;\r
96 \r
97         //Memory comparison to see if CSI report is the same with previous one\r
98         pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, Frame_Addr2(*pPduOS), &Idx);\r
99 \r
100         if (pBeamformEntry == NULL) {\r
101                 ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("Beamforming_GetReportFrame: Cannot find entry by addr\n"));\r
102                 return RT_STATUS_FAILURE;\r
103         }\r
104 \r
105         pktType = PacketGetActionFrameType(pPduOS);\r
106         \r
107         //-@ Modified by David\r
108         if (pktType == ACT_PKT_VHT_COMPRESSED_BEAMFORMING) {\r
109                 pMIMOCtrlField = pPduOS->Octet + 26; \r
110                 Nc = ((*pMIMOCtrlField) & 0x7) + 1;\r
111                 Nr = (((*pMIMOCtrlField) & 0x38) >> 3) + 1;\r
112                 CH_W =  (((*pMIMOCtrlField) & 0xC0) >> 6);\r
113                 pCSIMatrix = pMIMOCtrlField + 3 + Nc; //24+(1+1+3)+2  MAC header+(Category+ActionCode+MIMOControlField) +SNR(Nc=2)\r
114                 CSIMatrixLen = pPduOS->Length  - 26 -3 -Nc;\r
115         } else if (pktType == ACT_PKT_HT_COMPRESSED_BEAMFORMING) {\r
116                 pMIMOCtrlField = pPduOS->Octet + 26; \r
117                 Nc = ((*pMIMOCtrlField) & 0x3) + 1;\r
118                 Nr =  (((*pMIMOCtrlField) & 0xC) >> 2) + 1;\r
119                 CH_W =  (((*pMIMOCtrlField) & 0x10) >> 4);\r
120                 pCSIMatrix = pMIMOCtrlField + 6 + Nr;   //24+(1+1+6)+2  MAC header+(Category+ActionCode+MIMOControlField) +SNR(Nc=2)\r
121                 CSIMatrixLen = pPduOS->Length  - 26 -6 -Nr;\r
122         } else\r
123                 return RT_STATUS_SUCCESS;       \r
124         \r
125         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] idx=%d, pkt type=%d, Nc=%d, Nr=%d, CH_W=%d\n", __func__, Idx, pktType, Nc, Nr, CH_W));              \r
126 \r
127         return RT_STATUS_SUCCESS;\r
128 }\r
129 \r
130 \r
131 VOID\r
132 ConstructHTNDPAPacket(\r
133         PADAPTER                Adapter,\r
134         pu1Byte                 RA,\r
135         pu1Byte                 Buffer,\r
136         pu4Byte                 pLength,\r
137         CHANNEL_WIDTH   BW\r
138         )\r
139 {\r
140         u2Byte                                  Duration= 0;\r
141         PMGNT_INFO                              pMgntInfo = &(Adapter->MgntInfo);\r
142         OCTET_STRING                    pNDPAFrame,ActionContent;\r
143         u1Byte                                  ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};\r
144 \r
145         PlatformZeroMemory(Buffer, 32);\r
146 \r
147         SET_80211_HDR_FRAME_CONTROL(Buffer,0);\r
148 \r
149         SET_80211_HDR_ORDER(Buffer, 1);\r
150         SET_80211_HDR_TYPE_AND_SUBTYPE(Buffer,Type_Action_No_Ack);\r
151 \r
152         SET_80211_HDR_ADDRESS1(Buffer, RA);\r
153         SET_80211_HDR_ADDRESS2(Buffer, Adapter->CurrentAddress);\r
154         SET_80211_HDR_ADDRESS3(Buffer, pMgntInfo->Bssid);\r
155 \r
156         Duration = 2*aSifsTime + 40;\r
157         \r
158         if (BW == CHANNEL_WIDTH_40)\r
159                 Duration+= 87;\r
160         else    \r
161                 Duration+= 180;\r
162 \r
163         SET_80211_HDR_DURATION(Buffer, Duration);\r
164 \r
165         //HT control field\r
166         SET_HT_CTRL_CSI_STEERING(Buffer+sMacHdrLng, 3);\r
167         SET_HT_CTRL_NDP_ANNOUNCEMENT(Buffer+sMacHdrLng, 1);\r
168         \r
169         FillOctetString(pNDPAFrame, Buffer, sMacHdrLng+sHTCLng);\r
170 \r
171         FillOctetString(ActionContent, ActionHdr, 4);\r
172         PacketAppendData(&pNDPAFrame, ActionContent);   \r
173 \r
174         *pLength = 32;\r
175 }\r
176 \r
177 \r
178 \r
179 \r
180 BOOLEAN\r
181 SendFWHTNDPAPacket(\r
182         IN      PVOID                   pDM_VOID,\r
183         IN      pu1Byte                 RA,\r
184         IN      CHANNEL_WIDTH   BW\r
185         )\r
186 {\r
187         PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
188         PADAPTER                                Adapter = pDM_Odm->Adapter;\r
189         PRT_TCB                                 pTcb;\r
190         PRT_TX_LOCAL_BUFFER     pBuf;\r
191         BOOLEAN                                 ret = TRUE;\r
192         u4Byte                                  BufLen;\r
193         pu1Byte                                 BufAddr;\r
194         u1Byte                                  DescLen = 0, Idx = 0, NDPTxRate;\r
195         PADAPTER                                pDefAdapter = GetDefaultAdapter(Adapter);\r
196         PRT_BEAMFORMING_INFO    pBeamInfo = &pDM_Odm->BeamformingInfo;\r
197         HAL_DATA_TYPE                   *pHalData = GET_HAL_DATA(Adapter);\r
198         PRT_BEAMFORMEE_ENTRY    pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
199 \r
200         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));\r
201 \r
202         if (pBeamformEntry == NULL)\r
203                 return FALSE;\r
204 \r
205         NDPTxRate = Beamforming_GetHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
206         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
207         PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
208 \r
209         if (MgntGetFWBuffer(pDefAdapter, &pTcb, &pBuf)) {\r
210 #if(DEV_BUS_TYPE != RT_PCI_INTERFACE)\r
211                 DescLen = Adapter->HWDescHeadLength - pHalData->USBALLDummyLength;\r
212 #endif\r
213                 BufAddr = pBuf->Buffer.VirtualAddress + DescLen;\r
214 \r
215                 ConstructHTNDPAPacket(\r
216                                 Adapter, \r
217                                 RA,\r
218                                 BufAddr, \r
219                                 &BufLen,\r
220                                 BW\r
221                                 );\r
222 \r
223                 pTcb->PacketLength = BufLen + DescLen;\r
224 \r
225                 pTcb->bTxEnableSwCalcDur = TRUE;\r
226                 \r
227                 pTcb->BWOfPacket = BW;\r
228 \r
229                 if(ACTING_AS_IBSS(Adapter) || ACTING_AS_AP(Adapter))\r
230                         pTcb->G_ID = 63;\r
231 \r
232                 pTcb->P_AID = pBeamformEntry->P_AID;\r
233                 pTcb->DataRate = NDPTxRate;     /*rate of NDP decide by Nr*/\r
234 \r
235                 Adapter->HalFunc.CmdSendPacketHandler(Adapter, pTcb, pBuf, pTcb->PacketLength, DESC_PACKET_TYPE_NORMAL, FALSE);\r
236         } else\r
237                 ret = FALSE;\r
238 \r
239         PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);\r
240         \r
241         if (ret)\r
242                 RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
243 \r
244         return ret;\r
245 }\r
246 \r
247 \r
248 BOOLEAN\r
249 SendSWHTNDPAPacket(\r
250         IN      PVOID                   pDM_VOID,\r
251         IN      pu1Byte                 RA,\r
252         IN      CHANNEL_WIDTH   BW\r
253         )\r
254 {\r
255         PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
256         PADAPTER                                Adapter = pDM_Odm->Adapter;\r
257         PRT_TCB                                 pTcb;\r
258         PRT_TX_LOCAL_BUFFER             pBuf;\r
259         BOOLEAN                                 ret = TRUE;\r
260         u1Byte                                  Idx = 0, NDPTxRate = 0;\r
261         PRT_BEAMFORMING_INFO    pBeamInfo = &pDM_Odm->BeamformingInfo;\r
262         PRT_BEAMFORMEE_ENTRY    pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
263 \r
264         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));\r
265 \r
266         NDPTxRate = Beamforming_GetHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
267         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
268         \r
269         PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
270 \r
271         if (MgntGetBuffer(Adapter, &pTcb, &pBuf)) {\r
272                 ConstructHTNDPAPacket(\r
273                                 Adapter, \r
274                                 RA,\r
275                                 pBuf->Buffer.VirtualAddress, \r
276                                 &pTcb->PacketLength,\r
277                                 BW\r
278                                 );\r
279 \r
280                 pTcb->bTxEnableSwCalcDur = TRUE;\r
281 \r
282                 pTcb->BWOfPacket = BW;\r
283 \r
284                 MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, NDPTxRate);\r
285         } else\r
286                 ret = FALSE;\r
287         \r
288         PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);\r
289 \r
290         if (ret)\r
291                 RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
292 \r
293         return ret;\r
294 }\r
295 \r
296 \r
297 \r
298 VOID\r
299 ConstructVHTNDPAPacket(\r
300         IN PDM_ODM_T    pDM_Odm,\r
301         pu1Byte                 RA,\r
302         u2Byte                  AID,\r
303         pu1Byte                 Buffer,\r
304         pu4Byte                 pLength,\r
305         CHANNEL_WIDTH   BW\r
306         )\r
307 {\r
308         u2Byte                                  Duration= 0;\r
309         u1Byte                                  Sequence = 0;\r
310         pu1Byte                                 pNDPAFrame = Buffer;\r
311         RT_NDPA_STA_INFO                STAInfo;\r
312         PADAPTER                                Adapter = pDM_Odm->Adapter;\r
313         u1Byte  Idx = 0;\r
314         PRT_BEAMFORMEE_ENTRY    pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
315         // Frame control.\r
316         SET_80211_HDR_FRAME_CONTROL(pNDPAFrame, 0);\r
317         SET_80211_HDR_TYPE_AND_SUBTYPE(pNDPAFrame, Type_NDPA);\r
318 \r
319         SET_80211_HDR_ADDRESS1(pNDPAFrame, RA);\r
320         SET_80211_HDR_ADDRESS2(pNDPAFrame, pBeamformEntry->MyMacAddr);\r
321 \r
322         Duration = 2*aSifsTime + 44;\r
323         \r
324         if (BW == CHANNEL_WIDTH_80)\r
325                 Duration += 40;\r
326         else if(BW == CHANNEL_WIDTH_40)\r
327                 Duration+= 87;\r
328         else    \r
329                 Duration+= 180;\r
330 \r
331         SET_80211_HDR_DURATION(pNDPAFrame, Duration);\r
332 \r
333         Sequence = *(pDM_Odm->pSoundingSeq) << 2;\r
334         ODM_MoveMemory(pDM_Odm, pNDPAFrame+16, &Sequence, 1);\r
335 \r
336         if (phydm_actingDetermine(pDM_Odm, PhyDM_ACTING_AS_IBSS) || phydm_actingDetermine(pDM_Odm, PhyDM_ACTING_AS_AP) == FALSE)\r
337                 AID = 0;\r
338 \r
339         STAInfo.AID = AID;\r
340         STAInfo.FeedbackType = 0;\r
341         STAInfo.NcIndex = 0;\r
342         \r
343         ODM_MoveMemory(pDM_Odm, pNDPAFrame+17, (pu1Byte)&STAInfo, 2);\r
344 \r
345         *pLength = 19;\r
346 }\r
347 \r
348 \r
349 BOOLEAN\r
350 SendFWVHTNDPAPacket(\r
351         IN      PVOID                   pDM_VOID,\r
352         IN      pu1Byte                 RA,\r
353         IN      u2Byte                  AID,\r
354         IN      CHANNEL_WIDTH   BW\r
355         )\r
356 {\r
357         PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
358         PADAPTER                                Adapter = pDM_Odm->Adapter;\r
359         PRT_TCB                                 pTcb;\r
360         PRT_TX_LOCAL_BUFFER             pBuf;\r
361         BOOLEAN                                 ret = TRUE;\r
362         u4Byte                                  BufLen;\r
363         pu1Byte                                 BufAddr;\r
364         u1Byte                                  DescLen = 0, Idx = 0, NDPTxRate = 0;\r
365         PADAPTER                                pDefAdapter = GetDefaultAdapter(Adapter);\r
366         PRT_BEAMFORMING_INFO    pBeamInfo = &pDM_Odm->BeamformingInfo;\r
367         HAL_DATA_TYPE                   *pHalData = GET_HAL_DATA(Adapter);\r
368         PRT_BEAMFORMEE_ENTRY    pBeamformEntry =phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
369 \r
370         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));\r
371 \r
372         if (pBeamformEntry == NULL)\r
373                 return FALSE;\r
374 \r
375         NDPTxRate = Beamforming_GetVHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
376         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
377         \r
378         PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
379 \r
380         if (MgntGetFWBuffer(pDefAdapter, &pTcb, &pBuf)) {\r
381 #if(DEV_BUS_TYPE != RT_PCI_INTERFACE)\r
382                 DescLen = Adapter->HWDescHeadLength - pHalData->USBALLDummyLength;\r
383 #endif\r
384                 BufAddr = pBuf->Buffer.VirtualAddress + DescLen;\r
385 \r
386                 ConstructVHTNDPAPacket(\r
387                                 pDM_Odm, \r
388                                 RA,\r
389                                 AID,\r
390                                 BufAddr, \r
391                                 &BufLen,\r
392                                 BW\r
393                                 );\r
394                 \r
395                 pTcb->PacketLength = BufLen + DescLen;\r
396 \r
397                 pTcb->bTxEnableSwCalcDur = TRUE;\r
398                 \r
399                 pTcb->BWOfPacket = BW;\r
400 \r
401                 if (phydm_actingDetermine(pDM_Odm, PhyDM_ACTING_AS_IBSS) || phydm_actingDetermine(pDM_Odm, PhyDM_ACTING_AS_AP))\r
402                         pTcb->G_ID = 63;\r
403 \r
404                 pTcb->P_AID = pBeamformEntry->P_AID;\r
405                 pTcb->DataRate = NDPTxRate;     /*decide by Nr*/\r
406 \r
407                 Adapter->HalFunc.CmdSendPacketHandler(Adapter, pTcb, pBuf, pTcb->PacketLength, DESC_PACKET_TYPE_NORMAL, FALSE);\r
408         } else\r
409                 ret = FALSE;\r
410         \r
411         PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);       \r
412 \r
413         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] End, ret=%d\n", __func__, ret));\r
414 \r
415         if (ret)\r
416                 RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
417 \r
418         return ret;\r
419 }\r
420 \r
421 \r
422 \r
423 BOOLEAN\r
424 SendSWVHTNDPAPacket(\r
425         IN      PVOID                   pDM_VOID,\r
426         IN      pu1Byte                 RA,\r
427         IN      u2Byte                  AID,\r
428         IN      CHANNEL_WIDTH   BW\r
429         )\r
430 {\r
431         PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
432         PADAPTER                                Adapter = pDM_Odm->Adapter;\r
433         PRT_TCB                                 pTcb;\r
434         PRT_TX_LOCAL_BUFFER             pBuf;\r
435         BOOLEAN                                 ret = TRUE;\r
436         u1Byte                                  Idx = 0, NDPTxRate = 0;\r
437         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
438         PRT_BEAMFORMEE_ENTRY    pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
439 \r
440         NDPTxRate = Beamforming_GetVHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
441         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
442 \r
443         PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
444 \r
445         if (MgntGetBuffer(Adapter, &pTcb, &pBuf)) {\r
446                 ConstructVHTNDPAPacket(\r
447                                 pDM_Odm, \r
448                                 RA,\r
449                                 AID,\r
450                                 pBuf->Buffer.VirtualAddress, \r
451                                 &pTcb->PacketLength,\r
452                                 BW\r
453                                 );\r
454 \r
455                 pTcb->bTxEnableSwCalcDur = TRUE;\r
456                 pTcb->BWOfPacket = BW;\r
457 \r
458                 /*rate of NDP decide by Nr*/\r
459                 MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, NDPTxRate);\r
460         } else\r
461                 ret = FALSE;\r
462         \r
463         PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);       \r
464 \r
465         if (ret)\r
466                 RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
467 \r
468         return ret;\r
469 }\r
470 \r
471 #ifdef SUPPORT_MU_BF\r
472 #if (SUPPORT_MU_BF == 1)\r
473 /*\r
474 // Description: On VHT GID management frame by an MU beamformee.\r
475 //\r
476 // 2015.05.20. Created by tynli.\r
477 */\r
478 RT_STATUS\r
479 Beamforming_GetVHTGIDMgntFrame(\r
480         IN      PADAPTER                Adapter,\r
481         IN      PRT_RFD                 pRfd,\r
482         IN      POCTET_STRING   pPduOS\r
483         )\r
484 {\r
485         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(Adapter);\r
486         PDM_ODM_T               pDM_Odm = &pHalData->DM_OutSrc;\r
487         RT_STATUS               rtStatus = RT_STATUS_SUCCESS;\r
488         pu1Byte                 pBuffer = NULL;\r
489         pu1Byte                 pRaddr = NULL;\r
490         u1Byte                  MemStatus[8] = {0}, UserPos[16] = {0};\r
491         u1Byte                  idx;\r
492         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
493         PRT_BEAMFORMER_ENTRY    pBeamformEntry = &pBeamInfo->BeamformerEntry[pBeamInfo->mu_ap_index];\r
494 \r
495         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] On VHT GID mgnt frame!\n", __func__));              \r
496 \r
497         /* Check length*/\r
498         if (pPduOS->Length < (FRAME_OFFSET_VHT_GID_MGNT_USER_POSITION_ARRAY+16)) {      \r
499                 ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("Beamforming_GetVHTGIDMgntFrame(): Invalid length (%d)\n", pPduOS->Length));\r
500                 return RT_STATUS_INVALID_LENGTH;\r
501         }\r
502 \r
503         /* Check RA*/\r
504         pRaddr = (pu1Byte)(pPduOS->Octet)+4;\r
505         if (!eqMacAddr(pRaddr, Adapter->CurrentAddress)) {              \r
506                 ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("Beamforming_GetVHTGIDMgntFrame(): Drop because of RA error.\n"));\r
507                 return RT_STATUS_PKT_DROP;\r
508         }\r
509 \r
510         RT_DISP_DATA(FBEAM, FBEAM_DATA, "On VHT GID Mgnt Frame ==>:\n", pPduOS->Octet, pPduOS->Length);\r
511 \r
512         /*Parsing Membership Status Array*/\r
513         pBuffer = pPduOS->Octet + FRAME_OFFSET_VHT_GID_MGNT_MEMBERSHIP_STATUS_ARRAY;\r
514         for (idx = 0; idx < 8; idx++) {\r
515                 MemStatus[idx] = GET_VHT_GID_MGNT_INFO_MEMBERSHIP_STATUS(pBuffer+idx);\r
516                 pBeamformEntry->gid_valid[idx] = GET_VHT_GID_MGNT_INFO_MEMBERSHIP_STATUS(pBuffer+idx);\r
517         }\r
518 \r
519         RT_DISP_DATA(FBEAM, FBEAM_DATA, "MemStatus: ", MemStatus, 8);\r
520 \r
521         /* Parsing User Position Array*/\r
522         pBuffer = pPduOS->Octet + FRAME_OFFSET_VHT_GID_MGNT_USER_POSITION_ARRAY;\r
523         for (idx = 0; idx < 16; idx++) {\r
524                 UserPos[idx] = GET_VHT_GID_MGNT_INFO_USER_POSITION(pBuffer+idx);\r
525                 pBeamformEntry->user_position[idx] = GET_VHT_GID_MGNT_INFO_USER_POSITION(pBuffer+idx);\r
526         }\r
527 \r
528         RT_DISP_DATA(FBEAM, FBEAM_DATA, "UserPos: ", UserPos, 16);\r
529 \r
530         /* Group ID detail printed*/\r
531         {\r
532                 u1Byte  i, j;\r
533                 u1Byte  tmpVal;\r
534                 u2Byte  tmpVal2;\r
535 \r
536                 for (i = 0; i < 8; i++) {\r
537                         tmpVal = MemStatus[i];\r
538                         tmpVal2 = ((UserPos[i*2 + 1] << 8) & 0xFF00) + (UserPos[i * 2] & 0xFF);\r
539                         for (j = 0; j < 8; j++) {\r
540                                 if ((tmpVal >> j) & BIT0) {\r
541                                         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("Use Group ID (%d), User Position (%d)\n",\r
542                                                 (i*8+j), (tmpVal2 >> 2 * j)&0x3));\r
543                                 }\r
544                         }\r
545                 }\r
546         }\r
547 \r
548         /* Indicate GID frame to IHV service. */\r
549         {\r
550                 u1Byte  Indibuffer[24] = {0};\r
551                 u1Byte  Indioffset = 0;\r
552                         \r
553                 PlatformMoveMemory(Indibuffer + Indioffset, pBeamformEntry->gid_valid, 8);\r
554                 Indioffset += 8;\r
555                 PlatformMoveMemory(Indibuffer + Indioffset, pBeamformEntry->user_position, 16);\r
556                 Indioffset += 16;\r
557 \r
558                 PlatformIndicateCustomStatus(\r
559                         Adapter,\r
560                         RT_CUSTOM_EVENT_VHT_RECV_GID_MGNT_FRAME,\r
561                         RT_CUSTOM_INDI_TARGET_IHV,\r
562                         Indibuffer,\r
563                         Indioffset);\r
564         }\r
565 \r
566         /* Config HW GID table */\r
567         halComTxbf_ConfigGtab(pDM_Odm);\r
568 \r
569         return rtStatus;\r
570 }\r
571 \r
572 /*\r
573 // Description: Construct VHT Group ID (GID) management frame.\r
574 //\r
575 // 2015.05.20. Created by tynli.\r
576 */\r
577 VOID\r
578 ConstructVHTGIDMgntFrame(\r
579         IN      PDM_ODM_T               pDM_Odm,\r
580         IN      pu1Byte                 RA,\r
581         IN      PRT_BEAMFORMEE_ENTRY    pBeamformEntry,\r
582         OUT     pu1Byte                 Buffer,\r
583         OUT     pu4Byte                 pLength\r
584         \r
585 )\r
586 {\r
587         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
588         PADAPTER                                Adapter = pBeamInfo->SourceAdapter;\r
589         OCTET_STRING            osFTMFrame, tmp;\r
590 \r
591         FillOctetString(osFTMFrame, Buffer, 0);\r
592         *pLength = 0;\r
593 \r
594         ConstructMaFrameHdr(\r
595                                         Adapter, \r
596                                         RA, \r
597                                         ACT_CAT_VHT, \r
598                                         ACT_VHT_GROUPID_MANAGEMENT, \r
599                                         &osFTMFrame);\r
600 \r
601         /* Membership Status Array*/\r
602         FillOctetString(tmp, pBeamformEntry->gid_valid, 8);\r
603         PacketAppendData(&osFTMFrame, tmp);\r
604 \r
605         /* User Position Array*/\r
606         FillOctetString(tmp, pBeamformEntry->user_position, 16);\r
607         PacketAppendData(&osFTMFrame, tmp);\r
608 \r
609         *pLength = osFTMFrame.Length;\r
610 \r
611         RT_DISP_DATA(FBEAM, FBEAM_DATA, "ConstructVHTGIDMgntFrame():\n", Buffer, *pLength);\r
612 }\r
613 \r
614 BOOLEAN\r
615 SendSWVHTGIDMgntFrame(\r
616         IN      PVOID                   pDM_VOID,\r
617         IN      pu1Byte                 RA,\r
618         IN      u1Byte                  Idx\r
619         )\r
620 {\r
621         PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
622         PRT_TCB                                 pTcb;\r
623         PRT_TX_LOCAL_BUFFER             pBuf;\r
624         BOOLEAN                                 ret = TRUE;\r
625         u1Byte                                  DataRate = 0;\r
626         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
627         PRT_BEAMFORMEE_ENTRY    pBeamformEntry = &pBeamInfo->BeamformeeEntry[Idx];\r
628         PADAPTER                                Adapter = pBeamInfo->SourceAdapter;\r
629 \r
630         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));\r
631         \r
632         PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
633 \r
634         if (MgntGetBuffer(Adapter, &pTcb, &pBuf)) {\r
635                 ConstructVHTGIDMgntFrame(\r
636                                 pDM_Odm, \r
637                                 RA,\r
638                                 pBeamformEntry,\r
639                                 pBuf->Buffer.VirtualAddress, \r
640                                 &pTcb->PacketLength\r
641                                 );\r
642 \r
643                 pTcb->BWOfPacket = CHANNEL_WIDTH_20;\r
644                 DataRate = MGN_6M;\r
645                 MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, DataRate);\r
646         } else\r
647                 ret = FALSE;\r
648         \r
649         PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);\r
650 \r
651         if (ret)\r
652                 RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
653 \r
654         return ret;\r
655 }\r
656 \r
657 \r
658 /*\r
659 // Description: Construct VHT beamforming report poll.\r
660 //\r
661 // 2015.05.20. Created by tynli.\r
662 */\r
663 VOID\r
664 ConstructVHTBFReportPoll(\r
665         IN      PDM_ODM_T               pDM_Odm,\r
666         IN      pu1Byte                 RA,\r
667         OUT     pu1Byte                 Buffer,\r
668         OUT     pu4Byte                 pLength\r
669 )\r
670 {\r
671         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
672         PADAPTER                                Adapter = pBeamInfo->SourceAdapter;\r
673         pu1Byte                 pBFRptPoll = Buffer;\r
674         \r
675         /* Frame control*/\r
676         SET_80211_HDR_FRAME_CONTROL(pBFRptPoll, 0);\r
677         SET_80211_HDR_TYPE_AND_SUBTYPE(pBFRptPoll, Type_Beamforming_Report_Poll);\r
678 \r
679         /* Duration*/   \r
680         SET_80211_HDR_DURATION(pBFRptPoll, 100);\r
681 \r
682         /* RA*/\r
683         SET_VHT_BF_REPORT_POLL_RA(pBFRptPoll, RA);\r
684 \r
685         /* TA*/\r
686         SET_VHT_BF_REPORT_POLL_TA(pBFRptPoll, Adapter->CurrentAddress);\r
687 \r
688         /* Feedback Segment Retransmission Bitmap*/\r
689         SET_VHT_BF_REPORT_POLL_FEEDBACK_SEG_RETRAN_BITMAP(pBFRptPoll, 0xFF);\r
690 \r
691         *pLength = 17;\r
692 \r
693         RT_DISP_DATA(FBEAM, FBEAM_DATA, "ConstructVHTBFReportPoll():\n", Buffer, *pLength);\r
694 \r
695 }\r
696 \r
697 BOOLEAN\r
698 SendSWVHTBFReportPoll(\r
699         IN      PVOID                   pDM_VOID,\r
700         IN      pu1Byte                 RA,\r
701         IN      BOOLEAN                 bFinalPoll\r
702         )\r
703 {\r
704         PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
705         PRT_TCB                                 pTcb;\r
706         PRT_TX_LOCAL_BUFFER             pBuf;\r
707         BOOLEAN                                 ret = TRUE;\r
708         u1Byte                                  Idx = 0, DataRate = 0;\r
709         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
710         PRT_BEAMFORMEE_ENTRY    pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
711         PADAPTER                                Adapter = pBeamInfo->SourceAdapter;\r
712 \r
713         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));\r
714 \r
715         PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
716 \r
717         if (MgntGetBuffer(Adapter, &pTcb, &pBuf)) {\r
718                 ConstructVHTBFReportPoll(\r
719                                 pDM_Odm, \r
720                                 RA,\r
721                                 pBuf->Buffer.VirtualAddress, \r
722                                 &pTcb->PacketLength\r
723                                 );\r
724 \r
725                 pTcb->bTxEnableSwCalcDur = TRUE; /* <tynli_note> need?*/\r
726                 pTcb->BWOfPacket = CHANNEL_WIDTH_20;\r
727 \r
728                 if (bFinalPoll)\r
729                         pTcb->TxBFPktType = RT_BF_PKT_TYPE_FINAL_BF_REPORT_POLL;\r
730                 else\r
731                         pTcb->TxBFPktType = RT_BF_PKT_TYPE_BF_REPORT_POLL;\r
732                 \r
733                 DataRate = MGN_6M;      /* Legacy OFDM rate*/\r
734                 MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, DataRate);\r
735         } else\r
736                 ret = FALSE;\r
737         \r
738         PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);\r
739 \r
740         if (ret)\r
741                 RT_DISP_DATA(FBEAM, FBEAM_DATA, "SendSWVHTBFReportPoll():\n", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
742 \r
743         return ret;\r
744 \r
745 }\r
746 \r
747 \r
748 /*\r
749 // Description: Construct VHT MU NDPA packet.\r
750 //      <Note> We should combine this function with ConstructVHTNDPAPacket() in the future.\r
751 //\r
752 // 2015.05.21. Created by tynli.\r
753 */\r
754 VOID\r
755 ConstructVHTMUNDPAPacket(\r
756         IN PDM_ODM_T            pDM_Odm,\r
757         IN CHANNEL_WIDTH        BW,\r
758         OUT pu1Byte                     Buffer,\r
759         OUT pu4Byte                     pLength\r
760         )\r
761 {       \r
762         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
763         PADAPTER                                Adapter = pBeamInfo->SourceAdapter;\r
764         u2Byte                                  Duration = 0;\r
765         u1Byte                                  Sequence = 0;\r
766         pu1Byte                                 pNDPAFrame = Buffer;\r
767         RT_NDPA_STA_INFO                STAInfo;\r
768         u1Byte                                  idx;\r
769         u1Byte                                  DestAddr[6] = {0};\r
770         PRT_BEAMFORMEE_ENTRY    pEntry = NULL;\r
771 \r
772         /* Fill the first MU BFee entry (STA1) MAC addr to destination address then\r
773              HW will change A1 to broadcast addr. 2015.05.28. Suggested by SD1 Chunchu. */\r
774         for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) {              \r
775                 pEntry = &(pBeamInfo->BeamformeeEntry[idx]);\r
776                 if (pEntry->is_mu_sta) {\r
777                         cpMacAddr(DestAddr, pEntry->MacAddr);\r
778                         break;\r
779                 }\r
780         }\r
781         if (pEntry == NULL)\r
782                 return;\r
783         \r
784         /* Frame control.*/\r
785         SET_80211_HDR_FRAME_CONTROL(pNDPAFrame, 0);\r
786         SET_80211_HDR_TYPE_AND_SUBTYPE(pNDPAFrame, Type_NDPA);\r
787 \r
788         SET_80211_HDR_ADDRESS1(pNDPAFrame, DestAddr);\r
789         SET_80211_HDR_ADDRESS2(pNDPAFrame, pEntry->MyMacAddr);\r
790 \r
791         /*--------------------------------------------*/\r
792         /* <Note> Need to modify "Duration" to MU consideration. */\r
793         Duration = 2*aSifsTime + 44;\r
794         \r
795         if (BW == CHANNEL_WIDTH_80)\r
796                 Duration += 40;\r
797         else if(BW == CHANNEL_WIDTH_40)\r
798                 Duration+= 87;\r
799         else    \r
800                 Duration+= 180;\r
801         /*--------------------------------------------*/\r
802 \r
803         SET_80211_HDR_DURATION(pNDPAFrame, Duration);\r
804 \r
805         Sequence = *(pDM_Odm->pSoundingSeq) << 2;\r
806         ODM_MoveMemory(pDM_Odm, pNDPAFrame + 16, &Sequence, 1);\r
807 \r
808         *pLength = 17;\r
809 \r
810         /* Construct STA info. for multiple STAs*/\r
811         for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) {              \r
812                 pEntry = &(pBeamInfo->BeamformeeEntry[idx]);\r
813                 if (pEntry->is_mu_sta) {\r
814                         STAInfo.AID = pEntry->AID;\r
815                         STAInfo.FeedbackType = 1; /* 1'b1: MU*/\r
816                         STAInfo.NcIndex = 0;\r
817 \r
818                         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Get BeamformeeEntry idx(%d), AID =%d\n", __func__, idx, pEntry->AID));\r
819                         \r
820                         ODM_MoveMemory(pDM_Odm, pNDPAFrame+(*pLength), (pu1Byte)&STAInfo, 2);\r
821                         *pLength += 2;\r
822                 }\r
823         }\r
824 \r
825 }\r
826 \r
827 BOOLEAN\r
828 SendSWVHTMUNDPAPacket(\r
829         IN      PVOID                   pDM_VOID,\r
830         IN      CHANNEL_WIDTH   BW\r
831         )\r
832 {\r
833         PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
834         PRT_TCB                                 pTcb;\r
835         PRT_TX_LOCAL_BUFFER             pBuf;\r
836         BOOLEAN                                 ret = TRUE;\r
837         u1Byte                                  NDPTxRate = 0;\r
838         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
839         PADAPTER                                Adapter = pBeamInfo->SourceAdapter;\r
840 \r
841         NDPTxRate = MGN_VHT2SS_MCS0;\r
842         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
843 \r
844         PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
845 \r
846         if (MgntGetBuffer(Adapter, &pTcb, &pBuf)) {\r
847                 ConstructVHTMUNDPAPacket(\r
848                                 pDM_Odm,\r
849                                 BW,\r
850                                 pBuf->Buffer.VirtualAddress, \r
851                                 &pTcb->PacketLength\r
852                                 );\r
853 \r
854                 pTcb->bTxEnableSwCalcDur = TRUE;\r
855                 pTcb->BWOfPacket = BW;\r
856                 pTcb->TxBFPktType = RT_BF_PKT_TYPE_BROADCAST_NDPA;\r
857 \r
858                 /*rate of NDP decide by Nr*/\r
859                 MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, NDPTxRate);\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 VOID\r
873 DBG_ConstructVHTMUNDPAPacket(\r
874         IN PDM_ODM_T            pDM_Odm,\r
875         IN CHANNEL_WIDTH        BW,\r
876         OUT pu1Byte                     Buffer,\r
877         OUT pu4Byte                     pLength\r
878         )\r
879 {       \r
880         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
881         PADAPTER                                Adapter = pBeamInfo->SourceAdapter;\r
882         u2Byte                                  Duration = 0;\r
883         u1Byte                                  Sequence = 0;\r
884         pu1Byte                                 pNDPAFrame = Buffer;\r
885         RT_NDPA_STA_INFO                STAInfo;\r
886         u1Byte                                  idx;\r
887         u1Byte                                  DestAddr[6] = {0};\r
888         PRT_BEAMFORMEE_ENTRY    pEntry = NULL;\r
889 \r
890         BOOLEAN is_STA1 = FALSE;\r
891 \r
892 \r
893         /* Fill the first MU BFee entry (STA1) MAC addr to destination address then\r
894              HW will change A1 to broadcast addr. 2015.05.28. Suggested by SD1 Chunchu. */\r
895         for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) {              \r
896                 pEntry = &(pBeamInfo->BeamformeeEntry[idx]);\r
897                 if (pEntry->is_mu_sta) {\r
898                         if (is_STA1 == FALSE) {\r
899                                 is_STA1 = TRUE;\r
900                                 continue;\r
901                         } else {\r
902                                 cpMacAddr(DestAddr, pEntry->MacAddr);\r
903                                 break;\r
904                         }\r
905                 }\r
906         }\r
907 \r
908         /* Frame control.*/\r
909         SET_80211_HDR_FRAME_CONTROL(pNDPAFrame, 0);\r
910         SET_80211_HDR_TYPE_AND_SUBTYPE(pNDPAFrame, Type_NDPA);\r
911 \r
912         SET_80211_HDR_ADDRESS1(pNDPAFrame, DestAddr);\r
913         SET_80211_HDR_ADDRESS2(pNDPAFrame, pDM_Odm->CurrentAddress);\r
914 \r
915         /*--------------------------------------------*/\r
916         /* <Note> Need to modify "Duration" to MU consideration. */\r
917         Duration = 2*aSifsTime + 44;\r
918         \r
919         if (BW == CHANNEL_WIDTH_80)\r
920                 Duration += 40;\r
921         else if (BW == CHANNEL_WIDTH_40)\r
922                 Duration += 87;\r
923         else    \r
924                 Duration += 180;\r
925         /*--------------------------------------------*/\r
926 \r
927         SET_80211_HDR_DURATION(pNDPAFrame, Duration);\r
928 \r
929         Sequence = *(pDM_Odm->pSoundingSeq) << 2;\r
930         ODM_MoveMemory(pDM_Odm, pNDPAFrame + 16, &Sequence, 1);\r
931 \r
932         *pLength = 17;\r
933 \r
934         /*STA2's STA Info*/\r
935         STAInfo.AID = pEntry->AID;\r
936         STAInfo.FeedbackType = 1; /* 1'b1: MU */\r
937         STAInfo.NcIndex = 0;\r
938 \r
939         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Get BeamformeeEntry idx(%d), AID =%d\n", __func__, idx, pEntry->AID));\r
940         \r
941         ODM_MoveMemory(pDM_Odm, pNDPAFrame+(*pLength), (pu1Byte)&STAInfo, 2);\r
942         *pLength += 2;\r
943 \r
944 }\r
945 \r
946 BOOLEAN\r
947 DBG_SendSWVHTMUNDPAPacket(\r
948         IN      PVOID                   pDM_VOID,\r
949         IN      CHANNEL_WIDTH   BW\r
950         )\r
951 {\r
952         PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
953         PRT_TCB                                 pTcb;\r
954         PRT_TX_LOCAL_BUFFER             pBuf;\r
955         BOOLEAN                                 ret = TRUE;\r
956         u1Byte                                  NDPTxRate = 0;\r
957         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
958         PADAPTER                                Adapter = pBeamInfo->SourceAdapter;\r
959 \r
960         NDPTxRate = MGN_VHT2SS_MCS0;\r
961         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
962 \r
963         PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);\r
964 \r
965         if (MgntGetBuffer(Adapter, &pTcb, &pBuf)) {\r
966                 DBG_ConstructVHTMUNDPAPacket(\r
967                                 pDM_Odm,\r
968                                 BW,\r
969                                 pBuf->Buffer.VirtualAddress, \r
970                                 &pTcb->PacketLength\r
971                                 );\r
972 \r
973                 pTcb->bTxEnableSwCalcDur = TRUE;\r
974                 pTcb->BWOfPacket = BW;\r
975                 pTcb->TxBFPktType = RT_BF_PKT_TYPE_UNICAST_NDPA;\r
976 \r
977                 /*rate of NDP decide by Nr*/\r
978                 MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, NDPTxRate);\r
979         } else\r
980                 ret = FALSE;\r
981         \r
982         PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);       \r
983 \r
984         if (ret)\r
985                 RT_DISP_DATA(FBEAM, FBEAM_DATA, "", pBuf->Buffer.VirtualAddress, pTcb->PacketLength);\r
986 \r
987         return ret;\r
988 }\r
989 \r
990 \r
991 #endif  /*#if (SUPPORT_MU_BF == 1)*/\r
992 #endif  /*#ifdef SUPPORT_MU_BF*/\r
993 \r
994 \r
995 #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)\r
996 \r
997 u4Byte\r
998 Beamforming_GetReportFrame(\r
999         IN      PVOID                   pDM_VOID,\r
1000         union recv_frame *precv_frame\r
1001         )\r
1002 {\r
1003         PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
1004         u4Byte                                  ret = _SUCCESS;\r
1005         PRT_BEAMFORMEE_ENTRY    pBeamformEntry = NULL;\r
1006         pu1Byte                                 pframe = precv_frame->u.hdr.rx_data;\r
1007         u4Byte                                  frame_len = precv_frame->u.hdr.len;\r
1008         pu1Byte                                 TA;\r
1009         u1Byte                                  Idx, offset;\r
1010         \r
1011 \r
1012         /*Memory comparison to see if CSI report is the same with previous one*/\r
1013         TA = GetAddr2Ptr(pframe);\r
1014         pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, TA, &Idx);\r
1015         if(pBeamformEntry->BeamformEntryCap & BEAMFORMER_CAP_VHT_SU)\r
1016                 offset = 31;            /*24+(1+1+3)+2  MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)*/\r
1017         else if(pBeamformEntry->BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT)\r
1018                 offset = 34;            /*24+(1+1+6)+2  MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)*/\r
1019         else\r
1020                 return ret;\r
1021 \r
1022         \r
1023         return ret;\r
1024 }\r
1025 \r
1026 \r
1027 BOOLEAN\r
1028 SendFWHTNDPAPacket(\r
1029         IN      PVOID                   pDM_VOID,\r
1030         IN      pu1Byte                 RA,\r
1031         IN      CHANNEL_WIDTH   BW\r
1032         )\r
1033 {\r
1034         PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
1035         PADAPTER                                Adapter = pDM_Odm->Adapter;\r
1036         struct xmit_frame               *pmgntframe;\r
1037         struct pkt_attrib               *pattrib;\r
1038         struct rtw_ieee80211_hdr        *pwlanhdr;\r
1039         struct xmit_priv                *pxmitpriv = &(Adapter->xmitpriv);\r
1040         struct mlme_ext_priv    *pmlmeext = &Adapter->mlmeextpriv;\r
1041         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
1042         u1Byte  ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};\r
1043         u1Byte  *pframe;\r
1044         u2Byte  *fctrl;\r
1045         u2Byte  duration = 0;\r
1046         u1Byte  aSifsTime = 0, NDPTxRate = 0, Idx = 0;\r
1047         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
1048         PRT_BEAMFORMEE_ENTRY    pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
1049 \r
1050         pmgntframe = alloc_mgtxmitframe(pxmitpriv);\r
1051         \r
1052         if (pmgntframe == NULL) {\r
1053                 ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, alloc mgnt frame fail\n", __func__));\r
1054                 return _FALSE;\r
1055         }\r
1056 \r
1057         //update attribute\r
1058         pattrib = &pmgntframe->attrib;\r
1059         update_mgntframe_attrib(Adapter, pattrib);\r
1060 \r
1061         pattrib->qsel = QSLT_BEACON;\r
1062         NDPTxRate = Beamforming_GetHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
1063         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
1064         pattrib->rate = NDPTxRate;\r
1065         pattrib->bwmode = BW;\r
1066         pattrib->order = 1;\r
1067         pattrib->subtype = WIFI_ACTION_NOACK;\r
1068 \r
1069         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);\r
1070 \r
1071         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;\r
1072 \r
1073         pwlanhdr = (struct rtw_ieee80211_hdr*)pframe;\r
1074 \r
1075         fctrl = &pwlanhdr->frame_ctl;\r
1076         *(fctrl) = 0;\r
1077 \r
1078         SetOrderBit(pframe);\r
1079         SetFrameSubType(pframe, WIFI_ACTION_NOACK);\r
1080 \r
1081         _rtw_memcpy(pwlanhdr->addr1, RA, ETH_ALEN);\r
1082         _rtw_memcpy(pwlanhdr->addr2, pBeamformEntry->MyMacAddr, ETH_ALEN);\r
1083         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);\r
1084 \r
1085         if( pmlmeext->cur_wireless_mode == WIRELESS_11B)\r
1086                 aSifsTime = 10;\r
1087         else\r
1088                 aSifsTime = 16;\r
1089 \r
1090         duration = 2*aSifsTime + 40;\r
1091         \r
1092         if(BW == CHANNEL_WIDTH_40)\r
1093                 duration+= 87;\r
1094         else    \r
1095                 duration+= 180;\r
1096 \r
1097         SetDuration(pframe, duration);\r
1098 \r
1099         //HT control field\r
1100         SET_HT_CTRL_CSI_STEERING(pframe+24, 3);\r
1101         SET_HT_CTRL_NDP_ANNOUNCEMENT(pframe+24, 1);\r
1102 \r
1103         _rtw_memcpy(pframe+28, ActionHdr, 4);\r
1104 \r
1105         pattrib->pktlen = 32;\r
1106 \r
1107         pattrib->last_txcmdsz = pattrib->pktlen;\r
1108 \r
1109         dump_mgntframe(Adapter, pmgntframe);\r
1110 \r
1111         return _TRUE;\r
1112 }\r
1113 \r
1114 \r
1115 BOOLEAN\r
1116 SendSWHTNDPAPacket(\r
1117         IN      PVOID                   pDM_VOID,\r
1118         IN      pu1Byte                 RA,\r
1119         IN      CHANNEL_WIDTH   BW\r
1120         )\r
1121 {\r
1122         PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
1123         PADAPTER                                Adapter = pDM_Odm->Adapter;\r
1124         struct xmit_frame               *pmgntframe;\r
1125         struct pkt_attrib               *pattrib;\r
1126         struct rtw_ieee80211_hdr        *pwlanhdr;\r
1127         struct xmit_priv                *pxmitpriv = &(Adapter->xmitpriv);\r
1128         struct mlme_ext_priv    *pmlmeext = &Adapter->mlmeextpriv;\r
1129         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
1130         u1Byte  ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};\r
1131         pu1Byte pframe;\r
1132         pu2Byte fctrl;\r
1133         u2Byte  duration = 0;\r
1134         u1Byte  aSifsTime = 0, NDPTxRate = 0, Idx = 0;\r
1135         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
1136         PRT_BEAMFORMEE_ENTRY    pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
1137 \r
1138         NDPTxRate = Beamforming_GetHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
1139         \r
1140         pmgntframe = alloc_mgtxmitframe(pxmitpriv);\r
1141         \r
1142         if (pmgntframe == NULL) {\r
1143                 ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, alloc mgnt frame fail\n", __func__));\r
1144                 return _FALSE;\r
1145         }\r
1146 \r
1147         /*update attribute*/\r
1148         pattrib = &pmgntframe->attrib;\r
1149         update_mgntframe_attrib(Adapter, pattrib);\r
1150         pattrib->qsel = QSLT_MGNT;\r
1151         pattrib->rate = NDPTxRate;\r
1152         pattrib->bwmode = BW;\r
1153         pattrib->order = 1;\r
1154         pattrib->subtype = WIFI_ACTION_NOACK;\r
1155 \r
1156         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);\r
1157 \r
1158         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;\r
1159 \r
1160         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;\r
1161 \r
1162         fctrl = &pwlanhdr->frame_ctl;\r
1163         *(fctrl) = 0;\r
1164 \r
1165         SetOrderBit(pframe);\r
1166         SetFrameSubType(pframe, WIFI_ACTION_NOACK);\r
1167 \r
1168         _rtw_memcpy(pwlanhdr->addr1, RA, ETH_ALEN);\r
1169         _rtw_memcpy(pwlanhdr->addr2, pBeamformEntry->MyMacAddr, ETH_ALEN);\r
1170         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);\r
1171 \r
1172         if (pmlmeext->cur_wireless_mode == WIRELESS_11B)\r
1173                 aSifsTime = 10;\r
1174         else\r
1175                 aSifsTime = 16;\r
1176 \r
1177         duration = 2*aSifsTime + 40;\r
1178         \r
1179         if (BW == CHANNEL_WIDTH_40)\r
1180                 duration += 87;\r
1181         else    \r
1182                 duration += 180;\r
1183 \r
1184         SetDuration(pframe, duration);\r
1185 \r
1186         /*HT control field*/\r
1187         SET_HT_CTRL_CSI_STEERING(pframe+24, 3);\r
1188         SET_HT_CTRL_NDP_ANNOUNCEMENT(pframe+24, 1);\r
1189 \r
1190         _rtw_memcpy(pframe+28, ActionHdr, 4);\r
1191 \r
1192         pattrib->pktlen = 32;\r
1193 \r
1194         pattrib->last_txcmdsz = pattrib->pktlen;\r
1195 \r
1196         dump_mgntframe(Adapter, pmgntframe);\r
1197 \r
1198         return _TRUE;\r
1199 }\r
1200 \r
1201 \r
1202 BOOLEAN\r
1203 SendFWVHTNDPAPacket(\r
1204         IN      PVOID                   pDM_VOID,\r
1205         IN      pu1Byte                 RA,\r
1206         IN      u2Byte                  AID,\r
1207         IN      CHANNEL_WIDTH   BW\r
1208         )\r
1209 {\r
1210         PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
1211         PADAPTER                                Adapter = pDM_Odm->Adapter;\r
1212         struct xmit_frame               *pmgntframe;\r
1213         struct pkt_attrib               *pattrib;\r
1214         struct rtw_ieee80211_hdr        *pwlanhdr;\r
1215         struct xmit_priv                *pxmitpriv = &(Adapter->xmitpriv);\r
1216         struct mlme_ext_priv    *pmlmeext = &Adapter->mlmeextpriv;\r
1217         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
1218         struct mlme_priv                *pmlmepriv = &(Adapter->mlmepriv);\r
1219         pu1Byte pframe;\r
1220         pu2Byte fctrl;\r
1221         u2Byte  duration = 0;\r
1222         u1Byte  sequence = 0, aSifsTime = 0, NDPTxRate= 0, Idx = 0;\r
1223         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
1224         PRT_BEAMFORMEE_ENTRY    pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
1225         RT_NDPA_STA_INFO        sta_info;\r
1226 \r
1227         pmgntframe = alloc_mgtxmitframe(pxmitpriv);\r
1228         \r
1229         if (pmgntframe == NULL) {\r
1230                 ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, alloc mgnt frame fail\n", __func__));\r
1231                 return _FALSE;\r
1232         }\r
1233 \r
1234         //update attribute\r
1235         pattrib = &pmgntframe->attrib;\r
1236         _rtw_memcpy(pattrib->ra, RA, ETH_ALEN);\r
1237         update_mgntframe_attrib(Adapter, pattrib);\r
1238 \r
1239         pattrib->qsel = QSLT_BEACON;\r
1240         NDPTxRate = Beamforming_GetVHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
1241         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
1242         pattrib->rate = NDPTxRate;\r
1243         pattrib->bwmode = BW;\r
1244         pattrib->subtype = WIFI_NDPA;\r
1245 \r
1246         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);\r
1247 \r
1248         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;\r
1249 \r
1250         pwlanhdr = (struct rtw_ieee80211_hdr*)pframe;\r
1251 \r
1252         fctrl = &pwlanhdr->frame_ctl;\r
1253         *(fctrl) = 0;\r
1254 \r
1255         SetFrameSubType(pframe, WIFI_NDPA);\r
1256 \r
1257         _rtw_memcpy(pwlanhdr->addr1, RA, ETH_ALEN);\r
1258         _rtw_memcpy(pwlanhdr->addr2, pBeamformEntry->MyMacAddr, ETH_ALEN);\r
1259 \r
1260         if (IsSupported5G(pmlmeext->cur_wireless_mode) || IsSupportedHT(pmlmeext->cur_wireless_mode))\r
1261                 aSifsTime = 16;\r
1262         else\r
1263                 aSifsTime = 10;\r
1264 \r
1265         duration = 2*aSifsTime + 44;\r
1266         \r
1267         if(BW == CHANNEL_WIDTH_80)\r
1268                 duration += 40;\r
1269         else if(BW == CHANNEL_WIDTH_40)\r
1270                 duration+= 87;\r
1271         else    \r
1272                 duration+= 180;\r
1273 \r
1274         SetDuration(pframe, duration);\r
1275 \r
1276         sequence = pBeamInfo->SoundingSequence<< 2;\r
1277         if (pBeamInfo->SoundingSequence >= 0x3f)\r
1278                 pBeamInfo->SoundingSequence = 0;\r
1279         else\r
1280                 pBeamInfo->SoundingSequence++;\r
1281 \r
1282         _rtw_memcpy(pframe+16, &sequence,1);\r
1283 \r
1284         if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))\r
1285                 AID = 0;                \r
1286 \r
1287         sta_info.AID = AID;\r
1288         sta_info.FeedbackType = 0;\r
1289         sta_info.NcIndex= 0;\r
1290         \r
1291         _rtw_memcpy(pframe+17, (u8 *)&sta_info, 2);\r
1292 \r
1293         pattrib->pktlen = 19;\r
1294 \r
1295         pattrib->last_txcmdsz = pattrib->pktlen;\r
1296 \r
1297         dump_mgntframe(Adapter, pmgntframe);\r
1298 \r
1299         return _TRUE;\r
1300 }\r
1301 \r
1302 \r
1303 \r
1304 BOOLEAN\r
1305 SendSWVHTNDPAPacket(\r
1306         IN      PVOID                   pDM_VOID,\r
1307         IN      pu1Byte                 RA,\r
1308         IN      u2Byte                  AID,\r
1309         IN      CHANNEL_WIDTH   BW\r
1310         )\r
1311 {\r
1312         PDM_ODM_T                               pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
1313         PADAPTER                                Adapter = pDM_Odm->Adapter;\r
1314         struct xmit_frame               *pmgntframe;\r
1315         struct pkt_attrib               *pattrib;\r
1316         struct rtw_ieee80211_hdr        *pwlanhdr;\r
1317         struct xmit_priv                *pxmitpriv = &(Adapter->xmitpriv);\r
1318         struct mlme_ext_priv    *pmlmeext = &Adapter->mlmeextpriv;\r
1319         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
1320         struct mlme_priv                *pmlmepriv = &(Adapter->mlmepriv);\r
1321         RT_NDPA_STA_INFO        ndpa_sta_info;\r
1322         u1Byte  NDPTxRate = 0, sequence = 0, aSifsTime = 0, Idx = 0;\r
1323         pu1Byte pframe;\r
1324         pu2Byte fctrl;\r
1325         u2Byte  duration = 0;\r
1326         PRT_BEAMFORMING_INFO    pBeamInfo = &(pDM_Odm->BeamformingInfo);\r
1327         PRT_BEAMFORMEE_ENTRY    pBeamformEntry = phydm_Beamforming_GetBFeeEntryByAddr(pDM_Odm, RA, &Idx);\r
1328 \r
1329         NDPTxRate = Beamforming_GetVHTNDPTxRate(pDM_Odm, pBeamformEntry->CompSteeringNumofBFer);\r
1330         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] NDPTxRate =%d\n", __func__, NDPTxRate));\r
1331 \r
1332         pmgntframe = alloc_mgtxmitframe(pxmitpriv);\r
1333         \r
1334         if (pmgntframe == NULL) {\r
1335                 ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s, alloc mgnt frame fail\n", __func__));\r
1336                 return _FALSE;\r
1337         }\r
1338         \r
1339         /*update attribute*/\r
1340         pattrib = &pmgntframe->attrib;\r
1341         _rtw_memcpy(pattrib->ra, RA, ETH_ALEN);\r
1342         update_mgntframe_attrib(Adapter, pattrib);\r
1343         pattrib->qsel = QSLT_MGNT;\r
1344         pattrib->rate = NDPTxRate;\r
1345         pattrib->bwmode = BW;\r
1346         pattrib->subtype = WIFI_NDPA;\r
1347 \r
1348         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);\r
1349 \r
1350         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;\r
1351 \r
1352         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;\r
1353 \r
1354         fctrl = &pwlanhdr->frame_ctl;\r
1355         *(fctrl) = 0;\r
1356 \r
1357         SetFrameSubType(pframe, WIFI_NDPA);\r
1358 \r
1359         _rtw_memcpy(pwlanhdr->addr1, RA, ETH_ALEN);\r
1360         _rtw_memcpy(pwlanhdr->addr2, pBeamformEntry->MyMacAddr, ETH_ALEN);\r
1361 \r
1362         if (IsSupported5G(pmlmeext->cur_wireless_mode) || IsSupportedHT(pmlmeext->cur_wireless_mode))\r
1363                 aSifsTime = 16;\r
1364         else\r
1365                 aSifsTime = 10;\r
1366 \r
1367         duration = 2*aSifsTime + 44;\r
1368         \r
1369         if (BW == CHANNEL_WIDTH_80)\r
1370                 duration += 40;\r
1371         else if (BW == CHANNEL_WIDTH_40)\r
1372                 duration += 87;\r
1373         else    \r
1374                 duration += 180;\r
1375 \r
1376         SetDuration(pframe, duration);\r
1377         \r
1378         sequence = pBeamInfo->SoundingSequence << 2;\r
1379         if (pBeamInfo->SoundingSequence >= 0x3f)\r
1380                 pBeamInfo->SoundingSequence = 0;\r
1381         else\r
1382                 pBeamInfo->SoundingSequence++;\r
1383 \r
1384         _rtw_memcpy(pframe+16, &sequence, 1);\r
1385         if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))\r
1386                 AID = 0;                \r
1387 \r
1388         ndpa_sta_info.AID = AID;\r
1389         ndpa_sta_info.FeedbackType = 0;\r
1390         ndpa_sta_info.NcIndex = 0;\r
1391         \r
1392         _rtw_memcpy(pframe+17, (u8 *)&ndpa_sta_info, 2);\r
1393 \r
1394         pattrib->pktlen = 19;\r
1395 \r
1396         pattrib->last_txcmdsz = pattrib->pktlen;\r
1397 \r
1398         dump_mgntframe(Adapter, pmgntframe);\r
1399         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] [%d]\n", __func__, __LINE__));\r
1400         \r
1401         return _TRUE;\r
1402 }\r
1403 \r
1404 \r
1405 #endif\r
1406 \r
1407 \r
1408 VOID\r
1409 Beamforming_GetNDPAFrame(\r
1410         IN      PVOID                   pDM_VOID,\r
1411 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
1412         IN      OCTET_STRING    pduOS\r
1413 #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)\r
1414         union recv_frame *precv_frame\r
1415 #endif\r
1416 )\r
1417 {\r
1418         PDM_ODM_T                                       pDM_Odm = (PDM_ODM_T)pDM_VOID;\r
1419         PADAPTER                                        Adapter = pDM_Odm->Adapter;\r
1420         pu1Byte                                         TA ;\r
1421         u1Byte                                          Idx, Sequence;\r
1422 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
1423         pu1Byte                                         pNDPAFrame = pduOS.Octet;\r
1424 #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)\r
1425         pu1Byte                                         pNDPAFrame = precv_frame->u.hdr.rx_data;\r
1426 #endif\r
1427         PRT_BEAMFORMER_ENTRY            pBeamformerEntry = NULL;                /*Modified By Jeffery @2014-10-29*/\r
1428         \r
1429 \r
1430 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
1431                 RT_DISP_DATA(FBEAM, FBEAM_DATA, "Beamforming_GetNDPAFrame\n", pduOS.Octet, pduOS.Length);\r
1432         if (IsCtrlNDPA(pNDPAFrame) == FALSE)\r
1433 #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)\r
1434         if (GetFrameSubType(pNDPAFrame) != WIFI_NDPA)\r
1435 #endif\r
1436                 return;\r
1437         else if (!(pDM_Odm->SupportICType & (ODM_RTL8812 | ODM_RTL8821))) {\r
1438                 ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] not 8812 or 8821A, return\n", __func__));\r
1439                 return;\r
1440         }\r
1441 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)\r
1442         TA = Frame_Addr2(pduOS);\r
1443 #elif (DM_ODM_SUPPORT_TYPE == ODM_CE)\r
1444         TA = GetAddr2Ptr(pNDPAFrame);\r
1445 #endif\r
1446         /*Remove signaling TA. */\r
1447         TA[0] = TA[0] & 0xFE;\r
1448     \r
1449         pBeamformerEntry = phydm_Beamforming_GetBFerEntryByAddr(pDM_Odm, TA, &Idx);             // Modified By Jeffery @2014-10-29\r
1450 \r
1451         /*Break options for Clock Reset*/    \r
1452         if (pBeamformerEntry == NULL)\r
1453                 return;\r
1454         else if (!(pBeamformerEntry->BeamformEntryCap & BEAMFORMEE_CAP_VHT_SU))\r
1455                 return;\r
1456         /*LogSuccess: As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is NO LONGER needed !2015-04-10, Jeffery*/\r
1457         /*ClockResetTimes: While BFer entry always doesn't receive our CSI, clock will reset again and again.So ClockResetTimes is limited to 5 times.2015-04-13, Jeffery*/\r
1458         else if ((pBeamformerEntry->LogSuccess == 1) || (pBeamformerEntry->ClockResetTimes == 5)) {\r
1459                 ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] LogSeq=%d, PreLogSeq=%d, LogRetryCnt=%d, LogSuccess=%d, ClockResetTimes=%d, clock reset is no longer needed.\n", \r
1460                         __func__, pBeamformerEntry->LogSeq, pBeamformerEntry->PreLogSeq, pBeamformerEntry->LogRetryCnt, pBeamformerEntry->LogSuccess, pBeamformerEntry->ClockResetTimes));\r
1461 \r
1462         return;\r
1463         }\r
1464 \r
1465         Sequence = (pNDPAFrame[16]) >> 2;\r
1466 \r
1467         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start, Sequence=%d, LogSeq=%d, PreLogSeq=%d, LogRetryCnt=%d, ClockResetTimes=%d, LogSuccess=%d\n", \r
1468                 __func__, Sequence, pBeamformerEntry->LogSeq, pBeamformerEntry->PreLogSeq, pBeamformerEntry->LogRetryCnt, pBeamformerEntry->ClockResetTimes, pBeamformerEntry->LogSuccess));\r
1469 \r
1470         if ((pBeamformerEntry->LogSeq != 0) && (pBeamformerEntry->PreLogSeq != 0)) {\r
1471                 /*Success condition*/\r
1472                 if ((pBeamformerEntry->LogSeq != Sequence) && (pBeamformerEntry->PreLogSeq != pBeamformerEntry->LogSeq)) {\r
1473                         /* break option for clcok reset, 2015-03-30, Jeffery */\r
1474                         pBeamformerEntry->LogRetryCnt = 0;\r
1475                         /*As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is no longer needed.*/\r
1476                         /*That is, LogSuccess is NOT needed to be reset to zero, 2015-04-13, Jeffery*/\r
1477                         pBeamformerEntry->LogSuccess = 1;\r
1478 \r
1479                 } else {/*Fail condition*/\r
1480 \r
1481                         if (pBeamformerEntry->LogRetryCnt == 5) {\r
1482                                 pBeamformerEntry->ClockResetTimes++;\r
1483                                 pBeamformerEntry->LogRetryCnt = 0;\r
1484 \r
1485                         ODM_RT_TRACE(pDM_Odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Clock Reset!!! ClockResetTimes=%d\n", \r
1486                                 __func__, pBeamformerEntry->ClockResetTimes));\r
1487                         HalComTxbf_Set(pDM_Odm, TXBF_SET_SOUNDING_CLK, NULL);\r
1488 \r
1489                         } else\r
1490                                 pBeamformerEntry->LogRetryCnt++;\r
1491                 }\r
1492         }\r
1493 \r
1494         /*Update LogSeq & PreLogSeq*/\r
1495         pBeamformerEntry->PreLogSeq = pBeamformerEntry->LogSeq;\r
1496         pBeamformerEntry->LogSeq = Sequence;\r
1497         \r
1498 }\r
1499 \r
1500 \r
1501 \r
1502 #endif\r