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 <rtw_ioctl_set.h>
22 #include <rtl8723a_hal.h>
23 #include <usb_ops_linux.h>
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
30 static u8 _is_fw_read_cmd_down(struct rtw_adapter *padapter, u8 msgbox_num)
37 valid = rtl8723au_read8(padapter, REG_HMETFR) & BIT(msgbox_num);
40 } while ((!read_down) && (retry_cnts--));
45 /*****************************************
47 *| 31 - 8 |7 | 6 - 0 |
48 *| h2c_msg |Ext_bit |CMD_ID |
50 ******************************************/
51 int FillH2CCmd(struct rtw_adapter *padapter, u8 ElementID, u32 CmdLen,
59 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
64 padapter = GET_PRIMARY_ADAPTER(padapter);
65 pHalData = GET_HAL_DATA(padapter);
67 mutex_lock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex);
71 if (CmdLen > RTL92C_MAX_CMD_LEN)
73 if (padapter->bSurpriseRemoved == true)
76 /* pay attention to if race condition happened in H2C cmd setting. */
78 h2c_box_num = pHalData->LastHMEBoxNum;
80 if (!_is_fw_read_cmd_down(padapter, h2c_box_num)) {
81 DBG_8723A(" fw read cmd failed...\n");
86 memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen);
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);
93 *(u8 *)(&h2c_cmd) |= ElementID;
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);
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);
106 pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL92C_MAX_H2C_BOX_NUMS;
108 } while ((!bcmd_down) && (retry_cnts--));
113 mutex_unlock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex);
117 int rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u8 *param)
121 *((u32 *)param) = cpu_to_le32(*((u32 *)param));
123 FillH2CCmd(padapter, RSSI_SETTING_EID, 3, param);
128 int rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg)
134 mask = cpu_to_le32(mask);
135 memcpy(buf, &mask, 4);
138 FillH2CCmd(padapter, MACID_CONFIG_EID, 5, buf);
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)
149 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
151 u8 raid = (bitmap>>28) & 0x0f;
153 bitmap &= 0x0fffffff;
154 if (rssi_level != DM_RATR_STA_INIT)
155 bitmap = ODM_Get_Rate_Bitmap23a(&pHalData->odmpriv, macid, bitmap, rssi_level);
157 bitmap |= ((raid<<28)&0xf0000000);
159 if (pHalData->fw_ractrl == true) {
160 rtl8723a_set_raid_cmd(pAdapter, bitmap, arg);
162 u8 init_rate, shortGIrate = false;
164 init_rate = get_highest_rate_idx23a(bitmap&0x0fffffff)&0x3f;
166 shortGIrate = (arg&BIT(5)) ? true:false;
168 if (shortGIrate == true)
171 rtl8723au_write8(pAdapter, REG_INIDATA_RATE_SEL + macid,
176 void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter *padapter, u8 Mode)
178 struct setpwrmode_parm H2CSetPwrMode;
179 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
180 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
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);
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);
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;
200 FillH2CCmd(padapter, SET_PWRMODE_EID, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
204 static void ConstructBeacon(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
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};
214 /* DBG_8723A("%s\n", __FUNCTION__); */
216 pwlanhdr = (struct ieee80211_hdr *)pframe;
218 pwlanhdr->frame_control = 0;
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);
224 /* A Beacon frame shouldn't have fragment bits set */
225 pwlanhdr->seq_ctrl = 0;
227 SetFrameSubType(pframe, WIFI_BEACON);
229 pframe += sizeof(struct ieee80211_hdr_3addr);
230 pktlen = sizeof (struct ieee80211_hdr_3addr);
232 /* timestamp will be inserted by hardware */
236 /* beacon interval: 2 bytes */
237 memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval23a_from_ie(cur_network->IEs)), 2);
242 /* capability info: 2 bytes */
243 memcpy(pframe, (unsigned char *)(rtw_get_capability23a_from_ie(cur_network->IEs)), 2);
248 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
250 offsetof(struct ieee80211_mgmt, u.beacon.variable) -
251 offsetof(struct ieee80211_mgmt, u.beacon);
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);
257 goto _ConstructBeacon;
260 /* below for ad-hoc mode */
263 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
264 cur_network->Ssid.ssid_len,
265 cur_network->Ssid.ssid, &pktlen);
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);
272 /* DS parameter set */
273 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
274 &cur_network->DSConfig, &pktlen);
276 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
278 /* IBSS Parameter Set... */
279 /* ATIMWindow = cur->ATIMWindow; */
281 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
282 (unsigned char *)&ATIMWindow, &pktlen);
287 /* EXTERNDED SUPPORTED RATE */
289 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
291 (cur_network->SupportedRates + 8),
294 /* todo:HT for adhoc */
298 if ((pktlen + TXDESC_SIZE) > 512) {
299 DBG_8723A("beacon frame too large\n");
305 /* DBG_8723A("%s bcn_sz =%d\n", __FUNCTION__, pktlen); */
309 static void ConstructPSPoll(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
311 struct ieee80211_hdr *pwlanhdr;
313 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
314 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
316 pwlanhdr = (struct ieee80211_hdr *)pframe;
319 fctrl = &pwlanhdr->frame_control;
322 SetFrameSubType(pframe, WIFI_PSPOLL);
325 SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
328 memcpy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
331 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
337 ConstructNullFunctionData(struct rtw_adapter *padapter, u8 *pframe,
338 u32 *pLength, u8 *StaAddr, u8 bQoS, u8 AC,
339 u8 bEosp, u8 bForcePowerSave)
341 struct ieee80211_hdr *pwlanhdr;
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;
349 pwlanhdr = (struct ieee80211_hdr *)pframe;
351 pwlanhdr->frame_control = 0;
352 pwlanhdr->seq_ctrl = 0;
354 fctrl = &pwlanhdr->frame_control;
359 switch (cur_network->network.ifmode) {
360 case NL80211_IFTYPE_P2P_CLIENT:
361 case NL80211_IFTYPE_STATION:
363 memcpy(pwlanhdr->addr1,
364 get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
365 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv),
367 memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
369 case NL80211_IFTYPE_P2P_GO:
370 case NL80211_IFTYPE_AP:
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),
378 case NL80211_IFTYPE_ADHOC:
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);
388 struct ieee80211_qos_hdr *pwlanqoshdr;
390 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
392 pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe;
393 SetPriority(&pwlanqoshdr->qos_ctrl, AC);
394 SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
396 pktlen = sizeof(struct ieee80211_qos_hdr);
398 SetFrameSubType(pframe, WIFI_DATA_NULL);
400 pktlen = sizeof(struct ieee80211_hdr_3addr);
406 static void ConstructProbeRsp(struct rtw_adapter *padapter, u8 *pframe,
407 u32 *pLength, u8 *StaAddr, bool bHideSSID)
409 struct ieee80211_hdr *pwlanhdr;
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;
416 /* DBG_8723A("%s\n", __FUNCTION__); */
418 pwlanhdr = (struct ieee80211_hdr *)pframe;
420 mac = myid(&padapter->eeprompriv);
421 bssid = cur_network->MacAddress;
423 pwlanhdr->frame_control = 0;
424 pwlanhdr->seq_ctrl = 0;
426 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
427 memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
428 memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
430 SetFrameSubType(&pwlanhdr->frame_control, WIFI_PROBERSP);
432 pktlen = sizeof(struct ieee80211_hdr_3addr);
435 if (cur_network->IELength > MAX_IE_SZ)
438 memcpy(pframe, cur_network->IEs, cur_network->IELength);
439 pframe += cur_network->IELength;
440 pktlen += cur_network->IELength;
445 /* To check if reserved page content is destroyed by beacon beacuse beacon is too large. */
446 void CheckFwRsvdPageContent23a(struct rtw_adapter *Adapter)
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. */
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)
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;
474 struct rsvdpage_loc RsvdPageLoc;
476 DBG_8723A("%s\n", __FUNCTION__);
478 ReservedPagePacket = kzalloc(1000, GFP_KERNEL);
479 if (ReservedPagePacket == NULL) {
480 DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
484 pHalData = GET_HAL_DATA(padapter);
485 pxmitpriv = &padapter->xmitpriv;
486 pmlmeext = &padapter->mlmeextpriv;
487 pmlmeinfo = &pmlmeext->mlmext_info;
489 TxDescLen = TXDESC_SIZE;
493 BufIndex = TXDESC_OFFSET;
494 ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
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. */
503 pHalData->FwRsvdPageStartOffset = PageNum;
505 BufIndex += PageNeed*128;
508 RsvdPageLoc.LocPsPoll = PageNum;
509 ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);
510 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false);
512 PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);
515 BufIndex += PageNeed*128;
517 /* 3 (3) null data */
518 RsvdPageLoc.LocNullData = PageNum;
519 ConstructNullFunctionData(padapter, &ReservedPagePacket[BufIndex],
521 get_my_bssid23a(&pmlmeinfo->network),
523 rtl8723a_fill_fake_txdesc(padapter,
524 &ReservedPagePacket[BufIndex-TxDescLen],
525 NullDataLength, false, false);
527 PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
530 BufIndex += PageNeed*128;
532 /* 3 (4) probe response */
533 RsvdPageLoc.LocProbeRsp = PageNum;
536 &ReservedPagePacket[BufIndex],
538 get_my_bssid23a(&pmlmeinfo->network),
540 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, false, false);
542 PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength);
545 BufIndex += PageNeed*128;
547 /* 3 (5) Qos null data */
548 RsvdPageLoc.LocQosNull = PageNum;
549 ConstructNullFunctionData(
551 &ReservedPagePacket[BufIndex],
553 get_my_bssid23a(&pmlmeinfo->network),
555 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false);
557 PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);
560 BufIndex += PageNeed*128;
562 /* 3 (6) BT Qos null data */
563 RsvdPageLoc.LocBTQosNull = PageNum;
564 ConstructNullFunctionData(
566 &ReservedPagePacket[BufIndex],
568 get_my_bssid23a(&pmlmeinfo->network),
570 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
572 TotalPacketLen = BufIndex + BTQosNullLength;
574 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
575 if (pmgntframe == NULL)
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);
585 rtl8723au_mgnt_xmit(padapter, pmgntframe);
587 DBG_8723A("%s: Set RSVD page location to Fw\n", __FUNCTION__);
588 FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
591 kfree(ReservedPagePacket);
594 void rtl8723a_set_FwJoinBssReport_cmd(struct rtw_adapter *padapter, u8 mstatus)
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;
601 DBG_8723A("%s mstatus(%x)\n", __FUNCTION__, mstatus);
604 bool bRecover = false;
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); */
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);
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));
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))
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);
640 /* 2010.05.11. Added by tynli. */
641 SetBcnCtrlReg23a(padapter, BIT(3), BIT(4));
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. */
649 rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
650 pHalData->RegFwHwTxQCtrl | BIT(6));
651 pHalData->RegFwHwTxQCtrl |= BIT(6);
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);
660 JoinBssRptParm.OpMode = mstatus;
662 FillH2CCmd(padapter, JOINBSS_RPT_EID, sizeof(JoinBssRptParm), (u8 *)&JoinBssRptParm);
666 #ifdef CONFIG_8723AU_BT_COEXIST
667 static void SetFwRsvdPagePkt_BTCoex(struct rtw_adapter *padapter)
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;
681 struct rsvdpage_loc RsvdPageLoc;
683 DBG_8723A("+%s\n", __FUNCTION__);
685 ReservedPagePacket = kzalloc(1024, GFP_KERNEL);
686 if (ReservedPagePacket == NULL) {
687 DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
691 pHalData = GET_HAL_DATA(padapter);
692 pxmitpriv = &padapter->xmitpriv;
693 pmlmeext = &padapter->mlmeextpriv;
694 pmlmeinfo = &pmlmeext->mlmext_info;
696 TxDescLen = TXDESC_SIZE;
700 BufIndex = TXDESC_OFFSET;
701 /* skip Beacon Packet */
705 pHalData->FwRsvdPageStartOffset = PageNum;
707 BufIndex += PageNeed*128;
709 /* 3 (3) null data */
710 RsvdPageLoc.LocNullData = PageNum;
711 ConstructNullFunctionData(
713 &ReservedPagePacket[BufIndex],
717 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
719 PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
722 BufIndex += PageNeed*128;
724 /* 3 (6) BT Qos null data */
725 RsvdPageLoc.LocBTQosNull = PageNum;
726 ConstructNullFunctionData(
728 &ReservedPagePacket[BufIndex],
732 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
734 TotalPacketLen = BufIndex + BTQosNullLength;
736 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
737 if (pmgntframe == NULL)
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);
747 rtl8723au_mgnt_xmit(padapter, pmgntframe);
749 DBG_8723A("%s: Set RSVD page location to Fw\n", __FUNCTION__);
750 FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
753 kfree(ReservedPagePacket);
756 void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(struct rtw_adapter *padapter)
758 struct hal_data_8723a *pHalData;
761 DBG_8723A("+%s\n", __FUNCTION__);
763 pHalData = GET_HAL_DATA(padapter);
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))
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);
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. */
781 pHalData->RegFwHwTxQCtrl |= BIT(6);
782 rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
783 pHalData->RegFwHwTxQCtrl);