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 _RTL8723B_CMD_C_
17 #include <drv_types.h>
18 #include <rtw_debug.h>
19 #include <rtl8723b_hal.h>
20 #include "hal_com_h2c.h"
22 #define MAX_H2C_BOX_NUMS 4
23 #define MESSAGE_BOX_SIZE 4
25 #define RTL8723B_MAX_CMD_LEN 7
26 #define RTL8723B_EX_MESSAGE_BOX_SIZE 4
28 static u8 _is_fw_read_cmd_down(struct adapter *padapter, u8 msgbox_num)
35 /* DBG_8192C(" _is_fw_read_cmd_down , reg_1cc(%x), msg_box(%d)...\n", rtw_read8(padapter, REG_HMETFR), msgbox_num); */
38 valid = rtw_read8(padapter, REG_HMETFR) & BIT(msgbox_num);
46 }while ((!read_down) && (retry_cnts--));
53 /*****************************************
55 *| 31 - 8 |7-5 | 4 - 0 |
56 *| h2c_msg |Class |CMD_ID |
60 ******************************************/
61 s32 FillH2CCmd8723B(struct adapter *padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)
65 u32 msgbox_ex_addr = 0;
66 struct hal_com_data *pHalData;
71 padapter = GET_PRIMARY_ADAPTER(padapter);
72 pHalData = GET_HAL_DATA(padapter);
73 if (mutex_lock_interruptible(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex)))
79 if (CmdLen > RTL8723B_MAX_CMD_LEN) {
82 if (padapter->bSurpriseRemoved == true)
85 /* pay attention to if race condition happened in H2C cmd setting. */
87 h2c_box_num = pHalData->LastHMEBoxNum;
89 if (!_is_fw_read_cmd_down(padapter, h2c_box_num)) {
90 DBG_8192C(" fw read cmd failed...\n");
91 /* DBG_8192C(" 0x1c0: 0x%8x\n", rtw_read32(padapter, 0x1c0)); */
92 /* DBG_8192C(" 0x1c4: 0x%8x\n", rtw_read32(padapter, 0x1c4)); */
98 memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen);
101 memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, 3);
102 memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer+3, CmdLen-3);
103 /* *(u8 *)(&h2c_cmd) |= BIT(7); */
106 *(u8 *)(&h2c_cmd) |= ElementID;
109 msgbox_ex_addr = REG_HMEBOX_EXT0_8723B + (h2c_box_num *RTL8723B_EX_MESSAGE_BOX_SIZE);
110 rtw_write32(padapter, msgbox_ex_addr, h2c_cmd_ex);
112 msgbox_addr =REG_HMEBOX_0 + (h2c_box_num *MESSAGE_BOX_SIZE);
113 rtw_write32(padapter, msgbox_addr, h2c_cmd);
115 /* DBG_8192C("MSG_BOX:%d, CmdLen(%d), CmdID(0x%x), reg:0x%x =>h2c_cmd:0x%.8x, reg:0x%x =>h2c_cmd_ex:0x%.8x\n" */
116 /* , pHalData->LastHMEBoxNum , CmdLen, ElementID, msgbox_addr, h2c_cmd, msgbox_ex_addr, h2c_cmd_ex); */
118 pHalData->LastHMEBoxNum = (h2c_box_num+1) % MAX_H2C_BOX_NUMS;
126 mutex_unlock(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex));
130 static void ConstructBeacon(struct adapter *padapter, u8 *pframe, u32 *pLength)
132 struct ieee80211_hdr *pwlanhdr;
134 u32 rate_len, pktlen;
135 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
136 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
137 struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
138 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
141 /* DBG_871X("%s\n", __func__); */
143 pwlanhdr = (struct ieee80211_hdr *)pframe;
145 fctrl = &(pwlanhdr->frame_control);
148 memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
149 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
150 memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
152 SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
153 /* pmlmeext->mgnt_seq++; */
154 SetFrameSubType(pframe, WIFI_BEACON);
156 pframe += sizeof(struct ieee80211_hdr_3addr);
157 pktlen = sizeof (struct ieee80211_hdr_3addr);
159 /* timestamp will be inserted by hardware */
163 /* beacon interval: 2 bytes */
164 memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
169 /* capability info: 2 bytes */
170 memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
175 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
177 /* DBG_871X("ie len =%d\n", cur_network->IELength); */
178 pktlen += cur_network->IELength - sizeof(struct ndis_802_11_fix_ie);
179 memcpy(pframe, cur_network->IEs+sizeof(struct ndis_802_11_fix_ie), pktlen);
181 goto _ConstructBeacon;
184 /* below for ad-hoc mode */
187 pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);
189 /* supported rates... */
190 rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
191 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pktlen);
193 /* DS parameter set */
194 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
196 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
199 /* IBSS Parameter Set... */
200 /* ATIMWindow = cur->Configuration.ATIMWindow; */
202 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
209 /* EXTERNDED SUPPORTED RATE */
212 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
216 /* todo:HT for adhoc */
220 if ((pktlen + TXDESC_SIZE) > 512)
222 DBG_871X("beacon frame too large\n");
228 /* DBG_871X("%s bcn_sz =%d\n", __func__, pktlen); */
232 static void ConstructPSPoll(struct adapter *padapter, u8 *pframe, u32 *pLength)
234 struct ieee80211_hdr *pwlanhdr;
236 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
237 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
239 /* DBG_871X("%s\n", __func__); */
241 pwlanhdr = (struct ieee80211_hdr *)pframe;
244 fctrl = &(pwlanhdr->frame_control);
247 SetFrameSubType(pframe, WIFI_PSPOLL);
250 SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
253 memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
256 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
261 static void ConstructNullFunctionData(
262 struct adapter *padapter,
271 struct ieee80211_hdr *pwlanhdr;
274 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
275 struct wlan_network *cur_network = &pmlmepriv->cur_network;
276 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
277 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
280 /* DBG_871X("%s:%d\n", __func__, bForcePowerSave); */
282 pwlanhdr = (struct ieee80211_hdr*)pframe;
284 fctrl = &pwlanhdr->frame_control;
291 switch (cur_network->network.InfrastructureMode)
293 case Ndis802_11Infrastructure:
295 memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
296 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
297 memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
299 case Ndis802_11APMode:
301 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
302 memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
303 memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
307 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
308 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
309 memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
313 SetSeqNum(pwlanhdr, 0);
316 struct ieee80211_qos_hdr *pwlanqoshdr;
318 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
320 pwlanqoshdr = (struct ieee80211_qos_hdr*)pframe;
321 SetPriority(&pwlanqoshdr->qos_ctrl, AC);
322 SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
324 pktlen = sizeof(struct ieee80211_qos_hdr);
326 SetFrameSubType(pframe, WIFI_DATA_NULL);
328 pktlen = sizeof(struct ieee80211_hdr_3addr);
338 /* Construct the ARP response packet to support ARP offload. */
340 static void ConstructARPResponse(
341 struct adapter *padapter,
347 struct ieee80211_hdr *pwlanhdr;
349 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
350 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
351 struct security_priv *psecuritypriv = &padapter->securitypriv;
352 static u8 ARPLLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06};
353 u8 *pARPRspPkt = pframe;
354 /* for TKIP Cal MIC */
355 u8 *payload = pframe;
356 u8 EncryptionHeadOverhead = 0;
357 /* DBG_871X("%s:%d\n", __func__, bForcePowerSave); */
359 pwlanhdr = (struct ieee80211_hdr*)pframe;
361 fctrl = &pwlanhdr->frame_control;
367 SetFrameType(fctrl, WIFI_DATA);
368 /* SetFrameSubType(fctrl, 0); */
370 memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
371 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
372 memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
374 SetSeqNum(pwlanhdr, 0);
375 SetDuration(pwlanhdr, 0);
376 /* SET_80211_HDR_FRAME_CONTROL(pARPRspPkt, 0); */
377 /* SET_80211_HDR_TYPE_AND_SUBTYPE(pARPRspPkt, Type_Data); */
378 /* SET_80211_HDR_TO_DS(pARPRspPkt, 1); */
379 /* SET_80211_HDR_ADDRESS1(pARPRspPkt, pMgntInfo->Bssid); */
380 /* SET_80211_HDR_ADDRESS2(pARPRspPkt, Adapter->CurrentAddress); */
381 /* SET_80211_HDR_ADDRESS3(pARPRspPkt, pMgntInfo->Bssid); */
383 /* SET_80211_HDR_DURATION(pARPRspPkt, 0); */
384 /* SET_80211_HDR_FRAGMENT_SEQUENCE(pARPRspPkt, 0); */
388 /* Security Header: leave space for it if necessary. */
391 switch (psecuritypriv->dot11PrivacyAlgrthm)
395 EncryptionHeadOverhead = 4;
398 EncryptionHeadOverhead = 8;
401 EncryptionHeadOverhead = 8;
404 EncryptionHeadOverhead = 0;
407 if (EncryptionHeadOverhead > 0)
409 memset(&(pframe[*pLength]), 0, EncryptionHeadOverhead);
410 *pLength += EncryptionHeadOverhead;
417 pARPRspPkt = (u8 *)(pframe+ *pLength);
418 payload = pARPRspPkt; /* Get Payload pointer */
420 memcpy(pARPRspPkt, ARPLLCHeader, 8);
425 SET_ARP_PKT_HW(pARPRspPkt, 0x0100);
426 SET_ARP_PKT_PROTOCOL(pARPRspPkt, 0x0008); /* IP protocol */
427 SET_ARP_PKT_HW_ADDR_LEN(pARPRspPkt, 6);
428 SET_ARP_PKT_PROTOCOL_ADDR_LEN(pARPRspPkt, 4);
429 SET_ARP_PKT_OPERATION(pARPRspPkt, 0x0200); /* ARP response */
430 SET_ARP_PKT_SENDER_MAC_ADDR(pARPRspPkt, myid(&(padapter->eeprompriv)));
431 SET_ARP_PKT_SENDER_IP_ADDR(pARPRspPkt, pIPAddress);
433 SET_ARP_PKT_TARGET_MAC_ADDR(pARPRspPkt, get_my_bssid(&(pmlmeinfo->network)));
434 SET_ARP_PKT_TARGET_IP_ADDR(pARPRspPkt, pIPAddress);
435 DBG_871X("%s Target Mac Addr:" MAC_FMT "\n", __func__, MAC_ARG(get_my_bssid(&(pmlmeinfo->network))));
436 DBG_871X("%s Target IP Addr" IP_FMT "\n", __func__, IP_ARG(pIPAddress));
441 if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_)
444 struct mic_data micdata;
445 struct sta_info *psta = NULL;
446 u8 priority[4]={0x0, 0x0, 0x0, 0x0};
447 u8 null_key[16]={0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
449 DBG_871X("%s(): Add MIC\n", __func__);
451 psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(&(pmlmeinfo->network)));
453 if (!memcmp(&psta->dot11tkiptxmickey.skey[0], null_key, 16)) {
454 DBG_871X("%s(): STA dot11tkiptxmickey == 0\n", __func__);
456 /* start to calculate the mic code */
457 rtw_secmicsetkey(&micdata, &psta->dot11tkiptxmickey.skey[0]);
460 rtw_secmicappend(&micdata, pwlanhdr->addr3, 6); /* DA */
462 rtw_secmicappend(&micdata, pwlanhdr->addr2, 6); /* SA */
465 rtw_secmicappend(&micdata, &priority[0], 4);
467 rtw_secmicappend(&micdata, payload, 36); /* payload length = 8 + 28 */
469 rtw_secgetmic(&micdata,&(mic[0]));
472 memcpy(pARPRspPkt, &(mic[0]), 8);
478 #ifdef CONFIG_PNO_SUPPORT
479 static void ConstructPnoInfo(
480 struct adapter *padapter,
486 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
488 u8 *pPnoInfoPkt = pframe;
489 pPnoInfoPkt = (u8 *)(pframe+ *pLength);
490 memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_num, 4);
494 memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->fast_scan_period, 4);
498 memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->fast_scan_iterations, 4);
502 memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->slow_scan_period, 4);
506 memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_length,
509 *pLength+=MAX_PNO_LIST_COUNT;
510 pPnoInfoPkt += MAX_PNO_LIST_COUNT;
511 memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_cipher_info,
514 *pLength+=MAX_PNO_LIST_COUNT;
515 pPnoInfoPkt += MAX_PNO_LIST_COUNT;
516 memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_channel_info,
519 *pLength+=MAX_PNO_LIST_COUNT;
520 pPnoInfoPkt += MAX_PNO_LIST_COUNT;
523 static void ConstructSSIDList(
524 struct adapter *padapter,
530 u8 *pSSIDListPkt = pframe;
531 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
533 pSSIDListPkt = (u8 *)(pframe+ *pLength);
535 for (i = 0; i < pwrctl->pnlo_info->ssid_num ; i++) {
536 memcpy(pSSIDListPkt, &pwrctl->pno_ssid_list->node[i].SSID,
537 pwrctl->pnlo_info->ssid_length[i]);
539 *pLength += WLAN_SSID_MAXLEN;
540 pSSIDListPkt += WLAN_SSID_MAXLEN;
544 static void ConstructScanInfo(
545 struct adapter *padapter,
551 u8 *pScanInfoPkt = pframe;
552 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
554 pScanInfoPkt = (u8 *)(pframe+ *pLength);
556 memcpy(pScanInfoPkt, &pwrctl->pscan_info->channel_num, 1);
560 memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_ch, 1);
565 memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_bw, 1);
570 memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_40_offset, 1);
574 memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_80_offset, 1);
578 memcpy(pScanInfoPkt, &pwrctl->pscan_info->periodScan, 1);
582 memcpy(pScanInfoPkt, &pwrctl->pscan_info->period_scan_time, 1);
586 memcpy(pScanInfoPkt, &pwrctl->pscan_info->enableRFE, 1);
590 memcpy(pScanInfoPkt, &pwrctl->pscan_info->rfe_type, 8);
595 for (i = 0 ; i < MAX_SCAN_LIST_COUNT ; i ++) {
597 &pwrctl->pscan_info->ssid_channel_info[i], 4);
605 static void ConstructGTKResponse(
606 struct adapter *padapter,
611 struct ieee80211_hdr *pwlanhdr;
613 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
614 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
615 struct security_priv *psecuritypriv = &padapter->securitypriv;
616 static u8 LLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8E};
617 static u8 GTKbody_a[11] ={0x01, 0x03, 0x00, 0x5F, 0x02, 0x03, 0x12, 0x00, 0x10, 0x42, 0x0B};
618 u8 *pGTKRspPkt = pframe;
619 u8 EncryptionHeadOverhead = 0;
620 /* DBG_871X("%s:%d\n", __func__, bForcePowerSave); */
622 pwlanhdr = (struct ieee80211_hdr*)pframe;
624 fctrl = &pwlanhdr->frame_control;
630 SetFrameType(fctrl, WIFI_DATA);
631 /* SetFrameSubType(fctrl, 0); */
633 memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
634 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
635 memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
637 SetSeqNum(pwlanhdr, 0);
638 SetDuration(pwlanhdr, 0);
643 /* Security Header: leave space for it if necessary. */
646 switch (psecuritypriv->dot11PrivacyAlgrthm)
650 EncryptionHeadOverhead = 4;
653 EncryptionHeadOverhead = 8;
656 EncryptionHeadOverhead = 8;
659 EncryptionHeadOverhead = 0;
662 if (EncryptionHeadOverhead > 0)
664 memset(&(pframe[*pLength]), 0, EncryptionHeadOverhead);
665 *pLength += EncryptionHeadOverhead;
666 /* GTK's privacy bit is done by FW */
667 /* SetPrivacy(fctrl); */
673 pGTKRspPkt = (u8 *)(pframe+ *pLength);
675 memcpy(pGTKRspPkt, LLCHeader, 8);
681 /* GTK frame body after LLC, part 1 */
682 memcpy(pGTKRspPkt, GTKbody_a, 11);
685 /* GTK frame body after LLC, part 2 */
686 memset(&(pframe[*pLength]), 0, 88);
691 #endif /* CONFIG_GTK_OL */
693 #ifdef CONFIG_PNO_SUPPORT
694 static void ConstructProbeReq(struct adapter *padapter, u8 *pframe, u32 *pLength)
696 struct ieee80211_hdr *pwlanhdr;
700 unsigned char bssrate[NumRates];
701 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
702 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
703 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
704 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
706 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
708 pwlanhdr = (struct ieee80211_hdr *)pframe;
709 mac = myid(&(padapter->eeprompriv));
711 fctrl = &(pwlanhdr->frame_control);
714 /* broadcast probe request frame */
715 memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
716 memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
718 memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
720 SetSeqNum(pwlanhdr, 0);
721 SetFrameSubType(pframe, WIFI_PROBEREQ);
723 pktlen = sizeof(struct ieee80211_hdr_3addr);
726 pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &pktlen);
728 get_rate_set(padapter, bssrate, &bssrate_len);
732 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &pktlen);
733 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &pktlen);
737 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &pktlen);
742 #endif /* CONFIG_PNO_SUPPORT */
743 #endif /* CONFIG_WOWLAN */
745 #ifdef CONFIG_AP_WOWLAN
746 static void ConstructProbeRsp(struct adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID)
748 struct ieee80211_hdr *pwlanhdr;
752 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
753 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
754 struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
757 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
759 /* DBG_871X("%s\n", __func__); */
761 pwlanhdr = (struct ieee80211_hdr *)pframe;
763 mac = myid(&(padapter->eeprompriv));
764 bssid = cur_network->MacAddress;
766 fctrl = &(pwlanhdr->frame_control);
768 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
769 memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
770 memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
772 DBG_871X("%s FW Mac Addr:" MAC_FMT "\n", __func__, MAC_ARG(mac));
773 DBG_871X("%s FW IP Addr" IP_FMT "\n", __func__, IP_ARG(StaAddr));
775 SetSeqNum(pwlanhdr, 0);
776 SetFrameSubType(fctrl, WIFI_PROBERSP);
778 pktlen = sizeof(struct ieee80211_hdr_3addr);
781 if (cur_network->IELength>MAX_IE_SZ)
784 pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_,
785 cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
787 /* inerset & update wps_probe_resp_ie */
788 if ((pmlmepriv->wps_probe_resp_ie!= NULL) && pwps_ie && (wps_ielen>0)) {
789 uint wps_offset, remainder_ielen;
792 wps_offset = (uint)(pwps_ie - cur_network->IEs);
794 premainder_ie = pwps_ie + wps_ielen;
796 remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
798 memcpy(pframe, cur_network->IEs, wps_offset);
799 pframe += wps_offset;
800 pktlen += wps_offset;
802 wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
803 if ((wps_offset+wps_ielen+2)<=MAX_IE_SZ) {
804 memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
805 pframe += wps_ielen+2;
806 pktlen += wps_ielen+2;
809 if ((wps_offset+wps_ielen+2+remainder_ielen)<=MAX_IE_SZ) {
810 memcpy(pframe, premainder_ie, remainder_ielen);
811 pframe += remainder_ielen;
812 pktlen += remainder_ielen;
815 memcpy(pframe, cur_network->IEs, cur_network->IELength);
816 pframe += cur_network->IELength;
817 pktlen += cur_network->IELength;
820 /* retrieve SSID IE from cur_network->Ssid */
824 sint ssid_ielen_diff;
826 u8 *ies = pframe + sizeof(struct ieee80211_hdr_3addr);
828 ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, _SSID_IE_, &ssid_ielen,
829 (pframe-ies)-_FIXED_IE_LENGTH_);
831 ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen;
833 if (ssid_ie && cur_network->Ssid.SsidLength) {
834 uint remainder_ielen;
836 remainder_ie = ssid_ie+2;
837 remainder_ielen = (pframe-remainder_ie);
839 if (remainder_ielen > MAX_IE_SZ) {
840 DBG_871X_LEVEL(_drv_warning_, FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter));
841 remainder_ielen = MAX_IE_SZ;
844 memcpy(buf, remainder_ie, remainder_ielen);
845 memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen);
846 *(ssid_ie+1) = cur_network->Ssid.SsidLength;
847 memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength);
848 pframe += ssid_ielen_diff;
849 pktlen += ssid_ielen_diff;
856 #endif /* CONFIG_AP_WOWLAN */
858 /* To check if reserved page content is destroyed by beacon beacuse beacon is too large. */
859 /* 2010.06.23. Added by tynli. */
861 CheckFwRsvdPageContent(
862 struct adapter * Adapter
867 static void rtl8723b_set_FwRsvdPage_cmd(struct adapter *padapter, PRSVDPAGE_LOC rsvdpageloc)
869 u8 u1H2CRsvdPageParm[H2C_RSVDPAGE_LOC_LEN]={0};
871 DBG_871X("8723BRsvdPageLoc: ProbeRsp =%d PsPoll =%d Null =%d QoSNull =%d BTNull =%d\n",
872 rsvdpageloc->LocProbeRsp, rsvdpageloc->LocPsPoll,
873 rsvdpageloc->LocNullData, rsvdpageloc->LocQosNull,
874 rsvdpageloc->LocBTQosNull);
876 SET_8723B_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1H2CRsvdPageParm, rsvdpageloc->LocProbeRsp);
877 SET_8723B_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1H2CRsvdPageParm, rsvdpageloc->LocPsPoll);
878 SET_8723B_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocNullData);
879 SET_8723B_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocQosNull);
880 SET_8723B_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocBTQosNull);
882 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CRsvdPageParm:", u1H2CRsvdPageParm, H2C_RSVDPAGE_LOC_LEN);
883 FillH2CCmd8723B(padapter, H2C_8723B_RSVD_PAGE, H2C_RSVDPAGE_LOC_LEN, u1H2CRsvdPageParm);
886 static void rtl8723b_set_FwAoacRsvdPage_cmd(struct adapter *padapter, PRSVDPAGE_LOC rsvdpageloc)
889 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
890 u8 u1H2CAoacRsvdPageParm[H2C_AOAC_RSVDPAGE_LOC_LEN]={0};
892 DBG_871X("8723BAOACRsvdPageLoc: RWC =%d ArpRsp =%d NbrAdv =%d GtkRsp =%d GtkInfo =%d ProbeReq =%d NetworkList =%d\n",
893 rsvdpageloc->LocRemoteCtrlInfo, rsvdpageloc->LocArpRsp,
894 rsvdpageloc->LocNbrAdv, rsvdpageloc->LocGTKRsp,
895 rsvdpageloc->LocGTKInfo, rsvdpageloc->LocProbeReq,
896 rsvdpageloc->LocNetList);
898 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
899 SET_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1H2CAoacRsvdPageParm, rsvdpageloc->LocRemoteCtrlInfo);
900 SET_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1H2CAoacRsvdPageParm, rsvdpageloc->LocArpRsp);
901 /* SET_H2CCMD_AOAC_RSVDPAGE_LOC_NEIGHBOR_ADV(u1H2CAoacRsvdPageParm, rsvdpageloc->LocNbrAdv); */
902 SET_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_RSP(u1H2CAoacRsvdPageParm, rsvdpageloc->LocGTKRsp);
903 SET_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_INFO(u1H2CAoacRsvdPageParm, rsvdpageloc->LocGTKInfo);
905 SET_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1H2CAoacRsvdPageParm, rsvdpageloc->LocGTKEXTMEM);
906 #endif /* CONFIG_GTK_OL */
907 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CAoacRsvdPageParm:", u1H2CAoacRsvdPageParm, H2C_AOAC_RSVDPAGE_LOC_LEN);
908 FillH2CCmd8723B(padapter, H2C_8723B_AOAC_RSVD_PAGE, H2C_AOAC_RSVDPAGE_LOC_LEN, u1H2CAoacRsvdPageParm);
910 #ifdef CONFIG_PNO_SUPPORT
911 if (!pwrpriv->pno_in_resume) {
912 DBG_871X("NLO_INFO =%d\n", rsvdpageloc->LocPNOInfo);
913 memset(&u1H2CAoacRsvdPageParm, 0, sizeof(u1H2CAoacRsvdPageParm));
914 SET_H2CCMD_AOAC_RSVDPAGE_LOC_NLO_INFO(u1H2CAoacRsvdPageParm, rsvdpageloc->LocPNOInfo);
915 FillH2CCmd8723B(padapter, H2C_AOAC_RSVDPAGE3, H2C_AOAC_RSVDPAGE_LOC_LEN, u1H2CAoacRsvdPageParm);
921 #endif /* CONFIG_WOWLAN */
924 #ifdef CONFIG_AP_WOWLAN
925 static void rtl8723b_set_ap_wow_rsvdpage_cmd(struct adapter *padapter,
926 PRSVDPAGE_LOC rsvdpageloc)
929 u8 rsvdparm[H2C_AOAC_RSVDPAGE_LOC_LEN]={0};
931 header = rtw_read8(padapter, REG_BCNQ_BDNY);
933 DBG_871X("%s: beacon: %d, probeRsp: %d, header:0x%02x\n", __func__,
934 rsvdpageloc->LocApOffloadBCN,
935 rsvdpageloc->LocProbeRsp,
938 SET_H2CCMD_AP_WOWLAN_RSVDPAGE_LOC_BCN(rsvdparm,
939 rsvdpageloc->LocApOffloadBCN + header);
941 FillH2CCmd8723B(padapter, H2C_8723B_BCN_RSVDPAGE,
942 H2C_BCN_RSVDPAGE_LEN, rsvdparm);
946 memset(&rsvdparm, 0, sizeof(rsvdparm));
948 SET_H2CCMD_AP_WOWLAN_RSVDPAGE_LOC_ProbeRsp(
950 rsvdpageloc->LocProbeRsp + header);
952 FillH2CCmd8723B(padapter, H2C_8723B_PROBERSP_RSVDPAGE,
953 H2C_PROBERSP_RSVDPAGE_LEN, rsvdparm);
957 #endif /* CONFIG_AP_WOWLAN */
959 void rtl8723b_set_FwMediaStatusRpt_cmd(struct adapter *padapter, u8 mstatus, u8 macid)
961 u8 u1H2CMediaStatusRptParm[H2C_MEDIA_STATUS_RPT_LEN]={0};
964 DBG_871X("%s(): mstatus = %d macid =%d\n", __func__, mstatus, macid);
966 SET_8723B_H2CCMD_MSRRPT_PARM_OPMODE(u1H2CMediaStatusRptParm, mstatus);
967 SET_8723B_H2CCMD_MSRRPT_PARM_MACID_IND(u1H2CMediaStatusRptParm, 0);
968 SET_8723B_H2CCMD_MSRRPT_PARM_MACID(u1H2CMediaStatusRptParm, macid);
969 SET_8723B_H2CCMD_MSRRPT_PARM_MACID_END(u1H2CMediaStatusRptParm, macid_end);
971 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CMediaStatusRptParm:", u1H2CMediaStatusRptParm, H2C_MEDIA_STATUS_RPT_LEN);
972 FillH2CCmd8723B(padapter, H2C_8723B_MEDIA_STATUS_RPT, H2C_MEDIA_STATUS_RPT_LEN, u1H2CMediaStatusRptParm);
976 static void rtl8723b_set_FwKeepAlive_cmd(struct adapter *padapter, u8 benable, u8 pkt_type)
978 u8 u1H2CKeepAliveParm[H2C_KEEP_ALIVE_CTRL_LEN]={0};
979 u8 adopt = 1, check_period = 5;
981 DBG_871X("%s(): benable = %d\n", __func__, benable);
982 SET_8723B_H2CCMD_KEEPALIVE_PARM_ENABLE(u1H2CKeepAliveParm, benable);
983 SET_8723B_H2CCMD_KEEPALIVE_PARM_ADOPT(u1H2CKeepAliveParm, adopt);
984 SET_8723B_H2CCMD_KEEPALIVE_PARM_PKT_TYPE(u1H2CKeepAliveParm, pkt_type);
985 SET_8723B_H2CCMD_KEEPALIVE_PARM_CHECK_PERIOD(u1H2CKeepAliveParm, check_period);
987 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CKeepAliveParm:", u1H2CKeepAliveParm, H2C_KEEP_ALIVE_CTRL_LEN);
989 FillH2CCmd8723B(padapter, H2C_8723B_KEEP_ALIVE, H2C_KEEP_ALIVE_CTRL_LEN, u1H2CKeepAliveParm);
992 static void rtl8723b_set_FwDisconDecision_cmd(struct adapter *padapter, u8 benable)
994 u8 u1H2CDisconDecisionParm[H2C_DISCON_DECISION_LEN]={0};
995 u8 adopt = 1, check_period = 10, trypkt_num = 0;
997 DBG_871X("%s(): benable = %d\n", __func__, benable);
998 SET_8723B_H2CCMD_DISCONDECISION_PARM_ENABLE(u1H2CDisconDecisionParm, benable);
999 SET_8723B_H2CCMD_DISCONDECISION_PARM_ADOPT(u1H2CDisconDecisionParm, adopt);
1000 SET_8723B_H2CCMD_DISCONDECISION_PARM_CHECK_PERIOD(u1H2CDisconDecisionParm, check_period);
1001 SET_8723B_H2CCMD_DISCONDECISION_PARM_TRY_PKT_NUM(u1H2CDisconDecisionParm, trypkt_num);
1003 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CDisconDecisionParm:", u1H2CDisconDecisionParm, H2C_DISCON_DECISION_LEN);
1005 FillH2CCmd8723B(padapter, H2C_8723B_DISCON_DECISION, H2C_DISCON_DECISION_LEN, u1H2CDisconDecisionParm);
1007 #endif /* CONFIG_WOWLAN */
1009 void rtl8723b_set_FwMacIdConfig_cmd(struct adapter *padapter, u8 mac_id, u8 raid, u8 bw, u8 sgi, u32 mask)
1011 u8 u1H2CMacIdConfigParm[H2C_MACID_CFG_LEN]={0};
1013 DBG_871X("%s(): mac_id =%d raid = 0x%x bw =%d mask = 0x%x\n", __func__, mac_id, raid, bw, mask);
1015 SET_8723B_H2CCMD_MACID_CFG_MACID(u1H2CMacIdConfigParm, mac_id);
1016 SET_8723B_H2CCMD_MACID_CFG_RAID(u1H2CMacIdConfigParm, raid);
1017 SET_8723B_H2CCMD_MACID_CFG_SGI_EN(u1H2CMacIdConfigParm, (sgi)? 1:0);
1018 SET_8723B_H2CCMD_MACID_CFG_BW(u1H2CMacIdConfigParm, bw);
1019 SET_8723B_H2CCMD_MACID_CFG_RATE_MASK0(u1H2CMacIdConfigParm, (u8)(mask & 0x000000ff));
1020 SET_8723B_H2CCMD_MACID_CFG_RATE_MASK1(u1H2CMacIdConfigParm, (u8)((mask & 0x0000ff00) >>8));
1021 SET_8723B_H2CCMD_MACID_CFG_RATE_MASK2(u1H2CMacIdConfigParm, (u8)((mask & 0x00ff0000) >> 16));
1022 SET_8723B_H2CCMD_MACID_CFG_RATE_MASK3(u1H2CMacIdConfigParm, (u8)((mask & 0xff000000) >> 24));
1024 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CMacIdConfigParm:", u1H2CMacIdConfigParm, H2C_MACID_CFG_LEN);
1025 FillH2CCmd8723B(padapter, H2C_8723B_MACID_CFG, H2C_MACID_CFG_LEN, u1H2CMacIdConfigParm);
1028 static void rtl8723b_set_FwRssiSetting_cmd(struct adapter *padapter, u8 *param)
1030 u8 u1H2CRssiSettingParm[H2C_RSSI_SETTING_LEN]={0};
1032 u8 rssi = *(param+2);
1035 /* DBG_871X("%s(): param =%.2x-%.2x-%.2x\n", __func__, *param, *(param+1), *(param+2)); */
1036 /* DBG_871X("%s(): mac_id =%d rssi =%d\n", __func__, mac_id, rssi); */
1038 SET_8723B_H2CCMD_RSSI_SETTING_MACID(u1H2CRssiSettingParm, mac_id);
1039 SET_8723B_H2CCMD_RSSI_SETTING_RSSI(u1H2CRssiSettingParm, rssi);
1040 SET_8723B_H2CCMD_RSSI_SETTING_ULDL_STATE(u1H2CRssiSettingParm, uldl_state);
1042 RT_PRINT_DATA(_module_hal_init_c_, _drv_notice_, "u1H2CRssiSettingParm:", u1H2CRssiSettingParm, H2C_RSSI_SETTING_LEN);
1043 FillH2CCmd8723B(padapter, H2C_8723B_RSSI_SETTING, H2C_RSSI_SETTING_LEN, u1H2CRssiSettingParm);
1046 void rtl8723b_set_FwPwrMode_cmd(struct adapter *padapter, u8 psmode)
1049 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1050 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1051 u8 u1H2CPwrModeParm[H2C_PWRMODE_LEN]={0};
1052 u8 PowerState = 0, awake_intvl = 1, byte5 = 0, rlbm = 0;
1054 if (pwrpriv->dtim > 0)
1055 DBG_871X("%s(): FW LPS mode = %d, SmartPS =%d, dtim =%d\n", __func__, psmode, pwrpriv->smart_ps, pwrpriv->dtim);
1057 DBG_871X("%s(): FW LPS mode = %d, SmartPS =%d\n", __func__, psmode, pwrpriv->smart_ps);
1059 #ifdef CONFIG_WOWLAN
1060 if (psmode == PS_MODE_DTIM) /* For WOWLAN LPS, DTIM = (awake_intvl - 1) */
1062 awake_intvl = 3;/* DTIM =2 */
1066 #endif /* CONFIG_WOWLAN */
1068 if (pwrpriv->dtim > 0 && pwrpriv->dtim < 16)
1069 awake_intvl = pwrpriv->dtim+1;/* DTIM = (awake_intvl - 1) */
1071 awake_intvl = 3;/* DTIM =2 */
1077 if (padapter->registrypriv.wifi_spec == 1)
1085 if (rtw_btcoex_IsBtControlLps(padapter) == true)
1087 PowerState = rtw_btcoex_RpwmVal(padapter);
1088 byte5 = rtw_btcoex_LpsVal(padapter);
1090 if ((rlbm == 2) && (byte5 & BIT(4)))
1092 /* Keep awake interval to 1 to prevent from */
1093 /* decreasing coex performance */
1100 PowerState = 0x00;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */
1106 PowerState = 0x0C;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */
1110 SET_8723B_H2CCMD_PWRMODE_PARM_MODE(u1H2CPwrModeParm, (psmode>0)?1:0);
1111 SET_8723B_H2CCMD_PWRMODE_PARM_SMART_PS(u1H2CPwrModeParm, pwrpriv->smart_ps);
1112 SET_8723B_H2CCMD_PWRMODE_PARM_RLBM(u1H2CPwrModeParm, rlbm);
1113 SET_8723B_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1H2CPwrModeParm, awake_intvl);
1114 SET_8723B_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1H2CPwrModeParm, padapter->registrypriv.uapsd_enable);
1115 SET_8723B_H2CCMD_PWRMODE_PARM_PWR_STATE(u1H2CPwrModeParm, PowerState);
1116 SET_8723B_H2CCMD_PWRMODE_PARM_BYTE5(u1H2CPwrModeParm, byte5);
1117 if (psmode != PS_MODE_ACTIVE)
1119 if (pmlmeext ->adaptive_tsf_done == false && pmlmeext->bcn_cnt>0)
1121 u8 ratio_20_delay, ratio_80_delay;
1123 /* byte 6 for adaptive_early_32k */
1124 /* 0:3] = DrvBcnEarly (ms) , [4:7] = DrvBcnTimeOut (ms) */
1125 /* 20% for DrvBcnEarly, 80% for DrvBcnTimeOut */
1128 pmlmeext->DrvBcnEarly = 0xff;
1129 pmlmeext->DrvBcnTimeOut = 0xff;
1131 DBG_871X("%s(): bcn_cnt = %d\n", __func__, pmlmeext->bcn_cnt);
1133 for (i = 0; i<9; i++)
1135 pmlmeext->bcn_delay_ratio[i] = (pmlmeext->bcn_delay_cnt[i] * 100) /pmlmeext->bcn_cnt;
1137 DBG_871X("%s(): bcn_delay_cnt[%d]=%d, bcn_delay_ratio[%d] = %d\n", __func__, i, pmlmeext->bcn_delay_cnt[i]
1138 , i , pmlmeext->bcn_delay_ratio[i]);
1140 ratio_20_delay += pmlmeext->bcn_delay_ratio[i];
1141 ratio_80_delay += pmlmeext->bcn_delay_ratio[i];
1143 if (ratio_20_delay > 20 && pmlmeext->DrvBcnEarly == 0xff)
1145 pmlmeext->DrvBcnEarly = i;
1146 DBG_871X("%s(): DrvBcnEarly = %d\n", __func__, pmlmeext->DrvBcnEarly);
1149 if (ratio_80_delay > 80 && pmlmeext->DrvBcnTimeOut == 0xff)
1151 pmlmeext->DrvBcnTimeOut = i;
1152 DBG_871X("%s(): DrvBcnTimeOut = %d\n", __func__, pmlmeext->DrvBcnTimeOut);
1155 /* reset adaptive_early_32k cnt */
1156 pmlmeext->bcn_delay_cnt[i] = 0;
1157 pmlmeext->bcn_delay_ratio[i] = 0;
1161 pmlmeext->bcn_cnt = 0;
1162 pmlmeext ->adaptive_tsf_done = true;
1167 DBG_871X("%s(): DrvBcnEarly = %d\n", __func__, pmlmeext->DrvBcnEarly);
1168 DBG_871X("%s(): DrvBcnTimeOut = %d\n", __func__, pmlmeext->DrvBcnTimeOut);
1171 /* offload to FW if fw version > v15.10
1172 pmlmeext->DrvBcnEarly = 0;
1173 pmlmeext->DrvBcnTimeOut =7;
1175 if ((pmlmeext->DrvBcnEarly!= 0Xff) && (pmlmeext->DrvBcnTimeOut!= 0xff))
1176 u1H2CPwrModeParm[H2C_PWRMODE_LEN-1] = BIT(0) | ((pmlmeext->DrvBcnEarly<<1)&0x0E) |((pmlmeext->DrvBcnTimeOut<<4)&0xf0) ;
1181 rtw_btcoex_RecordPwrMode(padapter, u1H2CPwrModeParm, H2C_PWRMODE_LEN);
1183 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CPwrModeParm:", u1H2CPwrModeParm, H2C_PWRMODE_LEN);
1185 FillH2CCmd8723B(padapter, H2C_8723B_SET_PWR_MODE, H2C_PWRMODE_LEN, u1H2CPwrModeParm);
1188 void rtl8723b_set_FwPsTuneParam_cmd(struct adapter *padapter)
1190 u8 u1H2CPsTuneParm[H2C_PSTUNEPARAM_LEN]={0};
1191 u8 bcn_to_limit = 10; /* 10 * 100 * awakeinterval (ms) */
1192 u8 dtim_timeout = 5; /* ms wait broadcast data timer */
1193 u8 ps_timeout = 20; /* ms Keep awake when tx */
1196 /* DBG_871X("%s(): FW LPS mode = %d\n", __func__, psmode); */
1198 SET_8723B_H2CCMD_PSTUNE_PARM_BCN_TO_LIMIT(u1H2CPsTuneParm, bcn_to_limit);
1199 SET_8723B_H2CCMD_PSTUNE_PARM_DTIM_TIMEOUT(u1H2CPsTuneParm, dtim_timeout);
1200 SET_8723B_H2CCMD_PSTUNE_PARM_PS_TIMEOUT(u1H2CPsTuneParm, ps_timeout);
1201 SET_8723B_H2CCMD_PSTUNE_PARM_ADOPT(u1H2CPsTuneParm, 1);
1202 SET_8723B_H2CCMD_PSTUNE_PARM_DTIM_PERIOD(u1H2CPsTuneParm, dtim_period);
1204 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CPsTuneParm:", u1H2CPsTuneParm, H2C_PSTUNEPARAM_LEN);
1206 FillH2CCmd8723B(padapter, H2C_8723B_PS_TUNING_PARA, H2C_PSTUNEPARAM_LEN, u1H2CPsTuneParm);
1209 void rtl8723b_set_FwPwrModeInIPS_cmd(struct adapter *padapter, u8 cmd_param)
1211 /* BIT0:enable, BIT1:NoConnect32k */
1213 DBG_871X("%s()\n", __func__);
1215 FillH2CCmd8723B(padapter, H2C_8723B_FWLPS_IN_IPS_, 1, &cmd_param);
1218 #ifdef CONFIG_WOWLAN
1219 static void rtl8723b_set_FwWoWlanCtrl_Cmd(struct adapter *padapter, u8 bFuncEn)
1221 struct security_priv *psecpriv = &padapter->securitypriv;
1222 u8 u1H2CWoWlanCtrlParm[H2C_WOWLAN_LEN]={0};
1223 u8 discont_wake = 1, gpionum = 0, gpio_dur = 0, hw_unicast = 0;
1224 u8 sdio_wakeup_enable = 1;
1225 u8 gpio_high_active = 0; /* 0: low active, 1: high active */
1228 #ifdef CONFIG_GPIO_WAKEUP
1229 gpionum = WAKEUP_GPIO_IDX;
1230 sdio_wakeup_enable = 0;
1233 #ifdef CONFIG_PNO_SUPPORT
1234 if (!ppwrpriv->wowlan_pno_enable) {
1239 if (psecpriv->dot11PrivacyAlgrthm == _WEP40_ || psecpriv->dot11PrivacyAlgrthm == _WEP104_)
1242 DBG_871X("%s(): bFuncEn =%d\n", __func__, bFuncEn);
1244 SET_H2CCMD_WOWLAN_FUNC_ENABLE(u1H2CWoWlanCtrlParm, bFuncEn);
1245 SET_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(u1H2CWoWlanCtrlParm, 0);
1246 SET_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(u1H2CWoWlanCtrlParm, magic_pkt);
1247 SET_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(u1H2CWoWlanCtrlParm, hw_unicast);
1248 SET_H2CCMD_WOWLAN_ALL_PKT_DROP(u1H2CWoWlanCtrlParm, 0);
1249 SET_H2CCMD_WOWLAN_GPIO_ACTIVE(u1H2CWoWlanCtrlParm, gpio_high_active);
1250 SET_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(u1H2CWoWlanCtrlParm, discont_wake);
1251 SET_H2CCMD_WOWLAN_GPIONUM(u1H2CWoWlanCtrlParm, gpionum);
1252 SET_H2CCMD_WOWLAN_DATAPIN_WAKE_UP(u1H2CWoWlanCtrlParm, sdio_wakeup_enable);
1253 SET_H2CCMD_WOWLAN_GPIO_DURATION(u1H2CWoWlanCtrlParm, gpio_dur);
1254 /* SET_H2CCMD_WOWLAN_GPIO_PULSE_EN(u1H2CWoWlanCtrlParm, 1); */
1255 SET_H2CCMD_WOWLAN_GPIO_PULSE_COUNT(u1H2CWoWlanCtrlParm, 0x09);
1257 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CWoWlanCtrlParm:", u1H2CWoWlanCtrlParm, H2C_WOWLAN_LEN);
1259 FillH2CCmd8723B(padapter, H2C_8723B_WOWLAN, H2C_WOWLAN_LEN, u1H2CWoWlanCtrlParm);
1262 static void rtl8723b_set_FwRemoteWakeCtrl_Cmd(struct adapter *padapter, u8 benable)
1264 u8 u1H2CRemoteWakeCtrlParm[H2C_REMOTE_WAKE_CTRL_LEN]={0};
1265 struct security_priv* psecuritypriv =&(padapter->securitypriv);
1266 struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(padapter);
1268 DBG_871X("%s(): Enable =%d\n", __func__, benable);
1270 if (!ppwrpriv->wowlan_pno_enable) {
1271 SET_H2CCMD_REMOTE_WAKECTRL_ENABLE(u1H2CRemoteWakeCtrlParm, benable);
1272 SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(u1H2CRemoteWakeCtrlParm, 1);
1273 #ifdef CONFIG_GTK_OL
1274 if (psecuritypriv->binstallKCK_KEK &&
1275 psecuritypriv->dot11PrivacyAlgrthm == _AES_) {
1276 SET_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(u1H2CRemoteWakeCtrlParm, 1);
1278 DBG_871X("no kck or security is not AES\n");
1279 SET_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(u1H2CRemoteWakeCtrlParm, 0);
1281 #endif /* CONFIG_GTK_OL */
1283 SET_H2CCMD_REMOTE_WAKE_CTRL_FW_UNICAST_EN(u1H2CRemoteWakeCtrlParm, 1);
1285 if ((psecuritypriv->dot11PrivacyAlgrthm == _AES_) ||
1286 (psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_))
1287 SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_ACTION(u1H2CRemoteWakeCtrlParm, 0);
1289 SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_ACTION(u1H2CRemoteWakeCtrlParm, 1);
1291 #ifdef CONFIG_PNO_SUPPORT
1293 SET_H2CCMD_REMOTE_WAKECTRL_ENABLE(u1H2CRemoteWakeCtrlParm, benable);
1294 SET_H2CCMD_REMOTE_WAKE_CTRL_NLO_OFFLOAD_EN(u1H2CRemoteWakeCtrlParm, benable);
1297 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CRemoteWakeCtrlParm:", u1H2CRemoteWakeCtrlParm, H2C_REMOTE_WAKE_CTRL_LEN);
1298 FillH2CCmd8723B(padapter, H2C_8723B_REMOTE_WAKE_CTRL,
1299 H2C_REMOTE_WAKE_CTRL_LEN, u1H2CRemoteWakeCtrlParm);
1300 #ifdef CONFIG_PNO_SUPPORT
1301 if (ppwrpriv->wowlan_pno_enable && ppwrpriv->pno_in_resume == false) {
1302 res = rtw_read8(padapter, REG_PNO_STATUS);
1303 DBG_871X("cmd: 0x81 REG_PNO_STATUS: 0x%02x\n", res);
1304 while (!(res&BIT(7)) && count < 25) {
1305 DBG_871X("[%d] cmd: 0x81 REG_PNO_STATUS: 0x%02x\n", count, res);
1306 res = rtw_read8(padapter, REG_PNO_STATUS);
1310 DBG_871X("cmd: 0x81 REG_PNO_STATUS: 0x%02x\n", res);
1312 #endif /* CONFIG_PNO_SUPPORT */
1315 static void rtl8723b_set_FwAOACGlobalInfo_Cmd(struct adapter *padapter, u8 group_alg, u8 pairwise_alg)
1317 u8 u1H2CAOACGlobalInfoParm[H2C_AOAC_GLOBAL_INFO_LEN]={0};
1319 DBG_871X("%s(): group_alg =%d pairwise_alg =%d\n", __func__, group_alg, pairwise_alg);
1321 SET_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(u1H2CAOACGlobalInfoParm, pairwise_alg);
1322 SET_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(u1H2CAOACGlobalInfoParm, group_alg);
1324 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CAOACGlobalInfoParm:", u1H2CAOACGlobalInfoParm, H2C_AOAC_GLOBAL_INFO_LEN);
1326 FillH2CCmd8723B(padapter, H2C_8723B_AOAC_GLOBAL_INFO, H2C_AOAC_GLOBAL_INFO_LEN, u1H2CAOACGlobalInfoParm);
1329 #ifdef CONFIG_PNO_SUPPORT
1330 static void rtl8723b_set_FwScanOffloadInfo_cmd(struct adapter *padapter, PRSVDPAGE_LOC rsvdpageloc, u8 enable)
1332 u8 u1H2CScanOffloadInfoParm[H2C_SCAN_OFFLOAD_CTRL_LEN]={0};
1333 u8 res = 0, count = 0;
1334 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1336 DBG_871X("%s: loc_probe_packet:%d, loc_scan_info: %d loc_ssid_info:%d\n",
1337 __func__, rsvdpageloc->LocProbePacket, rsvdpageloc->LocScanInfo, rsvdpageloc->LocSSIDInfo);
1339 SET_H2CCMD_AOAC_NLO_FUN_EN(u1H2CScanOffloadInfoParm, enable);
1340 SET_H2CCMD_AOAC_RSVDPAGE_LOC_SCAN_INFO(u1H2CScanOffloadInfoParm, rsvdpageloc->LocScanInfo);
1341 SET_H2CCMD_AOAC_RSVDPAGE_LOC_PROBE_PACKET(u1H2CScanOffloadInfoParm, rsvdpageloc->LocProbePacket);
1342 SET_H2CCMD_AOAC_RSVDPAGE_LOC_SSID_INFO(u1H2CScanOffloadInfoParm, rsvdpageloc->LocSSIDInfo);
1344 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CScanOffloadInfoParm:", u1H2CScanOffloadInfoParm, H2C_SCAN_OFFLOAD_CTRL_LEN);
1345 FillH2CCmd8723B(padapter, H2C_8723B_D0_SCAN_OFFLOAD_INFO, H2C_SCAN_OFFLOAD_CTRL_LEN, u1H2CScanOffloadInfoParm);
1349 #endif /* CONFIG_PNO_SUPPORT */
1351 static void rtl8723b_set_FwWoWlanRelated_cmd(struct adapter *padapter, u8 enable)
1353 struct security_priv *psecpriv = &padapter->securitypriv;
1354 struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(padapter);
1355 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1356 struct sta_info *psta = NULL;
1359 DBG_871X_LEVEL(_drv_always_, "+%s()+: enable =%d\n", __func__, enable);
1361 rtl8723b_set_FwAOACGlobalInfo_Cmd(padapter, psecpriv->dot118021XGrpPrivacy, psecpriv->dot11PrivacyAlgrthm);
1363 rtl8723b_set_FwJoinBssRpt_cmd(padapter, RT_MEDIA_CONNECT); /* RT_MEDIA_CONNECT will confuse in the future */
1365 if (!(ppwrpriv->wowlan_pno_enable))
1367 psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(pmlmepriv));
1369 rtl8723b_set_FwMediaStatusRpt_cmd(padapter, RT_MEDIA_CONNECT, psta->mac_id);
1372 DBG_871X("%s(): Disconnected, no FwMediaStatusRpt CONNECT\n", __func__);
1376 if (!(ppwrpriv->wowlan_pno_enable)) {
1377 rtl8723b_set_FwDisconDecision_cmd(padapter, enable);
1380 if ((psecpriv->dot11PrivacyAlgrthm != _WEP40_) || (psecpriv->dot11PrivacyAlgrthm != _WEP104_))
1382 rtl8723b_set_FwKeepAlive_cmd(padapter, enable, pkt_type);
1386 rtl8723b_set_FwWoWlanCtrl_Cmd(padapter, enable);
1389 rtl8723b_set_FwRemoteWakeCtrl_Cmd(padapter, enable);
1393 rtl8723b_set_FwRemoteWakeCtrl_Cmd(padapter, enable);
1395 rtl8723b_set_FwWoWlanCtrl_Cmd(padapter, enable);
1398 DBG_871X_LEVEL(_drv_always_, "-%s()-\n", __func__);
1402 void rtl8723b_set_wowlan_cmd(struct adapter *padapter, u8 enable)
1404 rtl8723b_set_FwWoWlanRelated_cmd(padapter, enable);
1406 #endif /* CONFIG_WOWLAN */
1408 #ifdef CONFIG_AP_WOWLAN
1409 static void rtl8723b_set_FwAPWoWlanCtrl_Cmd(struct adapter *padapter, u8 bFuncEn)
1411 u8 u1H2CAPWoWlanCtrlParm[H2C_WOWLAN_LEN]={0};
1412 u8 gpionum = 0, gpio_dur = 0;
1413 u8 gpio_high_active = 1; /* 0: low active, 1: high active */
1414 u8 gpio_pulse = bFuncEn;
1415 #ifdef CONFIG_GPIO_WAKEUP
1416 gpionum = WAKEUP_GPIO_IDX;
1419 DBG_871X("%s(): bFuncEn =%d\n", __func__, bFuncEn);
1426 SET_H2CCMD_AP_WOW_GPIO_CTRL_INDEX(u1H2CAPWoWlanCtrlParm,
1428 SET_H2CCMD_AP_WOW_GPIO_CTRL_PLUS(u1H2CAPWoWlanCtrlParm,
1430 SET_H2CCMD_AP_WOW_GPIO_CTRL_HIGH_ACTIVE(u1H2CAPWoWlanCtrlParm,
1432 SET_H2CCMD_AP_WOW_GPIO_CTRL_EN(u1H2CAPWoWlanCtrlParm,
1434 SET_H2CCMD_AP_WOW_GPIO_CTRL_DURATION(u1H2CAPWoWlanCtrlParm,
1437 FillH2CCmd8723B(padapter, H2C_8723B_AP_WOW_GPIO_CTRL,
1438 H2C_AP_WOW_GPIO_CTRL_LEN, u1H2CAPWoWlanCtrlParm);
1441 static void rtl8723b_set_Fw_AP_Offload_Cmd(struct adapter *padapter, u8 bFuncEn)
1443 u8 u1H2CAPOffloadCtrlParm[H2C_WOWLAN_LEN]={0};
1445 DBG_871X("%s(): bFuncEn =%d\n", __func__, bFuncEn);
1447 SET_H2CCMD_AP_WOWLAN_EN(u1H2CAPOffloadCtrlParm, bFuncEn);
1449 FillH2CCmd8723B(padapter, H2C_8723B_AP_OFFLOAD,
1450 H2C_AP_OFFLOAD_LEN, u1H2CAPOffloadCtrlParm);
1453 static void rtl8723b_set_AP_FwWoWlan_cmd(struct adapter *padapter, u8 enable)
1455 DBG_871X_LEVEL(_drv_always_, "+%s()+: enable =%d\n", __func__, enable);
1457 rtl8723b_set_FwJoinBssRpt_cmd(padapter, RT_MEDIA_CONNECT);
1458 issue_beacon(padapter, 0);
1461 rtl8723b_set_FwAPWoWlanCtrl_Cmd(padapter, enable);
1463 rtl8723b_set_Fw_AP_Offload_Cmd(padapter, enable);
1465 DBG_871X_LEVEL(_drv_always_, "-%s()-\n", __func__);
1469 void rtl8723b_set_ap_wowlan_cmd(struct adapter *padapter, u8 enable)
1471 rtl8723b_set_AP_FwWoWlan_cmd(padapter, enable);
1473 #endif /* CONFIG_AP_WOWLAN */
1476 /* Description: Fill the reserved packets that FW will use to RSVD page. */
1477 /* Now we just send 4 types packet to rsvd page. */
1478 /* (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */
1480 /* bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */
1481 /* so we need to set the packet length to total lengh. */
1482 /* true: At the second time, we should send the first packet (default:beacon) */
1483 /* to Hw again and set the lengh in descriptor to the real beacon lengh. */
1484 /* 2009.10.15 by tynli. */
1485 static void rtl8723b_set_FwRsvdPagePkt(struct adapter *padapter, bool bDLFinished)
1487 struct hal_com_data *pHalData;
1488 struct xmit_frame *pcmdframe;
1489 struct pkt_attrib *pattrib;
1490 struct xmit_priv *pxmitpriv;
1491 struct mlme_ext_priv *pmlmeext;
1492 struct mlme_ext_info *pmlmeinfo;
1493 struct pwrctrl_priv *pwrctl;
1494 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1495 u32 BeaconLength = 0, PSPollLength = 0;
1496 u32 NullDataLength = 0, QosNullLength = 0, BTQosNullLength = 0;
1497 u8 *ReservedPagePacket;
1498 u8 TxDescLen = TXDESC_SIZE, TxDescOffset = TXDESC_OFFSET;
1499 u8 TotalPageNum = 0, CurtPktPageNum = 0, RsvdPageNum = 0;
1500 u16 BufIndex, PageSize = 128;
1501 u32 TotalPacketLen, MaxRsvdPageBufSize = 0;
1502 RSVDPAGE_LOC RsvdPageLoc;
1503 #ifdef CONFIG_WOWLAN
1504 u32 ARPLegnth = 0, GTKLegnth = 0;
1506 u8 cur_dot11txpn[8];
1507 #ifdef CONFIG_GTK_OL
1508 struct sta_priv *pstapriv = &padapter->stapriv;
1509 struct sta_info * psta;
1510 u8 kek[RTW_KEK_LEN];
1511 u8 kck[RTW_KCK_LEN];
1515 /* DBG_871X("%s---->\n", __func__); */
1517 pHalData = GET_HAL_DATA(padapter);
1518 pxmitpriv = &padapter->xmitpriv;
1519 pmlmeext = &padapter->mlmeextpriv;
1520 pmlmeinfo = &pmlmeext->mlmext_info;
1521 pwrctl = adapter_to_pwrctl(padapter);
1523 RsvdPageNum = BCNQ_PAGE_NUM_8723B + WOWLAN_PAGE_NUM_8723B;
1524 MaxRsvdPageBufSize = RsvdPageNum*PageSize;
1526 pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv);
1527 if (pcmdframe == NULL) {
1528 DBG_871X("%s: alloc ReservedPagePacket fail!\n", __func__);
1532 ReservedPagePacket = pcmdframe->buf_addr;
1533 memset(&RsvdPageLoc, 0, sizeof(RSVDPAGE_LOC));
1536 BufIndex = TxDescOffset;
1537 ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
1539 /* When we count the first page size, we need to reserve description size for the RSVD */
1540 /* packet, it will be filled in front of the packet in TXPKTBUF. */
1541 CurtPktPageNum = (u8)PageNum_128(TxDescLen + BeaconLength);
1542 /* If we don't add 1 more page, the WOWLAN function has a problem. Baron thinks it's a bug of firmware */
1543 if (CurtPktPageNum == 1)
1545 CurtPktPageNum += 1;
1547 TotalPageNum += CurtPktPageNum;
1549 BufIndex += (CurtPktPageNum*PageSize);
1552 RsvdPageLoc.LocPsPoll = TotalPageNum;
1553 ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);
1554 rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false, false);
1556 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: PS-POLL %p %d\n", */
1557 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], (PSPollLength+TxDescLen)); */
1559 CurtPktPageNum = (u8)PageNum_128(TxDescLen + PSPollLength);
1561 TotalPageNum += CurtPktPageNum;
1563 BufIndex += (CurtPktPageNum*PageSize);
1565 /* 3 (3) null data */
1566 RsvdPageLoc.LocNullData = TotalPageNum;
1567 ConstructNullFunctionData(
1569 &ReservedPagePacket[BufIndex],
1571 get_my_bssid(&pmlmeinfo->network),
1572 false, 0, 0, false);
1573 rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false, false);
1575 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: NULL DATA %p %d\n", */
1576 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], (NullDataLength+TxDescLen)); */
1578 CurtPktPageNum = (u8)PageNum_128(TxDescLen + NullDataLength);
1580 TotalPageNum += CurtPktPageNum;
1582 BufIndex += (CurtPktPageNum*PageSize);
1584 /* 3 (5) Qos null data */
1585 RsvdPageLoc.LocQosNull = TotalPageNum;
1586 ConstructNullFunctionData(
1588 &ReservedPagePacket[BufIndex],
1590 get_my_bssid(&pmlmeinfo->network),
1592 rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false, false);
1594 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: QOS NULL DATA %p %d\n", */
1595 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], (QosNullLength+TxDescLen)); */
1597 CurtPktPageNum = (u8)PageNum_128(TxDescLen + QosNullLength);
1599 TotalPageNum += CurtPktPageNum;
1601 BufIndex += (CurtPktPageNum*PageSize);
1603 /* 3 (6) BT Qos null data */
1604 RsvdPageLoc.LocBTQosNull = TotalPageNum;
1605 ConstructNullFunctionData(
1607 &ReservedPagePacket[BufIndex],
1609 get_my_bssid(&pmlmeinfo->network),
1611 rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true, false);
1613 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: BT QOS NULL DATA %p %d\n", */
1614 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], (BTQosNullLength+TxDescLen)); */
1616 CurtPktPageNum = (u8)PageNum_128(TxDescLen + BTQosNullLength);
1618 TotalPageNum += CurtPktPageNum;
1620 BufIndex += (CurtPktPageNum*PageSize);
1622 #ifdef CONFIG_WOWLAN
1623 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1624 /* if (pwrctl->wowlan_mode == true) { */
1625 /* BufIndex += (CurtPktPageNum*PageSize); */
1628 rtw_get_current_ip_address(padapter, currentip);
1629 RsvdPageLoc.LocArpRsp = TotalPageNum;
1631 ConstructARPResponse(
1633 &ReservedPagePacket[BufIndex],
1637 rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], ARPLegnth, false, false, true);
1639 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: ARP RSP %p %d\n", */
1640 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], (ARPLegnth+TxDescLen)); */
1642 CurtPktPageNum = (u8)PageNum_128(TxDescLen + ARPLegnth);
1644 TotalPageNum += CurtPktPageNum;
1646 BufIndex += (CurtPktPageNum*PageSize);
1649 rtw_get_sec_iv(padapter, cur_dot11txpn, get_my_bssid(&pmlmeinfo->network));
1650 RsvdPageLoc.LocRemoteCtrlInfo = TotalPageNum;
1651 memcpy(ReservedPagePacket+BufIndex-TxDescLen, cur_dot11txpn, _AES_IV_LEN_);
1653 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: SEC IV %p %d\n", */
1654 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], _AES_IV_LEN_); */
1656 CurtPktPageNum = (u8)PageNum_128(_AES_IV_LEN_);
1658 TotalPageNum += CurtPktPageNum;
1660 #ifdef CONFIG_GTK_OL
1661 BufIndex += (CurtPktPageNum*PageSize);
1663 /* if the ap staion info. exists, get the kek, kck from staion info. */
1664 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
1667 memset(kek, 0, RTW_KEK_LEN);
1668 memset(kck, 0, RTW_KCK_LEN);
1669 DBG_8192C("%s, KEK, KCK download rsvd page all zero\n", __func__);
1673 memcpy(kek, psta->kek, RTW_KEK_LEN);
1674 memcpy(kck, psta->kck, RTW_KCK_LEN);
1678 RsvdPageLoc.LocGTKInfo = TotalPageNum;
1679 memcpy(ReservedPagePacket+BufIndex-TxDescLen, kck, RTW_KCK_LEN);
1680 memcpy(ReservedPagePacket+BufIndex-TxDescLen+RTW_KCK_LEN, kek, RTW_KEK_LEN);
1682 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: KEK KCK %p %d\n", */
1683 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], (TxDescLen + RTW_KCK_LEN + RTW_KEK_LEN)); */
1685 CurtPktPageNum = (u8)PageNum_128(TxDescLen + RTW_KCK_LEN + RTW_KEK_LEN);
1687 TotalPageNum += CurtPktPageNum;
1689 BufIndex += (CurtPktPageNum*PageSize);
1691 /* 3(10) GTK Response */
1692 RsvdPageLoc.LocGTKRsp = TotalPageNum;
1693 ConstructGTKResponse(
1695 &ReservedPagePacket[BufIndex],
1699 rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], GTKLegnth, false, false, true);
1700 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: GTK RSP %p %d\n", */
1701 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], (TxDescLen + GTKLegnth)); */
1703 CurtPktPageNum = (u8)PageNum_128(TxDescLen + GTKLegnth);
1705 TotalPageNum += CurtPktPageNum;
1707 BufIndex += (CurtPktPageNum*PageSize);
1709 /* below page is empty for GTK extension memory */
1710 /* 3(11) GTK EXT MEM */
1711 RsvdPageLoc.LocGTKEXTMEM = TotalPageNum;
1715 TotalPageNum += CurtPktPageNum;
1717 TotalPacketLen = BufIndex-TxDescLen + 256; /* extension memory for FW */
1719 TotalPacketLen = BufIndex-TxDescLen + sizeof (union pn48); /* IV len */
1720 #endif /* CONFIG_GTK_OL */
1722 #endif /* CONFIG_WOWLAN */
1724 #ifdef CONFIG_PNO_SUPPORT
1725 if (pwrctl->pno_in_resume == false && pwrctl->pno_inited == true) {
1727 RsvdPageLoc.LocProbePacket = TotalPageNum;
1730 &ReservedPagePacket[BufIndex],
1733 rtl8723b_fill_fake_txdesc(padapter,
1734 &ReservedPagePacket[BufIndex-TxDescLen],
1735 ProbeReqLength, false, false, false);
1736 #ifdef CONFIG_PNO_SET_DEBUG
1739 printk("probe req pkt =>\n");
1740 for (gj = 0; gj < ProbeReqLength + TxDescLen; gj++) {
1741 printk(" %02x ", ReservedPagePacket[BufIndex- TxDescLen + gj]);
1742 if ((gj + 1)%8 == 0)
1749 (u8)PageNum_128(TxDescLen + ProbeReqLength);
1751 TotalPageNum += CurtPktPageNum;
1753 BufIndex += (CurtPktPageNum*PageSize);
1756 RsvdPageLoc.LocPNOInfo = TotalPageNum;
1757 ConstructPnoInfo(padapter, &ReservedPagePacket[BufIndex -TxDescLen], &PNOLength);
1758 #ifdef CONFIG_PNO_SET_DEBUG
1761 printk("PNO pkt =>\n");
1762 for (gj = 0; gj < PNOLength; gj++) {
1763 printk(" %02x ", ReservedPagePacket[BufIndex-TxDescLen +gj]);
1764 if ((gj + 1)%8 == 0)
1771 CurtPktPageNum = (u8)PageNum_128(PNOLength);
1772 TotalPageNum += CurtPktPageNum;
1773 BufIndex += (CurtPktPageNum*PageSize);
1775 /* SSID List Page */
1776 RsvdPageLoc.LocSSIDInfo = TotalPageNum;
1777 ConstructSSIDList(padapter, &ReservedPagePacket[BufIndex-TxDescLen], &SSIDLegnth);
1778 #ifdef CONFIG_PNO_SET_DEBUG
1781 printk("SSID list pkt =>\n");
1782 for (gj = 0; gj < SSIDLegnth; gj++) {
1783 printk(" %02x ", ReservedPagePacket[BufIndex-TxDescLen+gj]);
1784 if ((gj + 1)%8 == 0)
1790 CurtPktPageNum = (u8)PageNum_128(SSIDLegnth);
1791 TotalPageNum += CurtPktPageNum;
1792 BufIndex += (CurtPktPageNum*PageSize);
1794 /* Scan Info Page */
1795 RsvdPageLoc.LocScanInfo = TotalPageNum;
1796 ConstructScanInfo(padapter, &ReservedPagePacket[BufIndex-TxDescLen], &ScanInfoLength);
1797 #ifdef CONFIG_PNO_SET_DEBUG
1800 printk("Scan info pkt =>\n");
1801 for (gj = 0; gj < ScanInfoLength; gj++) {
1802 printk(" %02x ", ReservedPagePacket[BufIndex-TxDescLen+gj]);
1803 if ((gj + 1)%8 == 0)
1809 CurtPktPageNum = (u8)PageNum_128(ScanInfoLength);
1810 TotalPageNum += CurtPktPageNum;
1811 BufIndex += (CurtPktPageNum*PageSize);
1813 TotalPacketLen = BufIndex + ScanInfoLength;
1815 TotalPacketLen = BufIndex + BTQosNullLength;
1817 #else /* CONFIG_PNO_SUPPORT */
1818 TotalPacketLen = BufIndex + BTQosNullLength;
1822 if (TotalPacketLen > MaxRsvdPageBufSize)
1824 DBG_871X("%s(): ERROR: The rsvd page size is not enough!!TotalPacketLen %d, MaxRsvdPageBufSize %d\n", __func__,
1825 TotalPacketLen, MaxRsvdPageBufSize);
1830 /* update attribute */
1831 pattrib = &pcmdframe->attrib;
1832 update_mgntframe_attrib(padapter, pattrib);
1833 pattrib->qsel = 0x10;
1834 pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TxDescOffset;
1835 dump_mgntframe_and_wait(padapter, pcmdframe, 100);
1838 DBG_871X("%s: Set RSVD page location to Fw , TotalPacketLen(%d), TotalPageNum(%d)\n", __func__, TotalPacketLen, TotalPageNum);
1839 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1840 rtl8723b_set_FwRsvdPage_cmd(padapter, &RsvdPageLoc);
1841 rtl8723b_set_FwAoacRsvdPage_cmd(padapter, &RsvdPageLoc);
1843 rtl8723b_set_FwAoacRsvdPage_cmd(padapter, &RsvdPageLoc);
1844 #ifdef CONFIG_PNO_SUPPORT
1845 if (pwrctl->pno_in_resume)
1846 rtl8723b_set_FwScanOffloadInfo_cmd(padapter,
1849 rtl8723b_set_FwScanOffloadInfo_cmd(padapter,
1857 rtw_free_xmitframe(pxmitpriv, pcmdframe);
1860 #ifdef CONFIG_AP_WOWLAN
1862 /* Description: Fill the reserved packets that FW will use to RSVD page. */
1863 /* Now we just send 2 types packet to rsvd page. (1)Beacon, (2)ProbeRsp. */
1865 /* Input: bDLFinished */
1867 /* false: At the first time we will send all the packets as a large packet to Hw, */
1868 /* so we need to set the packet length to total lengh. */
1870 /* true: At the second time, we should send the first packet (default:beacon) */
1871 /* to Hw again and set the lengh in descriptor to the real beacon lengh. */
1872 /* 2009.10.15 by tynli. */
1873 static void rtl8723b_set_AP_FwRsvdPagePkt(struct adapter *padapter,
1876 struct hal_com_data *pHalData;
1877 struct xmit_frame *pcmdframe;
1878 struct pkt_attrib *pattrib;
1879 struct xmit_priv *pxmitpriv;
1880 struct mlme_ext_priv *pmlmeext;
1881 struct mlme_ext_info *pmlmeinfo;
1882 struct pwrctrl_priv *pwrctl;
1883 u32 BeaconLength = 0, ProbeRspLength = 0;
1884 u8 *ReservedPagePacket;
1885 u8 TxDescLen = TXDESC_SIZE, TxDescOffset = TXDESC_OFFSET;
1886 u8 TotalPageNum = 0, CurtPktPageNum = 0, RsvdPageNum = 0;
1888 u16 BufIndex, PageSize = 128;
1889 u32 TotalPacketLen = 0, MaxRsvdPageBufSize = 0;
1890 RSVDPAGE_LOC RsvdPageLoc;
1892 /* DBG_871X("%s---->\n", __func__); */
1893 DBG_8192C("+" FUNC_ADPT_FMT ": iface_type =%d\n",
1894 FUNC_ADPT_ARG(padapter), get_iface_type(padapter));
1896 pHalData = GET_HAL_DATA(padapter);
1897 pxmitpriv = &padapter->xmitpriv;
1898 pmlmeext = &padapter->mlmeextpriv;
1899 pmlmeinfo = &pmlmeext->mlmext_info;
1900 pwrctl = adapter_to_pwrctl(padapter);
1902 RsvdPageNum = BCNQ_PAGE_NUM_8723B + AP_WOWLAN_PAGE_NUM_8723B;
1903 MaxRsvdPageBufSize = RsvdPageNum*PageSize;
1905 pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv);
1906 if (pcmdframe == NULL) {
1907 DBG_871X("%s: alloc ReservedPagePacket fail!\n", __func__);
1911 ReservedPagePacket = pcmdframe->buf_addr;
1912 memset(&RsvdPageLoc, 0, sizeof(RSVDPAGE_LOC));
1915 BufIndex = TxDescOffset;
1916 ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
1918 /* When we count the first page size, we need to reserve description size for the RSVD */
1919 /* packet, it will be filled in front of the packet in TXPKTBUF. */
1920 CurtPktPageNum = (u8)PageNum_128(TxDescLen + BeaconLength);
1921 /* If we don't add 1 more page, the WOWLAN function has a problem. Baron thinks it's a bug of firmware */
1922 if (CurtPktPageNum == 1)
1924 CurtPktPageNum += 1;
1926 TotalPageNum += CurtPktPageNum;
1928 BufIndex += (CurtPktPageNum*PageSize);
1930 /* 2 (4) probe response */
1931 RsvdPageLoc.LocProbeRsp = TotalPageNum;
1933 rtw_get_current_ip_address(padapter, currentip);
1937 &ReservedPagePacket[BufIndex],
1941 rtl8723b_fill_fake_txdesc(padapter,
1942 &ReservedPagePacket[BufIndex-TxDescLen],
1944 false, false, false);
1946 DBG_871X("%s(): HW_VAR_SET_TX_CMD: PROBE RSP %p %d\n",
1947 __func__, &ReservedPagePacket[BufIndex-TxDescLen],
1948 (ProbeRspLength+TxDescLen));
1950 CurtPktPageNum = (u8)PageNum_128(TxDescLen + ProbeRspLength);
1952 TotalPageNum += CurtPktPageNum;
1954 BufIndex += (CurtPktPageNum*PageSize);
1956 TotalPacketLen = BufIndex + ProbeRspLength;
1958 if (TotalPacketLen > MaxRsvdPageBufSize) {
1959 DBG_871X("%s(): ERROR: The rsvd page size is not enough \
1960 !!TotalPacketLen %d, MaxRsvdPageBufSize %d\n",
1961 __func__, TotalPacketLen, MaxRsvdPageBufSize);
1964 /* update attribute */
1965 pattrib = &pcmdframe->attrib;
1966 update_mgntframe_attrib(padapter, pattrib);
1967 pattrib->qsel = 0x10;
1968 pattrib->pktlen = TotalPacketLen - TxDescOffset;
1969 pattrib->last_txcmdsz = TotalPacketLen - TxDescOffset;
1970 dump_mgntframe_and_wait(padapter, pcmdframe, 100);
1973 DBG_871X("%s: Set RSVD page location to Fw , TotalPacketLen(%d), TotalPageNum(%d)\n", __func__, TotalPacketLen, TotalPageNum);
1974 rtl8723b_set_ap_wow_rsvdpage_cmd(padapter, &RsvdPageLoc);
1978 rtw_free_xmitframe(pxmitpriv, pcmdframe);
1980 #endif /* CONFIG_AP_WOWLAN */
1982 void rtl8723b_download_rsvd_page(struct adapter *padapter, u8 mstatus)
1984 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1985 #ifdef CONFIG_AP_WOWLAN
1986 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1988 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1989 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1990 bool bcn_valid = false;
1995 DBG_8192C("+" FUNC_ADPT_FMT ": iface_type =%d mstatus(%x)\n",
1996 FUNC_ADPT_ARG(padapter), get_iface_type(padapter), mstatus);
1998 if (mstatus == RT_MEDIA_CONNECT)
2000 bool bRecover = false;
2003 /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
2004 /* Suggested by filen. Added by tynli. */
2005 rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
2007 /* set REG_CR bit 8 */
2008 v8 = rtw_read8(padapter, REG_CR+1);
2009 v8 |= BIT(0); /* ENSWBCN */
2010 rtw_write8(padapter, REG_CR+1, v8);
2012 /* Disable Hw protection for a time which revserd for Hw sending beacon. */
2013 /* Fix download reserved page packet fail that access collision with the protection time. */
2014 /* 2010.05.11. Added by tynli. */
2015 val8 = rtw_read8(padapter, REG_BCN_CTRL);
2016 val8 &= ~EN_BCN_FUNCTION;
2017 val8 |= DIS_TSF_UDT;
2018 rtw_write8(padapter, REG_BCN_CTRL, val8);
2020 /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
2021 if (pHalData->RegFwHwTxQCtrl & BIT(6))
2024 /* To tell Hw the packet is not a real beacon frame. */
2025 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl & ~BIT(6));
2026 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
2028 /* Clear beacon valid check bit. */
2029 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
2030 rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
2035 #ifdef CONFIG_AP_WOWLAN
2036 if (pwrpriv->wowlan_ap_mode)
2037 rtl8723b_set_AP_FwRsvdPagePkt(padapter, 0);
2039 rtl8723b_set_FwRsvdPagePkt(padapter, 0);
2041 /* download rsvd page. */
2042 rtl8723b_set_FwRsvdPagePkt(padapter, 0);
2049 /* check rsvd page download OK. */
2050 rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bcn_valid));
2052 } while (!bcn_valid && (poll%10)!= 0 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
2054 }while (!bcn_valid && DLBcnCount<= 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
2056 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
2059 else if (!bcn_valid)
2060 DBG_871X(ADPT_FMT": 1 DL RSVD page failed! DLBcnCount:%u, poll:%u\n",
2061 ADPT_ARG(padapter) , DLBcnCount, poll);
2063 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
2064 pwrctl->fw_psmode_iface_id = padapter->iface_id;
2065 DBG_871X(ADPT_FMT": 1 DL RSVD page success! DLBcnCount:%u, poll:%u\n",
2066 ADPT_ARG(padapter), DLBcnCount, poll);
2069 /* 2010.05.11. Added by tynli. */
2070 val8 = rtw_read8(padapter, REG_BCN_CTRL);
2071 val8 |= EN_BCN_FUNCTION;
2072 val8 &= ~DIS_TSF_UDT;
2073 rtw_write8(padapter, REG_BCN_CTRL, val8);
2075 /* To make sure that if there exists an adapter which would like to send beacon. */
2076 /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
2077 /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
2078 /* the beacon cannot be sent by HW. */
2079 /* 2010.06.23. Added by tynli. */
2082 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl | BIT(6));
2083 pHalData->RegFwHwTxQCtrl |= BIT(6);
2086 /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
2087 v8 = rtw_read8(padapter, REG_CR+1);
2088 v8 &= ~BIT(0); /* ~ENSWBCN */
2089 rtw_write8(padapter, REG_CR+1, v8);
2093 void rtl8723b_set_rssi_cmd(struct adapter *padapter, u8 *param)
2095 rtl8723b_set_FwRssiSetting_cmd(padapter, param);
2098 void rtl8723b_set_FwJoinBssRpt_cmd(struct adapter *padapter, u8 mstatus)
2101 rtl8723b_download_rsvd_page(padapter, RT_MEDIA_CONNECT);
2104 /* arg[0] = macid */
2106 /* arg[2] = shortGIrate */
2107 /* arg[3] = init_rate */
2108 void rtl8723b_Add_RateATid(struct adapter *padapter, u32 bitmap, u8 *arg, u8 rssi_level)
2110 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2111 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2112 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2113 struct sta_info *psta;
2116 u8 shortGI = arg[2];
2118 u32 mask = bitmap&0x0FFFFFFF;
2120 psta = pmlmeinfo->FW_sta_info[mac_id].psta;
2128 if (rssi_level != DM_RATR_STA_INIT)
2129 mask = ODM_Get_Rate_Bitmap(&pHalData->odmpriv, mac_id, mask, rssi_level);
2131 DBG_871X("%s(): mac_id =%d raid = 0x%x bw =%d mask = 0x%x\n", __func__, mac_id, raid, bw, mask);
2132 rtl8723b_set_FwMacIdConfig_cmd(padapter, mac_id, raid, bw, shortGI, mask);
2135 static void ConstructBtNullFunctionData(
2136 struct adapter *padapter,
2145 struct ieee80211_hdr *pwlanhdr;
2148 struct mlme_ext_priv *pmlmeext;
2149 struct mlme_ext_info *pmlmeinfo;
2153 DBG_871X("+" FUNC_ADPT_FMT ": qos =%d eosp =%d ps =%d\n",
2154 FUNC_ADPT_ARG(padapter), bQoS, bEosp, bForcePowerSave);
2156 pwlanhdr = (struct ieee80211_hdr*)pframe;
2157 pmlmeext = &padapter->mlmeextpriv;
2158 pmlmeinfo = &pmlmeext->mlmext_info;
2160 if (NULL == StaAddr)
2162 memcpy(bssid, myid(&padapter->eeprompriv), ETH_ALEN);
2166 fctrl = &pwlanhdr->frame_control;
2168 if (bForcePowerSave)
2172 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
2173 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2174 memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
2176 SetDuration(pwlanhdr, 0);
2177 SetSeqNum(pwlanhdr, 0);
2181 struct ieee80211_qos_hdr *pwlanqoshdr;
2183 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
2185 pwlanqoshdr = (struct ieee80211_qos_hdr*)pframe;
2186 SetPriority(&pwlanqoshdr->qos_ctrl, AC);
2187 SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
2189 pktlen = sizeof(struct ieee80211_qos_hdr);
2193 SetFrameSubType(pframe, WIFI_DATA_NULL);
2195 pktlen = sizeof(struct ieee80211_hdr_3addr);
2201 static void SetFwRsvdPagePkt_BTCoex(struct adapter *padapter)
2203 struct hal_com_data *pHalData;
2204 struct xmit_frame *pcmdframe;
2205 struct pkt_attrib *pattrib;
2206 struct xmit_priv *pxmitpriv;
2207 struct mlme_ext_priv *pmlmeext;
2208 struct mlme_ext_info *pmlmeinfo;
2209 u32 BeaconLength = 0;
2210 u32 BTQosNullLength = 0;
2211 u8 *ReservedPagePacket;
2212 u8 TxDescLen, TxDescOffset;
2213 u8 TotalPageNum = 0, CurtPktPageNum = 0, RsvdPageNum = 0;
2214 u16 BufIndex, PageSize;
2215 u32 TotalPacketLen, MaxRsvdPageBufSize = 0;
2216 RSVDPAGE_LOC RsvdPageLoc;
2219 /* DBG_8192C("+" FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(padapter)); */
2221 pHalData = GET_HAL_DATA(padapter);
2222 pxmitpriv = &padapter->xmitpriv;
2223 pmlmeext = &padapter->mlmeextpriv;
2224 pmlmeinfo = &pmlmeext->mlmext_info;
2225 TxDescLen = TXDESC_SIZE;
2226 TxDescOffset = TXDESC_OFFSET;
2227 PageSize = PAGE_SIZE_TX_8723B;
2229 RsvdPageNum = BCNQ_PAGE_NUM_8723B;
2230 MaxRsvdPageBufSize = RsvdPageNum*PageSize;
2232 pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv);
2233 if (pcmdframe == NULL) {
2234 DBG_8192C("%s: alloc ReservedPagePacket fail!\n", __func__);
2238 ReservedPagePacket = pcmdframe->buf_addr;
2239 memset(&RsvdPageLoc, 0, sizeof(RSVDPAGE_LOC));
2242 BufIndex = TxDescOffset;
2243 ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
2245 /* When we count the first page size, we need to reserve description size for the RSVD */
2246 /* packet, it will be filled in front of the packet in TXPKTBUF. */
2247 CurtPktPageNum = (u8)PageNum_128(TxDescLen + BeaconLength);
2248 /* If we don't add 1 more page, the WOWLAN function has a problem. Baron thinks it's a bug of firmware */
2249 if (CurtPktPageNum == 1)
2251 CurtPktPageNum += 1;
2253 TotalPageNum += CurtPktPageNum;
2255 BufIndex += (CurtPktPageNum*PageSize);
2257 /* Jump to lastest page */
2258 if (BufIndex < (MaxRsvdPageBufSize - PageSize))
2260 BufIndex = TxDescOffset + (MaxRsvdPageBufSize - PageSize);
2261 TotalPageNum = BCNQ_PAGE_NUM_8723B - 1;
2264 /* 3 (6) BT Qos null data */
2265 RsvdPageLoc.LocBTQosNull = TotalPageNum;
2266 ConstructBtNullFunctionData(
2268 &ReservedPagePacket[BufIndex],
2272 rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true, false);
2274 CurtPktPageNum = (u8)PageNum_128(TxDescLen + BTQosNullLength);
2276 TotalPageNum += CurtPktPageNum;
2278 TotalPacketLen = BufIndex + BTQosNullLength;
2279 if (TotalPacketLen > MaxRsvdPageBufSize)
2281 DBG_8192C(FUNC_ADPT_FMT ": ERROR: The rsvd page size is not enough!!TotalPacketLen %d, MaxRsvdPageBufSize %d\n",
2282 FUNC_ADPT_ARG(padapter), TotalPacketLen, MaxRsvdPageBufSize);
2286 /* update attribute */
2287 pattrib = &pcmdframe->attrib;
2288 update_mgntframe_attrib(padapter, pattrib);
2289 pattrib->qsel = 0x10;
2290 pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TxDescOffset;
2291 dump_mgntframe_and_wait(padapter, pcmdframe, 100);
2293 /* DBG_8192C(FUNC_ADPT_FMT ": Set RSVD page location to Fw, TotalPacketLen(%d), TotalPageNum(%d)\n", */
2294 /* FUNC_ADPT_ARG(padapter), TotalPacketLen, TotalPageNum); */
2295 rtl8723b_set_FwRsvdPage_cmd(padapter, &RsvdPageLoc);
2296 rtl8723b_set_FwAoacRsvdPage_cmd(padapter, &RsvdPageLoc);
2301 rtw_free_xmitframe(pxmitpriv, pcmdframe);
2304 void rtl8723b_download_BTCoex_AP_mode_rsvd_page(struct adapter *padapter)
2306 struct hal_com_data *pHalData;
2307 struct mlme_ext_priv *pmlmeext;
2308 struct mlme_ext_info *pmlmeinfo;
2309 u8 bRecover = false;
2310 u8 bcn_valid = false;
2316 DBG_8192C("+" FUNC_ADPT_FMT ": iface_type =%d fw_state = 0x%08X\n",
2317 FUNC_ADPT_ARG(padapter), get_iface_type(padapter), get_fwstate(&padapter->mlmepriv));
2320 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == false)
2322 DBG_8192C(FUNC_ADPT_FMT ": [WARNING] not in AP mode!!\n",
2323 FUNC_ADPT_ARG(padapter));
2325 #endif /* CONFIG_DEBUG */
2327 pHalData = GET_HAL_DATA(padapter);
2328 pmlmeext = &padapter->mlmeextpriv;
2329 pmlmeinfo = &pmlmeext->mlmext_info;
2331 /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
2332 /* Suggested by filen. Added by tynli. */
2333 rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
2335 /* set REG_CR bit 8 */
2336 val8 = rtw_read8(padapter, REG_CR+1);
2337 val8 |= BIT(0); /* ENSWBCN */
2338 rtw_write8(padapter, REG_CR+1, val8);
2340 /* Disable Hw protection for a time which revserd for Hw sending beacon. */
2341 /* Fix download reserved page packet fail that access collision with the protection time. */
2342 /* 2010.05.11. Added by tynli. */
2343 val8 = rtw_read8(padapter, REG_BCN_CTRL);
2344 val8 &= ~EN_BCN_FUNCTION;
2345 val8 |= DIS_TSF_UDT;
2346 rtw_write8(padapter, REG_BCN_CTRL, val8);
2348 /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
2349 if (pHalData->RegFwHwTxQCtrl & BIT(6))
2352 /* To tell Hw the packet is not a real beacon frame. */
2353 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
2354 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
2356 /* Clear beacon valid check bit. */
2357 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
2358 rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
2363 SetFwRsvdPagePkt_BTCoex(padapter);
2368 /* check rsvd page download OK. */
2369 rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, &bcn_valid);
2371 } while (!bcn_valid && (poll%10)!= 0 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
2372 } while (!bcn_valid && (DLBcnCount<= 100) && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
2374 if (true == bcn_valid)
2376 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
2377 pwrctl->fw_psmode_iface_id = padapter->iface_id;
2378 DBG_8192C(ADPT_FMT": DL RSVD page success! DLBcnCount:%d, poll:%d\n",
2379 ADPT_ARG(padapter), DLBcnCount, poll);
2383 DBG_8192C(ADPT_FMT": DL RSVD page fail! DLBcnCount:%d, poll:%d\n",
2384 ADPT_ARG(padapter), DLBcnCount, poll);
2385 DBG_8192C(ADPT_FMT": DL RSVD page fail! bSurpriseRemoved =%d\n",
2386 ADPT_ARG(padapter), padapter->bSurpriseRemoved);
2387 DBG_8192C(ADPT_FMT": DL RSVD page fail! bDriverStopped =%d\n",
2388 ADPT_ARG(padapter), padapter->bDriverStopped);
2391 /* 2010.05.11. Added by tynli. */
2392 val8 = rtw_read8(padapter, REG_BCN_CTRL);
2393 val8 |= EN_BCN_FUNCTION;
2394 val8 &= ~DIS_TSF_UDT;
2395 rtw_write8(padapter, REG_BCN_CTRL, val8);
2397 /* To make sure that if there exists an adapter which would like to send beacon. */
2398 /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
2399 /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
2400 /* the beacon cannot be sent by HW. */
2401 /* 2010.06.23. Added by tynli. */
2404 pHalData->RegFwHwTxQCtrl |= BIT(6);
2405 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
2408 /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
2409 val8 = rtw_read8(padapter, REG_CR+1);
2410 val8 &= ~BIT(0); /* ~ENSWBCN */
2411 rtw_write8(padapter, REG_CR+1, val8);