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