net: wireless: rockchip_wlan: add rtl8188eu support
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8188eu / hal / rtl8188e / rtl8188e_cmd.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *
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.
8  *
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
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _RTL8188E_CMD_C_
21
22 #include <drv_types.h>
23 #include <rtl8188e_hal.h>
24 #include "hal_com_h2c.h"
25
26 #define CONFIG_H2C_EF
27
28 #define RTL88E_MAX_H2C_BOX_NUMS 4
29 #define RTL88E_MAX_CMD_LEN      7
30 #define RTL88E_MESSAGE_BOX_SIZE         4
31 #define RTL88E_EX_MESSAGE_BOX_SIZE      4
32
33 static u8 _is_fw_read_cmd_down(_adapter* padapter, u8 msgbox_num)
34 {
35         u8      read_down = _FALSE;
36         int     retry_cnts = 100;
37
38         u8 valid;
39
40         //DBG_8192C(" _is_fw_read_cmd_down ,reg_1cc(%x),msg_box(%d)...\n",rtw_read8(padapter,REG_HMETFR),msgbox_num);
41
42         do{
43                 valid = rtw_read8(padapter,REG_HMETFR) & BIT(msgbox_num);
44                 if(0 == valid ){
45                         read_down = _TRUE;
46                 }
47                 else
48                         rtw_msleep_os(1);
49         }while( (!read_down) && (retry_cnts--));
50
51         return read_down;
52
53 }
54
55
56 /*****************************************
57 * H2C Msg format :
58 * 0x1DF - 0x1D0
59 *| 31 - 8       | 7-5    4 - 0  |
60 *| h2c_msg      |Class_ID CMD_ID        |
61 *
62 * Extend 0x1FF - 0x1F0
63 *|31 - 0          |
64 *|ext_msg|
65 ******************************************/
66 s32 FillH2CCmd_88E(PADAPTER padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)
67 {
68         struct dvobj_priv *dvobj =  adapter_to_dvobj(padapter);
69         HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
70         u8 h2c_box_num;
71         u32     msgbox_addr;
72         u32 msgbox_ex_addr = 0;
73         u8 cmd_idx,ext_cmd_len;
74         u32     h2c_cmd = 0;
75         u32     h2c_cmd_ex = 0;
76         s32 ret = _FAIL;
77
78 _func_enter_;
79
80         padapter = GET_PRIMARY_ADAPTER(padapter);               
81         pHalData = GET_HAL_DATA(padapter);
82
83         if(padapter->bFWReady == _FALSE)
84         {
85                 DBG_8192C("FillH2CCmd_88E(): return H2C cmd because fw is not ready\n");
86                 return ret;
87         }
88
89         _enter_critical_mutex(&(dvobj->h2c_fwcmd_mutex), NULL);
90
91         if (!pCmdBuffer) {
92                 goto exit;
93         }
94         if (CmdLen > RTL88E_MAX_CMD_LEN) {
95                 goto exit;
96         }
97         if (rtw_is_surprise_removed(padapter))
98                 goto exit;
99
100         //pay attention to if  race condition happened in  H2C cmd setting.
101         do{
102                 h2c_box_num = pHalData->LastHMEBoxNum;
103
104                 if(!_is_fw_read_cmd_down(padapter, h2c_box_num)){
105                         DBG_8192C(" fw read cmd failed...\n");
106                         goto exit;
107                 }
108
109                 *(u8*)(&h2c_cmd) = ElementID;
110
111                 if(CmdLen<=3)
112                 {
113                         _rtw_memcpy((u8*)(&h2c_cmd)+1, pCmdBuffer, CmdLen );
114                 }
115                 else{                   
116                         _rtw_memcpy((u8*)(&h2c_cmd)+1, pCmdBuffer,3);
117                         ext_cmd_len = CmdLen-3; 
118                         _rtw_memcpy((u8*)(&h2c_cmd_ex), pCmdBuffer+3,ext_cmd_len );
119
120                         //Write Ext command
121                         msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num *RTL88E_EX_MESSAGE_BOX_SIZE);
122                         #ifdef CONFIG_H2C_EF
123                         for(cmd_idx=0;cmd_idx<ext_cmd_len;cmd_idx++ ){
124                                 rtw_write8(padapter,msgbox_ex_addr+cmd_idx,*((u8*)(&h2c_cmd_ex)+cmd_idx));
125                         }
126                         #else
127                         h2c_cmd_ex = le32_to_cpu( h2c_cmd_ex );
128                         rtw_write32(padapter, msgbox_ex_addr, h2c_cmd_ex);
129                         #endif
130                 }
131                 // Write command
132                 msgbox_addr =REG_HMEBOX_0 + (h2c_box_num *RTL88E_MESSAGE_BOX_SIZE);
133                 #ifdef CONFIG_H2C_EF
134                 for(cmd_idx=0;cmd_idx<RTL88E_MESSAGE_BOX_SIZE;cmd_idx++ ){
135                         rtw_write8(padapter,msgbox_addr+cmd_idx,*((u8*)(&h2c_cmd)+cmd_idx));
136                 }
137                 #else
138                 h2c_cmd = le32_to_cpu( h2c_cmd );
139                 rtw_write32(padapter,msgbox_addr, h2c_cmd);
140                 #endif
141                 
142
143         //      DBG_8192C("MSG_BOX:%d,CmdLen(%d), reg:0x%x =>h2c_cmd:0x%x, reg:0x%x =>h2c_cmd_ex:0x%x ..\n"
144         //              ,pHalData->LastHMEBoxNum ,CmdLen,msgbox_addr,h2c_cmd,msgbox_ex_addr,h2c_cmd_ex);
145
146                 pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL88E_MAX_H2C_BOX_NUMS;
147
148         }while(0);
149
150         ret = _SUCCESS;
151
152 exit:
153
154         _exit_critical_mutex(&(dvobj->h2c_fwcmd_mutex), NULL);
155
156 _func_exit_;
157
158         return ret;
159 }
160
161 u8 rtl8192c_h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf)
162 {
163         u8 ElementID, CmdLen;
164         u8 *pCmdBuffer;
165         struct cmd_msg_parm  *pcmdmsg;
166
167         if(!pbuf)
168                 return H2C_PARAMETERS_ERROR;
169
170         pcmdmsg = (struct cmd_msg_parm*)pbuf;
171         ElementID = pcmdmsg->eid;
172         CmdLen = pcmdmsg->sz;
173         pCmdBuffer = pcmdmsg->buf;
174
175         FillH2CCmd_88E(padapter, ElementID, CmdLen, pCmdBuffer);
176
177         return H2C_SUCCESS;
178 }
179 /*
180 #if defined(CONFIG_AUTOSUSPEND) && defined(SUPPORT_HW_RFOFF_DETECTED)
181 u8 rtl8192c_set_FwSelectSuspend_cmd(_adapter *padapter ,u8 bfwpoll, u16 period)
182 {
183         u8      res=_SUCCESS;
184         struct H2C_SS_RFOFF_PARAM param;
185         DBG_8192C("==>%s bfwpoll(%x)\n",__FUNCTION__,bfwpoll);
186         param.gpio_period = period;//Polling GPIO_11 period time
187         param.ROFOn = (_TRUE == bfwpoll)?1:0;
188         FillH2CCmd_88E(padapter, SELECTIVE_SUSPEND_ROF_CMD, sizeof(param), (u8*)(&param));              
189         return res;
190 }
191 #endif //CONFIG_AUTOSUSPEND && SUPPORT_HW_RFOFF_DETECTED
192 */
193 u8 rtl8188e_set_rssi_cmd(_adapter*padapter, u8 *param)
194 {
195         u8      res=_SUCCESS;
196         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
197 _func_enter_;
198
199         if(pHalData->fw_ractrl == _FALSE){              
200                 DBG_8192C("==>%s fw dont support RA \n",__FUNCTION__);
201                 return _FAIL;
202         }
203                 
204         *((u32*) param ) = cpu_to_le32( *((u32*) param ) );
205         FillH2CCmd_88E(padapter, H2C_RSSI_REPORT, 3, param);    
206
207 _func_exit_;
208
209         return res;
210 }
211
212 u8 rtl8188e_set_raid_cmd(_adapter*padapter, u32 bitmap, u8* arg)
213 {       
214         u8      res=_SUCCESS;
215         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
216         struct sta_info *psta = NULL;
217         struct macid_ctl_t *macid_ctl = &padapter->dvobj->macid_ctl;
218         u8 macid, init_rate, raid, shortGIrate=_FALSE;  
219         u8 H2CCommand[7]={0};
220                 
221         if(pHalData->fw_ractrl == _FALSE){              
222                 DBG_8192C("==>%s fw dont support RA \n",__FUNCTION__);
223                 return _FAIL;
224         }
225
226         macid = arg[0];
227         raid = arg[1];
228         shortGIrate = arg[2];
229         init_rate = arg[3];     
230
231         if (macid < macid_ctl->num)
232                 psta = macid_ctl->sta[macid];
233         if (psta == NULL) {
234                 DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" macid:%u, sta is NULL\n"
235                         , FUNC_ADPT_ARG(padapter), macid);
236                 return _FAIL;
237         }
238                 
239         H2CCommand[0] = macid;
240         H2CCommand[1] = raid | (shortGIrate?0x80:0x00) ;        
241         H2CCommand[2] = psta->bw_mode & 0x03; //BW; 
242
243 #ifdef CONFIG_INTEL_PROXIM
244         if(padapter->proximity.proxim_on ==_TRUE)
245                 pHalData->bDisableTXPowerTraining = _FALSE;
246 #endif
247
248         //DisableTXPowerTraining
249         if(pHalData->bDisableTXPowerTraining){
250                 H2CCommand[2] |= BIT6;
251                 DBG_871X("%s,Disable PWT by driver\n",__FUNCTION__);
252         }
253         else{
254                 PDM_ODM_T       pDM_OutSrc = &pHalData->odmpriv;
255
256                 if(pDM_OutSrc->bDisablePowerTraining){
257                         H2CCommand[2] |= BIT6;
258                         DBG_871X("%s,Disable PWT by DM\n",__FUNCTION__);        
259                 }
260         }
261         
262         H2CCommand[3] = (u1Byte)(bitmap & 0x000000ff);
263         H2CCommand[4] = (u1Byte)((bitmap & 0x0000ff00) >>8);
264         H2CCommand[5] = (u1Byte)((bitmap & 0x00ff0000) >> 16);
265         H2CCommand[6] = (u1Byte)((bitmap & 0xff000000) >> 24);
266         
267         FillH2CCmd_88E(padapter, H2C_DM_MACID_CFG, 7, H2CCommand);
268
269         //The firmware Rate Adaption function is triggered by TBTT INT, so to
270         // enable the rate adaption, we need to enable the hardware Beacon function Reg 0x550[3]                
271         //SetBcnCtrlReg(padapter, BIT3, 0);             
272         rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)|BIT3);
273
274         return res;
275
276 }
277
278 //bitmap[0:27] = tx_rate_bitmap
279 //bitmap[28:31]= Rate Adaptive id
280 //arg[0:4] = macid
281 //arg[5] = Short GI
282 void rtl8188e_Add_RateATid(PADAPTER pAdapter, u64 rate_bitmap, u8 *arg, u8 rssi_level)
283 {
284         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(pAdapter);
285         u8 macid, init_rate, raid, shortGIrate=_FALSE;
286         u32 bitmap = (u32) rate_bitmap;
287
288         macid = arg[0];
289         raid = arg[1];
290         shortGIrate = arg[2];
291         init_rate = arg[3];
292
293         bitmap &=0x0fffffff;    
294         
295         if(rssi_level != DM_RATR_STA_INIT)
296                 bitmap = ODM_Get_Rate_Bitmap(&pHalData->odmpriv, macid, bitmap, rssi_level);            
297
298         if (shortGIrate==_TRUE)
299                 init_rate |= BIT(6);
300
301         bitmap &= 0x0fffffff;
302         
303         DBG_871X("%s=> mac_id:%d , raid:%d , ra_bitmap=0x%x, shortGIrate=0x%02x\n", 
304                         __FUNCTION__,macid ,raid ,bitmap, shortGIrate);
305
306
307 #if(RATE_ADAPTIVE_SUPPORT == 1)
308         if(!pHalData->fw_ractrl ){
309                 ODM_RA_UpdateRateInfo_8188E(
310                                 &(pHalData->odmpriv),
311                                 macid,
312                                 raid, 
313                                 bitmap,
314                                 shortGIrate
315                                 );
316         }
317         else
318 #endif
319         {
320                  rtl8188e_set_raid_cmd(pAdapter,bitmap,arg);
321         }
322         
323
324 }
325
326 void rtl8188e_set_FwPwrMode_cmd(PADAPTER padapter, u8 Mode)
327 {
328         SETPWRMODE_PARM H2CSetPwrMode;
329         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
330         u8      RLBM = 0; // 0:Min, 1:Max , 2:User define
331 _func_enter_;
332
333         DBG_871X("%s: Mode=%d SmartPS=%d UAPSD=%d\n", __FUNCTION__,
334                         Mode, pwrpriv->smart_ps, padapter->registrypriv.uapsd_enable);
335
336         H2CSetPwrMode.AwakeInterval = 2;        //DTIM = 1
337
338         switch(Mode)
339         {
340                 case PS_MODE_ACTIVE:
341                         H2CSetPwrMode.Mode = 0;
342                         break;
343                 case PS_MODE_MIN:
344                         H2CSetPwrMode.Mode = 1;
345                         break;
346                 case PS_MODE_MAX:
347                         RLBM = 1;
348                         H2CSetPwrMode.Mode = 1;
349                         break;
350                 case PS_MODE_DTIM:
351                         RLBM = 2;
352                         H2CSetPwrMode.AwakeInterval = 3; //DTIM = 2
353                         H2CSetPwrMode.Mode = 1;
354                         break;
355                 case PS_MODE_UAPSD_WMM:
356                         H2CSetPwrMode.Mode = 2;
357                         break;
358                 default:
359                         H2CSetPwrMode.Mode = 0;
360                         break;
361         }
362
363         //H2CSetPwrMode.Mode = Mode;
364
365         H2CSetPwrMode.SmartPS_RLBM = (((pwrpriv->smart_ps<<4)&0xf0) | (RLBM & 0x0f));
366
367         H2CSetPwrMode.bAllQueueUAPSD = padapter->registrypriv.uapsd_enable;
368
369         if(Mode > 0)
370         {
371                 H2CSetPwrMode.PwrState = 0x00;// AllON(0x0C), RFON(0x04), RFOFF(0x00)
372 #ifdef CONFIG_EXT_CLK
373                 H2CSetPwrMode.Mode |= BIT(7);//supporting 26M XTAL CLK_Request feature.
374 #endif //CONFIG_EXT_CLK
375         }
376         else
377                 H2CSetPwrMode.PwrState = 0x0C;// AllON(0x0C), RFON(0x04), RFOFF(0x00)
378
379         FillH2CCmd_88E(padapter, H2C_PS_PWR_MODE, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
380         
381
382 _func_exit_;
383 }
384
385 void ConstructBeacon(_adapter *padapter, u8 *pframe, u32 *pLength)
386 {
387         struct rtw_ieee80211_hdr        *pwlanhdr;
388         u16                                     *fctrl;
389         u32                                     rate_len, pktlen;
390         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
391         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
392         WLAN_BSSID_EX           *cur_network = &(pmlmeinfo->network);
393         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
394
395
396         //DBG_871X("%s\n", __FUNCTION__);
397
398         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
399
400         fctrl = &(pwlanhdr->frame_ctl);
401         *(fctrl) = 0;
402
403         _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
404         _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
405         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
406
407         SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
408         //pmlmeext->mgnt_seq++;
409         SetFrameSubType(pframe, WIFI_BEACON);
410
411         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
412         pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
413
414         //timestamp will be inserted by hardware
415         pframe += 8;
416         pktlen += 8;
417
418         // beacon interval: 2 bytes
419         _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
420
421         pframe += 2;
422         pktlen += 2;
423
424         // capability info: 2 bytes
425         _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
426
427         pframe += 2;
428         pktlen += 2;
429
430         if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
431         {
432                 //DBG_871X("ie len=%d\n", cur_network->IELength);
433                 pktlen += cur_network->IELength - sizeof(NDIS_802_11_FIXED_IEs);
434                 _rtw_memcpy(pframe, cur_network->IEs+sizeof(NDIS_802_11_FIXED_IEs), pktlen);
435
436                 goto _ConstructBeacon;
437         }
438
439         //below for ad-hoc mode
440
441         // SSID
442         pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);
443
444         // supported rates...
445         rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
446         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pktlen);
447
448         // DS parameter set
449         pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
450
451         if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
452         {
453                 u32 ATIMWindow;
454                 // IBSS Parameter Set...
455                 //ATIMWindow = cur->Configuration.ATIMWindow;
456                 ATIMWindow = 0;
457                 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
458         }
459
460
461         //todo: ERP IE
462
463
464         // EXTERNDED SUPPORTED RATE
465         if (rate_len > 8)
466         {
467                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
468         }
469
470
471         //todo:HT for adhoc
472
473 _ConstructBeacon:
474
475         if ((pktlen + TXDESC_SIZE) > 512)
476         {
477                 DBG_871X("beacon frame too large\n");
478                 return;
479         }
480
481         *pLength = pktlen;
482
483         //DBG_871X("%s bcn_sz=%d\n", __FUNCTION__, pktlen);
484
485 }
486
487 void ConstructPSPoll(_adapter *padapter, u8 *pframe, u32 *pLength)
488 {
489         struct rtw_ieee80211_hdr        *pwlanhdr;
490         u16                                     *fctrl;
491         u32                                     pktlen;
492         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
493         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
494
495         //DBG_871X("%s\n", __FUNCTION__);
496
497         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
498
499         // Frame control.
500         fctrl = &(pwlanhdr->frame_ctl);
501         *(fctrl) = 0;
502         SetPwrMgt(fctrl);
503         SetFrameSubType(pframe, WIFI_PSPOLL);
504
505         // AID.
506         SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
507
508         // BSSID.
509         _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
510
511         // TA.
512         _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
513
514         *pLength = 16;
515 }
516
517 void ConstructNullFunctionData(
518         PADAPTER padapter,
519         u8              *pframe,
520         u32             *pLength,
521         u8              *StaAddr,
522         u8              bQoS,
523         u8              AC,
524         u8              bEosp,
525         u8              bForcePowerSave)
526 {
527         struct rtw_ieee80211_hdr        *pwlanhdr;
528         u16                                             *fctrl;
529         u32                                             pktlen;
530         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;
531         struct wlan_network             *cur_network = &pmlmepriv->cur_network;
532         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
533         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
534
535
536         //DBG_871X("%s:%d\n", __FUNCTION__, bForcePowerSave);
537
538         pwlanhdr = (struct rtw_ieee80211_hdr*)pframe;
539
540         fctrl = &pwlanhdr->frame_ctl;
541         *(fctrl) = 0;
542         if (bForcePowerSave)
543         {
544                 SetPwrMgt(fctrl);
545         }
546
547         switch(cur_network->network.InfrastructureMode)
548         {
549                 case Ndis802_11Infrastructure:
550                         SetToDs(fctrl);
551                         _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
552                         _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
553                         _rtw_memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
554                         break;
555                 case Ndis802_11APMode:
556                         SetFrDs(fctrl);
557                         _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
558                         _rtw_memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
559                         _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
560                         break;
561                 case Ndis802_11IBSS:
562                 default:
563                         _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
564                         _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
565                         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
566                         break;
567         }
568
569         SetSeqNum(pwlanhdr, 0);
570
571         if (bQoS == _TRUE) {
572                 struct rtw_ieee80211_hdr_3addr_qos *pwlanqoshdr;
573
574                 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
575
576                 pwlanqoshdr = (struct rtw_ieee80211_hdr_3addr_qos*)pframe;
577                 SetPriority(&pwlanqoshdr->qc, AC);
578                 SetEOSP(&pwlanqoshdr->qc, bEosp);
579
580                 pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
581         } else {
582                 SetFrameSubType(pframe, WIFI_DATA_NULL);
583
584                 pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
585         }
586
587         *pLength = pktlen;
588 }
589
590 void rtl8188e_set_FwRsvdPage_cmd(PADAPTER padapter, PRSVDPAGE_LOC rsvdpageloc)
591 {
592     u8 u1H2CRsvdPageParm[H2C_RSVDPAGE_LOC_LEN]={0};
593     u8 u1H2CAoacRsvdPageParm[H2C_AOAC_RSVDPAGE_LOC_LEN]={0};
594
595     //DBG_871X("8188RsvdPageLoc: PsPoll=%d Null=%d QoSNull=%d\n", 
596         //      rsvdpageloc->LocPsPoll, rsvdpageloc->LocNullData, rsvdpageloc->LocQosNull);
597
598     SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1H2CRsvdPageParm, rsvdpageloc->LocPsPoll);
599     SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocNullData);
600     SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocQosNull);
601     
602     FillH2CCmd_88E(padapter, H2C_COM_RSVD_PAGE, H2C_RSVDPAGE_LOC_LEN, u1H2CRsvdPageParm);
603
604 #ifdef CONFIG_WOWLAN    
605     //DBG_871X("8188E_AOACRsvdPageLoc: RWC=%d ArpRsp=%d\n", rsvdpageloc->LocRemoteCtrlInfo, rsvdpageloc->LocArpRsp);
606     SET_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1H2CAoacRsvdPageParm, rsvdpageloc->LocRemoteCtrlInfo);
607     SET_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1H2CAoacRsvdPageParm, rsvdpageloc->LocArpRsp);
608
609     FillH2CCmd_88E(padapter, H2C_COM_AOAC_RSVD_PAGE, H2C_AOAC_RSVDPAGE_LOC_LEN, u1H2CAoacRsvdPageParm);
610 #endif
611 }
612
613 // To check if reserved page content is destroyed by beacon beacuse beacon is too large.
614 // 2010.06.23. Added by tynli.
615 VOID
616 CheckFwRsvdPageContent(
617         IN      PADAPTER                Adapter
618 )
619 {
620         HAL_DATA_TYPE*  pHalData = GET_HAL_DATA(Adapter);
621         u32     MaxBcnPageNum;
622
623         if(pHalData->FwRsvdPageStartOffset != 0)
624         {
625                 /*MaxBcnPageNum = PageNum_128(pMgntInfo->MaxBeaconSize);
626                 RT_ASSERT((MaxBcnPageNum <= pHalData->FwRsvdPageStartOffset),
627                         ("CheckFwRsvdPageContent(): The reserved page content has been"\
628                         "destroyed by beacon!!! MaxBcnPageNum(%d) FwRsvdPageStartOffset(%d)\n!",
629                         MaxBcnPageNum, pHalData->FwRsvdPageStartOffset));*/
630         }
631 }
632
633 //
634 // Description: Get the reserved page number in Tx packet buffer.
635 // Retrun value: the page number.
636 // 2012.08.09, by tynli.
637 //
638 u8
639 GetTxBufferRsvdPageNum8188E(_adapter *padapter, bool wowlan)
640 {
641         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
642         u8      RsvdPageNum=0;
643         // default reseved 1 page for the IC type which is undefined.
644         u8      TxPageBndy= LAST_ENTRY_OF_TX_PKT_BUFFER_8188E(padapter);
645
646         rtw_hal_get_def_var(padapter, HAL_DEF_TX_PAGE_BOUNDARY, (u8 *)&TxPageBndy);
647
648         RsvdPageNum = LAST_ENTRY_OF_TX_PKT_BUFFER_8188E(padapter) - TxPageBndy + 1;
649
650         return RsvdPageNum;
651 }
652
653 void rtl8188e_set_FwJoinBssReport_cmd(PADAPTER padapter, u8 mstatus)
654 {
655         JOINBSSRPT_PARM_88E     JoinBssRptParm;
656         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
657         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
658         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
659 #ifdef CONFIG_WOWLAN
660         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
661         struct sta_info *psta = NULL;
662 #endif
663         BOOLEAN         bSendBeacon=_FALSE;
664         BOOLEAN         bcn_valid = _FALSE;
665         u8      DLBcnCount=0;
666         u32 poll = 0;
667
668 _func_enter_;
669
670         DBG_871X("%s mstatus(%x)\n", __FUNCTION__,mstatus);
671
672         if(mstatus == 1)
673         {
674                 // We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C.
675                 // Suggested by filen. Added by tynli.
676                 rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
677                 // Do not set TSF again here or vWiFi beacon DMA INT will not work.
678                 //correct_TSF(padapter, pmlmeext);
679                 // Hw sequende enable by dedault. 2010.06.23. by tynli.
680                 //rtw_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF));
681                 //rtw_write8(padapter, REG_HWSEQ_CTRL, 0xFF);
682
683                 //Set REG_CR bit 8. DMA beacon by SW.
684                 pHalData->RegCR_1 |= BIT0;
685                 rtw_write8(padapter,  REG_CR+1, pHalData->RegCR_1);
686
687                 // Disable Hw protection for a time which revserd for Hw sending beacon.
688                 // Fix download reserved page packet fail that access collision with the protection time.
689                 // 2010.05.11. Added by tynli.
690                 //SetBcnCtrlReg(padapter, 0, BIT3);
691                 //SetBcnCtrlReg(padapter, BIT4, 0);
692                 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)&(~BIT(3)));
693                 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)|BIT(4));
694
695                 if(pHalData->RegFwHwTxQCtrl&BIT6)
696                 {
697                         DBG_871X("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n");
698                         bSendBeacon = _TRUE;
699                 }
700
701                 // Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.
702                 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, (pHalData->RegFwHwTxQCtrl&(~BIT6)));
703                 pHalData->RegFwHwTxQCtrl &= (~BIT6);
704
705                 // Clear beacon valid check bit.
706                 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
707                 DLBcnCount = 0;
708                 poll = 0;
709                 do
710                 {
711                         /* download rsvd page.*/
712                         rtw_hal_set_fw_rsvd_page(padapter, _FALSE);
713                         DLBcnCount++;
714                         do
715                         {
716                                 rtw_yield_os();
717                                 //rtw_mdelay_os(10);
718                                 // check rsvd page download OK.
719                                 rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8*)(&bcn_valid));
720                                 poll++;
721                         } while (!bcn_valid && (poll%10) != 0 && !RTW_CANNOT_RUN(padapter));
722                         
723                 } while (!bcn_valid && DLBcnCount <= 100 && !RTW_CANNOT_RUN(padapter));
724                 
725                 //RT_ASSERT(bcn_valid, ("HalDownloadRSVDPage88ES(): 1 Download RSVD page failed!\n"));
726                 if (RTW_CANNOT_RUN(padapter))
727                         ;
728                 else if (!bcn_valid)
729                         DBG_871X(ADPT_FMT": 1 DL RSVD page failed! DLBcnCount:%u, poll:%u\n",
730                                 ADPT_ARG(padapter) ,DLBcnCount, poll);
731                 else {
732                         struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
733                         pwrctl->fw_psmode_iface_id = padapter->iface_id;
734                         DBG_871X(ADPT_FMT": 1 DL RSVD page success! DLBcnCount:%u, poll:%u\n",
735                                 ADPT_ARG(padapter), DLBcnCount, poll);
736                 }
737
738                 // Enable Bcn
739                 //SetBcnCtrlReg(padapter, BIT3, 0);
740                 //SetBcnCtrlReg(padapter, 0, BIT4);
741                 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)|BIT(3));
742                 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)&(~BIT(4)));
743
744                 // To make sure that if there exists an adapter which would like to send beacon.
745                 // If exists, the origianl value of 0x422[6] will be 1, we should check this to
746                 // prevent from setting 0x422[6] to 0 after download reserved page, or it will cause 
747                 // the beacon cannot be sent by HW.
748                 // 2010.06.23. Added by tynli.
749                 if(bSendBeacon)
750                 {
751                         rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, (pHalData->RegFwHwTxQCtrl|BIT6));
752                         pHalData->RegFwHwTxQCtrl |= BIT6;
753                 }
754
755                 //
756                 // Update RSVD page location H2C to Fw.
757                 //
758                 if(bcn_valid)
759                 {
760                         rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
761                         DBG_871X("Set RSVD page location to Fw.\n");
762                         //FillH2CCmd88E(Adapter, H2C_88E_RSVDPAGE, H2C_RSVDPAGE_LOC_LENGTH, pMgntInfo->u1RsvdPageLoc);
763                 }
764                 
765                 // Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli.
766                 //if(!padapter->bEnterPnpSleep)
767                 {
768                         // Clear CR[8] or beacon packet will not be send to TxBuf anymore.
769                         pHalData->RegCR_1 &= (~BIT0);
770                         rtw_write8(padapter,  REG_CR+1, pHalData->RegCR_1);
771                 }
772         }
773 _func_exit_;
774 }
775
776 #ifdef CONFIG_P2P_PS
777 void rtl8188e_set_p2p_ps_offload_cmd(_adapter* padapter, u8 p2p_ps_state)
778 {
779         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);
780         struct pwrctrl_priv             *pwrpriv = adapter_to_pwrctl(padapter);
781         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );
782         struct P2P_PS_Offload_t *p2p_ps_offload = (struct P2P_PS_Offload_t      *)(&pHalData->p2p_ps_offload);
783         u8      i;
784
785 _func_enter_;
786
787 #if 1
788         switch(p2p_ps_state)
789         {
790                 case P2P_PS_DISABLE:
791                         DBG_8192C("P2P_PS_DISABLE \n");
792                         _rtw_memset(p2p_ps_offload, 0 ,1);
793                         break;
794                 case P2P_PS_ENABLE:
795                         DBG_8192C("P2P_PS_ENABLE \n");
796                         // update CTWindow value.
797                         if( pwdinfo->ctwindow > 0 )
798                         {
799                                 p2p_ps_offload->CTWindow_En = 1;
800                                 rtw_write8(padapter, REG_P2P_CTWIN, pwdinfo->ctwindow);
801                         }
802
803                         // hw only support 2 set of NoA
804                         for( i=0 ; i<pwdinfo->noa_num ; i++)
805                         {
806                                 // To control the register setting for which NOA
807                                 rtw_write8(padapter, REG_NOA_DESC_SEL, (i << 4));
808                                 if(i == 0)
809                                         p2p_ps_offload->NoA0_En = 1;
810                                 else
811                                         p2p_ps_offload->NoA1_En = 1;
812
813                                 // config P2P NoA Descriptor Register
814                                 //DBG_8192C("%s(): noa_duration = %x\n",__FUNCTION__,pwdinfo->noa_duration[i]);
815                                 rtw_write32(padapter, REG_NOA_DESC_DURATION, pwdinfo->noa_duration[i]);
816
817                                 //DBG_8192C("%s(): noa_interval = %x\n",__FUNCTION__,pwdinfo->noa_interval[i]);
818                                 rtw_write32(padapter, REG_NOA_DESC_INTERVAL, pwdinfo->noa_interval[i]);
819
820                                 //DBG_8192C("%s(): start_time = %x\n",__FUNCTION__,pwdinfo->noa_start_time[i]);
821                                 rtw_write32(padapter, REG_NOA_DESC_START, pwdinfo->noa_start_time[i]);
822
823                                 //DBG_8192C("%s(): noa_count = %x\n",__FUNCTION__,pwdinfo->noa_count[i]);
824                                 rtw_write8(padapter, REG_NOA_DESC_COUNT, pwdinfo->noa_count[i]);
825                         }
826
827                         if( (pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0) )
828                         {
829                                 // rst p2p circuit
830                                 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(4));
831
832                                 p2p_ps_offload->Offload_En = 1;
833
834                                 if(pwdinfo->role == P2P_ROLE_GO)
835                                 {
836                                         p2p_ps_offload->role= 1;
837                                         p2p_ps_offload->AllStaSleep = 0;
838                                 }
839                                 else
840                                 {
841                                         p2p_ps_offload->role= 0;
842                                 }
843
844                                 p2p_ps_offload->discovery = 0;
845                         }
846                         break;
847                 case P2P_PS_SCAN:
848                         DBG_8192C("P2P_PS_SCAN \n");
849                         p2p_ps_offload->discovery = 1;
850                         break;
851                 case P2P_PS_SCAN_DONE:
852                         DBG_8192C("P2P_PS_SCAN_DONE \n");
853                         p2p_ps_offload->discovery = 0;
854                         pwdinfo->p2p_ps_state = P2P_PS_ENABLE;
855                         break;
856                 default:
857                         break;
858         }
859
860         FillH2CCmd_88E(padapter, H2C_PS_P2P_OFFLOAD, 1, (u8 *)p2p_ps_offload);
861 #endif
862
863 _func_exit_;
864
865 }
866 #endif //CONFIG_P2P_PS
867
868 #ifdef CONFIG_TSF_RESET_OFFLOAD
869 /*
870         ask FW to Reset sync register at Beacon early interrupt
871 */
872 u8 rtl8188e_reset_tsf(_adapter *padapter, u8 reset_port )
873 {       
874         u8      buf[2];
875         u8      res=_SUCCESS;
876
877         s32 ret;
878 _func_enter_;
879         if (IFACE_PORT0==reset_port) {
880                 buf[0] = 0x1; buf[1] = 0;
881         } else{
882                 buf[0] = 0x0; buf[1] = 0x1;
883         }
884
885         ret = FillH2CCmd_88E(padapter, H2C_RESET_TSF, 2, buf);
886
887 _func_exit_;
888
889         return res;
890 }
891
892 int reset_tsf(PADAPTER Adapter, u8 reset_port )
893 {
894         u8 reset_cnt_before = 0, reset_cnt_after = 0, loop_cnt = 0;
895         u32 reg_reset_tsf_cnt = (IFACE_PORT0==reset_port) ?
896                                 REG_FW_RESET_TSF_CNT_0:REG_FW_RESET_TSF_CNT_1;
897         u32 reg_bcncrtl = (IFACE_PORT0==reset_port) ?
898                                 REG_BCN_CTRL_1:REG_BCN_CTRL;
899
900         rtw_scan_abort(Adapter->pbuddy_adapter);        /*      site survey will cause reset_tsf fail   */
901         reset_cnt_after = reset_cnt_before = rtw_read8(Adapter,reg_reset_tsf_cnt);
902         rtl8188e_reset_tsf(Adapter, reset_port);
903
904         while ((reset_cnt_after == reset_cnt_before ) && (loop_cnt < 10)) {
905                 rtw_msleep_os(100);
906                 loop_cnt++;
907                 reset_cnt_after = rtw_read8(Adapter, reg_reset_tsf_cnt);
908         }
909
910         return(loop_cnt >= 10) ? _FAIL : _TRUE;
911 }
912
913
914 #endif  // CONFIG_TSF_RESET_OFFLOAD