1 /******************************************************************************
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
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.
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
14 ******************************************************************************/
15 #define _RTL8723A_CMD_C_
17 #include <osdep_service.h>
18 #include <drv_types.h>
19 #include <recv_osdep.h>
20 #include <mlme_osdep.h>
21 #include <rtl8723a_hal.h>
22 #include <usb_ops_linux.h>
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
29 static u8 _is_fw_read_cmd_down(struct rtw_adapter *padapter, u8 msgbox_num)
36 valid = rtl8723au_read8(padapter, REG_HMETFR) & BIT(msgbox_num);
39 } while ((!read_down) && (retry_cnts--));
44 /*****************************************
46 *| 31 - 8 |7 | 6 - 0 |
47 *| h2c_msg |Ext_bit |CMD_ID |
49 ******************************************/
50 int FillH2CCmd(struct rtw_adapter *padapter, u8 ElementID, u32 CmdLen,
58 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
63 padapter = GET_PRIMARY_ADAPTER(padapter);
64 pHalData = GET_HAL_DATA(padapter);
66 mutex_lock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex);
70 if (CmdLen > RTL92C_MAX_CMD_LEN)
72 if (padapter->bSurpriseRemoved == true)
75 /* pay attention to if race condition happened in H2C cmd setting. */
77 h2c_box_num = pHalData->LastHMEBoxNum;
79 if (!_is_fw_read_cmd_down(padapter, h2c_box_num)) {
80 DBG_8723A(" fw read cmd failed...\n");
85 memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen);
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);
92 *(u8 *)(&h2c_cmd) |= ElementID;
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 rtl8723au_write16(padapter, msgbox_ex_addr, h2c_cmd_ex);
99 msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * MESSAGE_BOX_SIZE);
100 h2c_cmd = le32_to_cpu(h2c_cmd);
101 rtl8723au_write32(padapter, msgbox_addr, h2c_cmd);
105 pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL92C_MAX_H2C_BOX_NUMS;
107 } while ((!bcmd_down) && (retry_cnts--));
112 mutex_unlock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex);
116 int rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u8 *param)
118 *((u32 *)param) = cpu_to_le32(*((u32 *)param));
120 FillH2CCmd(padapter, RSSI_SETTING_EID, 3, param);
125 int rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg)
130 mask = cpu_to_le32(mask);
131 memcpy(buf, &mask, 4);
134 FillH2CCmd(padapter, MACID_CONFIG_EID, 5, buf);
139 /* bitmap[0:27] = tx_rate_bitmap */
140 /* bitmap[28:31]= Rate Adaptive id */
141 /* arg[0:4] = macid */
142 /* arg[5] = Short GI */
143 void rtl8723a_add_rateatid(struct rtw_adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level)
145 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
147 u8 raid = (bitmap>>28) & 0x0f;
149 bitmap &= 0x0fffffff;
150 if (rssi_level != DM_RATR_STA_INIT)
151 bitmap = ODM_Get_Rate_Bitmap23a(pHalData, macid, bitmap,
154 bitmap |= ((raid<<28)&0xf0000000);
156 if (pHalData->fw_ractrl == true) {
157 rtl8723a_set_raid_cmd(pAdapter, bitmap, arg);
159 u8 init_rate, shortGIrate = false;
161 init_rate = get_highest_rate_idx23a(bitmap&0x0fffffff)&0x3f;
163 shortGIrate = (arg&BIT(5)) ? true:false;
165 if (shortGIrate == true)
168 rtl8723au_write8(pAdapter, REG_INIDATA_RATE_SEL + macid,
173 void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter *padapter, u8 Mode)
175 struct setpwrmode_parm H2CSetPwrMode;
176 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
177 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
179 DBG_8723A("%s: Mode =%d SmartPS =%d UAPSD =%d BcnMode = 0x%02x\n", __func__,
180 Mode, pwrpriv->smart_ps, padapter->registrypriv.uapsd_enable, pwrpriv->bcn_ant_mode);
182 /* Forece leave RF low power mode for 1T1R to
183 prevent conficting setting in Fw power */
184 /* saving sequence. 2010.06.07. Added by tynli.
185 Suggested by SD3 yschang. */
186 if ((Mode != PS_MODE_ACTIVE) &&
187 (!IS_92C_SERIAL(pHalData->VersionID))) {
188 ODM_RF_Saving23a(&pHalData->odmpriv, true);
191 H2CSetPwrMode.Mode = Mode;
192 H2CSetPwrMode.SmartPS = pwrpriv->smart_ps;
193 H2CSetPwrMode.AwakeInterval = 1;
194 H2CSetPwrMode.bAllQueueUAPSD = padapter->registrypriv.uapsd_enable;
195 H2CSetPwrMode.BcnAntMode = pwrpriv->bcn_ant_mode;
197 FillH2CCmd(padapter, SET_PWRMODE_EID, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
202 ConstructBeacon(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
204 struct ieee80211_mgmt *mgmt;
205 u32 rate_len, pktlen;
206 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
207 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
208 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
209 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
211 /* DBG_8723A("%s\n", __func__); */
213 mgmt = (struct ieee80211_mgmt *)pframe;
215 mgmt->frame_control =
216 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
218 ether_addr_copy(mgmt->da, bc_addr);
219 ether_addr_copy(mgmt->sa, myid(&padapter->eeprompriv));
220 ether_addr_copy(mgmt->bssid, get_my_bssid23a(cur_network));
222 /* A Beacon frame shouldn't have fragment bits set */
225 /* timestamp will be inserted by hardware */
227 put_unaligned_le16(cur_network->beacon_interval,
228 &mgmt->u.beacon.beacon_int);
230 put_unaligned_le16(cur_network->capability,
231 &mgmt->u.beacon.capab_info);
233 pframe = mgmt->u.beacon.variable;
234 pktlen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
236 if ((pmlmeinfo->state&0x03) == MSR_AP) {
237 /* DBG_8723A("ie len =%d\n", cur_network->IELength); */
238 pktlen += cur_network->IELength;
239 memcpy(pframe, cur_network->IEs, pktlen);
241 goto _ConstructBeacon;
244 /* below for ad-hoc mode */
247 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
248 cur_network->Ssid.ssid_len,
249 cur_network->Ssid.ssid, &pktlen);
251 /* supported rates... */
252 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
253 pframe = rtw_set_ie23a(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ?
254 8 : rate_len), cur_network->SupportedRates, &pktlen);
256 /* DS parameter set */
257 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
258 &cur_network->DSConfig, &pktlen);
260 if ((pmlmeinfo->state&0x03) == MSR_ADHOC) {
262 /* IBSS Parameter Set... */
263 /* ATIMWindow = cur->ATIMWindow; */
265 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
266 (unsigned char *)&ATIMWindow, &pktlen);
271 /* EXTERNDED SUPPORTED RATE */
273 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
275 (cur_network->SupportedRates + 8),
278 /* todo:HT for adhoc */
282 if ((pktlen + TXDESC_SIZE) > 512) {
283 DBG_8723A("beacon frame too large\n");
289 /* DBG_8723A("%s bcn_sz =%d\n", __func__, pktlen); */
293 static void ConstructPSPoll(struct rtw_adapter *padapter,
294 u8 *pframe, u32 *pLength)
296 struct ieee80211_hdr *pwlanhdr;
297 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
298 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
300 pwlanhdr = (struct ieee80211_hdr *)pframe;
303 pwlanhdr->frame_control =
304 cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
305 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
308 pwlanhdr->duration_id = cpu_to_le16(pmlmeinfo->aid | 0xc000);
311 memcpy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
314 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
320 ConstructNullFunctionData(struct rtw_adapter *padapter, u8 *pframe,
321 u32 *pLength, u8 *StaAddr, u8 bQoS, u8 AC,
322 u8 bEosp, u8 bForcePowerSave)
324 struct ieee80211_hdr *pwlanhdr;
326 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
327 struct wlan_network *cur_network = &pmlmepriv->cur_network;
328 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
329 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
331 pwlanhdr = (struct ieee80211_hdr *)pframe;
333 pwlanhdr->frame_control = 0;
334 pwlanhdr->seq_ctrl = 0;
337 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
339 switch (cur_network->network.ifmode) {
340 case NL80211_IFTYPE_P2P_CLIENT:
341 case NL80211_IFTYPE_STATION:
342 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_TODS);
343 memcpy(pwlanhdr->addr1,
344 get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
345 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv),
347 memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
349 case NL80211_IFTYPE_P2P_GO:
350 case NL80211_IFTYPE_AP:
351 pwlanhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
352 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
353 memcpy(pwlanhdr->addr2,
354 get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
355 memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv),
358 case NL80211_IFTYPE_ADHOC:
360 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
361 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
362 memcpy(pwlanhdr->addr3,
363 get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
368 struct ieee80211_qos_hdr *qoshdr;
369 qoshdr = (struct ieee80211_qos_hdr *)pframe;
371 qoshdr->frame_control |=
372 cpu_to_le16(IEEE80211_FTYPE_DATA |
373 IEEE80211_STYPE_QOS_NULLFUNC);
375 qoshdr->qos_ctrl = cpu_to_le16(AC & IEEE80211_QOS_CTL_TID_MASK);
377 qoshdr->qos_ctrl |= cpu_to_le16(IEEE80211_QOS_CTL_EOSP);
379 pktlen = sizeof(struct ieee80211_qos_hdr);
381 pwlanhdr->frame_control |=
382 cpu_to_le16(IEEE80211_FTYPE_DATA |
383 IEEE80211_STYPE_NULLFUNC);
385 pktlen = sizeof(struct ieee80211_hdr_3addr);
391 static void ConstructProbeRsp(struct rtw_adapter *padapter, u8 *pframe,
392 u32 *pLength, u8 *StaAddr, bool bHideSSID)
394 struct ieee80211_mgmt *mgmt;
397 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
398 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
399 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
401 /* DBG_8723A("%s\n", __func__); */
403 mgmt = (struct ieee80211_mgmt *)pframe;
405 mac = myid(&padapter->eeprompriv);
406 bssid = cur_network->MacAddress;
408 mgmt->frame_control =
409 cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
413 memcpy(mgmt->da, StaAddr, ETH_ALEN);
414 memcpy(mgmt->sa, mac, ETH_ALEN);
415 memcpy(mgmt->bssid, bssid, ETH_ALEN);
417 put_unaligned_le64(cur_network->tsf,
418 &mgmt->u.probe_resp.timestamp);
419 put_unaligned_le16(cur_network->beacon_interval,
420 &mgmt->u.probe_resp.beacon_int);
421 put_unaligned_le16(cur_network->capability,
422 &mgmt->u.probe_resp.capab_info);
424 pktlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
426 if (cur_network->IELength > MAX_IE_SZ)
429 memcpy(mgmt->u.probe_resp.variable, cur_network->IEs,
430 cur_network->IELength);
431 pktlen += (cur_network->IELength);
437 /* Description: Fill the reserved packets that FW will use to RSVD page. */
438 /* Now we just send 4 types packet to rsvd page. */
439 /* (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */
441 /* bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */
442 /* so we need to set the packet length to total lengh. */
443 /* true: At the second time, we should send the first packet (default:beacon) */
444 /* to Hw again and set the lengh in descriptor to the real beacon lengh. */
445 /* 2009.10.15 by tynli. */
446 static void SetFwRsvdPagePkt(struct rtw_adapter *padapter, bool bDLFinished)
448 struct hal_data_8723a *pHalData;
449 struct xmit_frame *pmgntframe;
450 struct pkt_attrib *pattrib;
451 struct xmit_priv *pxmitpriv;
452 struct mlme_ext_priv *pmlmeext;
453 struct mlme_ext_info *pmlmeinfo;
454 u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength;
455 u32 NullDataLength, QosNullLength, BTQosNullLength;
456 u8 *ReservedPagePacket;
457 u8 PageNum, PageNeed, TxDescLen;
460 struct rsvdpage_loc RsvdPageLoc;
462 DBG_8723A("%s\n", __func__);
464 ReservedPagePacket = kzalloc(1000, GFP_KERNEL);
465 if (ReservedPagePacket == NULL) {
466 DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __func__);
470 pHalData = GET_HAL_DATA(padapter);
471 pxmitpriv = &padapter->xmitpriv;
472 pmlmeext = &padapter->mlmeextpriv;
473 pmlmeinfo = &pmlmeext->mlmext_info;
475 TxDescLen = TXDESC_SIZE;
479 BufIndex = TXDESC_OFFSET;
480 ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
482 /* When we count the first page size, we need to reserve description size for the RSVD */
483 /* packet, it will be filled in front of the packet in TXPKTBUF. */
484 PageNeed = (u8)PageNum_128(TxDescLen + BeaconLength);
485 /* To reserved 2 pages for beacon buffer. 2010.06.24. */
489 pHalData->FwRsvdPageStartOffset = PageNum;
491 BufIndex += PageNeed*128;
494 RsvdPageLoc.LocPsPoll = PageNum;
495 ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);
496 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false);
498 PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);
501 BufIndex += PageNeed*128;
503 /* 3 (3) null data */
504 RsvdPageLoc.LocNullData = PageNum;
505 ConstructNullFunctionData(padapter, &ReservedPagePacket[BufIndex],
507 get_my_bssid23a(&pmlmeinfo->network),
509 rtl8723a_fill_fake_txdesc(padapter,
510 &ReservedPagePacket[BufIndex-TxDescLen],
511 NullDataLength, false, false);
513 PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
516 BufIndex += PageNeed*128;
518 /* 3 (4) probe response */
519 RsvdPageLoc.LocProbeRsp = PageNum;
522 &ReservedPagePacket[BufIndex],
524 get_my_bssid23a(&pmlmeinfo->network),
526 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, false, false);
528 PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength);
531 BufIndex += PageNeed*128;
533 /* 3 (5) Qos null data */
534 RsvdPageLoc.LocQosNull = PageNum;
535 ConstructNullFunctionData(
537 &ReservedPagePacket[BufIndex],
539 get_my_bssid23a(&pmlmeinfo->network),
541 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false);
543 PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);
546 BufIndex += PageNeed*128;
548 /* 3 (6) BT Qos null data */
549 RsvdPageLoc.LocBTQosNull = PageNum;
550 ConstructNullFunctionData(
552 &ReservedPagePacket[BufIndex],
554 get_my_bssid23a(&pmlmeinfo->network),
556 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
558 TotalPacketLen = BufIndex + BTQosNullLength;
560 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
561 if (pmgntframe == NULL)
564 /* update attribute */
565 pattrib = &pmgntframe->attrib;
566 update_mgntframe_attrib23a(padapter, pattrib);
567 pattrib->qsel = 0x10;
568 pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
569 memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
571 rtl8723au_mgnt_xmit(padapter, pmgntframe);
573 DBG_8723A("%s: Set RSVD page location to Fw\n", __func__);
574 FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
577 kfree(ReservedPagePacket);
580 void rtl8723a_set_FwJoinBssReport_cmd(struct rtw_adapter *padapter, u8 mstatus)
582 struct joinbssrpt_parm JoinBssRptParm;
583 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
584 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
585 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
587 DBG_8723A("%s mstatus(%x)\n", __func__, mstatus);
590 bool bRecover = false;
593 /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
594 /* Suggested by filen. Added by tynli. */
595 rtl8723au_write16(padapter, REG_BCN_PSR_RPT,
596 0xC000|pmlmeinfo->aid);
597 /* Do not set TSF again here or vWiFi beacon DMA INT will not work. */
598 /* correct_TSF23a(padapter, pmlmeext); */
599 /* Hw sequende enable by dedault. 2010.06.23. by tynli. */
600 /* rtl8723au_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF)); */
601 /* rtl8723au_write8(padapter, REG_HWSEQ_CTRL, 0xFF); */
603 /* set REG_CR bit 8 */
604 v8 = rtl8723au_read8(padapter, REG_CR+1);
605 v8 |= BIT(0); /* ENSWBCN */
606 rtl8723au_write8(padapter, REG_CR+1, v8);
608 /* Disable Hw protection for a time which revserd for Hw sending beacon. */
609 /* Fix download reserved page packet fail that access collision with the protection time. */
610 /* 2010.05.11. Added by tynli. */
611 /* SetBcnCtrlReg23a(padapter, 0, BIT(3)); */
612 /* SetBcnCtrlReg23a(padapter, BIT(4), 0); */
613 SetBcnCtrlReg23a(padapter, BIT(4), BIT(3));
615 /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
616 if (pHalData->RegFwHwTxQCtrl & BIT(6))
619 /* To tell Hw the packet is not a real beacon frame. */
620 /* U1bTmp = rtl8723au_read8(padapter, REG_FWHW_TXQ_CTRL+2); */
621 rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
622 pHalData->RegFwHwTxQCtrl & ~BIT(6));
623 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
624 SetFwRsvdPagePkt(padapter, 0);
626 /* 2010.05.11. Added by tynli. */
627 SetBcnCtrlReg23a(padapter, BIT(3), BIT(4));
629 /* To make sure that if there exists an adapter which would like to send beacon. */
630 /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
631 /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
632 /* the beacon cannot be sent by HW. */
633 /* 2010.06.23. Added by tynli. */
635 rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
636 pHalData->RegFwHwTxQCtrl | BIT(6));
637 pHalData->RegFwHwTxQCtrl |= BIT(6);
640 /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
641 v8 = rtl8723au_read8(padapter, REG_CR+1);
642 v8 &= ~BIT(0); /* ~ENSWBCN */
643 rtl8723au_write8(padapter, REG_CR+1, v8);
646 JoinBssRptParm.OpMode = mstatus;
648 FillH2CCmd(padapter, JOINBSS_RPT_EID, sizeof(JoinBssRptParm), (u8 *)&JoinBssRptParm);
652 #ifdef CONFIG_8723AU_BT_COEXIST
653 static void SetFwRsvdPagePkt_BTCoex(struct rtw_adapter *padapter)
655 struct hal_data_8723a *pHalData;
656 struct xmit_frame *pmgntframe;
657 struct pkt_attrib *pattrib;
658 struct xmit_priv *pxmitpriv;
659 struct mlme_ext_priv *pmlmeext;
660 struct mlme_ext_info *pmlmeinfo;
661 u8 fakemac[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x00};
662 u32 NullDataLength, BTQosNullLength;
663 u8 *ReservedPagePacket;
664 u8 PageNum, PageNeed, TxDescLen;
667 struct rsvdpage_loc RsvdPageLoc;
669 DBG_8723A("+%s\n", __func__);
671 ReservedPagePacket = kzalloc(1024, GFP_KERNEL);
672 if (ReservedPagePacket == NULL) {
673 DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __func__);
677 pHalData = GET_HAL_DATA(padapter);
678 pxmitpriv = &padapter->xmitpriv;
679 pmlmeext = &padapter->mlmeextpriv;
680 pmlmeinfo = &pmlmeext->mlmext_info;
682 TxDescLen = TXDESC_SIZE;
686 BufIndex = TXDESC_OFFSET;
687 /* skip Beacon Packet */
691 pHalData->FwRsvdPageStartOffset = PageNum;
693 BufIndex += PageNeed*128;
695 /* 3 (3) null data */
696 RsvdPageLoc.LocNullData = PageNum;
697 ConstructNullFunctionData(
699 &ReservedPagePacket[BufIndex],
703 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
705 PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
708 BufIndex += PageNeed*128;
710 /* 3 (6) BT Qos null data */
711 RsvdPageLoc.LocBTQosNull = PageNum;
712 ConstructNullFunctionData(
714 &ReservedPagePacket[BufIndex],
718 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
720 TotalPacketLen = BufIndex + BTQosNullLength;
722 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
723 if (pmgntframe == NULL)
726 /* update attribute */
727 pattrib = &pmgntframe->attrib;
728 update_mgntframe_attrib23a(padapter, pattrib);
729 pattrib->qsel = 0x10;
730 pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
731 memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
733 rtl8723au_mgnt_xmit(padapter, pmgntframe);
735 DBG_8723A("%s: Set RSVD page location to Fw\n", __func__);
736 FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
739 kfree(ReservedPagePacket);
742 void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(struct rtw_adapter *padapter)
744 struct hal_data_8723a *pHalData;
747 DBG_8723A("+%s\n", __func__);
749 pHalData = GET_HAL_DATA(padapter);
751 /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
752 if (pHalData->RegFwHwTxQCtrl & BIT(6))
755 /* To tell Hw the packet is not a real beacon frame. */
756 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
757 rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
758 pHalData->RegFwHwTxQCtrl);
759 SetFwRsvdPagePkt_BTCoex(padapter);
761 /* To make sure that if there exists an adapter which would like to send beacon. */
762 /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
763 /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
764 /* the beacon cannot be sent by HW. */
765 /* 2010.06.23. Added by tynli. */
767 pHalData->RegFwHwTxQCtrl |= BIT(6);
768 rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
769 pHalData->RegFwHwTxQCtrl);