1 /******************************************************************************
\r
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
\r
5 * This program is free software; you can redistribute it and/or modify it
\r
6 * under the terms of version 2 of the GNU General Public License as
\r
7 * published by the Free Software Foundation.
\r
9 * This program is distributed in the hope that it will be useful, but WITHOUT
\r
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
\r
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
14 * You should have received a copy of the GNU General Public License along with
\r
15 * this program; if not, write to the Free Software Foundation, Inc.,
\r
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
\r
19 ******************************************************************************/
\r
20 #define _RTL8723A_CMD_C_
\r
22 #include <drv_conf.h>
\r
23 #include <osdep_service.h>
\r
24 #include <drv_types.h>
\r
25 #include <recv_osdep.h>
\r
26 #include <cmd_osdep.h>
\r
27 #include <mlme_osdep.h>
\r
28 #include <rtw_byteorder.h>
\r
29 #include <circ_buf.h>
\r
30 #include <rtw_ioctl_set.h>
\r
32 #include <rtl8723a_hal.h>
\r
35 #define RTL92C_MAX_H2C_BOX_NUMS 4
\r
36 #define RTL92C_MAX_CMD_LEN 5
\r
37 #define MESSAGE_BOX_SIZE 4
\r
38 #define EX_MESSAGE_BOX_SIZE 2
\r
41 static u8 _is_fw_read_cmd_down(_adapter* padapter, u8 msgbox_num)
\r
43 u8 read_down = _FALSE;
\r
44 int retry_cnts = 100;
\r
48 //DBG_8192C(" _is_fw_read_cmd_down ,reg_1cc(%x),msg_box(%d)...\n",rtw_read8(padapter,REG_HMETFR),msgbox_num);
\r
51 valid = rtw_read8(padapter,REG_HMETFR) & BIT(msgbox_num);
\r
56 }while( (!read_down) && (retry_cnts--));
\r
63 /*****************************************
\r
65 *| 31 - 8 |7 | 6 - 0 |
\r
66 *| h2c_msg |Ext_bit |CMD_ID |
\r
68 ******************************************/
\r
69 s32 FillH2CCmd(PADAPTER padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)
\r
71 u8 bcmd_down = _FALSE;
\r
72 s32 retry_cnts = 100;
\r
76 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
\r
83 padapter = GET_PRIMARY_ADAPTER(padapter);
\r
84 pHalData = GET_HAL_DATA(padapter);
\r
86 _enter_critical_mutex(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex), NULL);
\r
91 if (CmdLen > RTL92C_MAX_CMD_LEN) {
\r
94 if (padapter->bSurpriseRemoved == _TRUE)
\r
97 //pay attention to if race condition happened in H2C cmd setting.
\r
99 h2c_box_num = pHalData->LastHMEBoxNum;
\r
101 if(!_is_fw_read_cmd_down(padapter, h2c_box_num)){
\r
102 DBG_8192C(" fw read cmd failed...\n");
\r
108 _rtw_memcpy((u8*)(&h2c_cmd)+1, pCmdBuffer, CmdLen );
\r
111 _rtw_memcpy((u8*)(&h2c_cmd_ex), pCmdBuffer, EX_MESSAGE_BOX_SIZE);
\r
112 _rtw_memcpy((u8*)(&h2c_cmd)+1, pCmdBuffer+2,( CmdLen-EX_MESSAGE_BOX_SIZE));
\r
113 *(u8*)(&h2c_cmd) |= BIT(7);
\r
116 *(u8*)(&h2c_cmd) |= ElementID;
\r
118 if(h2c_cmd & BIT(7)){
\r
119 msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num *EX_MESSAGE_BOX_SIZE);
\r
120 h2c_cmd_ex = le16_to_cpu( h2c_cmd_ex );
\r
121 rtw_write16(padapter, msgbox_ex_addr, h2c_cmd_ex);
\r
123 msgbox_addr =REG_HMEBOX_0 + (h2c_box_num *MESSAGE_BOX_SIZE);
\r
124 h2c_cmd = le32_to_cpu( h2c_cmd );
\r
125 rtw_write32(padapter,msgbox_addr, h2c_cmd);
\r
129 //DBG_8192C("MSG_BOX:%d,CmdLen(%d), reg:0x%x =>h2c_cmd:0x%x, reg:0x%x =>h2c_cmd_ex:0x%x ..\n"
\r
130 // ,pHalData->LastHMEBoxNum ,CmdLen,msgbox_addr,h2c_cmd,msgbox_ex_addr,h2c_cmd_ex);
\r
132 pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL92C_MAX_H2C_BOX_NUMS;
\r
134 }while((!bcmd_down) && (retry_cnts--));
\r
140 _exit_critical_mutex(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex), NULL);
\r
147 u8 rtl8192c_h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf)
\r
149 u8 ElementID, CmdLen;
\r
151 struct cmd_msg_parm *pcmdmsg;
\r
154 return H2C_PARAMETERS_ERROR;
\r
156 pcmdmsg = (struct cmd_msg_parm*)pbuf;
\r
157 ElementID = pcmdmsg->eid;
\r
158 CmdLen = pcmdmsg->sz;
\r
159 pCmdBuffer = pcmdmsg->buf;
\r
161 FillH2CCmd(padapter, ElementID, CmdLen, pCmdBuffer);
\r
163 return H2C_SUCCESS;
\r
166 #if defined(CONFIG_AUTOSUSPEND) && defined(SUPPORT_HW_RFOFF_DETECTED)
\r
167 u8 rtl8192c_set_FwSelectSuspend_cmd(_adapter *padapter ,u8 bfwpoll, u16 period)
\r
170 struct H2C_SS_RFOFF_PARAM param;
\r
171 DBG_8192C("==>%s bfwpoll(%x)\n",__FUNCTION__,bfwpoll);
\r
172 param.gpio_period = period;//Polling GPIO_11 period time
\r
173 param.ROFOn = (_TRUE == bfwpoll)?1:0;
\r
174 FillH2CCmd(padapter, SELECTIVE_SUSPEND_ROF_CMD, sizeof(param), (u8*)(¶m));
\r
177 #endif //CONFIG_AUTOSUSPEND && SUPPORT_HW_RFOFF_DETECTED
\r
179 u8 rtl8192c_set_rssi_cmd(_adapter*padapter, u8 *param)
\r
185 *((u32*) param ) = cpu_to_le32( *((u32*) param ) );
\r
187 FillH2CCmd(padapter, RSSI_SETTING_EID, 3, param);
\r
194 u8 rtl8192c_set_raid_cmd(_adapter*padapter, u32 mask, u8 arg)
\r
201 _rtw_memset(buf, 0, 5);
\r
202 mask = cpu_to_le32( mask );
\r
203 _rtw_memcpy(buf, &mask, 4);
\r
206 FillH2CCmd(padapter, MACID_CONFIG_EID, 5, buf);
\r
214 //bitmap[0:27] = tx_rate_bitmap
\r
215 //bitmap[28:31]= Rate Adaptive id
\r
217 //arg[5] = Short GI
\r
218 void rtl8192c_Add_RateATid(PADAPTER pAdapter, u32 bitmap, u8 arg, u8 rssi_level)
\r
220 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter);
\r
222 u8 macid = arg&0x1f;
\r
224 #ifdef CONFIG_ODM_REFRESH_RAMASK
\r
225 u8 raid = (bitmap>>28) & 0x0f;
\r
226 bitmap &=0x0fffffff;
\r
227 if(rssi_level != DM_RATR_STA_INIT)
\r
228 bitmap = ODM_Get_Rate_Bitmap(&pHalData->odmpriv, macid, bitmap, rssi_level);
\r
230 bitmap |= ((raid<<28)&0xf0000000);
\r
231 #endif //CONFIG_ODM_REFRESH_RAMASK
\r
234 if(pHalData->fw_ractrl == _TRUE)
\r
236 rtl8192c_set_raid_cmd(pAdapter, bitmap, arg);
\r
240 u8 init_rate, shortGIrate=_FALSE;
\r
242 init_rate = get_highest_rate_idx(bitmap&0x0fffffff)&0x3f;
\r
245 shortGIrate = (arg&BIT(5)) ? _TRUE:_FALSE;
\r
247 if (shortGIrate==_TRUE)
\r
248 init_rate |= BIT(6);
\r
250 rtw_write8(pAdapter, (REG_INIDATA_RATE_SEL+macid), (u8)init_rate);
\r
255 void rtl8723a_set_FwPwrMode_cmd(PADAPTER padapter, u8 Mode)
\r
257 SETPWRMODE_PARM H2CSetPwrMode;
\r
258 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
\r
262 H2CSetPwrMode.Mode = Mode;
\r
263 H2CSetPwrMode.SmartPS = pwrpriv->smart_ps;
\r
264 H2CSetPwrMode.AwakeInterval = 1;
\r
265 H2CSetPwrMode.bAllQueueUAPSD = padapter->registrypriv.uapsd_enable;
\r
269 /* Leave LPS, set BcnAntMode to 0 */
\r
270 H2CSetPwrMode.BcnAntMode = 0;
\r
274 H2CSetPwrMode.BcnAntMode = pwrpriv->bcn_ant_mode;
\r
277 DBG_871X("%s: Mode=%d SmartPS=%d UAPSD=%d BcnMode=0x%02x\n", __FUNCTION__,
\r
278 H2CSetPwrMode.Mode, H2CSetPwrMode.SmartPS, H2CSetPwrMode.bAllQueueUAPSD, H2CSetPwrMode.BcnAntMode);
\r
280 FillH2CCmd(padapter, SET_PWRMODE_EID, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
\r
286 void rtl8723a_set_FwMediaStatus_cmd(PADAPTER padapter, u16 mstatus_rpt )
\r
289 u16 mst_rpt = cpu_to_le16 (mstatus_rpt);
\r
290 u32 reg_macid_no_link = REG_MACID_NO_LINK;
\r
291 opmode = (u8) mst_rpt;
\r
292 macid = (u8)(mst_rpt >> 8) ;
\r
293 DBG_871X("### %s: MStatus=%x MACID=%d \n", __FUNCTION__,opmode,macid);
\r
295 //Delete select macid (MACID 0~63) from queue list.
\r
296 if(opmode == 1)// 1:connect
\r
298 rtw_write32(padapter,reg_macid_no_link, (rtw_read32(padapter,reg_macid_no_link) & (~BIT(macid))));
\r
300 else//0: disconnect
\r
302 rtw_write32(padapter,reg_macid_no_link, (rtw_read32(padapter,reg_macid_no_link)|BIT(macid)));
\r
307 void ConstructBeacon(_adapter *padapter, u8 *pframe, u32 *pLength)
\r
309 struct rtw_ieee80211_hdr *pwlanhdr;
\r
311 u32 rate_len, pktlen;
\r
312 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
313 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
314 WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
\r
315 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
\r
318 //DBG_871X("%s\n", __FUNCTION__);
\r
320 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
\r
322 fctrl = &(pwlanhdr->frame_ctl);
\r
325 _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
\r
326 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
327 _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
\r
329 SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
\r
330 //pmlmeext->mgnt_seq++;
\r
331 SetFrameSubType(pframe, WIFI_BEACON);
\r
333 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
\r
334 pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
\r
336 //timestamp will be inserted by hardware
\r
340 // beacon interval: 2 bytes
\r
341 _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
\r
346 // capability info: 2 bytes
\r
347 _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
\r
352 if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
\r
354 //DBG_871X("ie len=%d\n", cur_network->IELength);
\r
355 pktlen += cur_network->IELength - sizeof(NDIS_802_11_FIXED_IEs);
\r
356 _rtw_memcpy(pframe, cur_network->IEs+sizeof(NDIS_802_11_FIXED_IEs), pktlen);
\r
358 goto _ConstructBeacon;
\r
361 //below for ad-hoc mode
\r
364 pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);
\r
366 // supported rates...
\r
367 rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
\r
368 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pktlen);
\r
370 // DS parameter set
\r
371 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
\r
373 if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
\r
376 // IBSS Parameter Set...
\r
377 //ATIMWindow = cur->Configuration.ATIMWindow;
\r
379 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
\r
386 // EXTERNDED SUPPORTED RATE
\r
389 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
\r
393 //todo:HT for adhoc
\r
397 if ((pktlen + TXDESC_SIZE) > 512)
\r
399 DBG_871X("beacon frame too large\n");
\r
405 //DBG_871X("%s bcn_sz=%d\n", __FUNCTION__, pktlen);
\r
409 void ConstructPSPoll(_adapter *padapter, u8 *pframe, u32 *pLength)
\r
411 struct rtw_ieee80211_hdr *pwlanhdr;
\r
414 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
415 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
417 //DBG_871X("%s\n", __FUNCTION__);
\r
419 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
\r
422 fctrl = &(pwlanhdr->frame_ctl);
\r
425 SetFrameSubType(pframe, WIFI_PSPOLL);
\r
428 SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
\r
431 _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
\r
434 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
439 void ConstructNullFunctionData(
\r
447 u8 bForcePowerSave)
\r
449 struct rtw_ieee80211_hdr *pwlanhdr;
\r
452 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
453 struct wlan_network *cur_network = &pmlmepriv->cur_network;
\r
454 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
455 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
458 //DBG_871X("%s:%d\n", __FUNCTION__, bForcePowerSave);
\r
460 pwlanhdr = (struct rtw_ieee80211_hdr*)pframe;
\r
462 fctrl = &pwlanhdr->frame_ctl;
\r
464 if (bForcePowerSave)
\r
469 switch(cur_network->network.InfrastructureMode)
\r
471 case Ndis802_11Infrastructure:
\r
473 _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
\r
474 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
475 _rtw_memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
\r
477 case Ndis802_11APMode:
\r
479 _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
\r
480 _rtw_memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
\r
481 _rtw_memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
483 case Ndis802_11IBSS:
\r
485 _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
\r
486 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
487 _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
\r
491 SetSeqNum(pwlanhdr, 0);
\r
493 if (bQoS == _TRUE) {
\r
494 struct rtw_ieee80211_hdr_3addr_qos *pwlanqoshdr;
\r
496 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
\r
498 pwlanqoshdr = (struct rtw_ieee80211_hdr_3addr_qos*)pframe;
\r
499 SetPriority(&pwlanqoshdr->qc, AC);
\r
500 SetEOSP(&pwlanqoshdr->qc, bEosp);
\r
502 pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
\r
504 SetFrameSubType(pframe, WIFI_DATA_NULL);
\r
506 pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
\r
512 void ConstructProbeRsp(_adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, BOOLEAN bHideSSID)
\r
514 struct rtw_ieee80211_hdr *pwlanhdr;
\r
518 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
519 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
520 WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
\r
523 //DBG_871X("%s\n", __FUNCTION__);
\r
525 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
\r
527 mac = myid(&(padapter->eeprompriv));
\r
528 bssid = cur_network->MacAddress;
\r
530 fctrl = &(pwlanhdr->frame_ctl);
\r
532 _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
\r
533 _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
\r
534 _rtw_memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
\r
536 SetSeqNum(pwlanhdr, 0);
\r
537 SetFrameSubType(fctrl, WIFI_PROBERSP);
\r
539 pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
\r
542 if(cur_network->IELength>MAX_IE_SZ)
\r
545 _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
\r
546 pframe += cur_network->IELength;
\r
547 pktlen += cur_network->IELength;
\r
552 // To check if reserved page content is destroyed by beacon beacuse beacon is too large.
\r
553 // 2010.06.23. Added by tynli.
\r
555 CheckFwRsvdPageContent(
\r
556 IN PADAPTER Adapter
\r
559 HAL_DATA_TYPE* pHalData = GET_HAL_DATA(Adapter);
\r
562 if(pHalData->FwRsvdPageStartOffset != 0)
\r
564 /*MaxBcnPageNum = PageNum_128(pMgntInfo->MaxBeaconSize);
\r
565 RT_ASSERT((MaxBcnPageNum <= pHalData->FwRsvdPageStartOffset),
\r
566 ("CheckFwRsvdPageContent(): The reserved page content has been"\
\r
567 "destroyed by beacon!!! MaxBcnPageNum(%d) FwRsvdPageStartOffset(%d)\n!",
\r
568 MaxBcnPageNum, pHalData->FwRsvdPageStartOffset));*/
\r
573 // Description: Fill the reserved packets that FW will use to RSVD page.
\r
574 // Now we just send 4 types packet to rsvd page.
\r
575 // (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp.
\r
577 // bDLFinished - FALSE: At the first time we will send all the packets as a large packet to Hw,
\r
578 // so we need to set the packet length to total lengh.
\r
579 // TRUE: At the second time, we should send the first packet (default:beacon)
\r
580 // to Hw again and set the lengh in descriptor to the real beacon lengh.
\r
581 // 2009.10.15 by tynli.
\r
582 static void SetFwRsvdPagePkt(PADAPTER padapter, BOOLEAN bDLFinished)
\r
584 PHAL_DATA_TYPE pHalData;
\r
585 struct xmit_frame *pmgntframe;
\r
586 struct pkt_attrib *pattrib;
\r
587 struct xmit_priv *pxmitpriv;
\r
588 struct mlme_ext_priv *pmlmeext;
\r
589 struct mlme_ext_info *pmlmeinfo;
\r
590 u32 BeaconLength, ProbeRspLength, PSPollLength;
\r
591 u32 NullDataLength, QosNullLength, BTQosNullLength;
\r
592 u8 *ReservedPagePacket;
\r
593 u8 PageNum, PageNeed, TxDescLen;
\r
595 u32 TotalPacketLen;
\r
596 RSVDPAGE_LOC RsvdPageLoc;
\r
599 DBG_871X("%s\n", __FUNCTION__);
\r
601 ReservedPagePacket = (u8*)rtw_zmalloc(1000);
\r
602 if (ReservedPagePacket == NULL) {
\r
603 DBG_871X("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
\r
607 pHalData = GET_HAL_DATA(padapter);
\r
608 pxmitpriv = &padapter->xmitpriv;
\r
609 pmlmeext = &padapter->mlmeextpriv;
\r
610 pmlmeinfo = &pmlmeext->mlmext_info;
\r
612 TxDescLen = TXDESC_SIZE;
\r
616 BufIndex = TXDESC_OFFSET;
\r
617 ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
\r
619 // When we count the first page size, we need to reserve description size for the RSVD
\r
620 // packet, it will be filled in front of the packet in TXPKTBUF.
\r
621 PageNeed = (u8)PageNum_128(TxDescLen + BeaconLength);
\r
622 // To reserved 2 pages for beacon buffer. 2010.06.24.
\r
625 PageNum += PageNeed;
\r
626 pHalData->FwRsvdPageStartOffset = PageNum;
\r
628 BufIndex += PageNeed*128;
\r
631 RsvdPageLoc.LocPsPoll = PageNum;
\r
632 ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);
\r
633 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, _TRUE, _FALSE);
\r
635 PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);
\r
636 PageNum += PageNeed;
\r
638 BufIndex += PageNeed*128;
\r
641 RsvdPageLoc.LocNullData = PageNum;
\r
642 ConstructNullFunctionData(
\r
644 &ReservedPagePacket[BufIndex],
\r
646 get_my_bssid(&pmlmeinfo->network),
\r
647 _FALSE, 0, 0, _FALSE);
\r
648 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, _FALSE, _FALSE);
\r
650 PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
\r
651 PageNum += PageNeed;
\r
653 BufIndex += PageNeed*128;
\r
655 //3 (4) probe response
\r
656 RsvdPageLoc.LocProbeRsp = PageNum;
\r
659 &ReservedPagePacket[BufIndex],
\r
661 get_my_bssid(&pmlmeinfo->network),
\r
663 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, _FALSE, _FALSE);
\r
665 PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength);
\r
666 PageNum += PageNeed;
\r
668 BufIndex += PageNeed*128;
\r
670 //3 (5) Qos null data
\r
671 RsvdPageLoc.LocQosNull = PageNum;
\r
672 ConstructNullFunctionData(
\r
674 &ReservedPagePacket[BufIndex],
\r
676 get_my_bssid(&pmlmeinfo->network),
\r
677 _TRUE, 0, 0, _FALSE);
\r
678 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, _FALSE, _FALSE);
\r
680 PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);
\r
681 PageNum += PageNeed;
\r
683 BufIndex += PageNeed*128;
\r
685 //3 (6) BT Qos null data
\r
686 RsvdPageLoc.LocBTQosNull = PageNum;
\r
687 ConstructNullFunctionData(
\r
689 &ReservedPagePacket[BufIndex],
\r
691 get_my_bssid(&pmlmeinfo->network),
\r
692 _TRUE, 0, 0, _FALSE);
\r
693 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, _FALSE, _TRUE);
\r
695 TotalPacketLen = BufIndex + BTQosNullLength;
\r
697 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
\r
698 if (pmgntframe == NULL)
\r
701 // update attribute
\r
702 pattrib = &pmgntframe->attrib;
\r
703 update_mgntframe_attrib(padapter, pattrib);
\r
704 pattrib->qsel = 0x10;
\r
705 pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
\r
706 _rtw_memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
\r
708 rtw_hal_mgnt_xmit(padapter, pmgntframe);
\r
710 DBG_871X("%s: Set RSVD page location to Fw\n", __FUNCTION__);
\r
711 FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8*)&RsvdPageLoc);
\r
714 rtw_mfree(ReservedPagePacket, 1000);
\r
717 void rtl8723a_set_FwJoinBssReport_cmd(PADAPTER padapter, u8 mstatus)
\r
719 JOINBSSRPT_PARM JoinBssRptParm;
\r
720 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
\r
721 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
722 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
726 DBG_871X("%s mstatus(%x)\n", __FUNCTION__,mstatus);
\r
730 BOOLEAN bRecover = _FALSE;
\r
733 // We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C.
\r
734 // Suggested by filen. Added by tynli.
\r
735 rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
\r
736 // Do not set TSF again here or vWiFi beacon DMA INT will not work.
\r
737 //correct_TSF(padapter, pmlmeext);
\r
738 // Hw sequende enable by dedault. 2010.06.23. by tynli.
\r
739 //rtw_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF));
\r
740 //rtw_write8(padapter, REG_HWSEQ_CTRL, 0xFF);
\r
742 // set REG_CR bit 8
\r
743 v8 = rtw_read8(padapter, REG_CR+1);
\r
744 v8 |= BIT(0); // ENSWBCN
\r
745 rtw_write8(padapter, REG_CR+1, v8);
\r
747 // Disable Hw protection for a time which revserd for Hw sending beacon.
\r
748 // Fix download reserved page packet fail that access collision with the protection time.
\r
749 // 2010.05.11. Added by tynli.
\r
750 // SetBcnCtrlReg(padapter, 0, BIT(3));
\r
751 // SetBcnCtrlReg(padapter, BIT(4), 0);
\r
752 SetBcnCtrlReg(padapter, BIT(4), BIT(3));
\r
754 // Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.
\r
755 if (pHalData->RegFwHwTxQCtrl & BIT(6))
\r
758 // To tell Hw the packet is not a real beacon frame.
\r
759 //U1bTmp = rtw_read8(padapter, REG_FWHW_TXQ_CTRL+2);
\r
760 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl & ~BIT(6));
\r
761 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
\r
762 SetFwRsvdPagePkt(padapter, 0);
\r
764 // 2010.05.11. Added by tynli.
\r
765 // SetBcnCtrlReg(padapter, BIT3, 0);
\r
766 // SetBcnCtrlReg(padapter, 0, BIT4);
\r
767 SetBcnCtrlReg(padapter, BIT(3), BIT(4));
\r
769 // To make sure that if there exists an adapter which would like to send beacon.
\r
770 // If exists, the origianl value of 0x422[6] will be 1, we should check this to
\r
771 // prevent from setting 0x422[6] to 0 after download reserved page, or it will cause
\r
772 // the beacon cannot be sent by HW.
\r
773 // 2010.06.23. Added by tynli.
\r
776 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl | BIT(6));
\r
777 pHalData->RegFwHwTxQCtrl |= BIT(6);
\r
780 // Clear CR[8] or beacon packet will not be send to TxBuf anymore.
\r
781 v8 = rtw_read8(padapter, REG_CR+1);
\r
782 v8 &= ~BIT(0); // ~ENSWBCN
\r
783 rtw_write8(padapter, REG_CR+1, v8);
\r
786 JoinBssRptParm.OpMode = mstatus;
\r
788 FillH2CCmd(padapter, JOINBSS_RPT_EID, sizeof(JoinBssRptParm), (u8 *)&JoinBssRptParm);
\r
793 #ifdef CONFIG_BT_COEXIST
\r
794 static void SetFwRsvdPagePkt_BTCoex(PADAPTER padapter)
\r
796 PHAL_DATA_TYPE pHalData;
\r
797 struct xmit_frame *pmgntframe;
\r
798 struct pkt_attrib *pattrib;
\r
799 struct xmit_priv *pxmitpriv;
\r
800 struct mlme_ext_priv *pmlmeext;
\r
801 struct mlme_ext_info *pmlmeinfo;
\r
802 u8 fakemac[6]={0x00,0xe0,0x4c,0x00,0x00,0x00};
\r
803 u32 BeaconLength, ProbeRspLength, PSPollLength;
\r
804 u32 NullDataLength, QosNullLength, BTQosNullLength;
\r
805 u8 *ReservedPagePacket;
\r
806 u8 PageNum, PageNeed, TxDescLen;
\r
808 u32 TotalPacketLen;
\r
809 RSVDPAGE_LOC RsvdPageLoc;
\r
812 DBG_871X("+%s\n", __FUNCTION__);
\r
814 ReservedPagePacket = (u8*)rtw_zmalloc(1024);
\r
815 if (ReservedPagePacket == NULL) {
\r
816 DBG_871X("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
\r
820 pHalData = GET_HAL_DATA(padapter);
\r
821 pxmitpriv = &padapter->xmitpriv;
\r
822 pmlmeext = &padapter->mlmeextpriv;
\r
823 pmlmeinfo = &pmlmeext->mlmext_info;
\r
825 TxDescLen = TXDESC_SIZE;
\r
829 BufIndex = TXDESC_OFFSET;
\r
831 ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
\r
833 // When we count the first page size, we need to reserve description size for the RSVD
\r
834 // packet, it will be filled in front of the packet in TXPKTBUF.
\r
835 PageNeed = (u8)PageNum_128(TxDescLen + BeaconLength);
\r
836 // To reserved 2 pages for beacon buffer. 2010.06.24.
\r
840 // skip Beacon Packet
\r
844 PageNum += PageNeed;
\r
845 pHalData->FwRsvdPageStartOffset = PageNum;
\r
847 BufIndex += PageNeed*128;
\r
851 RsvdPageLoc.LocPsPoll = PageNum;
\r
852 ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);
\r
853 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, _TRUE, _FALSE);
\r
855 PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);
\r
856 PageNum += PageNeed;
\r
858 BufIndex += PageNeed*128;
\r
862 RsvdPageLoc.LocNullData = PageNum;
\r
863 ConstructNullFunctionData(
\r
865 &ReservedPagePacket[BufIndex],
\r
868 _FALSE, 0, 0, _FALSE);
\r
869 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, _FALSE, _FALSE);
\r
871 PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
\r
872 PageNum += PageNeed;
\r
874 BufIndex += PageNeed*128;
\r
876 //3 (4) probe response
\r
878 RsvdPageLoc.LocProbeRsp = PageNum;
\r
881 &ReservedPagePacket[BufIndex],
\r
883 get_my_bssid(&pmlmeinfo->network),
\r
885 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, _FALSE, _FALSE);
\r
887 PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength);
\r
888 PageNum += PageNeed;
\r
890 BufIndex += PageNeed*128;
\r
893 //3 (5) Qos null data
\r
895 RsvdPageLoc.LocQosNull = PageNum;
\r
896 ConstructNullFunctionData(
\r
898 &ReservedPagePacket[BufIndex],
\r
900 get_my_bssid(&pmlmeinfo->network),
\r
901 _TRUE, 0, 0, _FALSE);
\r
902 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, _FALSE, _FALSE);
\r
904 PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);
\r
905 PageNum += PageNeed;
\r
907 BufIndex += PageNeed*128;
\r
910 //3 (6) BT Qos null data
\r
911 RsvdPageLoc.LocBTQosNull = PageNum;
\r
912 ConstructNullFunctionData(
\r
914 &ReservedPagePacket[BufIndex],
\r
917 _TRUE, 0, 0, _FALSE);
\r
918 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, _FALSE, _TRUE);
\r
920 TotalPacketLen = BufIndex + BTQosNullLength;
\r
922 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
\r
923 if (pmgntframe == NULL)
\r
926 // update attribute
\r
927 pattrib = &pmgntframe->attrib;
\r
928 update_mgntframe_attrib(padapter, pattrib);
\r
929 pattrib->qsel = 0x10;
\r
930 pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
\r
931 _rtw_memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
\r
933 rtw_hal_mgnt_xmit(padapter, pmgntframe);
\r
935 DBG_8192C("%s: Set RSVD page location to Fw\n", __FUNCTION__);
\r
936 FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8*)&RsvdPageLoc);
\r
939 rtw_mfree(ReservedPagePacket, 1024);
\r
942 void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(PADAPTER padapter)
\r
944 PHAL_DATA_TYPE pHalData;
\r
945 u8 bRecover = _FALSE;
\r
948 DBG_8192C("+%s\n", __FUNCTION__);
\r
950 pHalData = GET_HAL_DATA(padapter);
\r
952 // Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.
\r
953 if (pHalData->RegFwHwTxQCtrl & BIT(6))
\r
956 // To tell Hw the packet is not a real beacon frame.
\r
957 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
\r
958 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
\r
959 SetFwRsvdPagePkt_BTCoex(padapter);
\r
961 // To make sure that if there exists an adapter which would like to send beacon.
\r
962 // If exists, the origianl value of 0x422[6] will be 1, we should check this to
\r
963 // prevent from setting 0x422[6] to 0 after download reserved page, or it will cause
\r
964 // the beacon cannot be sent by HW.
\r
965 // 2010.06.23. Added by tynli.
\r
968 pHalData->RegFwHwTxQCtrl |= BIT(6);
\r
969 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
\r
974 #ifdef CONFIG_P2P_PS
\r
975 void rtl8192c_set_p2p_ps_offload_cmd(_adapter* padapter, u8 p2p_ps_state)
\r
977 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
\r
978 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
\r
979 struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
\r
980 struct P2P_PS_Offload_t *p2p_ps_offload = &pHalData->p2p_ps_offload;
\r
985 switch(p2p_ps_state)
\r
987 case P2P_PS_DISABLE:
\r
988 DBG_8192C("P2P_PS_DISABLE \n");
\r
989 _rtw_memset(p2p_ps_offload, 0 ,1);
\r
991 case P2P_PS_ENABLE:
\r
992 DBG_8192C("P2P_PS_ENABLE \n");
\r
993 // update CTWindow value.
\r
994 if( pwdinfo->ctwindow > 0 )
\r
996 p2p_ps_offload->CTWindow_En = 1;
\r
997 rtw_write8(padapter, REG_P2P_CTWIN, pwdinfo->ctwindow);
\r
1000 // hw only support 2 set of NoA
\r
1001 for( i=0 ; i<pwdinfo->noa_num ; i++)
\r
1003 // To control the register setting for which NOA
\r
1004 rtw_write8(padapter, REG_NOA_DESC_SEL, (i << 4));
\r
1006 p2p_ps_offload->NoA0_En = 1;
\r
1008 p2p_ps_offload->NoA1_En = 1;
\r
1010 // config P2P NoA Descriptor Register
\r
1011 //DBG_8192C("%s(): noa_duration = %x\n",__FUNCTION__,pwdinfo->noa_duration[i]);
\r
1012 rtw_write32(padapter, REG_NOA_DESC_DURATION, pwdinfo->noa_duration[i]);
\r
1014 //DBG_8192C("%s(): noa_interval = %x\n",__FUNCTION__,pwdinfo->noa_interval[i]);
\r
1015 rtw_write32(padapter, REG_NOA_DESC_INTERVAL, pwdinfo->noa_interval[i]);
\r
1017 //DBG_8192C("%s(): start_time = %x\n",__FUNCTION__,pwdinfo->noa_start_time[i]);
\r
1018 rtw_write32(padapter, REG_NOA_DESC_START, pwdinfo->noa_start_time[i]);
\r
1020 //DBG_8192C("%s(): noa_count = %x\n",__FUNCTION__,pwdinfo->noa_count[i]);
\r
1021 rtw_write8(padapter, REG_NOA_DESC_COUNT, pwdinfo->noa_count[i]);
\r
1024 if( (pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0) )
\r
1026 // rst p2p circuit
\r
1027 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(4));
\r
1029 p2p_ps_offload->Offload_En = 1;
\r
1031 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
\r
1033 p2p_ps_offload->role= 1;
\r
1034 p2p_ps_offload->AllStaSleep = 0;
\r
1038 p2p_ps_offload->role= 0;
\r
1041 p2p_ps_offload->discovery = 0;
\r
1045 DBG_8192C("P2P_PS_SCAN \n");
\r
1046 p2p_ps_offload->discovery = 1;
\r
1048 case P2P_PS_SCAN_DONE:
\r
1049 DBG_8192C("P2P_PS_SCAN_DONE \n");
\r
1050 p2p_ps_offload->discovery = 0;
\r
1051 pwdinfo->p2p_ps_state = P2P_PS_ENABLE;
\r
1057 FillH2CCmd(padapter, P2P_PS_OFFLOAD_EID, 1, (u8 *)p2p_ps_offload);
\r
1062 #endif //CONFIG_P2P_PS
\r
1065 #include <rtw_iol.h>
\r
1066 #ifdef CONFIG_USB_HCI
\r
1067 #include <usb_ops.h>
\r
1069 int rtl8192c_IOL_exec_cmds_sync(ADAPTER *adapter, struct xmit_frame *xmit_frame, u32 max_wating_ms, u32 bndy_cnt)
\r
1071 IO_OFFLOAD_LOC IoOffloadLoc;
\r
1072 u32 start_time = rtw_get_current_time();
\r
1073 u32 passing_time_ms;
\r
1077 if (rtw_IOL_append_END_cmd(xmit_frame) != _SUCCESS)
\r
1079 #ifdef CONFIG_USB_HCI
\r
1081 struct pkt_attrib *pattrib = &xmit_frame->attrib;
\r
1082 if(rtw_usb_bulk_size_boundary(adapter,TXDESC_SIZE+pattrib->last_txcmdsz))
\r
1084 if (rtw_IOL_append_END_cmd(xmit_frame) != _SUCCESS)
\r
1088 #endif //CONFIG_USB_HCI
\r
1091 dump_mgntframe_and_wait(adapter, xmit_frame, max_wating_ms);
\r
1093 IoOffloadLoc.LocCmd = 0;
\r
1094 if(_SUCCESS != FillH2CCmd(adapter, H2C_92C_IO_OFFLOAD, sizeof(IO_OFFLOAD_LOC), (u8 *)&IoOffloadLoc))
\r
1097 //polling if the IO offloading is done
\r
1098 while( (passing_time_ms=rtw_get_passing_time_ms(start_time)) <= max_wating_ms) {
\r
1100 if(0xff == rtw_read8(adapter, REG_C2HEVT_CLEAR))
\r
1103 if(0x00 != (polling_ret=rtw_read8(adapter, 0x1c3)))
\r
1109 DBG_871X("IOL %s, polling_ret:0x%02x, 0x1c0=0x%08x, 0x1c4=0x%08x, 0x1cc=0x%08x, 0x1e8=0x%08x, 0x130=0x%08x, 0x134=0x%08x\n"
\r
1110 , polling_ret==0xff?"success":"error"
\r
1112 , rtw_read32(adapter, 0x1c0)
\r
1113 , rtw_read32(adapter, 0x1c4)
\r
1114 , rtw_read32(adapter, 0x1cc)
\r
1115 , rtw_read32(adapter, 0x1e8)
\r
1116 , rtw_read32(adapter, 0x130)
\r
1117 , rtw_read32(adapter, 0x134)
\r
1119 rtw_write32(adapter, 0x1c0, 0x0);
\r
1122 if(polling_ret == 0xff)
\r
1125 DBG_871X("IOL %s, polling_ret:0x%02x\n"
\r
1126 //", 0x1c0=0x%08x, 0x1c4=0x%08x, 0x1cc=0x%08x, 0x1e8=0x%08x, 0x130=0x%08x, 0x134=0x%08x\n"
\r
1127 , polling_ret==0xff?"success":"error"
\r
1129 //, rtw_read32(adapter, 0x1c0)
\r
1130 //, rtw_read32(adapter, 0x1c4)
\r
1131 //, rtw_read32(adapter, 0x1cc)
\r
1132 //, rtw_read32(adapter, 0x1e8)
\r
1133 //, rtw_read32(adapter, 0x130)
\r
1134 //, rtw_read32(adapter, 0x134)
\r
1137 rtw_write16(adapter, 0x1c4, 0x0000);
\r
1138 rtw_msleep_os(10);
\r
1139 DBG_871X("after reset, 0x1c4=0x%08x\n", rtw_read32(adapter, 0x1c4));
\r
1148 c2h_evt = rtw_read32(adapter, REG_C2HEVT_MSG_NORMAL);
\r
1149 DBG_871X("%s io-offloading complete, in %ums: 0x%08x\n", __FUNCTION__, passing_time_ms, c2h_evt);
\r
1150 rtw_write8(adapter, REG_C2HEVT_CLEAR, 0x0);
\r
1152 //DBG_871X("%s IOF complete in %ums\n", __FUNCTION__, passing_time_ms);
\r
1153 rtw_write8(adapter, 0x1c3, 0x0);
\r
1161 #endif //CONFIG_IOL
\r
1163 #ifdef CONFIG_TSF_RESET_OFFLOAD
\r
1165 ask FW to Reset sync register at Beacon early interrupt
\r
1167 u8 rtl8723c_reset_tsf(_adapter *padapter, u8 reset_port )
\r
1173 if (IFACE_PORT0==reset_port) {
\r
1174 buf[0] = 0x1; buf[1] = 0;
\r
1177 buf[0] = 0x0; buf[1] = 0x1;
\r
1179 FillH2CCmd(padapter, H2C_RESET_TSF, 2, buf);
\r
1184 #endif // CONFIG_TSF_RESET_OFFLOAD
\r