]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - drivers/net/wireless/realtek/rtl8192cu/hal/rtl8192c/rtl8192c_cmd.c
net: Add non-mainline source for rtl8192cu wlan
[mirror_ubuntu-zesty-kernel.git] / drivers / net / wireless / realtek / rtl8192cu / hal / rtl8192c / rtl8192c_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 _RTL8192C_CMD_C_
21
22 #include <drv_conf.h>
23 #include <osdep_service.h>
24 #include <drv_types.h>
25 #include <recv_osdep.h>
26 #include <cmd_osdep.h>
27 #include <mlme_osdep.h>
28 #include <rtw_byteorder.h>
29 #include <circ_buf.h>
30 #include <rtw_ioctl_set.h>
31
32 #include <rtl8192c_hal.h>
33
34
35 #define RTL92C_MAX_H2C_BOX_NUMS 4
36 #define RTL92C_MAX_CMD_LEN 5
37 #define MESSAGE_BOX_SIZE 4
38 #define EX_MESSAGE_BOX_SIZE 2
39
40 static u8 _is_fw_read_cmd_down(_adapter* padapter, u8 msgbox_num)
41 {
42 u8 read_down = _FALSE;
43 int retry_cnts = 100;
44
45 u8 valid;
46
47 // DBG_8192C(" _is_fw_read_cmd_down ,isnormal_chip(%x),reg_1cc(%x),msg_box(%d)...\n",isvern,rtw_read8(padapter,REG_HMETFR),msgbox_num);
48
49 do{
50 valid = rtw_read8(padapter,REG_HMETFR) & BIT(msgbox_num);
51 if(0 == valid ){
52 read_down = _TRUE;
53 }
54 }while( (!read_down) && (retry_cnts--));
55
56 return read_down;
57
58 }
59
60
61 /*****************************************
62 * H2C Msg format :
63 *| 31 - 8 |7 | 6 - 0 |
64 *| h2c_msg |Ext_bit |CMD_ID |
65 *
66 ******************************************/
67 int rtl8192c_FillH2CCmd(_adapter* padapter, u8 ElementID, u32 CmdLen, u8* pCmdBuffer)
68 {
69 u8 bcmd_down = _FALSE;
70 int retry_cnts = 100;
71 u8 h2c_box_num;
72 u32 msgbox_addr;
73 u32 msgbox_ex_addr;
74 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
75 u32 h2c_cmd = 0;
76 u16 h2c_cmd_ex = 0;
77 int ret = _FAIL;
78
79 _func_enter_;
80
81 padapter = GET_PRIMARY_ADAPTER(padapter);
82 pHalData = GET_HAL_DATA(padapter);
83
84 if(padapter->bFWReady == _FALSE)
85 {
86 DBG_8192C("FillH2CCmd(): return H2C cmd because fw is not ready\n");
87 return ret;
88 }
89
90 _enter_critical_mutex(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex), NULL);
91
92 if(!pCmdBuffer){
93 goto exit;
94 }
95 if(CmdLen > RTL92C_MAX_CMD_LEN){
96 goto exit;
97 }
98 //pay attention to if race condition happened in H2C cmd setting.
99 do{
100 h2c_box_num = pHalData->LastHMEBoxNum;
101
102 if(!_is_fw_read_cmd_down(padapter, h2c_box_num)){
103 DBG_8192C(" fw read cmd failed...\n");
104 goto exit;
105 }
106
107 if(CmdLen<=3)
108 {
109 _rtw_memcpy((u8*)(&h2c_cmd)+1, pCmdBuffer, CmdLen );
110 }
111 else{
112 _rtw_memcpy((u8*)(&h2c_cmd_ex), pCmdBuffer, EX_MESSAGE_BOX_SIZE);
113 _rtw_memcpy((u8*)(&h2c_cmd)+1, pCmdBuffer+2,( CmdLen-EX_MESSAGE_BOX_SIZE));
114 *(u8*)(&h2c_cmd) |= BIT(7);
115 }
116
117 *(u8*)(&h2c_cmd) |= ElementID;
118
119 if(h2c_cmd & BIT(7)){
120 msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num *EX_MESSAGE_BOX_SIZE);
121 h2c_cmd_ex = cpu_to_le16( h2c_cmd_ex );
122 rtw_write16(padapter, msgbox_ex_addr, h2c_cmd_ex);
123 }
124 msgbox_addr =REG_HMEBOX_0 + (h2c_box_num *MESSAGE_BOX_SIZE);
125 h2c_cmd = cpu_to_le32( h2c_cmd );
126 rtw_write32(padapter,msgbox_addr, h2c_cmd);
127
128 bcmd_down = _TRUE;
129
130 // DBG_8192C("MSG_BOX:%d,CmdLen(%d), reg:0x%x =>h2c_cmd:0x%x, reg:0x%x =>h2c_cmd_ex:0x%x ..\n"
131 // ,pHalData->LastHMEBoxNum ,CmdLen,msgbox_addr,h2c_cmd,msgbox_ex_addr,h2c_cmd_ex);
132
133 pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL92C_MAX_H2C_BOX_NUMS ;
134
135 }while((!bcmd_down) && (retry_cnts--));
136 /*
137 if(bcmd_down)
138 DBG_8192C("H2C Cmd exe down. \n" );
139 else
140 DBG_8192C("H2C Cmd exe failed. \n" );
141 */
142 ret = _SUCCESS;
143
144 exit:
145
146 _exit_critical_mutex(&(adapter_to_dvobj(padapter)->h2c_fwcmd_mutex), NULL);
147
148 _func_exit_;
149
150 return ret;
151
152 }
153
154 u8 rtl8192c_h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf)
155 {
156 u8 ElementID, CmdLen;
157 u8 *pCmdBuffer;
158 struct cmd_msg_parm *pcmdmsg;
159
160 if(!pbuf)
161 return H2C_PARAMETERS_ERROR;
162
163 pcmdmsg = (struct cmd_msg_parm*)pbuf;
164 ElementID = pcmdmsg->eid;
165 CmdLen = pcmdmsg->sz;
166 pCmdBuffer = pcmdmsg->buf;
167
168 rtl8192c_FillH2CCmd(padapter, ElementID, CmdLen, pCmdBuffer);
169
170 return H2C_SUCCESS;
171 }
172
173 #if defined(CONFIG_AUTOSUSPEND) && defined(SUPPORT_HW_RFOFF_DETECTED)
174 u8 rtl8192c_set_FwSelectSuspend_cmd(_adapter *padapter ,u8 bfwpoll, u16 period)
175 {
176 u8 res=_SUCCESS;
177 struct H2C_SS_RFOFF_PARAM param;
178 DBG_8192C("==>%s bfwpoll(%x)\n",__FUNCTION__,bfwpoll);
179 param.gpio_period = period;//Polling GPIO_11 period time
180 param.ROFOn = (_TRUE == bfwpoll)?1:0;
181 rtl8192c_FillH2CCmd(padapter, SELECTIVE_SUSPEND_ROF_CMD, sizeof(param), (u8*)(&param));
182 return res;
183 }
184 #endif //CONFIG_AUTOSUSPEND && SUPPORT_HW_RFOFF_DETECTED
185
186 u8 rtl8192c_set_rssi_cmd(_adapter*padapter, u8 *param)
187 {
188 u8 res=_SUCCESS;
189
190 _func_enter_;
191
192 *((u32*) param ) = cpu_to_le32( *((u32*) param ) );
193
194 rtl8192c_FillH2CCmd(padapter, RSSI_SETTING_EID, 3, param);
195
196 _func_exit_;
197
198 return res;
199 }
200
201 u8 rtl8192c_set_raid_cmd(_adapter*padapter, u32 mask, u8 arg)
202 {
203 u8 buf[5];
204 u8 res=_SUCCESS;
205
206 _func_enter_;
207
208 _rtw_memset(buf, 0, 5);
209 mask = cpu_to_le32( mask );
210 _rtw_memcpy(buf, &mask, 4);
211 buf[4] = arg;
212
213 rtl8192c_FillH2CCmd(padapter, MACID_CONFIG_EID, 5, buf);
214
215 _func_exit_;
216
217 return res;
218
219 }
220
221 //bitmap[0:27] = tx_rate_bitmap
222 //bitmap[28:31]= Rate Adaptive id
223 //arg[0:4] = macid
224 //arg[5] = Short GI
225 void rtl8192c_Add_RateATid(PADAPTER pAdapter, u32 bitmap, u8 arg)
226 {
227
228 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter);
229
230 if(pHalData->fw_ractrl == _TRUE)
231 {
232 rtl8192c_set_raid_cmd(pAdapter, bitmap, arg);
233 }
234 else
235 {
236 u8 macid, init_rate, shortGIrate=_FALSE;
237
238 init_rate = get_highest_rate_idx(bitmap&0x0fffffff)&0x3f;
239
240 macid = arg&0x1f;
241
242 shortGIrate = (arg&BIT(5)) ? _TRUE:_FALSE;
243
244 if (shortGIrate==_TRUE)
245 init_rate |= BIT(6);
246
247 rtw_write8(pAdapter, (REG_INIDATA_RATE_SEL+macid), (u8)init_rate);
248 }
249
250 }
251
252 void rtl8192c_set_FwPwrMode_cmd(_adapter*padapter, u8 Mode)
253 {
254 SETPWRMODE_PARM H2CSetPwrMode;
255 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
256
257 _func_enter_;
258
259 DBG_871X("%s(): Mode = %d, SmartPS = %d\n", __FUNCTION__,Mode,pwrpriv->smart_ps);
260
261 H2CSetPwrMode.Mode = Mode;
262
263 H2CSetPwrMode.SmartPS = pwrpriv->smart_ps;
264
265 H2CSetPwrMode.BcnPassTime = 1;//pPSC->RegMaxLPSAwakeIntvl;
266
267 rtl8192c_FillH2CCmd(padapter, SET_PWRMODE_EID, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
268
269 _func_exit_;
270 }
271
272 void ConstructBeacon(_adapter *padapter, u8 *pframe, u32 *pLength)
273 {
274 struct rtw_ieee80211_hdr *pwlanhdr;
275 u16 *fctrl;
276 u32 rate_len, pktlen;
277 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
278 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
279 WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
280 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
281
282
283 //DBG_871X("%s\n", __FUNCTION__);
284
285 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
286
287 fctrl = &(pwlanhdr->frame_ctl);
288 *(fctrl) = 0;
289
290 _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
291 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
292 _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
293
294 SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
295 //pmlmeext->mgnt_seq++;
296 SetFrameSubType(pframe, WIFI_BEACON);
297
298 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
299 pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
300
301 //timestamp will be inserted by hardware
302 pframe += 8;
303 pktlen += 8;
304
305 // beacon interval: 2 bytes
306 _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
307
308 pframe += 2;
309 pktlen += 2;
310
311 // capability info: 2 bytes
312 _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
313
314 pframe += 2;
315 pktlen += 2;
316
317 if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
318 {
319 //DBG_871X("ie len=%d\n", cur_network->IELength);
320 pktlen += cur_network->IELength - sizeof(NDIS_802_11_FIXED_IEs);
321 _rtw_memcpy(pframe, cur_network->IEs+sizeof(NDIS_802_11_FIXED_IEs), pktlen);
322
323 goto _ConstructBeacon;
324 }
325
326 //below for ad-hoc mode
327
328 // SSID
329 pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);
330
331 // supported rates...
332 rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
333 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pktlen);
334
335 // DS parameter set
336 pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
337
338 if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
339 {
340 u32 ATIMWindow;
341 // IBSS Parameter Set...
342 //ATIMWindow = cur->Configuration.ATIMWindow;
343 ATIMWindow = 0;
344 pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
345 }
346
347
348 //todo: ERP IE
349
350
351 // EXTERNDED SUPPORTED RATE
352 if (rate_len > 8)
353 {
354 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
355 }
356
357
358 //todo:HT for adhoc
359
360 _ConstructBeacon:
361
362 if ((pktlen + TXDESC_SIZE) > 512)
363 {
364 DBG_871X("beacon frame too large\n");
365 return;
366 }
367
368 *pLength = pktlen;
369
370 //DBG_871X("%s bcn_sz=%d\n", __FUNCTION__, pktlen);
371
372 }
373
374 void ConstructPSPoll(_adapter *padapter, u8 *pframe, u32 *pLength)
375 {
376 struct rtw_ieee80211_hdr *pwlanhdr;
377 u16 *fctrl;
378 u32 pktlen;
379 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
380 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
381
382 //DBG_871X("%s\n", __FUNCTION__);
383
384 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
385
386 // Frame control.
387 fctrl = &(pwlanhdr->frame_ctl);
388 *(fctrl) = 0;
389 SetPwrMgt(fctrl);
390 SetFrameSubType(pframe, WIFI_PSPOLL);
391
392 // AID.
393 SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
394
395 // BSSID.
396 _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
397
398 // TA.
399 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
400
401 *pLength = 16;
402 }
403
404 void ConstructNullFunctionData(_adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, BOOLEAN bForcePowerSave)
405 {
406 struct rtw_ieee80211_hdr *pwlanhdr;
407 u16 *fctrl;
408 u32 pktlen;
409 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
410 struct wlan_network *cur_network = &pmlmepriv->cur_network;
411 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
412 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
413
414 //DBG_871X("%s:%d\n", __FUNCTION__, bForcePowerSave);
415
416 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
417
418 fctrl = &(pwlanhdr->frame_ctl);
419 *(fctrl) = 0;
420 if (bForcePowerSave)
421 {
422 SetPwrMgt(fctrl);
423 }
424
425 switch(cur_network->network.InfrastructureMode)
426 {
427 case Ndis802_11Infrastructure:
428 SetToDs(fctrl);
429 _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
430 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
431 _rtw_memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
432 break;
433 case Ndis802_11APMode:
434 SetFrDs(fctrl);
435 _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
436 _rtw_memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
437 _rtw_memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
438 break;
439 case Ndis802_11IBSS:
440 default:
441 _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
442 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
443 _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
444 break;
445 }
446
447 SetSeqNum(pwlanhdr, 0);
448
449 SetFrameSubType(pframe, WIFI_DATA_NULL);
450
451 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
452 pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
453
454 *pLength = pktlen;
455 }
456
457 void ConstructProbeRsp(_adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, BOOLEAN bHideSSID)
458 {
459 struct rtw_ieee80211_hdr *pwlanhdr;
460 u16 *fctrl;
461 u8 *mac, *bssid;
462 u32 pktlen;
463 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
464 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
465 WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
466
467
468 //DBG_871X("%s\n", __FUNCTION__);
469
470 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
471
472 mac = myid(&(padapter->eeprompriv));
473 bssid = cur_network->MacAddress;
474
475 fctrl = &(pwlanhdr->frame_ctl);
476 *(fctrl) = 0;
477 _rtw_memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
478 _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
479 _rtw_memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
480
481 SetSeqNum(pwlanhdr, 0);
482 SetFrameSubType(fctrl, WIFI_PROBERSP);
483
484 pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
485 pframe += pktlen;
486
487 if(cur_network->IELength>MAX_IE_SZ)
488 return;
489
490 _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
491 pframe += cur_network->IELength;
492 pktlen += cur_network->IELength;
493
494 *pLength = pktlen;
495 }
496
497 //
498 // Description: In normal chip, we should send some packet to Hw which will be used by Fw
499 // in FW LPS mode. The function is to fill the Tx descriptor of this packets, then
500 // Fw can tell Hw to send these packet derectly.
501 // Added by tynli. 2009.10.15.
502 //
503 static VOID
504 FillFakeTxDescriptor92C(
505 IN PADAPTER Adapter,
506 IN u8* pDesc,
507 IN u32 BufferLen,
508 IN BOOLEAN IsPsPoll
509 )
510 {
511 struct tx_desc *ptxdesc = (struct tx_desc *)pDesc;
512
513 // Clear all status
514 _rtw_memset(pDesc, 0, 32);
515
516 //offset 0
517 ptxdesc->txdw0 |= cpu_to_le32( OWN | FSG | LSG); //own, bFirstSeg, bLastSeg;
518
519 ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000); //32 bytes for TX Desc
520
521 ptxdesc->txdw0 |= cpu_to_le32(BufferLen&0x0000ffff); // Buffer size + command header
522
523 //offset 4
524 ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT<<QSEL_SHT)&0x00001f00); // Fixed queue of Mgnt queue
525
526 //Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error vlaue by Hw.
527 if(IsPsPoll)
528 {
529 ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR);
530 }
531 else
532 {
533 ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); // Hw set sequence number
534 ptxdesc->txdw3 |= cpu_to_le32((8 <<28)); //set bit3 to 1. Suugested by TimChen. 2009.12.29.
535 }
536
537 //offset 16
538 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));//driver uses rate
539
540 #ifdef CONFIG_USB_HCI
541 // USB interface drop packet if the checksum of descriptor isn't correct.
542 // Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.).
543 rtl8192cu_cal_txdesc_chksum(ptxdesc);
544 #endif
545
546 //RT_PRINT_DATA(COMP_CMD, DBG_TRACE, "TxFillCmdDesc8192C(): H2C Tx Cmd Content ----->\n", pDesc, TX_DESC_SIZE);
547 }
548
549 // To check if reserved page content is destroyed by beacon beacuse beacon is too large.
550 // 2010.06.23. Added by tynli.
551 VOID
552 CheckFwRsvdPageContent(
553 IN PADAPTER Adapter
554 )
555 {
556 HAL_DATA_TYPE* pHalData = GET_HAL_DATA(Adapter);
557 u32 MaxBcnPageNum;
558
559 if(pHalData->FwRsvdPageStartOffset != 0)
560 {
561 /*MaxBcnPageNum = PageNum_128(pMgntInfo->MaxBeaconSize);
562 RT_ASSERT((MaxBcnPageNum <= pHalData->FwRsvdPageStartOffset),
563 ("CheckFwRsvdPageContent(): The reserved page content has been"\
564 "destroyed by beacon!!! MaxBcnPageNum(%d) FwRsvdPageStartOffset(%d)\n!",
565 MaxBcnPageNum, pHalData->FwRsvdPageStartOffset));*/
566 }
567 }
568
569 //
570 // Description: Fill the reserved packets that FW will use to RSVD page.
571 // Now we just send 4 types packet to rsvd page.
572 // (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp.
573 // Input:
574 // bDLFinished - FALSE: At the first time we will send all the packets as a large packet to Hw,
575 // so we need to set the packet length to total lengh.
576 // TRUE: At the second time, we should send the first packet (default:beacon)
577 // to Hw again and set the lengh in descriptor to the real beacon lengh.
578 // 2009.10.15 by tynli.
579 static void SetFwRsvdPagePkt(PADAPTER Adapter, BOOLEAN bDLFinished)
580 {
581 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
582 struct xmit_frame *pmgntframe;
583 struct pkt_attrib *pattrib;
584 struct xmit_priv *pxmitpriv = &(Adapter->xmitpriv);
585 struct mlme_ext_priv *pmlmeext = &(Adapter->mlmeextpriv);
586 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
587 u32 BeaconLength, ProbeRspLength, PSPollLength, NullFunctionDataLength;
588 u8 *ReservedPagePacket;
589 u8 PageNum=0, U1bTmp, TxDescLen=0, TxDescOffset=0;
590 u16 BufIndex=0;
591 u32 TotalPacketLen;
592 RSVDPAGE_LOC RsvdPageLoc;
593 BOOLEAN bDLOK = _FALSE;
594
595 DBG_871X("%s\n", __FUNCTION__);
596
597 ReservedPagePacket = (u8*)rtw_malloc(1000);
598 if(ReservedPagePacket == NULL){
599 DBG_871X("%s(): alloc ReservedPagePacket fail !!!\n", __FUNCTION__);
600 return;
601 }
602
603 _rtw_memset(ReservedPagePacket, 0, 1000);
604
605 TxDescLen = 32;//TX_DESC_SIZE;
606
607 #ifdef CONFIG_USB_HCI
608 BufIndex = TXDESC_OFFSET;
609 TxDescOffset = TxDescLen+8; //Shift index for 8 bytes because the dummy bytes in the first descipstor.
610 #else
611 BufIndex = 0;
612 TxDescOffset = 0;
613 #endif
614
615 //(1) beacon
616 ConstructBeacon(Adapter,&ReservedPagePacket[BufIndex],&BeaconLength);
617
618 //DBG_8192C("SetFwRsvdPagePkt(): HW_VAR_SET_TX_CMD: BCN\n", &ReservedPagePacket[BufIndex], (BeaconLength+BufIndex));
619
620 //--------------------------------------------------------------------
621
622 // When we count the first page size, we need to reserve description size for the RSVD
623 // packet, it will be filled in front of the packet in TXPKTBUF.
624 U1bTmp = (u8)PageNum_128(BeaconLength+TxDescLen);
625 PageNum += U1bTmp;
626 // To reserved 2 pages for beacon buffer. 2010.06.24.
627 if(PageNum == 1)
628 PageNum+=1;
629 pHalData->FwRsvdPageStartOffset = PageNum;
630
631 BufIndex = (PageNum*128) + TxDescOffset;
632
633 //(2) ps-poll
634 ConstructPSPoll(Adapter, &ReservedPagePacket[BufIndex],&PSPollLength);
635
636 FillFakeTxDescriptor92C(Adapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, _TRUE);
637
638 //DBG_8192C("SetFwRsvdPagePkt(): HW_VAR_SET_TX_CMD: PS-POLL\n", &ReservedPagePacket[BufIndex-TxDescLen], (PSPollLength+TxDescLen));
639
640 RsvdPageLoc.LocPsPoll = PageNum;
641
642 //------------------------------------------------------------------
643
644 U1bTmp = (u8)PageNum_128(PSPollLength+TxDescLen);
645 PageNum += U1bTmp;
646
647 BufIndex = (PageNum*128) + TxDescOffset;
648
649 //(3) null data
650 ConstructNullFunctionData(
651 Adapter,
652 &ReservedPagePacket[BufIndex],
653 &NullFunctionDataLength,
654 get_my_bssid(&(pmlmeinfo->network)),
655 _FALSE);
656
657 FillFakeTxDescriptor92C(Adapter, &ReservedPagePacket[BufIndex-TxDescLen], NullFunctionDataLength, _FALSE);
658
659 RsvdPageLoc.LocNullData = PageNum;
660
661 //DBG_8192C("SetFwRsvdPagePkt(): HW_VAR_SET_TX_CMD: NULL DATA \n", &ReservedPagePacket[BufIndex-TxDescLen], (NullFunctionDataLength+TxDescLen));
662 //------------------------------------------------------------------
663
664 U1bTmp = (u8)PageNum_128(NullFunctionDataLength+TxDescLen);
665 PageNum += U1bTmp;
666
667 BufIndex = (PageNum*128) + TxDescOffset;
668
669 //(4) probe response
670 ConstructProbeRsp(
671 Adapter,
672 &ReservedPagePacket[BufIndex],
673 &ProbeRspLength,
674 get_my_bssid(&(pmlmeinfo->network)),
675 _FALSE);
676
677 FillFakeTxDescriptor92C(Adapter, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, _FALSE);
678
679 RsvdPageLoc.LocProbeRsp = PageNum;
680
681 //DBG_8192C("SetFwRsvdPagePkt(): HW_VAR_SET_TX_CMD: PROBE RSP \n", &ReservedPagePacket[BufIndex-TxDescLen], (ProbeRspLength-TxDescLen));
682
683 //------------------------------------------------------------------
684
685 U1bTmp = (u8)PageNum_128(ProbeRspLength+TxDescLen);
686
687 PageNum += U1bTmp;
688
689 TotalPacketLen = (PageNum*128);
690
691 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
692 {
693 return;
694 }
695
696 //update attribute
697 pattrib = &pmgntframe->attrib;
698 update_mgntframe_attrib(Adapter, pattrib);
699 pattrib->qsel = 0x10;
700 pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TxDescLen;
701 _rtw_memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
702
703 rtw_hal_mgnt_xmit(Adapter, pmgntframe);
704
705 bDLOK = _TRUE;
706
707 if(bDLOK)
708 {
709 DBG_871X("Set RSVD page location to Fw.\n");
710 rtl8192c_FillH2CCmd(Adapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
711 }
712
713 rtw_mfree(ReservedPagePacket,1000);
714
715 }
716
717 void rtl8192c_set_FwJoinBssReport_cmd(_adapter* padapter, u8 mstatus)
718 {
719 JOINBSSRPT_PARM JoinBssRptParm;
720 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
721 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
722 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
723
724 _func_enter_;
725
726 DBG_871X("%s mstatus(%x)\n", __FUNCTION__,mstatus);
727
728 if(mstatus == 1)
729 {
730 BOOLEAN bRecover = _FALSE;
731
732 // We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C.
733 // Suggested by filen. Added by tynli.
734 rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
735 // Do not set TSF again here or vWiFi beacon DMA INT will not work.
736 //correct_TSF(padapter, pmlmeext);
737 // Hw sequende enable by dedault. 2010.06.23. by tynli.
738 //rtw_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF));
739 //rtw_write8(padapter, REG_HWSEQ_CTRL, 0xFF);
740
741 //set REG_CR bit 8
742 //U1bTmp = rtw_read8(padapter, REG_CR+1);
743 rtw_write8(padapter, REG_CR+1, 0x03);
744
745 // Disable Hw protection for a time which revserd for Hw sending beacon.
746 // Fix download reserved page packet fail that access collision with the protection time.
747 // 2010.05.11. Added by tynli.
748 //SetBcnCtrlReg(padapter, 0, BIT3);
749 //SetBcnCtrlReg(padapter, BIT4, 0);
750 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)&(~BIT(3)));
751 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)|BIT(4));
752
753 // Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.
754 if(pHalData->RegFwHwTxQCtrl&BIT6)
755 bRecover = _TRUE;
756
757 // To tell Hw the packet is not a real beacon frame.
758 //U1bTmp = rtw_read8(padapter, REG_FWHW_TXQ_CTRL+2);
759 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, (pHalData->RegFwHwTxQCtrl&(~BIT6)));
760 pHalData->RegFwHwTxQCtrl &= (~BIT6);
761 SetFwRsvdPagePkt(padapter, 0);
762
763 // 2010.05.11. Added by tynli.
764 //SetBcnCtrlReg(padapter, BIT3, 0);
765 //SetBcnCtrlReg(padapter, 0, BIT4);
766 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)|BIT(3));
767 rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL)&(~BIT(4)));
768
769 // To make sure that if there exists an adapter which would like to send beacon.
770 // If exists, the origianl value of 0x422[6] will be 1, we should check this to
771 // prevent from setting 0x422[6] to 0 after download reserved page, or it will cause
772 // the beacon cannot be sent by HW.
773 // 2010.06.23. Added by tynli.
774 if(bRecover)
775 {
776 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, (pHalData->RegFwHwTxQCtrl|BIT6));
777 pHalData->RegFwHwTxQCtrl |= BIT6;
778 }
779
780 // Clear CR[8] or beacon packet will not be send to TxBuf anymore.
781 rtw_write8(padapter, REG_CR+1, 0x02);
782 }
783
784 JoinBssRptParm.OpMode = mstatus;
785
786 rtl8192c_FillH2CCmd(padapter, JOINBSS_RPT_EID, sizeof(JoinBssRptParm), (u8 *)&JoinBssRptParm);
787
788 _func_exit_;
789 }
790
791 #ifdef CONFIG_P2P_PS
792 void rtl8192c_set_p2p_ctw_period_cmd(_adapter* padapter, u8 ctwindow)
793 {
794 struct P2P_PS_CTWPeriod_t p2p_ps_ctw;
795
796 p2p_ps_ctw.CTWPeriod = ctwindow;
797
798 rtl8192c_FillH2CCmd(padapter, P2P_PS_CTW_CMD_EID, 1, (u8 *)(&p2p_ps_ctw));
799
800 }
801
802 void rtl8192c_set_p2p_ps_offload_cmd(_adapter* padapter, u8 p2p_ps_state)
803 {
804 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
805 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
806 struct wifidirect_info *pwdinfo = &( padapter->wdinfo );
807 struct P2P_PS_Offload_t *p2p_ps_offload = &pHalData->p2p_ps_offload;
808 u8 i;
809 u16 ctwindow;
810 u32 start_time, tsf_low;
811
812 _func_enter_;
813
814 switch(p2p_ps_state)
815 {
816 case P2P_PS_DISABLE:
817 DBG_8192C("P2P_PS_DISABLE \n");
818 _rtw_memset(p2p_ps_offload, 0 ,1);
819 break;
820 case P2P_PS_ENABLE:
821 DBG_8192C("P2P_PS_ENABLE \n");
822 // update CTWindow value.
823 if( pwdinfo->ctwindow > 0 )
824 {
825 p2p_ps_offload->CTWindow_En = 1;
826 ctwindow = pwdinfo->ctwindow;
827 if(IS_HARDWARE_TYPE_8723A(padapter))
828 {
829 //rtw_write16(padapter, REG_ATIMWND, ctwindow);
830 }
831 else
832 {
833 rtl8192c_set_p2p_ctw_period_cmd(padapter, ctwindow);
834 }
835 }
836
837 // hw only support 2 set of NoA
838 for( i=0 ; i<pwdinfo->noa_num ; i++)
839 {
840 // To control the register setting for which NOA
841 rtw_write8(padapter, 0x5CF, (i << 4));
842 if(i == 0)
843 p2p_ps_offload->NoA0_En = 1;
844 else
845 p2p_ps_offload->NoA1_En = 1;
846
847 // config P2P NoA Descriptor Register
848 rtw_write32(padapter, 0x5E0, pwdinfo->noa_duration[i]);
849
850 rtw_write32(padapter, 0x5E4, pwdinfo->noa_interval[i]);
851
852 //Get Current \14TSF value
853 tsf_low = rtw_read32(padapter, REG_TSFTR);
854
855 start_time = pwdinfo->noa_start_time[i];
856 if(pwdinfo->noa_count[i] != 1)
857 {
858 while( start_time <= (tsf_low+(50*1024) ) )
859 {
860 start_time += pwdinfo->noa_interval[i];
861 if(pwdinfo->noa_count[i] != 255)
862 pwdinfo->noa_count[i]--;
863 }
864 }
865 //DBG_8192C("%s(): start_time = %x\n",__FUNCTION__,start_time);
866 rtw_write32(padapter, 0x5E8, start_time);
867
868 rtw_write8(padapter, 0x5EC, pwdinfo->noa_count[i]);
869 }
870
871 if( (pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0) )
872 {
873 // rst p2p circuit
874 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(4));
875
876 p2p_ps_offload->Offload_En = 1;
877
878 if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
879 {
880 p2p_ps_offload->role= 1;
881 p2p_ps_offload->AllStaSleep = 0;
882 }
883 else
884 {
885 p2p_ps_offload->role= 0;
886 }
887
888 p2p_ps_offload->discovery = 0;
889 }
890 break;
891 case P2P_PS_SCAN:
892 DBG_8192C("P2P_PS_SCAN \n");
893 p2p_ps_offload->discovery = 1;
894 break;
895 case P2P_PS_SCAN_DONE:
896 DBG_8192C("P2P_PS_SCAN_DONE \n");
897 p2p_ps_offload->discovery = 0;
898 pwdinfo->p2p_ps_state = P2P_PS_ENABLE;
899 break;
900 default:
901 break;
902 }
903
904 rtl8192c_FillH2CCmd(padapter, P2P_PS_OFFLOAD_EID, 1, (u8 *)p2p_ps_offload);
905
906 _func_exit_;
907
908 }
909 #endif // CONFIG_P2P_PS
910
911 #ifdef CONFIG_IOL
912 #include <rtw_iol.h>
913 int rtl8192c_IOL_exec_cmds_sync(ADAPTER *adapter, struct xmit_frame *xmit_frame, u32 max_wating_ms)
914 {
915 IO_OFFLOAD_LOC IoOffloadLoc;
916 u32 start_time = rtw_get_current_time();
917 u32 passing_time_ms;
918 u8 polling_ret;
919 int ret = _FAIL;
920
921 if (rtw_IOL_append_END_cmd(xmit_frame) != _SUCCESS)
922 goto exit;
923
924 dump_mgntframe_and_wait(adapter, xmit_frame, max_wating_ms);
925
926 IoOffloadLoc.LocCmd = 0;
927 if(_SUCCESS != rtl8192c_FillH2CCmd(adapter, H2C_92C_IO_OFFLOAD, sizeof(IO_OFFLOAD_LOC), (u8 *)&IoOffloadLoc))
928 goto exit;
929
930 //polling if the IO offloading is done
931 while( (passing_time_ms=rtw_get_passing_time_ms(start_time)) <= max_wating_ms) {
932 #if 0 //C2H
933 if(0xff == rtw_read8(adapter, REG_C2HEVT_CLEAR))
934 break;
935 #else// 0x1c3
936 if(0x00 != (polling_ret=rtw_read8(adapter, 0x1c3)))
937 break;
938 #endif
939 rtw_msleep_os(5);
940 }
941 #if 0 //debug
942 DBG_871X("IOL %s, polling_ret:0x%02x, 0x1c0=0x%08x, 0x1c4=0x%08x, 0x1cc=0x%08x, 0x1e8=0x%08x, 0x130=0x%08x, 0x134=0x%08x\n"
943 , polling_ret==0xff?"success":"error"
944 , polling_ret
945 , rtw_read32(adapter, 0x1c0)
946 , rtw_read32(adapter, 0x1c4)
947 , rtw_read32(adapter, 0x1cc)
948 , rtw_read32(adapter, 0x1e8)
949 , rtw_read32(adapter, 0x130)
950 , rtw_read32(adapter, 0x134)
951 );
952 rtw_write32(adapter, 0x1c0, 0x0);
953 #endif
954
955 if(polling_ret == 0xff)
956 ret =_SUCCESS;
957 else {
958 DBG_871X("IOL %s, polling_ret:0x%02x\n"
959 //", 0x1c0=0x%08x, 0x1c4=0x%08x, 0x1cc=0x%08x, 0x1e8=0x%08x, 0x130=0x%08x, 0x134=0x%08x\n"
960 , polling_ret==0xff?"success":"error"
961 , polling_ret
962 //, rtw_read32(adapter, 0x1c0)
963 //, rtw_read32(adapter, 0x1c4)
964 //, rtw_read32(adapter, 0x1cc)
965 //, rtw_read32(adapter, 0x1e8)
966 //, rtw_read32(adapter, 0x130)
967 //, rtw_read32(adapter, 0x134)
968 );
969 #if 0 //debug
970 rtw_write16(adapter, 0x1c4, 0x0000);
971 rtw_msleep_os(10);
972 DBG_871X("after reset, 0x1c4=0x%08x\n", rtw_read32(adapter, 0x1c4));
973 #endif
974
975 }
976
977 {
978 #if 0 //C2H
979 u32 c2h_evt;
980 int i;
981 c2h_evt = rtw_read32(adapter, REG_C2HEVT_MSG_NORMAL);
982 DBG_871X("%s io-offloading complete, in %ums: 0x%08x\n", __FUNCTION__, passing_time_ms, c2h_evt);
983 rtw_write8(adapter, REG_C2HEVT_CLEAR, 0x0);
984 #else// 0x1c3
985 DBG_871X("IOL %s complete in %ums\n", __FUNCTION__, passing_time_ms);
986 rtw_write8(adapter, 0x1c3, 0x0);
987 #endif
988 }
989
990 exit:
991 return ret;
992
993 }
994 #endif //CONFIG_IOL
995
996
997 #ifdef CONFIG_BEACON_DISABLE_OFFLOAD
998 /*
999 rtl8192c_dis_beacon_fun_cmd()
1000 This function shall only be called by PORT1.
1001 PORT0's beacon function can't be disabled, because it's used by RA function in FW/HW.
1002
1003 // Still has the REG_BCN_CTRL_1 modified by unknowned party issue in case of Primary Interface + PORT1 combination.
1004 */
1005 u8 rtl8192c_dis_beacon_fun_cmd(_adapter* padapter)
1006 {
1007 u8 buf[2];
1008 u8 res=_SUCCESS;
1009
1010 _func_enter_;
1011
1012 _rtw_memset(buf, 0, sizeof(buf));
1013
1014 if (padapter->iface_type == IFACE_PORT0) {
1015 //buf[0] = 0x1;
1016 DBG_871X("%s(): ERROR! padapter->iface_type = %d\n", __FUNCTION__, padapter->iface_type);
1017 return _FAIL;
1018 } else
1019 buf[1] = 0x1;
1020
1021 rtl8192c_FillH2CCmd(padapter, H2C_92C_DISABLE_BCN_FUNC, 2, buf);
1022
1023 _func_exit_;
1024
1025 return res;
1026
1027 }
1028 #endif // CONFIG_BEACON_DISABLE_OFFLOAD
1029
1030
1031 #ifdef CONFIG_TSF_RESET_OFFLOAD
1032 /*
1033 ask FW to Reset sync register at Beacon early interrupt
1034 */
1035 u8 rtl8192c_reset_tsf(_adapter *padapter, u8 reset_port )
1036 {
1037 u8 buf[2];
1038 u8 res=_SUCCESS;
1039
1040 _func_enter_;
1041 if (IFACE_PORT0==reset_port) {
1042 buf[0] = 0x1; buf[1] = 0;
1043
1044 } else{
1045 buf[0] = 0x0; buf[1] = 0x1;
1046 }
1047 rtl8192c_FillH2CCmd(padapter, H2C_92C_RESET_TSF, 2, buf);
1048 _func_exit_;
1049
1050 return res;
1051 }
1052
1053 int reset_tsf(PADAPTER Adapter, u8 reset_port )
1054 {
1055 u8 reset_cnt_before = 0, reset_cnt_after = 0, loop_cnt = 0;
1056 u32 reg_reset_tsf_cnt = (IFACE_PORT0==reset_port) ?
1057 REG_FW_RESET_TSF_CNT_0:REG_FW_RESET_TSF_CNT_1;
1058
1059 rtw_scan_abort(Adapter->pbuddy_adapter); /* site survey will cause reset_tsf fail */
1060 reset_cnt_after = reset_cnt_before = rtw_read8(Adapter,reg_reset_tsf_cnt);
1061 rtl8192c_reset_tsf(Adapter, reset_port);
1062
1063 while ((reset_cnt_after == reset_cnt_before ) && (loop_cnt < 10)) {
1064 rtw_msleep_os(100);
1065 loop_cnt++;
1066 reset_cnt_after = rtw_read8(Adapter, reg_reset_tsf_cnt);
1067 }
1068
1069 return(loop_cnt >= 10) ? _FAIL : _TRUE;
1070 }
1071
1072
1073 #endif // CONFIG_TSF_RESET_OFFLOAD
1074
1075 #ifdef CONFIG_WOWLAN
1076
1077 void rtl8192c_set_wowlan_cmd(_adapter* padapter)
1078 {
1079 u8 res=_SUCCESS;
1080 SETWOWLAN_PARM pwowlan_parm;
1081 struct pwrctrl_priv *pwrpriv=&padapter->pwrctrlpriv;
1082
1083 _func_enter_;
1084
1085 pwowlan_parm.mode =0;
1086 pwowlan_parm.gpio_index=0;
1087 pwowlan_parm.gpio_duration=0;
1088 pwowlan_parm.second_mode =0;
1089 pwowlan_parm.reserve=0;
1090
1091 if(pwrpriv->wowlan_mode ==_TRUE){
1092 pwowlan_parm.mode |=FW_WOWLAN_FUN_EN;
1093 //printk("\n %s 1.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );
1094 if(pwrpriv->wowlan_pattern ==_TRUE){
1095 pwowlan_parm.mode |= FW_WOWLAN_PATTERN_MATCH;
1096 //printk("\n %s 2.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );
1097 }
1098 if(pwrpriv->wowlan_magic ==_TRUE){
1099 pwowlan_parm.mode |=FW_WOWLAN_MAGIC_PKT;
1100 //printk("\n %s 3.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );
1101 }
1102 if(pwrpriv->wowlan_unicast ==_TRUE){
1103 pwowlan_parm.mode |=FW_WOWLAN_UNICAST;
1104 //printk("\n %s 4.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );
1105 }
1106 //WOWLAN_GPIO_ACTIVE means GPIO high active
1107 //pwowlan_parm.mode |=FW_WOWLAN_GPIO_ACTIVE;
1108 pwowlan_parm.mode |=FW_WOWLAN_REKEY_WAKEUP;
1109 pwowlan_parm.mode |=FW_WOWLAN_DEAUTH_WAKEUP;
1110
1111 rtl8192c_set_FwJoinBssReport_cmd( padapter, 1);
1112
1113 //GPIO3
1114 pwowlan_parm.gpio_index=3;
1115
1116 //duration unit is 64us
1117 pwowlan_parm.gpio_duration=0xff;
1118 //
1119 pwowlan_parm.second_mode|=FW_WOWLAN_GPIO_WAKEUP_EN;
1120 //printk("\n %s 5.pwowlan_parm.mode=0x%x \n",__FUNCTION__,pwowlan_parm.mode );
1121 { u8 *ptr=(u8 *)&pwowlan_parm;
1122 printk("\n %s H2C_WO_WLAN=%x %02x:%02x:%02x:%02x:%02x \n",__FUNCTION__,H2C_WO_WLAN_CMD,ptr[0],ptr[1],ptr[2],ptr[3],ptr[4] );
1123 }
1124 rtl8192c_FillH2CCmd(padapter, H2C_WO_WLAN_CMD, 4, (u8 *)&pwowlan_parm);
1125
1126 //keep alive period = 3 * 10 BCN interval
1127 pwowlan_parm.mode =3;
1128 pwowlan_parm.gpio_index=3;
1129 rtl8192c_FillH2CCmd(padapter, KEEP_ALIVE_CONTROL_CMD, 2, (u8 *)&pwowlan_parm);
1130 printk("%s after KEEP_ALIVE_CONTROL_CMD register 0x81=%x \n",__FUNCTION__,rtw_read8(padapter, 0x81));
1131
1132 pwowlan_parm.mode =1;
1133 pwowlan_parm.gpio_index=0;
1134 pwowlan_parm.gpio_duration=0;
1135 rtl8192c_FillH2CCmd(padapter, DISCONNECT_DECISION_CTRL_CMD, 3, (u8 *)&pwowlan_parm);
1136 printk("%s after DISCONNECT_DECISION_CTRL_CMD register 0x81=%x \n",__FUNCTION__,rtw_read8(padapter, 0x81));
1137
1138 //enable GPIO wakeup
1139 pwowlan_parm.mode =1;
1140 pwowlan_parm.gpio_index=0;
1141 pwowlan_parm.gpio_duration=0;
1142 rtl8192c_FillH2CCmd(padapter, REMOTE_WAKE_CTRL_CMD, 3, (u8 *)&pwowlan_parm);
1143 }
1144 else
1145 rtl8192c_FillH2CCmd(padapter, H2C_WO_WLAN_CMD, 3, (u8 *)&pwowlan_parm);
1146
1147
1148 _func_exit_;
1149
1150 return ;
1151
1152 }
1153
1154 #endif //CONFIG_WOWLAN