1 /******************************************************************************
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 ******************************************************************************/
15 #define _RTL8723A_CMD_C_
17 #include <osdep_service.h>
18 #include <drv_types.h>
19 #include <recv_osdep.h>
20 #include <cmd_osdep.h>
21 #include <mlme_osdep.h>
22 #include <rtw_ioctl_set.h>
23 #include <rtl8723a_hal.h>
25 #define RTL92C_MAX_H2C_BOX_NUMS 4
26 #define RTL92C_MAX_CMD_LEN 5
27 #define MESSAGE_BOX_SIZE 4
28 #define EX_MESSAGE_BOX_SIZE 2
30 static u8 _is_fw_read_cmd_down(struct rtw_adapter *padapter, u8 msgbox_num)
37 valid = rtw_read8(padapter, REG_HMETFR) & BIT(msgbox_num);
40 } while ((!read_down) && (retry_cnts--));
45 /*****************************************
47 *| 31 - 8 |7 | 6 - 0 |
48 *| h2c_msg |Ext_bit |CMD_ID |
50 ******************************************/
51 s32 FillH2CCmd(struct rtw_adapter *padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)
58 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
63 padapter = GET_PRIMARY_ADAPTER(padapter);
64 pHalData = GET_HAL_DATA(padapter);
66 mutex_lock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex);
70 if (CmdLen > RTL92C_MAX_CMD_LEN)
72 if (padapter->bSurpriseRemoved == true)
75 /* pay attention to if race condition happened in H2C cmd setting. */
77 h2c_box_num = pHalData->LastHMEBoxNum;
79 if (!_is_fw_read_cmd_down(padapter, h2c_box_num)) {
80 DBG_8723A(" fw read cmd failed...\n");
85 memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen);
87 memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer, EX_MESSAGE_BOX_SIZE);
88 memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer+2, (CmdLen-EX_MESSAGE_BOX_SIZE));
89 *(u8 *)(&h2c_cmd) |= BIT(7);
92 *(u8 *)(&h2c_cmd) |= ElementID;
94 if (h2c_cmd & BIT(7)) {
95 msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE);
96 h2c_cmd_ex = le16_to_cpu(h2c_cmd_ex);
97 rtw_write16(padapter, msgbox_ex_addr, h2c_cmd_ex);
99 msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * MESSAGE_BOX_SIZE);
100 h2c_cmd = le32_to_cpu(h2c_cmd);
101 rtw_write32(padapter, msgbox_addr, h2c_cmd);
105 pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL92C_MAX_H2C_BOX_NUMS;
107 } while ((!bcmd_down) && (retry_cnts--));
112 mutex_unlock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex);
116 u8 rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u8 *param)
120 *((u32 *)param) = cpu_to_le32(*((u32 *)param));
122 FillH2CCmd(padapter, RSSI_SETTING_EID, 3, param);
127 u8 rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg)
133 mask = cpu_to_le32(mask);
134 memcpy(buf, &mask, 4);
137 FillH2CCmd(padapter, MACID_CONFIG_EID, 5, buf);
143 /* bitmap[0:27] = tx_rate_bitmap */
144 /* bitmap[28:31]= Rate Adaptive id */
145 /* arg[0:4] = macid */
146 /* arg[5] = Short GI */
147 void rtl8723a_add_rateatid(struct rtw_adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level)
149 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
151 u8 raid = (bitmap>>28) & 0x0f;
153 bitmap &= 0x0fffffff;
154 if (rssi_level != DM_RATR_STA_INIT)
155 bitmap = ODM_Get_Rate_Bitmap23a(&pHalData->odmpriv, macid, bitmap, rssi_level);
157 bitmap |= ((raid<<28)&0xf0000000);
159 if (pHalData->fw_ractrl == true) {
160 rtl8723a_set_raid_cmd(pAdapter, bitmap, arg);
162 u8 init_rate, shortGIrate = false;
164 init_rate = get_highest_rate_idx23a(bitmap&0x0fffffff)&0x3f;
166 shortGIrate = (arg&BIT(5)) ? true:false;
168 if (shortGIrate == true)
171 rtw_write8(pAdapter, (REG_INIDATA_RATE_SEL+macid), (u8)init_rate);
175 void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter *padapter, u8 Mode)
177 struct setpwrmode_parm H2CSetPwrMode;
178 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
179 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
181 DBG_8723A("%s: Mode =%d SmartPS =%d UAPSD =%d BcnMode = 0x%02x\n", __FUNCTION__,
182 Mode, pwrpriv->smart_ps, padapter->registrypriv.uapsd_enable, pwrpriv->bcn_ant_mode);
184 /* Forece leave RF low power mode for 1T1R to
185 prevent conficting setting in Fw power */
186 /* saving sequence. 2010.06.07. Added by tynli.
187 Suggested by SD3 yschang. */
188 if ((Mode != PS_MODE_ACTIVE) &&
189 (!IS_92C_SERIAL(pHalData->VersionID))) {
190 ODM_RF_Saving23a(&pHalData->odmpriv, true);
193 H2CSetPwrMode.Mode = Mode;
194 H2CSetPwrMode.SmartPS = pwrpriv->smart_ps;
195 H2CSetPwrMode.AwakeInterval = 1;
196 H2CSetPwrMode.bAllQueueUAPSD = padapter->registrypriv.uapsd_enable;
197 H2CSetPwrMode.BcnAntMode = pwrpriv->bcn_ant_mode;
199 FillH2CCmd(padapter, SET_PWRMODE_EID, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
203 static void ConstructBeacon(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
205 struct ieee80211_hdr *pwlanhdr;
207 u32 rate_len, pktlen;
208 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
209 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
210 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
211 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
213 /* DBG_8723A("%s\n", __FUNCTION__); */
215 pwlanhdr = (struct ieee80211_hdr *)pframe;
217 fctrl = &pwlanhdr->frame_control;
220 memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
221 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
222 memcpy(pwlanhdr->addr3, get_my_bssid23a(cur_network), ETH_ALEN);
224 SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
225 /* pmlmeext->mgnt_seq++; */
226 SetFrameSubType(pframe, WIFI_BEACON);
228 pframe += sizeof(struct ieee80211_hdr_3addr);
229 pktlen = sizeof (struct ieee80211_hdr_3addr);
231 /* timestamp will be inserted by hardware */
235 /* beacon interval: 2 bytes */
236 memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval23a_from_ie(cur_network->IEs)), 2);
241 /* capability info: 2 bytes */
242 memcpy(pframe, (unsigned char *)(rtw_get_capability23a_from_ie(cur_network->IEs)), 2);
247 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
248 /* DBG_8723A("ie len =%d\n", cur_network->IELength); */
249 pktlen += cur_network->IELength - sizeof(struct ndis_802_11_fixed_ies);
250 memcpy(pframe, cur_network->IEs+sizeof(struct ndis_802_11_fixed_ies), pktlen);
252 goto _ConstructBeacon;
255 /* below for ad-hoc mode */
258 pframe = rtw_set_ie23a(pframe, _SSID_IE_, cur_network->Ssid.ssid_len,
259 cur_network->Ssid.ssid, &pktlen);
261 /* supported rates... */
262 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
263 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ?
264 8 : rate_len), cur_network->SupportedRates, &pktlen);
266 /* DS parameter set */
267 pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pktlen);
269 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
271 /* IBSS Parameter Set... */
272 /* ATIMWindow = cur->Configuration.ATIMWindow; */
274 pframe = rtw_set_ie23a(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
279 /* EXTERNDED SUPPORTED RATE */
281 pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
283 /* todo:HT for adhoc */
287 if ((pktlen + TXDESC_SIZE) > 512) {
288 DBG_8723A("beacon frame too large\n");
294 /* DBG_8723A("%s bcn_sz =%d\n", __FUNCTION__, pktlen); */
298 static void ConstructPSPoll(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
300 struct ieee80211_hdr *pwlanhdr;
302 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
303 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
305 pwlanhdr = (struct ieee80211_hdr *)pframe;
308 fctrl = &pwlanhdr->frame_control;
311 SetFrameSubType(pframe, WIFI_PSPOLL);
314 SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
317 memcpy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
320 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
325 static void ConstructNullFunctionData(
326 struct rtw_adapter *padapter,
335 struct ieee80211_hdr *pwlanhdr;
338 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
339 struct wlan_network *cur_network = &pmlmepriv->cur_network;
340 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
341 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
343 pwlanhdr = (struct ieee80211_hdr *)pframe;
345 fctrl = &pwlanhdr->frame_control;
350 switch (cur_network->network.InfrastructureMode) {
351 case Ndis802_11Infrastructure:
353 memcpy(pwlanhdr->addr1,
354 get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
355 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv),
357 memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
359 case Ndis802_11APMode:
361 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
362 memcpy(pwlanhdr->addr2,
363 get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
364 memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv),
369 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
370 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
371 memcpy(pwlanhdr->addr3,
372 get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
376 SetSeqNum(pwlanhdr, 0);
379 struct ieee80211_qos_hdr *pwlanqoshdr;
381 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
383 pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe;
384 SetPriority(&pwlanqoshdr->qos_ctrl, AC);
385 SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
387 pktlen = sizeof(struct ieee80211_qos_hdr);
389 SetFrameSubType(pframe, WIFI_DATA_NULL);
391 pktlen = sizeof(struct ieee80211_hdr_3addr);
397 static void ConstructProbeRsp(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID)
399 struct ieee80211_hdr *pwlanhdr;
403 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
404 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
405 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
407 /* DBG_8723A("%s\n", __FUNCTION__); */
409 pwlanhdr = (struct ieee80211_hdr *)pframe;
411 mac = myid(&padapter->eeprompriv);
412 bssid = cur_network->MacAddress;
414 fctrl = &pwlanhdr->frame_control;
416 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
417 memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
418 memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
420 SetSeqNum(pwlanhdr, 0);
421 SetFrameSubType(fctrl, WIFI_PROBERSP);
423 pktlen = sizeof(struct ieee80211_hdr_3addr);
426 if (cur_network->IELength > MAX_IE_SZ)
429 memcpy(pframe, cur_network->IEs, cur_network->IELength);
430 pframe += cur_network->IELength;
431 pktlen += cur_network->IELength;
436 /* To check if reserved page content is destroyed by beacon beacuse beacon is too large. */
437 void CheckFwRsvdPageContent23a(struct rtw_adapter *Adapter)
442 /* Description: Fill the reserved packets that FW will use to RSVD page. */
443 /* Now we just send 4 types packet to rsvd page. */
444 /* (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */
446 /* bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */
447 /* so we need to set the packet length to total lengh. */
448 /* true: At the second time, we should send the first packet (default:beacon) */
449 /* to Hw again and set the lengh in descriptor to the real beacon lengh. */
450 /* 2009.10.15 by tynli. */
451 static void SetFwRsvdPagePkt(struct rtw_adapter *padapter, bool bDLFinished)
453 struct hal_data_8723a *pHalData;
454 struct xmit_frame *pmgntframe;
455 struct pkt_attrib *pattrib;
456 struct xmit_priv *pxmitpriv;
457 struct mlme_ext_priv *pmlmeext;
458 struct mlme_ext_info *pmlmeinfo;
459 u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength;
460 u32 NullDataLength, QosNullLength, BTQosNullLength;
461 u8 *ReservedPagePacket;
462 u8 PageNum, PageNeed, TxDescLen;
465 struct rsvdpage_loc RsvdPageLoc;
467 DBG_8723A("%s\n", __FUNCTION__);
469 ReservedPagePacket = kzalloc(1000, GFP_KERNEL);
470 if (ReservedPagePacket == NULL) {
471 DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
475 pHalData = GET_HAL_DATA(padapter);
476 pxmitpriv = &padapter->xmitpriv;
477 pmlmeext = &padapter->mlmeextpriv;
478 pmlmeinfo = &pmlmeext->mlmext_info;
480 TxDescLen = TXDESC_SIZE;
484 BufIndex = TXDESC_OFFSET;
485 ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
487 /* When we count the first page size, we need to reserve description size for the RSVD */
488 /* packet, it will be filled in front of the packet in TXPKTBUF. */
489 PageNeed = (u8)PageNum_128(TxDescLen + BeaconLength);
490 /* To reserved 2 pages for beacon buffer. 2010.06.24. */
494 pHalData->FwRsvdPageStartOffset = PageNum;
496 BufIndex += PageNeed*128;
499 RsvdPageLoc.LocPsPoll = PageNum;
500 ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);
501 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false);
503 PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);
506 BufIndex += PageNeed*128;
508 /* 3 (3) null data */
509 RsvdPageLoc.LocNullData = PageNum;
510 ConstructNullFunctionData(
512 &ReservedPagePacket[BufIndex],
514 get_my_bssid23a(&pmlmeinfo->network),
516 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
518 PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
521 BufIndex += PageNeed*128;
523 /* 3 (4) probe response */
524 RsvdPageLoc.LocProbeRsp = PageNum;
527 &ReservedPagePacket[BufIndex],
529 get_my_bssid23a(&pmlmeinfo->network),
531 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, false, false);
533 PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength);
536 BufIndex += PageNeed*128;
538 /* 3 (5) Qos null data */
539 RsvdPageLoc.LocQosNull = PageNum;
540 ConstructNullFunctionData(
542 &ReservedPagePacket[BufIndex],
544 get_my_bssid23a(&pmlmeinfo->network),
546 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false);
548 PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);
551 BufIndex += PageNeed*128;
553 /* 3 (6) BT Qos null data */
554 RsvdPageLoc.LocBTQosNull = PageNum;
555 ConstructNullFunctionData(
557 &ReservedPagePacket[BufIndex],
559 get_my_bssid23a(&pmlmeinfo->network),
561 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
563 TotalPacketLen = BufIndex + BTQosNullLength;
565 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
566 if (pmgntframe == NULL)
569 /* update attribute */
570 pattrib = &pmgntframe->attrib;
571 update_mgntframe_attrib23a(padapter, pattrib);
572 pattrib->qsel = 0x10;
573 pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
574 memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
576 rtw_hal_mgnt_xmit23a(padapter, pmgntframe);
578 DBG_8723A("%s: Set RSVD page location to Fw\n", __FUNCTION__);
579 FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
582 kfree(ReservedPagePacket);
585 void rtl8723a_set_FwJoinBssReport_cmd(struct rtw_adapter *padapter, u8 mstatus)
587 struct joinbssrpt_parm JoinBssRptParm;
588 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
589 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
590 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
592 DBG_8723A("%s mstatus(%x)\n", __FUNCTION__, mstatus);
595 bool bRecover = false;
598 /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
599 /* Suggested by filen. Added by tynli. */
600 rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
601 /* Do not set TSF again here or vWiFi beacon DMA INT will not work. */
602 /* correct_TSF23a(padapter, pmlmeext); */
603 /* Hw sequende enable by dedault. 2010.06.23. by tynli. */
604 /* rtw_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF)); */
605 /* rtw_write8(padapter, REG_HWSEQ_CTRL, 0xFF); */
607 /* set REG_CR bit 8 */
608 v8 = rtw_read8(padapter, REG_CR+1);
609 v8 |= BIT(0); /* ENSWBCN */
610 rtw_write8(padapter, REG_CR+1, v8);
612 /* Disable Hw protection for a time which revserd for Hw sending beacon. */
613 /* Fix download reserved page packet fail that access collision with the protection time. */
614 /* 2010.05.11. Added by tynli. */
615 /* SetBcnCtrlReg23a(padapter, 0, BIT(3)); */
616 /* SetBcnCtrlReg23a(padapter, BIT(4), 0); */
617 SetBcnCtrlReg23a(padapter, BIT(4), BIT(3));
619 /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
620 if (pHalData->RegFwHwTxQCtrl & BIT(6))
623 /* To tell Hw the packet is not a real beacon frame. */
624 /* U1bTmp = rtw_read8(padapter, REG_FWHW_TXQ_CTRL+2); */
625 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl & ~BIT(6));
626 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
627 SetFwRsvdPagePkt(padapter, 0);
629 /* 2010.05.11. Added by tynli. */
630 SetBcnCtrlReg23a(padapter, BIT(3), BIT(4));
632 /* To make sure that if there exists an adapter which would like to send beacon. */
633 /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
634 /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
635 /* the beacon cannot be sent by HW. */
636 /* 2010.06.23. Added by tynli. */
638 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl | BIT(6));
639 pHalData->RegFwHwTxQCtrl |= BIT(6);
642 /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
643 v8 = rtw_read8(padapter, REG_CR+1);
644 v8 &= ~BIT(0); /* ~ENSWBCN */
645 rtw_write8(padapter, REG_CR+1, v8);
648 JoinBssRptParm.OpMode = mstatus;
650 FillH2CCmd(padapter, JOINBSS_RPT_EID, sizeof(JoinBssRptParm), (u8 *)&JoinBssRptParm);
654 #ifdef CONFIG_8723AU_BT_COEXIST
655 static void SetFwRsvdPagePkt_BTCoex(struct rtw_adapter *padapter)
657 struct hal_data_8723a *pHalData;
658 struct xmit_frame *pmgntframe;
659 struct pkt_attrib *pattrib;
660 struct xmit_priv *pxmitpriv;
661 struct mlme_ext_priv *pmlmeext;
662 struct mlme_ext_info *pmlmeinfo;
663 u8 fakemac[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x00};
664 u32 NullDataLength, BTQosNullLength;
665 u8 *ReservedPagePacket;
666 u8 PageNum, PageNeed, TxDescLen;
669 struct rsvdpage_loc RsvdPageLoc;
671 DBG_8723A("+%s\n", __FUNCTION__);
673 ReservedPagePacket = kzalloc(1024, GFP_KERNEL);
674 if (ReservedPagePacket == NULL) {
675 DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
679 pHalData = GET_HAL_DATA(padapter);
680 pxmitpriv = &padapter->xmitpriv;
681 pmlmeext = &padapter->mlmeextpriv;
682 pmlmeinfo = &pmlmeext->mlmext_info;
684 TxDescLen = TXDESC_SIZE;
688 BufIndex = TXDESC_OFFSET;
689 /* skip Beacon Packet */
693 pHalData->FwRsvdPageStartOffset = PageNum;
695 BufIndex += PageNeed*128;
697 /* 3 (3) null data */
698 RsvdPageLoc.LocNullData = PageNum;
699 ConstructNullFunctionData(
701 &ReservedPagePacket[BufIndex],
705 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
707 PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
710 BufIndex += PageNeed*128;
712 /* 3 (6) BT Qos null data */
713 RsvdPageLoc.LocBTQosNull = PageNum;
714 ConstructNullFunctionData(
716 &ReservedPagePacket[BufIndex],
720 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
722 TotalPacketLen = BufIndex + BTQosNullLength;
724 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
725 if (pmgntframe == NULL)
728 /* update attribute */
729 pattrib = &pmgntframe->attrib;
730 update_mgntframe_attrib23a(padapter, pattrib);
731 pattrib->qsel = 0x10;
732 pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
733 memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
735 rtw_hal_mgnt_xmit23a(padapter, pmgntframe);
737 DBG_8723A("%s: Set RSVD page location to Fw\n", __FUNCTION__);
738 FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
741 kfree(ReservedPagePacket);
744 void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(struct rtw_adapter *padapter)
746 struct hal_data_8723a *pHalData;
749 DBG_8723A("+%s\n", __FUNCTION__);
751 pHalData = GET_HAL_DATA(padapter);
753 /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
754 if (pHalData->RegFwHwTxQCtrl & BIT(6))
757 /* To tell Hw the packet is not a real beacon frame. */
758 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
759 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
760 SetFwRsvdPagePkt_BTCoex(padapter);
762 /* To make sure that if there exists an adapter which would like to send beacon. */
763 /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
764 /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
765 /* the beacon cannot be sent by HW. */
766 /* 2010.06.23. Added by tynli. */
768 pHalData->RegFwHwTxQCtrl |= BIT(6);
769 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
774 #ifdef CONFIG_8723AU_P2P
775 void rtl8723a_set_p2p_ps_offload_cmd(struct rtw_adapter *padapter, u8 p2p_ps_state)
777 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
778 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
779 struct P2P_PS_Offload_t *p2p_ps_offload = &pHalData->p2p_ps_offload;
782 switch (p2p_ps_state) {
784 DBG_8723A("P2P_PS_DISABLE \n");
785 memset(p2p_ps_offload, 0, 1);
788 DBG_8723A("P2P_PS_ENABLE \n");
789 /* update CTWindow value. */
790 if (pwdinfo->ctwindow > 0) {
791 p2p_ps_offload->CTWindow_En = 1;
792 rtw_write8(padapter, REG_P2P_CTWIN, pwdinfo->ctwindow);
795 /* hw only support 2 set of NoA */
796 for (i = 0; i < pwdinfo->noa_num; i++) {
797 /* To control the register setting for which NOA */
798 rtw_write8(padapter, REG_NOA_DESC_SEL, (i << 4));
800 p2p_ps_offload->NoA0_En = 1;
802 p2p_ps_offload->NoA1_En = 1;
804 /* config P2P NoA Descriptor Register */
805 rtw_write32(padapter, REG_NOA_DESC_DURATION, pwdinfo->noa_duration[i]);
807 rtw_write32(padapter, REG_NOA_DESC_INTERVAL, pwdinfo->noa_interval[i]);
809 rtw_write32(padapter, REG_NOA_DESC_START, pwdinfo->noa_start_time[i]);
811 rtw_write8(padapter, REG_NOA_DESC_COUNT, pwdinfo->noa_count[i]);
814 if ((pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0)) {
815 /* rst p2p circuit */
816 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(4));
818 p2p_ps_offload->Offload_En = 1;
820 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
821 p2p_ps_offload->role = 1;
822 p2p_ps_offload->AllStaSleep = 0;
824 p2p_ps_offload->role = 0;
827 p2p_ps_offload->discovery = 0;
831 DBG_8723A("P2P_PS_SCAN \n");
832 p2p_ps_offload->discovery = 1;
834 case P2P_PS_SCAN_DONE:
835 DBG_8723A("P2P_PS_SCAN_DONE \n");
836 p2p_ps_offload->discovery = 0;
837 pwdinfo->p2p_ps_state = P2P_PS_ENABLE;
843 FillH2CCmd(padapter, P2P_PS_OFFLOAD_EID, 1, (u8 *)p2p_ps_offload);
845 #endif /* CONFIG_8723AU_P2P */