staging: rtl8723au: rtl8723a_cmd.c: Properly initialize seq_ctrl
[jlayton/linux.git] / drivers / staging / rtl8723au / hal / rtl8723a_cmd.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  ******************************************************************************/
15 #define _RTL8723A_CMD_C_
16
17 #include <osdep_service.h>
18 #include <drv_types.h>
19 #include <recv_osdep.h>
20 #include <mlme_osdep.h>
21 #include <rtw_ioctl_set.h>
22 #include <rtl8723a_hal.h>
23 #include <usb_ops_linux.h>
24
25 #define RTL92C_MAX_H2C_BOX_NUMS         4
26 #define RTL92C_MAX_CMD_LEN              5
27 #define MESSAGE_BOX_SIZE                4
28 #define EX_MESSAGE_BOX_SIZE             2
29
30 static u8 _is_fw_read_cmd_down(struct rtw_adapter *padapter, u8 msgbox_num)
31 {
32         u8 read_down = false;
33         int     retry_cnts = 100;
34         u8 valid;
35
36         do {
37                 valid = rtl8723au_read8(padapter, REG_HMETFR) & BIT(msgbox_num);
38                 if (0 == valid)
39                         read_down = true;
40         } while ((!read_down) && (retry_cnts--));
41
42         return read_down;
43 }
44
45 /*****************************************
46 * H2C Msg format :
47 *| 31 - 8               |7              | 6 - 0 |
48 *| h2c_msg      |Ext_bit        |CMD_ID |
49 *
50 ******************************************/
51 int FillH2CCmd(struct rtw_adapter *padapter, u8 ElementID, u32 CmdLen,
52                u8 *pCmdBuffer)
53 {
54         u8 bcmd_down = false;
55         s32 retry_cnts = 100;
56         u8 h2c_box_num;
57         u32 msgbox_addr;
58         u32 msgbox_ex_addr;
59         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
60         u32 h2c_cmd = 0;
61         u16 h2c_cmd_ex = 0;
62         int ret = _FAIL;
63
64         padapter = GET_PRIMARY_ADAPTER(padapter);
65         pHalData = GET_HAL_DATA(padapter);
66
67         mutex_lock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex);
68
69         if (!pCmdBuffer)
70                 goto exit;
71         if (CmdLen > RTL92C_MAX_CMD_LEN)
72                 goto exit;
73         if (padapter->bSurpriseRemoved == true)
74                 goto exit;
75
76         /* pay attention to if  race condition happened in  H2C cmd setting. */
77         do {
78                 h2c_box_num = pHalData->LastHMEBoxNum;
79
80                 if (!_is_fw_read_cmd_down(padapter, h2c_box_num)) {
81                         DBG_8723A(" fw read cmd failed...\n");
82                         goto exit;
83                 }
84
85                 if (CmdLen <= 3) {
86                         memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen);
87                 } else {
88                         memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer, EX_MESSAGE_BOX_SIZE);
89                         memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer+2, (CmdLen-EX_MESSAGE_BOX_SIZE));
90                         *(u8 *)(&h2c_cmd) |= BIT(7);
91                 }
92
93                 *(u8 *)(&h2c_cmd) |= ElementID;
94
95                 if (h2c_cmd & BIT(7)) {
96                         msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE);
97                         h2c_cmd_ex = le16_to_cpu(h2c_cmd_ex);
98                         rtl8723au_write16(padapter, msgbox_ex_addr, h2c_cmd_ex);
99                 }
100                 msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * MESSAGE_BOX_SIZE);
101                 h2c_cmd = le32_to_cpu(h2c_cmd);
102                 rtl8723au_write32(padapter, msgbox_addr, h2c_cmd);
103
104                 bcmd_down = true;
105
106                 pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL92C_MAX_H2C_BOX_NUMS;
107
108         } while ((!bcmd_down) && (retry_cnts--));
109
110         ret = _SUCCESS;
111
112 exit:
113         mutex_unlock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex);
114         return ret;
115 }
116
117 int rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u8 *param)
118 {
119         int res = _SUCCESS;
120
121         *((u32 *)param) = cpu_to_le32(*((u32 *)param));
122
123         FillH2CCmd(padapter, RSSI_SETTING_EID, 3, param);
124
125         return res;
126 }
127
128 int rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg)
129 {
130         u8 buf[5];
131         int res = _SUCCESS;
132
133         memset(buf, 0, 5);
134         mask = cpu_to_le32(mask);
135         memcpy(buf, &mask, 4);
136         buf[4]  = arg;
137
138         FillH2CCmd(padapter, MACID_CONFIG_EID, 5, buf);
139
140         return res;
141 }
142
143 /* bitmap[0:27] = tx_rate_bitmap */
144 /* bitmap[28:31]= Rate Adaptive id */
145 /* arg[0:4] = macid */
146 /* arg[5] = Short GI */
147 void rtl8723a_add_rateatid(struct rtw_adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level)
148 {
149         struct hal_data_8723a   *pHalData = GET_HAL_DATA(pAdapter);
150         u8 macid = arg&0x1f;
151         u8 raid = (bitmap>>28) & 0x0f;
152
153         bitmap &= 0x0fffffff;
154         if (rssi_level != DM_RATR_STA_INIT)
155                 bitmap = ODM_Get_Rate_Bitmap23a(&pHalData->odmpriv, macid, bitmap, rssi_level);
156
157         bitmap |= ((raid<<28)&0xf0000000);
158
159         if (pHalData->fw_ractrl == true) {
160                 rtl8723a_set_raid_cmd(pAdapter, bitmap, arg);
161         } else {
162                 u8 init_rate, shortGIrate = false;
163
164                 init_rate = get_highest_rate_idx23a(bitmap&0x0fffffff)&0x3f;
165
166                 shortGIrate = (arg&BIT(5)) ? true:false;
167
168                 if (shortGIrate == true)
169                         init_rate |= BIT(6);
170
171                 rtl8723au_write8(pAdapter, REG_INIDATA_RATE_SEL + macid,
172                                  init_rate);
173         }
174 }
175
176 void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter *padapter, u8 Mode)
177 {
178         struct setpwrmode_parm H2CSetPwrMode;
179         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
180         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
181
182         DBG_8723A("%s: Mode =%d SmartPS =%d UAPSD =%d BcnMode = 0x%02x\n", __FUNCTION__,
183                         Mode, pwrpriv->smart_ps, padapter->registrypriv.uapsd_enable, pwrpriv->bcn_ant_mode);
184
185         /*  Forece leave RF low power mode for 1T1R to
186             prevent conficting setting in Fw power */
187         /*  saving sequence. 2010.06.07. Added by tynli.
188             Suggested by SD3 yschang. */
189         if ((Mode != PS_MODE_ACTIVE) &&
190             (!IS_92C_SERIAL(pHalData->VersionID))) {
191                 ODM_RF_Saving23a(&pHalData->odmpriv, true);
192         }
193
194         H2CSetPwrMode.Mode = Mode;
195         H2CSetPwrMode.SmartPS = pwrpriv->smart_ps;
196         H2CSetPwrMode.AwakeInterval = 1;
197         H2CSetPwrMode.bAllQueueUAPSD = padapter->registrypriv.uapsd_enable;
198         H2CSetPwrMode.BcnAntMode = pwrpriv->bcn_ant_mode;
199
200         FillH2CCmd(padapter, SET_PWRMODE_EID, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
201
202 }
203
204 static void ConstructBeacon(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
205 {
206         struct ieee80211_hdr *pwlanhdr;
207         u32 rate_len, pktlen;
208         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
209         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
210         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
211         u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
212         int bcn_fixed_size;
213
214         /* DBG_8723A("%s\n", __FUNCTION__); */
215
216         pwlanhdr = (struct ieee80211_hdr *)pframe;
217
218         pwlanhdr->frame_control = 0;
219
220         memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
221         memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
222         memcpy(pwlanhdr->addr3, get_my_bssid23a(cur_network), ETH_ALEN);
223
224         /* A Beacon frame shouldn't have fragment bits set */
225         pwlanhdr->seq_ctrl = 0;
226
227         SetFrameSubType(pframe, WIFI_BEACON);
228
229         pframe += sizeof(struct ieee80211_hdr_3addr);
230         pktlen = sizeof (struct ieee80211_hdr_3addr);
231
232         /* timestamp will be inserted by hardware */
233         pframe += 8;
234         pktlen += 8;
235
236         /*  beacon interval: 2 bytes */
237         memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval23a_from_ie(cur_network->IEs)), 2);
238
239         pframe += 2;
240         pktlen += 2;
241
242         /*  capability info: 2 bytes */
243         memcpy(pframe, (unsigned char *)(rtw_get_capability23a_from_ie(cur_network->IEs)), 2);
244
245         pframe += 2;
246         pktlen += 2;
247
248         if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
249                 bcn_fixed_size =
250                         offsetof(struct ieee80211_mgmt, u.beacon.variable) -
251                         offsetof(struct ieee80211_mgmt, u.beacon);
252
253                 /* DBG_8723A("ie len =%d\n", cur_network->IELength); */
254                 pktlen += cur_network->IELength - bcn_fixed_size;
255                 memcpy(pframe, cur_network->IEs + bcn_fixed_size, pktlen);
256
257                 goto _ConstructBeacon;
258         }
259
260         /* below for ad-hoc mode */
261
262         /*  SSID */
263         pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
264                                cur_network->Ssid.ssid_len,
265                                cur_network->Ssid.ssid, &pktlen);
266
267         /*  supported rates... */
268         rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
269         pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ?
270                                8 : rate_len), cur_network->SupportedRates, &pktlen);
271
272         /*  DS parameter set */
273         pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
274                                &cur_network->DSConfig, &pktlen);
275
276         if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
277                 u32 ATIMWindow;
278                 /*  IBSS Parameter Set... */
279                 /* ATIMWindow = cur->ATIMWindow; */
280                 ATIMWindow = 0;
281                 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
282                                        (unsigned char *)&ATIMWindow, &pktlen);
283         }
284
285         /* todo: ERP IE */
286
287         /*  EXTERNDED SUPPORTED RATE */
288         if (rate_len > 8)
289                 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
290                                        (rate_len - 8),
291                                        (cur_network->SupportedRates + 8),
292                                        &pktlen);
293
294         /* todo:HT for adhoc */
295
296 _ConstructBeacon:
297
298         if ((pktlen + TXDESC_SIZE) > 512) {
299                 DBG_8723A("beacon frame too large\n");
300                 return;
301         }
302
303         *pLength = pktlen;
304
305         /* DBG_8723A("%s bcn_sz =%d\n", __FUNCTION__, pktlen); */
306
307 }
308
309 static void ConstructPSPoll(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
310 {
311         struct ieee80211_hdr *pwlanhdr;
312         __le16 *fctrl;
313         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
314         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
315
316         pwlanhdr = (struct ieee80211_hdr *)pframe;
317
318         /*  Frame control. */
319         fctrl = &pwlanhdr->frame_control;
320         *(fctrl) = 0;
321         SetPwrMgt(fctrl);
322         SetFrameSubType(pframe, WIFI_PSPOLL);
323
324         /*  AID. */
325         SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
326
327         /*  BSSID. */
328         memcpy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
329
330         /*  TA. */
331         memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
332
333         *pLength = 16;
334 }
335
336 static void
337 ConstructNullFunctionData(struct rtw_adapter *padapter, u8 *pframe,
338                           u32 *pLength, u8 *StaAddr, u8 bQoS, u8 AC,
339                           u8 bEosp, u8 bForcePowerSave)
340 {
341         struct ieee80211_hdr *pwlanhdr;
342         __le16 *fctrl;
343         u32 pktlen;
344         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
345         struct wlan_network *cur_network = &pmlmepriv->cur_network;
346         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
347         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
348
349         pwlanhdr = (struct ieee80211_hdr *)pframe;
350
351         pwlanhdr->frame_control = 0;
352         pwlanhdr->seq_ctrl = 0;
353
354         fctrl = &pwlanhdr->frame_control;
355
356         if (bForcePowerSave)
357                 SetPwrMgt(fctrl);
358
359         switch (cur_network->network.ifmode) {
360         case NL80211_IFTYPE_P2P_CLIENT:
361         case NL80211_IFTYPE_STATION:
362                 SetToDs(fctrl);
363                 memcpy(pwlanhdr->addr1,
364                        get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
365                 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv),
366                        ETH_ALEN);
367                 memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
368                 break;
369         case NL80211_IFTYPE_P2P_GO:
370         case NL80211_IFTYPE_AP:
371                 SetFrDs(fctrl);
372                 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
373                 memcpy(pwlanhdr->addr2,
374                        get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
375                 memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv),
376                        ETH_ALEN);
377                 break;
378         case NL80211_IFTYPE_ADHOC:
379         default:
380                 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
381                 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
382                 memcpy(pwlanhdr->addr3,
383                        get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
384                 break;
385         }
386
387         if (bQoS == true) {
388                 struct ieee80211_qos_hdr *pwlanqoshdr;
389
390                 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
391
392                 pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe;
393                 SetPriority(&pwlanqoshdr->qos_ctrl, AC);
394                 SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
395
396                 pktlen = sizeof(struct ieee80211_qos_hdr);
397         } else {
398                 SetFrameSubType(pframe, WIFI_DATA_NULL);
399
400                 pktlen = sizeof(struct ieee80211_hdr_3addr);
401         }
402
403         *pLength = pktlen;
404 }
405
406 static void ConstructProbeRsp(struct rtw_adapter *padapter, u8 *pframe,
407                               u32 *pLength, u8 *StaAddr, bool bHideSSID)
408 {
409         struct ieee80211_hdr *pwlanhdr;
410         u8 *mac, *bssid;
411         u32 pktlen;
412         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
413         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
414         struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
415
416         /* DBG_8723A("%s\n", __FUNCTION__); */
417
418         pwlanhdr = (struct ieee80211_hdr *)pframe;
419
420         mac = myid(&padapter->eeprompriv);
421         bssid = cur_network->MacAddress;
422
423         pwlanhdr->frame_control = 0;
424         pwlanhdr->seq_ctrl = 0;
425
426         memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
427         memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
428         memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
429
430         SetFrameSubType(&pwlanhdr->frame_control, WIFI_PROBERSP);
431
432         pktlen = sizeof(struct ieee80211_hdr_3addr);
433         pframe += pktlen;
434
435         if (cur_network->IELength > MAX_IE_SZ)
436                 return;
437
438         memcpy(pframe, cur_network->IEs, cur_network->IELength);
439         pframe += cur_network->IELength;
440         pktlen += cur_network->IELength;
441
442         *pLength = pktlen;
443 }
444
445 /*  To check if reserved page content is destroyed by beacon beacuse beacon is too large. */
446 void CheckFwRsvdPageContent23a(struct rtw_adapter *Adapter)
447 {
448 }
449
450 /*  */
451 /*  Description: Fill the reserved packets that FW will use to RSVD page. */
452 /*                      Now we just send 4 types packet to rsvd page. */
453 /*                      (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */
454 /*      Input: */
455 /*          bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */
456 /*                                              so we need to set the packet length to total lengh. */
457 /*                            true: At the second time, we should send the first packet (default:beacon) */
458 /*                                              to Hw again and set the lengh in descriptor to the real beacon lengh. */
459 /*  2009.10.15 by tynli. */
460 static void SetFwRsvdPagePkt(struct rtw_adapter *padapter, bool bDLFinished)
461 {
462         struct hal_data_8723a *pHalData;
463         struct xmit_frame *pmgntframe;
464         struct pkt_attrib *pattrib;
465         struct xmit_priv *pxmitpriv;
466         struct mlme_ext_priv *pmlmeext;
467         struct mlme_ext_info *pmlmeinfo;
468         u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength;
469         u32 NullDataLength, QosNullLength, BTQosNullLength;
470         u8 *ReservedPagePacket;
471         u8 PageNum, PageNeed, TxDescLen;
472         u16 BufIndex;
473         u32 TotalPacketLen;
474         struct rsvdpage_loc     RsvdPageLoc;
475
476         DBG_8723A("%s\n", __FUNCTION__);
477
478         ReservedPagePacket = kzalloc(1000, GFP_KERNEL);
479         if (ReservedPagePacket == NULL) {
480                 DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
481                 return;
482         }
483
484         pHalData = GET_HAL_DATA(padapter);
485         pxmitpriv = &padapter->xmitpriv;
486         pmlmeext = &padapter->mlmeextpriv;
487         pmlmeinfo = &pmlmeext->mlmext_info;
488
489         TxDescLen = TXDESC_SIZE;
490         PageNum = 0;
491
492         /* 3 (1) beacon */
493         BufIndex = TXDESC_OFFSET;
494         ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
495
496         /*  When we count the first page size, we need to reserve description size for the RSVD */
497         /*  packet, it will be filled in front of the packet in TXPKTBUF. */
498         PageNeed = (u8)PageNum_128(TxDescLen + BeaconLength);
499         /*  To reserved 2 pages for beacon buffer. 2010.06.24. */
500         if (PageNeed == 1)
501                 PageNeed += 1;
502         PageNum += PageNeed;
503         pHalData->FwRsvdPageStartOffset = PageNum;
504
505         BufIndex += PageNeed*128;
506
507         /* 3 (2) ps-poll */
508         RsvdPageLoc.LocPsPoll = PageNum;
509         ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);
510         rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false);
511
512         PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);
513         PageNum += PageNeed;
514
515         BufIndex += PageNeed*128;
516
517         /* 3 (3) null data */
518         RsvdPageLoc.LocNullData = PageNum;
519         ConstructNullFunctionData(padapter, &ReservedPagePacket[BufIndex],
520                                   &NullDataLength,
521                                   get_my_bssid23a(&pmlmeinfo->network),
522                                   false, 0, 0, false);
523         rtl8723a_fill_fake_txdesc(padapter,
524                                   &ReservedPagePacket[BufIndex-TxDescLen],
525                                   NullDataLength, false, false);
526
527         PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
528         PageNum += PageNeed;
529
530         BufIndex += PageNeed*128;
531
532         /* 3 (4) probe response */
533         RsvdPageLoc.LocProbeRsp = PageNum;
534         ConstructProbeRsp(
535                 padapter,
536                 &ReservedPagePacket[BufIndex],
537                 &ProbeRspLength,
538                 get_my_bssid23a(&pmlmeinfo->network),
539                 false);
540         rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, false, false);
541
542         PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength);
543         PageNum += PageNeed;
544
545         BufIndex += PageNeed*128;
546
547         /* 3 (5) Qos null data */
548         RsvdPageLoc.LocQosNull = PageNum;
549         ConstructNullFunctionData(
550                 padapter,
551                 &ReservedPagePacket[BufIndex],
552                 &QosNullLength,
553                 get_my_bssid23a(&pmlmeinfo->network),
554                 true, 0, 0, false);
555         rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false);
556
557         PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);
558         PageNum += PageNeed;
559
560         BufIndex += PageNeed*128;
561
562         /* 3 (6) BT Qos null data */
563         RsvdPageLoc.LocBTQosNull = PageNum;
564         ConstructNullFunctionData(
565                 padapter,
566                 &ReservedPagePacket[BufIndex],
567                 &BTQosNullLength,
568                 get_my_bssid23a(&pmlmeinfo->network),
569                 true, 0, 0, false);
570         rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
571
572         TotalPacketLen = BufIndex + BTQosNullLength;
573
574         pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
575         if (pmgntframe == NULL)
576                 goto exit;
577
578         /*  update attribute */
579         pattrib = &pmgntframe->attrib;
580         update_mgntframe_attrib23a(padapter, pattrib);
581         pattrib->qsel = 0x10;
582         pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
583         memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
584
585         rtl8723au_mgnt_xmit(padapter, pmgntframe);
586
587         DBG_8723A("%s: Set RSVD page location to Fw\n", __FUNCTION__);
588         FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
589
590 exit:
591         kfree(ReservedPagePacket);
592 }
593
594 void rtl8723a_set_FwJoinBssReport_cmd(struct rtw_adapter *padapter, u8 mstatus)
595 {
596         struct joinbssrpt_parm  JoinBssRptParm;
597         struct hal_data_8723a   *pHalData = GET_HAL_DATA(padapter);
598         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
599         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
600
601         DBG_8723A("%s mstatus(%x)\n", __FUNCTION__, mstatus);
602
603         if (mstatus == 1) {
604                 bool bRecover = false;
605                 u8 v8;
606
607                 /*  We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
608                 /*  Suggested by filen. Added by tynli. */
609                 rtl8723au_write16(padapter, REG_BCN_PSR_RPT,
610                                   0xC000|pmlmeinfo->aid);
611                 /*  Do not set TSF again here or vWiFi beacon DMA INT will not work. */
612                 /* correct_TSF23a(padapter, pmlmeext); */
613                 /*  Hw sequende enable by dedault. 2010.06.23. by tynli. */
614                 /* rtl8723au_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF)); */
615                 /* rtl8723au_write8(padapter, REG_HWSEQ_CTRL, 0xFF); */
616
617                 /*  set REG_CR bit 8 */
618                 v8 = rtl8723au_read8(padapter, REG_CR+1);
619                 v8 |= BIT(0); /*  ENSWBCN */
620                 rtl8723au_write8(padapter,  REG_CR+1, v8);
621
622                 /*  Disable Hw protection for a time which revserd for Hw sending beacon. */
623                 /*  Fix download reserved page packet fail that access collision with the protection time. */
624                 /*  2010.05.11. Added by tynli. */
625 /*                      SetBcnCtrlReg23a(padapter, 0, BIT(3)); */
626 /*                      SetBcnCtrlReg23a(padapter, BIT(4), 0); */
627                 SetBcnCtrlReg23a(padapter, BIT(4), BIT(3));
628
629                 /*  Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
630                 if (pHalData->RegFwHwTxQCtrl & BIT(6))
631                         bRecover = true;
632
633                 /*  To tell Hw the packet is not a real beacon frame. */
634                 /* U1bTmp = rtl8723au_read8(padapter, REG_FWHW_TXQ_CTRL+2); */
635                 rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
636                                  pHalData->RegFwHwTxQCtrl & ~BIT(6));
637                 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
638                 SetFwRsvdPagePkt(padapter, 0);
639
640                 /*  2010.05.11. Added by tynli. */
641                 SetBcnCtrlReg23a(padapter, BIT(3), BIT(4));
642
643                 /*  To make sure that if there exists an adapter which would like to send beacon. */
644                 /*  If exists, the origianl value of 0x422[6] will be 1, we should check this to */
645                 /*  prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
646                 /*  the beacon cannot be sent by HW. */
647                 /*  2010.06.23. Added by tynli. */
648                 if (bRecover) {
649                         rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
650                                          pHalData->RegFwHwTxQCtrl | BIT(6));
651                         pHalData->RegFwHwTxQCtrl |= BIT(6);
652                 }
653
654                 /*  Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
655                 v8 = rtl8723au_read8(padapter, REG_CR+1);
656                 v8 &= ~BIT(0); /*  ~ENSWBCN */
657                 rtl8723au_write8(padapter, REG_CR+1, v8);
658         }
659
660         JoinBssRptParm.OpMode = mstatus;
661
662         FillH2CCmd(padapter, JOINBSS_RPT_EID, sizeof(JoinBssRptParm), (u8 *)&JoinBssRptParm);
663
664 }
665
666 #ifdef CONFIG_8723AU_BT_COEXIST
667 static void SetFwRsvdPagePkt_BTCoex(struct rtw_adapter *padapter)
668 {
669         struct hal_data_8723a *pHalData;
670         struct xmit_frame *pmgntframe;
671         struct pkt_attrib *pattrib;
672         struct xmit_priv *pxmitpriv;
673         struct mlme_ext_priv *pmlmeext;
674         struct mlme_ext_info *pmlmeinfo;
675         u8 fakemac[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x00};
676         u32 NullDataLength, BTQosNullLength;
677         u8 *ReservedPagePacket;
678         u8 PageNum, PageNeed, TxDescLen;
679         u16 BufIndex;
680         u32 TotalPacketLen;
681         struct rsvdpage_loc     RsvdPageLoc;
682
683         DBG_8723A("+%s\n", __FUNCTION__);
684
685         ReservedPagePacket = kzalloc(1024, GFP_KERNEL);
686         if (ReservedPagePacket == NULL) {
687                 DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
688                 return;
689         }
690
691         pHalData = GET_HAL_DATA(padapter);
692         pxmitpriv = &padapter->xmitpriv;
693         pmlmeext = &padapter->mlmeextpriv;
694         pmlmeinfo = &pmlmeext->mlmext_info;
695
696         TxDescLen = TXDESC_SIZE;
697         PageNum = 0;
698
699         /* 3 (1) beacon */
700         BufIndex = TXDESC_OFFSET;
701         /*  skip Beacon Packet */
702         PageNeed = 3;
703
704         PageNum += PageNeed;
705         pHalData->FwRsvdPageStartOffset = PageNum;
706
707         BufIndex += PageNeed*128;
708
709         /* 3 (3) null data */
710         RsvdPageLoc.LocNullData = PageNum;
711         ConstructNullFunctionData(
712                 padapter,
713                 &ReservedPagePacket[BufIndex],
714                 &NullDataLength,
715                 fakemac,
716                 false, 0, 0, false);
717         rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
718
719         PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
720         PageNum += PageNeed;
721
722         BufIndex += PageNeed*128;
723
724         /* 3 (6) BT Qos null data */
725         RsvdPageLoc.LocBTQosNull = PageNum;
726         ConstructNullFunctionData(
727                 padapter,
728                 &ReservedPagePacket[BufIndex],
729                 &BTQosNullLength,
730                 fakemac,
731                 true, 0, 0, false);
732         rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
733
734         TotalPacketLen = BufIndex + BTQosNullLength;
735
736         pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
737         if (pmgntframe == NULL)
738                 goto exit;
739
740         /*  update attribute */
741         pattrib = &pmgntframe->attrib;
742         update_mgntframe_attrib23a(padapter, pattrib);
743         pattrib->qsel = 0x10;
744         pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
745         memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
746
747         rtl8723au_mgnt_xmit(padapter, pmgntframe);
748
749         DBG_8723A("%s: Set RSVD page location to Fw\n", __FUNCTION__);
750         FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
751
752 exit:
753         kfree(ReservedPagePacket);
754 }
755
756 void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(struct rtw_adapter *padapter)
757 {
758         struct hal_data_8723a *pHalData;
759         u8 bRecover = false;
760
761         DBG_8723A("+%s\n", __FUNCTION__);
762
763         pHalData = GET_HAL_DATA(padapter);
764
765         /*  Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
766         if (pHalData->RegFwHwTxQCtrl & BIT(6))
767                 bRecover = true;
768
769         /*  To tell Hw the packet is not a real beacon frame. */
770         pHalData->RegFwHwTxQCtrl &= ~BIT(6);
771         rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
772                          pHalData->RegFwHwTxQCtrl);
773         SetFwRsvdPagePkt_BTCoex(padapter);
774
775         /*  To make sure that if there exists an adapter which would like to send beacon. */
776         /*  If exists, the origianl value of 0x422[6] will be 1, we should check this to */
777         /*  prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
778         /*  the beacon cannot be sent by HW. */
779         /*  2010.06.23. Added by tynli. */
780         if (bRecover) {
781                 pHalData->RegFwHwTxQCtrl |= BIT(6);
782                 rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
783                                  pHalData->RegFwHwTxQCtrl);
784         }
785 }
786 #endif