1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * 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
19 ******************************************************************************/
20 #define _RTL8192C_CMD_C_
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>
30 #include <rtw_ioctl_set.h>
32 #include <rtl8192c_hal.h>
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
40 static u8
_is_fw_read_cmd_down(_adapter
* padapter
, u8 msgbox_num
)
42 u8 read_down
= _FALSE
;
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);
50 valid
= rtw_read8(padapter
,REG_HMETFR
) & BIT(msgbox_num
);
54 }while( (!read_down
) && (retry_cnts
--));
61 /*****************************************
63 *| 31 - 8 |7 | 6 - 0 |
64 *| h2c_msg |Ext_bit |CMD_ID |
66 ******************************************/
67 int rtl8192c_FillH2CCmd(_adapter
* padapter
, u8 ElementID
, u32 CmdLen
, u8
* pCmdBuffer
)
69 u8 bcmd_down
= _FALSE
;
74 HAL_DATA_TYPE
*pHalData
= GET_HAL_DATA(padapter
);
81 padapter
= GET_PRIMARY_ADAPTER(padapter
);
82 pHalData
= GET_HAL_DATA(padapter
);
84 if(padapter
->bFWReady
== _FALSE
)
86 DBG_8192C("FillH2CCmd(): return H2C cmd because fw is not ready\n");
90 _enter_critical_mutex(&(adapter_to_dvobj(padapter
)->h2c_fwcmd_mutex
), NULL
);
95 if(CmdLen
> RTL92C_MAX_CMD_LEN
){
98 //pay attention to if race condition happened in H2C cmd setting.
100 h2c_box_num
= pHalData
->LastHMEBoxNum
;
102 if(!_is_fw_read_cmd_down(padapter
, h2c_box_num
)){
103 DBG_8192C(" fw read cmd failed...\n");
109 _rtw_memcpy((u8
*)(&h2c_cmd
)+1, pCmdBuffer
, CmdLen
);
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);
117 *(u8
*)(&h2c_cmd
) |= ElementID
;
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
);
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
);
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);
133 pHalData
->LastHMEBoxNum
= (h2c_box_num
+1) % RTL92C_MAX_H2C_BOX_NUMS
;
135 }while((!bcmd_down
) && (retry_cnts
--));
138 DBG_8192C("H2C Cmd exe down. \n" );
140 DBG_8192C("H2C Cmd exe failed. \n" );
146 _exit_critical_mutex(&(adapter_to_dvobj(padapter
)->h2c_fwcmd_mutex
), NULL
);
154 u8
rtl8192c_h2c_msg_hdl(_adapter
*padapter
, unsigned char *pbuf
)
156 u8 ElementID
, CmdLen
;
158 struct cmd_msg_parm
*pcmdmsg
;
161 return H2C_PARAMETERS_ERROR
;
163 pcmdmsg
= (struct cmd_msg_parm
*)pbuf
;
164 ElementID
= pcmdmsg
->eid
;
165 CmdLen
= pcmdmsg
->sz
;
166 pCmdBuffer
= pcmdmsg
->buf
;
168 rtl8192c_FillH2CCmd(padapter
, ElementID
, CmdLen
, pCmdBuffer
);
173 #if defined(CONFIG_AUTOSUSPEND) && defined(SUPPORT_HW_RFOFF_DETECTED)
174 u8
rtl8192c_set_FwSelectSuspend_cmd(_adapter
*padapter
,u8 bfwpoll
, u16 period
)
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
*)(¶m
));
184 #endif //CONFIG_AUTOSUSPEND && SUPPORT_HW_RFOFF_DETECTED
186 u8
rtl8192c_set_rssi_cmd(_adapter
*padapter
, u8
*param
)
192 *((u32
*) param
) = cpu_to_le32( *((u32
*) param
) );
194 rtl8192c_FillH2CCmd(padapter
, RSSI_SETTING_EID
, 3, param
);
201 u8
rtl8192c_set_raid_cmd(_adapter
*padapter
, u32 mask
, u8 arg
)
208 _rtw_memset(buf
, 0, 5);
209 mask
= cpu_to_le32( mask
);
210 _rtw_memcpy(buf
, &mask
, 4);
213 rtl8192c_FillH2CCmd(padapter
, MACID_CONFIG_EID
, 5, buf
);
221 //bitmap[0:27] = tx_rate_bitmap
222 //bitmap[28:31]= Rate Adaptive id
225 void rtl8192c_Add_RateATid(PADAPTER pAdapter
, u32 bitmap
, u8 arg
)
228 HAL_DATA_TYPE
*pHalData
= GET_HAL_DATA(pAdapter
);
230 if(pHalData
->fw_ractrl
== _TRUE
)
232 rtl8192c_set_raid_cmd(pAdapter
, bitmap
, arg
);
236 u8 macid
, init_rate
, shortGIrate
=_FALSE
;
238 init_rate
= get_highest_rate_idx(bitmap
&0x0fffffff)&0x3f;
242 shortGIrate
= (arg
&BIT(5)) ? _TRUE
:_FALSE
;
244 if (shortGIrate
==_TRUE
)
247 rtw_write8(pAdapter
, (REG_INIDATA_RATE_SEL
+macid
), (u8
)init_rate
);
252 void rtl8192c_set_FwPwrMode_cmd(_adapter
*padapter
, u8 Mode
)
254 SETPWRMODE_PARM H2CSetPwrMode
;
255 struct pwrctrl_priv
*pwrpriv
= &padapter
->pwrctrlpriv
;
259 DBG_871X("%s(): Mode = %d, SmartPS = %d\n", __FUNCTION__
,Mode
,pwrpriv
->smart_ps
);
261 H2CSetPwrMode
.Mode
= Mode
;
263 H2CSetPwrMode
.SmartPS
= pwrpriv
->smart_ps
;
265 H2CSetPwrMode
.BcnPassTime
= 1;//pPSC->RegMaxLPSAwakeIntvl;
267 rtl8192c_FillH2CCmd(padapter
, SET_PWRMODE_EID
, sizeof(H2CSetPwrMode
), (u8
*)&H2CSetPwrMode
);
272 void ConstructBeacon(_adapter
*padapter
, u8
*pframe
, u32
*pLength
)
274 struct rtw_ieee80211_hdr
*pwlanhdr
;
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};
283 //DBG_871X("%s\n", __FUNCTION__);
285 pwlanhdr
= (struct rtw_ieee80211_hdr
*)pframe
;
287 fctrl
= &(pwlanhdr
->frame_ctl
);
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
);
294 SetSeqNum(pwlanhdr
, 0/*pmlmeext->mgnt_seq*/);
295 //pmlmeext->mgnt_seq++;
296 SetFrameSubType(pframe
, WIFI_BEACON
);
298 pframe
+= sizeof(struct rtw_ieee80211_hdr_3addr
);
299 pktlen
= sizeof (struct rtw_ieee80211_hdr_3addr
);
301 //timestamp will be inserted by hardware
305 // beacon interval: 2 bytes
306 _rtw_memcpy(pframe
, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network
->IEs
)), 2);
311 // capability info: 2 bytes
312 _rtw_memcpy(pframe
, (unsigned char *)(rtw_get_capability_from_ie(cur_network
->IEs
)), 2);
317 if( (pmlmeinfo
->state
&0x03) == WIFI_FW_AP_STATE
)
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
);
323 goto _ConstructBeacon
;
326 //below for ad-hoc mode
329 pframe
= rtw_set_ie(pframe
, _SSID_IE_
, cur_network
->Ssid
.SsidLength
, cur_network
->Ssid
.Ssid
, &pktlen
);
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
);
336 pframe
= rtw_set_ie(pframe
, _DSSET_IE_
, 1, (unsigned char *)&(cur_network
->Configuration
.DSConfig
), &pktlen
);
338 if( (pmlmeinfo
->state
&0x03) == WIFI_FW_ADHOC_STATE
)
341 // IBSS Parameter Set...
342 //ATIMWindow = cur->Configuration.ATIMWindow;
344 pframe
= rtw_set_ie(pframe
, _IBSS_PARA_IE_
, 2, (unsigned char *)(&ATIMWindow
), &pktlen
);
351 // EXTERNDED SUPPORTED RATE
354 pframe
= rtw_set_ie(pframe
, _EXT_SUPPORTEDRATES_IE_
, (rate_len
- 8), (cur_network
->SupportedRates
+ 8), &pktlen
);
362 if ((pktlen
+ TXDESC_SIZE
) > 512)
364 DBG_871X("beacon frame too large\n");
370 //DBG_871X("%s bcn_sz=%d\n", __FUNCTION__, pktlen);
374 void ConstructPSPoll(_adapter
*padapter
, u8
*pframe
, u32
*pLength
)
376 struct rtw_ieee80211_hdr
*pwlanhdr
;
379 struct mlme_ext_priv
*pmlmeext
= &(padapter
->mlmeextpriv
);
380 struct mlme_ext_info
*pmlmeinfo
= &(pmlmeext
->mlmext_info
);
382 //DBG_871X("%s\n", __FUNCTION__);
384 pwlanhdr
= (struct rtw_ieee80211_hdr
*)pframe
;
387 fctrl
= &(pwlanhdr
->frame_ctl
);
390 SetFrameSubType(pframe
, WIFI_PSPOLL
);
393 SetDuration(pframe
, (pmlmeinfo
->aid
| 0xc000));
396 _rtw_memcpy(pwlanhdr
->addr1
, get_my_bssid(&(pmlmeinfo
->network
)), ETH_ALEN
);
399 _rtw_memcpy(pwlanhdr
->addr2
, myid(&(padapter
->eeprompriv
)), ETH_ALEN
);
404 void ConstructNullFunctionData(_adapter
*padapter
, u8
*pframe
, u32
*pLength
, u8
*StaAddr
, BOOLEAN bForcePowerSave
)
406 struct rtw_ieee80211_hdr
*pwlanhdr
;
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
);
414 //DBG_871X("%s:%d\n", __FUNCTION__, bForcePowerSave);
416 pwlanhdr
= (struct rtw_ieee80211_hdr
*)pframe
;
418 fctrl
= &(pwlanhdr
->frame_ctl
);
425 switch(cur_network
->network
.InfrastructureMode
)
427 case Ndis802_11Infrastructure
:
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
);
433 case Ndis802_11APMode
:
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
);
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
);
447 SetSeqNum(pwlanhdr
, 0);
449 SetFrameSubType(pframe
, WIFI_DATA_NULL
);
451 pframe
+= sizeof(struct rtw_ieee80211_hdr_3addr
);
452 pktlen
= sizeof(struct rtw_ieee80211_hdr_3addr
);
457 void ConstructProbeRsp(_adapter
*padapter
, u8
*pframe
, u32
*pLength
, u8
*StaAddr
, BOOLEAN bHideSSID
)
459 struct rtw_ieee80211_hdr
*pwlanhdr
;
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
);
468 //DBG_871X("%s\n", __FUNCTION__);
470 pwlanhdr
= (struct rtw_ieee80211_hdr
*)pframe
;
472 mac
= myid(&(padapter
->eeprompriv
));
473 bssid
= cur_network
->MacAddress
;
475 fctrl
= &(pwlanhdr
->frame_ctl
);
477 _rtw_memcpy(pwlanhdr
->addr1
, StaAddr
, ETH_ALEN
);
478 _rtw_memcpy(pwlanhdr
->addr2
, mac
, ETH_ALEN
);
479 _rtw_memcpy(pwlanhdr
->addr3
, bssid
, ETH_ALEN
);
481 SetSeqNum(pwlanhdr
, 0);
482 SetFrameSubType(fctrl
, WIFI_PROBERSP
);
484 pktlen
= sizeof(struct rtw_ieee80211_hdr_3addr
);
487 if(cur_network
->IELength
>MAX_IE_SZ
)
490 _rtw_memcpy(pframe
, cur_network
->IEs
, cur_network
->IELength
);
491 pframe
+= cur_network
->IELength
;
492 pktlen
+= cur_network
->IELength
;
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.
504 FillFakeTxDescriptor92C(
511 struct tx_desc
*ptxdesc
= (struct tx_desc
*)pDesc
;
514 _rtw_memset(pDesc
, 0, 32);
517 ptxdesc
->txdw0
|= cpu_to_le32( OWN
| FSG
| LSG
); //own, bFirstSeg, bLastSeg;
519 ptxdesc
->txdw0
|= cpu_to_le32(((TXDESC_SIZE
+OFFSET_SZ
)<<OFFSET_SHT
)&0x00ff0000); //32 bytes for TX Desc
521 ptxdesc
->txdw0
|= cpu_to_le32(BufferLen
&0x0000ffff); // Buffer size + command header
524 ptxdesc
->txdw1
|= cpu_to_le32((QSLT_MGNT
<<QSEL_SHT
)&0x00001f00); // Fixed queue of Mgnt queue
526 //Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error vlaue by Hw.
529 ptxdesc
->txdw1
|= cpu_to_le32(NAVUSEHDR
);
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.
538 ptxdesc
->txdw4
|= cpu_to_le32(BIT(8));//driver uses rate
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
);
546 //RT_PRINT_DATA(COMP_CMD, DBG_TRACE, "TxFillCmdDesc8192C(): H2C Tx Cmd Content ----->\n", pDesc, TX_DESC_SIZE);
549 // To check if reserved page content is destroyed by beacon beacuse beacon is too large.
550 // 2010.06.23. Added by tynli.
552 CheckFwRsvdPageContent(
556 HAL_DATA_TYPE
* pHalData
= GET_HAL_DATA(Adapter
);
559 if(pHalData
->FwRsvdPageStartOffset
!= 0)
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));*/
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.
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
)
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;
592 RSVDPAGE_LOC RsvdPageLoc
;
593 BOOLEAN bDLOK
= _FALSE
;
595 DBG_871X("%s\n", __FUNCTION__
);
597 ReservedPagePacket
= (u8
*)rtw_malloc(1000);
598 if(ReservedPagePacket
== NULL
){
599 DBG_871X("%s(): alloc ReservedPagePacket fail !!!\n", __FUNCTION__
);
603 _rtw_memset(ReservedPagePacket
, 0, 1000);
605 TxDescLen
= 32;//TX_DESC_SIZE;
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.
616 ConstructBeacon(Adapter
,&ReservedPagePacket
[BufIndex
],&BeaconLength
);
618 //DBG_8192C("SetFwRsvdPagePkt(): HW_VAR_SET_TX_CMD: BCN\n", &ReservedPagePacket[BufIndex], (BeaconLength+BufIndex));
620 //--------------------------------------------------------------------
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
);
626 // To reserved 2 pages for beacon buffer. 2010.06.24.
629 pHalData
->FwRsvdPageStartOffset
= PageNum
;
631 BufIndex
= (PageNum
*128) + TxDescOffset
;
634 ConstructPSPoll(Adapter
, &ReservedPagePacket
[BufIndex
],&PSPollLength
);
636 FillFakeTxDescriptor92C(Adapter
, &ReservedPagePacket
[BufIndex
-TxDescLen
], PSPollLength
, _TRUE
);
638 //DBG_8192C("SetFwRsvdPagePkt(): HW_VAR_SET_TX_CMD: PS-POLL\n", &ReservedPagePacket[BufIndex-TxDescLen], (PSPollLength+TxDescLen));
640 RsvdPageLoc
.LocPsPoll
= PageNum
;
642 //------------------------------------------------------------------
644 U1bTmp
= (u8
)PageNum_128(PSPollLength
+TxDescLen
);
647 BufIndex
= (PageNum
*128) + TxDescOffset
;
650 ConstructNullFunctionData(
652 &ReservedPagePacket
[BufIndex
],
653 &NullFunctionDataLength
,
654 get_my_bssid(&(pmlmeinfo
->network
)),
657 FillFakeTxDescriptor92C(Adapter
, &ReservedPagePacket
[BufIndex
-TxDescLen
], NullFunctionDataLength
, _FALSE
);
659 RsvdPageLoc
.LocNullData
= PageNum
;
661 //DBG_8192C("SetFwRsvdPagePkt(): HW_VAR_SET_TX_CMD: NULL DATA \n", &ReservedPagePacket[BufIndex-TxDescLen], (NullFunctionDataLength+TxDescLen));
662 //------------------------------------------------------------------
664 U1bTmp
= (u8
)PageNum_128(NullFunctionDataLength
+TxDescLen
);
667 BufIndex
= (PageNum
*128) + TxDescOffset
;
672 &ReservedPagePacket
[BufIndex
],
674 get_my_bssid(&(pmlmeinfo
->network
)),
677 FillFakeTxDescriptor92C(Adapter
, &ReservedPagePacket
[BufIndex
-TxDescLen
], ProbeRspLength
, _FALSE
);
679 RsvdPageLoc
.LocProbeRsp
= PageNum
;
681 //DBG_8192C("SetFwRsvdPagePkt(): HW_VAR_SET_TX_CMD: PROBE RSP \n", &ReservedPagePacket[BufIndex-TxDescLen], (ProbeRspLength-TxDescLen));
683 //------------------------------------------------------------------
685 U1bTmp
= (u8
)PageNum_128(ProbeRspLength
+TxDescLen
);
689 TotalPacketLen
= (PageNum
*128);
691 if ((pmgntframe
= alloc_mgtxmitframe(pxmitpriv
)) == NULL
)
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
);
703 rtw_hal_mgnt_xmit(Adapter
, pmgntframe
);
709 DBG_871X("Set RSVD page location to Fw.\n");
710 rtl8192c_FillH2CCmd(Adapter
, RSVD_PAGE_EID
, sizeof(RsvdPageLoc
), (u8
*)&RsvdPageLoc
);
713 rtw_mfree(ReservedPagePacket
,1000);
717 void rtl8192c_set_FwJoinBssReport_cmd(_adapter
* padapter
, u8 mstatus
)
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
);
726 DBG_871X("%s mstatus(%x)\n", __FUNCTION__
,mstatus
);
730 BOOLEAN bRecover
= _FALSE
;
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);
742 //U1bTmp = rtw_read8(padapter, REG_CR+1);
743 rtw_write8(padapter
, REG_CR
+1, 0x03);
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));
753 // Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.
754 if(pHalData
->RegFwHwTxQCtrl
&BIT6
)
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);
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)));
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.
776 rtw_write8(padapter
, REG_FWHW_TXQ_CTRL
+2, (pHalData
->RegFwHwTxQCtrl
|BIT6
));
777 pHalData
->RegFwHwTxQCtrl
|= BIT6
;
780 // Clear CR[8] or beacon packet will not be send to TxBuf anymore.
781 rtw_write8(padapter
, REG_CR
+1, 0x02);
784 JoinBssRptParm
.OpMode
= mstatus
;
786 rtl8192c_FillH2CCmd(padapter
, JOINBSS_RPT_EID
, sizeof(JoinBssRptParm
), (u8
*)&JoinBssRptParm
);
792 void rtl8192c_set_p2p_ctw_period_cmd(_adapter
* padapter
, u8 ctwindow
)
794 struct P2P_PS_CTWPeriod_t p2p_ps_ctw
;
796 p2p_ps_ctw
.CTWPeriod
= ctwindow
;
798 rtl8192c_FillH2CCmd(padapter
, P2P_PS_CTW_CMD_EID
, 1, (u8
*)(&p2p_ps_ctw
));
802 void rtl8192c_set_p2p_ps_offload_cmd(_adapter
* padapter
, u8 p2p_ps_state
)
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
;
810 u32 start_time
, tsf_low
;
817 DBG_8192C("P2P_PS_DISABLE \n");
818 _rtw_memset(p2p_ps_offload
, 0 ,1);
821 DBG_8192C("P2P_PS_ENABLE \n");
822 // update CTWindow value.
823 if( pwdinfo
->ctwindow
> 0 )
825 p2p_ps_offload
->CTWindow_En
= 1;
826 ctwindow
= pwdinfo
->ctwindow
;
827 if(IS_HARDWARE_TYPE_8723A(padapter
))
829 //rtw_write16(padapter, REG_ATIMWND, ctwindow);
833 rtl8192c_set_p2p_ctw_period_cmd(padapter
, ctwindow
);
837 // hw only support 2 set of NoA
838 for( i
=0 ; i
<pwdinfo
->noa_num
; i
++)
840 // To control the register setting for which NOA
841 rtw_write8(padapter
, 0x5CF, (i
<< 4));
843 p2p_ps_offload
->NoA0_En
= 1;
845 p2p_ps_offload
->NoA1_En
= 1;
847 // config P2P NoA Descriptor Register
848 rtw_write32(padapter
, 0x5E0, pwdinfo
->noa_duration
[i
]);
850 rtw_write32(padapter
, 0x5E4, pwdinfo
->noa_interval
[i
]);
852 //Get Current \14TSF value
853 tsf_low
= rtw_read32(padapter
, REG_TSFTR
);
855 start_time
= pwdinfo
->noa_start_time
[i
];
856 if(pwdinfo
->noa_count
[i
] != 1)
858 while( start_time
<= (tsf_low
+(50*1024) ) )
860 start_time
+= pwdinfo
->noa_interval
[i
];
861 if(pwdinfo
->noa_count
[i
] != 255)
862 pwdinfo
->noa_count
[i
]--;
865 //DBG_8192C("%s(): start_time = %x\n",__FUNCTION__,start_time);
866 rtw_write32(padapter
, 0x5E8, start_time
);
868 rtw_write8(padapter
, 0x5EC, pwdinfo
->noa_count
[i
]);
871 if( (pwdinfo
->opp_ps
== 1) || (pwdinfo
->noa_num
> 0) )
874 rtw_write8(padapter
, REG_DUAL_TSF_RST
, BIT(4));
876 p2p_ps_offload
->Offload_En
= 1;
878 if(rtw_p2p_chk_role(pwdinfo
, P2P_ROLE_GO
))
880 p2p_ps_offload
->role
= 1;
881 p2p_ps_offload
->AllStaSleep
= 0;
885 p2p_ps_offload
->role
= 0;
888 p2p_ps_offload
->discovery
= 0;
892 DBG_8192C("P2P_PS_SCAN \n");
893 p2p_ps_offload
->discovery
= 1;
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
;
904 rtl8192c_FillH2CCmd(padapter
, P2P_PS_OFFLOAD_EID
, 1, (u8
*)p2p_ps_offload
);
909 #endif // CONFIG_P2P_PS
913 int rtl8192c_IOL_exec_cmds_sync(ADAPTER
*adapter
, struct xmit_frame
*xmit_frame
, u32 max_wating_ms
)
915 IO_OFFLOAD_LOC IoOffloadLoc
;
916 u32 start_time
= rtw_get_current_time();
921 if (rtw_IOL_append_END_cmd(xmit_frame
) != _SUCCESS
)
924 dump_mgntframe_and_wait(adapter
, xmit_frame
, max_wating_ms
);
926 IoOffloadLoc
.LocCmd
= 0;
927 if(_SUCCESS
!= rtl8192c_FillH2CCmd(adapter
, H2C_92C_IO_OFFLOAD
, sizeof(IO_OFFLOAD_LOC
), (u8
*)&IoOffloadLoc
))
930 //polling if the IO offloading is done
931 while( (passing_time_ms
=rtw_get_passing_time_ms(start_time
)) <= max_wating_ms
) {
933 if(0xff == rtw_read8(adapter
, REG_C2HEVT_CLEAR
))
936 if(0x00 != (polling_ret
=rtw_read8(adapter
, 0x1c3)))
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"
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)
952 rtw_write32(adapter
, 0x1c0, 0x0);
955 if(polling_ret
== 0xff)
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"
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)
970 rtw_write16(adapter
, 0x1c4, 0x0000);
972 DBG_871X("after reset, 0x1c4=0x%08x\n", rtw_read32(adapter
, 0x1c4));
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);
985 DBG_871X("IOL %s complete in %ums\n", __FUNCTION__
, passing_time_ms
);
986 rtw_write8(adapter
, 0x1c3, 0x0);
997 #ifdef CONFIG_BEACON_DISABLE_OFFLOAD
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.
1003 // Still has the REG_BCN_CTRL_1 modified by unknowned party issue in case of Primary Interface + PORT1 combination.
1005 u8
rtl8192c_dis_beacon_fun_cmd(_adapter
* padapter
)
1012 _rtw_memset(buf
, 0, sizeof(buf
));
1014 if (padapter
->iface_type
== IFACE_PORT0
) {
1016 DBG_871X("%s(): ERROR! padapter->iface_type = %d\n", __FUNCTION__
, padapter
->iface_type
);
1021 rtl8192c_FillH2CCmd(padapter
, H2C_92C_DISABLE_BCN_FUNC
, 2, buf
);
1028 #endif // CONFIG_BEACON_DISABLE_OFFLOAD
1031 #ifdef CONFIG_TSF_RESET_OFFLOAD
1033 ask FW to Reset sync register at Beacon early interrupt
1035 u8
rtl8192c_reset_tsf(_adapter
*padapter
, u8 reset_port
)
1041 if (IFACE_PORT0
==reset_port
) {
1042 buf
[0] = 0x1; buf
[1] = 0;
1045 buf
[0] = 0x0; buf
[1] = 0x1;
1047 rtl8192c_FillH2CCmd(padapter
, H2C_92C_RESET_TSF
, 2, buf
);
1053 int reset_tsf(PADAPTER Adapter
, u8 reset_port
)
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
;
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
);
1063 while ((reset_cnt_after
== reset_cnt_before
) && (loop_cnt
< 10)) {
1066 reset_cnt_after
= rtw_read8(Adapter
, reg_reset_tsf_cnt
);
1069 return(loop_cnt
>= 10) ? _FAIL
: _TRUE
;
1073 #endif // CONFIG_TSF_RESET_OFFLOAD
1075 #ifdef CONFIG_WOWLAN
1077 void rtl8192c_set_wowlan_cmd(_adapter
* padapter
)
1080 SETWOWLAN_PARM pwowlan_parm
;
1081 struct pwrctrl_priv
*pwrpriv
=&padapter
->pwrctrlpriv
;
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;
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 );
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 );
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 );
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
;
1111 rtl8192c_set_FwJoinBssReport_cmd( padapter
, 1);
1114 pwowlan_parm
.gpio_index
=3;
1116 //duration unit is 64us
1117 pwowlan_parm
.gpio_duration
=0xff;
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] );
1124 rtl8192c_FillH2CCmd(padapter
, H2C_WO_WLAN_CMD
, 4, (u8
*)&pwowlan_parm
);
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));
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));
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
);
1145 rtl8192c_FillH2CCmd(padapter
, H2C_WO_WLAN_CMD
, 3, (u8
*)&pwowlan_parm
);
1154 #endif //CONFIG_WOWLAN