wifi: renew patch drivers/net/wireless
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rtl8188eu / hal / rtl8188e / rtl8188e_cmd.c
1 /******************************************************************************\r
2  *\r
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.\r
4  *\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
8  *\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
12  * more details.\r
13  *\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
17  *\r
18  *\r
19  ******************************************************************************/\r
20 #define _RTL8188E_CMD_C_\r
21 \r
22 #include <drv_types.h>\r
23 #include <rtl8188e_hal.h>\r
24 #include "hal_com_h2c.h"\r
25 \r
26 #define CONFIG_H2C_EF\r
27 \r
28 #define RTL88E_MAX_H2C_BOX_NUMS 4\r
29 #define RTL88E_MAX_CMD_LEN      7\r
30 #define RTL88E_MESSAGE_BOX_SIZE         4\r
31 #define RTL88E_EX_MESSAGE_BOX_SIZE      4\r
32 \r
33 static u8 _is_fw_read_cmd_down(_adapter* padapter, u8 msgbox_num)\r
34 {\r
35         u8      read_down = _FALSE;\r
36         int     retry_cnts = 100;\r
37 \r
38         u8 valid;\r
39 \r
40         //DBG_8192C(" _is_fw_read_cmd_down ,reg_1cc(%x),msg_box(%d)...\n",rtw_read8(padapter,REG_HMETFR),msgbox_num);\r
41 \r
42         do{\r
43                 valid = rtw_read8(padapter,REG_HMETFR) & BIT(msgbox_num);\r
44                 if(0 == valid ){\r
45                         read_down = _TRUE;\r
46                 }\r
47 #ifdef CONFIG_WOWLAN\r
48                 rtw_msleep_os(2);\r
49 #endif\r
50         }while( (!read_down) && (retry_cnts--));\r
51 \r
52         return read_down;\r
53 \r
54 }\r
55 \r
56 \r
57 /*****************************************\r
58 * H2C Msg format :\r
59 * 0x1DF - 0x1D0\r
60 *| 31 - 8       | 7-5    4 - 0  |\r
61 *| h2c_msg      |Class_ID CMD_ID        |\r
62 *\r
63 * Extend 0x1FF - 0x1F0\r
64 *|31 - 0          |\r
65 *|ext_msg|\r
66 ******************************************/\r
67 static s32 FillH2CCmd_88E(PADAPTER padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)\r
68 {\r
69         struct dvobj_priv *dvobj =  adapter_to_dvobj(padapter);\r
70         HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);\r
71         u8 h2c_box_num;\r
72         u32     msgbox_addr;\r
73         u32 msgbox_ex_addr;\r
74         u8 cmd_idx,ext_cmd_len;\r
75         u32     h2c_cmd = 0;\r
76         u32     h2c_cmd_ex = 0;\r
77         s32 ret = _FAIL;\r
78 \r
79 _func_enter_;\r
80 \r
81         padapter = GET_PRIMARY_ADAPTER(padapter);               \r
82         pHalData = GET_HAL_DATA(padapter);\r
83 \r
84         if(padapter->bFWReady == _FALSE)\r
85         {\r
86                 DBG_8192C("FillH2CCmd_88E(): return H2C cmd because fw is not ready\n");\r
87                 return ret;\r
88         }\r
89 \r
90         _enter_critical_mutex(&(dvobj->h2c_fwcmd_mutex), NULL);\r
91 \r
92         if (!pCmdBuffer) {\r
93                 goto exit;\r
94         }\r
95         if (CmdLen > RTL88E_MAX_CMD_LEN) {\r
96                 goto exit;\r
97         }\r
98         if (padapter->bSurpriseRemoved == _TRUE)\r
99                 goto exit;\r
100 \r
101         //pay attention to if  race condition happened in  H2C cmd setting.\r
102         do{\r
103                 h2c_box_num = pHalData->LastHMEBoxNum;\r
104 \r
105                 if(!_is_fw_read_cmd_down(padapter, h2c_box_num)){\r
106                         DBG_8192C(" fw read cmd failed...\n");\r
107                         goto exit;\r
108                 }\r
109 \r
110                 *(u8*)(&h2c_cmd) = ElementID;\r
111 \r
112                 if(CmdLen<=3)\r
113                 {\r
114                         _rtw_memcpy((u8*)(&h2c_cmd)+1, pCmdBuffer, CmdLen );\r
115                 }\r
116                 else{                   \r
117                         _rtw_memcpy((u8*)(&h2c_cmd)+1, pCmdBuffer,3);\r
118                         ext_cmd_len = CmdLen-3; \r
119                         _rtw_memcpy((u8*)(&h2c_cmd_ex), pCmdBuffer+3,ext_cmd_len );\r
120 \r
121                         //Write Ext command\r
122                         msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num *RTL88E_EX_MESSAGE_BOX_SIZE);\r
123                         #ifdef CONFIG_H2C_EF\r
124                         for(cmd_idx=0;cmd_idx<ext_cmd_len;cmd_idx++ ){\r
125                                 rtw_write8(padapter,msgbox_ex_addr+cmd_idx,*((u8*)(&h2c_cmd_ex)+cmd_idx));\r
126                         }\r
127                         #else\r
128                         h2c_cmd_ex = le32_to_cpu( h2c_cmd_ex );\r
129                         rtw_write32(padapter, msgbox_ex_addr, h2c_cmd_ex);\r
130                         #endif\r
131                 }\r
132                 // Write command\r
133                 msgbox_addr =REG_HMEBOX_0 + (h2c_box_num *RTL88E_MESSAGE_BOX_SIZE);\r
134                 #ifdef CONFIG_H2C_EF\r
135                 for(cmd_idx=0;cmd_idx<RTL88E_MESSAGE_BOX_SIZE;cmd_idx++ ){\r
136                         rtw_write8(padapter,msgbox_addr+cmd_idx,*((u8*)(&h2c_cmd)+cmd_idx));\r
137                 }\r
138                 #else\r
139                 h2c_cmd = le32_to_cpu( h2c_cmd );\r
140                 rtw_write32(padapter,msgbox_addr, h2c_cmd);\r
141                 #endif\r
142                 \r
143 \r
144         //      DBG_8192C("MSG_BOX:%d,CmdLen(%d), reg:0x%x =>h2c_cmd:0x%x, reg:0x%x =>h2c_cmd_ex:0x%x ..\n"\r
145         //              ,pHalData->LastHMEBoxNum ,CmdLen,msgbox_addr,h2c_cmd,msgbox_ex_addr,h2c_cmd_ex);\r
146 \r
147                 pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL88E_MAX_H2C_BOX_NUMS;\r
148 \r
149         }while(0);\r
150 \r
151         ret = _SUCCESS;\r
152 \r
153 exit:\r
154 \r
155         _exit_critical_mutex(&(dvobj->h2c_fwcmd_mutex), NULL);\r
156 \r
157 _func_exit_;\r
158 \r
159         return ret;\r
160 }\r
161 \r
162 u8 rtl8192c_h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf)\r
163 {\r
164         u8 ElementID, CmdLen;\r
165         u8 *pCmdBuffer;\r
166         struct cmd_msg_parm  *pcmdmsg;\r
167 \r
168         if(!pbuf)\r
169                 return H2C_PARAMETERS_ERROR;\r
170 \r
171         pcmdmsg = (struct cmd_msg_parm*)pbuf;\r
172         ElementID = pcmdmsg->eid;\r
173         CmdLen = pcmdmsg->sz;\r
174         pCmdBuffer = pcmdmsg->buf;\r
175 \r
176         FillH2CCmd_88E(padapter, ElementID, CmdLen, pCmdBuffer);\r
177 \r
178         return H2C_SUCCESS;\r
179 }\r
180 /*\r
181 #if defined(CONFIG_AUTOSUSPEND) && defined(SUPPORT_HW_RFOFF_DETECTED)\r
182 u8 rtl8192c_set_FwSelectSuspend_cmd(_adapter *padapter ,u8 bfwpoll, u16 period)\r
183 {\r
184         u8      res=_SUCCESS;\r
185         struct H2C_SS_RFOFF_PARAM param;\r
186         DBG_8192C("==>%s bfwpoll(%x)\n",__FUNCTION__,bfwpoll);\r
187         param.gpio_period = period;//Polling GPIO_11 period time\r
188         param.ROFOn = (_TRUE == bfwpoll)?1:0;\r
189         FillH2CCmd_88E(padapter, SELECTIVE_SUSPEND_ROF_CMD, sizeof(param), (u8*)(&param));              \r
190         return res;\r
191 }\r
192 #endif //CONFIG_AUTOSUSPEND && SUPPORT_HW_RFOFF_DETECTED\r
193 */\r
194 u8 rtl8188e_set_rssi_cmd(_adapter*padapter, u8 *param)\r
195 {\r
196         u8      res=_SUCCESS;\r
197         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);\r
198 _func_enter_;\r
199 \r
200         if(pHalData->fw_ractrl == _TRUE){\r
201                 #if 0\r
202         *((u32*) param ) = cpu_to_le32( *((u32*) param ) );\r
203 \r
204                 FillH2CCmd_88E(padapter, RSSI_SETTING_EID, 3, param);\r
205                 #endif\r
206         }else{\r
207                 DBG_8192C("==>%s fw dont support RA \n",__FUNCTION__);\r
208                 res=_FAIL;\r
209         }\r
210 \r
211 _func_exit_;\r
212 \r
213         return res;\r
214 }\r
215 \r
216 u8 rtl8188e_set_raid_cmd(_adapter*padapter, u32 mask)\r
217 {\r
218         u8      buf[3];\r
219         u8      res=_SUCCESS;\r
220         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);\r
221 _func_enter_;\r
222         if(pHalData->fw_ractrl == _TRUE){\r
223                 _rtw_memset(buf, 0, 3);\r
224                 mask = cpu_to_le32( mask );\r
225                 _rtw_memcpy(buf, &mask, 3);             \r
226 \r
227                 FillH2CCmd_88E(padapter, H2C_DM_MACID_CFG, 3, buf);\r
228         }else{\r
229                 DBG_8192C("==>%s fw dont support RA \n",__FUNCTION__);\r
230                 res=_FAIL;\r
231         }       \r
232 \r
233 _func_exit_;\r
234 \r
235         return res;\r
236 \r
237 }\r
238 \r
239 //bitmap[0:27] = tx_rate_bitmap\r
240 //bitmap[28:31]= Rate Adaptive id\r
241 //arg[0:4] = macid\r
242 //arg[5] = Short GI\r
243 void rtl8188e_Add_RateATid(PADAPTER pAdapter, u32 bitmap, u8* arg, u8 rssi_level)\r
244 {\r
245         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(pAdapter);\r
246         u8 macid, init_rate, raid, shortGIrate=_FALSE;\r
247 \r
248         macid = arg[0];\r
249         raid = arg[1];\r
250         shortGIrate = arg[2];\r
251         init_rate = arg[3];\r
252 \r
253         bitmap &=0x0fffffff;    \r
254         \r
255         if(rssi_level != DM_RATR_STA_INIT)\r
256                 bitmap = ODM_Get_Rate_Bitmap(&pHalData->odmpriv, macid, bitmap, rssi_level);            \r
257 \r
258         if (shortGIrate==_TRUE)\r
259                 init_rate |= BIT(6);\r
260 \r
261         bitmap &= 0x0fffffff;\r
262         \r
263         DBG_871X("%s=> mac_id:%d , raid:%d , ra_bitmap=0x%x, shortGIrate=0x%02x\n", \r
264                         __FUNCTION__,macid ,raid ,bitmap, shortGIrate);\r
265 \r
266 \r
267 #if(RATE_ADAPTIVE_SUPPORT == 1)\r
268         ODM_RA_UpdateRateInfo_8188E(\r
269                         &(pHalData->odmpriv),\r
270                         macid,\r
271                         raid, \r
272                         bitmap,\r
273                         shortGIrate\r
274                         );\r
275 #endif  \r
276 \r
277 }\r
278 \r
279 void rtl8188e_set_FwPwrMode_cmd(PADAPTER padapter, u8 Mode)\r
280 {\r
281         SETPWRMODE_PARM H2CSetPwrMode;\r
282         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);\r
283         u8      RLBM = 0; // 0:Min, 1:Max , 2:User define\r
284 _func_enter_;\r
285 \r
286         DBG_871X("%s: Mode=%d SmartPS=%d UAPSD=%d\n", __FUNCTION__,\r
287                         Mode, pwrpriv->smart_ps, padapter->registrypriv.uapsd_enable);\r
288 \r
289         H2CSetPwrMode.AwakeInterval = 2;        //DTIM = 1\r
290 \r
291         switch(Mode)\r
292         {\r
293                 case PS_MODE_ACTIVE:\r
294                         H2CSetPwrMode.Mode = 0;\r
295                         break;\r
296                 case PS_MODE_MIN:\r
297                         H2CSetPwrMode.Mode = 1;\r
298                         break;\r
299                 case PS_MODE_MAX:\r
300                         RLBM = 1;\r
301                         H2CSetPwrMode.Mode = 1;\r
302                         break;\r
303                 case PS_MODE_DTIM:\r
304                         RLBM = 2;\r
305                         H2CSetPwrMode.AwakeInterval = 3; //DTIM = 2\r
306                         H2CSetPwrMode.Mode = 1;\r
307                         break;\r
308                 case PS_MODE_UAPSD_WMM:\r
309                         H2CSetPwrMode.Mode = 2;\r
310                         break;\r
311                 default:\r
312                         H2CSetPwrMode.Mode = 0;\r
313                         break;\r
314         }\r
315 \r
316         //H2CSetPwrMode.Mode = Mode;\r
317 \r
318         H2CSetPwrMode.SmartPS_RLBM = (((pwrpriv->smart_ps<<4)&0xf0) | (RLBM & 0x0f));\r
319 \r
320         H2CSetPwrMode.bAllQueueUAPSD = padapter->registrypriv.uapsd_enable;\r
321 \r
322         if(Mode > 0)\r
323         {\r
324                 H2CSetPwrMode.PwrState = 0x00;// AllON(0x0C), RFON(0x04), RFOFF(0x00)\r
325 #ifdef CONFIG_EXT_CLK\r
326                 H2CSetPwrMode.Mode |= BIT(7);//supporting 26M XTAL CLK_Request feature.\r
327 #endif //CONFIG_EXT_CLK\r
328         }\r
329         else\r
330                 H2CSetPwrMode.PwrState = 0x0C;// AllON(0x0C), RFON(0x04), RFOFF(0x00)\r
331 \r
332         FillH2CCmd_88E(padapter, H2C_PS_PWR_MODE, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);\r
333         \r
334 \r
335 _func_exit_;\r
336 }\r
337 \r
338 void rtl8188e_set_FwMediaStatus_cmd(PADAPTER padapter, u16 mstatus_rpt )\r
339 {\r
340         u8 opmode,macid;\r
341         u16 mst_rpt = cpu_to_le16 (mstatus_rpt);\r
342         u32 reg_macid_no_link = REG_MACID_NO_LINK_0;\r
343         opmode = (u8) mst_rpt;\r
344         macid = (u8)(mst_rpt >> 8)  ;\r
345         DBG_871X("### %s: MStatus=%x MACID=%d \n", __FUNCTION__,opmode,macid);\r
346         FillH2CCmd_88E(padapter, H2C_COM_MEDIA_STATUS_RPT, sizeof(mst_rpt), (u8 *)&mst_rpt);    \r
347 \r
348         if(macid > 31){\r
349                 macid = macid-32;\r
350                 reg_macid_no_link = REG_MACID_NO_LINK_1;\r
351         }\r
352         \r
353         //Delete select macid (MACID 0~63) from queue list.\r
354         if(opmode == 1)// 1:connect\r
355         {\r
356                 rtw_write32(padapter,reg_macid_no_link, (rtw_read32(padapter,reg_macid_no_link) & (~BIT(macid))));\r
357         }\r
358         else//0: disconnect\r
359         {\r
360                 rtw_write32(padapter,reg_macid_no_link, (rtw_read32(padapter,reg_macid_no_link)|BIT(macid)));\r
361         }\r
362         \r
363         \r
364         \r
365 }\r
366 \r
367 void ConstructBeacon(_adapter *padapter, u8 *pframe, u32 *pLength)\r
368 {\r
369         struct rtw_ieee80211_hdr        *pwlanhdr;\r
370         u16                                     *fctrl;\r
371         u32                                     rate_len, pktlen;\r
372         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
373         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
374         WLAN_BSSID_EX           *cur_network = &(pmlmeinfo->network);\r
375         u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
376 \r
377 \r
378         //DBG_871X("%s\n", __FUNCTION__);\r
379 \r
380         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;\r
381 \r
382         fctrl = &(pwlanhdr->frame_ctl);\r
383         *(fctrl) = 0;\r
384 \r
385         _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);\r
386         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
387         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);\r
388 \r
389         SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);\r
390         //pmlmeext->mgnt_seq++;\r
391         SetFrameSubType(pframe, WIFI_BEACON);\r
392 \r
393         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);\r
394         pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);\r
395 \r
396         //timestamp will be inserted by hardware\r
397         pframe += 8;\r
398         pktlen += 8;\r
399 \r
400         // beacon interval: 2 bytes\r
401         _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);\r
402 \r
403         pframe += 2;\r
404         pktlen += 2;\r
405 \r
406         // capability info: 2 bytes\r
407         _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);\r
408 \r
409         pframe += 2;\r
410         pktlen += 2;\r
411 \r
412         if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)\r
413         {\r
414                 //DBG_871X("ie len=%d\n", cur_network->IELength);\r
415                 pktlen += cur_network->IELength - sizeof(NDIS_802_11_FIXED_IEs);\r
416                 _rtw_memcpy(pframe, cur_network->IEs+sizeof(NDIS_802_11_FIXED_IEs), pktlen);\r
417 \r
418                 goto _ConstructBeacon;\r
419         }\r
420 \r
421         //below for ad-hoc mode\r
422 \r
423         // SSID\r
424         pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);\r
425 \r
426         // supported rates...\r
427         rate_len = rtw_get_rateset_len(cur_network->SupportedRates);\r
428         pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pktlen);\r
429 \r
430         // DS parameter set\r
431         pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);\r
432 \r
433         if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)\r
434         {\r
435                 u32 ATIMWindow;\r
436                 // IBSS Parameter Set...\r
437                 //ATIMWindow = cur->Configuration.ATIMWindow;\r
438                 ATIMWindow = 0;\r
439                 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);\r
440         }\r
441 \r
442 \r
443         //todo: ERP IE\r
444 \r
445 \r
446         // EXTERNDED SUPPORTED RATE\r
447         if (rate_len > 8)\r
448         {\r
449                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);\r
450         }\r
451 \r
452 \r
453         //todo:HT for adhoc\r
454 \r
455 _ConstructBeacon:\r
456 \r
457         if ((pktlen + TXDESC_SIZE) > 512)\r
458         {\r
459                 DBG_871X("beacon frame too large\n");\r
460                 return;\r
461         }\r
462 \r
463         *pLength = pktlen;\r
464 \r
465         //DBG_871X("%s bcn_sz=%d\n", __FUNCTION__, pktlen);\r
466 \r
467 }\r
468 \r
469 void ConstructPSPoll(_adapter *padapter, u8 *pframe, u32 *pLength)\r
470 {\r
471         struct rtw_ieee80211_hdr        *pwlanhdr;\r
472         u16                                     *fctrl;\r
473         u32                                     pktlen;\r
474         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
475         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
476 \r
477         //DBG_871X("%s\n", __FUNCTION__);\r
478 \r
479         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;\r
480 \r
481         // Frame control.\r
482         fctrl = &(pwlanhdr->frame_ctl);\r
483         *(fctrl) = 0;\r
484         SetPwrMgt(fctrl);\r
485         SetFrameSubType(pframe, WIFI_PSPOLL);\r
486 \r
487         // AID.\r
488         SetDuration(pframe, (pmlmeinfo->aid | 0xc000));\r
489 \r
490         // BSSID.\r
491         _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);\r
492 \r
493         // TA.\r
494         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
495 \r
496         *pLength = 16;\r
497 }\r
498 \r
499 void ConstructNullFunctionData(\r
500         PADAPTER padapter,\r
501         u8              *pframe,\r
502         u32             *pLength,\r
503         u8              *StaAddr,\r
504         u8              bQoS,\r
505         u8              AC,\r
506         u8              bEosp,\r
507         u8              bForcePowerSave)\r
508 {\r
509         struct rtw_ieee80211_hdr        *pwlanhdr;\r
510         u16                                             *fctrl;\r
511         u32                                             pktlen;\r
512         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;\r
513         struct wlan_network             *cur_network = &pmlmepriv->cur_network;\r
514         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
515         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
516 \r
517 \r
518         //DBG_871X("%s:%d\n", __FUNCTION__, bForcePowerSave);\r
519 \r
520         pwlanhdr = (struct rtw_ieee80211_hdr*)pframe;\r
521 \r
522         fctrl = &pwlanhdr->frame_ctl;\r
523         *(fctrl) = 0;\r
524         if (bForcePowerSave)\r
525         {\r
526                 SetPwrMgt(fctrl);\r
527         }\r
528 \r
529         switch(cur_network->network.InfrastructureMode)\r
530         {\r
531                 case Ndis802_11Infrastructure:\r
532                         SetToDs(fctrl);\r
533                         _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);\r
534                         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
535                         _rtw_memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);\r
536                         break;\r
537                 case Ndis802_11APMode:\r
538                         SetFrDs(fctrl);\r
539                         _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);\r
540                         _rtw_memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);\r
541                         _rtw_memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
542                         break;\r
543                 case Ndis802_11IBSS:\r
544                 default:\r
545                         _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);\r
546                         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
547                         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);\r
548                         break;\r
549         }\r
550 \r
551         SetSeqNum(pwlanhdr, 0);\r
552 \r
553         if (bQoS == _TRUE) {\r
554                 struct rtw_ieee80211_hdr_3addr_qos *pwlanqoshdr;\r
555 \r
556                 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);\r
557 \r
558                 pwlanqoshdr = (struct rtw_ieee80211_hdr_3addr_qos*)pframe;\r
559                 SetPriority(&pwlanqoshdr->qc, AC);\r
560                 SetEOSP(&pwlanqoshdr->qc, bEosp);\r
561 \r
562                 pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);\r
563         } else {\r
564                 SetFrameSubType(pframe, WIFI_DATA_NULL);\r
565 \r
566                 pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);\r
567         }\r
568 \r
569         *pLength = pktlen;\r
570 }\r
571 \r
572 #ifdef CONFIG_WOWLAN\r
573 //\r
574 // Description:\r
575 //      Construct the ARP response packet to support ARP offload.\r
576 //\r
577 static void ConstructARPResponse(\r
578         PADAPTER padapter,\r
579         u8                      *pframe,\r
580         u32                     *pLength,\r
581         u8                      *pIPAddress\r
582         )\r
583 {\r
584         struct rtw_ieee80211_hdr        *pwlanhdr;\r
585         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;\r
586         struct wlan_network             *cur_network = &pmlmepriv->cur_network;\r
587         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
588         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
589         struct security_priv    *psecuritypriv = &padapter->securitypriv;\r
590         static u8                               ARPLLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06};\r
591 \r
592         u16             *fctrl;\r
593         u32             pktlen;\r
594         u8              *pARPRspPkt = pframe;\r
595         //for TKIP Cal MIC\r
596         u8              *payload = pframe;\r
597         u8              EncryptionHeadOverhead = 0;\r
598 \r
599         pwlanhdr = (struct rtw_ieee80211_hdr*)pframe;\r
600 \r
601         fctrl = &pwlanhdr->frame_ctl;\r
602         *(fctrl) = 0;\r
603 \r
604         //-------------------------------------------------------------------------\r
605         // MAC Header.\r
606         //-------------------------------------------------------------------------\r
607         SetFrameType(fctrl, WIFI_DATA);\r
608         //SetFrameSubType(fctrl, 0);\r
609         SetToDs(fctrl);\r
610         _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);\r
611         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
612         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);\r
613 \r
614         SetSeqNum(pwlanhdr, 0);\r
615         SetDuration(pwlanhdr, 0);\r
616         //SET_80211_HDR_FRAME_CONTROL(pARPRspPkt, 0);\r
617         //SET_80211_HDR_TYPE_AND_SUBTYPE(pARPRspPkt, Type_Data);\r
618         //SET_80211_HDR_TO_DS(pARPRspPkt, 1);\r
619         //SET_80211_HDR_ADDRESS1(pARPRspPkt, pMgntInfo->Bssid);\r
620         //SET_80211_HDR_ADDRESS2(pARPRspPkt, Adapter->CurrentAddress);\r
621         //SET_80211_HDR_ADDRESS3(pARPRspPkt, pMgntInfo->Bssid);\r
622 \r
623         //SET_80211_HDR_DURATION(pARPRspPkt, 0);\r
624         //SET_80211_HDR_FRAGMENT_SEQUENCE(pARPRspPkt, 0);\r
625 #ifdef CONFIG_WAPI_SUPPORT\r
626         *pLength = sMacHdrLng;\r
627 #else\r
628         *pLength = 24;\r
629 #endif\r
630 \r
631 \r
632 //YJ,del,120503\r
633 #if 0\r
634         //-------------------------------------------------------------------------\r
635         // Qos Header: leave space for it if necessary.\r
636         //-------------------------------------------------------------------------\r
637         if(pStaQos->CurrentQosMode > QOS_DISABLE)\r
638         {\r
639                 SET_80211_HDR_QOS_EN(pARPRspPkt, 1);\r
640                 PlatformZeroMemory(&(Buffer[*pLength]), sQoSCtlLng);\r
641                 *pLength += sQoSCtlLng;\r
642         }\r
643 #endif\r
644         //-------------------------------------------------------------------------\r
645         // Security Header: leave space for it if necessary.\r
646         //-------------------------------------------------------------------------\r
647 \r
648         switch (psecuritypriv->dot11PrivacyAlgrthm)\r
649         {\r
650                 case _WEP40_:\r
651                 case _WEP104_:\r
652                         EncryptionHeadOverhead = 4;\r
653                         break;\r
654                 case _TKIP_:\r
655                         EncryptionHeadOverhead = 8;\r
656                         break;\r
657                 case _AES_:\r
658                         EncryptionHeadOverhead = 8;\r
659                         break;\r
660 #ifdef CONFIG_WAPI_SUPPORT\r
661                 case _SMS4_:\r
662                         EncryptionHeadOverhead = 18;\r
663                         break;\r
664 #endif\r
665                 default:\r
666                         EncryptionHeadOverhead = 0;\r
667         }\r
668 \r
669         if(EncryptionHeadOverhead > 0)\r
670         {\r
671                 _rtw_memset(&(pframe[*pLength]), 0,EncryptionHeadOverhead);\r
672                 *pLength += EncryptionHeadOverhead;\r
673                 //SET_80211_HDR_WEP(pARPRspPkt, 1);  //Suggested by CCW.\r
674                 SetPrivacy(fctrl);\r
675         }\r
676 \r
677         //-------------------------------------------------------------------------\r
678         // Frame Body.\r
679         //-------------------------------------------------------------------------\r
680         pARPRspPkt =  (u8*)(pframe+ *pLength);\r
681         // LLC header\r
682         _rtw_memcpy(pARPRspPkt, ARPLLCHeader, 8);\r
683         *pLength += 8;\r
684 \r
685         // ARP element\r
686         pARPRspPkt += 8;\r
687         SET_ARP_PKT_HW(pARPRspPkt, 0x0100);\r
688         SET_ARP_PKT_PROTOCOL(pARPRspPkt, 0x0008);       // IP protocol\r
689         SET_ARP_PKT_HW_ADDR_LEN(pARPRspPkt, 6);\r
690         SET_ARP_PKT_PROTOCOL_ADDR_LEN(pARPRspPkt, 4);\r
691         SET_ARP_PKT_OPERATION(pARPRspPkt, 0x0200); // ARP response\r
692         SET_ARP_PKT_SENDER_MAC_ADDR(pARPRspPkt, myid(&(padapter->eeprompriv)));\r
693         SET_ARP_PKT_SENDER_IP_ADDR(pARPRspPkt, pIPAddress);\r
694         #ifdef CONFIG_ARP_KEEP_ALIVE\r
695         if (rtw_gw_addr_query(padapter)==0) {\r
696                 SET_ARP_PKT_TARGET_MAC_ADDR(pARPRspPkt, pmlmepriv->gw_mac_addr);\r
697                 SET_ARP_PKT_TARGET_IP_ADDR(pARPRspPkt, pmlmepriv->gw_ip);\r
698         }\r
699         else\r
700 #endif\r
701         {\r
702                 SET_ARP_PKT_TARGET_MAC_ADDR(pARPRspPkt, get_my_bssid(&(pmlmeinfo->network)));\r
703                 SET_ARP_PKT_TARGET_IP_ADDR(pARPRspPkt, pIPAddress);\r
704                 DBG_871X("%s Target Mac Addr:" MAC_FMT "\n", __FUNCTION__, MAC_ARG(get_my_bssid(&(pmlmeinfo->network))));\r
705                 DBG_871X("%s Target IP Addr" IP_FMT "\n", __FUNCTION__, IP_ARG(pIPAddress));\r
706         }\r
707         *pLength += 28;\r
708         if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_)\r
709         {\r
710                 u8      mic[8];\r
711                 struct mic_data micdata;\r
712                 struct sta_info *psta = NULL;\r
713                 u8      priority[4]={0x0,0x0,0x0,0x0};\r
714                 u8      null_key[16]={0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};\r
715 \r
716                 DBG_871X("%s(): Add MIC\n",__FUNCTION__);\r
717 \r
718                 psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(&(pmlmeinfo->network)));\r
719                 if (psta != NULL) {\r
720                         if(_rtw_memcmp(&psta->dot11tkiptxmickey.skey[0],null_key, 16)==_TRUE){\r
721                                 DBG_871X("%s(): STA dot11tkiptxmickey==0\n",__FUNCTION__);\r
722                         }\r
723                         //start to calculate the mic code\r
724                         rtw_secmicsetkey(&micdata, &psta->dot11tkiptxmickey.skey[0]);\r
725                 }\r
726 \r
727                 rtw_secmicappend(&micdata, pwlanhdr->addr3, 6);  //DA\r
728 \r
729                 rtw_secmicappend(&micdata, pwlanhdr->addr2, 6); //SA\r
730 \r
731                 priority[0]=0;\r
732                 rtw_secmicappend(&micdata, &priority[0], 4);\r
733 \r
734                 rtw_secmicappend(&micdata, payload, 36); //payload length = 8 + 28\r
735 \r
736                 rtw_secgetmic(&micdata,&(mic[0]));\r
737 \r
738                 pARPRspPkt += 28;\r
739                 _rtw_memcpy(pARPRspPkt, &(mic[0]),8);\r
740 \r
741                 *pLength += 8;\r
742         }\r
743 }\r
744 #endif\r
745 \r
746 void ConstructProbeRsp(_adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, BOOLEAN bHideSSID)\r
747 {\r
748         struct rtw_ieee80211_hdr        *pwlanhdr;\r
749         u16                                     *fctrl;\r
750         u8                                      *mac, *bssid;\r
751         u32                                     pktlen;\r
752         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
753         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
754         WLAN_BSSID_EX           *cur_network = &(pmlmeinfo->network);\r
755 \r
756 \r
757         //DBG_871X("%s\n", __FUNCTION__);\r
758 \r
759         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;\r
760 \r
761         mac = myid(&(padapter->eeprompriv));\r
762         bssid = cur_network->MacAddress;\r
763 \r
764         fctrl = &(pwlanhdr->frame_ctl);\r
765         *(fctrl) = 0;\r
766         _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);\r
767         _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);\r
768         _rtw_memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);\r
769 \r
770         SetSeqNum(pwlanhdr, 0);\r
771         SetFrameSubType(fctrl, WIFI_PROBERSP);\r
772 \r
773         pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);\r
774         pframe += pktlen;\r
775 \r
776         if(cur_network->IELength>MAX_IE_SZ)\r
777                 return;\r
778 \r
779         _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);\r
780         pframe += cur_network->IELength;\r
781         pktlen += cur_network->IELength;\r
782 \r
783         *pLength = pktlen;\r
784 }\r
785 \r
786 void rtl8188e_set_FwRsvdPage_cmd(PADAPTER padapter, PRSVDPAGE_LOC rsvdpageloc)\r
787 {\r
788     u8 u1H2CRsvdPageParm[H2C_RSVDPAGE_LOC_LEN]={0};\r
789     u8 u1H2CAoacRsvdPageParm[H2C_AOAC_RSVDPAGE_LOC_LEN]={0};\r
790 \r
791     //DBG_871X("8188RsvdPageLoc: PsPoll=%d Null=%d QoSNull=%d\n", \r
792         //      rsvdpageloc->LocPsPoll, rsvdpageloc->LocNullData, rsvdpageloc->LocQosNull);\r
793 \r
794     SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1H2CRsvdPageParm, rsvdpageloc->LocPsPoll);\r
795     SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocNullData);\r
796     SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocQosNull);\r
797     \r
798     FillH2CCmd_88E(padapter, H2C_COM_RSVD_PAGE, H2C_RSVDPAGE_LOC_LEN, u1H2CRsvdPageParm);\r
799 \r
800 #ifdef CONFIG_WOWLAN    \r
801     //DBG_871X("8188E_AOACRsvdPageLoc: RWC=%d ArpRsp=%d\n", rsvdpageloc->LocRemoteCtrlInfo, rsvdpageloc->LocArpRsp);\r
802     SET_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1H2CAoacRsvdPageParm, rsvdpageloc->LocRemoteCtrlInfo);\r
803     SET_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1H2CAoacRsvdPageParm, rsvdpageloc->LocArpRsp);\r
804 \r
805     FillH2CCmd_88E(padapter, H2C_COM_AOAC_RSVD_PAGE, H2C_AOAC_RSVDPAGE_LOC_LEN, u1H2CAoacRsvdPageParm);\r
806 #endif\r
807 }\r
808 \r
809 // To check if reserved page content is destroyed by beacon beacuse beacon is too large.\r
810 // 2010.06.23. Added by tynli.\r
811 VOID\r
812 CheckFwRsvdPageContent(\r
813         IN      PADAPTER                Adapter\r
814 )\r
815 {\r
816         HAL_DATA_TYPE*  pHalData = GET_HAL_DATA(Adapter);\r
817         u32     MaxBcnPageNum;\r
818 \r
819         if(pHalData->FwRsvdPageStartOffset != 0)\r
820         {\r
821                 /*MaxBcnPageNum = PageNum_128(pMgntInfo->MaxBeaconSize);\r
822                 RT_ASSERT((MaxBcnPageNum <= pHalData->FwRsvdPageStartOffset),\r
823                         ("CheckFwRsvdPageContent(): The reserved page content has been"\\r
824                         "destroyed by beacon!!! MaxBcnPageNum(%d) FwRsvdPageStartOffset(%d)\n!",\r
825                         MaxBcnPageNum, pHalData->FwRsvdPageStartOffset));*/\r
826         }\r
827 }\r
828 \r
829 //\r
830 // Description: Fill the reserved packets that FW will use to RSVD page.\r
831 //                      Now we just send 4 types packet to rsvd page.\r
832 //                      (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp.\r
833 //      Input:\r
834 //          bDLFinished - FALSE: At the first time we will send all the packets as a large packet to Hw,\r
835 //                                              so we need to set the packet length to total lengh.\r
836 //                            TRUE: At the second time, we should send the first packet (default:beacon)\r
837 //                                              to Hw again and set the lengh in descriptor to the real beacon lengh.\r
838 // 2009.10.15 by tynli.\r
839 static void SetFwRsvdPagePkt(PADAPTER padapter, BOOLEAN bDLFinished)\r
840 {\r
841         PHAL_DATA_TYPE pHalData;\r
842         struct xmit_frame       *pcmdframe;\r
843         struct pkt_attrib       *pattrib;\r
844         struct xmit_priv        *pxmitpriv;\r
845         struct mlme_ext_priv    *pmlmeext;\r
846         struct mlme_ext_info    *pmlmeinfo;\r
847         u32     BeaconLength, ProbeRspLength, PSPollLength;\r
848         u32     NullDataLength, QosNullLength, BTQosNullLength;\r
849         u8      *ReservedPagePacket;\r
850         u8      RsvdPageNum = 0;\r
851         u8      PageNum, PageNeed, TxDescLen;\r
852         u16     BufIndex, PageSize = 128;\r
853         u32     TotalPacketLen, MaxRsvdPageBufSize=0;\r
854         RSVDPAGE_LOC    RsvdPageLoc;\r
855 #ifdef CONFIG_WOWLAN\r
856         u32     ARPLegnth = 0;\r
857         struct security_priv *psecuritypriv = &padapter->securitypriv; //added by xx\r
858         u8 currentip[4];\r
859         u8 cur_dot11txpn[8];\r
860 #endif\r
861 \r
862         DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));\r
863 \r
864 #ifdef CONFIG_WOWLAN\r
865         RsvdPageNum = BCNQ_PAGE_NUM_88E + WOWLAN_PAGE_NUM_88E;\r
866 #else\r
867         RsvdPageNum = BCNQ_PAGE_NUM_88E;\r
868 #endif\r
869         printk("RsvdPageNum: %d\n", RsvdPageNum);\r
870 \r
871         MaxRsvdPageBufSize = RsvdPageNum*PageSize;\r
872 \r
873         ReservedPagePacket = (u8*)rtw_zmalloc(MaxRsvdPageBufSize);\r
874 \r
875         if (ReservedPagePacket == NULL) {\r
876                 DBG_871X("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);\r
877         }\r
878 \r
879         pHalData = GET_HAL_DATA(padapter);\r
880         pxmitpriv = &padapter->xmitpriv;\r
881         pmlmeext = &padapter->mlmeextpriv;\r
882         pmlmeinfo = &pmlmeext->mlmext_info;\r
883 \r
884         TxDescLen = TXDESC_SIZE;\r
885         PageNum = 0;\r
886 \r
887         //3 (1) beacon * 2 pages\r
888         BufIndex = TXDESC_OFFSET;\r
889         ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);\r
890 \r
891         // When we count the first page size, we need to reserve description size for the RSVD\r
892         // packet, it will be filled in front of the packet in TXPKTBUF.\r
893         PageNeed = (u8)PageNum_128(TxDescLen + BeaconLength);\r
894         // To reserved 2 pages for beacon buffer. 2010.06.24.\r
895         if (PageNeed == 1)\r
896                 PageNeed += 1;\r
897         PageNum += PageNeed;\r
898         pHalData->FwRsvdPageStartOffset = PageNum;\r
899 \r
900         BufIndex += PageNeed * PageSize;\r
901 \r
902         //3 (2) ps-poll *1 page\r
903         RsvdPageLoc.LocPsPoll = PageNum;\r
904         ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);\r
905         rtl8188e_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, _TRUE, _FALSE);\r
906 \r
907         PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);\r
908         PageNum += PageNeed;\r
909 \r
910         BufIndex += PageNeed * PageSize;\r
911 \r
912         //3 (3) null data * 1 page\r
913         RsvdPageLoc.LocNullData = PageNum;\r
914         ConstructNullFunctionData(\r
915                 padapter,\r
916                 &ReservedPagePacket[BufIndex],\r
917                 &NullDataLength,\r
918                 get_my_bssid(&pmlmeinfo->network),\r
919                 _FALSE, 0, 0, _FALSE);\r
920         rtl8188e_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, _FALSE, _FALSE);\r
921 \r
922         PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);\r
923         PageNum += PageNeed;\r
924 \r
925         BufIndex += PageNeed * PageSize;\r
926 \r
927         //3 (5) Qos null data\r
928         RsvdPageLoc.LocQosNull = PageNum;\r
929         ConstructNullFunctionData(\r
930                 padapter,\r
931                 &ReservedPagePacket[BufIndex],\r
932                 &QosNullLength,\r
933                 get_my_bssid(&pmlmeinfo->network),\r
934                 _TRUE, 0, 0, _FALSE);\r
935         rtl8188e_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, _FALSE, _FALSE);\r
936 \r
937         PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);\r
938         PageNum += PageNeed;\r
939 \r
940         BufIndex += PageNeed * PageSize;\r
941 \r
942 /*\r
943         //3 (6) BT Qos null data\r
944         RsvdPageLoc.LocBTQosNull = PageNum;\r
945         ConstructNullFunctionData(\r
946                 padapter, \r
947                 &ReservedPagePacket[BufIndex],\r
948                 &BTQosNullLength,\r
949                 get_my_bssid(&pmlmeinfo->network),\r
950                 _TRUE, 0, 0, _FALSE);\r
951         rtl8188e_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, _FALSE, _TRUE);\r
952 \r
953         TotalPacketLen = BufIndex + BTQosNullLength;\r
954 */\r
955 \r
956 #ifdef CONFIG_WOWLAN\r
957         //3(7) ARP\r
958         rtw_get_current_ip_address(padapter, currentip);\r
959         RsvdPageLoc.LocArpRsp = PageNum;\r
960         ConstructARPResponse(\r
961                 padapter,\r
962                 &ReservedPagePacket[BufIndex],\r
963                 &ARPLegnth,\r
964                 currentip\r
965                 );\r
966         rtl8188e_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], ARPLegnth, _FALSE, _FALSE);\r
967 \r
968         PageNeed = (u8)PageNum_128(TxDescLen + ARPLegnth);\r
969         PageNum += PageNeed;\r
970 \r
971         BufIndex += PageNeed * PageSize;\r
972 \r
973         //3(8) sec IV\r
974         rtw_get_sec_iv(padapter, cur_dot11txpn, get_my_bssid(&pmlmeinfo->network));\r
975         RsvdPageLoc.LocRemoteCtrlInfo = PageNum;\r
976         _rtw_memcpy(ReservedPagePacket+BufIndex-TxDescLen, cur_dot11txpn, 8);\r
977 \r
978         TotalPacketLen = BufIndex-TxDescLen + sizeof (union pn48); //IV len\r
979 #else\r
980         TotalPacketLen = BufIndex + QosNullLength;\r
981 #endif\r
982 \r
983         pcmdframe = alloc_mgtxmitframe(pxmitpriv);\r
984         if (pcmdframe == NULL)\r
985                 goto exit;\r
986 \r
987         // update attribute\r
988         pattrib = &pcmdframe->attrib;\r
989         update_mgntframe_attrib(padapter, pattrib);\r
990         pattrib->qsel = 0x10;\r
991         pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;\r
992 \r
993         if (TotalPacketLen < MaxRsvdPageBufSize)\r
994                 _rtw_memcpy(pcmdframe->buf_addr, ReservedPagePacket, TotalPacketLen);\r
995         else\r
996                 DBG_871X("%s: memory copy fail at Line:%d\n", __FUNCTION__, __LINE__);\r
997 \r
998         rtw_hal_mgnt_xmit(padapter, pcmdframe);\r
999 \r
1000         DBG_871X("%s: Set RSVD page location to Fw ,TotalPacketLen(%d)\n", __FUNCTION__,TotalPacketLen);\r
1001         rtl8188e_set_FwRsvdPage_cmd(padapter, &RsvdPageLoc);\r
1002 exit:\r
1003         rtw_mfree(ReservedPagePacket, MaxRsvdPageBufSize);\r
1004 }\r
1005 \r
1006 void rtl8188e_set_FwJoinBssReport_cmd(PADAPTER padapter, u8 mstatus)\r
1007 {\r
1008         JOINBSSRPT_PARM_88E     JoinBssRptParm;\r
1009         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);\r
1010         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
1011         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
1012 #ifdef CONFIG_WOWLAN\r
1013         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;\r
1014         struct sta_info *psta = NULL;\r
1015 #endif\r
1016         BOOLEAN         bSendBeacon=_FALSE;\r
1017         BOOLEAN         bcn_valid = _FALSE;\r
1018         u8      DLBcnCount=0;\r
1019         u32 poll = 0;\r
1020 \r
1021 _func_enter_;\r
1022 \r
1023         DBG_871X("%s mstatus(%x)\n", __FUNCTION__,mstatus);\r
1024 \r
1025         if(mstatus == 1)\r
1026         {\r
1027                 // We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C.\r
1028                 // Suggested by filen. Added by tynli.\r
1029                 rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));\r
1030                 // Do not set TSF again here or vWiFi beacon DMA INT will not work.\r
1031                 //correct_TSF(padapter, pmlmeext);\r
1032                 // Hw sequende enable by dedault. 2010.06.23. by tynli.\r
1033                 //rtw_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF));\r
1034                 //rtw_write8(padapter, REG_HWSEQ_CTRL, 0xFF);\r
1035 \r
1036                 //Set REG_CR bit 8. DMA beacon by SW.\r
1037                 pHalData->RegCR_1 |= BIT0;\r
1038                 rtw_write8(padapter,  REG_CR+1, pHalData->RegCR_1);\r
1039 \r
1040                 // Disable Hw protection for a time which revserd for Hw sending beacon.\r
1041                 // Fix download reserved page packet fail that access collision with the protection time.\r
1042                 // 2010.05.11. Added by tynli.\r
1043                 //SetBcnCtrlReg(padapter, 0, BIT3);\r
1044                 //SetBcnCtrlReg(padapter, BIT4, 0);\r
1045                 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)&(~BIT(3)));\r
1046                 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)|BIT(4));\r
1047 \r
1048                 if(pHalData->RegFwHwTxQCtrl&BIT6)\r
1049                 {\r
1050                         DBG_871X("HalDownloadRSVDPage(): There is an Adapter is sending beacon.\n");\r
1051                         bSendBeacon = _TRUE;\r
1052                 }\r
1053 \r
1054                 // Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.\r
1055                 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, (pHalData->RegFwHwTxQCtrl&(~BIT6)));\r
1056                 pHalData->RegFwHwTxQCtrl &= (~BIT6);\r
1057 \r
1058                 // Clear beacon valid check bit.\r
1059                 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);\r
1060                 DLBcnCount = 0;\r
1061                 poll = 0;\r
1062                 do\r
1063                 {\r
1064                         // download rsvd page.\r
1065                         SetFwRsvdPagePkt(padapter, _FALSE);\r
1066                         DLBcnCount++;\r
1067                         do\r
1068                         {\r
1069                                 rtw_yield_os();\r
1070                                 //rtw_mdelay_os(10);\r
1071                                 // check rsvd page download OK.\r
1072                                 rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8*)(&bcn_valid));\r
1073                                 poll++;\r
1074                         } while(!bcn_valid && (poll%10)!=0 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);\r
1075                         \r
1076                 }while(!bcn_valid && DLBcnCount<=100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);\r
1077                 \r
1078                 //RT_ASSERT(bcn_valid, ("HalDownloadRSVDPage88ES(): 1 Download RSVD page failed!\n"));\r
1079                 if(padapter->bSurpriseRemoved || padapter->bDriverStopped)\r
1080                 {\r
1081                 }\r
1082                 else if(!bcn_valid)\r
1083                         DBG_871X(ADPT_FMT": 1 DL RSVD page failed! DLBcnCount:%u, poll:%u\n",\r
1084                                 ADPT_ARG(padapter) ,DLBcnCount, poll);\r
1085                 else {\r
1086                         struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);\r
1087                         pwrctl->fw_psmode_iface_id = padapter->iface_id;\r
1088                         DBG_871X(ADPT_FMT": 1 DL RSVD page success! DLBcnCount:%u, poll:%u\n",\r
1089                                 ADPT_ARG(padapter), DLBcnCount, poll);\r
1090                 }\r
1091                 //\r
1092                 // We just can send the reserved page twice during the time that Tx thread is stopped (e.g. pnpsetpower)\r
1093                 // becuase we need to free the Tx BCN Desc which is used by the first reserved page packet.\r
1094                 // At run time, we cannot get the Tx Desc until it is released in TxHandleInterrupt() so we will return\r
1095                 // the beacon TCB in the following code. 2011.11.23. by tynli.\r
1096                 //\r
1097                 //if(bcn_valid && padapter->bEnterPnpSleep)\r
1098                 if(0)\r
1099                 {\r
1100                         if(bSendBeacon)\r
1101                         {\r
1102                                 rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);\r
1103                                 DLBcnCount = 0;\r
1104                                 poll = 0;\r
1105                                 do\r
1106                                 {\r
1107                                         SetFwRsvdPagePkt(padapter, _TRUE);\r
1108                                         DLBcnCount++;\r
1109                                         \r
1110                                         do\r
1111                                         {\r
1112                                                 rtw_yield_os();\r
1113                                                 //rtw_mdelay_os(10);\r
1114                                                 // check rsvd page download OK.\r
1115                                                 rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8*)(&bcn_valid));\r
1116                                                 poll++;\r
1117                                         } while(!bcn_valid && (poll%10)!=0 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);\r
1118                                 }while(!bcn_valid && DLBcnCount<=100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);\r
1119                                 \r
1120                                 //RT_ASSERT(bcn_valid, ("HalDownloadRSVDPage(): 2 Download RSVD page failed!\n"));\r
1121                                 if(padapter->bSurpriseRemoved || padapter->bDriverStopped)\r
1122                                 {\r
1123                                 }\r
1124                                 else if(!bcn_valid)\r
1125                                         DBG_871X("%s: 2 Download RSVD page failed! DLBcnCount:%u, poll:%u\n", __FUNCTION__ ,DLBcnCount, poll);\r
1126                                 else\r
1127                                         DBG_871X("%s: 2 Download RSVD success! DLBcnCount:%u, poll:%u\n", __FUNCTION__, DLBcnCount, poll);\r
1128                         }\r
1129                 }\r
1130 \r
1131                 // Enable Bcn\r
1132                 //SetBcnCtrlReg(padapter, BIT3, 0);\r
1133                 //SetBcnCtrlReg(padapter, 0, BIT4);\r
1134                 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)|BIT(3));\r
1135                 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)&(~BIT(4)));\r
1136 \r
1137                 // To make sure that if there exists an adapter which would like to send beacon.\r
1138                 // If exists, the origianl value of 0x422[6] will be 1, we should check this to\r
1139                 // prevent from setting 0x422[6] to 0 after download reserved page, or it will cause \r
1140                 // the beacon cannot be sent by HW.\r
1141                 // 2010.06.23. Added by tynli.\r
1142                 if(bSendBeacon)\r
1143                 {\r
1144                         rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, (pHalData->RegFwHwTxQCtrl|BIT6));\r
1145                         pHalData->RegFwHwTxQCtrl |= BIT6;\r
1146                 }\r
1147 \r
1148                 //\r
1149                 // Update RSVD page location H2C to Fw.\r
1150                 //\r
1151                 if(bcn_valid)\r
1152                 {\r
1153                         rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);\r
1154                         DBG_871X("Set RSVD page location to Fw.\n");\r
1155                         //FillH2CCmd88E(Adapter, H2C_88E_RSVDPAGE, H2C_RSVDPAGE_LOC_LENGTH, pMgntInfo->u1RsvdPageLoc);\r
1156                 }\r
1157                 \r
1158                 // Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli.\r
1159                 //if(!padapter->bEnterPnpSleep)\r
1160                 {\r
1161                         // Clear CR[8] or beacon packet will not be send to TxBuf anymore.\r
1162                         pHalData->RegCR_1 &= (~BIT0);\r
1163                         rtw_write8(padapter,  REG_CR+1, pHalData->RegCR_1);\r
1164                 }\r
1165         }\r
1166 #ifdef CONFIG_WOWLAN\r
1167         if (adapter_to_pwrctl(padapter)->wowlan_mode){\r
1168                 JoinBssRptParm.OpMode = mstatus;\r
1169                 psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(pmlmepriv));\r
1170                 if (psta != NULL) {\r
1171                         JoinBssRptParm.MacID = psta->mac_id;\r
1172                 } else {\r
1173                         JoinBssRptParm.MacID = 0;\r
1174                 }\r
1175                 FillH2CCmd_88E(padapter, H2C_COM_MEDIA_STATUS_RPT, sizeof(JoinBssRptParm), (u8 *)&JoinBssRptParm);\r
1176                 DBG_871X_LEVEL(_drv_info_, "%s opmode:%d MacId:%d\n", __func__, JoinBssRptParm.OpMode, JoinBssRptParm.MacID);\r
1177         } else {\r
1178                 DBG_871X_LEVEL(_drv_info_, "%s wowlan_mode is off\n", __func__);\r
1179         }\r
1180 #endif //CONFIG_WOWLAN\r
1181 _func_exit_;\r
1182 }\r
1183 \r
1184 #ifdef CONFIG_P2P_PS\r
1185 void rtl8188e_set_p2p_ps_offload_cmd(_adapter* padapter, u8 p2p_ps_state)\r
1186 {\r
1187         HAL_DATA_TYPE   *pHalData = GET_HAL_DATA(padapter);\r
1188         struct pwrctrl_priv             *pwrpriv = adapter_to_pwrctl(padapter);\r
1189         struct wifidirect_info  *pwdinfo = &( padapter->wdinfo );\r
1190         struct P2P_PS_Offload_t *p2p_ps_offload = (struct P2P_PS_Offload_t      *)(&pHalData->p2p_ps_offload);\r
1191         u8      i;\r
1192 \r
1193 _func_enter_;\r
1194 \r
1195 #if 1\r
1196         switch(p2p_ps_state)\r
1197         {\r
1198                 case P2P_PS_DISABLE:\r
1199                         DBG_8192C("P2P_PS_DISABLE \n");\r
1200                         _rtw_memset(p2p_ps_offload, 0 ,1);\r
1201                         break;\r
1202                 case P2P_PS_ENABLE:\r
1203                         DBG_8192C("P2P_PS_ENABLE \n");\r
1204                         // update CTWindow value.\r
1205                         if( pwdinfo->ctwindow > 0 )\r
1206                         {\r
1207                                 p2p_ps_offload->CTWindow_En = 1;\r
1208                                 rtw_write8(padapter, REG_P2P_CTWIN, pwdinfo->ctwindow);\r
1209                         }\r
1210 \r
1211                         // hw only support 2 set of NoA\r
1212                         for( i=0 ; i<pwdinfo->noa_num ; i++)\r
1213                         {\r
1214                                 // To control the register setting for which NOA\r
1215                                 rtw_write8(padapter, REG_NOA_DESC_SEL, (i << 4));\r
1216                                 if(i == 0)\r
1217                                         p2p_ps_offload->NoA0_En = 1;\r
1218                                 else\r
1219                                         p2p_ps_offload->NoA1_En = 1;\r
1220 \r
1221                                 // config P2P NoA Descriptor Register\r
1222                                 //DBG_8192C("%s(): noa_duration = %x\n",__FUNCTION__,pwdinfo->noa_duration[i]);\r
1223                                 rtw_write32(padapter, REG_NOA_DESC_DURATION, pwdinfo->noa_duration[i]);\r
1224 \r
1225                                 //DBG_8192C("%s(): noa_interval = %x\n",__FUNCTION__,pwdinfo->noa_interval[i]);\r
1226                                 rtw_write32(padapter, REG_NOA_DESC_INTERVAL, pwdinfo->noa_interval[i]);\r
1227 \r
1228                                 //DBG_8192C("%s(): start_time = %x\n",__FUNCTION__,pwdinfo->noa_start_time[i]);\r
1229                                 rtw_write32(padapter, REG_NOA_DESC_START, pwdinfo->noa_start_time[i]);\r
1230 \r
1231                                 //DBG_8192C("%s(): noa_count = %x\n",__FUNCTION__,pwdinfo->noa_count[i]);\r
1232                                 rtw_write8(padapter, REG_NOA_DESC_COUNT, pwdinfo->noa_count[i]);\r
1233                         }\r
1234 \r
1235                         if( (pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0) )\r
1236                         {\r
1237                                 // rst p2p circuit\r
1238                                 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(4));\r
1239 \r
1240                                 p2p_ps_offload->Offload_En = 1;\r
1241 \r
1242                                 if(pwdinfo->role == P2P_ROLE_GO)\r
1243                                 {\r
1244                                         p2p_ps_offload->role= 1;\r
1245                                         p2p_ps_offload->AllStaSleep = 0;\r
1246                                 }\r
1247                                 else\r
1248                                 {\r
1249                                         p2p_ps_offload->role= 0;\r
1250                                 }\r
1251 \r
1252                                 p2p_ps_offload->discovery = 0;\r
1253                         }\r
1254                         break;\r
1255                 case P2P_PS_SCAN:\r
1256                         DBG_8192C("P2P_PS_SCAN \n");\r
1257                         p2p_ps_offload->discovery = 1;\r
1258                         break;\r
1259                 case P2P_PS_SCAN_DONE:\r
1260                         DBG_8192C("P2P_PS_SCAN_DONE \n");\r
1261                         p2p_ps_offload->discovery = 0;\r
1262                         pwdinfo->p2p_ps_state = P2P_PS_ENABLE;\r
1263                         break;\r
1264                 default:\r
1265                         break;\r
1266         }\r
1267 \r
1268         FillH2CCmd_88E(padapter, H2C_PS_P2P_OFFLOAD, 1, (u8 *)p2p_ps_offload);\r
1269 #endif\r
1270 \r
1271 _func_exit_;\r
1272 \r
1273 }\r
1274 #endif //CONFIG_P2P_PS\r
1275 \r
1276 #ifdef CONFIG_TSF_RESET_OFFLOAD\r
1277 /*\r
1278         ask FW to Reset sync register at Beacon early interrupt\r
1279 */\r
1280 u8 rtl8188e_reset_tsf(_adapter *padapter, u8 reset_port )\r
1281 {       \r
1282         u8      buf[2];\r
1283         u8      res=_SUCCESS;\r
1284 \r
1285         s32 ret;\r
1286 _func_enter_;\r
1287         if (IFACE_PORT0==reset_port) {\r
1288                 buf[0] = 0x1; buf[1] = 0;\r
1289         } else{\r
1290                 buf[0] = 0x0; buf[1] = 0x1;\r
1291         }\r
1292 \r
1293         ret = FillH2CCmd_88E(padapter, H2C_RESET_TSF, 2, buf);\r
1294 \r
1295 _func_exit_;\r
1296 \r
1297         return res;\r
1298 }\r
1299 \r
1300 int reset_tsf(PADAPTER Adapter, u8 reset_port )\r
1301 {\r
1302         u8 reset_cnt_before = 0, reset_cnt_after = 0, loop_cnt = 0;\r
1303         u32 reg_reset_tsf_cnt = (IFACE_PORT0==reset_port) ?\r
1304                                 REG_FW_RESET_TSF_CNT_0:REG_FW_RESET_TSF_CNT_1;\r
1305         u32 reg_bcncrtl = (IFACE_PORT0==reset_port) ?\r
1306                                 REG_BCN_CTRL_1:REG_BCN_CTRL;\r
1307 \r
1308         rtw_scan_abort(Adapter->pbuddy_adapter);        /*      site survey will cause reset_tsf fail   */\r
1309         reset_cnt_after = reset_cnt_before = rtw_read8(Adapter,reg_reset_tsf_cnt);\r
1310         rtl8188e_reset_tsf(Adapter, reset_port);\r
1311 \r
1312         while ((reset_cnt_after == reset_cnt_before ) && (loop_cnt < 10)) {\r
1313                 rtw_msleep_os(100);\r
1314                 loop_cnt++;\r
1315                 reset_cnt_after = rtw_read8(Adapter, reg_reset_tsf_cnt);\r
1316         }\r
1317 \r
1318         return(loop_cnt >= 10) ? _FAIL : _TRUE;\r
1319 }\r
1320 \r
1321 \r
1322 #endif  // CONFIG_TSF_RESET_OFFLOAD\r
1323 \r
1324 #ifdef CONFIG_WOWLAN\r
1325 #ifdef CONFIG_GPIO_WAKEUP\r
1326 void rtl8188es_set_output_gpio(_adapter* padapter, u8 index, u8 outputval)\r
1327 {\r
1328         if ( index <= 7 ) {\r
1329                 /* config GPIO mode */\r
1330                 rtw_write8(padapter, REG_GPIO_PIN_CTRL + 3, rtw_read8(padapter, REG_GPIO_PIN_CTRL + 3) & ~BIT(index) );\r
1331 \r
1332                 /* config GPIO Sel */\r
1333                 /* 0: input */\r
1334                 /* 1: output */\r
1335                 rtw_write8(padapter, REG_GPIO_PIN_CTRL + 2, rtw_read8(padapter, REG_GPIO_PIN_CTRL + 2) | BIT(index));\r
1336 \r
1337                 /* set output value */\r
1338                 if ( outputval ) {\r
1339                         rtw_write8(padapter, REG_GPIO_PIN_CTRL + 1, rtw_read8(padapter, REG_GPIO_PIN_CTRL + 1) | BIT(index));\r
1340                 } else {\r
1341                         rtw_write8(padapter, REG_GPIO_PIN_CTRL + 1, rtw_read8(padapter, REG_GPIO_PIN_CTRL + 1) & ~BIT(index));\r
1342                 }\r
1343         } else {\r
1344                 /* 88C Series: */\r
1345                 /* index: 11~8 transform to 3~0 */\r
1346                 /* 8723 Series: */\r
1347                 /* index: 12~8 transform to 4~0 */  \r
1348                 index -= 8;\r
1349 \r
1350                 /* config GPIO mode */\r
1351                 rtw_write8(padapter, REG_GPIO_PIN_CTRL_2 + 3, rtw_read8(padapter, REG_GPIO_PIN_CTRL_2 + 3) & ~BIT(index) );\r
1352 \r
1353                 /* config GPIO Sel */\r
1354                 /* 0: input */\r
1355                 /* 1: output */\r
1356                 rtw_write8(padapter, REG_GPIO_PIN_CTRL_2 + 2, rtw_read8(padapter, REG_GPIO_PIN_CTRL_2 + 2) | BIT(index));\r
1357 \r
1358                 /* set output value */\r
1359                 if ( outputval ) {\r
1360                         rtw_write8(padapter, REG_GPIO_PIN_CTRL_2 + 1, rtw_read8(padapter, REG_GPIO_PIN_CTRL_2 + 1) | BIT(index));\r
1361                 } else {\r
1362                         rtw_write8(padapter, REG_GPIO_PIN_CTRL_2 + 1, rtw_read8(padapter, REG_GPIO_PIN_CTRL_2 + 1) & ~BIT(index));\r
1363                 }\r
1364         }\r
1365 }\r
1366 #endif //CONFIG_GPIO_WAKEUP\r
1367 \r
1368 void rtl8188es_set_wowlan_cmd(_adapter* padapter, u8 enable)\r
1369 {\r
1370         u8              res=_SUCCESS;\r
1371         u32             test=0;\r
1372         struct recv_priv        *precvpriv = &padapter->recvpriv;\r
1373         SETWOWLAN_PARM          pwowlan_parm;\r
1374         SETAOAC_GLOBAL_INFO     paoac_global_info_parm;\r
1375         struct pwrctrl_priv     *pwrpriv = adapter_to_pwrctl(padapter);\r
1376         struct security_priv *psecpriv = &padapter->securitypriv;\r
1377 #ifdef CONFIG_GPIO_WAKEUP\r
1378         u8              gpio_wake_pin = 7;\r
1379         u8              gpio_high_active = 0;   //default low active\r
1380 #endif\r
1381 \r
1382 _func_enter_;\r
1383                 DBG_871X_LEVEL(_drv_always_, "+%s+\n", __func__);\r
1384 \r
1385                 pwowlan_parm.mode =0;\r
1386                 pwowlan_parm.gpio_index=0;\r
1387                 pwowlan_parm.gpio_duration=0;\r
1388                 pwowlan_parm.second_mode =0;\r
1389                 pwowlan_parm.reserve=0;\r
1390 \r
1391                 if(enable){\r
1392 \r
1393                         pwowlan_parm.mode |=FW_WOWLAN_FUN_EN;\r
1394                         pwrpriv->wowlan_magic =_TRUE;\r
1395                         if (psecpriv->dot11PrivacyAlgrthm == _WEP40_ || psecpriv->dot11PrivacyAlgrthm == _WEP104_)\r
1396                                 pwrpriv->wowlan_unicast =_TRUE;\r
1397 \r
1398                         if(pwrpriv->wowlan_pattern ==_TRUE){\r
1399                                 pwowlan_parm.mode |= FW_WOWLAN_PATTERN_MATCH;\r
1400                                 DBG_871X_LEVEL(_drv_info_, "%s 2.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );\r
1401                         }\r
1402                         if(pwrpriv->wowlan_magic ==_TRUE){\r
1403                                 pwowlan_parm.mode |=FW_WOWLAN_MAGIC_PKT;\r
1404                                 DBG_871X_LEVEL(_drv_info_, "%s 3.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );\r
1405                         }\r
1406                         if(pwrpriv->wowlan_unicast ==_TRUE){\r
1407                                 pwowlan_parm.mode |=FW_WOWLAN_UNICAST;\r
1408                                 DBG_871X_LEVEL(_drv_info_, "%s 4.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );\r
1409                         }\r
1410 \r
1411                         pwowlan_parm.mode |=FW_WOWLAN_REKEY_WAKEUP;\r
1412                         pwowlan_parm.mode |=FW_WOWLAN_DEAUTH_WAKEUP;\r
1413 \r
1414                         //DataPinWakeUp\r
1415 #ifdef CONFIG_USB_HCI\r
1416                         pwowlan_parm.gpio_index=0x0;\r
1417 #endif //CONFIG_USB_HCI\r
1418 \r
1419 #ifdef CONFIG_SDIO_HCI\r
1420                         pwowlan_parm.gpio_index = 0x80;\r
1421 #endif //CONFIG_SDIO_HCI\r
1422 \r
1423 #ifdef CONFIG_GPIO_WAKEUP\r
1424                         pwowlan_parm.gpio_index = gpio_wake_pin;\r
1425 \r
1426                         //WOWLAN_GPIO_ACTIVE means GPIO high active\r
1427                         //pwowlan_parm.mode |=FW_WOWLAN_GPIO_ACTIVE;\r
1428                         if (gpio_high_active)\r
1429                                 pwowlan_parm.mode |=FW_WOWLAN_GPIO_ACTIVE;\r
1430 #endif //CONFIG_GPIO_WAKEUP\r
1431 \r
1432                         DBG_871X_LEVEL(_drv_info_, "%s 5.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode);\r
1433                         DBG_871X_LEVEL(_drv_info_, "%s 6.pwowlan_parm.index=0x%x \n",__FUNCTION__,pwowlan_parm.gpio_index);\r
1434                         res = FillH2CCmd_88E(padapter, H2C_COM_WWLAN, 2, (u8 *)&pwowlan_parm);\r
1435 \r
1436                         rtw_msleep_os(2);\r
1437 \r
1438                         //disconnect decision\r
1439                         pwowlan_parm.mode =1;\r
1440                         pwowlan_parm.gpio_index=0;\r
1441                         pwowlan_parm.gpio_duration=0;\r
1442                         FillH2CCmd_88E(padapter, H2C_COM_DISCNT_DECISION, 3, (u8 *)&pwowlan_parm);\r
1443 \r
1444                         //keep alive period = 10 * 10 BCN interval\r
1445                         pwowlan_parm.mode = FW_WOWLAN_KEEP_ALIVE_EN | FW_ADOPT_USER | FW_WOWLAN_KEEP_ALIVE_PKT_TYPE;\r
1446                         pwowlan_parm.gpio_index = 5;\r
1447                         res = FillH2CCmd_88E(padapter, H2C_COM_KEEP_ALIVE, 2, (u8 *)&pwowlan_parm);\r
1448 \r
1449                         rtw_msleep_os(2);\r
1450                         //Configure STA security information for GTK rekey wakeup event.\r
1451                         paoac_global_info_parm.pairwiseEncAlg =\r
1452                                         padapter->securitypriv.dot11PrivacyAlgrthm;\r
1453                         paoac_global_info_parm.groupEncAlg =\r
1454                                         padapter->securitypriv.dot118021XGrpPrivacy;\r
1455                         FillH2CCmd_88E(padapter, H2C_COM_AOAC_GLOBAL_INFO, 2, (u8 *)&paoac_global_info_parm);\r
1456 \r
1457                         rtw_msleep_os(2);\r
1458                         //enable Remote wake ctrl\r
1459                         pwowlan_parm.mode = FW_REMOTE_WAKE_CTRL_EN | FW_WOW_FW_UNICAST_EN | FW_ARP_EN;\r
1460                         if (psecpriv->dot11PrivacyAlgrthm == _AES_ || psecpriv->dot11PrivacyAlgrthm == _NO_PRIVACY_)\r
1461                         {\r
1462                                 pwowlan_parm.gpio_index=0;\r
1463                         } else {\r
1464                                 pwowlan_parm.gpio_index=1;\r
1465                         }\r
1466                         pwowlan_parm.gpio_duration=0;\r
1467 \r
1468                         res = FillH2CCmd_88E(padapter, H2C_COM_REMOTE_WAKE_CTRL, 3, (u8 *)&pwowlan_parm);\r
1469                 } else {\r
1470                         pwrpriv->wowlan_magic =_FALSE;\r
1471 #ifdef CONFIG_GPIO_WAKEUP\r
1472                         rtl8188es_set_output_gpio(padapter, gpio_wake_pin, !gpio_high_active);\r
1473 #endif //CONFIG_GPIO_WAKEUP\r
1474                         res = FillH2CCmd_88E(padapter, H2C_COM_WWLAN, 2, (u8 *)&pwowlan_parm);\r
1475                         rtw_msleep_os(2);\r
1476                         res = FillH2CCmd_88E(padapter, H2C_COM_REMOTE_WAKE_CTRL, 3, (u8 *)&pwowlan_parm);\r
1477                 }\r
1478 _func_exit_;\r
1479                 DBG_871X_LEVEL(_drv_always_, "-%s res:%d-\n", __func__, res);\r
1480                 return ;\r
1481 }\r
1482 #endif  //CONFIG_WOWLAN\r