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)))
80 if (CmdLen > RTL8723B_MAX_CMD_LEN) {
84 if (padapter->bSurpriseRemoved == true)
87 /* pay attention to if race condition happened in H2C cmd setting. */
89 h2c_box_num = pHalData->LastHMEBoxNum;
91 if (!_is_fw_read_cmd_down(padapter, h2c_box_num)) {
92 DBG_8192C(" fw read cmd failed...\n");
93 /* DBG_8192C(" 0x1c0: 0x%8x\n", rtw_read32(padapter, 0x1c0)); */
94 /* DBG_8192C(" 0x1c4: 0x%8x\n", rtw_read32(padapter, 0x1c4)); */
99 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) {
176 /* DBG_871X("ie len =%d\n", cur_network->IELength); */
177 pktlen += cur_network->IELength - sizeof(struct ndis_802_11_fix_ie);
178 memcpy(pframe, cur_network->IEs+sizeof(struct ndis_802_11_fix_ie), pktlen);
180 goto _ConstructBeacon;
183 /* below for ad-hoc mode */
186 pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);
188 /* supported rates... */
189 rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
190 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pktlen);
192 /* DS parameter set */
193 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
195 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
197 /* IBSS Parameter Set... */
198 /* ATIMWindow = cur->Configuration.ATIMWindow; */
200 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
207 /* EXTERNDED SUPPORTED RATE */
209 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
212 /* todo:HT for adhoc */
216 if ((pktlen + TXDESC_SIZE) > 512) {
217 DBG_871X("beacon frame too large\n");
223 /* DBG_871X("%s bcn_sz =%d\n", __func__, pktlen); */
227 static void ConstructPSPoll(struct adapter *padapter, u8 *pframe, u32 *pLength)
229 struct ieee80211_hdr *pwlanhdr;
231 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
232 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
234 /* DBG_871X("%s\n", __func__); */
236 pwlanhdr = (struct ieee80211_hdr *)pframe;
239 fctrl = &(pwlanhdr->frame_control);
242 SetFrameSubType(pframe, WIFI_PSPOLL);
245 SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
248 memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
251 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
256 static void ConstructNullFunctionData(
257 struct adapter *padapter,
267 struct ieee80211_hdr *pwlanhdr;
270 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
271 struct wlan_network *cur_network = &pmlmepriv->cur_network;
272 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
273 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
276 /* DBG_871X("%s:%d\n", __func__, bForcePowerSave); */
278 pwlanhdr = (struct ieee80211_hdr *)pframe;
280 fctrl = &pwlanhdr->frame_control;
285 switch (cur_network->network.InfrastructureMode) {
286 case Ndis802_11Infrastructure:
288 memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
289 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
290 memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
292 case Ndis802_11APMode:
294 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
295 memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
296 memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
300 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
301 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
302 memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
306 SetSeqNum(pwlanhdr, 0);
309 struct ieee80211_qos_hdr *pwlanqoshdr;
311 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
313 pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe;
314 SetPriority(&pwlanqoshdr->qos_ctrl, AC);
315 SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
317 pktlen = sizeof(struct ieee80211_qos_hdr);
319 SetFrameSubType(pframe, WIFI_DATA_NULL);
321 pktlen = sizeof(struct ieee80211_hdr_3addr);
331 /* Construct the ARP response packet to support ARP offload. */
333 static void ConstructARPResponse(
334 struct adapter *padapter,
340 struct ieee80211_hdr *pwlanhdr;
342 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
343 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
344 struct security_priv *psecuritypriv = &padapter->securitypriv;
345 static u8 ARPLLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06};
346 u8 *pARPRspPkt = pframe;
347 /* for TKIP Cal MIC */
348 u8 *payload = pframe;
349 u8 EncryptionHeadOverhead = 0;
350 /* DBG_871X("%s:%d\n", __func__, bForcePowerSave); */
352 pwlanhdr = (struct ieee80211_hdr *)pframe;
354 fctrl = &pwlanhdr->frame_control;
360 SetFrameType(fctrl, WIFI_DATA);
361 /* SetFrameSubType(fctrl, 0); */
363 memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
364 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
365 memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
367 SetSeqNum(pwlanhdr, 0);
368 SetDuration(pwlanhdr, 0);
369 /* SET_80211_HDR_FRAME_CONTROL(pARPRspPkt, 0); */
370 /* SET_80211_HDR_TYPE_AND_SUBTYPE(pARPRspPkt, Type_Data); */
371 /* SET_80211_HDR_TO_DS(pARPRspPkt, 1); */
372 /* SET_80211_HDR_ADDRESS1(pARPRspPkt, pMgntInfo->Bssid); */
373 /* SET_80211_HDR_ADDRESS2(pARPRspPkt, Adapter->CurrentAddress); */
374 /* SET_80211_HDR_ADDRESS3(pARPRspPkt, pMgntInfo->Bssid); */
376 /* SET_80211_HDR_DURATION(pARPRspPkt, 0); */
377 /* SET_80211_HDR_FRAGMENT_SEQUENCE(pARPRspPkt, 0); */
381 /* Security Header: leave space for it if necessary. */
384 switch (psecuritypriv->dot11PrivacyAlgrthm) {
387 EncryptionHeadOverhead = 4;
390 EncryptionHeadOverhead = 8;
393 EncryptionHeadOverhead = 8;
396 EncryptionHeadOverhead = 0;
399 if (EncryptionHeadOverhead > 0) {
400 memset(&(pframe[*pLength]), 0, EncryptionHeadOverhead);
401 *pLength += EncryptionHeadOverhead;
408 pARPRspPkt = (u8 *)(pframe + *pLength);
409 payload = pARPRspPkt; /* Get Payload pointer */
411 memcpy(pARPRspPkt, ARPLLCHeader, 8);
416 SET_ARP_PKT_HW(pARPRspPkt, 0x0100);
417 SET_ARP_PKT_PROTOCOL(pARPRspPkt, 0x0008); /* IP protocol */
418 SET_ARP_PKT_HW_ADDR_LEN(pARPRspPkt, 6);
419 SET_ARP_PKT_PROTOCOL_ADDR_LEN(pARPRspPkt, 4);
420 SET_ARP_PKT_OPERATION(pARPRspPkt, 0x0200); /* ARP response */
421 SET_ARP_PKT_SENDER_MAC_ADDR(pARPRspPkt, myid(&(padapter->eeprompriv)));
422 SET_ARP_PKT_SENDER_IP_ADDR(pARPRspPkt, pIPAddress);
424 SET_ARP_PKT_TARGET_MAC_ADDR(pARPRspPkt, get_my_bssid(&(pmlmeinfo->network)));
425 SET_ARP_PKT_TARGET_IP_ADDR(pARPRspPkt, pIPAddress);
426 DBG_871X("%s Target Mac Addr:" MAC_FMT "\n", __func__, MAC_ARG(get_my_bssid(&(pmlmeinfo->network))));
427 DBG_871X("%s Target IP Addr" IP_FMT "\n", __func__, IP_ARG(pIPAddress));
432 if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_) {
434 struct mic_data micdata;
435 struct sta_info *psta = NULL;
440 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
441 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
444 DBG_871X("%s(): Add MIC\n", __func__);
446 psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(&(pmlmeinfo->network)));
448 if (!memcmp(&psta->dot11tkiptxmickey.skey[0], null_key, 16)) {
449 DBG_871X("%s(): STA dot11tkiptxmickey == 0\n", __func__);
451 /* start to calculate the mic code */
452 rtw_secmicsetkey(&micdata, &psta->dot11tkiptxmickey.skey[0]);
455 rtw_secmicappend(&micdata, pwlanhdr->addr3, 6); /* DA */
457 rtw_secmicappend(&micdata, pwlanhdr->addr2, 6); /* SA */
460 rtw_secmicappend(&micdata, &priority[0], 4);
462 rtw_secmicappend(&micdata, payload, 36); /* payload length = 8 + 28 */
464 rtw_secgetmic(&micdata, &(mic[0]));
467 memcpy(pARPRspPkt, &(mic[0]), 8);
473 #ifdef CONFIG_PNO_SUPPORT
474 static void ConstructPnoInfo(
475 struct adapter *padapter, u8 *pframe, u32 *pLength
479 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
481 u8 *pPnoInfoPkt = pframe;
482 pPnoInfoPkt = (u8 *)(pframe + *pLength);
483 memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_num, 4);
487 memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->fast_scan_period, 4);
491 memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->fast_scan_iterations, 4);
495 memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->slow_scan_period, 4);
499 memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_length,
502 *pLength += MAX_PNO_LIST_COUNT;
503 pPnoInfoPkt += MAX_PNO_LIST_COUNT;
504 memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_cipher_info,
507 *pLength += MAX_PNO_LIST_COUNT;
508 pPnoInfoPkt += MAX_PNO_LIST_COUNT;
509 memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_channel_info,
512 *pLength += MAX_PNO_LIST_COUNT;
513 pPnoInfoPkt += MAX_PNO_LIST_COUNT;
516 static void ConstructSSIDList(
517 struct adapter *padapter, u8 *pframe, u32 *pLength
521 u8 *pSSIDListPkt = pframe;
522 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
524 pSSIDListPkt = (u8 *)(pframe + *pLength);
526 for (i = 0; i < pwrctl->pnlo_info->ssid_num ; i++) {
527 memcpy(pSSIDListPkt, &pwrctl->pno_ssid_list->node[i].SSID,
528 pwrctl->pnlo_info->ssid_length[i]);
530 *pLength += WLAN_SSID_MAXLEN;
531 pSSIDListPkt += WLAN_SSID_MAXLEN;
535 static void ConstructScanInfo(
536 struct adapter *padapter, u8 *pframe, u32 *pLength
540 u8 *pScanInfoPkt = pframe;
541 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
543 pScanInfoPkt = (u8 *)(pframe + *pLength);
545 memcpy(pScanInfoPkt, &pwrctl->pscan_info->channel_num, 1);
549 memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_ch, 1);
554 memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_bw, 1);
559 memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_40_offset, 1);
563 memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_80_offset, 1);
567 memcpy(pScanInfoPkt, &pwrctl->pscan_info->periodScan, 1);
571 memcpy(pScanInfoPkt, &pwrctl->pscan_info->period_scan_time, 1);
575 memcpy(pScanInfoPkt, &pwrctl->pscan_info->enableRFE, 1);
579 memcpy(pScanInfoPkt, &pwrctl->pscan_info->rfe_type, 8);
584 for (i = 0; i < MAX_SCAN_LIST_COUNT; i++) {
585 memcpy(pScanInfoPkt, &pwrctl->pscan_info->ssid_channel_info[i], 4);
593 static void ConstructGTKResponse(
594 struct adapter *padapter, u8 *pframe, u32 *pLength
597 struct ieee80211_hdr *pwlanhdr;
599 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
600 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
601 struct security_priv *psecuritypriv = &padapter->securitypriv;
602 static u8 LLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8E};
603 static u8 GTKbody_a[11] = {0x01, 0x03, 0x00, 0x5F, 0x02, 0x03, 0x12, 0x00, 0x10, 0x42, 0x0B};
604 u8 *pGTKRspPkt = pframe;
605 u8 EncryptionHeadOverhead = 0;
606 /* DBG_871X("%s:%d\n", __func__, bForcePowerSave); */
608 pwlanhdr = (struct ieee80211_hdr *)pframe;
610 fctrl = &pwlanhdr->frame_control;
616 SetFrameType(fctrl, WIFI_DATA);
617 /* SetFrameSubType(fctrl, 0); */
619 memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
620 memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
621 memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
623 SetSeqNum(pwlanhdr, 0);
624 SetDuration(pwlanhdr, 0);
629 /* Security Header: leave space for it if necessary. */
632 switch (psecuritypriv->dot11PrivacyAlgrthm) {
635 EncryptionHeadOverhead = 4;
638 EncryptionHeadOverhead = 8;
641 EncryptionHeadOverhead = 8;
644 EncryptionHeadOverhead = 0;
647 if (EncryptionHeadOverhead > 0) {
648 memset(&(pframe[*pLength]), 0, EncryptionHeadOverhead);
649 *pLength += EncryptionHeadOverhead;
650 /* GTK's privacy bit is done by FW */
651 /* SetPrivacy(fctrl); */
657 pGTKRspPkt = (u8 *)(pframe + *pLength);
659 memcpy(pGTKRspPkt, LLCHeader, 8);
665 /* GTK frame body after LLC, part 1 */
666 memcpy(pGTKRspPkt, GTKbody_a, 11);
669 /* GTK frame body after LLC, part 2 */
670 memset(&(pframe[*pLength]), 0, 88);
675 #endif /* CONFIG_GTK_OL */
677 #ifdef CONFIG_PNO_SUPPORT
678 static void ConstructProbeReq(struct adapter *padapter, u8 *pframe, u32 *pLength)
680 struct ieee80211_hdr *pwlanhdr;
684 unsigned char bssrate[NumRates];
685 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
686 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
687 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
688 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
690 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
692 pwlanhdr = (struct ieee80211_hdr *)pframe;
693 mac = myid(&(padapter->eeprompriv));
695 fctrl = &(pwlanhdr->frame_control);
698 /* broadcast probe request frame */
699 memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
700 memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
702 memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
704 SetSeqNum(pwlanhdr, 0);
705 SetFrameSubType(pframe, WIFI_PROBEREQ);
707 pktlen = sizeof(struct ieee80211_hdr_3addr);
710 pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &pktlen);
712 get_rate_set(padapter, bssrate, &bssrate_len);
714 if (bssrate_len > 8) {
715 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &pktlen);
716 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &pktlen);
718 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &pktlen);
722 #endif /* CONFIG_PNO_SUPPORT */
723 #endif /* CONFIG_WOWLAN */
725 #ifdef CONFIG_AP_WOWLAN
726 static void ConstructProbeRsp(struct adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID)
728 struct ieee80211_hdr *pwlanhdr;
732 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
733 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
734 struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
737 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
739 /* DBG_871X("%s\n", __func__); */
741 pwlanhdr = (struct ieee80211_hdr *)pframe;
743 mac = myid(&(padapter->eeprompriv));
744 bssid = cur_network->MacAddress;
746 fctrl = &(pwlanhdr->frame_control);
748 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
749 memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
750 memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
752 DBG_871X("%s FW Mac Addr:" MAC_FMT "\n", __func__, MAC_ARG(mac));
753 DBG_871X("%s FW IP Addr" IP_FMT "\n", __func__, IP_ARG(StaAddr));
755 SetSeqNum(pwlanhdr, 0);
756 SetFrameSubType(fctrl, WIFI_PROBERSP);
758 pktlen = sizeof(struct ieee80211_hdr_3addr);
761 if (cur_network->IELength > MAX_IE_SZ)
764 pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_,
765 cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
767 /* inerset & update wps_probe_resp_ie */
768 if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie && (wps_ielen > 0)) {
769 uint wps_offset, remainder_ielen;
772 wps_offset = (uint)(pwps_ie - cur_network->IEs);
774 premainder_ie = pwps_ie + wps_ielen;
776 remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
778 memcpy(pframe, cur_network->IEs, wps_offset);
779 pframe += wps_offset;
780 pktlen += wps_offset;
782 wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
783 if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) {
784 memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
785 pframe += wps_ielen+2;
786 pktlen += wps_ielen+2;
789 if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) {
790 memcpy(pframe, premainder_ie, remainder_ielen);
791 pframe += remainder_ielen;
792 pktlen += remainder_ielen;
795 memcpy(pframe, cur_network->IEs, cur_network->IELength);
796 pframe += cur_network->IELength;
797 pktlen += cur_network->IELength;
800 /* retrieve SSID IE from cur_network->Ssid */
804 sint ssid_ielen_diff;
806 u8 *ies = pframe + sizeof(struct ieee80211_hdr_3addr);
808 ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, _SSID_IE_, &ssid_ielen,
809 (pframe-ies)-_FIXED_IE_LENGTH_);
811 ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen;
813 if (ssid_ie && cur_network->Ssid.SsidLength) {
814 uint remainder_ielen;
816 remainder_ie = ssid_ie+2;
817 remainder_ielen = (pframe-remainder_ie);
819 if (remainder_ielen > MAX_IE_SZ) {
820 DBG_871X_LEVEL(_drv_warning_, FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter));
821 remainder_ielen = MAX_IE_SZ;
824 memcpy(buf, remainder_ie, remainder_ielen);
825 memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen);
826 *(ssid_ie+1) = cur_network->Ssid.SsidLength;
827 memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength);
828 pframe += ssid_ielen_diff;
829 pktlen += ssid_ielen_diff;
836 #endif /* CONFIG_AP_WOWLAN */
838 /* To check if reserved page content is destroyed by beacon beacuse beacon is too large. */
839 /* 2010.06.23. Added by tynli. */
840 void CheckFwRsvdPageContent(struct adapter *Adapter)
844 static void rtl8723b_set_FwRsvdPage_cmd(struct adapter *padapter, PRSVDPAGE_LOC rsvdpageloc)
846 u8 u1H2CRsvdPageParm[H2C_RSVDPAGE_LOC_LEN] = {0};
848 DBG_871X("8723BRsvdPageLoc: ProbeRsp =%d PsPoll =%d Null =%d QoSNull =%d BTNull =%d\n",
849 rsvdpageloc->LocProbeRsp, rsvdpageloc->LocPsPoll,
850 rsvdpageloc->LocNullData, rsvdpageloc->LocQosNull,
851 rsvdpageloc->LocBTQosNull);
853 SET_8723B_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1H2CRsvdPageParm, rsvdpageloc->LocProbeRsp);
854 SET_8723B_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1H2CRsvdPageParm, rsvdpageloc->LocPsPoll);
855 SET_8723B_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocNullData);
856 SET_8723B_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocQosNull);
857 SET_8723B_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocBTQosNull);
859 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CRsvdPageParm:", u1H2CRsvdPageParm, H2C_RSVDPAGE_LOC_LEN);
860 FillH2CCmd8723B(padapter, H2C_8723B_RSVD_PAGE, H2C_RSVDPAGE_LOC_LEN, u1H2CRsvdPageParm);
863 static void rtl8723b_set_FwAoacRsvdPage_cmd(struct adapter *padapter, PRSVDPAGE_LOC rsvdpageloc)
866 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
867 u8 u1H2CAoacRsvdPageParm[H2C_AOAC_RSVDPAGE_LOC_LEN] = {0};
869 DBG_871X("8723BAOACRsvdPageLoc: RWC =%d ArpRsp =%d NbrAdv =%d GtkRsp =%d GtkInfo =%d ProbeReq =%d NetworkList =%d\n",
870 rsvdpageloc->LocRemoteCtrlInfo, rsvdpageloc->LocArpRsp,
871 rsvdpageloc->LocNbrAdv, rsvdpageloc->LocGTKRsp,
872 rsvdpageloc->LocGTKInfo, rsvdpageloc->LocProbeReq,
873 rsvdpageloc->LocNetList);
875 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
876 SET_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1H2CAoacRsvdPageParm, rsvdpageloc->LocRemoteCtrlInfo);
877 SET_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1H2CAoacRsvdPageParm, rsvdpageloc->LocArpRsp);
878 /* SET_H2CCMD_AOAC_RSVDPAGE_LOC_NEIGHBOR_ADV(u1H2CAoacRsvdPageParm, rsvdpageloc->LocNbrAdv); */
879 SET_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_RSP(u1H2CAoacRsvdPageParm, rsvdpageloc->LocGTKRsp);
880 SET_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_INFO(u1H2CAoacRsvdPageParm, rsvdpageloc->LocGTKInfo);
882 SET_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1H2CAoacRsvdPageParm, rsvdpageloc->LocGTKEXTMEM);
883 #endif /* CONFIG_GTK_OL */
884 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CAoacRsvdPageParm:", u1H2CAoacRsvdPageParm, H2C_AOAC_RSVDPAGE_LOC_LEN);
885 FillH2CCmd8723B(padapter, H2C_8723B_AOAC_RSVD_PAGE, H2C_AOAC_RSVDPAGE_LOC_LEN, u1H2CAoacRsvdPageParm);
887 #ifdef CONFIG_PNO_SUPPORT
888 if (!pwrpriv->pno_in_resume) {
889 DBG_871X("NLO_INFO =%d\n", rsvdpageloc->LocPNOInfo);
890 memset(&u1H2CAoacRsvdPageParm, 0, sizeof(u1H2CAoacRsvdPageParm));
891 SET_H2CCMD_AOAC_RSVDPAGE_LOC_NLO_INFO(u1H2CAoacRsvdPageParm, rsvdpageloc->LocPNOInfo);
892 FillH2CCmd8723B(padapter, H2C_AOAC_RSVDPAGE3, H2C_AOAC_RSVDPAGE_LOC_LEN, u1H2CAoacRsvdPageParm);
898 #endif /* CONFIG_WOWLAN */
901 #ifdef CONFIG_AP_WOWLAN
902 static void rtl8723b_set_ap_wow_rsvdpage_cmd(
903 struct adapter *padapter, PRSVDPAGE_LOC rsvdpageloc
907 u8 rsvdparm[H2C_AOAC_RSVDPAGE_LOC_LEN] = {0};
909 header = rtw_read8(padapter, REG_BCNQ_BDNY);
911 DBG_871X("%s: beacon: %d, probeRsp: %d, header:0x%02x\n", __func__,
912 rsvdpageloc->LocApOffloadBCN,
913 rsvdpageloc->LocProbeRsp,
916 SET_H2CCMD_AP_WOWLAN_RSVDPAGE_LOC_BCN(rsvdparm,
917 rsvdpageloc->LocApOffloadBCN + header);
919 FillH2CCmd8723B(padapter, H2C_8723B_BCN_RSVDPAGE,
920 H2C_BCN_RSVDPAGE_LEN, rsvdparm);
924 memset(&rsvdparm, 0, sizeof(rsvdparm));
926 SET_H2CCMD_AP_WOWLAN_RSVDPAGE_LOC_ProbeRsp(
928 rsvdpageloc->LocProbeRsp + header);
930 FillH2CCmd8723B(padapter, H2C_8723B_PROBERSP_RSVDPAGE,
931 H2C_PROBERSP_RSVDPAGE_LEN, rsvdparm);
935 #endif /* CONFIG_AP_WOWLAN */
937 void rtl8723b_set_FwMediaStatusRpt_cmd(struct adapter *padapter, u8 mstatus, u8 macid)
939 u8 u1H2CMediaStatusRptParm[H2C_MEDIA_STATUS_RPT_LEN] = {0};
942 DBG_871X("%s(): mstatus = %d macid =%d\n", __func__, mstatus, macid);
944 SET_8723B_H2CCMD_MSRRPT_PARM_OPMODE(u1H2CMediaStatusRptParm, mstatus);
945 SET_8723B_H2CCMD_MSRRPT_PARM_MACID_IND(u1H2CMediaStatusRptParm, 0);
946 SET_8723B_H2CCMD_MSRRPT_PARM_MACID(u1H2CMediaStatusRptParm, macid);
947 SET_8723B_H2CCMD_MSRRPT_PARM_MACID_END(u1H2CMediaStatusRptParm, macid_end);
949 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CMediaStatusRptParm:", u1H2CMediaStatusRptParm, H2C_MEDIA_STATUS_RPT_LEN);
950 FillH2CCmd8723B(padapter, H2C_8723B_MEDIA_STATUS_RPT, H2C_MEDIA_STATUS_RPT_LEN, u1H2CMediaStatusRptParm);
954 static void rtl8723b_set_FwKeepAlive_cmd(struct adapter *padapter, u8 benable, u8 pkt_type)
956 u8 u1H2CKeepAliveParm[H2C_KEEP_ALIVE_CTRL_LEN] = {0};
957 u8 adopt = 1, check_period = 5;
959 DBG_871X("%s(): benable = %d\n", __func__, benable);
960 SET_8723B_H2CCMD_KEEPALIVE_PARM_ENABLE(u1H2CKeepAliveParm, benable);
961 SET_8723B_H2CCMD_KEEPALIVE_PARM_ADOPT(u1H2CKeepAliveParm, adopt);
962 SET_8723B_H2CCMD_KEEPALIVE_PARM_PKT_TYPE(u1H2CKeepAliveParm, pkt_type);
963 SET_8723B_H2CCMD_KEEPALIVE_PARM_CHECK_PERIOD(u1H2CKeepAliveParm, check_period);
965 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CKeepAliveParm:", u1H2CKeepAliveParm, H2C_KEEP_ALIVE_CTRL_LEN);
967 FillH2CCmd8723B(padapter, H2C_8723B_KEEP_ALIVE, H2C_KEEP_ALIVE_CTRL_LEN, u1H2CKeepAliveParm);
970 static void rtl8723b_set_FwDisconDecision_cmd(struct adapter *padapter, u8 benable)
972 u8 u1H2CDisconDecisionParm[H2C_DISCON_DECISION_LEN] = {0};
973 u8 adopt = 1, check_period = 10, trypkt_num = 0;
975 DBG_871X("%s(): benable = %d\n", __func__, benable);
976 SET_8723B_H2CCMD_DISCONDECISION_PARM_ENABLE(u1H2CDisconDecisionParm, benable);
977 SET_8723B_H2CCMD_DISCONDECISION_PARM_ADOPT(u1H2CDisconDecisionParm, adopt);
978 SET_8723B_H2CCMD_DISCONDECISION_PARM_CHECK_PERIOD(u1H2CDisconDecisionParm, check_period);
979 SET_8723B_H2CCMD_DISCONDECISION_PARM_TRY_PKT_NUM(u1H2CDisconDecisionParm, trypkt_num);
981 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CDisconDecisionParm:", u1H2CDisconDecisionParm, H2C_DISCON_DECISION_LEN);
983 FillH2CCmd8723B(padapter, H2C_8723B_DISCON_DECISION, H2C_DISCON_DECISION_LEN, u1H2CDisconDecisionParm);
985 #endif /* CONFIG_WOWLAN */
987 void rtl8723b_set_FwMacIdConfig_cmd(struct adapter *padapter, u8 mac_id, u8 raid, u8 bw, u8 sgi, u32 mask)
989 u8 u1H2CMacIdConfigParm[H2C_MACID_CFG_LEN] = {0};
991 DBG_871X("%s(): mac_id =%d raid = 0x%x bw =%d mask = 0x%x\n", __func__, mac_id, raid, bw, mask);
993 SET_8723B_H2CCMD_MACID_CFG_MACID(u1H2CMacIdConfigParm, mac_id);
994 SET_8723B_H2CCMD_MACID_CFG_RAID(u1H2CMacIdConfigParm, raid);
995 SET_8723B_H2CCMD_MACID_CFG_SGI_EN(u1H2CMacIdConfigParm, sgi ? 1 : 0);
996 SET_8723B_H2CCMD_MACID_CFG_BW(u1H2CMacIdConfigParm, bw);
997 SET_8723B_H2CCMD_MACID_CFG_RATE_MASK0(u1H2CMacIdConfigParm, (u8)(mask & 0x000000ff));
998 SET_8723B_H2CCMD_MACID_CFG_RATE_MASK1(u1H2CMacIdConfigParm, (u8)((mask & 0x0000ff00) >> 8));
999 SET_8723B_H2CCMD_MACID_CFG_RATE_MASK2(u1H2CMacIdConfigParm, (u8)((mask & 0x00ff0000) >> 16));
1000 SET_8723B_H2CCMD_MACID_CFG_RATE_MASK3(u1H2CMacIdConfigParm, (u8)((mask & 0xff000000) >> 24));
1002 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CMacIdConfigParm:", u1H2CMacIdConfigParm, H2C_MACID_CFG_LEN);
1003 FillH2CCmd8723B(padapter, H2C_8723B_MACID_CFG, H2C_MACID_CFG_LEN, u1H2CMacIdConfigParm);
1006 static void rtl8723b_set_FwRssiSetting_cmd(struct adapter *padapter, u8 *param)
1008 u8 u1H2CRssiSettingParm[H2C_RSSI_SETTING_LEN] = {0};
1010 u8 rssi = *(param+2);
1013 /* DBG_871X("%s(): param =%.2x-%.2x-%.2x\n", __func__, *param, *(param+1), *(param+2)); */
1014 /* DBG_871X("%s(): mac_id =%d rssi =%d\n", __func__, mac_id, rssi); */
1016 SET_8723B_H2CCMD_RSSI_SETTING_MACID(u1H2CRssiSettingParm, mac_id);
1017 SET_8723B_H2CCMD_RSSI_SETTING_RSSI(u1H2CRssiSettingParm, rssi);
1018 SET_8723B_H2CCMD_RSSI_SETTING_ULDL_STATE(u1H2CRssiSettingParm, uldl_state);
1020 RT_PRINT_DATA(_module_hal_init_c_, _drv_notice_, "u1H2CRssiSettingParm:", u1H2CRssiSettingParm, H2C_RSSI_SETTING_LEN);
1021 FillH2CCmd8723B(padapter, H2C_8723B_RSSI_SETTING, H2C_RSSI_SETTING_LEN, u1H2CRssiSettingParm);
1024 void rtl8723b_set_FwPwrMode_cmd(struct adapter *padapter, u8 psmode)
1027 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1028 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1029 u8 u1H2CPwrModeParm[H2C_PWRMODE_LEN] = {0};
1030 u8 PowerState = 0, awake_intvl = 1, byte5 = 0, rlbm = 0;
1032 if (pwrpriv->dtim > 0)
1033 DBG_871X("%s(): FW LPS mode = %d, SmartPS =%d, dtim =%d\n", __func__, psmode, pwrpriv->smart_ps, pwrpriv->dtim);
1035 DBG_871X("%s(): FW LPS mode = %d, SmartPS =%d\n", __func__, psmode, pwrpriv->smart_ps);
1037 #ifdef CONFIG_WOWLAN
1038 if (psmode == PS_MODE_DTIM) { /* For WOWLAN LPS, DTIM = (awake_intvl - 1) */
1039 awake_intvl = 3;/* DTIM =2 */
1042 #endif /* CONFIG_WOWLAN */
1044 if (pwrpriv->dtim > 0 && pwrpriv->dtim < 16)
1045 awake_intvl = pwrpriv->dtim+1;/* DTIM = (awake_intvl - 1) */
1047 awake_intvl = 3;/* DTIM =2 */
1053 if (padapter->registrypriv.wifi_spec == 1) {
1059 if (rtw_btcoex_IsBtControlLps(padapter) == true) {
1060 PowerState = rtw_btcoex_RpwmVal(padapter);
1061 byte5 = rtw_btcoex_LpsVal(padapter);
1063 if ((rlbm == 2) && (byte5 & BIT(4))) {
1064 /* Keep awake interval to 1 to prevent from */
1065 /* decreasing coex performance */
1070 PowerState = 0x00;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */
1074 PowerState = 0x0C;/* AllON(0x0C), RFON(0x04), RFOFF(0x00) */
1078 SET_8723B_H2CCMD_PWRMODE_PARM_MODE(u1H2CPwrModeParm, (psmode > 0) ? 1 : 0);
1079 SET_8723B_H2CCMD_PWRMODE_PARM_SMART_PS(u1H2CPwrModeParm, pwrpriv->smart_ps);
1080 SET_8723B_H2CCMD_PWRMODE_PARM_RLBM(u1H2CPwrModeParm, rlbm);
1081 SET_8723B_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1H2CPwrModeParm, awake_intvl);
1082 SET_8723B_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1H2CPwrModeParm, padapter->registrypriv.uapsd_enable);
1083 SET_8723B_H2CCMD_PWRMODE_PARM_PWR_STATE(u1H2CPwrModeParm, PowerState);
1084 SET_8723B_H2CCMD_PWRMODE_PARM_BYTE5(u1H2CPwrModeParm, byte5);
1085 if (psmode != PS_MODE_ACTIVE) {
1086 if (pmlmeext->adaptive_tsf_done == false && pmlmeext->bcn_cnt > 0) {
1087 u8 ratio_20_delay, ratio_80_delay;
1089 /* byte 6 for adaptive_early_32k */
1090 /* 0:3] = DrvBcnEarly (ms) , [4:7] = DrvBcnTimeOut (ms) */
1091 /* 20% for DrvBcnEarly, 80% for DrvBcnTimeOut */
1094 pmlmeext->DrvBcnEarly = 0xff;
1095 pmlmeext->DrvBcnTimeOut = 0xff;
1097 DBG_871X("%s(): bcn_cnt = %d\n", __func__, pmlmeext->bcn_cnt);
1099 for (i = 0; i < 9; i++) {
1100 pmlmeext->bcn_delay_ratio[i] = (pmlmeext->bcn_delay_cnt[i]*100)/pmlmeext->bcn_cnt;
1103 "%s(): bcn_delay_cnt[%d]=%d, bcn_delay_ratio[%d] = %d\n",
1106 pmlmeext->bcn_delay_cnt[i],
1108 pmlmeext->bcn_delay_ratio[i]
1111 ratio_20_delay += pmlmeext->bcn_delay_ratio[i];
1112 ratio_80_delay += pmlmeext->bcn_delay_ratio[i];
1114 if (ratio_20_delay > 20 && pmlmeext->DrvBcnEarly == 0xff) {
1115 pmlmeext->DrvBcnEarly = i;
1116 DBG_871X("%s(): DrvBcnEarly = %d\n", __func__, pmlmeext->DrvBcnEarly);
1119 if (ratio_80_delay > 80 && pmlmeext->DrvBcnTimeOut == 0xff) {
1120 pmlmeext->DrvBcnTimeOut = i;
1121 DBG_871X("%s(): DrvBcnTimeOut = %d\n", __func__, pmlmeext->DrvBcnTimeOut);
1124 /* reset adaptive_early_32k cnt */
1125 pmlmeext->bcn_delay_cnt[i] = 0;
1126 pmlmeext->bcn_delay_ratio[i] = 0;
1130 pmlmeext->bcn_cnt = 0;
1131 pmlmeext->adaptive_tsf_done = true;
1134 DBG_871X("%s(): DrvBcnEarly = %d\n", __func__, pmlmeext->DrvBcnEarly);
1135 DBG_871X("%s(): DrvBcnTimeOut = %d\n", __func__, pmlmeext->DrvBcnTimeOut);
1138 /* offload to FW if fw version > v15.10
1139 pmlmeext->DrvBcnEarly = 0;
1140 pmlmeext->DrvBcnTimeOut =7;
1142 if ((pmlmeext->DrvBcnEarly!= 0Xff) && (pmlmeext->DrvBcnTimeOut!= 0xff))
1143 u1H2CPwrModeParm[H2C_PWRMODE_LEN-1] = BIT(0) | ((pmlmeext->DrvBcnEarly<<1)&0x0E) |((pmlmeext->DrvBcnTimeOut<<4)&0xf0) ;
1148 rtw_btcoex_RecordPwrMode(padapter, u1H2CPwrModeParm, H2C_PWRMODE_LEN);
1150 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CPwrModeParm:", u1H2CPwrModeParm, H2C_PWRMODE_LEN);
1152 FillH2CCmd8723B(padapter, H2C_8723B_SET_PWR_MODE, H2C_PWRMODE_LEN, u1H2CPwrModeParm);
1155 void rtl8723b_set_FwPsTuneParam_cmd(struct adapter *padapter)
1157 u8 u1H2CPsTuneParm[H2C_PSTUNEPARAM_LEN] = {0};
1158 u8 bcn_to_limit = 10; /* 10 * 100 * awakeinterval (ms) */
1159 u8 dtim_timeout = 5; /* ms wait broadcast data timer */
1160 u8 ps_timeout = 20; /* ms Keep awake when tx */
1163 /* DBG_871X("%s(): FW LPS mode = %d\n", __func__, psmode); */
1165 SET_8723B_H2CCMD_PSTUNE_PARM_BCN_TO_LIMIT(u1H2CPsTuneParm, bcn_to_limit);
1166 SET_8723B_H2CCMD_PSTUNE_PARM_DTIM_TIMEOUT(u1H2CPsTuneParm, dtim_timeout);
1167 SET_8723B_H2CCMD_PSTUNE_PARM_PS_TIMEOUT(u1H2CPsTuneParm, ps_timeout);
1168 SET_8723B_H2CCMD_PSTUNE_PARM_ADOPT(u1H2CPsTuneParm, 1);
1169 SET_8723B_H2CCMD_PSTUNE_PARM_DTIM_PERIOD(u1H2CPsTuneParm, dtim_period);
1171 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CPsTuneParm:", u1H2CPsTuneParm, H2C_PSTUNEPARAM_LEN);
1173 FillH2CCmd8723B(padapter, H2C_8723B_PS_TUNING_PARA, H2C_PSTUNEPARAM_LEN, u1H2CPsTuneParm);
1176 void rtl8723b_set_FwPwrModeInIPS_cmd(struct adapter *padapter, u8 cmd_param)
1178 /* BIT0:enable, BIT1:NoConnect32k */
1180 DBG_871X("%s()\n", __func__);
1182 FillH2CCmd8723B(padapter, H2C_8723B_FWLPS_IN_IPS_, 1, &cmd_param);
1185 #ifdef CONFIG_WOWLAN
1186 static void rtl8723b_set_FwWoWlanCtrl_Cmd(struct adapter *padapter, u8 bFuncEn)
1188 struct security_priv *psecpriv = &padapter->securitypriv;
1189 u8 u1H2CWoWlanCtrlParm[H2C_WOWLAN_LEN] = {0};
1190 u8 discont_wake = 1, gpionum = 0, gpio_dur = 0, hw_unicast = 0;
1191 u8 sdio_wakeup_enable = 1;
1192 u8 gpio_high_active = 0; /* 0: low active, 1: high active */
1195 #ifdef CONFIG_GPIO_WAKEUP
1196 gpionum = WAKEUP_GPIO_IDX;
1197 sdio_wakeup_enable = 0;
1200 #ifdef CONFIG_PNO_SUPPORT
1201 if (!ppwrpriv->wowlan_pno_enable)
1205 if (psecpriv->dot11PrivacyAlgrthm == _WEP40_ || psecpriv->dot11PrivacyAlgrthm == _WEP104_)
1208 DBG_871X("%s(): bFuncEn =%d\n", __func__, bFuncEn);
1210 SET_H2CCMD_WOWLAN_FUNC_ENABLE(u1H2CWoWlanCtrlParm, bFuncEn);
1211 SET_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(u1H2CWoWlanCtrlParm, 0);
1212 SET_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(u1H2CWoWlanCtrlParm, magic_pkt);
1213 SET_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(u1H2CWoWlanCtrlParm, hw_unicast);
1214 SET_H2CCMD_WOWLAN_ALL_PKT_DROP(u1H2CWoWlanCtrlParm, 0);
1215 SET_H2CCMD_WOWLAN_GPIO_ACTIVE(u1H2CWoWlanCtrlParm, gpio_high_active);
1216 SET_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(u1H2CWoWlanCtrlParm, discont_wake);
1217 SET_H2CCMD_WOWLAN_GPIONUM(u1H2CWoWlanCtrlParm, gpionum);
1218 SET_H2CCMD_WOWLAN_DATAPIN_WAKE_UP(u1H2CWoWlanCtrlParm, sdio_wakeup_enable);
1219 SET_H2CCMD_WOWLAN_GPIO_DURATION(u1H2CWoWlanCtrlParm, gpio_dur);
1220 /* SET_H2CCMD_WOWLAN_GPIO_PULSE_EN(u1H2CWoWlanCtrlParm, 1); */
1221 SET_H2CCMD_WOWLAN_GPIO_PULSE_COUNT(u1H2CWoWlanCtrlParm, 0x09);
1223 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CWoWlanCtrlParm:", u1H2CWoWlanCtrlParm, H2C_WOWLAN_LEN);
1225 FillH2CCmd8723B(padapter, H2C_8723B_WOWLAN, H2C_WOWLAN_LEN, u1H2CWoWlanCtrlParm);
1228 static void rtl8723b_set_FwRemoteWakeCtrl_Cmd(struct adapter *padapter, u8 benable)
1230 u8 u1H2CRemoteWakeCtrlParm[H2C_REMOTE_WAKE_CTRL_LEN] = {0};
1231 struct security_priv *psecuritypriv = &(padapter->securitypriv);
1232 struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(padapter);
1234 DBG_871X("%s(): Enable =%d\n", __func__, benable);
1236 if (!ppwrpriv->wowlan_pno_enable) {
1237 SET_H2CCMD_REMOTE_WAKECTRL_ENABLE(u1H2CRemoteWakeCtrlParm, benable);
1238 SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(u1H2CRemoteWakeCtrlParm, 1);
1239 #ifdef CONFIG_GTK_OL
1240 if (psecuritypriv->binstallKCK_KEK &&
1241 psecuritypriv->dot11PrivacyAlgrthm == _AES_) {
1242 SET_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(u1H2CRemoteWakeCtrlParm, 1);
1244 DBG_871X("no kck or security is not AES\n");
1245 SET_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(u1H2CRemoteWakeCtrlParm, 0);
1247 #endif /* CONFIG_GTK_OL */
1249 SET_H2CCMD_REMOTE_WAKE_CTRL_FW_UNICAST_EN(u1H2CRemoteWakeCtrlParm, 1);
1251 if ((psecuritypriv->dot11PrivacyAlgrthm == _AES_) ||
1252 (psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_))
1253 SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_ACTION(u1H2CRemoteWakeCtrlParm, 0);
1255 SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_ACTION(u1H2CRemoteWakeCtrlParm, 1);
1257 #ifdef CONFIG_PNO_SUPPORT
1259 SET_H2CCMD_REMOTE_WAKECTRL_ENABLE(u1H2CRemoteWakeCtrlParm, benable);
1260 SET_H2CCMD_REMOTE_WAKE_CTRL_NLO_OFFLOAD_EN(u1H2CRemoteWakeCtrlParm, benable);
1263 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CRemoteWakeCtrlParm:", u1H2CRemoteWakeCtrlParm, H2C_REMOTE_WAKE_CTRL_LEN);
1264 FillH2CCmd8723B(padapter, H2C_8723B_REMOTE_WAKE_CTRL,
1265 H2C_REMOTE_WAKE_CTRL_LEN, u1H2CRemoteWakeCtrlParm);
1266 #ifdef CONFIG_PNO_SUPPORT
1267 if (ppwrpriv->wowlan_pno_enable && ppwrpriv->pno_in_resume == false) {
1268 res = rtw_read8(padapter, REG_PNO_STATUS);
1269 DBG_871X("cmd: 0x81 REG_PNO_STATUS: 0x%02x\n", res);
1270 while (!(res&BIT(7)) && count < 25) {
1271 DBG_871X("[%d] cmd: 0x81 REG_PNO_STATUS: 0x%02x\n", count, res);
1272 res = rtw_read8(padapter, REG_PNO_STATUS);
1276 DBG_871X("cmd: 0x81 REG_PNO_STATUS: 0x%02x\n", res);
1278 #endif /* CONFIG_PNO_SUPPORT */
1281 static void rtl8723b_set_FwAOACGlobalInfo_Cmd(struct adapter *padapter, u8 group_alg, u8 pairwise_alg)
1283 u8 u1H2CAOACGlobalInfoParm[H2C_AOAC_GLOBAL_INFO_LEN] = {0};
1285 DBG_871X("%s(): group_alg =%d pairwise_alg =%d\n", __func__, group_alg, pairwise_alg);
1287 SET_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(u1H2CAOACGlobalInfoParm, pairwise_alg);
1288 SET_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(u1H2CAOACGlobalInfoParm, group_alg);
1290 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CAOACGlobalInfoParm:", u1H2CAOACGlobalInfoParm, H2C_AOAC_GLOBAL_INFO_LEN);
1292 FillH2CCmd8723B(padapter, H2C_8723B_AOAC_GLOBAL_INFO, H2C_AOAC_GLOBAL_INFO_LEN, u1H2CAOACGlobalInfoParm);
1295 #ifdef CONFIG_PNO_SUPPORT
1296 static void rtl8723b_set_FwScanOffloadInfo_cmd(struct adapter *padapter, PRSVDPAGE_LOC rsvdpageloc, u8 enable)
1298 u8 u1H2CScanOffloadInfoParm[H2C_SCAN_OFFLOAD_CTRL_LEN] = {0};
1299 u8 res = 0, count = 0;
1300 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1302 DBG_871X("%s: loc_probe_packet:%d, loc_scan_info: %d loc_ssid_info:%d\n",
1303 __func__, rsvdpageloc->LocProbePacket, rsvdpageloc->LocScanInfo, rsvdpageloc->LocSSIDInfo);
1305 SET_H2CCMD_AOAC_NLO_FUN_EN(u1H2CScanOffloadInfoParm, enable);
1306 SET_H2CCMD_AOAC_RSVDPAGE_LOC_SCAN_INFO(u1H2CScanOffloadInfoParm, rsvdpageloc->LocScanInfo);
1307 SET_H2CCMD_AOAC_RSVDPAGE_LOC_PROBE_PACKET(u1H2CScanOffloadInfoParm, rsvdpageloc->LocProbePacket);
1308 SET_H2CCMD_AOAC_RSVDPAGE_LOC_SSID_INFO(u1H2CScanOffloadInfoParm, rsvdpageloc->LocSSIDInfo);
1310 RT_PRINT_DATA(_module_hal_init_c_, _drv_always_, "u1H2CScanOffloadInfoParm:", u1H2CScanOffloadInfoParm, H2C_SCAN_OFFLOAD_CTRL_LEN);
1311 FillH2CCmd8723B(padapter, H2C_8723B_D0_SCAN_OFFLOAD_INFO, H2C_SCAN_OFFLOAD_CTRL_LEN, u1H2CScanOffloadInfoParm);
1315 #endif /* CONFIG_PNO_SUPPORT */
1317 static void rtl8723b_set_FwWoWlanRelated_cmd(struct adapter *padapter, u8 enable)
1319 struct security_priv *psecpriv = &padapter->securitypriv;
1320 struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(padapter);
1321 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1322 struct sta_info *psta = NULL;
1325 DBG_871X_LEVEL(_drv_always_, "+%s()+: enable =%d\n", __func__, enable);
1327 rtl8723b_set_FwAOACGlobalInfo_Cmd(padapter, psecpriv->dot118021XGrpPrivacy, psecpriv->dot11PrivacyAlgrthm);
1329 rtl8723b_set_FwJoinBssRpt_cmd(padapter, RT_MEDIA_CONNECT); /* RT_MEDIA_CONNECT will confuse in the future */
1331 if (!(ppwrpriv->wowlan_pno_enable)) {
1332 psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(pmlmepriv));
1334 rtl8723b_set_FwMediaStatusRpt_cmd(padapter, RT_MEDIA_CONNECT, psta->mac_id);
1336 DBG_871X("%s(): Disconnected, no FwMediaStatusRpt CONNECT\n", __func__);
1340 if (!(ppwrpriv->wowlan_pno_enable)) {
1341 rtl8723b_set_FwDisconDecision_cmd(padapter, enable);
1344 if ((psecpriv->dot11PrivacyAlgrthm != _WEP40_) || (psecpriv->dot11PrivacyAlgrthm != _WEP104_))
1347 rtl8723b_set_FwKeepAlive_cmd(padapter, enable, pkt_type);
1351 rtl8723b_set_FwWoWlanCtrl_Cmd(padapter, enable);
1354 rtl8723b_set_FwRemoteWakeCtrl_Cmd(padapter, enable);
1356 rtl8723b_set_FwRemoteWakeCtrl_Cmd(padapter, enable);
1358 rtl8723b_set_FwWoWlanCtrl_Cmd(padapter, enable);
1361 DBG_871X_LEVEL(_drv_always_, "-%s()-\n", __func__);
1364 void rtl8723b_set_wowlan_cmd(struct adapter *padapter, u8 enable)
1366 rtl8723b_set_FwWoWlanRelated_cmd(padapter, enable);
1368 #endif /* CONFIG_WOWLAN */
1370 #ifdef CONFIG_AP_WOWLAN
1371 static void rtl8723b_set_FwAPWoWlanCtrl_Cmd(struct adapter *padapter, u8 bFuncEn)
1373 u8 u1H2CAPWoWlanCtrlParm[H2C_WOWLAN_LEN] = {0};
1374 u8 gpionum = 0, gpio_dur = 0;
1375 u8 gpio_high_active = 1; /* 0: low active, 1: high active */
1376 u8 gpio_pulse = bFuncEn;
1377 #ifdef CONFIG_GPIO_WAKEUP
1378 gpionum = WAKEUP_GPIO_IDX;
1381 DBG_871X("%s(): bFuncEn =%d\n", __func__, bFuncEn);
1388 SET_H2CCMD_AP_WOW_GPIO_CTRL_INDEX(u1H2CAPWoWlanCtrlParm,
1390 SET_H2CCMD_AP_WOW_GPIO_CTRL_PLUS(u1H2CAPWoWlanCtrlParm,
1392 SET_H2CCMD_AP_WOW_GPIO_CTRL_HIGH_ACTIVE(u1H2CAPWoWlanCtrlParm,
1394 SET_H2CCMD_AP_WOW_GPIO_CTRL_EN(u1H2CAPWoWlanCtrlParm,
1396 SET_H2CCMD_AP_WOW_GPIO_CTRL_DURATION(u1H2CAPWoWlanCtrlParm,
1399 FillH2CCmd8723B(padapter, H2C_8723B_AP_WOW_GPIO_CTRL,
1400 H2C_AP_WOW_GPIO_CTRL_LEN, u1H2CAPWoWlanCtrlParm);
1403 static void rtl8723b_set_Fw_AP_Offload_Cmd(struct adapter *padapter, u8 bFuncEn)
1405 u8 u1H2CAPOffloadCtrlParm[H2C_WOWLAN_LEN] = {0};
1407 DBG_871X("%s(): bFuncEn =%d\n", __func__, bFuncEn);
1409 SET_H2CCMD_AP_WOWLAN_EN(u1H2CAPOffloadCtrlParm, bFuncEn);
1411 FillH2CCmd8723B(padapter, H2C_8723B_AP_OFFLOAD,
1412 H2C_AP_OFFLOAD_LEN, u1H2CAPOffloadCtrlParm);
1415 static void rtl8723b_set_AP_FwWoWlan_cmd(struct adapter *padapter, u8 enable)
1417 DBG_871X_LEVEL(_drv_always_, "+%s()+: enable =%d\n", __func__, enable);
1419 rtl8723b_set_FwJoinBssRpt_cmd(padapter, RT_MEDIA_CONNECT);
1420 issue_beacon(padapter, 0);
1423 rtl8723b_set_FwAPWoWlanCtrl_Cmd(padapter, enable);
1425 rtl8723b_set_Fw_AP_Offload_Cmd(padapter, enable);
1427 DBG_871X_LEVEL(_drv_always_, "-%s()-\n", __func__);
1431 void rtl8723b_set_ap_wowlan_cmd(struct adapter *padapter, u8 enable)
1433 rtl8723b_set_AP_FwWoWlan_cmd(padapter, enable);
1435 #endif /* CONFIG_AP_WOWLAN */
1438 /* Description: Fill the reserved packets that FW will use to RSVD page. */
1439 /* Now we just send 4 types packet to rsvd page. */
1440 /* (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */
1442 /* bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */
1443 /* so we need to set the packet length to total lengh. */
1444 /* true: At the second time, we should send the first packet (default:beacon) */
1445 /* to Hw again and set the lengh in descriptor to the real beacon lengh. */
1446 /* 2009.10.15 by tynli. */
1447 static void rtl8723b_set_FwRsvdPagePkt(
1448 struct adapter *padapter, bool bDLFinished
1451 struct hal_com_data *pHalData;
1452 struct xmit_frame *pcmdframe;
1453 struct pkt_attrib *pattrib;
1454 struct xmit_priv *pxmitpriv;
1455 struct mlme_ext_priv *pmlmeext;
1456 struct mlme_ext_info *pmlmeinfo;
1457 struct pwrctrl_priv *pwrctl;
1458 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1459 u32 BeaconLength = 0, PSPollLength = 0;
1460 u32 NullDataLength = 0, QosNullLength = 0, BTQosNullLength = 0;
1461 u8 *ReservedPagePacket;
1462 u8 TxDescLen = TXDESC_SIZE, TxDescOffset = TXDESC_OFFSET;
1463 u8 TotalPageNum = 0, CurtPktPageNum = 0, RsvdPageNum = 0;
1464 u16 BufIndex, PageSize = 128;
1465 u32 TotalPacketLen, MaxRsvdPageBufSize = 0;
1466 RSVDPAGE_LOC RsvdPageLoc;
1467 #ifdef CONFIG_WOWLAN
1468 u32 ARPLegnth = 0, GTKLegnth = 0;
1470 u8 cur_dot11txpn[8];
1471 #ifdef CONFIG_GTK_OL
1472 struct sta_priv *pstapriv = &padapter->stapriv;
1473 struct sta_info *psta;
1474 u8 kek[RTW_KEK_LEN];
1475 u8 kck[RTW_KCK_LEN];
1479 /* DBG_871X("%s---->\n", __func__); */
1481 pHalData = GET_HAL_DATA(padapter);
1482 pxmitpriv = &padapter->xmitpriv;
1483 pmlmeext = &padapter->mlmeextpriv;
1484 pmlmeinfo = &pmlmeext->mlmext_info;
1485 pwrctl = adapter_to_pwrctl(padapter);
1487 RsvdPageNum = BCNQ_PAGE_NUM_8723B + WOWLAN_PAGE_NUM_8723B;
1488 MaxRsvdPageBufSize = RsvdPageNum*PageSize;
1490 pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv);
1491 if (pcmdframe == NULL) {
1492 DBG_871X("%s: alloc ReservedPagePacket fail!\n", __func__);
1496 ReservedPagePacket = pcmdframe->buf_addr;
1497 memset(&RsvdPageLoc, 0, sizeof(RSVDPAGE_LOC));
1500 BufIndex = TxDescOffset;
1501 ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
1503 /* When we count the first page size, we need to reserve description size for the RSVD */
1504 /* packet, it will be filled in front of the packet in TXPKTBUF. */
1505 CurtPktPageNum = (u8)PageNum_128(TxDescLen + BeaconLength);
1506 /* If we don't add 1 more page, the WOWLAN function has a problem. Baron thinks it's a bug of firmware */
1507 if (CurtPktPageNum == 1)
1508 CurtPktPageNum += 1;
1510 TotalPageNum += CurtPktPageNum;
1512 BufIndex += (CurtPktPageNum*PageSize);
1515 RsvdPageLoc.LocPsPoll = TotalPageNum;
1516 ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);
1517 rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false, false);
1519 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: PS-POLL %p %d\n", */
1520 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], (PSPollLength+TxDescLen)); */
1522 CurtPktPageNum = (u8)PageNum_128(TxDescLen + PSPollLength);
1524 TotalPageNum += CurtPktPageNum;
1526 BufIndex += (CurtPktPageNum*PageSize);
1528 /* 3 (3) null data */
1529 RsvdPageLoc.LocNullData = TotalPageNum;
1530 ConstructNullFunctionData(
1532 &ReservedPagePacket[BufIndex],
1534 get_my_bssid(&pmlmeinfo->network),
1537 rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false, false);
1539 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: NULL DATA %p %d\n", */
1540 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], (NullDataLength+TxDescLen)); */
1542 CurtPktPageNum = (u8)PageNum_128(TxDescLen + NullDataLength);
1544 TotalPageNum += CurtPktPageNum;
1546 BufIndex += (CurtPktPageNum*PageSize);
1548 /* 3 (5) Qos null data */
1549 RsvdPageLoc.LocQosNull = TotalPageNum;
1550 ConstructNullFunctionData(
1552 &ReservedPagePacket[BufIndex],
1554 get_my_bssid(&pmlmeinfo->network),
1557 rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false, false);
1559 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: QOS NULL DATA %p %d\n", */
1560 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], (QosNullLength+TxDescLen)); */
1562 CurtPktPageNum = (u8)PageNum_128(TxDescLen + QosNullLength);
1564 TotalPageNum += CurtPktPageNum;
1566 BufIndex += (CurtPktPageNum*PageSize);
1568 /* 3 (6) BT Qos null data */
1569 RsvdPageLoc.LocBTQosNull = TotalPageNum;
1570 ConstructNullFunctionData(
1572 &ReservedPagePacket[BufIndex],
1574 get_my_bssid(&pmlmeinfo->network),
1577 rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true, false);
1579 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: BT QOS NULL DATA %p %d\n", */
1580 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], (BTQosNullLength+TxDescLen)); */
1582 CurtPktPageNum = (u8)PageNum_128(TxDescLen + BTQosNullLength);
1584 TotalPageNum += CurtPktPageNum;
1586 BufIndex += (CurtPktPageNum*PageSize);
1588 #ifdef CONFIG_WOWLAN
1589 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1590 /* if (pwrctl->wowlan_mode == true) { */
1591 /* BufIndex += (CurtPktPageNum*PageSize); */
1594 rtw_get_current_ip_address(padapter, currentip);
1595 RsvdPageLoc.LocArpRsp = TotalPageNum;
1597 ConstructARPResponse(
1599 &ReservedPagePacket[BufIndex],
1603 rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], ARPLegnth, false, false, true);
1605 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: ARP RSP %p %d\n", */
1606 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], (ARPLegnth+TxDescLen)); */
1608 CurtPktPageNum = (u8)PageNum_128(TxDescLen + ARPLegnth);
1610 TotalPageNum += CurtPktPageNum;
1612 BufIndex += (CurtPktPageNum*PageSize);
1615 rtw_get_sec_iv(padapter, cur_dot11txpn, get_my_bssid(&pmlmeinfo->network));
1616 RsvdPageLoc.LocRemoteCtrlInfo = TotalPageNum;
1617 memcpy(ReservedPagePacket+BufIndex-TxDescLen, cur_dot11txpn, _AES_IV_LEN_);
1619 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: SEC IV %p %d\n", */
1620 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], _AES_IV_LEN_); */
1622 CurtPktPageNum = (u8)PageNum_128(_AES_IV_LEN_);
1624 TotalPageNum += CurtPktPageNum;
1626 #ifdef CONFIG_GTK_OL
1627 BufIndex += (CurtPktPageNum*PageSize);
1629 /* if the ap staion info. exists, get the kek, kck from staion info. */
1630 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
1632 memset(kek, 0, RTW_KEK_LEN);
1633 memset(kck, 0, RTW_KCK_LEN);
1634 DBG_8192C("%s, KEK, KCK download rsvd page all zero\n", __func__);
1636 memcpy(kek, psta->kek, RTW_KEK_LEN);
1637 memcpy(kck, psta->kck, RTW_KCK_LEN);
1641 RsvdPageLoc.LocGTKInfo = TotalPageNum;
1642 memcpy(ReservedPagePacket+BufIndex-TxDescLen, kck, RTW_KCK_LEN);
1643 memcpy(ReservedPagePacket+BufIndex-TxDescLen+RTW_KCK_LEN, kek, RTW_KEK_LEN);
1645 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: KEK KCK %p %d\n", */
1646 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], (TxDescLen + RTW_KCK_LEN + RTW_KEK_LEN)); */
1648 CurtPktPageNum = (u8)PageNum_128(TxDescLen + RTW_KCK_LEN + RTW_KEK_LEN);
1650 TotalPageNum += CurtPktPageNum;
1652 BufIndex += (CurtPktPageNum*PageSize);
1654 /* 3(10) GTK Response */
1655 RsvdPageLoc.LocGTKRsp = TotalPageNum;
1656 ConstructGTKResponse(
1658 &ReservedPagePacket[BufIndex],
1662 rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], GTKLegnth, false, false, true);
1663 /* DBG_871X("%s(): HW_VAR_SET_TX_CMD: GTK RSP %p %d\n", */
1664 /* __func__, &ReservedPagePacket[BufIndex-TxDescLen], (TxDescLen + GTKLegnth)); */
1666 CurtPktPageNum = (u8)PageNum_128(TxDescLen + GTKLegnth);
1668 TotalPageNum += CurtPktPageNum;
1670 BufIndex += (CurtPktPageNum*PageSize);
1672 /* below page is empty for GTK extension memory */
1673 /* 3(11) GTK EXT MEM */
1674 RsvdPageLoc.LocGTKEXTMEM = TotalPageNum;
1678 TotalPageNum += CurtPktPageNum;
1680 TotalPacketLen = BufIndex-TxDescLen + 256; /* extension memory for FW */
1682 TotalPacketLen = BufIndex-TxDescLen + sizeof (union pn48); /* IV len */
1683 #endif /* CONFIG_GTK_OL */
1685 #endif /* CONFIG_WOWLAN */
1687 #ifdef CONFIG_PNO_SUPPORT
1688 if (pwrctl->pno_in_resume == false && pwrctl->pno_inited == true) {
1690 RsvdPageLoc.LocProbePacket = TotalPageNum;
1693 &ReservedPagePacket[BufIndex],
1696 rtl8723b_fill_fake_txdesc(padapter,
1697 &ReservedPagePacket[BufIndex-TxDescLen],
1698 ProbeReqLength, false, false, false);
1699 #ifdef CONFIG_PNO_SET_DEBUG
1702 printk("probe req pkt =>\n");
1703 for (gj = 0; gj < ProbeReqLength+TxDescLen; gj++) {
1704 printk(" %02x ", ReservedPagePacket[BufIndex-TxDescLen+gj]);
1712 (u8)PageNum_128(TxDescLen + ProbeReqLength);
1714 TotalPageNum += CurtPktPageNum;
1716 BufIndex += (CurtPktPageNum*PageSize);
1719 RsvdPageLoc.LocPNOInfo = TotalPageNum;
1720 ConstructPnoInfo(padapter, &ReservedPagePacket[BufIndex-TxDescLen], &PNOLength);
1721 #ifdef CONFIG_PNO_SET_DEBUG
1724 printk("PNO pkt =>\n");
1725 for (gj = 0; gj < PNOLength; gj++) {
1726 printk(" %02x ", ReservedPagePacket[BufIndex-TxDescLen+gj]);
1727 if ((gj + 1)%8 == 0)
1734 CurtPktPageNum = (u8)PageNum_128(PNOLength);
1735 TotalPageNum += CurtPktPageNum;
1736 BufIndex += (CurtPktPageNum*PageSize);
1738 /* SSID List Page */
1739 RsvdPageLoc.LocSSIDInfo = TotalPageNum;
1740 ConstructSSIDList(padapter, &ReservedPagePacket[BufIndex-TxDescLen], &SSIDLegnth);
1741 #ifdef CONFIG_PNO_SET_DEBUG
1744 printk("SSID list pkt =>\n");
1745 for (gj = 0; gj < SSIDLegnth; gj++) {
1746 printk(" %02x ", ReservedPagePacket[BufIndex-TxDescLen+gj]);
1747 if ((gj + 1)%8 == 0)
1753 CurtPktPageNum = (u8)PageNum_128(SSIDLegnth);
1754 TotalPageNum += CurtPktPageNum;
1755 BufIndex += (CurtPktPageNum*PageSize);
1757 /* Scan Info Page */
1758 RsvdPageLoc.LocScanInfo = TotalPageNum;
1759 ConstructScanInfo(padapter, &ReservedPagePacket[BufIndex-TxDescLen], &ScanInfoLength);
1760 #ifdef CONFIG_PNO_SET_DEBUG
1763 printk("Scan info pkt =>\n");
1764 for (gj = 0; gj < ScanInfoLength; gj++) {
1765 printk(" %02x ", ReservedPagePacket[BufIndex-TxDescLen+gj]);
1766 if ((gj + 1)%8 == 0)
1772 CurtPktPageNum = (u8)PageNum_128(ScanInfoLength);
1773 TotalPageNum += CurtPktPageNum;
1774 BufIndex += (CurtPktPageNum*PageSize);
1776 TotalPacketLen = BufIndex + ScanInfoLength;
1778 TotalPacketLen = BufIndex + BTQosNullLength;
1780 #else /* CONFIG_PNO_SUPPORT */
1781 TotalPacketLen = BufIndex + BTQosNullLength;
1785 if (TotalPacketLen > MaxRsvdPageBufSize) {
1786 DBG_871X("%s(): ERROR: The rsvd page size is not enough!!TotalPacketLen %d, MaxRsvdPageBufSize %d\n", __func__,
1787 TotalPacketLen, MaxRsvdPageBufSize);
1790 /* update attribute */
1791 pattrib = &pcmdframe->attrib;
1792 update_mgntframe_attrib(padapter, pattrib);
1793 pattrib->qsel = 0x10;
1794 pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TxDescOffset;
1795 dump_mgntframe_and_wait(padapter, pcmdframe, 100);
1798 DBG_871X("%s: Set RSVD page location to Fw , TotalPacketLen(%d), TotalPageNum(%d)\n", __func__, TotalPacketLen, TotalPageNum);
1799 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1800 rtl8723b_set_FwRsvdPage_cmd(padapter, &RsvdPageLoc);
1801 rtl8723b_set_FwAoacRsvdPage_cmd(padapter, &RsvdPageLoc);
1803 rtl8723b_set_FwAoacRsvdPage_cmd(padapter, &RsvdPageLoc);
1804 #ifdef CONFIG_PNO_SUPPORT
1805 if (pwrctl->pno_in_resume)
1806 rtl8723b_set_FwScanOffloadInfo_cmd(padapter,
1809 rtl8723b_set_FwScanOffloadInfo_cmd(padapter,
1817 rtw_free_xmitframe(pxmitpriv, pcmdframe);
1820 #ifdef CONFIG_AP_WOWLAN
1822 /* Description: Fill the reserved packets that FW will use to RSVD page. */
1823 /* Now we just send 2 types packet to rsvd page. (1)Beacon, (2)ProbeRsp. */
1825 /* Input: bDLFinished */
1827 /* false: At the first time we will send all the packets as a large packet to Hw, */
1828 /* so we need to set the packet length to total lengh. */
1830 /* true: At the second time, we should send the first packet (default:beacon) */
1831 /* to Hw again and set the lengh in descriptor to the real beacon lengh. */
1832 /* 2009.10.15 by tynli. */
1833 static void rtl8723b_set_AP_FwRsvdPagePkt(
1834 struct adapter *padapter, bool bDLFinished
1837 struct hal_com_data *pHalData;
1838 struct xmit_frame *pcmdframe;
1839 struct pkt_attrib *pattrib;
1840 struct xmit_priv *pxmitpriv;
1841 struct mlme_ext_priv *pmlmeext;
1842 struct mlme_ext_info *pmlmeinfo;
1843 struct pwrctrl_priv *pwrctl;
1844 u32 BeaconLength = 0, ProbeRspLength = 0;
1845 u8 *ReservedPagePacket;
1846 u8 TxDescLen = TXDESC_SIZE, TxDescOffset = TXDESC_OFFSET;
1847 u8 TotalPageNum = 0, CurtPktPageNum = 0, RsvdPageNum = 0;
1849 u16 BufIndex, PageSize = 128;
1850 u32 TotalPacketLen = 0, MaxRsvdPageBufSize = 0;
1851 RSVDPAGE_LOC RsvdPageLoc;
1853 /* DBG_871X("%s---->\n", __func__); */
1854 DBG_8192C("+" FUNC_ADPT_FMT ": iface_type =%d\n",
1855 FUNC_ADPT_ARG(padapter), get_iface_type(padapter));
1857 pHalData = GET_HAL_DATA(padapter);
1858 pxmitpriv = &padapter->xmitpriv;
1859 pmlmeext = &padapter->mlmeextpriv;
1860 pmlmeinfo = &pmlmeext->mlmext_info;
1861 pwrctl = adapter_to_pwrctl(padapter);
1863 RsvdPageNum = BCNQ_PAGE_NUM_8723B + AP_WOWLAN_PAGE_NUM_8723B;
1864 MaxRsvdPageBufSize = RsvdPageNum*PageSize;
1866 pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv);
1867 if (pcmdframe == NULL) {
1868 DBG_871X("%s: alloc ReservedPagePacket fail!\n", __func__);
1872 ReservedPagePacket = pcmdframe->buf_addr;
1873 memset(&RsvdPageLoc, 0, sizeof(RSVDPAGE_LOC));
1876 BufIndex = TxDescOffset;
1877 ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
1879 /* When we count the first page size, we need to reserve description size for the RSVD */
1880 /* packet, it will be filled in front of the packet in TXPKTBUF. */
1881 CurtPktPageNum = (u8)PageNum_128(TxDescLen + BeaconLength);
1882 /* If we don't add 1 more page, the WOWLAN function has a problem. Baron thinks it's a bug of firmware */
1883 if (CurtPktPageNum == 1)
1884 CurtPktPageNum += 1;
1885 TotalPageNum += CurtPktPageNum;
1887 BufIndex += (CurtPktPageNum*PageSize);
1889 /* 2 (4) probe response */
1890 RsvdPageLoc.LocProbeRsp = TotalPageNum;
1892 rtw_get_current_ip_address(padapter, currentip);
1896 &ReservedPagePacket[BufIndex],
1900 rtl8723b_fill_fake_txdesc(padapter,
1901 &ReservedPagePacket[BufIndex-TxDescLen],
1903 false, false, false);
1905 DBG_871X("%s(): HW_VAR_SET_TX_CMD: PROBE RSP %p %d\n",
1906 __func__, &ReservedPagePacket[BufIndex-TxDescLen],
1907 (ProbeRspLength+TxDescLen));
1909 CurtPktPageNum = (u8)PageNum_128(TxDescLen + ProbeRspLength);
1911 TotalPageNum += CurtPktPageNum;
1913 BufIndex += (CurtPktPageNum*PageSize);
1915 TotalPacketLen = BufIndex + ProbeRspLength;
1917 if (TotalPacketLen > MaxRsvdPageBufSize) {
1918 DBG_871X("%s(): ERROR: The rsvd page size is not enough \
1919 !!TotalPacketLen %d, MaxRsvdPageBufSize %d\n",
1920 __func__, TotalPacketLen, MaxRsvdPageBufSize);
1923 /* update attribute */
1924 pattrib = &pcmdframe->attrib;
1925 update_mgntframe_attrib(padapter, pattrib);
1926 pattrib->qsel = 0x10;
1927 pattrib->pktlen = TotalPacketLen - TxDescOffset;
1928 pattrib->last_txcmdsz = TotalPacketLen - TxDescOffset;
1929 dump_mgntframe_and_wait(padapter, pcmdframe, 100);
1932 DBG_871X("%s: Set RSVD page location to Fw , TotalPacketLen(%d), TotalPageNum(%d)\n", __func__, TotalPacketLen, TotalPageNum);
1933 rtl8723b_set_ap_wow_rsvdpage_cmd(padapter, &RsvdPageLoc);
1937 rtw_free_xmitframe(pxmitpriv, pcmdframe);
1939 #endif /* CONFIG_AP_WOWLAN */
1941 void rtl8723b_download_rsvd_page(struct adapter *padapter, u8 mstatus)
1943 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1944 #ifdef CONFIG_AP_WOWLAN
1945 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
1947 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1948 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1949 bool bcn_valid = false;
1954 DBG_8192C("+" FUNC_ADPT_FMT ": iface_type =%d mstatus(%x)\n",
1955 FUNC_ADPT_ARG(padapter), get_iface_type(padapter), mstatus);
1957 if (mstatus == RT_MEDIA_CONNECT) {
1958 bool bRecover = false;
1961 /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
1962 /* Suggested by filen. Added by tynli. */
1963 rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
1965 /* set REG_CR bit 8 */
1966 v8 = rtw_read8(padapter, REG_CR+1);
1967 v8 |= BIT(0); /* ENSWBCN */
1968 rtw_write8(padapter, REG_CR+1, v8);
1970 /* Disable Hw protection for a time which revserd for Hw sending beacon. */
1971 /* Fix download reserved page packet fail that access collision with the protection time. */
1972 /* 2010.05.11. Added by tynli. */
1973 val8 = rtw_read8(padapter, REG_BCN_CTRL);
1974 val8 &= ~EN_BCN_FUNCTION;
1975 val8 |= DIS_TSF_UDT;
1976 rtw_write8(padapter, REG_BCN_CTRL, val8);
1978 /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
1979 if (pHalData->RegFwHwTxQCtrl & BIT(6))
1982 /* To tell Hw the packet is not a real beacon frame. */
1983 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl & ~BIT(6));
1984 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
1986 /* Clear beacon valid check bit. */
1987 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
1988 rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
1993 #ifdef CONFIG_AP_WOWLAN
1994 if (pwrpriv->wowlan_ap_mode)
1995 rtl8723b_set_AP_FwRsvdPagePkt(padapter, 0);
1997 rtl8723b_set_FwRsvdPagePkt(padapter, 0);
1999 /* download rsvd page. */
2000 rtl8723b_set_FwRsvdPagePkt(padapter, 0);
2006 /* check rsvd page download OK. */
2007 rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bcn_valid));
2009 } while (!bcn_valid && (poll%10) != 0 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
2011 } while (!bcn_valid && DLBcnCount <= 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
2013 if (padapter->bSurpriseRemoved || padapter->bDriverStopped) {
2014 } else if (!bcn_valid)
2015 DBG_871X(ADPT_FMT": 1 DL RSVD page failed! DLBcnCount:%u, poll:%u\n",
2016 ADPT_ARG(padapter), DLBcnCount, poll);
2018 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
2019 pwrctl->fw_psmode_iface_id = padapter->iface_id;
2020 DBG_871X(ADPT_FMT": 1 DL RSVD page success! DLBcnCount:%u, poll:%u\n",
2021 ADPT_ARG(padapter), DLBcnCount, poll);
2024 /* 2010.05.11. Added by tynli. */
2025 val8 = rtw_read8(padapter, REG_BCN_CTRL);
2026 val8 |= EN_BCN_FUNCTION;
2027 val8 &= ~DIS_TSF_UDT;
2028 rtw_write8(padapter, REG_BCN_CTRL, val8);
2030 /* To make sure that if there exists an adapter which would like to send beacon. */
2031 /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
2032 /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
2033 /* the beacon cannot be sent by HW. */
2034 /* 2010.06.23. Added by tynli. */
2036 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl | BIT(6));
2037 pHalData->RegFwHwTxQCtrl |= BIT(6);
2040 /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
2041 v8 = rtw_read8(padapter, REG_CR+1);
2042 v8 &= ~BIT(0); /* ~ENSWBCN */
2043 rtw_write8(padapter, REG_CR+1, v8);
2047 void rtl8723b_set_rssi_cmd(struct adapter *padapter, u8 *param)
2049 rtl8723b_set_FwRssiSetting_cmd(padapter, param);
2052 void rtl8723b_set_FwJoinBssRpt_cmd(struct adapter *padapter, u8 mstatus)
2055 rtl8723b_download_rsvd_page(padapter, RT_MEDIA_CONNECT);
2058 /* arg[0] = macid */
2060 /* arg[2] = shortGIrate */
2061 /* arg[3] = init_rate */
2062 void rtl8723b_Add_RateATid(
2063 struct adapter *padapter,
2069 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2070 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2071 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2072 struct sta_info *psta;
2075 u8 shortGI = arg[2];
2077 u32 mask = bitmap&0x0FFFFFFF;
2079 psta = pmlmeinfo->FW_sta_info[mac_id].psta;
2085 if (rssi_level != DM_RATR_STA_INIT)
2086 mask = ODM_Get_Rate_Bitmap(&pHalData->odmpriv, mac_id, mask, rssi_level);
2088 DBG_871X("%s(): mac_id =%d raid = 0x%x bw =%d mask = 0x%x\n", __func__, mac_id, raid, bw, mask);
2089 rtl8723b_set_FwMacIdConfig_cmd(padapter, mac_id, raid, bw, shortGI, mask);
2092 static void ConstructBtNullFunctionData(
2093 struct adapter *padapter,
2103 struct ieee80211_hdr *pwlanhdr;
2106 struct mlme_ext_priv *pmlmeext;
2107 struct mlme_ext_info *pmlmeinfo;
2111 DBG_871X("+" FUNC_ADPT_FMT ": qos =%d eosp =%d ps =%d\n",
2112 FUNC_ADPT_ARG(padapter), bQoS, bEosp, bForcePowerSave);
2114 pwlanhdr = (struct ieee80211_hdr *)pframe;
2115 pmlmeext = &padapter->mlmeextpriv;
2116 pmlmeinfo = &pmlmeext->mlmext_info;
2118 if (NULL == StaAddr) {
2119 memcpy(bssid, myid(&padapter->eeprompriv), ETH_ALEN);
2123 fctrl = &pwlanhdr->frame_control;
2125 if (bForcePowerSave)
2129 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
2130 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2131 memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
2133 SetDuration(pwlanhdr, 0);
2134 SetSeqNum(pwlanhdr, 0);
2137 struct ieee80211_qos_hdr *pwlanqoshdr;
2139 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
2141 pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe;
2142 SetPriority(&pwlanqoshdr->qos_ctrl, AC);
2143 SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
2145 pktlen = sizeof(struct ieee80211_qos_hdr);
2147 SetFrameSubType(pframe, WIFI_DATA_NULL);
2149 pktlen = sizeof(struct ieee80211_hdr_3addr);
2155 static void SetFwRsvdPagePkt_BTCoex(struct adapter *padapter)
2157 struct hal_com_data *pHalData;
2158 struct xmit_frame *pcmdframe;
2159 struct pkt_attrib *pattrib;
2160 struct xmit_priv *pxmitpriv;
2161 struct mlme_ext_priv *pmlmeext;
2162 struct mlme_ext_info *pmlmeinfo;
2163 u32 BeaconLength = 0;
2164 u32 BTQosNullLength = 0;
2165 u8 *ReservedPagePacket;
2166 u8 TxDescLen, TxDescOffset;
2167 u8 TotalPageNum = 0, CurtPktPageNum = 0, RsvdPageNum = 0;
2168 u16 BufIndex, PageSize;
2169 u32 TotalPacketLen, MaxRsvdPageBufSize = 0;
2170 RSVDPAGE_LOC RsvdPageLoc;
2173 /* DBG_8192C("+" FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(padapter)); */
2175 pHalData = GET_HAL_DATA(padapter);
2176 pxmitpriv = &padapter->xmitpriv;
2177 pmlmeext = &padapter->mlmeextpriv;
2178 pmlmeinfo = &pmlmeext->mlmext_info;
2179 TxDescLen = TXDESC_SIZE;
2180 TxDescOffset = TXDESC_OFFSET;
2181 PageSize = PAGE_SIZE_TX_8723B;
2183 RsvdPageNum = BCNQ_PAGE_NUM_8723B;
2184 MaxRsvdPageBufSize = RsvdPageNum*PageSize;
2186 pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv);
2187 if (pcmdframe == NULL) {
2188 DBG_8192C("%s: alloc ReservedPagePacket fail!\n", __func__);
2192 ReservedPagePacket = pcmdframe->buf_addr;
2193 memset(&RsvdPageLoc, 0, sizeof(RSVDPAGE_LOC));
2196 BufIndex = TxDescOffset;
2197 ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
2199 /* When we count the first page size, we need to reserve description size for the RSVD */
2200 /* packet, it will be filled in front of the packet in TXPKTBUF. */
2201 CurtPktPageNum = (u8)PageNum_128(TxDescLen + BeaconLength);
2202 /* If we don't add 1 more page, the WOWLAN function has a problem. Baron thinks it's a bug of firmware */
2203 if (CurtPktPageNum == 1)
2204 CurtPktPageNum += 1;
2205 TotalPageNum += CurtPktPageNum;
2207 BufIndex += (CurtPktPageNum*PageSize);
2209 /* Jump to lastest page */
2210 if (BufIndex < (MaxRsvdPageBufSize - PageSize)) {
2211 BufIndex = TxDescOffset + (MaxRsvdPageBufSize - PageSize);
2212 TotalPageNum = BCNQ_PAGE_NUM_8723B - 1;
2215 /* 3 (6) BT Qos null data */
2216 RsvdPageLoc.LocBTQosNull = TotalPageNum;
2217 ConstructBtNullFunctionData(
2219 &ReservedPagePacket[BufIndex],
2224 rtl8723b_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true, false);
2226 CurtPktPageNum = (u8)PageNum_128(TxDescLen + BTQosNullLength);
2228 TotalPageNum += CurtPktPageNum;
2230 TotalPacketLen = BufIndex + BTQosNullLength;
2231 if (TotalPacketLen > MaxRsvdPageBufSize) {
2232 DBG_8192C(FUNC_ADPT_FMT ": ERROR: The rsvd page size is not enough!!TotalPacketLen %d, MaxRsvdPageBufSize %d\n",
2233 FUNC_ADPT_ARG(padapter), TotalPacketLen, MaxRsvdPageBufSize);
2237 /* update attribute */
2238 pattrib = &pcmdframe->attrib;
2239 update_mgntframe_attrib(padapter, pattrib);
2240 pattrib->qsel = 0x10;
2241 pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TxDescOffset;
2242 dump_mgntframe_and_wait(padapter, pcmdframe, 100);
2244 /* DBG_8192C(FUNC_ADPT_FMT ": Set RSVD page location to Fw, TotalPacketLen(%d), TotalPageNum(%d)\n", */
2245 /* FUNC_ADPT_ARG(padapter), TotalPacketLen, TotalPageNum); */
2246 rtl8723b_set_FwRsvdPage_cmd(padapter, &RsvdPageLoc);
2247 rtl8723b_set_FwAoacRsvdPage_cmd(padapter, &RsvdPageLoc);
2252 rtw_free_xmitframe(pxmitpriv, pcmdframe);
2255 void rtl8723b_download_BTCoex_AP_mode_rsvd_page(struct adapter *padapter)
2257 struct hal_com_data *pHalData;
2258 struct mlme_ext_priv *pmlmeext;
2259 struct mlme_ext_info *pmlmeinfo;
2260 u8 bRecover = false;
2261 u8 bcn_valid = false;
2267 DBG_8192C("+" FUNC_ADPT_FMT ": iface_type =%d fw_state = 0x%08X\n",
2268 FUNC_ADPT_ARG(padapter), get_iface_type(padapter), get_fwstate(&padapter->mlmepriv));
2271 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == false) {
2272 DBG_8192C(FUNC_ADPT_FMT ": [WARNING] not in AP mode!!\n",
2273 FUNC_ADPT_ARG(padapter));
2275 #endif /* CONFIG_DEBUG */
2277 pHalData = GET_HAL_DATA(padapter);
2278 pmlmeext = &padapter->mlmeextpriv;
2279 pmlmeinfo = &pmlmeext->mlmext_info;
2281 /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
2282 /* Suggested by filen. Added by tynli. */
2283 rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
2285 /* set REG_CR bit 8 */
2286 val8 = rtw_read8(padapter, REG_CR+1);
2287 val8 |= BIT(0); /* ENSWBCN */
2288 rtw_write8(padapter, REG_CR+1, val8);
2290 /* Disable Hw protection for a time which revserd for Hw sending beacon. */
2291 /* Fix download reserved page packet fail that access collision with the protection time. */
2292 /* 2010.05.11. Added by tynli. */
2293 val8 = rtw_read8(padapter, REG_BCN_CTRL);
2294 val8 &= ~EN_BCN_FUNCTION;
2295 val8 |= DIS_TSF_UDT;
2296 rtw_write8(padapter, REG_BCN_CTRL, val8);
2298 /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
2299 if (pHalData->RegFwHwTxQCtrl & BIT(6))
2302 /* To tell Hw the packet is not a real beacon frame. */
2303 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
2304 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
2306 /* Clear beacon valid check bit. */
2307 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
2308 rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
2313 SetFwRsvdPagePkt_BTCoex(padapter);
2318 /* check rsvd page download OK. */
2319 rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, &bcn_valid);
2321 } while (!bcn_valid && (poll%10) != 0 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
2322 } while (!bcn_valid && (DLBcnCount <= 100) && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
2324 if (true == bcn_valid) {
2325 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
2326 pwrctl->fw_psmode_iface_id = padapter->iface_id;
2327 DBG_8192C(ADPT_FMT": DL RSVD page success! DLBcnCount:%d, poll:%d\n",
2328 ADPT_ARG(padapter), DLBcnCount, poll);
2330 DBG_8192C(ADPT_FMT": DL RSVD page fail! DLBcnCount:%d, poll:%d\n",
2331 ADPT_ARG(padapter), DLBcnCount, poll);
2332 DBG_8192C(ADPT_FMT": DL RSVD page fail! bSurpriseRemoved =%d\n",
2333 ADPT_ARG(padapter), padapter->bSurpriseRemoved);
2334 DBG_8192C(ADPT_FMT": DL RSVD page fail! bDriverStopped =%d\n",
2335 ADPT_ARG(padapter), padapter->bDriverStopped);
2338 /* 2010.05.11. Added by tynli. */
2339 val8 = rtw_read8(padapter, REG_BCN_CTRL);
2340 val8 |= EN_BCN_FUNCTION;
2341 val8 &= ~DIS_TSF_UDT;
2342 rtw_write8(padapter, REG_BCN_CTRL, val8);
2344 /* To make sure that if there exists an adapter which would like to send beacon. */
2345 /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
2346 /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
2347 /* the beacon cannot be sent by HW. */
2348 /* 2010.06.23. Added by tynli. */
2350 pHalData->RegFwHwTxQCtrl |= BIT(6);
2351 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
2354 /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
2355 val8 = rtw_read8(padapter, REG_CR+1);
2356 val8 &= ~BIT(0); /* ~ENSWBCN */
2357 rtw_write8(padapter, REG_CR+1, val8);