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>
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 = rtw_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 rtw_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 rtw_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)
120 *((u32 *)param) = cpu_to_le32(*((u32 *)param));
122 FillH2CCmd(padapter, RSSI_SETTING_EID, 3, param);
127 int rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg)
133 mask = cpu_to_le32(mask);
134 memcpy(buf, &mask, 4);
137 FillH2CCmd(padapter, MACID_CONFIG_EID, 5, buf);
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)
148 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
150 u8 raid = (bitmap>>28) & 0x0f;
152 bitmap &= 0x0fffffff;
153 if (rssi_level != DM_RATR_STA_INIT)
154 bitmap = ODM_Get_Rate_Bitmap23a(&pHalData->odmpriv, macid, bitmap, rssi_level);
156 bitmap |= ((raid<<28)&0xf0000000);
158 if (pHalData->fw_ractrl == true) {
159 rtl8723a_set_raid_cmd(pAdapter, bitmap, arg);
161 u8 init_rate, shortGIrate = false;
163 init_rate = get_highest_rate_idx23a(bitmap&0x0fffffff)&0x3f;
165 shortGIrate = (arg&BIT(5)) ? true:false;
167 if (shortGIrate == true)
170 rtw_write8(pAdapter, (REG_INIDATA_RATE_SEL+macid), (u8)init_rate);
174 void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter *padapter, u8 Mode)
176 struct setpwrmode_parm H2CSetPwrMode;
177 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
178 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
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);
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);
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;
198 FillH2CCmd(padapter, SET_PWRMODE_EID, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
202 static void ConstructBeacon(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
204 struct ieee80211_hdr *pwlanhdr;
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};
212 /* DBG_8723A("%s\n", __FUNCTION__); */
214 pwlanhdr = (struct ieee80211_hdr *)pframe;
216 fctrl = &pwlanhdr->frame_control;
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);
223 SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
224 /* pmlmeext->mgnt_seq++; */
225 SetFrameSubType(pframe, WIFI_BEACON);
227 pframe += sizeof(struct ieee80211_hdr_3addr);
228 pktlen = sizeof (struct ieee80211_hdr_3addr);
230 /* timestamp will be inserted by hardware */
234 /* beacon interval: 2 bytes */
235 memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval23a_from_ie(cur_network->IEs)), 2);
240 /* capability info: 2 bytes */
241 memcpy(pframe, (unsigned char *)(rtw_get_capability23a_from_ie(cur_network->IEs)), 2);
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);
251 goto _ConstructBeacon;
254 /* below for ad-hoc mode */
257 pframe = rtw_set_ie23a(pframe, WLAN_EID_SSID,
258 cur_network->Ssid.ssid_len,
259 cur_network->Ssid.ssid, &pktlen);
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);
266 /* DS parameter set */
267 pframe = rtw_set_ie23a(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)
268 &cur_network->Configuration.DSConfig, &pktlen);
270 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
272 /* IBSS Parameter Set... */
273 /* ATIMWindow = cur->Configuration.ATIMWindow; */
275 pframe = rtw_set_ie23a(pframe, WLAN_EID_IBSS_PARAMS, 2,
276 (unsigned char *)(&ATIMWindow), &pktlen);
281 /* EXTERNDED SUPPORTED RATE */
283 pframe = rtw_set_ie23a(pframe, WLAN_EID_EXT_SUPP_RATES,
285 (cur_network->SupportedRates + 8),
288 /* todo:HT for adhoc */
292 if ((pktlen + TXDESC_SIZE) > 512) {
293 DBG_8723A("beacon frame too large\n");
299 /* DBG_8723A("%s bcn_sz =%d\n", __FUNCTION__, pktlen); */
303 static void ConstructPSPoll(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
305 struct ieee80211_hdr *pwlanhdr;
307 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
308 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
310 pwlanhdr = (struct ieee80211_hdr *)pframe;
313 fctrl = &pwlanhdr->frame_control;
316 SetFrameSubType(pframe, WIFI_PSPOLL);
319 SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
322 memcpy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
325 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
330 static void ConstructNullFunctionData(
331 struct rtw_adapter *padapter,
340 struct ieee80211_hdr *pwlanhdr;
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;
348 pwlanhdr = (struct ieee80211_hdr *)pframe;
350 fctrl = &pwlanhdr->frame_control;
355 switch (cur_network->network.InfrastructureMode) {
356 case Ndis802_11Infrastructure:
358 memcpy(pwlanhdr->addr1,
359 get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
360 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv),
362 memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
364 case Ndis802_11APMode:
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),
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);
381 SetSeqNum(pwlanhdr, 0);
384 struct ieee80211_qos_hdr *pwlanqoshdr;
386 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
388 pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe;
389 SetPriority(&pwlanqoshdr->qos_ctrl, AC);
390 SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
392 pktlen = sizeof(struct ieee80211_qos_hdr);
394 SetFrameSubType(pframe, WIFI_DATA_NULL);
396 pktlen = sizeof(struct ieee80211_hdr_3addr);
402 static void ConstructProbeRsp(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID)
404 struct ieee80211_hdr *pwlanhdr;
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;
412 /* DBG_8723A("%s\n", __FUNCTION__); */
414 pwlanhdr = (struct ieee80211_hdr *)pframe;
416 mac = myid(&padapter->eeprompriv);
417 bssid = cur_network->MacAddress;
419 fctrl = &pwlanhdr->frame_control;
421 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
422 memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
423 memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
425 SetSeqNum(pwlanhdr, 0);
426 SetFrameSubType(fctrl, WIFI_PROBERSP);
428 pktlen = sizeof(struct ieee80211_hdr_3addr);
431 if (cur_network->IELength > MAX_IE_SZ)
434 memcpy(pframe, cur_network->IEs, cur_network->IELength);
435 pframe += cur_network->IELength;
436 pktlen += cur_network->IELength;
441 /* To check if reserved page content is destroyed by beacon beacuse beacon is too large. */
442 void CheckFwRsvdPageContent23a(struct rtw_adapter *Adapter)
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. */
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)
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;
470 struct rsvdpage_loc RsvdPageLoc;
472 DBG_8723A("%s\n", __FUNCTION__);
474 ReservedPagePacket = kzalloc(1000, GFP_KERNEL);
475 if (ReservedPagePacket == NULL) {
476 DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
480 pHalData = GET_HAL_DATA(padapter);
481 pxmitpriv = &padapter->xmitpriv;
482 pmlmeext = &padapter->mlmeextpriv;
483 pmlmeinfo = &pmlmeext->mlmext_info;
485 TxDescLen = TXDESC_SIZE;
489 BufIndex = TXDESC_OFFSET;
490 ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
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. */
499 pHalData->FwRsvdPageStartOffset = PageNum;
501 BufIndex += PageNeed*128;
504 RsvdPageLoc.LocPsPoll = PageNum;
505 ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);
506 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false);
508 PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);
511 BufIndex += PageNeed*128;
513 /* 3 (3) null data */
514 RsvdPageLoc.LocNullData = PageNum;
515 ConstructNullFunctionData(
517 &ReservedPagePacket[BufIndex],
519 get_my_bssid23a(&pmlmeinfo->network),
521 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
523 PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
526 BufIndex += PageNeed*128;
528 /* 3 (4) probe response */
529 RsvdPageLoc.LocProbeRsp = PageNum;
532 &ReservedPagePacket[BufIndex],
534 get_my_bssid23a(&pmlmeinfo->network),
536 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, false, false);
538 PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength);
541 BufIndex += PageNeed*128;
543 /* 3 (5) Qos null data */
544 RsvdPageLoc.LocQosNull = PageNum;
545 ConstructNullFunctionData(
547 &ReservedPagePacket[BufIndex],
549 get_my_bssid23a(&pmlmeinfo->network),
551 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false);
553 PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);
556 BufIndex += PageNeed*128;
558 /* 3 (6) BT Qos null data */
559 RsvdPageLoc.LocBTQosNull = PageNum;
560 ConstructNullFunctionData(
562 &ReservedPagePacket[BufIndex],
564 get_my_bssid23a(&pmlmeinfo->network),
566 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
568 TotalPacketLen = BufIndex + BTQosNullLength;
570 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
571 if (pmgntframe == NULL)
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);
581 rtl8723au_mgnt_xmit(padapter, pmgntframe);
583 DBG_8723A("%s: Set RSVD page location to Fw\n", __FUNCTION__);
584 FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
587 kfree(ReservedPagePacket);
590 void rtl8723a_set_FwJoinBssReport_cmd(struct rtw_adapter *padapter, u8 mstatus)
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;
597 DBG_8723A("%s mstatus(%x)\n", __FUNCTION__, mstatus);
600 bool bRecover = false;
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); */
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);
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));
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))
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);
634 /* 2010.05.11. Added by tynli. */
635 SetBcnCtrlReg23a(padapter, BIT(3), BIT(4));
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. */
643 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl | BIT(6));
644 pHalData->RegFwHwTxQCtrl |= BIT(6);
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);
653 JoinBssRptParm.OpMode = mstatus;
655 FillH2CCmd(padapter, JOINBSS_RPT_EID, sizeof(JoinBssRptParm), (u8 *)&JoinBssRptParm);
659 #ifdef CONFIG_8723AU_BT_COEXIST
660 static void SetFwRsvdPagePkt_BTCoex(struct rtw_adapter *padapter)
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;
674 struct rsvdpage_loc RsvdPageLoc;
676 DBG_8723A("+%s\n", __FUNCTION__);
678 ReservedPagePacket = kzalloc(1024, GFP_KERNEL);
679 if (ReservedPagePacket == NULL) {
680 DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
684 pHalData = GET_HAL_DATA(padapter);
685 pxmitpriv = &padapter->xmitpriv;
686 pmlmeext = &padapter->mlmeextpriv;
687 pmlmeinfo = &pmlmeext->mlmext_info;
689 TxDescLen = TXDESC_SIZE;
693 BufIndex = TXDESC_OFFSET;
694 /* skip Beacon Packet */
698 pHalData->FwRsvdPageStartOffset = PageNum;
700 BufIndex += PageNeed*128;
702 /* 3 (3) null data */
703 RsvdPageLoc.LocNullData = PageNum;
704 ConstructNullFunctionData(
706 &ReservedPagePacket[BufIndex],
710 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
712 PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
715 BufIndex += PageNeed*128;
717 /* 3 (6) BT Qos null data */
718 RsvdPageLoc.LocBTQosNull = PageNum;
719 ConstructNullFunctionData(
721 &ReservedPagePacket[BufIndex],
725 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
727 TotalPacketLen = BufIndex + BTQosNullLength;
729 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
730 if (pmgntframe == NULL)
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);
740 rtl8723au_mgnt_xmit(padapter, pmgntframe);
742 DBG_8723A("%s: Set RSVD page location to Fw\n", __FUNCTION__);
743 FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
746 kfree(ReservedPagePacket);
749 void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(struct rtw_adapter *padapter)
751 struct hal_data_8723a *pHalData;
754 DBG_8723A("+%s\n", __FUNCTION__);
756 pHalData = GET_HAL_DATA(padapter);
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))
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);
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. */
773 pHalData->RegFwHwTxQCtrl |= BIT(6);
774 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);