aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/rtl8723au/Kconfig38
-rw-r--r--drivers/staging/rtl8723au/Makefile58
-rw-r--r--drivers/staging/rtl8723au/TODO13
-rw-r--r--drivers/staging/rtl8723au/core/rtw_ap.c2087
-rw-r--r--drivers/staging/rtl8723au/core/rtw_cmd.c1876
-rw-r--r--drivers/staging/rtl8723au/core/rtw_efuse.c716
-rw-r--r--drivers/staging/rtl8723au/core/rtw_ieee80211.c1861
-rw-r--r--drivers/staging/rtl8723au/core/rtw_io.c266
-rw-r--r--drivers/staging/rtl8723au/core/rtw_ioctl_set.c601
-rw-r--r--drivers/staging/rtl8723au/core/rtw_led.c1899
-rw-r--r--drivers/staging/rtl8723au/core/rtw_mlme.c2500
-rw-r--r--drivers/staging/rtl8723au/core/rtw_mlme_ext.c9990
-rw-r--r--drivers/staging/rtl8723au/core/rtw_p2p.c4001
-rw-r--r--drivers/staging/rtl8723au/core/rtw_pwrctrl.c689
-rw-r--r--drivers/staging/rtl8723au/core/rtw_recv.c2471
-rw-r--r--drivers/staging/rtl8723au/core/rtw_security.c1652
-rw-r--r--drivers/staging/rtl8723au/core/rtw_sreset.c255
-rw-r--r--drivers/staging/rtl8723au/core/rtw_sta_mgt.c509
-rw-r--r--drivers/staging/rtl8723au/core/rtw_wlan_util.c1760
-rw-r--r--drivers/staging/rtl8723au/core/rtw_xmit.c2460
-rw-r--r--drivers/staging/rtl8723au/hal/Hal8723PwrSeq.c80
-rw-r--r--drivers/staging/rtl8723au/hal/Hal8723UHWImg_CE.c136
-rw-r--r--drivers/staging/rtl8723au/hal/HalDMOutSrc8723A_CE.c1063
-rw-r--r--drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c726
-rw-r--r--drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c188
-rw-r--r--drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c259
-rw-r--r--drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c163
-rw-r--r--drivers/staging/rtl8723au/hal/hal_com.c881
-rw-r--r--drivers/staging/rtl8723au/hal/hal_intf.c420
-rw-r--r--drivers/staging/rtl8723au/hal/odm.c2090
-rw-r--r--drivers/staging/rtl8723au/hal/odm_HWConfig.c481
-rw-r--r--drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c162
-rw-r--r--drivers/staging/rtl8723au/hal/odm_debug.c24
-rw-r--r--drivers/staging/rtl8723au/hal/odm_interface.c236
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c11304
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_cmd.c845
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_dm.c273
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c3452
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c1162
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c507
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_rxdesc.c69
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_sreset.c73
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723a_xmit.c52
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723au_led.c113
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723au_recv.c247
-rw-r--r--drivers/staging/rtl8723au/hal/rtl8723au_xmit.c548
-rw-r--r--drivers/staging/rtl8723au/hal/usb_halinit.c1834
-rw-r--r--drivers/staging/rtl8723au/hal/usb_ops_linux.c848
-rw-r--r--drivers/staging/rtl8723au/include/Hal8723APhyCfg.h230
-rw-r--r--drivers/staging/rtl8723au/include/Hal8723APhyReg.h1078
-rw-r--r--drivers/staging/rtl8723au/include/Hal8723PwrSeq.h150
-rw-r--r--drivers/staging/rtl8723au/include/Hal8723UHWImg_CE.h29
-rw-r--r--drivers/staging/rtl8723au/include/HalDMOutSrc8723A.h64
-rw-r--r--drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h44
-rw-r--r--drivers/staging/rtl8723au/include/HalHWImg8723A_FW.h28
-rw-r--r--drivers/staging/rtl8723au/include/HalHWImg8723A_MAC.h26
-rw-r--r--drivers/staging/rtl8723au/include/HalHWImg8723A_RF.h25
-rw-r--r--drivers/staging/rtl8723au/include/HalPwrSeqCmd.h130
-rw-r--r--drivers/staging/rtl8723au/include/HalVerDef.h136
-rw-r--r--drivers/staging/rtl8723au/include/cmd_osdep.h26
-rw-r--r--drivers/staging/rtl8723au/include/drv_types.h360
-rw-r--r--drivers/staging/rtl8723au/include/ethernet.h22
-rw-r--r--drivers/staging/rtl8723au/include/hal_com.h211
-rw-r--r--drivers/staging/rtl8723au/include/hal_intf.h392
-rw-r--r--drivers/staging/rtl8723au/include/ieee80211.h603
-rw-r--r--drivers/staging/rtl8723au/include/ioctl_cfg80211.h119
-rw-r--r--drivers/staging/rtl8723au/include/mlme_osdep.h28
-rw-r--r--drivers/staging/rtl8723au/include/mp_custom_oid.h342
-rw-r--r--drivers/staging/rtl8723au/include/odm.h1205
-rw-r--r--drivers/staging/rtl8723au/include/odm_HWConfig.h174
-rw-r--r--drivers/staging/rtl8723au/include/odm_RegConfig8723A.h34
-rw-r--r--drivers/staging/rtl8723au/include/odm_RegDefine11AC.h49
-rw-r--r--drivers/staging/rtl8723au/include/odm_RegDefine11N.h165
-rw-r--r--drivers/staging/rtl8723au/include/odm_debug.h139
-rw-r--r--drivers/staging/rtl8723au/include/odm_interface.h131
-rw-r--r--drivers/staging/rtl8723au/include/odm_precomp.h54
-rw-r--r--drivers/staging/rtl8723au/include/odm_reg.h114
-rw-r--r--drivers/staging/rtl8723au/include/odm_types.h36
-rw-r--r--drivers/staging/rtl8723au/include/osdep_intf.h46
-rw-r--r--drivers/staging/rtl8723au/include/osdep_service.h207
-rw-r--r--drivers/staging/rtl8723au/include/recv_osdep.h45
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h1672
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_cmd.h160
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_dm.h144
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_hal.h575
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_led.h30
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_pg.h98
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_recv.h70
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_rf.h58
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_spec.h2158
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_sreset.h25
-rw-r--r--drivers/staging/rtl8723au/include/rtl8723a_xmit.h229
-rw-r--r--drivers/staging/rtl8723au/include/rtw_ap.h55
-rw-r--r--drivers/staging/rtl8723au/include/rtw_cmd.h835
-rw-r--r--drivers/staging/rtl8723au/include/rtw_debug.h192
-rw-r--r--drivers/staging/rtl8723au/include/rtw_eeprom.h135
-rw-r--r--drivers/staging/rtl8723au/include/rtw_efuse.h109
-rw-r--r--drivers/staging/rtl8723au/include/rtw_event.h114
-rw-r--r--drivers/staging/rtl8723au/include/rtw_ht.h43
-rw-r--r--drivers/staging/rtl8723au/include/rtw_io.h416
-rw-r--r--drivers/staging/rtl8723au/include/rtw_ioctl.h26
-rw-r--r--drivers/staging/rtl8723au/include/rtw_ioctl_set.h39
-rw-r--r--drivers/staging/rtl8723au/include/rtw_led.h181
-rw-r--r--drivers/staging/rtl8723au/include/rtw_mlme.h624
-rw-r--r--drivers/staging/rtl8723au/include/rtw_mlme_ext.h780
-rw-r--r--drivers/staging/rtl8723au/include/rtw_p2p.h158
-rw-r--r--drivers/staging/rtl8723au/include/rtw_pwrctrl.h265
-rw-r--r--drivers/staging/rtl8723au/include/rtw_qos.h26
-rw-r--r--drivers/staging/rtl8723au/include/rtw_recv.h318
-rw-r--r--drivers/staging/rtl8723au/include/rtw_rf.h113
-rw-r--r--drivers/staging/rtl8723au/include/rtw_security.h357
-rw-r--r--drivers/staging/rtl8723au/include/rtw_sreset.h56
-rw-r--r--drivers/staging/rtl8723au/include/rtw_version.h1
-rw-r--r--drivers/staging/rtl8723au/include/rtw_xmit.h407
-rw-r--r--drivers/staging/rtl8723au/include/sta_info.h385
-rw-r--r--drivers/staging/rtl8723au/include/usb_hal.h20
-rw-r--r--drivers/staging/rtl8723au/include/usb_ops.h97
-rw-r--r--drivers/staging/rtl8723au/include/usb_ops_linux.h46
-rw-r--r--drivers/staging/rtl8723au/include/usb_osintf.h24
-rw-r--r--drivers/staging/rtl8723au/include/usb_vendor_req.h31
-rw-r--r--drivers/staging/rtl8723au/include/wifi.h707
-rw-r--r--drivers/staging/rtl8723au/include/wlan_bssdef.h215
-rw-r--r--drivers/staging/rtl8723au/include/xmit_osdep.h57
-rw-r--r--drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c4532
-rw-r--r--drivers/staging/rtl8723au/os_dep/mlme_linux.c187
-rw-r--r--drivers/staging/rtl8723au/os_dep/os_intfs.c970
-rw-r--r--drivers/staging/rtl8723au/os_dep/osdep_service.c175
-rw-r--r--drivers/staging/rtl8723au/os_dep/recv_linux.c225
-rw-r--r--drivers/staging/rtl8723au/os_dep/usb_intf.c833
-rw-r--r--drivers/staging/rtl8723au/os_dep/usb_ops_linux.c283
-rw-r--r--drivers/staging/rtl8723au/os_dep/xmit_linux.c195
-rw-r--r--drivers/staging/unisys/Kconfig2
-rw-r--r--drivers/staging/unisys/visorchipset/filexfer.c2
-rw-r--r--drivers/staging/unisys/visorchipset/visorchipset_main.c18
136 files changed, 89854 insertions, 2 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 47cf17543008..ea5efb426f75 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -50,6 +50,8 @@ source "drivers/staging/rtl8712/Kconfig"
50 50
51source "drivers/staging/rtl8188eu/Kconfig" 51source "drivers/staging/rtl8188eu/Kconfig"
52 52
53source "drivers/staging/rtl8723au/Kconfig"
54
53source "drivers/staging/rtl8821ae/Kconfig" 55source "drivers/staging/rtl8821ae/Kconfig"
54 56
55source "drivers/staging/rts5139/Kconfig" 57source "drivers/staging/rts5139/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index d12f6189db46..86e020c2ad0d 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_RTL8192U) += rtl8192u/
17obj-$(CONFIG_RTL8192E) += rtl8192e/ 17obj-$(CONFIG_RTL8192E) += rtl8192e/
18obj-$(CONFIG_R8712U) += rtl8712/ 18obj-$(CONFIG_R8712U) += rtl8712/
19obj-$(CONFIG_R8188EU) += rtl8188eu/ 19obj-$(CONFIG_R8188EU) += rtl8188eu/
20obj-$(CONFIG_R8723AU) += rtl8723au/
20obj-$(CONFIG_R8821AE) += rtl8821ae/ 21obj-$(CONFIG_R8821AE) += rtl8821ae/
21obj-$(CONFIG_RTS5139) += rts5139/ 22obj-$(CONFIG_RTS5139) += rts5139/
22obj-$(CONFIG_RTS5208) += rts5208/ 23obj-$(CONFIG_RTS5208) += rts5208/
diff --git a/drivers/staging/rtl8723au/Kconfig b/drivers/staging/rtl8723au/Kconfig
new file mode 100644
index 000000000000..07fb5e4e50fa
--- /dev/null
+++ b/drivers/staging/rtl8723au/Kconfig
@@ -0,0 +1,38 @@
1config R8723AU
2 tristate "Realtek RTL8723AU Wireless LAN NIC driver"
3 depends on USB && WLAN && RFKILL
4 select WIRELESS_EXT
5 select WEXT_PRIV
6 select CFG80211
7 default n
8 ---help---
9 This option adds the Realtek RTL8723AU USB device such as found in
10 the Lenovo Yogi 13 tablet. If built as a module, it will be called r8723au.
11
12if R8723AU
13
14config 8723AU_AP_MODE
15 bool "Realtek RTL8723AU AP mode"
16 default y
17 ---help---
18 This option enables Access Point mode. Unless you know that your system
19 will never be used as an AP, or the target system has limited memory,
20 "Y" should be selected.
21
22config 8723AU_P2P
23 bool "Realtek RTL8723AU Peer-to-peer mode"
24 default y
25 ---help---
26 This option enables peer-to-peer mode for the r8723au driver. Unless you
27 know that peer-to-peer (P2P) mode will never be used, or the target system has
28 limited memory, "Y" should be selected.
29
30config 8723AU_BT_COEXIST
31 bool "Realtek RTL8723AU BlueTooth Coexistence"
32 default y
33 ---help---
34 This option enables icoexistence with BlueTooth communications for the r8723au driver.
35 Unless you know that this driver will never by used with BT, or the target system has
36 limited memory, "Y" should be selected.
37
38endif
diff --git a/drivers/staging/rtl8723au/Makefile b/drivers/staging/rtl8723au/Makefile
new file mode 100644
index 000000000000..11c6dd486462
--- /dev/null
+++ b/drivers/staging/rtl8723au/Makefile
@@ -0,0 +1,58 @@
1r8723au-y := \
2 core/rtw_ap.o \
3 core/rtw_cmd.o \
4 core/rtw_efuse.o \
5 core/rtw_io.o \
6 core/rtw_ioctl_set.o \
7 core/rtw_ieee80211.o \
8 core/rtw_led.o \
9 core/rtw_mlme.o \
10 core/rtw_mlme_ext.o \
11 core/rtw_p2p.o \
12 core/rtw_pwrctrl.o \
13 core/rtw_recv.o \
14 core/rtw_security.o \
15 core/rtw_sreset.o \
16 core/rtw_sta_mgt.o \
17 core/rtw_xmit.o \
18 core/rtw_wlan_util.o \
19 hal/hal_com.o \
20 hal/hal_intf.o \
21 hal/Hal8723PwrSeq.o \
22 hal/Hal8723UHWImg_CE.o \
23 hal/HalDMOutSrc8723A_CE.o \
24 hal/HalHWImg8723A_BB.o \
25 hal/HalHWImg8723A_MAC.o \
26 hal/HalHWImg8723A_RF.o \
27 hal/HalPwrSeqCmd.o \
28 hal/odm_RegConfig8723A.o \
29 hal/rtl8723a_bt-coexist.o \
30 hal/odm_debug.o \
31 hal/odm_interface.o \
32 hal/odm_HWConfig.o \
33 hal/odm.o \
34 hal/rtl8723a_cmd.o \
35 hal/rtl8723a_dm.o \
36 hal/rtl8723a_hal_init.o \
37 hal/rtl8723a_phycfg.o \
38 hal/rtl8723a_rf6052.o \
39 hal/rtl8723a_rxdesc.o \
40 hal/rtl8723a_sreset.o \
41 hal/rtl8723a_xmit.o \
42 hal/rtl8723au_led.o \
43 hal/rtl8723au_recv.o \
44 hal/rtl8723au_xmit.o \
45 hal/usb_halinit.o \
46 hal/usb_ops_linux.o \
47 os_dep/ioctl_cfg80211.o \
48 os_dep/mlme_linux.o \
49 os_dep/osdep_service.o \
50 os_dep/os_intfs.o \
51 os_dep/recv_linux.o \
52 os_dep/usb_intf.o \
53 os_dep/usb_ops_linux.o \
54 os_dep/xmit_linux.o
55
56obj-$(CONFIG_R8723AU) := r8723au.o
57
58ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/include
diff --git a/drivers/staging/rtl8723au/TODO b/drivers/staging/rtl8723au/TODO
new file mode 100644
index 000000000000..175a0ceb7421
--- /dev/null
+++ b/drivers/staging/rtl8723au/TODO
@@ -0,0 +1,13 @@
1TODO:
2- find and remove code valid only for 5 HGz. Many of the obvious
3 ones have been removed, but things like channel > 14 still exist.
4- find and remove any code for other chips that is left over
5- convert any remaining unusual variable types
6- find codes that can use %pM and %Nph formatting
7- checkpatch.pl fixes - most of the remaining ones are lines too long. Many
8 of them will require refactoring
9- merge Realtek's bugfixes and new features into the driver
10- switch to use MAC80211
11
12Please send any patches to Greg Kroah-Hartman <gregkh@linux.com>,
13Jes Sorensen <Jes.Sorensen@redhat.com>, and Larry Finger <Larry.Finger@lwfinger.net>.
diff --git a/drivers/staging/rtl8723au/core/rtw_ap.c b/drivers/staging/rtl8723au/core/rtw_ap.c
new file mode 100644
index 000000000000..a357e98cb83e
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_ap.c
@@ -0,0 +1,2087 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _RTW_AP_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <linux/ieee80211.h>
20#include <wifi.h>
21
22#ifdef CONFIG_8723AU_AP_MODE
23
24extern unsigned char RTW_WPA_OUI23A[];
25extern unsigned char WMM_OUI23A[];
26extern unsigned char WPS_OUI23A[];
27extern unsigned char P2P_OUI23A[];
28extern unsigned char WFD_OUI23A[];
29
30void init_mlme_ap_info23a(struct rtw_adapter *padapter)
31{
32 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
33 struct sta_priv *pstapriv = &padapter->stapriv;
34 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
35
36 spin_lock_init(&pmlmepriv->bcn_update_lock);
37
38 /* for ACL */
39 _rtw_init_queue23a(&pacl_list->acl_node_q);
40
41 start_ap_mode23a(padapter);
42}
43
44void free_mlme_ap_info23a(struct rtw_adapter *padapter)
45{
46 struct sta_info *psta = NULL;
47 struct sta_priv *pstapriv = &padapter->stapriv;
48 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
49 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
50 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
51
52 pmlmepriv->update_bcn = false;
53 pmlmeext->bstart_bss = false;
54
55 rtw_sta_flush23a(padapter);
56
57 pmlmeinfo->state = _HW_STATE_NOLINK_;
58
59 /* free_assoc_sta_resources */
60 rtw_free_all_stainfo23a(padapter);
61
62 /* free bc/mc sta_info */
63 psta = rtw_get_bcmc_stainfo23a(padapter);
64 spin_lock_bh(&pstapriv->sta_hash_lock);
65 rtw_free_stainfo23a(padapter, psta);
66 spin_unlock_bh(&pstapriv->sta_hash_lock);
67}
68
69static void update_BCNTIM(struct rtw_adapter *padapter)
70{
71 struct sta_priv *pstapriv = &padapter->stapriv;
72 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
73 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
74 struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network;
75 unsigned char *pie = pnetwork_mlmeext->IEs;
76 u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;
77 u16 tim_bitmap_le;
78 uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
79
80 tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);
81
82 p = rtw_get_ie23a(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);
83 if (p != NULL && tim_ielen>0) {
84 tim_ielen += 2;
85
86 premainder_ie = p+tim_ielen;
87
88 tim_ie_offset = (int)(p -pie);
89
90 remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen;
91
92 /* append TIM IE from dst_ie offset */
93 dst_ie = p;
94 } else {
95 tim_ielen = 0;
96
97 /* calulate head_len */
98 offset = _FIXED_IE_LENGTH_;
99
100 /* get ssid_ie len */
101 p = rtw_get_ie23a(pie + _BEACON_IE_OFFSET_, _SSID_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
102 if (p != NULL)
103 offset += tmp_len+2;
104
105 /* get supported rates len */
106 p = rtw_get_ie23a(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
107 if (p != NULL)
108 offset += tmp_len+2;
109
110 /* DS Parameter Set IE, len = 3 */
111 offset += 3;
112
113 premainder_ie = pie + offset;
114
115 remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;
116
117 /* append TIM IE from offset */
118 dst_ie = pie + offset;
119 }
120
121 if (remainder_ielen > 0) {
122 pbackup_remainder_ie = kmalloc(remainder_ielen, GFP_ATOMIC);
123 if (pbackup_remainder_ie && premainder_ie)
124 memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
125 }
126
127 *dst_ie++= _TIM_IE_;
128
129 if ((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fc))
130 tim_ielen = 5;
131 else
132 tim_ielen = 4;
133
134 *dst_ie++= tim_ielen;
135
136 *dst_ie++= 0;/* DTIM count */
137 *dst_ie++= 1;/* DTIM peroid */
138
139 if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */
140 *dst_ie++ = BIT(0);/* bitmap ctrl */
141 else
142 *dst_ie++ = 0;
143
144 if (tim_ielen == 4) {
145 *dst_ie++ = *(u8*)&tim_bitmap_le;
146 } else if (tim_ielen == 5) {
147 memcpy(dst_ie, &tim_bitmap_le, 2);
148 dst_ie+= 2;
149 }
150
151 /* copy remainder IE */
152 if (pbackup_remainder_ie) {
153 memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
154
155 kfree(pbackup_remainder_ie);
156 }
157
158 offset = (uint)(dst_ie - pie);
159 pnetwork_mlmeext->IELength = offset + remainder_ielen;
160
161 set_tx_beacon_cmd23a(padapter);
162}
163
164static u8 chk_sta_is_alive(struct sta_info *psta)
165{
166 u8 ret = false;
167
168 if ((psta->sta_stats.last_rx_data_pkts +
169 psta->sta_stats.last_rx_ctrl_pkts) !=
170 (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts))
171 ret = true;
172
173 sta_update_last_rx_pkts(psta);
174
175 return ret;
176}
177
178void expire_timeout_chk23a(struct rtw_adapter *padapter)
179{
180 struct list_head *phead, *plist, *ptmp;
181 u8 updated = 0;
182 struct sta_info *psta;
183 struct sta_priv *pstapriv = &padapter->stapriv;
184 u8 chk_alive_num = 0;
185 char chk_alive_list[NUM_STA];
186 int i;
187
188 spin_lock_bh(&pstapriv->auth_list_lock);
189
190 phead = &pstapriv->auth_list;
191
192 /* check auth_queue */
193 list_for_each_safe(plist, ptmp, phead) {
194 psta = container_of(plist, struct sta_info, auth_list);
195
196 if (psta->expire_to>0) {
197 psta->expire_to--;
198 if (psta->expire_to == 0) {
199 list_del_init(&psta->auth_list);
200 pstapriv->auth_list_cnt--;
201
202 DBG_8723A("auth expire %pM\n", psta->hwaddr);
203
204 spin_unlock_bh(&pstapriv->auth_list_lock);
205
206 spin_lock_bh(&pstapriv->sta_hash_lock);
207 rtw_free_stainfo23a(padapter, psta);
208 spin_unlock_bh(&pstapriv->sta_hash_lock);
209
210 spin_lock_bh(&pstapriv->auth_list_lock);
211 }
212 }
213
214 }
215
216 spin_unlock_bh(&pstapriv->auth_list_lock);
217
218 spin_lock_bh(&pstapriv->asoc_list_lock);
219
220 phead = &pstapriv->asoc_list;
221
222 /* check asoc_queue */
223 list_for_each_safe(plist, ptmp, phead) {
224 psta = container_of(plist, struct sta_info, asoc_list);
225
226 if (chk_sta_is_alive(psta) || !psta->expire_to) {
227 psta->expire_to = pstapriv->expire_to;
228 psta->keep_alive_trycnt = 0;
229 } else {
230 psta->expire_to--;
231 }
232
233 if (psta->expire_to <= 0)
234 {
235 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
236
237 if (padapter->registrypriv.wifi_spec == 1)
238 {
239 psta->expire_to = pstapriv->expire_to;
240 continue;
241 }
242
243 if (psta->state & WIFI_SLEEP_STATE) {
244 if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
245 /* to check if alive by another methods if staion is at ps mode. */
246 psta->expire_to = pstapriv->expire_to;
247 psta->state |= WIFI_STA_ALIVE_CHK_STATE;
248
249 /* to update bcn with tim_bitmap for this station */
250 pstapriv->tim_bitmap |= CHKBIT(psta->aid);
251 update_beacon23a(padapter, _TIM_IE_, NULL, false);
252
253 if (!pmlmeext->active_keep_alive_check)
254 continue;
255 }
256 }
257
258 if (pmlmeext->active_keep_alive_check) {
259 int stainfo_offset;
260
261 stainfo_offset = rtw_stainfo_offset23a(pstapriv, psta);
262 if (stainfo_offset_valid(stainfo_offset)) {
263 chk_alive_list[chk_alive_num++] = stainfo_offset;
264 }
265
266 continue;
267 }
268
269 list_del_init(&psta->asoc_list);
270 pstapriv->asoc_list_cnt--;
271
272 DBG_8723A("asoc expire "MAC_FMT", state = 0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
273 updated = ap_free_sta23a(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING);
274 } else {
275 /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
276 if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt)
277 && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME/pstapriv->asoc_list_cnt)/2)
278 ) {
279 DBG_8723A("%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__,
280 MAC_ARG(psta->hwaddr),
281 psta->sleepq_len,
282 padapter->xmitpriv.free_xmitframe_cnt,
283 pstapriv->asoc_list_cnt);
284 wakeup_sta_to_xmit23a(padapter, psta);
285 }
286 }
287 }
288
289 spin_unlock_bh(&pstapriv->asoc_list_lock);
290
291 if (chk_alive_num) {
292
293 u8 backup_oper_channel = 0;
294 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
295 /* switch to correct channel of current network before issue keep-alive frames */
296 if (rtw_get_oper_ch23a(padapter) != pmlmeext->cur_channel) {
297 backup_oper_channel = rtw_get_oper_ch23a(padapter);
298 SelectChannel23a(padapter, pmlmeext->cur_channel);
299 }
300
301 /* issue null data to check sta alive*/
302 for (i = 0; i < chk_alive_num; i++) {
303
304 int ret = _FAIL;
305
306 psta = rtw_get_stainfo23a_by_offset23a(pstapriv, chk_alive_list[i]);
307 if (!(psta->state &_FW_LINKED))
308 continue;
309
310 if (psta->state & WIFI_SLEEP_STATE)
311 ret = issue_nulldata23a(padapter, psta->hwaddr, 0, 1, 50);
312 else
313 ret = issue_nulldata23a(padapter, psta->hwaddr, 0, 3, 50);
314
315 psta->keep_alive_trycnt++;
316 if (ret == _SUCCESS)
317 {
318 DBG_8723A("asoc check, sta(" MAC_FMT ") is alive\n", MAC_ARG(psta->hwaddr));
319 psta->expire_to = pstapriv->expire_to;
320 psta->keep_alive_trycnt = 0;
321 continue;
322 }
323 else if (psta->keep_alive_trycnt <= 3)
324 {
325 DBG_8723A("ack check for asoc expire, keep_alive_trycnt =%d\n", psta->keep_alive_trycnt);
326 psta->expire_to = 1;
327 continue;
328 }
329
330 psta->keep_alive_trycnt = 0;
331
332 DBG_8723A("asoc expire "MAC_FMT", state = 0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
333 spin_lock_bh(&pstapriv->asoc_list_lock);
334 if (!list_empty(&psta->asoc_list)) {
335 list_del_init(&psta->asoc_list);
336 pstapriv->asoc_list_cnt--;
337 updated = ap_free_sta23a(padapter, psta, false, WLAN_REASON_DEAUTH_LEAVING);
338 }
339 spin_unlock_bh(&pstapriv->asoc_list_lock);
340
341 }
342
343 if (backup_oper_channel>0) /* back to the original operation channel */
344 SelectChannel23a(padapter, backup_oper_channel);
345}
346
347 associated_clients_update23a(padapter, updated);
348}
349
350void add_RATid23a(struct rtw_adapter *padapter, struct sta_info *psta, u8 rssi_level)
351{
352 int i;
353 u8 rf_type;
354 u32 init_rate = 0;
355 unsigned char sta_band = 0, raid, shortGIrate = false;
356 unsigned char limit;
357 unsigned int tx_ra_bitmap = 0;
358 struct ht_priv *psta_ht = NULL;
359 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
360 struct wlan_bssid_ex *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
361
362 if (psta)
363 psta_ht = &psta->htpriv;
364 else
365 return;
366
367 if (!(psta->state & _FW_LINKED))
368 return;
369
370 /* b/g mode ra_bitmap */
371 for (i = 0; i<sizeof(psta->bssrateset); i++)
372 {
373 if (psta->bssrateset[i])
374 tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value23a(psta->bssrateset[i]&0x7f);
375 }
376 /* n mode ra_bitmap */
377 if (psta_ht->ht_option)
378 {
379 rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
380 if (rf_type == RF_2T2R)
381 limit = 16;/* 2R */
382 else
383 limit = 8;/* 1R */
384
385 for (i = 0; i<limit; i++) {
386 if (psta_ht->ht_cap.mcs.rx_mask[i/8] & BIT(i%8))
387 tx_ra_bitmap |= CHKBIT(i+12);
388 }
389
390 /* max short GI rate */
391 shortGIrate = psta_ht->sgi;
392 }
393
394 if (pcur_network->Configuration.DSConfig > 14) {
395 /* 5G band */
396 if (tx_ra_bitmap & 0xffff000)
397 sta_band |= WIRELESS_11_5N | WIRELESS_11A;
398 else
399 sta_band |= WIRELESS_11A;
400 } else {
401 if (tx_ra_bitmap & 0xffff000)
402 sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B;
403 else if (tx_ra_bitmap & 0xff0)
404 sta_band |= WIRELESS_11G |WIRELESS_11B;
405 else
406 sta_band |= WIRELESS_11B;
407 }
408
409 psta->wireless_mode = sta_band;
410
411 raid = networktype_to_raid23a(sta_band);
412 init_rate = get_highest_rate_idx23a(tx_ra_bitmap&0x0fffffff)&0x3f;
413
414 if (psta->aid < NUM_STA)
415 {
416 u8 arg = 0;
417
418 arg = psta->mac_id&0x1f;
419
420 arg |= BIT(7);/* support entry 2~31 */
421
422 if (shortGIrate == true)
423 arg |= BIT(5);
424
425 tx_ra_bitmap |= ((raid<<28)&0xf0000000);
426
427 DBG_8723A("%s => mac_id:%d , raid:%d , bitmap = 0x%x, arg = "
428 "0x%x\n",
429 __func__, psta->mac_id, raid, tx_ra_bitmap, arg);
430
431 /* bitmap[0:27] = tx_rate_bitmap */
432 /* bitmap[28:31]= Rate Adaptive id */
433 /* arg[0:4] = macid */
434 /* arg[5] = Short GI */
435 rtw_hal_add_ra_tid23a(padapter, tx_ra_bitmap, arg, rssi_level);
436
437 if (shortGIrate == true)
438 init_rate |= BIT(6);
439
440 /* set ra_id, init_rate */
441 psta->raid = raid;
442 psta->init_rate = init_rate;
443
444 }
445 else
446 {
447 DBG_8723A("station aid %d exceed the max number\n", psta->aid);
448 }
449}
450
451static void update_bmc_sta(struct rtw_adapter *padapter)
452{
453 u32 init_rate = 0;
454 unsigned char network_type, raid;
455 int i, supportRateNum = 0;
456 unsigned int tx_ra_bitmap = 0;
457 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
458 struct wlan_bssid_ex *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
459 struct sta_info *psta = rtw_get_bcmc_stainfo23a(padapter);
460
461 if (psta)
462 {
463 psta->aid = 0;/* default set to 0 */
464 psta->mac_id = psta->aid + 1;
465
466 psta->qos_option = 0;
467 psta->htpriv.ht_option = false;
468
469 psta->ieee8021x_blocked = 0;
470
471 memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
472
473 /* prepare for add_RATid23a */
474 supportRateNum = rtw_get_rateset_len23a((u8*)&pcur_network->SupportedRates);
475 network_type = rtw_check_network_type23a((u8*)&pcur_network->SupportedRates, supportRateNum, 1);
476
477 memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum);
478 psta->bssratelen = supportRateNum;
479
480 /* b/g mode ra_bitmap */
481 for (i = 0; i<supportRateNum; i++)
482 {
483 if (psta->bssrateset[i])
484 tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value23a(psta->bssrateset[i]&0x7f);
485 }
486
487 if (pcur_network->Configuration.DSConfig > 14) {
488 /* force to A mode. 5G doesn't support CCK rates */
489 network_type = WIRELESS_11A;
490 tx_ra_bitmap = 0x150; /* 6, 12, 24 Mbps */
491 } else {
492 /* force to b mode */
493 network_type = WIRELESS_11B;
494 tx_ra_bitmap = 0xf;
495 }
496
497 raid = networktype_to_raid23a(network_type);
498 init_rate = get_highest_rate_idx23a(tx_ra_bitmap&0x0fffffff)&0x3f;
499
500 /* ap mode */
501 rtw_hal_set_odm_var23a(padapter, HAL_ODM_STA_INFO, psta, true);
502
503 {
504 u8 arg = 0;
505
506 arg = psta->mac_id&0x1f;
507
508 arg |= BIT(7);
509
510 tx_ra_bitmap |= ((raid<<28)&0xf0000000);
511
512 DBG_8723A("update_bmc_sta, mask = 0x%x, arg = 0x%x\n", tx_ra_bitmap, arg);
513
514 /* bitmap[0:27] = tx_rate_bitmap */
515 /* bitmap[28:31]= Rate Adaptive id */
516 /* arg[0:4] = macid */
517 /* arg[5] = Short GI */
518 rtw_hal_add_ra_tid23a(padapter, tx_ra_bitmap, arg, 0);
519
520 }
521
522 /* set ra_id, init_rate */
523 psta->raid = raid;
524 psta->init_rate = init_rate;
525
526 rtw_stassoc_hw_rpt23a(padapter, psta);
527
528 spin_lock_bh(&psta->lock);
529 psta->state = _FW_LINKED;
530 spin_unlock_bh(&psta->lock);
531
532 }
533 else
534 {
535 DBG_8723A("add_RATid23a_bmc_sta error!\n");
536 }
537}
538
539/* notes: */
540/* AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */
541/* MAC_ID = AID+1 for sta in ap/adhoc mode */
542/* MAC_ID = 1 for bc/mc for sta/ap/adhoc */
543/* MAC_ID = 0 for bssid for sta/ap/adhoc */
544/* CAM_ID = 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
545
546void update_sta_info23a_apmode23a(struct rtw_adapter *padapter, struct sta_info *psta)
547{
548 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
549 struct security_priv *psecuritypriv = &padapter->securitypriv;
550 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
551 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
552 struct ht_priv *phtpriv_sta = &psta->htpriv;
553 /* set intf_tag to if1 */
554
555 psta->mac_id = psta->aid+1;
556 DBG_8723A("%s\n", __func__);
557
558 /* ap mode */
559 rtw_hal_set_odm_var23a(padapter, HAL_ODM_STA_INFO, psta, true);
560
561 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
562 psta->ieee8021x_blocked = true;
563 else
564 psta->ieee8021x_blocked = false;
565
566 /* update sta's cap */
567
568 /* ERP */
569 VCS_update23a(padapter, psta);
570 /* HT related cap */
571 if (phtpriv_sta->ht_option)
572 {
573 /* check if sta supports rx ampdu */
574 phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;
575
576 /* check if sta support s Short GI */
577 if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40))
578 phtpriv_sta->sgi = true;
579
580 /* bwmode */
581 if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40)) {
582 /* phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_40; */
583 phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
584 phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
585
586 }
587
588 psta->qos_option = true;
589
590 }
591 else
592 {
593 phtpriv_sta->ampdu_enable = false;
594
595 phtpriv_sta->sgi = false;
596 phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20;
597 phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
598 }
599
600 /* Rx AMPDU */
601 send_delba23a(padapter, 0, psta->hwaddr);/* recipient */
602
603 /* TX AMPDU */
604 send_delba23a(padapter, 1, psta->hwaddr);/* originator */
605 phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */
606 phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */
607
608 /* todo: init other variables */
609
610 memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
611
612 spin_lock_bh(&psta->lock);
613 psta->state |= _FW_LINKED;
614 spin_unlock_bh(&psta->lock);
615}
616
617static void update_hw_ht_param(struct rtw_adapter *padapter)
618{
619 unsigned char max_AMPDU_len;
620 unsigned char min_MPDU_spacing;
621 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
622 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
623
624 DBG_8723A("%s\n", __func__);
625
626 /* handle A-MPDU parameter field */
627 /*
628 AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
629 AMPDU_para [4:2]:Min MPDU Start Spacing
630 */
631 max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
632
633 min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
634
635 rtw_hal_set_hwreg23a(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
636
637 rtw_hal_set_hwreg23a(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
638
639 /* Config SM Power Save setting */
640 pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
641 if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
642 DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
643}
644
645static void start_bss_network(struct rtw_adapter *padapter, u8 *pbuf)
646{
647 u8 *p;
648 u8 val8, cur_channel, cur_bwmode, cur_ch_offset;
649 u16 bcn_interval;
650 u32 acparm;
651 int ie_len;
652 struct registry_priv *pregpriv = &padapter->registrypriv;
653 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
654 struct security_priv* psecuritypriv = &padapter->securitypriv;
655 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
656 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
657 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
658 struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network;
659 struct HT_info_element *pht_info = NULL;
660#ifdef CONFIG_8723AU_P2P
661 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
662#endif /* CONFIG_8723AU_P2P */
663
664 bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
665 cur_channel = pnetwork->Configuration.DSConfig;
666 cur_bwmode = HT_CHANNEL_WIDTH_20;;
667 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
668
669 /* check if there is wps ie, */
670 /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */
671 /* and at first time the security ie (RSN/WPA IE) will not include in beacon. */
672 if (NULL == rtw_get_wps_ie23a(pnetwork->IEs+_FIXED_IE_LENGTH_, pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL))
673 pmlmeext->bstart_bss = true;
674
675 /* todo: update wmm, ht cap */
676 /* pmlmeinfo->WMM_enable; */
677 /* pmlmeinfo->HT_enable; */
678 if (pmlmepriv->qospriv.qos_option)
679 pmlmeinfo->WMM_enable = true;
680 if (pmlmepriv->htpriv.ht_option) {
681 pmlmeinfo->WMM_enable = true;
682 pmlmeinfo->HT_enable = true;
683
684 update_hw_ht_param(padapter);
685 }
686
687 if (pmlmepriv->cur_network.join_res != true) {
688 /* setting only at first time */
689 /* WEP Key will be set before this function, do not clear CAM. */
690 if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))
691 flush_all_cam_entry23a(padapter); /* clear CAM */
692 }
693
694 /* set MSR to AP_Mode */
695 Set_MSR23a(padapter, _HW_STATE_AP_);
696
697 /* Set BSSID REG */
698 rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, pnetwork->MacAddress);
699
700 /* Set EDCA param reg */
701 acparm = 0x002F3217; /* VO */
702 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
703 acparm = 0x005E4317; /* VI */
704 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
705 acparm = 0x005ea42b;
706 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
707 acparm = 0x0000A444; /* BK */
708 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
709
710 /* Set Security */
711 val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
712 rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
713
714 /* Beacon Control related register */
715 rtw_hal_set_hwreg23a(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));
716
717 UpdateBrateTbl23a(padapter, pnetwork->SupportedRates);
718 rtw_hal_set_hwreg23a(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
719
720 if (!pmlmepriv->cur_network.join_res) {
721 /* setting only at first time */
722
723 /* disable dynamic functions, such as high power, DIG */
724
725 /* turn on all dynamic functions */
726 Switch_DM_Func23a(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
727 }
728 /* set channel, bwmode */
729 p = rtw_get_ie23a((pnetwork->IEs + sizeof(struct ndis_802_11_fixed_ies)),
730 _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength -
731 sizeof(struct ndis_802_11_fixed_ies)));
732 if (p && ie_len) {
733 pht_info = (struct HT_info_element *)(p+2);
734
735 if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
736 /* switch to the 40M Hz mode */
737 cur_bwmode = HT_CHANNEL_WIDTH_40;
738 switch (pht_info->infos[0] & 0x3) {
739 case 1:
740 /* pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; */
741 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
742 break;
743 case 3:
744 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
745 break;
746 default:
747 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
748 break;
749 }
750 }
751 }
752 /* TODO: need to judge the phy parameters on concurrent mode for single phy */
753 set_channel_bwmode23a(padapter, cur_channel, cur_ch_offset, cur_bwmode);
754
755 DBG_8723A("CH =%d, BW =%d, offset =%d\n", cur_channel, cur_bwmode,
756 cur_ch_offset);
757
758 pmlmeext->cur_channel = cur_channel;
759 pmlmeext->cur_bwmode = cur_bwmode;
760 pmlmeext->cur_ch_offset = cur_ch_offset;
761 pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type;
762
763 /* update cur_wireless_mode */
764 update_wireless_mode23a(padapter);
765
766 /* udpate capability after cur_wireless_mode updated */
767 update_capinfo23a(padapter, rtw_get_capability23a((struct wlan_bssid_ex *)pnetwork));
768
769 /* let pnetwork_mlmeext == pnetwork_mlme. */
770 memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
771
772#ifdef CONFIG_8723AU_P2P
773 memcpy(pwdinfo->p2p_group_ssid, pnetwork->Ssid.ssid,
774 pnetwork->Ssid.ssid_len);
775 pwdinfo->p2p_group_ssid_len = pnetwork->Ssid.ssid_len;
776#endif /* CONFIG_8723AU_P2P */
777
778 if (pmlmeext->bstart_bss) {
779 update_beacon23a(padapter, _TIM_IE_, NULL, false);
780
781 /* issue beacon frame */
782 if (send_beacon23a(padapter) == _FAIL)
783 DBG_8723A("issue_beacon23a, fail!\n");
784 }
785
786 /* update bc/mc sta_info */
787 update_bmc_sta(padapter);
788}
789
790int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf, int len)
791{
792 int ret = _SUCCESS;
793 u8 *p;
794 u8 *pHT_caps_ie = NULL;
795 u8 *pHT_info_ie = NULL;
796 struct sta_info *psta = NULL;
797 u16 cap, ht_cap = false;
798 uint ie_len = 0;
799 int group_cipher, pairwise_cipher;
800 u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];
801 int supportRateNum = 0;
802 u8 OUI1[] = {0x00, 0x50, 0xf2, 0x01};
803 u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
804 struct registry_priv *pregistrypriv = &padapter->registrypriv;
805 struct security_priv *psecuritypriv = &padapter->securitypriv;
806 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
807 struct wlan_bssid_ex *pbss_network = &pmlmepriv->cur_network.network;
808 u8 *ie = pbss_network->IEs;
809
810 /* SSID */
811 /* Supported rates */
812 /* DS Params */
813 /* WLAN_EID_COUNTRY */
814 /* ERP Information element */
815 /* Extended supported rates */
816 /* WPA/WPA2 */
817 /* Wi-Fi Wireless Multimedia Extensions */
818 /* ht_capab, ht_oper */
819 /* WPS IE */
820
821 DBG_8723A("%s, len =%d\n", __func__, len);
822
823 if (!check_fwstate(pmlmepriv, WIFI_AP_STATE))
824 return _FAIL;
825
826 if (len>MAX_IE_SZ)
827 return _FAIL;
828
829 pbss_network->IELength = len;
830
831 memset(ie, 0, MAX_IE_SZ);
832
833 memcpy(ie, pbuf, pbss_network->IELength);
834
835 if (pbss_network->InfrastructureMode!= Ndis802_11APMode)
836 return _FAIL;
837
838 pbss_network->Rssi = 0;
839
840 memcpy(pbss_network->MacAddress, myid(&padapter->eeprompriv), ETH_ALEN);
841
842 /* beacon interval */
843 /* ie + 8; 8: TimeStamp, 2: Beacon Interval 2:Capability */
844 p = rtw_get_beacon_interval23a_from_ie(ie);
845 pbss_network->Configuration.BeaconPeriod = get_unaligned_le16(p);
846
847 /* capability */
848 cap = get_unaligned_le16(ie);
849
850 /* SSID */
851 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len,
852 (pbss_network->IELength -_BEACON_IE_OFFSET_));
853 if (p && ie_len > 0) {
854 memset(&pbss_network->Ssid, 0, sizeof(struct cfg80211_ssid));
855 memcpy(pbss_network->Ssid.ssid, (p + 2), ie_len);
856 pbss_network->Ssid.ssid_len = ie_len;
857 }
858
859 /* chnnel */
860 channel = 0;
861 pbss_network->Configuration.Length = 0;
862 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len,
863 (pbss_network->IELength - _BEACON_IE_OFFSET_));
864 if (p && ie_len > 0)
865 channel = *(p + 2);
866
867 pbss_network->Configuration.DSConfig = channel;
868
869 memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
870 /* get supported rates */
871 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len,
872 (pbss_network->IELength - _BEACON_IE_OFFSET_));
873 if (p) {
874 memcpy(supportRate, p+2, ie_len);
875 supportRateNum = ie_len;
876 }
877
878 /* get ext_supported rates */
879 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_,
880 &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_);
881 if (p) {
882 memcpy(supportRate+supportRateNum, p+2, ie_len);
883 supportRateNum += ie_len;
884 }
885
886 network_type = rtw_check_network_type23a(supportRate,
887 supportRateNum, channel);
888
889 rtw_set_supported_rate23a(pbss_network->SupportedRates, network_type);
890
891 /* parsing ERP_IE */
892 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len,
893 (pbss_network->IELength - _BEACON_IE_OFFSET_));
894 if (p && ie_len > 0)
895 ERP_IE_handler23a(padapter, (struct ndis_802_11_var_ies *)p);
896
897 /* update privacy/security */
898 if (cap & BIT(4))
899 pbss_network->Privacy = 1;
900 else
901 pbss_network->Privacy = 0;
902
903 psecuritypriv->wpa_psk = 0;
904
905 /* wpa2 */
906 group_cipher = 0; pairwise_cipher = 0;
907 psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
908 psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
909 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len,
910 (pbss_network->IELength - _BEACON_IE_OFFSET_));
911 if (p && ie_len > 0) {
912 if (rtw_parse_wpa2_ie23a(p, ie_len+2, &group_cipher,
913 &pairwise_cipher, NULL) == _SUCCESS) {
914 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
915
916 psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */
917 psecuritypriv->wpa_psk |= BIT(1);
918
919 psecuritypriv->wpa2_group_cipher = group_cipher;
920 psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;
921 }
922 }
923
924 /* wpa */
925 ie_len = 0;
926 group_cipher = 0;
927 pairwise_cipher = 0;
928 psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
929 psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
930 for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2)) {
931 p = rtw_get_ie23a(p, _SSN_IE_1_, &ie_len,
932 (pbss_network->IELength - _BEACON_IE_OFFSET_ -
933 (ie_len + 2)));
934 if ((p) && (!memcmp(p+2, OUI1, 4))) {
935 if (rtw_parse_wpa_ie23a(p, ie_len+2, &group_cipher,
936 &pairwise_cipher, NULL) == _SUCCESS) {
937 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
938
939 /* psk, todo:802.1x */
940 psecuritypriv->dot8021xalg = 1;
941
942 psecuritypriv->wpa_psk |= BIT(0);
943
944 psecuritypriv->wpa_group_cipher = group_cipher;
945 psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;
946 }
947 break;
948 }
949
950 if ((p == NULL) || (ie_len == 0))
951 break;
952 }
953
954 /* wmm */
955 ie_len = 0;
956 pmlmepriv->qospriv.qos_option = 0;
957 if (pregistrypriv->wmm_enable) {
958 for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2)) {
959 p = rtw_get_ie23a(p, _VENDOR_SPECIFIC_IE_, &ie_len,
960 (pbss_network->IELength -
961 _BEACON_IE_OFFSET_ - (ie_len + 2)));
962 if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) {
963 pmlmepriv->qospriv.qos_option = 1;
964
965 *(p+8) |= BIT(7);/* QoS Info, support U-APSD */
966
967 /* disable all ACM bits since the WMM admission
968 * control is not supported
969 */
970 *(p + 10) &= ~BIT(4); /* BE */
971 *(p + 14) &= ~BIT(4); /* BK */
972 *(p + 18) &= ~BIT(4); /* VI */
973 *(p + 22) &= ~BIT(4); /* VO */
974 break;
975 }
976 if ((p == NULL) || (ie_len == 0))
977 break;
978 }
979 }
980 /* parsing HT_CAP_IE */
981 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len,
982 (pbss_network->IELength - _BEACON_IE_OFFSET_));
983 if (p && ie_len > 0) {
984 u8 rf_type;
985
986 struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p+2);
987
988 pHT_caps_ie = p;
989
990 ht_cap = true;
991 network_type |= WIRELESS_11_24N;
992
993 rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
994
995 if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||
996 (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP))
997 pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY & (0x07<<2));
998 else
999 pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_DENSITY&0x00);
1000
1001 /* set Max Rx AMPDU size to 64K */
1002 pht_cap->ampdu_params_info |= (IEEE80211_HT_AMPDU_PARM_FACTOR & 0x03);
1003
1004 if (rf_type == RF_1T1R) {
1005 pht_cap->mcs.rx_mask[0] = 0xff;
1006 pht_cap->mcs.rx_mask[1] = 0x0;
1007 }
1008
1009 memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len);
1010 }
1011
1012 /* parsing HT_INFO_IE */
1013 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len,
1014 (pbss_network->IELength - _BEACON_IE_OFFSET_));
1015 if (p && ie_len > 0)
1016 pHT_info_ie = p;
1017
1018 switch (network_type) {
1019 case WIRELESS_11B:
1020 pbss_network->NetworkTypeInUse = Ndis802_11DS;
1021 break;
1022 case WIRELESS_11G:
1023 case WIRELESS_11BG:
1024 case WIRELESS_11G_24N:
1025 case WIRELESS_11BG_24N:
1026 pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
1027 break;
1028 case WIRELESS_11A:
1029 pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;
1030 break;
1031 default :
1032 pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
1033 break;
1034 }
1035
1036 pmlmepriv->cur_network.network_type = network_type;
1037
1038 pmlmepriv->htpriv.ht_option = false;
1039
1040 /* ht_cap */
1041 if (pregistrypriv->ht_enable && ht_cap) {
1042 pmlmepriv->htpriv.ht_option = true;
1043 pmlmepriv->qospriv.qos_option = 1;
1044
1045 if (pregistrypriv->ampdu_enable == 1)
1046 pmlmepriv->htpriv.ampdu_enable = true;
1047
1048 HT_caps_handler23a(padapter, (struct ndis_802_11_var_ies *)pHT_caps_ie);
1049
1050 HT_info_handler23a(padapter, (struct ndis_802_11_var_ies *)pHT_info_ie);
1051 }
1052
1053 pbss_network->Length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pbss_network);
1054
1055 /* issue beacon to start bss network */
1056 start_bss_network(padapter, (u8*)pbss_network);
1057
1058 /* alloc sta_info for ap itself */
1059 psta = rtw_get_stainfo23a(&padapter->stapriv, pbss_network->MacAddress);
1060 if (!psta) {
1061 psta = rtw_alloc_stainfo23a(&padapter->stapriv, pbss_network->MacAddress);
1062 if (!psta)
1063 return _FAIL;
1064 }
1065 /* fix bug of flush_cam_entry at STOP AP mode */
1066 psta->state |= WIFI_AP_STATE;
1067 rtw_indicate_connect23a(padapter);
1068
1069 /* for check if already set beacon */
1070 pmlmepriv->cur_network.join_res = true;
1071
1072 return ret;
1073}
1074
1075void rtw_set_macaddr_acl23a(struct rtw_adapter *padapter, int mode)
1076{
1077 struct sta_priv *pstapriv = &padapter->stapriv;
1078 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1079
1080 DBG_8723A("%s, mode =%d\n", __func__, mode);
1081
1082 pacl_list->mode = mode;
1083}
1084
1085int rtw_acl_add_sta23a(struct rtw_adapter *padapter, u8 *addr)
1086{
1087 struct list_head *plist, *phead;
1088 u8 added = false;
1089 int i, ret = 0;
1090 struct rtw_wlan_acl_node *paclnode;
1091 struct sta_priv *pstapriv = &padapter->stapriv;
1092 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1093 struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q;
1094
1095 DBG_8723A("%s(acl_num =%d) =" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));
1096
1097 if ((NUM_ACL-1) < pacl_list->num)
1098 return -1;
1099
1100 spin_lock_bh(&pacl_node_q->lock);
1101
1102 phead = get_list_head(pacl_node_q);
1103
1104 list_for_each(plist, phead) {
1105 paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
1106
1107 if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
1108 if (paclnode->valid == true) {
1109 added = true;
1110 DBG_8723A("%s, sta has been added\n", __func__);
1111 break;
1112 }
1113 }
1114 }
1115
1116 spin_unlock_bh(&pacl_node_q->lock);
1117
1118 if (added)
1119 return ret;
1120
1121 spin_lock_bh(&pacl_node_q->lock);
1122
1123 for (i = 0; i < NUM_ACL; i++) {
1124 paclnode = &pacl_list->aclnode[i];
1125
1126 if (!paclnode->valid) {
1127 INIT_LIST_HEAD(&paclnode->list);
1128
1129 memcpy(paclnode->addr, addr, ETH_ALEN);
1130
1131 paclnode->valid = true;
1132
1133 list_add_tail(&paclnode->list, get_list_head(pacl_node_q));
1134
1135 pacl_list->num++;
1136
1137 break;
1138 }
1139 }
1140
1141 DBG_8723A("%s, acl_num =%d\n", __func__, pacl_list->num);
1142
1143 spin_unlock_bh(&pacl_node_q->lock);
1144 return ret;
1145}
1146
1147int rtw_acl_remove_sta23a(struct rtw_adapter *padapter, u8 *addr)
1148{
1149 struct list_head *plist, *phead, *ptmp;
1150 struct rtw_wlan_acl_node *paclnode;
1151 struct sta_priv *pstapriv = &padapter->stapriv;
1152 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1153 struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q;
1154 int ret = 0;
1155
1156 DBG_8723A("%s(acl_num =%d) = %pM\n", __func__, pacl_list->num, addr);
1157
1158 spin_lock_bh(&pacl_node_q->lock);
1159
1160 phead = get_list_head(pacl_node_q);
1161
1162 list_for_each_safe(plist, ptmp, phead) {
1163 paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
1164
1165 if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
1166 if (paclnode->valid) {
1167 paclnode->valid = false;
1168
1169 list_del_init(&paclnode->list);
1170
1171 pacl_list->num--;
1172 }
1173 }
1174 }
1175
1176 spin_unlock_bh(&pacl_node_q->lock);
1177
1178 DBG_8723A("%s, acl_num =%d\n", __func__, pacl_list->num);
1179
1180 return ret;
1181}
1182
1183static void update_bcn_fixed_ie(struct rtw_adapter *padapter)
1184{
1185 DBG_8723A("%s\n", __func__);
1186}
1187
1188static void update_bcn_erpinfo_ie(struct rtw_adapter *padapter)
1189{
1190 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1191 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1192 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1193 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
1194 unsigned char *p, *ie = pnetwork->IEs;
1195 u32 len = 0;
1196
1197 DBG_8723A("%s, ERP_enable =%d\n", __func__, pmlmeinfo->ERP_enable);
1198
1199 if (!pmlmeinfo->ERP_enable)
1200 return;
1201
1202 /* parsing ERP_IE */
1203 p = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
1204 if (p && len>0)
1205 {
1206 struct ndis_802_11_var_ies * pIE = (struct ndis_802_11_var_ies *)p;
1207
1208 if (pmlmepriv->num_sta_non_erp == 1)
1209 pIE->data[0] |= WLAN_ERP_NON_ERP_PRESENT |
1210 WLAN_ERP_USE_PROTECTION;
1211 else
1212 pIE->data[0] &= ~(WLAN_ERP_NON_ERP_PRESENT |
1213 WLAN_ERP_USE_PROTECTION);
1214
1215 if (pmlmepriv->num_sta_no_short_preamble > 0)
1216 pIE->data[0] |= WLAN_ERP_BARKER_PREAMBLE;
1217 else
1218 pIE->data[0] &= ~(WLAN_ERP_BARKER_PREAMBLE);
1219
1220 ERP_IE_handler23a(padapter, pIE);
1221 }
1222}
1223
1224static void update_bcn_htcap_ie(struct rtw_adapter *padapter)
1225{
1226 DBG_8723A("%s\n", __func__);
1227}
1228
1229static void update_bcn_htinfo_ie(struct rtw_adapter *padapter)
1230{
1231 DBG_8723A("%s\n", __func__);
1232}
1233
1234static void update_bcn_rsn_ie(struct rtw_adapter *padapter)
1235{
1236 DBG_8723A("%s\n", __func__);
1237}
1238
1239static void update_bcn_wpa_ie(struct rtw_adapter *padapter)
1240{
1241 DBG_8723A("%s\n", __func__);
1242}
1243
1244static void update_bcn_wmm_ie(struct rtw_adapter *padapter)
1245{
1246 DBG_8723A("%s\n", __func__);
1247}
1248
1249static void update_bcn_wps_ie(struct rtw_adapter *padapter)
1250{
1251 u8 *pwps_ie = NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie = NULL;
1252 uint wps_ielen = 0, wps_offset, remainder_ielen;
1253 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1254 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1255 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1256 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
1257 unsigned char *ie = pnetwork->IEs;
1258 u32 ielen = pnetwork->IELength;
1259
1260 DBG_8723A("%s\n", __func__);
1261
1262 pwps_ie = rtw_get_wps_ie23a(ie+_FIXED_IE_LENGTH_, ielen-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
1263
1264 if (pwps_ie == NULL || wps_ielen == 0)
1265 return;
1266
1267 wps_offset = (uint)(pwps_ie-ie);
1268
1269 premainder_ie = pwps_ie + wps_ielen;
1270
1271 remainder_ielen = ielen - wps_offset - wps_ielen;
1272
1273 if (remainder_ielen > 0) {
1274 pbackup_remainder_ie = kmalloc(remainder_ielen, GFP_ATOMIC);
1275 if (pbackup_remainder_ie)
1276 memcpy(pbackup_remainder_ie, premainder_ie,
1277 remainder_ielen);
1278 }
1279
1280 pwps_ie_src = pmlmepriv->wps_beacon_ie;
1281 if (pwps_ie_src == NULL)
1282 return;
1283
1284 wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */
1285 if ((wps_offset+wps_ielen+2+remainder_ielen)<= MAX_IE_SZ)
1286 {
1287 memcpy(pwps_ie, pwps_ie_src, wps_ielen+2);
1288 pwps_ie += (wps_ielen+2);
1289
1290 if (pbackup_remainder_ie)
1291 memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
1292
1293 /* update IELength */
1294 pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen;
1295 }
1296
1297 if (pbackup_remainder_ie)
1298 kfree(pbackup_remainder_ie);
1299}
1300
1301static void update_bcn_p2p_ie(struct rtw_adapter *padapter)
1302{
1303}
1304
1305static void update_bcn_vendor_spec_ie(struct rtw_adapter *padapter, u8*oui)
1306{
1307 DBG_8723A("%s\n", __func__);
1308
1309 if (!memcmp(RTW_WPA_OUI23A, oui, 4))
1310 {
1311 update_bcn_wpa_ie(padapter);
1312 }
1313 else if (!memcmp(WMM_OUI23A, oui, 4))
1314 {
1315 update_bcn_wmm_ie(padapter);
1316 }
1317 else if (!memcmp(WPS_OUI23A, oui, 4))
1318 {
1319 update_bcn_wps_ie(padapter);
1320 }
1321 else if (!memcmp(P2P_OUI23A, oui, 4))
1322 {
1323 update_bcn_p2p_ie(padapter);
1324 }
1325 else
1326 {
1327 DBG_8723A("unknown OUI type!\n");
1328 }
1329}
1330
1331void update_beacon23a(struct rtw_adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
1332{
1333 struct mlme_priv *pmlmepriv;
1334 struct mlme_ext_priv *pmlmeext;
1335 /* struct mlme_ext_info *pmlmeinfo; */
1336
1337 /* DBG_8723A("%s\n", __func__); */
1338
1339 if (!padapter)
1340 return;
1341
1342 pmlmepriv = &padapter->mlmepriv;
1343 pmlmeext = &padapter->mlmeextpriv;
1344 /* pmlmeinfo = &pmlmeext->mlmext_info; */
1345
1346 if (false == pmlmeext->bstart_bss)
1347 return;
1348
1349 spin_lock_bh(&pmlmepriv->bcn_update_lock);
1350
1351 switch (ie_id)
1352 {
1353 case 0xFF:
1354
1355 update_bcn_fixed_ie(padapter);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */
1356
1357 break;
1358
1359 case _TIM_IE_:
1360
1361 update_BCNTIM(padapter);
1362
1363 break;
1364
1365 case _ERPINFO_IE_:
1366
1367 update_bcn_erpinfo_ie(padapter);
1368
1369 break;
1370
1371 case _HT_CAPABILITY_IE_:
1372
1373 update_bcn_htcap_ie(padapter);
1374
1375 break;
1376
1377 case _RSN_IE_2_:
1378
1379 update_bcn_rsn_ie(padapter);
1380
1381 break;
1382
1383 case _HT_ADD_INFO_IE_:
1384
1385 update_bcn_htinfo_ie(padapter);
1386
1387 break;
1388
1389 case _VENDOR_SPECIFIC_IE_:
1390
1391 update_bcn_vendor_spec_ie(padapter, oui);
1392
1393 break;
1394
1395 default:
1396 break;
1397 }
1398
1399 pmlmepriv->update_bcn = true;
1400
1401 spin_unlock_bh(&pmlmepriv->bcn_update_lock);
1402
1403 if (tx)
1404 set_tx_beacon_cmd23a(padapter);
1405}
1406
1407/*
1408op_mode
1409Set to 0 (HT pure) under the followign conditions
1410 - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
1411 - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
1412Set to 1 (HT non-member protection) if there may be non-HT STAs
1413 in both the primary and the secondary channel
1414Set to 2 if only HT STAs are associated in BSS,
1415 however and at least one 20 MHz HT STA is associated
1416Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
1417 (currently non-GF HT station is considered as non-HT STA also)
1418*/
1419static int rtw_ht_operation_update(struct rtw_adapter *padapter)
1420{
1421 u16 cur_op_mode, new_op_mode;
1422 int op_mode_changes = 0;
1423 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1424 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
1425
1426 if (pmlmepriv->htpriv.ht_option == true)
1427 return 0;
1428
1429 /* if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) */
1430 /* return 0; */
1431
1432 DBG_8723A("%s current operation mode = 0x%X\n",
1433 __func__, pmlmepriv->ht_op_mode);
1434
1435 if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
1436 && pmlmepriv->num_sta_ht_no_gf) {
1437 pmlmepriv->ht_op_mode |=
1438 HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
1439 op_mode_changes++;
1440 } else if ((pmlmepriv->ht_op_mode &
1441 HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
1442 pmlmepriv->num_sta_ht_no_gf == 0) {
1443 pmlmepriv->ht_op_mode &=
1444 ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
1445 op_mode_changes++;
1446 }
1447
1448 if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
1449 (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) {
1450 pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
1451 op_mode_changes++;
1452 } else if ((pmlmepriv->ht_op_mode &
1453 HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
1454 (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) {
1455 pmlmepriv->ht_op_mode &=
1456 ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
1457 op_mode_changes++;
1458 }
1459
1460 /* Note: currently we switch to the MIXED op mode if HT non-greenfield
1461 * station is associated. Probably it's a theoretical case, since
1462 * it looks like all known HT STAs support greenfield.
1463 */
1464 new_op_mode = 0;
1465 if (pmlmepriv->num_sta_no_ht ||
1466 (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
1467 new_op_mode = OP_MODE_MIXED;
1468 else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
1469 && pmlmepriv->num_sta_ht_20mhz)
1470 new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
1471 else if (pmlmepriv->olbc_ht)
1472 new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
1473 else
1474 new_op_mode = OP_MODE_PURE;
1475
1476 cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
1477 if (cur_op_mode != new_op_mode) {
1478 pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
1479 pmlmepriv->ht_op_mode |= new_op_mode;
1480 op_mode_changes++;
1481 }
1482
1483 DBG_8723A("%s new operation mode = 0x%X changes =%d\n",
1484 __func__, pmlmepriv->ht_op_mode, op_mode_changes);
1485
1486 return op_mode_changes;
1487}
1488
1489void associated_clients_update23a(struct rtw_adapter *padapter, u8 updated)
1490{
1491 /* update associcated stations cap. */
1492 if (updated == true)
1493 {
1494 struct list_head *phead, *plist, *ptmp;
1495 struct sta_info *psta;
1496 struct sta_priv *pstapriv = &padapter->stapriv;
1497
1498 spin_lock_bh(&pstapriv->asoc_list_lock);
1499
1500 phead = &pstapriv->asoc_list;
1501
1502 list_for_each_safe(plist, ptmp, phead) {
1503 psta = container_of(plist, struct sta_info, asoc_list);
1504
1505 VCS_update23a(padapter, psta);
1506 }
1507
1508 spin_unlock_bh(&pstapriv->asoc_list_lock);
1509 }
1510}
1511
1512/* called > TSR LEVEL for USB or SDIO Interface*/
1513void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info *psta)
1514{
1515 u8 beacon_updated = false;
1516 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1517 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1518
1519 if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE))
1520 {
1521 if (!psta->no_short_preamble_set)
1522 {
1523 psta->no_short_preamble_set = 1;
1524
1525 pmlmepriv->num_sta_no_short_preamble++;
1526
1527 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1528 (pmlmepriv->num_sta_no_short_preamble == 1))
1529 {
1530 beacon_updated = true;
1531 update_beacon23a(padapter, 0xFF, NULL, true);
1532 }
1533
1534 }
1535 }
1536 else
1537 {
1538 if (psta->no_short_preamble_set)
1539 {
1540 psta->no_short_preamble_set = 0;
1541
1542 pmlmepriv->num_sta_no_short_preamble--;
1543
1544 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1545 (pmlmepriv->num_sta_no_short_preamble == 0))
1546 {
1547 beacon_updated = true;
1548 update_beacon23a(padapter, 0xFF, NULL, true);
1549 }
1550
1551 }
1552 }
1553
1554 if (psta->flags & WLAN_STA_NONERP)
1555 {
1556 if (!psta->nonerp_set)
1557 {
1558 psta->nonerp_set = 1;
1559
1560 pmlmepriv->num_sta_non_erp++;
1561
1562 if (pmlmepriv->num_sta_non_erp == 1)
1563 {
1564 beacon_updated = true;
1565 update_beacon23a(padapter, _ERPINFO_IE_, NULL, true);
1566 }
1567 }
1568
1569 }
1570 else
1571 {
1572 if (psta->nonerp_set)
1573 {
1574 psta->nonerp_set = 0;
1575
1576 pmlmepriv->num_sta_non_erp--;
1577
1578 if (pmlmepriv->num_sta_non_erp == 0)
1579 {
1580 beacon_updated = true;
1581 update_beacon23a(padapter, _ERPINFO_IE_, NULL, true);
1582 }
1583 }
1584
1585 }
1586
1587 if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME))
1588 {
1589 if (!psta->no_short_slot_time_set)
1590 {
1591 psta->no_short_slot_time_set = 1;
1592
1593 pmlmepriv->num_sta_no_short_slot_time++;
1594
1595 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1596 (pmlmepriv->num_sta_no_short_slot_time == 1))
1597 {
1598 beacon_updated = true;
1599 update_beacon23a(padapter, 0xFF, NULL, true);
1600 }
1601
1602 }
1603 }
1604 else
1605 {
1606 if (psta->no_short_slot_time_set)
1607 {
1608 psta->no_short_slot_time_set = 0;
1609
1610 pmlmepriv->num_sta_no_short_slot_time--;
1611
1612 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1613 (pmlmepriv->num_sta_no_short_slot_time == 0))
1614 {
1615 beacon_updated = true;
1616 update_beacon23a(padapter, 0xFF, NULL, true);
1617 }
1618 }
1619 }
1620
1621 if (psta->flags & WLAN_STA_HT)
1622 {
1623 u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);
1624
1625 DBG_8723A("HT: STA " MAC_FMT " HT Capabilities "
1626 "Info: 0x%04x\n", MAC_ARG(psta->hwaddr), ht_capab);
1627
1628 if (psta->no_ht_set) {
1629 psta->no_ht_set = 0;
1630 pmlmepriv->num_sta_no_ht--;
1631 }
1632
1633 if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {
1634 if (!psta->no_ht_gf_set) {
1635 psta->no_ht_gf_set = 1;
1636 pmlmepriv->num_sta_ht_no_gf++;
1637 }
1638 DBG_8723A("%s STA " MAC_FMT " - no "
1639 "greenfield, num of non-gf stations %d\n",
1640 __func__, MAC_ARG(psta->hwaddr),
1641 pmlmepriv->num_sta_ht_no_gf);
1642 }
1643
1644 if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH_20_40) == 0) {
1645 if (!psta->ht_20mhz_set) {
1646 psta->ht_20mhz_set = 1;
1647 pmlmepriv->num_sta_ht_20mhz++;
1648 }
1649 DBG_8723A("%s STA " MAC_FMT " - 20 MHz HT, "
1650 "num of 20MHz HT STAs %d\n",
1651 __func__, MAC_ARG(psta->hwaddr),
1652 pmlmepriv->num_sta_ht_20mhz);
1653 }
1654
1655 }
1656 else
1657 {
1658 if (!psta->no_ht_set) {
1659 psta->no_ht_set = 1;
1660 pmlmepriv->num_sta_no_ht++;
1661 }
1662 if (pmlmepriv->htpriv.ht_option == true) {
1663 DBG_8723A("%s STA " MAC_FMT
1664 " - no HT, num of non-HT stations %d\n",
1665 __func__, MAC_ARG(psta->hwaddr),
1666 pmlmepriv->num_sta_no_ht);
1667 }
1668 }
1669
1670 if (rtw_ht_operation_update(padapter) > 0)
1671 {
1672 update_beacon23a(padapter, _HT_CAPABILITY_IE_, NULL, false);
1673 update_beacon23a(padapter, _HT_ADD_INFO_IE_, NULL, true);
1674 }
1675
1676 /* update associcated stations cap. */
1677 associated_clients_update23a(padapter, beacon_updated);
1678
1679 DBG_8723A("%s, updated =%d\n", __func__, beacon_updated);
1680}
1681
1682u8 bss_cap_update_on_sta_leave23a(struct rtw_adapter *padapter, struct sta_info *psta)
1683{
1684 u8 beacon_updated = false;
1685 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1686 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1687
1688 if (!psta)
1689 return beacon_updated;
1690
1691 if (psta->no_short_preamble_set) {
1692 psta->no_short_preamble_set = 0;
1693 pmlmepriv->num_sta_no_short_preamble--;
1694 if (pmlmeext->cur_wireless_mode > WIRELESS_11B
1695 && pmlmepriv->num_sta_no_short_preamble == 0)
1696 {
1697 beacon_updated = true;
1698 update_beacon23a(padapter, 0xFF, NULL, true);
1699 }
1700 }
1701
1702 if (psta->nonerp_set) {
1703 psta->nonerp_set = 0;
1704 pmlmepriv->num_sta_non_erp--;
1705 if (pmlmepriv->num_sta_non_erp == 0)
1706 {
1707 beacon_updated = true;
1708 update_beacon23a(padapter, _ERPINFO_IE_, NULL, true);
1709 }
1710 }
1711
1712 if (psta->no_short_slot_time_set) {
1713 psta->no_short_slot_time_set = 0;
1714 pmlmepriv->num_sta_no_short_slot_time--;
1715 if (pmlmeext->cur_wireless_mode > WIRELESS_11B
1716 && pmlmepriv->num_sta_no_short_slot_time == 0)
1717 {
1718 beacon_updated = true;
1719 update_beacon23a(padapter, 0xFF, NULL, true);
1720 }
1721 }
1722
1723 if (psta->no_ht_gf_set) {
1724 psta->no_ht_gf_set = 0;
1725 pmlmepriv->num_sta_ht_no_gf--;
1726 }
1727
1728 if (psta->no_ht_set) {
1729 psta->no_ht_set = 0;
1730 pmlmepriv->num_sta_no_ht--;
1731 }
1732
1733 if (psta->ht_20mhz_set) {
1734 psta->ht_20mhz_set = 0;
1735 pmlmepriv->num_sta_ht_20mhz--;
1736 }
1737
1738 if (rtw_ht_operation_update(padapter) > 0)
1739 {
1740 update_beacon23a(padapter, _HT_CAPABILITY_IE_, NULL, false);
1741 update_beacon23a(padapter, _HT_ADD_INFO_IE_, NULL, true);
1742 }
1743
1744 /* update associcated stations cap. */
1745
1746 DBG_8723A("%s, updated =%d\n", __func__, beacon_updated);
1747
1748 return beacon_updated;
1749}
1750
1751u8 ap_free_sta23a(struct rtw_adapter *padapter, struct sta_info *psta, bool active, u16 reason)
1752{
1753 struct sta_priv *pstapriv = &padapter->stapriv;
1754 u8 beacon_updated = false;
1755
1756 if (!psta)
1757 return beacon_updated;
1758
1759 if (active == true)
1760 {
1761 /* tear down Rx AMPDU */
1762 send_delba23a(padapter, 0, psta->hwaddr);/* recipient */
1763
1764 /* tear down TX AMPDU */
1765 send_delba23a(padapter, 1, psta->hwaddr);/* originator */
1766
1767 issue_deauth23a(padapter, psta->hwaddr, reason);
1768 }
1769
1770 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
1771 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
1772
1773 /* report_del_sta_event23a(padapter, psta->hwaddr, reason); */
1774
1775 /* clear cam entry / key */
1776 /* clear_cam_entry23a(padapter, (psta->mac_id + 3)); */
1777 rtw_clearstakey_cmd23a(padapter, (u8*)psta, (u8)(psta->mac_id + 3), true);
1778
1779 spin_lock_bh(&psta->lock);
1780 psta->state &= ~_FW_LINKED;
1781 spin_unlock_bh(&psta->lock);
1782
1783 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);
1784
1785 report_del_sta_event23a(padapter, psta->hwaddr, reason);
1786
1787 beacon_updated = bss_cap_update_on_sta_leave23a(padapter, psta);
1788
1789 spin_lock_bh(&pstapriv->sta_hash_lock);
1790 rtw_free_stainfo23a(padapter, psta);
1791 spin_unlock_bh(&pstapriv->sta_hash_lock);
1792
1793 return beacon_updated;
1794}
1795
1796int rtw_ap_inform_ch_switch23a (struct rtw_adapter *padapter, u8 new_ch, u8 ch_offset)
1797{
1798 struct list_head *phead, *plist;
1799 int ret = 0;
1800 struct sta_info *psta = NULL;
1801 struct sta_priv *pstapriv = &padapter->stapriv;
1802 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1803 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1804 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1805
1806 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1807 return ret;
1808
1809 DBG_8723A(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",
1810 FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);
1811
1812 spin_lock_bh(&pstapriv->asoc_list_lock);
1813 phead = &pstapriv->asoc_list;
1814
1815 list_for_each(plist, phead) {
1816 psta = container_of(plist, struct sta_info, asoc_list);
1817
1818 issue_action_spct_ch_switch23a (padapter, psta->hwaddr, new_ch, ch_offset);
1819 psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);
1820 }
1821 spin_unlock_bh(&pstapriv->asoc_list_lock);
1822
1823 issue_action_spct_ch_switch23a (padapter, bc_addr, new_ch, ch_offset);
1824
1825 return ret;
1826}
1827
1828int rtw_sta_flush23a(struct rtw_adapter *padapter)
1829{
1830 struct list_head *phead, *plist, *ptmp;
1831 int ret = 0;
1832 struct sta_info *psta;
1833 struct sta_priv *pstapriv = &padapter->stapriv;
1834 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1835 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1836 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1837 u8 chk_alive_num = 0;
1838 char chk_alive_list[NUM_STA];
1839 int i;
1840
1841 DBG_8723A(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
1842
1843 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1844 return ret;
1845
1846 spin_lock_bh(&pstapriv->asoc_list_lock);
1847 phead = &pstapriv->asoc_list;
1848
1849 list_for_each_safe(plist, ptmp, phead) {
1850 int stainfo_offset;
1851
1852 psta = container_of(plist, struct sta_info, asoc_list);
1853
1854 /* Remove sta from asoc_list */
1855 list_del_init(&psta->asoc_list);
1856 pstapriv->asoc_list_cnt--;
1857
1858 /* Keep sta for ap_free_sta23a() beyond this asoc_list loop */
1859 stainfo_offset = rtw_stainfo_offset23a(pstapriv, psta);
1860 if (stainfo_offset_valid(stainfo_offset)) {
1861 chk_alive_list[chk_alive_num++] = stainfo_offset;
1862 }
1863 }
1864 spin_unlock_bh(&pstapriv->asoc_list_lock);
1865
1866 /* For each sta in chk_alive_list, call ap_free_sta23a */
1867 for (i = 0; i < chk_alive_num; i++) {
1868 psta = rtw_get_stainfo23a_by_offset23a(pstapriv, chk_alive_list[i]);
1869 ap_free_sta23a(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
1870 }
1871
1872 issue_deauth23a(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);
1873
1874 associated_clients_update23a(padapter, true);
1875
1876 return ret;
1877}
1878
1879/* called > TSR LEVEL for USB or SDIO Interface*/
1880void sta_info_update23a(struct rtw_adapter *padapter, struct sta_info *psta)
1881{
1882 int flags = psta->flags;
1883 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1884
1885 /* update wmm cap. */
1886 if (WLAN_STA_WME&flags)
1887 psta->qos_option = 1;
1888 else
1889 psta->qos_option = 0;
1890
1891 if (pmlmepriv->qospriv.qos_option == 0)
1892 psta->qos_option = 0;
1893
1894 /* update 802.11n ht cap. */
1895 if (WLAN_STA_HT&flags)
1896 {
1897 psta->htpriv.ht_option = true;
1898 psta->qos_option = 1;
1899 }
1900 else
1901 {
1902 psta->htpriv.ht_option = false;
1903 }
1904
1905 if (pmlmepriv->htpriv.ht_option == false)
1906 psta->htpriv.ht_option = false;
1907
1908 update_sta_info23a_apmode23a(padapter, psta);
1909}
1910
1911/* called >= TSR LEVEL for USB or SDIO Interface*/
1912void ap_sta_info_defer_update23a(struct rtw_adapter *padapter, struct sta_info *psta)
1913{
1914 if (psta->state & _FW_LINKED)
1915 {
1916 /* add ratid */
1917 add_RATid23a(padapter, psta, 0);/* DM_RATR_STA_INIT */
1918 }
1919}
1920
1921/* restore hw setting from sw data structures */
1922void rtw_ap_restore_network(struct rtw_adapter *padapter)
1923{
1924 struct mlme_priv *mlmepriv = &padapter->mlmepriv;
1925 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1926 struct sta_priv * pstapriv = &padapter->stapriv;
1927 struct sta_info *psta;
1928 struct security_priv *psecuritypriv = &padapter->securitypriv;
1929 struct list_head *phead, *plist, *ptmp;
1930 u8 chk_alive_num = 0;
1931 char chk_alive_list[NUM_STA];
1932 int i;
1933
1934 rtw_setopmode_cmd23a(padapter, Ndis802_11APMode);
1935
1936 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
1937
1938 start_bss_network(padapter, (u8*)&mlmepriv->cur_network.network);
1939
1940 if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
1941 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))
1942 {
1943 /* restore group key, WEP keys is restored in ips_leave23a() */
1944 rtw_set_key23a(padapter, psecuritypriv, psecuritypriv->dot118021XGrpKeyid, 0);
1945 }
1946
1947 /* per sta pairwise key and settings */
1948 if ((padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_) &&
1949 (padapter->securitypriv.dot11PrivacyAlgrthm != _AES_)) {
1950 return;
1951 }
1952
1953 spin_lock_bh(&pstapriv->asoc_list_lock);
1954
1955 phead = &pstapriv->asoc_list;
1956
1957 list_for_each_safe(plist, ptmp, phead) {
1958 int stainfo_offset;
1959
1960 psta = container_of(plist, struct sta_info, asoc_list);
1961
1962 stainfo_offset = rtw_stainfo_offset23a(pstapriv, psta);
1963 if (stainfo_offset_valid(stainfo_offset)) {
1964 chk_alive_list[chk_alive_num++] = stainfo_offset;
1965 }
1966 }
1967
1968 spin_unlock_bh(&pstapriv->asoc_list_lock);
1969
1970 for (i = 0; i < chk_alive_num; i++) {
1971 psta = rtw_get_stainfo23a_by_offset23a(pstapriv, chk_alive_list[i]);
1972
1973 if (psta == NULL) {
1974 DBG_8723A(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter));
1975 }
1976 else if (psta->state &_FW_LINKED)
1977 {
1978 Update_RA_Entry23a(padapter, psta);
1979 /* pairwise key */
1980 rtw_setstakey_cmd23a(padapter, (unsigned char *)psta, true);
1981 }
1982 }
1983}
1984
1985void start_ap_mode23a(struct rtw_adapter *padapter)
1986{
1987 int i;
1988 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1989 struct sta_priv *pstapriv = &padapter->stapriv;
1990 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1991 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1992
1993 pmlmepriv->update_bcn = false;
1994
1995 /* init_mlme_ap_info23a(padapter); */
1996 pmlmeext->bstart_bss = false;
1997
1998 pmlmepriv->num_sta_non_erp = 0;
1999
2000 pmlmepriv->num_sta_no_short_slot_time = 0;
2001
2002 pmlmepriv->num_sta_no_short_preamble = 0;
2003
2004 pmlmepriv->num_sta_ht_no_gf = 0;
2005 pmlmepriv->num_sta_no_ht = 0;
2006 pmlmepriv->num_sta_ht_20mhz = 0;
2007
2008 pmlmepriv->olbc = false;
2009
2010 pmlmepriv->olbc_ht = false;
2011
2012 pmlmepriv->ht_op_mode = 0;
2013
2014 for (i = 0; i<NUM_STA; i++)
2015 pstapriv->sta_aid[i] = NULL;
2016
2017 pmlmepriv->wps_beacon_ie = NULL;
2018 pmlmepriv->wps_probe_resp_ie = NULL;
2019 pmlmepriv->wps_assoc_resp_ie = NULL;
2020
2021 pmlmepriv->p2p_beacon_ie = NULL;
2022 pmlmepriv->p2p_probe_resp_ie = NULL;
2023
2024 /* for ACL */
2025 INIT_LIST_HEAD(&pacl_list->acl_node_q.queue);
2026 pacl_list->num = 0;
2027 pacl_list->mode = 0;
2028 for (i = 0; i < NUM_ACL; i++) {
2029 INIT_LIST_HEAD(&pacl_list->aclnode[i].list);
2030 pacl_list->aclnode[i].valid = false;
2031 }
2032}
2033
2034void stop_ap_mode23a(struct rtw_adapter *padapter)
2035{
2036 struct list_head *phead, *plist, *ptmp;
2037 struct rtw_wlan_acl_node *paclnode;
2038 struct sta_info *psta = NULL;
2039 struct sta_priv *pstapriv = &padapter->stapriv;
2040 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2041 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2042 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
2043 struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q;
2044
2045 pmlmepriv->update_bcn = false;
2046 pmlmeext->bstart_bss = false;
2047
2048 /* reset and init security priv , this can refine with rtw_reset_securitypriv23a */
2049 memset((unsigned char *)&padapter->securitypriv, 0, sizeof (struct security_priv));
2050 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
2051 padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
2052
2053 /* for ACL */
2054 spin_lock_bh(&pacl_node_q->lock);
2055 phead = get_list_head(pacl_node_q);
2056
2057 list_for_each_safe(plist, ptmp, phead) {
2058 paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
2059
2060 if (paclnode->valid == true) {
2061 paclnode->valid = false;
2062
2063 list_del_init(&paclnode->list);
2064
2065 pacl_list->num--;
2066 }
2067 }
2068 spin_unlock_bh(&pacl_node_q->lock);
2069
2070 DBG_8723A("%s, free acl_node_queue, num =%d\n", __func__, pacl_list->num);
2071
2072 rtw_sta_flush23a(padapter);
2073
2074 /* free_assoc_sta_resources */
2075 rtw_free_all_stainfo23a(padapter);
2076
2077 psta = rtw_get_bcmc_stainfo23a(padapter);
2078 spin_lock_bh(&pstapriv->sta_hash_lock);
2079 rtw_free_stainfo23a(padapter, psta);
2080 spin_unlock_bh(&pstapriv->sta_hash_lock);
2081
2082 rtw_init_bcmc_stainfo23a(padapter);
2083
2084 rtw23a_free_mlme_priv_ie_data(pmlmepriv);
2085}
2086
2087#endif /* CONFIG_8723AU_AP_MODE */
diff --git a/drivers/staging/rtl8723au/core/rtw_cmd.c b/drivers/staging/rtl8723au/core/rtw_cmd.c
new file mode 100644
index 000000000000..5e3088a01800
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_cmd.c
@@ -0,0 +1,1876 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _RTW_CMD_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <recv_osdep.h>
20#include <cmd_osdep.h>
21#include <mlme_osdep.h>
22
23#ifdef CONFIG_8723AU_BT_COEXIST
24#include <rtl8723a_hal.h>
25#endif /* CONFIG_8723AU_BT_COEXIST */
26
27static struct cmd_hdl wlancmds[] = {
28 GEN_DRV_CMD_HANDLER(0, NULL) /*0*/
29 GEN_DRV_CMD_HANDLER(0, NULL)
30 GEN_DRV_CMD_HANDLER(0, NULL)
31 GEN_DRV_CMD_HANDLER(0, NULL)
32 GEN_DRV_CMD_HANDLER(0, NULL)
33 GEN_DRV_CMD_HANDLER(0, NULL)
34 GEN_MLME_EXT_HANDLER(0, NULL)
35 GEN_MLME_EXT_HANDLER(0, NULL)
36 GEN_MLME_EXT_HANDLER(0, NULL)
37 GEN_MLME_EXT_HANDLER(0, NULL)
38 GEN_MLME_EXT_HANDLER(0, NULL) /*10*/
39 GEN_MLME_EXT_HANDLER(0, NULL)
40 GEN_MLME_EXT_HANDLER(0, NULL)
41 GEN_MLME_EXT_HANDLER(0, NULL)
42 GEN_MLME_EXT_HANDLER(sizeof (struct wlan_bssid_ex), join_cmd_hdl23a) /*14*/
43 GEN_MLME_EXT_HANDLER(sizeof (struct disconnect_parm), disconnect_hdl23a)
44 GEN_MLME_EXT_HANDLER(sizeof (struct wlan_bssid_ex), createbss_hdl23a)
45 GEN_MLME_EXT_HANDLER(sizeof (struct setopmode_parm), setopmode_hdl23a)
46 GEN_MLME_EXT_HANDLER(sizeof (struct sitesurvey_parm), sitesurvey_cmd_hdl23a) /*18*/
47 GEN_MLME_EXT_HANDLER(sizeof (struct setauth_parm), setauth_hdl23a)
48 GEN_MLME_EXT_HANDLER(sizeof (struct setkey_parm), setkey_hdl23a) /*20*/
49 GEN_MLME_EXT_HANDLER(sizeof (struct set_stakey_parm), set_stakey_hdl23a)
50 GEN_MLME_EXT_HANDLER(sizeof (struct set_assocsta_parm), NULL)
51 GEN_MLME_EXT_HANDLER(sizeof (struct del_assocsta_parm), NULL)
52 GEN_MLME_EXT_HANDLER(sizeof (struct setstapwrstate_parm), NULL)
53 GEN_MLME_EXT_HANDLER(sizeof (struct setbasicrate_parm), NULL)
54 GEN_MLME_EXT_HANDLER(sizeof (struct getbasicrate_parm), NULL)
55 GEN_MLME_EXT_HANDLER(sizeof (struct setdatarate_parm), NULL)
56 GEN_MLME_EXT_HANDLER(sizeof (struct getdatarate_parm), NULL)
57 GEN_MLME_EXT_HANDLER(sizeof (struct setphyinfo_parm), NULL)
58 GEN_MLME_EXT_HANDLER(sizeof (struct getphyinfo_parm), NULL) /*30*/
59 GEN_MLME_EXT_HANDLER(sizeof (struct setphy_parm), NULL)
60 GEN_MLME_EXT_HANDLER(sizeof (struct getphy_parm), NULL)
61 GEN_MLME_EXT_HANDLER(0, NULL)
62 GEN_MLME_EXT_HANDLER(0, NULL)
63 GEN_MLME_EXT_HANDLER(0, NULL)
64 GEN_MLME_EXT_HANDLER(0, NULL)
65 GEN_MLME_EXT_HANDLER(0, NULL)
66 GEN_MLME_EXT_HANDLER(0, NULL)
67 GEN_MLME_EXT_HANDLER(0, NULL)
68 GEN_MLME_EXT_HANDLER(0, NULL) /*40*/
69 GEN_MLME_EXT_HANDLER(0, NULL)
70 GEN_MLME_EXT_HANDLER(0, NULL)
71 GEN_MLME_EXT_HANDLER(0, NULL)
72 GEN_MLME_EXT_HANDLER(0, NULL)
73 GEN_MLME_EXT_HANDLER(sizeof(struct addBaReq_parm), add_ba_hdl23a)
74 GEN_MLME_EXT_HANDLER(sizeof(struct set_ch_parm), set_ch_hdl23a) /* 46 */
75 GEN_MLME_EXT_HANDLER(0, NULL)
76 GEN_MLME_EXT_HANDLER(0, NULL)
77 GEN_MLME_EXT_HANDLER(0, NULL)
78 GEN_MLME_EXT_HANDLER(0, NULL) /*50*/
79 GEN_MLME_EXT_HANDLER(0, NULL)
80 GEN_MLME_EXT_HANDLER(0, NULL)
81 GEN_MLME_EXT_HANDLER(0, NULL)
82 GEN_MLME_EXT_HANDLER(0, NULL)
83 GEN_MLME_EXT_HANDLER(sizeof(struct Tx_Beacon_param), tx_beacon_hdl23a) /*55*/
84
85 GEN_MLME_EXT_HANDLER(0, mlme_evt_hdl23a) /*56*/
86 GEN_MLME_EXT_HANDLER(0, rtw_drvextra_cmd_hdl23a) /*57*/
87
88 GEN_MLME_EXT_HANDLER(0, h2c_msg_hdl23a) /*58*/
89 GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelPlan_param), set_chplan_hdl23a) /*59*/
90 GEN_MLME_EXT_HANDLER(sizeof(struct LedBlink_param), led_blink_hdl23a) /*60*/
91
92 GEN_MLME_EXT_HANDLER(sizeof(struct SetChannelSwitch_param), set_csa_hdl23a) /*61*/
93 GEN_MLME_EXT_HANDLER(sizeof(struct TDLSoption_param), tdls_hdl23a) /*62*/
94};
95
96struct _cmd_callback rtw_cmd_callback[] = {
97 {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/
98 {GEN_CMD_CODE(_Write_MACREG), NULL},
99 {GEN_CMD_CODE(_Read_BBREG), &rtw_getbbrfreg_cmdrsp_callback23a},
100 {GEN_CMD_CODE(_Write_BBREG), NULL},
101 {GEN_CMD_CODE(_Read_RFREG), &rtw_getbbrfreg_cmdrsp_callback23a},
102 {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/
103 {GEN_CMD_CODE(_Read_EEPROM), NULL},
104 {GEN_CMD_CODE(_Write_EEPROM), NULL},
105 {GEN_CMD_CODE(_Read_EFUSE), NULL},
106 {GEN_CMD_CODE(_Write_EFUSE), NULL},
107
108 {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/
109 {GEN_CMD_CODE(_Write_CAM), NULL},
110 {GEN_CMD_CODE(_setBCNITV), NULL},
111 {GEN_CMD_CODE(_setMBIDCFG), NULL},
112 {GEN_CMD_CODE(_JoinBss), &rtw_joinbss_cmd23a_callback}, /*14*/
113 {GEN_CMD_CODE(_DisConnect), &rtw_disassoc_cmd23a_callback}, /*15*/
114 {GEN_CMD_CODE(_CreateBss), &rtw_createbss_cmd23a_callback},
115 {GEN_CMD_CODE(_SetOpMode), NULL},
116 {GEN_CMD_CODE(_SiteSurvey), &rtw_survey_cmd_callback23a}, /*18*/
117 {GEN_CMD_CODE(_SetAuth), NULL},
118
119 {GEN_CMD_CODE(_SetKey), NULL}, /*20*/
120 {GEN_CMD_CODE(_SetStaKey), &rtw_setstaKey_cmdrsp_callback23a},
121 {GEN_CMD_CODE(_SetAssocSta), &rtw_setassocsta_cmdrsp_callback23a},
122 {GEN_CMD_CODE(_DelAssocSta), NULL},
123 {GEN_CMD_CODE(_SetStaPwrState), NULL},
124 {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/
125 {GEN_CMD_CODE(_GetBasicRate), NULL},
126 {GEN_CMD_CODE(_SetDataRate), NULL},
127 {GEN_CMD_CODE(_GetDataRate), NULL},
128 {GEN_CMD_CODE(_SetPhyInfo), NULL},
129
130 {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/
131 {GEN_CMD_CODE(_SetPhy), NULL},
132 {GEN_CMD_CODE(_GetPhy), NULL},
133 {GEN_CMD_CODE(_readRssi), NULL},
134 {GEN_CMD_CODE(_readGain), NULL},
135 {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/
136 {GEN_CMD_CODE(_SetPwrMode), NULL},
137 {GEN_CMD_CODE(_JoinbssRpt), NULL},
138 {GEN_CMD_CODE(_SetRaTable), NULL},
139 {GEN_CMD_CODE(_GetRaTable), NULL},
140
141 {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/
142 {GEN_CMD_CODE(_GetDTMReport), NULL},
143 {GEN_CMD_CODE(_GetTXRateStatistics), NULL},
144 {GEN_CMD_CODE(_SetUsbSuspend), NULL},
145 {GEN_CMD_CODE(_SetH2cLbk), NULL},
146 {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/
147 {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/
148 {GEN_CMD_CODE(_SetTxPower), NULL},
149 {GEN_CMD_CODE(_SwitchAntenna), NULL},
150 {GEN_CMD_CODE(_SetCrystalCap), NULL},
151 {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/
152
153 {GEN_CMD_CODE(_SetSingleToneTx), NULL}, /*51*/
154 {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL},
155 {GEN_CMD_CODE(_SetContinuousTx), NULL},
156 {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/
157 {GEN_CMD_CODE(_TX_Beacon), NULL},/*55*/
158
159 {GEN_CMD_CODE(_Set_MLME_EVT), NULL},/*56*/
160 {GEN_CMD_CODE(_Set_Drv_Extra), NULL},/*57*/
161 {GEN_CMD_CODE(_Set_H2C_MSG), NULL},/*58*/
162 {GEN_CMD_CODE(_SetChannelPlan), NULL},/*59*/
163 {GEN_CMD_CODE(_LedBlink), NULL},/*60*/
164
165 {GEN_CMD_CODE(_SetChannelSwitch), NULL},/*61*/
166 {GEN_CMD_CODE(_TDLS), NULL},/*62*/
167};
168
169/*
170Caller and the rtw_cmd_thread23a can protect cmd_q by spin_lock.
171No irqsave is necessary.
172*/
173
174int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv)
175{
176 int res = _SUCCESS;
177
178 sema_init(&pcmdpriv->cmd_queue_sema, 0);
179 sema_init(&pcmdpriv->terminate_cmdthread_sema, 0);
180
181 _rtw_init_queue23a(&pcmdpriv->cmd_queue);
182
183 pcmdpriv->cmd_seq = 1;
184
185 pcmdpriv->cmd_allocated_buf = kzalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ,
186 GFP_KERNEL);
187
188 if (pcmdpriv->cmd_allocated_buf == NULL) {
189 res = _FAIL;
190 goto exit;
191 }
192
193 pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ -
194 ((unsigned long)(pcmdpriv->cmd_allocated_buf) &
195 (CMDBUFF_ALIGN_SZ - 1));
196
197 pcmdpriv->rsp_allocated_buf = kzalloc(MAX_RSPSZ + 4, GFP_KERNEL);
198
199 if (!pcmdpriv->rsp_allocated_buf) {
200 res = _FAIL;
201 goto exit;
202 }
203
204 pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 -
205 ((unsigned long)(pcmdpriv->rsp_allocated_buf) & 3);
206
207 pcmdpriv->cmd_issued_cnt = 0;
208 pcmdpriv->cmd_done_cnt = 0;
209 pcmdpriv->rsp_cnt = 0;
210
211exit:
212
213 return res;
214}
215
216/* forward definition */
217
218static void c2h_wk_callback(struct work_struct *work);
219int _rtw_init_evt_priv23a(struct evt_priv *pevtpriv)
220{
221 int res = _SUCCESS;
222
223 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
224 atomic_set(&pevtpriv->event_seq, 0);
225 pevtpriv->evt_done_cnt = 0;
226
227 INIT_WORK(&pevtpriv->c2h_wk, c2h_wk_callback);
228 pevtpriv->c2h_wk_alive = false;
229 pevtpriv->c2h_queue = rtw_cbuf_alloc23a(C2H_QUEUE_MAX_LEN + 1);
230
231 return res;
232}
233
234void _rtw_free_evt_priv23a (struct evt_priv *pevtpriv)
235{
236 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
237 ("+_rtw_free_evt_priv23a\n"));
238 cancel_work_sync(&pevtpriv->c2h_wk);
239 while(pevtpriv->c2h_wk_alive)
240 msleep(10);
241
242 while (!rtw_cbuf_empty23a(pevtpriv->c2h_queue)) {
243 void *c2h;
244 if ((c2h = rtw_cbuf_pop23a(pevtpriv->c2h_queue)) != NULL &&
245 c2h != (void *)pevtpriv) {
246 kfree(c2h);
247 }
248 }
249
250 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
251 ("-_rtw_free_evt_priv23a\n"));
252}
253
254void _rtw_free_cmd_priv23a(struct cmd_priv *pcmdpriv)
255{
256 if (pcmdpriv) {
257 kfree(pcmdpriv->cmd_allocated_buf);
258 kfree(pcmdpriv->rsp_allocated_buf);
259 }
260}
261
262/*
263Calling Context:
264rtw_enqueue_cmd23a can only be called between kernel thread,
265since only spin_lock is used.
266
267ISR/Call-Back functions can't call this sub-function.
268*/
269
270int _rtw_enqueue_cmd23a(struct rtw_queue *queue, struct cmd_obj *obj)
271{
272 unsigned long irqL;
273
274 if (obj == NULL)
275 goto exit;
276
277 spin_lock_irqsave(&queue->lock, irqL);
278
279 list_add_tail(&obj->list, &queue->queue);
280
281 spin_unlock_irqrestore(&queue->lock, irqL);
282
283exit:
284
285 return _SUCCESS;
286}
287
288u32 rtw_init_evt_priv23a(struct evt_priv *pevtpriv)
289{
290 int res;
291
292 res = _rtw_init_evt_priv23a(pevtpriv);
293
294 return res;
295}
296
297void rtw_free_evt_priv23a(struct evt_priv *pevtpriv)
298{
299 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
300 ("rtw_free_evt_priv23a\n"));
301 _rtw_free_evt_priv23a(pevtpriv);
302}
303
304void rtw_free_cmd_priv23a(struct cmd_priv *pcmdpriv)
305{
306 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
307 ("rtw_free_cmd_priv23a\n"));
308 _rtw_free_cmd_priv23a(pcmdpriv);
309}
310
311static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
312{
313 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
314 /* set to true to allow enqueuing cmd when hw_init_completed is false */
315 u8 bAllow = false;
316
317 /* To decide allow or not */
318 if (pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect &&
319 !pcmdpriv->padapter->registrypriv.usbss_enable) {
320 if (cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
321 pdrvextra_cmd_parm =
322 (struct drvextra_cmd_parm *)cmd_obj->parmbuf;
323 if (pdrvextra_cmd_parm->ec_id ==
324 POWER_SAVING_CTRL_WK_CID)
325 bAllow = true;
326 }
327 }
328
329 if (cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
330 bAllow = true;
331
332 if ((pcmdpriv->padapter->hw_init_completed == false &&
333 bAllow == false) || pcmdpriv->cmdthd_running == false)
334 return _FAIL;
335 return _SUCCESS;
336}
337
338u32 rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
339{
340 int res = _FAIL;
341 struct rtw_adapter *padapter = pcmdpriv->padapter;
342
343 if (!cmd_obj)
344 goto exit;
345
346 cmd_obj->padapter = padapter;
347
348 res = rtw_cmd_filter(pcmdpriv, cmd_obj);
349 if (res == _FAIL) {
350 rtw_free_cmd_obj23a(cmd_obj);
351 goto exit;
352 }
353
354 res = _rtw_enqueue_cmd23a(&pcmdpriv->cmd_queue, cmd_obj);
355
356 if (res == _SUCCESS)
357 up(&pcmdpriv->cmd_queue_sema);
358
359exit:
360 return res;
361}
362
363static struct cmd_obj *rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
364{
365 struct cmd_obj *obj;
366 struct rtw_queue *queue = &pcmdpriv->cmd_queue;
367 unsigned long irqL;
368
369 spin_lock_irqsave(&queue->lock, irqL);
370 if (list_empty(&queue->queue))
371 obj = NULL;
372 else {
373 obj = container_of((&queue->queue)->next, struct cmd_obj, list);
374 list_del_init(&obj->list);
375 }
376
377 spin_unlock_irqrestore(&queue->lock, irqL);
378
379 return obj;
380}
381
382void rtw_cmd_clr_isr23a(struct cmd_priv *pcmdpriv)
383{
384 pcmdpriv->cmd_done_cnt++;
385}
386
387void rtw_free_cmd_obj23a(struct cmd_obj *pcmd)
388{
389
390 if (pcmd->cmdcode != _JoinBss_CMD_ &&
391 pcmd->cmdcode != _CreateBss_CMD_) {
392 /* free parmbuf in cmd_obj */
393 kfree(pcmd->parmbuf);
394 }
395
396 if (pcmd->rsp) {
397 if (pcmd->rspsz != 0) {
398 /* free rsp in cmd_obj */
399 kfree(pcmd->rsp);
400 }
401 }
402
403 kfree(pcmd);
404}
405
406int rtw_cmd_thread23a(void *context)
407{
408 u8 ret;
409 struct cmd_obj *pcmd;
410 u8 *pcmdbuf, *prspbuf;
411 u8 (*cmd_hdl)(struct rtw_adapter *padapter, u8* pbuf);
412 void (*pcmd_callback)(struct rtw_adapter *dev, struct cmd_obj *pcmd);
413 struct rtw_adapter *padapter = (struct rtw_adapter *)context;
414 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
415
416 allow_signal(SIGTERM);
417
418 pcmdbuf = pcmdpriv->cmd_buf;
419 prspbuf = pcmdpriv->rsp_buf;
420
421 pcmdpriv->cmdthd_running = true;
422 up(&pcmdpriv->terminate_cmdthread_sema);
423
424 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
425 ("start r871x rtw_cmd_thread23a !!!!\n"));
426
427 while(1) {
428 if (down_interruptible(&pcmdpriv->cmd_queue_sema))
429 break;
430_next:
431 if ((padapter->bDriverStopped == true) ||
432 (padapter->bSurpriseRemoved == true)) {
433 DBG_8723A("%s: DriverStopped(%d) SurpriseRemoved(%d) "
434 "break at line %d\n", __func__,
435 padapter->bDriverStopped,
436 padapter->bSurpriseRemoved, __LINE__);
437 break;
438 }
439
440 if (!(pcmd = rtw_dequeue_cmd(pcmdpriv)))
441 continue;
442
443 if (rtw_cmd_filter(pcmdpriv, pcmd) == _FAIL) {
444 pcmd->res = H2C_DROPPED;
445 goto post_process;
446 }
447
448 pcmdpriv->cmd_issued_cnt++;
449
450 pcmd->cmdsz = ALIGN(pcmd->cmdsz, 4);
451
452 memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
453
454 if (pcmd->cmdcode < (sizeof(wlancmds)/sizeof(struct cmd_hdl))) {
455 cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
456
457 if (cmd_hdl) {
458 ret = cmd_hdl(pcmd->padapter, pcmdbuf);
459 pcmd->res = ret;
460 }
461
462 pcmdpriv->cmd_seq++;
463 } else
464 pcmd->res = H2C_PARAMETERS_ERROR;
465
466 cmd_hdl = NULL;
467
468post_process:
469 /* call callback function for post-processed */
470 if (pcmd->cmdcode < (sizeof(rtw_cmd_callback) /
471 sizeof(struct _cmd_callback))) {
472 pcmd_callback =
473 rtw_cmd_callback[pcmd->cmdcode].callback;
474 if (!pcmd_callback) {
475 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
476 ("mlme_cmd_hdl(): pcmd_callback = "
477 "0x%p, cmdcode = 0x%x\n",
478 pcmd_callback, pcmd->cmdcode));
479 rtw_free_cmd_obj23a(pcmd);
480 } else {
481 /* todo: !!! fill rsp_buf to pcmd->rsp
482 if (pcmd->rsp!= NULL) */
483 /* need conider that free cmd_obj in
484 rtw_cmd_callback */
485 pcmd_callback(pcmd->padapter, pcmd);
486 }
487 } else {
488 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
489 ("%s: cmdcode = 0x%x callback not defined!\n",
490 __func__, pcmd->cmdcode));
491 rtw_free_cmd_obj23a(pcmd);
492 }
493
494 if (signal_pending (current))
495 flush_signals(current);
496
497 goto _next;
498
499 }
500 pcmdpriv->cmdthd_running = false;
501
502 /* free all cmd_obj resources */
503 do {
504 pcmd = rtw_dequeue_cmd(pcmdpriv);
505 if (!pcmd)
506 break;
507
508 rtw_free_cmd_obj23a(pcmd);
509 } while(1);
510
511 up(&pcmdpriv->terminate_cmdthread_sema);
512
513 complete_and_exit(NULL, 0);
514}
515
516u8 rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter,
517 struct cfg80211_ssid *ssid, int ssid_num,
518 struct rtw_ieee80211_channel *ch, int ch_num)
519{
520 u8 res = _FAIL;
521 struct cmd_obj *ph2c;
522 struct sitesurvey_parm *psurveyPara;
523 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
524 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
525
526 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
527 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SCAN, 1);
528
529#ifdef CONFIG_8723AU_P2P
530 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
531 p2p_ps_wk_cmd23a(padapter, P2P_PS_SCAN, 1);
532 }
533#endif /* CONFIG_8723AU_P2P */
534
535 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
536 if (!ph2c)
537 return _FAIL;
538
539 psurveyPara = kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
540 if (!psurveyPara) {
541 kfree(ph2c);
542 return _FAIL;
543 }
544
545 rtw_free_network_queue23a(padapter, false);
546
547 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
548 ("%s: flush network queue\n", __func__));
549
550 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
551 GEN_CMD_CODE(_SiteSurvey));
552
553 /* psurveyPara->bsslimit = 48; */
554 psurveyPara->scan_mode = pmlmepriv->scan_mode;
555
556 /* prepare ssid list */
557 if (ssid) {
558 int i;
559 for (i = 0; i < ssid_num && i < RTW_SSID_SCAN_AMOUNT; i++) {
560 if (ssid[i].ssid_len) {
561 memcpy(&psurveyPara->ssid[i], &ssid[i],
562 sizeof(struct cfg80211_ssid));
563 psurveyPara->ssid_num++;
564 if (0)
565 DBG_8723A(FUNC_ADPT_FMT" ssid:(%s, %d)\n",
566 FUNC_ADPT_ARG(padapter),
567 psurveyPara->ssid[i].ssid,
568 psurveyPara->ssid[i].ssid_len);
569 }
570 }
571 }
572
573 /* prepare channel list */
574 if (ch) {
575 int i;
576 for (i = 0; i < ch_num && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
577 if (ch[i].hw_value &&
578 !(ch[i].flags & IEEE80211_CHAN_DISABLED)) {
579 memcpy(&psurveyPara->ch[i], &ch[i],
580 sizeof(struct rtw_ieee80211_channel));
581 psurveyPara->ch_num++;
582 if (0)
583 DBG_8723A(FUNC_ADPT_FMT" ch:%u\n",
584 FUNC_ADPT_ARG(padapter),
585 psurveyPara->ch[i].hw_value);
586 }
587 }
588 }
589
590 set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
591
592 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
593
594 if (res == _SUCCESS) {
595 mod_timer(&pmlmepriv->scan_to_timer, jiffies +
596 msecs_to_jiffies(SCANNING_TIMEOUT));
597
598 rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
599
600 pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
601 } else
602 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
603
604 return res;
605}
606
607void rtw_getbbrfreg_cmdrsp_callback23a(struct rtw_adapter *padapter,
608 struct cmd_obj *pcmd)
609{
610 kfree(pcmd->parmbuf);
611 kfree(pcmd);
612}
613
614u8 rtw_createbss_cmd23a(struct rtw_adapter *padapter)
615{
616 struct cmd_obj *pcmd;
617 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
618 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
619 struct wlan_bssid_ex *pdev_network;
620 u8 res = _SUCCESS;
621
622 pdev_network = &padapter->registrypriv.dev_network;
623
624 rtw_led_control(padapter, LED_CTL_START_TO_LINK);
625
626 if (pmlmepriv->assoc_ssid.ssid_len == 0) {
627 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
628 (" createbss for Any SSid:%s\n",
629 pmlmepriv->assoc_ssid.ssid));
630 } else {
631 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
632 (" createbss for SSid:%s\n",
633 pmlmepriv->assoc_ssid.ssid));
634 }
635
636 pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
637 if (!pcmd) {
638 res = _FAIL;
639 goto exit;
640 }
641
642 INIT_LIST_HEAD(&pcmd->list);
643 pcmd->cmdcode = _CreateBss_CMD_;
644 pcmd->parmbuf = (unsigned char *)pdev_network;
645 pcmd->cmdsz = get_wlan_bssid_ex_sz((struct wlan_bssid_ex*)pdev_network);
646 pcmd->rsp = NULL;
647 pcmd->rspsz = 0;
648
649 pdev_network->Length = pcmd->cmdsz;
650
651 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
652
653exit:
654
655 return res;
656}
657
658u8 rtw_joinbss_cmd23a(struct rtw_adapter *padapter,
659 struct wlan_network * pnetwork)
660{
661 u8 *auth, res = _SUCCESS;
662 uint t_len = 0;
663 struct wlan_bssid_ex *psecnetwork;
664 struct cmd_obj *pcmd;
665 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
666 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
667 struct qos_priv *pqospriv = &pmlmepriv->qospriv;
668 struct security_priv *psecuritypriv = &padapter->securitypriv;
669 struct registry_priv *pregistrypriv = &padapter->registrypriv;
670 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
671 enum ndis_802_11_net_infra ndis_network_mode;
672 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
673 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
674
675 ndis_network_mode = pnetwork->network.InfrastructureMode;
676
677 rtw_led_control(padapter, LED_CTL_START_TO_LINK);
678
679 if (pmlmepriv->assoc_ssid.ssid_len == 0) {
680 RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
681 ("+Join cmd: Any SSid\n"));
682 } else {
683 RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_,
684 ("+Join cmd: SSid =[%s]\n",
685 pmlmepriv->assoc_ssid.ssid));
686 }
687
688 pcmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
689 if (!pcmd) {
690 res = _FAIL;
691 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
692 ("rtw_joinbss_cmd23a: memory allocate for cmd_obj "
693 "fail!!!\n"));
694 goto exit;
695 }
696 /* for IEs is fix buf size */
697 t_len = sizeof(struct wlan_bssid_ex);
698
699 /* for hidden ap to set fw_state here */
700 if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE)) {
701 switch (ndis_network_mode) {
702 case Ndis802_11IBSS:
703 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
704 break;
705 case Ndis802_11Infrastructure:
706 set_fwstate(pmlmepriv, WIFI_STATION_STATE);
707 break;
708 case Ndis802_11APMode:
709 case Ndis802_11AutoUnknown:
710 case Ndis802_11InfrastructureMax:
711 break;
712 }
713 }
714
715 psecnetwork = (struct wlan_bssid_ex *)&psecuritypriv->sec_bss;
716 if (!psecnetwork) {
717 if (pcmd)
718 kfree(pcmd);
719
720 res = _FAIL;
721
722 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
723 ("rtw_joinbss_cmd23a :psecnetwork == NULL!!!\n"));
724
725 goto exit;
726 }
727
728 memset(psecnetwork, 0, t_len);
729
730 memcpy(psecnetwork, &pnetwork->network,
731 get_wlan_bssid_ex_sz(&pnetwork->network));
732
733 auth = &psecuritypriv->authenticator_ie[0];
734 psecuritypriv->authenticator_ie[0] =
735 (unsigned char)psecnetwork->IELength;
736
737 if ((psecnetwork->IELength-12) < (256-1)) {
738 memcpy(&psecuritypriv->authenticator_ie[1],
739 &psecnetwork->IEs[12], psecnetwork->IELength - 12);
740 } else {
741 memcpy(&psecuritypriv->authenticator_ie[1],
742 &psecnetwork->IEs[12], 256 - 1);
743 }
744
745 psecnetwork->IELength = 0;
746 /* Added by Albert 2009/02/18 */
747 /* If the the driver wants to use the bssid to create the
748 * connection. If not, we have to copy the connecting AP's
749 * MAC address to it so that the driver just has the bssid
750 * information for PMKIDList searching. */
751
752 if (pmlmepriv->assoc_by_bssid == false)
753 ether_addr_copy(&pmlmepriv->assoc_bssid[0],
754 &pnetwork->network.MacAddress[0]);
755
756 psecnetwork->IELength =
757 rtw_restruct_sec_ie23a(padapter, &pnetwork->network.IEs[0],
758 &psecnetwork->IEs[0],
759 pnetwork->network.IELength);
760
761 pqospriv->qos_option = 0;
762
763 if (pregistrypriv->wmm_enable) {
764 u32 tmp_len;
765
766 tmp_len = rtw_restruct_wmm_ie23a(padapter,
767 &pnetwork->network.IEs[0],
768 &psecnetwork->IEs[0],
769 pnetwork->network.IELength,
770 psecnetwork->IELength);
771
772 if (psecnetwork->IELength != tmp_len) {
773 psecnetwork->IELength = tmp_len;
774 /* There is WMM IE in this corresp. beacon */
775 pqospriv->qos_option = 1;
776 } else {
777 /* There is no WMM IE in this corresp. beacon */
778 pqospriv->qos_option = 0;
779 }
780 }
781
782 phtpriv->ht_option = false;
783 if (pregistrypriv->ht_enable) {
784 /* Added by Albert 2010/06/23 */
785 /* For the WEP mode, we will use the bg mode to do
786 the connection to avoid some IOT issue. */
787 /* Especially for Realtek 8192u SoftAP. */
788 if ((padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_) &&
789 (padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_) &&
790 (padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_)) {
791 /* rtw_restructure_ht_ie23a */
792 rtw_restructure_ht_ie23a(padapter,
793 &pnetwork->network.IEs[0],
794 &psecnetwork->IEs[0],
795 pnetwork->network.IELength,
796 &psecnetwork->IELength);
797 }
798 }
799
800 pmlmeinfo->assoc_AP_vendor =
801 check_assoc_AP23a(pnetwork->network.IEs,
802 pnetwork->network.IELength);
803
804 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA)
805 padapter->pwrctrlpriv.smart_ps = 0;
806 else
807 padapter->pwrctrlpriv.smart_ps =
808 padapter->registrypriv.smart_ps;
809
810 DBG_8723A("%s: smart_ps =%d\n", __func__,
811 padapter->pwrctrlpriv.smart_ps);
812
813 /* get cmdsz before endian conversion */
814 pcmd->cmdsz = get_wlan_bssid_ex_sz(psecnetwork);
815
816 INIT_LIST_HEAD(&pcmd->list);
817 pcmd->cmdcode = _JoinBss_CMD_;/* GEN_CMD_CODE(_JoinBss) */
818 pcmd->parmbuf = (unsigned char *)psecnetwork;
819 pcmd->rsp = NULL;
820 pcmd->rspsz = 0;
821
822 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
823exit:
824
825 return res;
826}
827
828u8 rtw_disassoc_cmd23a(struct rtw_adapter*padapter, u32 deauth_timeout_ms,
829 bool enqueue)
830{
831 struct cmd_obj *cmdobj = NULL;
832 struct disconnect_parm *param = NULL;
833 struct cmd_priv *cmdpriv = &padapter->cmdpriv;
834 u8 res = _SUCCESS;
835
836 RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_,
837 ("+rtw_disassoc_cmd23a\n"));
838
839 /* prepare cmd parameter */
840 param = kzalloc(sizeof(*param), GFP_ATOMIC);
841 if (param == NULL) {
842 res = _FAIL;
843 goto exit;
844 }
845 param->deauth_timeout_ms = deauth_timeout_ms;
846
847 if (enqueue) {
848 /* need enqueue, prepare cmd_obj and enqueue */
849 cmdobj = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
850 if (!cmdobj) {
851 res = _FAIL;
852 kfree(param);
853 goto exit;
854 }
855 init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
856 res = rtw_enqueue_cmd23a(cmdpriv, cmdobj);
857 } else {
858 /* no need to enqueue, do the cmd hdl directly and
859 free cmd parameter */
860 if (H2C_SUCCESS != disconnect_hdl23a(padapter, (u8 *)param))
861 res = _FAIL;
862 kfree(param);
863 }
864
865exit:
866 return res;
867}
868
869u8 rtw_setopmode_cmd23a(struct rtw_adapter *padapter,
870 enum ndis_802_11_net_infra networktype)
871{
872 struct cmd_obj *ph2c;
873 struct setopmode_parm *psetop;
874 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
875 u8 res = _SUCCESS;
876
877 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
878 if (!ph2c) {
879 res = false;
880 goto exit;
881 }
882 psetop = kzalloc(sizeof(struct setopmode_parm), GFP_KERNEL);
883
884 if (!psetop) {
885 kfree(ph2c);
886 res = false;
887 goto exit;
888 }
889
890 init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
891 psetop->mode = (u8)networktype;
892
893 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
894exit:
895 return res;
896}
897
898u8 rtw_setstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 unicast_key)
899{
900 struct cmd_obj *ph2c;
901 struct set_stakey_parm *psetstakey_para;
902 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
903 struct set_stakey_rsp *psetstakey_rsp = NULL;
904 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
905 struct security_priv *psecuritypriv = &padapter->securitypriv;
906 struct sta_info *sta = (struct sta_info*)psta;
907 u8 res = _SUCCESS;
908
909 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
910 if (!ph2c) {
911 res = _FAIL;
912 goto exit;
913 }
914
915 psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
916 if (!psetstakey_para) {
917 kfree(ph2c);
918 res = _FAIL;
919 goto exit;
920 }
921
922 psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp), GFP_KERNEL);
923 if (!psetstakey_rsp) {
924 kfree(ph2c);
925 kfree(psetstakey_para);
926 res = _FAIL;
927 goto exit;
928 }
929
930 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
931 ph2c->rsp = (u8 *) psetstakey_rsp;
932 ph2c->rspsz = sizeof(struct set_stakey_rsp);
933
934 ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
935
936 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
937 psetstakey_para->algorithm =
938 (unsigned char)psecuritypriv->dot11PrivacyAlgrthm;
939 } else {
940 GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm,
941 false);
942 }
943
944 if (unicast_key == true) {
945 memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
946 } else {
947 int idx = psecuritypriv->dot118021XGrpKeyid;
948 memcpy(&psetstakey_para->key,
949 &psecuritypriv->dot118021XGrpKey[idx].skey, 16);
950 }
951
952 /* jeff: set this becasue at least sw key is ready */
953 padapter->securitypriv.busetkipkey = true;
954
955 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
956
957exit:
958
959 return res;
960}
961
962u8 rtw_clearstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 entry,
963 u8 enqueue)
964{
965 struct cmd_obj *ph2c;
966 struct set_stakey_parm *psetstakey_para;
967 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
968 struct set_stakey_rsp *psetstakey_rsp = NULL;
969 struct sta_info *sta = (struct sta_info *)psta;
970 u8 res = _SUCCESS;
971
972 if (!enqueue) {
973 clear_cam_entry23a(padapter, entry);
974 } else {
975 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
976 if (!ph2c) {
977 res = _FAIL;
978 goto exit;
979 }
980
981 psetstakey_para = kzalloc(sizeof(struct set_stakey_parm),
982 GFP_KERNEL);
983 if (!psetstakey_para) {
984 kfree(ph2c);
985 res = _FAIL;
986 goto exit;
987 }
988
989 psetstakey_rsp = kzalloc(sizeof(struct set_stakey_rsp),
990 GFP_KERNEL);
991 if (!psetstakey_rsp) {
992 kfree(ph2c);
993 kfree(psetstakey_para);
994 res = _FAIL;
995 goto exit;
996 }
997
998 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para,
999 _SetStaKey_CMD_);
1000 ph2c->rsp = (u8 *) psetstakey_rsp;
1001 ph2c->rspsz = sizeof(struct set_stakey_rsp);
1002
1003 ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
1004
1005 psetstakey_para->algorithm = _NO_PRIVACY_;
1006
1007 psetstakey_para->id = entry;
1008
1009 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1010 }
1011exit:
1012 return res;
1013}
1014
1015u8 rtw_addbareq_cmd23a(struct rtw_adapter*padapter, u8 tid, u8 *addr)
1016{
1017 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1018 struct cmd_obj *ph2c;
1019 struct addBaReq_parm *paddbareq_parm;
1020 u8 res = _SUCCESS;
1021
1022 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1023 if (!ph2c) {
1024 res = _FAIL;
1025 goto exit;
1026 }
1027
1028 paddbareq_parm = kzalloc(sizeof(struct addBaReq_parm), GFP_ATOMIC);
1029 if (!paddbareq_parm) {
1030 kfree(ph2c);
1031 res = _FAIL;
1032 goto exit;
1033 }
1034
1035 paddbareq_parm->tid = tid;
1036 ether_addr_copy(paddbareq_parm->addr, addr);
1037
1038 init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm,
1039 GEN_CMD_CODE(_AddBAReq));
1040
1041 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1042exit:
1043 return res;
1044}
1045
1046u8 rtw_dynamic_chk_wk_cmd23a(struct rtw_adapter*padapter)
1047{
1048 struct cmd_obj *ph2c;
1049 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1050 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1051 u8 res = _SUCCESS;
1052
1053 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1054 if (!ph2c) {
1055 res = _FAIL;
1056 goto exit;
1057 }
1058
1059 pdrvextra_cmd_parm = kzalloc(sizeof(*pdrvextra_cmd_parm), GFP_ATOMIC);
1060 if (!pdrvextra_cmd_parm) {
1061 kfree(ph2c);
1062 res = _FAIL;
1063 goto exit;
1064 }
1065
1066 pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
1067 pdrvextra_cmd_parm->type_size = 0;
1068 pdrvextra_cmd_parm->pbuf = (u8 *)padapter;
1069
1070 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1071 GEN_CMD_CODE(_Set_Drv_Extra));
1072
1073 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1074exit:
1075
1076 return res;
1077}
1078
1079/*
1080 * This is only ever called from on_action_spct23a_ch_switch () which isn't
1081 * called from anywhere itself
1082 */
1083u8 rtw_set_ch_cmd23a(struct rtw_adapter*padapter, u8 ch, u8 bw, u8 ch_offset,
1084 u8 enqueue)
1085{
1086 struct cmd_obj *pcmdobj;
1087 struct set_ch_parm *set_ch_parm;
1088 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1089
1090 u8 res = _SUCCESS;
1091
1092 DBG_8723A(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
1093 FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
1094
1095 /* check input parameter */
1096
1097 /* prepare cmd parameter */
1098 set_ch_parm = kzalloc(sizeof(*set_ch_parm), GFP_KERNEL);
1099 if (!set_ch_parm) {
1100 res = _FAIL;
1101 goto exit;
1102 }
1103 set_ch_parm->ch = ch;
1104 set_ch_parm->bw = bw;
1105 set_ch_parm->ch_offset = ch_offset;
1106
1107 if (enqueue) {
1108 /* need enqueue, prepare cmd_obj and enqueue */
1109 pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1110 if (!pcmdobj) {
1111 kfree(set_ch_parm);
1112 res = _FAIL;
1113 goto exit;
1114 }
1115
1116 init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm,
1117 GEN_CMD_CODE(_SetChannel));
1118 res = rtw_enqueue_cmd23a(pcmdpriv, pcmdobj);
1119 } else {
1120 /* no need to enqueue, do the cmd hdl directly and
1121 free cmd parameter */
1122 if (H2C_SUCCESS != set_ch_hdl23a(padapter, (u8 *)set_ch_parm))
1123 res = _FAIL;
1124
1125 kfree(set_ch_parm);
1126 }
1127
1128 /* do something based on res... */
1129exit:
1130
1131 DBG_8723A(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev),
1132 res);
1133
1134 return res;
1135}
1136
1137static void traffic_status_watchdog(struct rtw_adapter *padapter)
1138{
1139 u8 bEnterPS;
1140 u8 bBusyTraffic = false, bTxBusyTraffic = false, bRxBusyTraffic = false;
1141 u8 bHigherBusyTraffic = false, bHigherBusyRxTraffic = false;
1142 u8 bHigherBusyTxTraffic = false;
1143 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1144#ifndef CONFIG_8723AU_BT_COEXIST
1145 int BusyThreshold = 100;
1146#endif
1147 /* */
1148 /* Determine if our traffic is busy now */
1149 /* */
1150 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1151#ifdef CONFIG_8723AU_BT_COEXIST
1152 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 50 ||
1153 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 50)
1154#else /* !CONFIG_8723AU_BT_COEXIST */
1155 /* if we raise bBusyTraffic in last watchdog, using
1156 lower threshold. */
1157 if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
1158 BusyThreshold = 75;
1159 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold ||
1160 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold)
1161#endif /* !CONFIG_8723AU_BT_COEXIST */
1162 {
1163 bBusyTraffic = true;
1164
1165 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod >
1166 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
1167 bRxBusyTraffic = true;
1168 else
1169 bTxBusyTraffic = true;
1170 }
1171
1172 /* Higher Tx/Rx data. */
1173 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
1174 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000) {
1175 bHigherBusyTraffic = true;
1176
1177 if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod >
1178 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
1179 bHigherBusyRxTraffic = true;
1180 else
1181 bHigherBusyTxTraffic = true;
1182 }
1183
1184#ifdef CONFIG_8723AU_BT_COEXIST
1185 if (BT_1Ant(padapter) == false)
1186#endif
1187 {
1188 /* check traffic for powersaving. */
1189 if (((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod +
1190 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
1191 (pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2))
1192 bEnterPS = false;
1193 else
1194 bEnterPS = true;
1195
1196 /* LeisurePS only work in infra mode. */
1197 if (bEnterPS)
1198 LPS_Enter23a(padapter);
1199 else
1200 LPS_Leave23a(padapter);
1201 }
1202 } else
1203 LPS_Leave23a(padapter);
1204
1205 pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
1206 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
1207 pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
1208 pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
1209 pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
1210 pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
1211 pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
1212 pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
1213 pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
1214}
1215
1216void dynamic_chk_wk_hdl(struct rtw_adapter *padapter, u8 *pbuf, int sz)
1217{
1218 struct mlme_priv *pmlmepriv;
1219
1220 padapter = (struct rtw_adapter *)pbuf;
1221 pmlmepriv = &padapter->mlmepriv;
1222
1223#ifdef CONFIG_8723AU_AP_MODE
1224 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
1225 expire_timeout_chk23a(padapter);
1226#endif
1227
1228 rtw_hal_sreset_xmit_status_check23a(padapter);
1229
1230 linked_status_chk23a(padapter);
1231 traffic_status_watchdog(padapter);
1232
1233 rtw_hal_dm_watchdog23a(padapter);
1234
1235#ifdef CONFIG_8723AU_BT_COEXIST
1236 /* */
1237 /* BT-Coexist */
1238 /* */
1239 BT_CoexistMechanism(padapter);
1240#endif
1241}
1242
1243void lps_ctrl_wk_hdl(struct rtw_adapter *padapter, u8 lps_ctrl_type)
1244{
1245 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1246 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1247 u8 mstatus;
1248
1249 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
1250 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
1251 return;
1252
1253 switch (lps_ctrl_type)
1254 {
1255 case LPS_CTRL_SCAN:
1256#ifdef CONFIG_8723AU_BT_COEXIST
1257 BT_WifiScanNotify(padapter, true);
1258 if (BT_1Ant(padapter) == false)
1259#endif
1260 {
1261 if (check_fwstate(pmlmepriv, _FW_LINKED))
1262 LPS_Leave23a(padapter);
1263 }
1264 break;
1265 case LPS_CTRL_JOINBSS:
1266 LPS_Leave23a(padapter);
1267 break;
1268 case LPS_CTRL_CONNECT:
1269 mstatus = 1;/* connect */
1270 /* Reset LPS Setting */
1271 padapter->pwrctrlpriv.LpsIdleCount = 0;
1272 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_JOINBSSRPT,
1273 (u8 *)&mstatus);
1274#ifdef CONFIG_8723AU_BT_COEXIST
1275 BT_WifiMediaStatusNotify(padapter, mstatus);
1276#endif
1277 break;
1278 case LPS_CTRL_DISCONNECT:
1279 mstatus = 0;/* disconnect */
1280#ifdef CONFIG_8723AU_BT_COEXIST
1281 BT_WifiMediaStatusNotify(padapter, mstatus);
1282 if (BT_1Ant(padapter) == false)
1283#endif
1284 {
1285 LPS_Leave23a(padapter);
1286 }
1287 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_JOINBSSRPT,
1288 (u8 *)&mstatus);
1289 break;
1290 case LPS_CTRL_SPECIAL_PACKET:
1291 pwrpriv->DelayLPSLastTimeStamp = jiffies;
1292#ifdef CONFIG_8723AU_BT_COEXIST
1293 BT_SpecialPacketNotify(padapter);
1294 if (BT_1Ant(padapter) == false)
1295#endif
1296 {
1297 LPS_Leave23a(padapter);
1298 }
1299 break;
1300 case LPS_CTRL_LEAVE:
1301#ifdef CONFIG_8723AU_BT_COEXIST
1302 BT_LpsLeave(padapter);
1303 if (BT_1Ant(padapter) == false)
1304#endif
1305 {
1306 LPS_Leave23a(padapter);
1307 }
1308 break;
1309
1310 default:
1311 break;
1312 }
1313}
1314
1315u8 rtw_lps_ctrl_wk_cmd23a(struct rtw_adapter *padapter,
1316 u8 lps_ctrl_type, u8 enqueue)
1317{
1318 struct cmd_obj *ph2c;
1319 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1320 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1321 u8 res = _SUCCESS;
1322
1323 if (enqueue) {
1324 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1325 if (!ph2c) {
1326 res = _FAIL;
1327 goto exit;
1328 }
1329
1330 pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1331 GFP_ATOMIC);
1332 if (!pdrvextra_cmd_parm) {
1333 kfree(ph2c);
1334 res = _FAIL;
1335 goto exit;
1336 }
1337
1338 pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
1339 pdrvextra_cmd_parm->type_size = lps_ctrl_type;
1340 pdrvextra_cmd_parm->pbuf = NULL;
1341
1342 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1343 GEN_CMD_CODE(_Set_Drv_Extra));
1344
1345 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1346 } else
1347 lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
1348exit:
1349
1350 return res;
1351}
1352
1353static void power_saving_wk_hdl(struct rtw_adapter *padapter, u8 *pbuf, int sz)
1354{
1355 rtw_ps_processor23a(padapter);
1356}
1357
1358#ifdef CONFIG_8723AU_P2P
1359u8 p2p_protocol_wk_cmd23a(struct rtw_adapter*padapter, int intCmdType)
1360{
1361 struct cmd_obj *ph2c;
1362 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1363 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1364 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1365 u8 res = _SUCCESS;
1366
1367 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1368 {
1369 return res;
1370 }
1371
1372 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1373 if (!ph2c) {
1374 res = _FAIL;
1375 goto exit;
1376 }
1377
1378 pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1379 GFP_ATOMIC);
1380 if (!pdrvextra_cmd_parm) {
1381 kfree(ph2c);
1382 res = _FAIL;
1383 goto exit;
1384 }
1385
1386 pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;
1387 pdrvextra_cmd_parm->type_size = intCmdType; /* As the command tppe. */
1388 pdrvextra_cmd_parm->pbuf = NULL; /* Must be NULL here */
1389
1390 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1391 GEN_CMD_CODE(_Set_Drv_Extra));
1392
1393 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1394exit:
1395
1396 return res;
1397}
1398#endif /* CONFIG_8723AU_P2P */
1399
1400u8 rtw_ps_cmd23a(struct rtw_adapter*padapter)
1401{
1402 struct cmd_obj *ppscmd;
1403 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1404 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1405
1406 u8 res = _SUCCESS;
1407
1408 ppscmd = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1409 if (!ppscmd) {
1410 res = _FAIL;
1411 goto exit;
1412 }
1413
1414 pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1415 GFP_ATOMIC);
1416 if (!pdrvextra_cmd_parm) {
1417 kfree(ppscmd);
1418 res = _FAIL;
1419 goto exit;
1420 }
1421
1422 pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
1423 pdrvextra_cmd_parm->pbuf = NULL;
1424 init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm,
1425 GEN_CMD_CODE(_Set_Drv_Extra));
1426
1427 res = rtw_enqueue_cmd23a(pcmdpriv, ppscmd);
1428exit:
1429
1430 return res;
1431}
1432
1433#ifdef CONFIG_8723AU_AP_MODE
1434
1435static void rtw_chk_hi_queue_hdl(struct rtw_adapter *padapter)
1436{
1437 int cnt = 0;
1438 struct sta_info *psta_bmc;
1439 struct sta_priv *pstapriv = &padapter->stapriv;
1440
1441 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
1442 if (!psta_bmc)
1443 return;
1444
1445 if (psta_bmc->sleepq_len == 0) {
1446 u8 val = 0;
1447
1448 rtw23a_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1449
1450 while(val == false) {
1451 msleep(100);
1452
1453 cnt++;
1454
1455 if (cnt>10)
1456 break;
1457
1458 rtw23a_hal_get_hwreg(padapter,
1459 HW_VAR_CHK_HI_QUEUE_EMPTY, &val);
1460 }
1461
1462 if (cnt <= 10) {
1463 pstapriv->tim_bitmap &= ~BIT(0);
1464 pstapriv->sta_dz_bitmap &= ~BIT(0);
1465
1466 update_beacon23a(padapter, _TIM_IE_, NULL, false);
1467 } else /* re check again */
1468 rtw_chk_hi_queue_cmd23a(padapter);
1469 }
1470}
1471
1472u8 rtw_chk_hi_queue_cmd23a(struct rtw_adapter*padapter)
1473{
1474 struct cmd_obj *ph2c;
1475 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1476 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1477 u8 res = _SUCCESS;
1478
1479 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1480 if (!ph2c) {
1481 res = _FAIL;
1482 goto exit;
1483 }
1484
1485 pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1486 GFP_ATOMIC);
1487 if (!pdrvextra_cmd_parm) {
1488 kfree(ph2c);
1489 res = _FAIL;
1490 goto exit;
1491 }
1492
1493 pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
1494 pdrvextra_cmd_parm->type_size = 0;
1495 pdrvextra_cmd_parm->pbuf = NULL;
1496
1497 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1498 GEN_CMD_CODE(_Set_Drv_Extra));
1499
1500 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1501exit:
1502
1503 return res;
1504}
1505#endif
1506
1507u8 rtw_c2h_wk_cmd23a(struct rtw_adapter *padapter, u8 *c2h_evt)
1508{
1509 struct cmd_obj *ph2c;
1510 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
1511 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
1512 u8 res = _SUCCESS;
1513
1514 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
1515 if (!ph2c) {
1516 res = _FAIL;
1517 goto exit;
1518 }
1519
1520 pdrvextra_cmd_parm = kzalloc(sizeof(struct drvextra_cmd_parm),
1521 GFP_ATOMIC);
1522 if (!pdrvextra_cmd_parm) {
1523 kfree(ph2c);
1524 res = _FAIL;
1525 goto exit;
1526 }
1527
1528 pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
1529 pdrvextra_cmd_parm->type_size = c2h_evt?16:0;
1530 pdrvextra_cmd_parm->pbuf = c2h_evt;
1531
1532 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm,
1533 GEN_CMD_CODE(_Set_Drv_Extra));
1534
1535 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
1536
1537exit:
1538
1539 return res;
1540}
1541
1542s32 c2h_evt_hdl(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt,
1543 c2h_id_filter filter)
1544{
1545 s32 ret = _FAIL;
1546 u8 buf[16];
1547
1548 if (!c2h_evt) {
1549 /* No c2h event in cmd_obj, read c2h event before handling*/
1550 if (c2h_evt_read23a(adapter, buf) == _SUCCESS) {
1551 c2h_evt = (struct c2h_evt_hdr *)buf;
1552
1553 if (filter && filter(c2h_evt->id) == false)
1554 goto exit;
1555
1556 ret = rtw_hal_c2h_handler23a(adapter, c2h_evt);
1557 }
1558 } else {
1559
1560 if (filter && filter(c2h_evt->id) == false)
1561 goto exit;
1562
1563 ret = rtw_hal_c2h_handler23a(adapter, c2h_evt);
1564 }
1565exit:
1566 return ret;
1567}
1568
1569static void c2h_wk_callback(struct work_struct *work)
1570{
1571 struct evt_priv *evtpriv;
1572 struct rtw_adapter *adapter;
1573 struct c2h_evt_hdr *c2h_evt;
1574 c2h_id_filter ccx_id_filter;
1575
1576 evtpriv = container_of(work, struct evt_priv, c2h_wk);
1577 adapter = container_of(evtpriv, struct rtw_adapter, evtpriv);
1578 ccx_id_filter = rtw_hal_c2h_id_filter_ccx23a(adapter);
1579
1580 evtpriv->c2h_wk_alive = true;
1581
1582 while (!rtw_cbuf_empty23a(evtpriv->c2h_queue)) {
1583 c2h_evt = (struct c2h_evt_hdr *)
1584 rtw_cbuf_pop23a(evtpriv->c2h_queue);
1585 if (c2h_evt) {
1586 /* This C2H event is read, clear it */
1587 c2h_evt_clear23a(adapter);
1588 } else if ((c2h_evt = (struct c2h_evt_hdr *)
1589 kmalloc(16, GFP_ATOMIC))) {
1590 /* This C2H event is not read, read & clear now */
1591 if (c2h_evt_read23a(adapter, (u8*)c2h_evt) != _SUCCESS)
1592 continue;
1593 }
1594
1595 /* Special pointer to trigger c2h_evt_clear23a only */
1596 if ((void *)c2h_evt == (void *)evtpriv)
1597 continue;
1598
1599 if (!c2h_evt_exist(c2h_evt)) {
1600 kfree(c2h_evt);
1601 continue;
1602 }
1603
1604 if (ccx_id_filter(c2h_evt->id) == true) {
1605 /* Handle CCX report here */
1606 rtw_hal_c2h_handler23a(adapter, c2h_evt);
1607 kfree(c2h_evt);
1608 } else {
1609 /* Enqueue into cmd_thread for others */
1610 rtw_c2h_wk_cmd23a(adapter, (u8 *)c2h_evt);
1611 }
1612 }
1613
1614 evtpriv->c2h_wk_alive = false;
1615}
1616
1617u8 rtw_drvextra_cmd_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
1618{
1619 struct drvextra_cmd_parm *pdrvextra_cmd;
1620
1621 if (!pbuf)
1622 return H2C_PARAMETERS_ERROR;
1623
1624 pdrvextra_cmd = (struct drvextra_cmd_parm *)pbuf;
1625
1626 switch (pdrvextra_cmd->ec_id)
1627 {
1628 case DYNAMIC_CHK_WK_CID:
1629 dynamic_chk_wk_hdl(padapter, pdrvextra_cmd->pbuf,
1630 pdrvextra_cmd->type_size);
1631 break;
1632 case POWER_SAVING_CTRL_WK_CID:
1633 power_saving_wk_hdl(padapter, pdrvextra_cmd->pbuf,
1634 pdrvextra_cmd->type_size);
1635 break;
1636 case LPS_CTRL_WK_CID:
1637 lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type_size);
1638 break;
1639#ifdef CONFIG_8723AU_P2P
1640 case P2P_PS_WK_CID:
1641 p2p_ps_wk_hdl23a(padapter, pdrvextra_cmd->type_size);
1642 break;
1643 case P2P_PROTO_WK_CID:
1644 /* Commented by Albert 2011/07/01 */
1645 /* I used the type_size as the type command */
1646 p2p_protocol_wk_hdl23a(padapter, pdrvextra_cmd->type_size);
1647 break;
1648#endif /* CONFIG_8723AU_P2P */
1649#ifdef CONFIG_8723AU_AP_MODE
1650 case CHECK_HIQ_WK_CID:
1651 rtw_chk_hi_queue_hdl(padapter);
1652 break;
1653#endif /* CONFIG_8723AU_AP_MODE */
1654 case C2H_WK_CID:
1655 c2h_evt_hdl(padapter,
1656 (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf, NULL);
1657 break;
1658
1659 default:
1660 break;
1661 }
1662
1663 if (pdrvextra_cmd->pbuf && (pdrvextra_cmd->type_size > 0)) {
1664 kfree(pdrvextra_cmd->pbuf);
1665 pdrvextra_cmd->pbuf = NULL;
1666 }
1667
1668 return H2C_SUCCESS;
1669}
1670
1671void rtw_survey_cmd_callback23a(struct rtw_adapter *padapter,
1672 struct cmd_obj *pcmd)
1673{
1674 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1675
1676 if (pcmd->res == H2C_DROPPED) {
1677 /* TODO: cancel timer and do timeout handler directly... */
1678 /* need to make timeout handlerOS independent */
1679 mod_timer(&pmlmepriv->scan_to_timer,
1680 jiffies + msecs_to_jiffies(1));
1681 } else if (pcmd->res != H2C_SUCCESS) {
1682 mod_timer(&pmlmepriv->scan_to_timer,
1683 jiffies + msecs_to_jiffies(1));
1684 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1685 ("\n ********Error: MgntActrtw_set_802_11_bssid23a_"
1686 "LIST_SCAN Fail ************\n\n."));
1687 }
1688
1689 /* free cmd */
1690 rtw_free_cmd_obj23a(pcmd);
1691}
1692
1693void rtw_disassoc_cmd23a_callback(struct rtw_adapter *padapter,
1694 struct cmd_obj *pcmd)
1695{
1696 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1697
1698 if (pcmd->res != H2C_SUCCESS) {
1699 spin_lock_bh(&pmlmepriv->lock);
1700 set_fwstate(pmlmepriv, _FW_LINKED);
1701 spin_unlock_bh(&pmlmepriv->lock);
1702 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1703 ("\n ***Error: disconnect_cmd_callback Fail ***\n."));
1704 return;
1705 }
1706
1707 /* free cmd */
1708 rtw_free_cmd_obj23a(pcmd);
1709}
1710
1711void rtw_joinbss_cmd23a_callback(struct rtw_adapter *padapter,
1712 struct cmd_obj *pcmd)
1713{
1714 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1715
1716 if (pcmd->res == H2C_DROPPED) {
1717 /* TODO: cancel timer and do timeout handler directly... */
1718 /* need to make timeout handlerOS independent */
1719 mod_timer(&pmlmepriv->assoc_timer,
1720 jiffies + msecs_to_jiffies(1));
1721 } else if (pcmd->res != H2C_SUCCESS) {
1722 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1723 ("********Error:rtw_select_and_join_from_scanned_"
1724 "queue Wait Sema Fail ************\n"));
1725 mod_timer(&pmlmepriv->assoc_timer,
1726 jiffies + msecs_to_jiffies(1));
1727 }
1728
1729 rtw_free_cmd_obj23a(pcmd);
1730}
1731
1732void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter,
1733 struct cmd_obj *pcmd)
1734{
1735 struct sta_info *psta;
1736 struct wlan_network *pwlan;
1737 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1738 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
1739 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1740
1741 if (pcmd->res != H2C_SUCCESS) {
1742 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1743 ("\n ********Error: rtw_createbss_cmd23a_callback "
1744 "Fail ************\n\n."));
1745 mod_timer(&pmlmepriv->assoc_timer,
1746 jiffies + msecs_to_jiffies(1));
1747 }
1748
1749 del_timer_sync(&pmlmepriv->assoc_timer);
1750
1751 spin_lock_bh(&pmlmepriv->lock);
1752
1753 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1754 psta = rtw_get_stainfo23a(&padapter->stapriv,
1755 pnetwork->MacAddress);
1756 if (!psta) {
1757 psta = rtw_alloc_stainfo23a(&padapter->stapriv,
1758 pnetwork->MacAddress);
1759 if (!psta) {
1760 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1761 ("\nCan't alloc sta_info when "
1762 "createbss_cmd_callback\n"));
1763 goto createbss_cmd_fail ;
1764 }
1765 }
1766
1767 rtw_indicate_connect23a(padapter);
1768 } else {
1769 pwlan = rtw_alloc_network(pmlmepriv);
1770 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1771 if (!pwlan) {
1772 pwlan = rtw_get_oldest_wlan_network23a(&pmlmepriv->scanned_queue);
1773 if (!pwlan) {
1774 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1775 ("\n Error: can't get pwlan in "
1776 "rtw23a_joinbss_event_cb\n"));
1777 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1778 goto createbss_cmd_fail;
1779 }
1780 pwlan->last_scanned = jiffies;
1781 } else {
1782 list_add_tail(&pwlan->list,
1783 &pmlmepriv->scanned_queue.queue);
1784 }
1785
1786 pnetwork->Length = get_wlan_bssid_ex_sz(pnetwork);
1787 memcpy(&pwlan->network, pnetwork, pnetwork->Length);
1788 /* pwlan->fixed = true; */
1789
1790 /* list_add_tail(&pwlan->list,
1791 &pmlmepriv->scanned_queue.queue); */
1792
1793 /* copy pdev_network information to
1794 pmlmepriv->cur_network */
1795 memcpy(&tgt_network->network, pnetwork,
1796 get_wlan_bssid_ex_sz(pnetwork));
1797
1798 /* reset DSConfig */
1799
1800 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1801
1802 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1803 /* we will set _FW_LINKED when there is one more sat to
1804 join us (rtw_stassoc_event_callback23a) */
1805 }
1806
1807createbss_cmd_fail:
1808
1809 spin_unlock_bh(&pmlmepriv->lock);
1810
1811 rtw_free_cmd_obj23a(pcmd);
1812}
1813
1814void rtw_setstaKey_cmdrsp_callback23a(struct rtw_adapter *padapter,
1815 struct cmd_obj *pcmd)
1816{
1817 struct sta_priv *pstapriv;
1818 struct set_stakey_rsp *psetstakey_rsp;
1819 struct sta_info *psta;
1820
1821 pstapriv = &padapter->stapriv;
1822 psetstakey_rsp = (struct set_stakey_rsp*) (pcmd->rsp);
1823 psta = rtw_get_stainfo23a(pstapriv, psetstakey_rsp->addr);
1824
1825 if (!psta) {
1826 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1827 ("\nERROR: rtw_setstaKey_cmdrsp_callback23a => "
1828 "can't get sta_info\n\n"));
1829 goto exit;
1830 }
1831
1832exit:
1833
1834 rtw_free_cmd_obj23a(pcmd);
1835}
1836
1837void rtw_setassocsta_cmdrsp_callback23a(struct rtw_adapter *padapter,
1838 struct cmd_obj *pcmd)
1839{
1840 struct sta_priv *pstapriv = &padapter->stapriv;
1841 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1842 struct set_assocsta_parm* passocsta_parm;
1843 struct set_assocsta_rsp* passocsta_rsp;
1844 struct sta_info *psta;
1845
1846 passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
1847 passocsta_rsp = (struct set_assocsta_rsp*) (pcmd->rsp);
1848 psta = rtw_get_stainfo23a(pstapriv, passocsta_parm->addr);
1849
1850 if (psta == NULL) {
1851 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
1852 ("\nERROR: setassocsta_cmdrsp_callbac => can't "
1853 "get sta_info\n\n"));
1854 goto exit;
1855 }
1856
1857 psta->aid = psta->mac_id = passocsta_rsp->cam_id;
1858
1859 spin_lock_bh(&pmlmepriv->lock);
1860
1861 if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) &&
1862 (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true))
1863 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1864
1865 set_fwstate(pmlmepriv, _FW_LINKED);
1866 spin_unlock_bh(&pmlmepriv->lock);
1867
1868exit:
1869 rtw_free_cmd_obj23a(pcmd);
1870}
1871
1872void rtw_getrttbl_cmd_cmdrsp_callback(struct rtw_adapter *padapter,
1873 struct cmd_obj *pcmd)
1874{
1875 rtw_free_cmd_obj23a(pcmd);
1876}
diff --git a/drivers/staging/rtl8723au/core/rtw_efuse.c b/drivers/staging/rtl8723au/core/rtw_efuse.c
new file mode 100644
index 000000000000..35b177fd0510
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_efuse.c
@@ -0,0 +1,716 @@
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 ******************************************************************************/
15#define _RTW_EFUSE_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19
20#include <rtw_efuse.h>
21
22/*------------------------Define local variable------------------------------*/
23
24/* */
25#define REG_EFUSE_CTRL 0x0030
26#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */
27/* */
28
29/*-----------------------------------------------------------------------------
30 * Function: Efuse_PowerSwitch23a
31 *
32 * Overview: When we want to enable write operation, we should change to
33 * pwr on state. When we stop write, we should switch to 500k mode
34 * and disable LDO 2.5V.
35 *
36 * Input: NONE
37 *
38 * Output: NONE
39 *
40 * Return: NONE
41 *
42 * Revised History:
43 * When Who Remark
44 * 11/17/2008 MHC Create Version 0.
45 *
46 *---------------------------------------------------------------------------*/
47void
48Efuse_PowerSwitch23a(
49 struct rtw_adapter * pAdapter,
50 u8 bWrite,
51 u8 PwrState)
52{
53 pAdapter->HalFunc.EfusePowerSwitch(pAdapter, bWrite, PwrState);
54}
55
56/*-----------------------------------------------------------------------------
57 * Function: efuse_GetCurrentSize23a
58 *
59 * Overview: Get current efuse size!!!
60 *
61 * Input: NONE
62 *
63 * Output: NONE
64 *
65 * Return: NONE
66 *
67 * Revised History:
68 * When Who Remark
69 * 11/16/2008 MHC Create Version 0.
70 *
71 *---------------------------------------------------------------------------*/
72u16
73Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType)
74{
75 u16 ret = 0;
76
77 ret = pAdapter->HalFunc.EfuseGetCurrentSize(pAdapter, efuseType);
78
79 return ret;
80}
81
82/* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
83u8
84Efuse_CalculateWordCnts23a(u8 word_en)
85{
86 u8 word_cnts = 0;
87 if (!(word_en & BIT(0))) word_cnts++; /* 0 : write enable */
88 if (!(word_en & BIT(1))) word_cnts++;
89 if (!(word_en & BIT(2))) word_cnts++;
90 if (!(word_en & BIT(3))) word_cnts++;
91 return word_cnts;
92}
93
94/* */
95/* Description: */
96/* Execute E-Fuse read byte operation. */
97/* Refered from SD1 Richard. */
98/* */
99/* Assumption: */
100/* 1. Boot from E-Fuse and successfully auto-load. */
101/* 2. PASSIVE_LEVEL (USB interface) */
102/* */
103/* Created by Roger, 2008.10.21. */
104/* */
105void
106ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf)
107{
108 u32 value32;
109 u8 readbyte;
110 u16 retry;
111
112 /* Write Address */
113 rtw_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff));
114 readbyte = rtw_read8(Adapter, EFUSE_CTRL+2);
115 rtw_write8(Adapter, EFUSE_CTRL+2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));
116
117 /* Write bit 32 0 */
118 readbyte = rtw_read8(Adapter, EFUSE_CTRL+3);
119 rtw_write8(Adapter, EFUSE_CTRL+3, (readbyte & 0x7f));
120
121 /* Check bit 32 read-ready */
122 retry = 0;
123 value32 = rtw_read32(Adapter, EFUSE_CTRL);
124 /* while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10)) */
125 while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10000))
126 {
127 value32 = rtw_read32(Adapter, EFUSE_CTRL);
128 retry++;
129 }
130
131 /* 20100205 Joseph: Add delay suggested by SD1 Victor. */
132 /* This fix the problem that Efuse read error in high temperature condition. */
133 /* Designer says that there shall be some delay after ready bit is set, or the */
134 /* result will always stay on last data we read. */
135 udelay(50);
136 value32 = rtw_read32(Adapter, EFUSE_CTRL);
137
138 *pbuf = (u8)(value32 & 0xff);
139}
140
141/* */
142/* Description: */
143/* 1. Execute E-Fuse read byte operation according as map offset and */
144/* save to E-Fuse table. */
145/* 2. Refered from SD1 Richard. */
146/* */
147/* Assumption: */
148/* 1. Boot from E-Fuse and successfully auto-load. */
149/* 2. PASSIVE_LEVEL (USB interface) */
150/* */
151/* Created by Roger, 2008.10.21. */
152/* */
153/* 2008/12/12 MH 1. Reorganize code flow and reserve bytes. and add description. */
154/* 2. Add efuse utilization collect. */
155/* 2008/12/22 MH Read Efuse must check if we write section 1 data again!!! Sec1 */
156/* write addr must be after sec5. */
157/* */
158
159void
160efuse_ReadEFuse(struct rtw_adapter *Adapter, u8 efuseType,
161 u16 _offset, u16 _size_byte, u8 *pbuf);
162void
163efuse_ReadEFuse(struct rtw_adapter *Adapter, u8 efuseType,
164 u16 _offset, u16 _size_byte, u8 *pbuf)
165{
166 Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset,
167 _size_byte, pbuf);
168}
169
170void
171EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType,
172 u8 type, void *pOut)
173{
174 pAdapter->HalFunc.EFUSEGetEfuseDefinition(pAdapter, efuseType,
175 type, pOut);
176}
177
178/*-----------------------------------------------------------------------------
179 * Function: EFUSE_Read1Byte23a
180 *
181 * Overview: Copy from WMAC fot EFUSE read 1 byte.
182 *
183 * Input: NONE
184 *
185 * Output: NONE
186 *
187 * Return: NONE
188 *
189 * Revised History:
190 * When Who Remark
191 * 09/23/2008 MHC Copy from WMAC.
192 *
193 *---------------------------------------------------------------------------*/
194u8
195EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address)
196{
197 u8 data;
198 u8 Bytetemp = {0x00};
199 u8 temp = {0x00};
200 u32 k = 0;
201 u16 contentLen = 0;
202
203 EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
204 TYPE_EFUSE_REAL_CONTENT_LEN,
205 (void *)&contentLen);
206
207 if (Address < contentLen) /* E-fuse 512Byte */
208 {
209 /* Write E-fuse Register address bit0~7 */
210 temp = Address & 0xFF;
211 rtw_write8(Adapter, EFUSE_CTRL+1, temp);
212 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);
213 /* Write E-fuse Register address bit8~9 */
214 temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
215 rtw_write8(Adapter, EFUSE_CTRL+2, temp);
216
217 /* Write 0x30[31]= 0 */
218 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
219 temp = Bytetemp & 0x7F;
220 rtw_write8(Adapter, EFUSE_CTRL+3, temp);
221
222 /* Wait Write-ready (0x30[31]= 1) */
223 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
224 while(!(Bytetemp & 0x80))
225 {
226 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
227 k++;
228 if (k == 1000)
229 {
230 k = 0;
231 break;
232 }
233 }
234 data = rtw_read8(Adapter, EFUSE_CTRL);
235 return data;
236 }
237 else
238 return 0xFF;
239}/* EFUSE_Read1Byte23a */
240
241/*-----------------------------------------------------------------------------
242 * Function: EFUSE_Write1Byte
243 *
244 * Overview: Copy from WMAC fot EFUSE write 1 byte.
245 *
246 * Input: NONE
247 *
248 * Output: NONE
249 *
250 * Return: NONE
251 *
252 * Revised History:
253 * When Who Remark
254 * 09/23/2008 MHC Copy from WMAC.
255 *
256 *---------------------------------------------------------------------------*/
257
258void
259EFUSE_Write1Byte(
260 struct rtw_adapter * Adapter,
261 u16 Address,
262 u8 Value);
263void
264EFUSE_Write1Byte(
265 struct rtw_adapter * Adapter,
266 u16 Address,
267 u8 Value)
268{
269 u8 Bytetemp = {0x00};
270 u8 temp = {0x00};
271 u32 k = 0;
272 u16 contentLen = 0;
273
274 /* RT_TRACE(COMP_EFUSE, DBG_LOUD, ("Addr =%x Data =%x\n", Address, Value)); */
275 EFUSE_GetEfuseDefinition23a(Adapter, EFUSE_WIFI,
276 TYPE_EFUSE_REAL_CONTENT_LEN,
277 (void *)&contentLen);
278
279 if (Address < contentLen) /* E-fuse 512Byte */
280 {
281 rtw_write8(Adapter, EFUSE_CTRL, Value);
282
283 /* Write E-fuse Register address bit0~7 */
284 temp = Address & 0xFF;
285 rtw_write8(Adapter, EFUSE_CTRL+1, temp);
286 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);
287
288 /* Write E-fuse Register address bit8~9 */
289 temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);
290 rtw_write8(Adapter, EFUSE_CTRL+2, temp);
291
292 /* Write 0x30[31]= 1 */
293 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
294 temp = Bytetemp | 0x80;
295 rtw_write8(Adapter, EFUSE_CTRL+3, temp);
296
297 /* Wait Write-ready (0x30[31]= 0) */
298 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
299 while(Bytetemp & 0x80)
300 {
301 Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
302 k++;
303 if (k == 100)
304 {
305 k = 0;
306 break;
307 }
308 }
309 }
310}/* EFUSE_Write1Byte */
311
312/* 11/16/2008 MH Read one byte from real Efuse. */
313u8
314efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data)
315{
316 u8 tmpidx = 0;
317 u8 bResult;
318
319 /* -----------------e-fuse reg ctrl --------------------------------- */
320 /* address */
321 rtw_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
322 rtw_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) &0x03)) |
323 (rtw_read8(pAdapter, EFUSE_CTRL+2)&0xFC));
324
325 rtw_write8(pAdapter, EFUSE_CTRL+3, 0x72);/* read cmd */
326
327 while(!(0x80 &rtw_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx<100))
328 tmpidx++;
329 if (tmpidx < 100) {
330 *data = rtw_read8(pAdapter, EFUSE_CTRL);
331 bResult = true;
332 } else {
333 *data = 0xff;
334 bResult = false;
335 }
336 return bResult;
337}
338
339/* 11/16/2008 MH Write one byte to reald Efuse. */
340u8
341efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data)
342{
343 u8 tmpidx = 0;
344 u8 bResult;
345
346 /* RT_TRACE(COMP_EFUSE, DBG_LOUD, ("Addr = %x Data =%x\n", addr, data)); */
347
348 /* return 0; */
349
350 /* -----------------e-fuse reg ctrl --------------------------------- */
351 /* address */
352 rtw_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));
353 rtw_write8(pAdapter, EFUSE_CTRL+2,
354 (rtw_read8(pAdapter, EFUSE_CTRL+2)&0xFC)|(u8)((addr>>8)&0x03));
355 rtw_write8(pAdapter, EFUSE_CTRL, data);/* data */
356
357 rtw_write8(pAdapter, EFUSE_CTRL+3, 0xF2);/* write cmd */
358
359 while((0x80 & rtw_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx<100)) {
360 tmpidx++;
361 }
362
363 if (tmpidx<100)
364 {
365 bResult = true;
366 }
367 else
368 {
369 bResult = false;
370 }
371
372 return bResult;
373}
374
375int
376Efuse_PgPacketRead23a(struct rtw_adapter *pAdapter, u8 offset, u8 *data)
377{
378 int ret = 0;
379
380 ret = pAdapter->HalFunc.Efuse_PgPacketRead23a(pAdapter, offset, data);
381
382 return ret;
383}
384
385int
386Efuse_PgPacketWrite23a(struct rtw_adapter *pAdapter, u8 offset,
387 u8 word_en, u8 *data)
388{
389 int ret;
390
391 ret = pAdapter->HalFunc.Efuse_PgPacketWrite23a(pAdapter, offset,
392 word_en, data);
393
394 return ret;
395}
396
397/*-----------------------------------------------------------------------------
398 * Function: efuse_WordEnableDataRead23a
399 *
400 * Overview: Read allowed word in current efuse section data.
401 *
402 * Input: NONE
403 *
404 * Output: NONE
405 *
406 * Return: NONE
407 *
408 * Revised History:
409 * When Who Remark
410 * 11/16/2008 MHC Create Version 0.
411 * 11/21/2008 MHC Fix Write bug when we only enable late word.
412 *
413 *---------------------------------------------------------------------------*/
414void
415efuse_WordEnableDataRead23a(u8 word_en,
416 u8 *sourdata,
417 u8 *targetdata)
418{
419 if (!(word_en&BIT(0)))
420 {
421 targetdata[0] = sourdata[0];
422 targetdata[1] = sourdata[1];
423 }
424 if (!(word_en&BIT(1)))
425 {
426 targetdata[2] = sourdata[2];
427 targetdata[3] = sourdata[3];
428 }
429 if (!(word_en&BIT(2)))
430 {
431 targetdata[4] = sourdata[4];
432 targetdata[5] = sourdata[5];
433 }
434 if (!(word_en&BIT(3)))
435 {
436 targetdata[6] = sourdata[6];
437 targetdata[7] = sourdata[7];
438 }
439}
440
441u8
442Efuse_WordEnableDataWrite23a(struct rtw_adapter *pAdapter, u16 efuse_addr,
443 u8 word_en, u8 *data)
444{
445 u8 ret = 0;
446
447 ret = pAdapter->HalFunc.Efuse_WordEnableDataWrite23a(pAdapter, efuse_addr,
448 word_en, data);
449
450 return ret;
451}
452
453static u8 efuse_read8(struct rtw_adapter *padapter, u16 address, u8 *value)
454{
455 return efuse_OneByteRead23a(padapter, address, value);
456}
457
458static u8 efuse_write8(struct rtw_adapter *padapter, u16 address, u8 *value)
459{
460 return efuse_OneByteWrite23a(padapter, address, *value);
461}
462
463/*
464 * read/wirte raw efuse data
465 */
466u8 rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bWrite, u16 start_addr,
467 u16 cnts, u8 *data)
468{
469 int i = 0;
470 u16 real_content_len = 0, max_available_size = 0;
471 u8 res = _FAIL ;
472 u8 (*rw8)(struct rtw_adapter *, u16, u8*);
473
474 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
475 TYPE_EFUSE_REAL_CONTENT_LEN,
476 (void *)&real_content_len);
477 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
478 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
479 (void *)&max_available_size);
480
481 if (start_addr > real_content_len)
482 return _FAIL;
483
484 if (true == bWrite) {
485 if ((start_addr + cnts) > max_available_size)
486 return _FAIL;
487 rw8 = &efuse_write8;
488 } else
489 rw8 = &efuse_read8;
490
491 Efuse_PowerSwitch23a(padapter, bWrite, true);
492
493 /* e-fuse one byte read / write */
494 for (i = 0; i < cnts; i++) {
495 if (start_addr >= real_content_len) {
496 res = _FAIL;
497 break;
498 }
499
500 res = rw8(padapter, start_addr++, data++);
501 if (_FAIL == res) break;
502 }
503
504 Efuse_PowerSwitch23a(padapter, bWrite, false);
505
506 return res;
507}
508/* */
509u16 efuse_GetMaxSize23a(struct rtw_adapter *padapter)
510{
511 u16 max_size;
512 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
513 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
514 (void *)&max_size);
515 return max_size;
516}
517/* */
518u8 efuse_GetCurrentSize23a(struct rtw_adapter *padapter, u16 *size)
519{
520 Efuse_PowerSwitch23a(padapter, false, true);
521 *size = Efuse_GetCurrentSize23a(padapter, EFUSE_WIFI);
522 Efuse_PowerSwitch23a(padapter, false, false);
523
524 return _SUCCESS;
525}
526/* */
527u8 rtw_efuse_map_read23a(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data)
528{
529 u16 mapLen = 0;
530
531 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
532 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
533
534 if ((addr + cnts) > mapLen)
535 return _FAIL;
536
537 Efuse_PowerSwitch23a(padapter, false, true);
538
539 efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data);
540
541 Efuse_PowerSwitch23a(padapter, false, false);
542
543 return _SUCCESS;
544}
545
546u8 rtw_BT_efuse_map_read23a(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data)
547{
548 u16 mapLen = 0;
549
550 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
551 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
552
553 if ((addr + cnts) > mapLen)
554 return _FAIL;
555
556 Efuse_PowerSwitch23a(padapter, false, true);
557
558 efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data);
559
560 Efuse_PowerSwitch23a(padapter, false, false);
561
562 return _SUCCESS;
563}
564
565/*-----------------------------------------------------------------------------
566 * Function: Efuse_ReadAllMap
567 *
568 * Overview: Read All Efuse content
569 *
570 * Input: NONE
571 *
572 * Output: NONE
573 *
574 * Return: NONE
575 *
576 * Revised History:
577 * When Who Remark
578 * 11/11/2008 MHC Create Version 0.
579 *
580 *---------------------------------------------------------------------------*/
581void
582Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse);
583void
584Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse)
585{
586 u16 mapLen = 0;
587
588 Efuse_PowerSwitch23a(pAdapter, false, true);
589
590 EFUSE_GetEfuseDefinition23a(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN,
591 (void *)&mapLen);
592
593 efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse);
594
595 Efuse_PowerSwitch23a(pAdapter, false, false);
596}
597
598/*-----------------------------------------------------------------------------
599 * Function: efuse_ShadowRead1Byte
600 * efuse_ShadowRead2Byte
601 * efuse_ShadowRead4Byte
602 *
603 * Overview: Read from efuse init map by one/two/four bytes !!!!!
604 *
605 * Input: NONE
606 *
607 * Output: NONE
608 *
609 * Return: NONE
610 *
611 * Revised History:
612 * When Who Remark
613 * 11/12/2008 MHC Create Version 0.
614 *
615 *---------------------------------------------------------------------------*/
616static void
617efuse_ShadowRead1Byte(
618 struct rtw_adapter * pAdapter,
619 u16 Offset,
620 u8 *Value)
621{
622 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
623
624 *Value = pEEPROM->efuse_eeprom_data[Offset];
625} /* EFUSE_ShadowRead23a1Byte */
626
627/* Read Two Bytes */
628static void
629efuse_ShadowRead2Byte(
630 struct rtw_adapter * pAdapter,
631 u16 Offset,
632 u16 *Value)
633{
634 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
635
636 *Value = pEEPROM->efuse_eeprom_data[Offset];
637 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
638} /* EFUSE_ShadowRead23a2Byte */
639
640/* Read Four Bytes */
641static void
642efuse_ShadowRead4Byte(
643 struct rtw_adapter * pAdapter,
644 u16 Offset,
645 u32 *Value)
646{
647 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
648
649 *Value = pEEPROM->efuse_eeprom_data[Offset];
650 *Value |= pEEPROM->efuse_eeprom_data[Offset+1]<<8;
651 *Value |= pEEPROM->efuse_eeprom_data[Offset+2]<<16;
652 *Value |= pEEPROM->efuse_eeprom_data[Offset+3]<<24;
653} /* efuse_ShadowRead4Byte */
654
655/*-----------------------------------------------------------------------------
656 * Function: EFUSE_ShadowMapUpdate23a
657 *
658 * Overview: Transfer current EFUSE content to shadow init and modify map.
659 *
660 * Input: NONE
661 *
662 * Output: NONE
663 *
664 * Return: NONE
665 *
666 * Revised History:
667 * When Who Remark
668 * 11/13/2008 MHC Create Version 0.
669 *
670 *---------------------------------------------------------------------------*/
671void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType)
672{
673 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter);
674 u16 mapLen = 0;
675
676 EFUSE_GetEfuseDefinition23a(pAdapter, efuseType,
677 TYPE_EFUSE_MAP_LEN, (void *)&mapLen);
678
679 if (pEEPROM->bautoload_fail_flag == true)
680 memset(pEEPROM->efuse_eeprom_data, 0xFF, mapLen);
681 else
682 Efuse_ReadAllMap(pAdapter, efuseType,
683 pEEPROM->efuse_eeprom_data);
684
685}/* EFUSE_ShadowMapUpdate23a */
686
687/*-----------------------------------------------------------------------------
688 * Function: EFUSE_ShadowRead23a
689 *
690 * Overview: Read from efuse init map !!!!!
691 *
692 * Input: NONE
693 *
694 * Output: NONE
695 *
696 * Return: NONE
697 *
698 * Revised History:
699 * When Who Remark
700 * 11/12/2008 MHC Create Version 0.
701 *
702 *---------------------------------------------------------------------------*/
703void
704EFUSE_ShadowRead23a(
705 struct rtw_adapter * pAdapter,
706 u8 Type,
707 u16 Offset,
708 u32 *Value )
709{
710 if (Type == 1)
711 efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
712 else if (Type == 2)
713 efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
714 else if (Type == 4)
715 efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
716} /* EFUSE_ShadowRead23a */
diff --git a/drivers/staging/rtl8723au/core/rtw_ieee80211.c b/drivers/staging/rtl8723au/core/rtw_ieee80211.c
new file mode 100644
index 000000000000..780631fd3b6d
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_ieee80211.c
@@ -0,0 +1,1861 @@
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 ******************************************************************************/
15#define _IEEE80211_C
16
17#include <drv_types.h>
18#include <linux/ieee80211.h>
19#include <ieee80211.h>
20#include <wifi.h>
21#include <osdep_service.h>
22#include <wlan_bssdef.h>
23
24u8 RTW_WPA_OUI23A_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
25u16 RTW_WPA_VERSION23A = 1;
26u8 WPA_AUTH_KEY_MGMT_NONE23A[] = { 0x00, 0x50, 0xf2, 0 };
27u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X23A[] = { 0x00, 0x50, 0xf2, 1 };
28u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[] = { 0x00, 0x50, 0xf2, 2 };
29u8 WPA_CIPHER_SUITE_NONE23A[] = { 0x00, 0x50, 0xf2, 0 };
30u8 WPA_CIPHER_SUITE_WEP4023A[] = { 0x00, 0x50, 0xf2, 1 };
31u8 WPA_CIPHER_SUITE_TKIP23A[] = { 0x00, 0x50, 0xf2, 2 };
32u8 WPA_CIPHER_SUITE_WRAP23A[] = { 0x00, 0x50, 0xf2, 3 };
33u8 WPA_CIPHER_SUITE_CCMP23A[] = { 0x00, 0x50, 0xf2, 4 };
34u8 WPA_CIPHER_SUITE_WEP10423A[] = { 0x00, 0x50, 0xf2, 5 };
35
36u16 RSN_VERSION_BSD23A = 1;
37u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X23A[] = { 0x00, 0x0f, 0xac, 1 };
38u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[] = { 0x00, 0x0f, 0xac, 2 };
39u8 RSN_CIPHER_SUITE_NONE23A[] = { 0x00, 0x0f, 0xac, 0 };
40u8 RSN_CIPHER_SUITE_WEP4023A[] = { 0x00, 0x0f, 0xac, 1 };
41u8 RSN_CIPHER_SUITE_TKIP23A[] = { 0x00, 0x0f, 0xac, 2 };
42u8 RSN_CIPHER_SUITE_WRAP23A[] = { 0x00, 0x0f, 0xac, 3 };
43u8 RSN_CIPHER_SUITE_CCMP23A[] = { 0x00, 0x0f, 0xac, 4 };
44u8 RSN_CIPHER_SUITE_WEP10423A[] = { 0x00, 0x0f, 0xac, 5 };
45/* */
46/* for adhoc-master to generate ie and provide supported-rate to fw */
47/* */
48
49static u8 WIFI_CCKRATES[] =
50{(IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK),
51 (IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK),
52 (IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK),
53 (IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK)};
54
55static u8 WIFI_OFDMRATES[] =
56{(IEEE80211_OFDM_RATE_6MB),
57 (IEEE80211_OFDM_RATE_9MB),
58 (IEEE80211_OFDM_RATE_12MB),
59 (IEEE80211_OFDM_RATE_18MB),
60 (IEEE80211_OFDM_RATE_24MB),
61 IEEE80211_OFDM_RATE_36MB,
62 IEEE80211_OFDM_RATE_48MB,
63 IEEE80211_OFDM_RATE_54MB};
64
65int rtw_get_bit_value_from_ieee_value23a(u8 val)
66{
67 unsigned char dot11_rate_table[]=
68 {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 0};
69
70 int i = 0;
71 while (dot11_rate_table[i] != 0) {
72 if (dot11_rate_table[i] == val)
73 return BIT(i);
74 i++;
75 }
76 return 0;
77}
78
79uint rtw_is_cckrates_included23a(u8 *rate)
80{
81 u32 i = 0;
82
83 while (rate[i] != 0) {
84 if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) ||
85 (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22))
86 return true;
87 i++;
88 }
89
90 return false;
91}
92
93uint rtw_is_cckratesonly_included23a(u8 *rate)
94{
95 u32 i = 0;
96
97 while (rate[i] != 0) {
98 if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
99 (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22))
100 return false;
101
102 i++;
103 }
104
105 return true;
106}
107
108int rtw_check_network_type23a(unsigned char *rate, int ratelen, int channel)
109{
110 if (channel > 14) {
111 if ((rtw_is_cckrates_included23a(rate)) == true)
112 return WIRELESS_INVALID;
113 else
114 return WIRELESS_11A;
115 } else { /* could be pure B, pure G, or B/G */
116 if ((rtw_is_cckratesonly_included23a(rate)) == true)
117 return WIRELESS_11B;
118 else if ((rtw_is_cckrates_included23a(rate)) == true)
119 return WIRELESS_11BG;
120 else
121 return WIRELESS_11G;
122 }
123}
124
125u8 *rtw_set_fixed_ie23a(unsigned char *pbuf, unsigned int len,
126 unsigned char *source, unsigned int *frlen)
127{
128 memcpy((void *)pbuf, (void *)source, len);
129 *frlen = *frlen + len;
130 return pbuf + len;
131}
132
133/* rtw_set_ie23a will update frame length */
134u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, u8 *source, uint *frlen)
135{
136
137 *pbuf = (u8)index;
138
139 *(pbuf + 1) = (u8)len;
140
141 if (len > 0)
142 memcpy((void *)(pbuf + 2), (void *)source, len);
143
144 *frlen = *frlen + (len + 2);
145
146
147 return pbuf + len + 2;
148}
149
150inline u8 *rtw_set_ie23a_ch_switch (u8 *buf, u32 *buf_len, u8 ch_switch_mode,
151 u8 new_ch, u8 ch_switch_cnt)
152{
153 u8 ie_data[3];
154
155 ie_data[0] = ch_switch_mode;
156 ie_data[1] = new_ch;
157 ie_data[2] = ch_switch_cnt;
158 return rtw_set_ie23a(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len);
159}
160
161inline u8 secondary_ch_offset_to_hal_ch_offset23a(u8 ch_offset)
162{
163 if (ch_offset == SCN)
164 return HAL_PRIME_CHNL_OFFSET_DONT_CARE;
165 else if (ch_offset == SCA)
166 return HAL_PRIME_CHNL_OFFSET_UPPER;
167 else if (ch_offset == SCB)
168 return HAL_PRIME_CHNL_OFFSET_LOWER;
169
170 return HAL_PRIME_CHNL_OFFSET_DONT_CARE;
171}
172
173inline u8 hal_ch_offset_to_secondary_ch_offset23a(u8 ch_offset)
174{
175 if (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
176 return SCN;
177 else if (ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
178 return SCB;
179 else if (ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
180 return SCA;
181
182 return SCN;
183}
184
185inline u8 *rtw_set_ie23a_secondary_ch_offset(u8 *buf, u32 *buf_len,
186 u8 secondary_ch_offset)
187{
188 return rtw_set_ie23a(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET,
189 1, &secondary_ch_offset, buf_len);
190}
191
192inline u8 *rtw_set_ie23a_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl,
193 u8 flags, u16 reason, u16 precedence)
194{
195 u8 ie_data[6];
196
197 ie_data[0] = ttl;
198 ie_data[1] = flags;
199 put_unaligned_le16(reason, (u8*)&ie_data[2]);
200 put_unaligned_le16(precedence, (u8*)&ie_data[4]);
201
202 return rtw_set_ie23a(buf, 0x118, 6, ie_data, buf_len);
203}
204
205/*----------------------------------------------------------------------------
206index: the information element id index, limit is the limit for search
207-----------------------------------------------------------------------------*/
208u8 *rtw_get_ie23a(u8 *pbuf, int index, int *len, int limit)
209{
210 int tmp, i;
211 u8 *p;
212
213 if (limit < 1) {
214
215 return NULL;
216 }
217
218 p = pbuf;
219 i = 0;
220 *len = 0;
221 while (1) {
222 if (*p == index) {
223 *len = *(p + 1);
224 return p;
225 } else {
226 tmp = *(p + 1);
227 p += (tmp + 2);
228 i += (tmp + 2);
229 }
230 if (i >= limit)
231 break;
232 }
233
234 return NULL;
235}
236
237/**
238 * rtw_get_ie23a_ex - Search specific IE from a series of IEs
239 * @in_ie: Address of IEs to search
240 * @in_len: Length limit from in_ie
241 * @eid: Element ID to match
242 * @oui: OUI to match
243 * @oui_len: OUI length
244 * @ie: If not NULL and the specific IE is found, the IE will be copied
245 * to the buf starting from the specific IE
246 * @ielen: If not NULL and the specific IE is found, will set to the length
247 * of the entire IE
248 *
249 * Returns: The address of the specific IE found, or NULL
250 */
251u8 *rtw_get_ie23a_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len,
252 u8 *ie, uint *ielen)
253{
254 uint cnt;
255 u8 *target_ie = NULL;
256
257 if (ielen)
258 *ielen = 0;
259
260 if (!in_ie || in_len <= 0)
261 return target_ie;
262
263 cnt = 0;
264
265 while (cnt < in_len) {
266 if (eid == in_ie[cnt] &&
267 (!oui || !memcmp(&in_ie[cnt+2], oui, oui_len))) {
268 target_ie = &in_ie[cnt];
269
270 if (ie)
271 memcpy(ie, &in_ie[cnt], in_ie[cnt+1]+2);
272
273 if (ielen)
274 *ielen = in_ie[cnt+1]+2;
275 break;
276 } else {
277 cnt += in_ie[cnt + 1] + 2; /* goto next */
278 }
279 }
280
281 return target_ie;
282}
283
284/**
285 * rtw_ies_remove_ie23a - Find matching IEs and remove
286 * @ies: Address of IEs to search
287 * @ies_len: Pointer of length of ies, will update to new length
288 * @offset: The offset to start scarch
289 * @eid: Element ID to match
290 * @oui: OUI to match
291 * @oui_len: OUI length
292 *
293 * Returns: _SUCCESS: ies is updated, _FAIL: not updated
294 */
295int rtw_ies_remove_ie23a(u8 *ies, uint *ies_len, uint offset, u8 eid,
296 u8 *oui, u8 oui_len)
297{
298 int ret = _FAIL;
299 u8 *target_ie;
300 u32 target_ielen;
301 u8 *start;
302 uint search_len;
303
304 if (!ies || !ies_len || *ies_len <= offset)
305 goto exit;
306
307 start = ies + offset;
308 search_len = *ies_len - offset;
309
310 while (1) {
311 target_ie = rtw_get_ie23a_ex(start, search_len, eid, oui, oui_len,
312 NULL, &target_ielen);
313 if (target_ie && target_ielen) {
314 u8 buf[MAX_IE_SZ] = {0};
315 u8 *remain_ies = target_ie + target_ielen;
316 uint remain_len = search_len - (remain_ies - start);
317
318 memcpy(buf, remain_ies, remain_len);
319 memcpy(target_ie, buf, remain_len);
320 *ies_len = *ies_len - target_ielen;
321 ret = _SUCCESS;
322
323 start = target_ie;
324 search_len = remain_len;
325 } else {
326 break;
327 }
328 }
329exit:
330 return ret;
331}
332
333void rtw_set_supported_rate23a(u8* SupportedRates, uint mode)
334{
335
336
337 memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
338
339 switch (mode)
340 {
341 case WIRELESS_11B:
342 memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
343 break;
344
345 case WIRELESS_11G:
346 case WIRELESS_11A:
347 case WIRELESS_11_5N:
348 case WIRELESS_11A_5N:/* Todo: no basic rate for ofdm ? */
349 memcpy(SupportedRates, WIFI_OFDMRATES,
350 IEEE80211_NUM_OFDM_RATESLEN);
351 break;
352
353 case WIRELESS_11BG:
354 case WIRELESS_11G_24N:
355 case WIRELESS_11_24N:
356 case WIRELESS_11BG_24N:
357 memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
358 memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES,
359 IEEE80211_NUM_OFDM_RATESLEN);
360 break;
361 }
362
363}
364
365uint rtw_get_rateset_len23a(u8 *rateset)
366{
367 uint i = 0;
368
369 while(1) {
370 if ((rateset[i]) == 0)
371 break;
372
373 if (i > 12)
374 break;
375
376 i++;
377 }
378
379 return i;
380}
381
382int rtw_generate_ie23a(struct registry_priv *pregistrypriv)
383{
384 u8 wireless_mode;
385 int sz = 0, rateLen;
386 struct wlan_bssid_ex* pdev_network = &pregistrypriv->dev_network;
387 u8* ie = pdev_network->IEs;
388
389
390
391 /* timestamp will be inserted by hardware */
392 sz += 8;
393 ie += sz;
394
395 /* beacon interval : 2bytes */
396 /* BCN_INTERVAL; */
397 *(u16*)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);
398 sz += 2;
399 ie += 2;
400
401 /* capability info */
402 *(u16*)ie = 0;
403
404 *(u16*)ie |= cpu_to_le16(cap_IBSS);
405
406 if (pregistrypriv->preamble == PREAMBLE_SHORT)
407 *(u16*)ie |= cpu_to_le16(cap_ShortPremble);
408
409 if (pdev_network->Privacy)
410 *(u16*)ie |= cpu_to_le16(cap_Privacy);
411
412 sz += 2;
413 ie += 2;
414
415 /* SSID */
416 ie = rtw_set_ie23a(ie, _SSID_IE_, pdev_network->Ssid.ssid_len,
417 pdev_network->Ssid.ssid, &sz);
418
419 /* supported rates */
420 if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) {
421 if (pdev_network->Configuration.DSConfig > 14)
422 wireless_mode = WIRELESS_11A_5N;
423 else
424 wireless_mode = WIRELESS_11BG_24N;
425 } else {
426 wireless_mode = pregistrypriv->wireless_mode;
427 }
428
429 rtw_set_supported_rate23a(pdev_network->SupportedRates, wireless_mode) ;
430
431 rateLen = rtw_get_rateset_len23a(pdev_network->SupportedRates);
432
433 if (rateLen > 8) {
434 ie = rtw_set_ie23a(ie, _SUPPORTEDRATES_IE_, 8,
435 pdev_network->SupportedRates, &sz);
436 /* ie = rtw_set_ie23a(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */
437 } else {
438 ie = rtw_set_ie23a(ie, _SUPPORTEDRATES_IE_, rateLen,
439 pdev_network->SupportedRates, &sz);
440 }
441
442 /* DS parameter set */
443 ie = rtw_set_ie23a(ie, _DSSET_IE_, 1,
444 (u8 *)&pdev_network->Configuration.DSConfig, &sz);
445
446 /* IBSS Parameter Set */
447
448 ie = rtw_set_ie23a(ie, _IBSS_PARA_IE_, 2,
449 (u8 *)&pdev_network->Configuration.ATIMWindow, &sz);
450
451 if (rateLen > 8) {
452 ie = rtw_set_ie23a(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8),
453 (pdev_network->SupportedRates + 8), &sz);
454 }
455
456
457
458 /* return _SUCCESS; */
459
460 return sz;
461}
462
463unsigned char *rtw_get_wpa_ie23a(unsigned char *pie, int *wpa_ie_len, int limit)
464{
465 int len;
466 u16 val16;
467 unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01};
468 u8 *pbuf = pie;
469 int limit_new = limit;
470
471 while(1) {
472 pbuf = rtw_get_ie23a(pbuf, _WPA_IE_ID_, &len, limit_new);
473
474 if (pbuf) {
475 /* check if oui matches... */
476 if (memcmp((pbuf + 2), wpa_oui_type,
477 sizeof(wpa_oui_type))) {
478 goto check_next_ie;
479 }
480
481 /* check version... */
482 memcpy((u8 *)&val16, (pbuf + 6), sizeof(val16));
483
484 val16 = le16_to_cpu(val16);
485 if (val16 != 0x0001)
486 goto check_next_ie;
487
488 *wpa_ie_len = *(pbuf + 1);
489
490 return pbuf;
491 } else {
492 *wpa_ie_len = 0;
493 return NULL;
494 }
495
496check_next_ie:
497
498 limit_new = limit - (pbuf - pie) - 2 - len;
499
500 if (limit_new <= 0)
501 break;
502
503 pbuf += (2 + len);
504 }
505
506 *wpa_ie_len = 0;
507
508 return NULL;
509}
510
511unsigned char *rtw_get_wpa2_ie23a(unsigned char *pie, int *rsn_ie_len, int limit)
512{
513 return rtw_get_ie23a(pie, _WPA2_IE_ID_, rsn_ie_len, limit);
514}
515
516int rtw_get_wpa_cipher_suite23a(u8 *s)
517{
518 if (!memcmp(s, WPA_CIPHER_SUITE_NONE23A, WPA_SELECTOR_LEN))
519 return WPA_CIPHER_NONE;
520 if (!memcmp(s, WPA_CIPHER_SUITE_WEP4023A, WPA_SELECTOR_LEN))
521 return WPA_CIPHER_WEP40;
522 if (!memcmp(s, WPA_CIPHER_SUITE_TKIP23A, WPA_SELECTOR_LEN))
523 return WPA_CIPHER_TKIP;
524 if (!memcmp(s, WPA_CIPHER_SUITE_CCMP23A, WPA_SELECTOR_LEN))
525 return WPA_CIPHER_CCMP;
526 if (!memcmp(s, WPA_CIPHER_SUITE_WEP10423A, WPA_SELECTOR_LEN))
527 return WPA_CIPHER_WEP104;
528
529 return 0;
530}
531
532int rtw_get_wpa2_cipher_suite23a(u8 *s)
533{
534 if (!memcmp(s, RSN_CIPHER_SUITE_NONE23A, RSN_SELECTOR_LEN))
535 return WPA_CIPHER_NONE;
536 if (!memcmp(s, RSN_CIPHER_SUITE_WEP4023A, RSN_SELECTOR_LEN))
537 return WPA_CIPHER_WEP40;
538 if (!memcmp(s, RSN_CIPHER_SUITE_TKIP23A, RSN_SELECTOR_LEN))
539 return WPA_CIPHER_TKIP;
540 if (!memcmp(s, RSN_CIPHER_SUITE_CCMP23A, RSN_SELECTOR_LEN))
541 return WPA_CIPHER_CCMP;
542 if (!memcmp(s, RSN_CIPHER_SUITE_WEP10423A, RSN_SELECTOR_LEN))
543 return WPA_CIPHER_WEP104;
544
545 return 0;
546}
547
548int rtw_parse_wpa_ie23a(u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
549{
550 int i, ret = _SUCCESS;
551 int left, count;
552 u8 *pos;
553 u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1};
554
555 if (wpa_ie_len <= 0) {
556 /* No WPA IE - fail silently */
557 return _FAIL;
558 }
559
560 if ((*wpa_ie != _WPA_IE_ID_) || (*(wpa_ie+1) != (u8)(wpa_ie_len - 2)) ||
561 memcmp(wpa_ie + 2, RTW_WPA_OUI23A_TYPE, WPA_SELECTOR_LEN)) {
562 return _FAIL;
563 }
564
565 pos = wpa_ie;
566
567 pos += 8;
568 left = wpa_ie_len - 8;
569
570 /* group_cipher */
571 if (left >= WPA_SELECTOR_LEN) {
572
573 *group_cipher = rtw_get_wpa_cipher_suite23a(pos);
574
575 pos += WPA_SELECTOR_LEN;
576 left -= WPA_SELECTOR_LEN;
577 } else if (left > 0) {
578 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
579 ("%s: ie length mismatch, %u too much",
580 __func__, left));
581
582 return _FAIL;
583 }
584
585 /* pairwise_cipher */
586 if (left >= 2) {
587 /* count = le16_to_cpu(*(u16*)pos); */
588 count = get_unaligned_le16(pos);
589 pos += 2;
590 left -= 2;
591
592 if (count == 0 || left < count * WPA_SELECTOR_LEN) {
593 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
594 ("%s: ie count botch (pairwise), "
595 "count %u left %u", __func__,
596 count, left));
597 return _FAIL;
598 }
599
600 for (i = 0; i < count; i++) {
601 *pairwise_cipher |= rtw_get_wpa_cipher_suite23a(pos);
602
603 pos += WPA_SELECTOR_LEN;
604 left -= WPA_SELECTOR_LEN;
605 }
606 } else if (left == 1) {
607 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
608 ("%s: ie too short (for key mgmt)", __func__));
609 return _FAIL;
610 }
611
612 if (is_8021x) {
613 if (left >= 6) {
614 pos += 2;
615 if (!memcmp(pos, SUITE_1X, 4)) {
616 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
617 ("%s : there has 802.1x auth\n",
618 __func__));
619 *is_8021x = 1;
620 }
621 }
622 }
623
624 return ret;
625}
626
627int rtw_parse_wpa2_ie23a(u8* rsn_ie, int rsn_ie_len, int *group_cipher,
628 int *pairwise_cipher, int *is_8021x)
629{
630 int i, ret = _SUCCESS;
631 int left, count;
632 u8 *pos;
633 u8 SUITE_1X[4] = {0x00, 0x0f, 0xac, 0x01};
634
635 if (rsn_ie_len <= 0) {
636 /* No RSN IE - fail silently */
637 return _FAIL;
638 }
639
640 if ((*rsn_ie!= _WPA2_IE_ID_) || (*(rsn_ie+1) != (u8)(rsn_ie_len - 2))) {
641 return _FAIL;
642 }
643
644 pos = rsn_ie;
645 pos += 4;
646 left = rsn_ie_len - 4;
647
648 /* group_cipher */
649 if (left >= RSN_SELECTOR_LEN) {
650 *group_cipher = rtw_get_wpa2_cipher_suite23a(pos);
651
652 pos += RSN_SELECTOR_LEN;
653 left -= RSN_SELECTOR_LEN;
654 } else if (left > 0) {
655 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
656 ("%s: ie length mismatch, %u too much",
657 __func__, left));
658 return _FAIL;
659 }
660
661 /* pairwise_cipher */
662 if (left >= 2) {
663 /* count = le16_to_cpu(*(u16*)pos); */
664 count = get_unaligned_le16(pos);
665 pos += 2;
666 left -= 2;
667
668 if (count == 0 || left < count * RSN_SELECTOR_LEN) {
669 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
670 ("%s: ie count botch (pairwise), "
671 "count %u left %u",
672 __func__, count, left));
673 return _FAIL;
674 }
675
676 for (i = 0; i < count; i++) {
677 *pairwise_cipher |= rtw_get_wpa2_cipher_suite23a(pos);
678
679 pos += RSN_SELECTOR_LEN;
680 left -= RSN_SELECTOR_LEN;
681 }
682 } else if (left == 1) {
683 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
684 ("%s: ie too short (for key mgmt)", __func__));
685
686 return _FAIL;
687 }
688
689 if (is_8021x) {
690 if (left >= 6) {
691 pos += 2;
692 if (!memcmp(pos, SUITE_1X, 4)) {
693 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
694 ("%s (): there has 802.1x auth\n",
695 __func__));
696 *is_8021x = 1;
697 }
698 }
699 }
700
701 return ret;
702}
703
704int rtw_get_sec_ie23a(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
705 u8 *wpa_ie, u16 *wpa_len)
706{
707 u8 authmode, sec_idx, i;
708 u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
709 uint cnt;
710
711
712
713 /* Search required WPA or WPA2 IE and copy to sec_ie[ ] */
714
715 cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
716
717 sec_idx = 0;
718
719 while(cnt < in_len) {
720 authmode = in_ie[cnt];
721
722 if ((authmode == _WPA_IE_ID_) &&
723 !memcmp(&in_ie[cnt+2], &wpa_oui[0], 4)) {
724 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
725 ("\n rtw_get_wpa_ie23a: sec_idx =%d "
726 "in_ie[cnt+1]+2 =%d\n",
727 sec_idx, in_ie[cnt + 1] + 2));
728
729 if (wpa_ie) {
730 memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt+1]+2);
731
732 for (i = 0; i < (in_ie[cnt + 1] + 2); i = i + 8) {
733 RT_TRACE(_module_rtl871x_mlme_c_,
734 _drv_info_,
735 ("\n %2x,%2x,%2x,%2x,%2x,%2x,"
736 "%2x,%2x\n", wpa_ie[i],
737 wpa_ie[i + 1], wpa_ie[i + 2],
738 wpa_ie[i + 3], wpa_ie[i + 4],
739 wpa_ie[i + 5], wpa_ie[i + 6],
740 wpa_ie[i + 7]));
741 }
742 }
743
744 *wpa_len = in_ie[cnt + 1] + 2;
745 cnt += in_ie[cnt + 1] + 2; /* get next */
746 } else {
747 if (authmode == _WPA2_IE_ID_) {
748 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
749 ("\n get_rsn_ie: sec_idx =%d in_ie"
750 "[cnt+1]+2 =%d\n", sec_idx,
751 in_ie[cnt + 1] + 2));
752
753 if (rsn_ie) {
754 memcpy(rsn_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
755
756 for (i = 0; i < (in_ie[cnt + 1] + 2); i = i + 8) {
757 RT_TRACE(_module_rtl871x_mlme_c_,
758 _drv_info_,
759 ("\n %2x,%2x,%2x,%2x,%2x,%2x,"
760 "%2x,%2x\n", rsn_ie[i],
761 rsn_ie[i + 1], rsn_ie[i + 2],
762 rsn_ie[i + 3], rsn_ie[i + 4],
763 rsn_ie[i + 5], rsn_ie[i + 6],
764 rsn_ie[i + 7]));
765 }
766 }
767
768 *rsn_len = in_ie[cnt + 1] + 2;
769 cnt += in_ie[cnt + 1] + 2; /* get next */
770 } else {
771 cnt += in_ie[cnt + 1] + 2; /* get next */
772 }
773 }
774 }
775
776
777
778 return *rsn_len + *wpa_len;
779}
780
781u8 rtw_is_wps_ie23a(u8 *ie_ptr, uint *wps_ielen)
782{
783 u8 match = false;
784 u8 eid, wps_oui[4]= {0x0, 0x50, 0xf2, 0x04};
785
786 if (!ie_ptr)
787 return match;
788
789 eid = ie_ptr[0];
790
791 if ((eid == _WPA_IE_ID_) && !memcmp(&ie_ptr[2], wps_oui, 4)) {
792 /* DBG_8723A("==> found WPS_IE.....\n"); */
793 *wps_ielen = ie_ptr[1] + 2;
794 match = true;
795 }
796 return match;
797}
798
799/**
800 * rtw_get_wps_ie23a - Search WPS IE from a series of IEs
801 * @in_ie: Address of IEs to search
802 * @in_len: Length limit from in_ie
803 * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the
804 * buf starting from wps_ie
805 * @wps_ielen: If not NULL and WPS IE is found, will set to the length of
806 * the entire WPS IE
807 *
808 * Returns: The address of the WPS IE found, or NULL
809 */
810u8 *rtw_get_wps_ie23a(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
811{
812 uint cnt;
813 u8 *wpsie_ptr = NULL;
814 u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
815
816 if (wps_ielen)
817 *wps_ielen = 0;
818
819 if (!in_ie || in_len <= 0)
820 return wpsie_ptr;
821
822 cnt = 0;
823
824 while (cnt < in_len) {
825 eid = in_ie[cnt];
826
827 if ((eid == _WPA_IE_ID_) && !memcmp(&in_ie[cnt+2], wps_oui, 4)) {
828 wpsie_ptr = &in_ie[cnt];
829
830 if (wps_ie)
831 memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
832
833 if (wps_ielen)
834 *wps_ielen = in_ie[cnt + 1] + 2;
835
836 cnt += in_ie[cnt + 1] + 2;
837
838 break;
839 } else {
840 cnt += in_ie[cnt + 1] + 2; /* goto next */
841 }
842 }
843
844 return wpsie_ptr;
845}
846
847/**
848 * rtw_get_wps_attr23a - Search a specific WPS attribute from a given WPS IE
849 * @wps_ie: Address of WPS IE to search
850 * @wps_ielen: Length limit from wps_ie
851 * @target_attr_id: The attribute ID of WPS attribute to search
852 * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute
853 * will be copied to the buf starting from buf_attr
854 * @len_attr: If not NULL and the WPS attribute is found, will set to the
855 * length of the entire WPS attribute
856 *
857 * Returns: the address of the specific WPS attribute found, or NULL
858 */
859u8 *rtw_get_wps_attr23a(u8 *wps_ie, uint wps_ielen, u16 target_attr_id,
860 u8 *buf_attr, u32 *len_attr)
861{
862 u8 *attr_ptr = NULL;
863 u8 * target_attr_ptr = NULL;
864 u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04};
865
866 if (len_attr)
867 *len_attr = 0;
868
869 if ((wps_ie[0] != _VENDOR_SPECIFIC_IE_) ||
870 memcmp(wps_ie + 2, wps_oui, 4)) {
871 return attr_ptr;
872 }
873
874 /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */
875 attr_ptr = wps_ie + 6; /* goto first attr */
876
877 while (attr_ptr - wps_ie < wps_ielen) {
878 /* 4 = 2(Attribute ID) + 2(Length) */
879 u16 attr_id = get_unaligned_be16(attr_ptr);
880 u16 attr_data_len = get_unaligned_be16(attr_ptr + 2);
881 u16 attr_len = attr_data_len + 4;
882
883 /* DBG_8723A("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); */
884 if (attr_id == target_attr_id) {
885 target_attr_ptr = attr_ptr;
886
887 if (buf_attr)
888 memcpy(buf_attr, attr_ptr, attr_len);
889
890 if (len_attr)
891 *len_attr = attr_len;
892
893 break;
894 } else {
895 attr_ptr += attr_len; /* goto next */
896 }
897 }
898
899 return target_attr_ptr;
900}
901
902/**
903 * rtw_get_wps_attr_content23a - Search a specific WPS attribute content
904 * from a given WPS IE
905 * @wps_ie: Address of WPS IE to search
906 * @wps_ielen: Length limit from wps_ie
907 * @target_attr_id: The attribute ID of WPS attribute to search
908 * @buf_content: If not NULL and the WPS attribute is found, WPS attribute
909 * content will be copied to the buf starting from buf_content
910 * @len_content: If not NULL and the WPS attribute is found, will set to the
911 * length of the WPS attribute content
912 *
913 * Returns: the address of the specific WPS attribute content found, or NULL
914 */
915u8 *rtw_get_wps_attr_content23a(u8 *wps_ie, uint wps_ielen, u16 target_attr_id,
916 u8 *buf_content, uint *len_content)
917{
918 u8 *attr_ptr;
919 u32 attr_len;
920
921 if (len_content)
922 *len_content = 0;
923
924 attr_ptr = rtw_get_wps_attr23a(wps_ie, wps_ielen, target_attr_id,
925 NULL, &attr_len);
926
927 if (attr_ptr && attr_len) {
928 if (buf_content)
929 memcpy(buf_content, attr_ptr + 4, attr_len - 4);
930
931 if (len_content)
932 *len_content = attr_len - 4;
933
934 return attr_ptr + 4;
935 }
936
937 return NULL;
938}
939
940static int
941rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen,
942 struct rtw_ieee802_11_elems *elems,
943 int show_errors)
944{
945 unsigned int oui;
946
947 /* first 3 bytes in vendor specific information element are the IEEE
948 * OUI of the vendor. The following byte is used a vendor specific
949 * sub-type. */
950 if (elen < 4) {
951 if (show_errors) {
952 DBG_8723A("short vendor specific "
953 "information element ignored (len =%lu)\n",
954 (unsigned long) elen);
955 }
956 return -1;
957 }
958
959 oui = RTW_GET_BE24(pos);
960 switch (oui) {
961 case WLAN_OUI_MICROSOFT:
962 /* Microsoft/Wi-Fi information elements are further typed and
963 * subtyped */
964 switch (pos[3]) {
965 case 1:
966 /* Microsoft OUI (00:50:F2) with OUI Type 1:
967 * real WPA information element */
968 elems->wpa_ie = pos;
969 elems->wpa_ie_len = elen;
970 break;
971 case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
972 if (elen < 5) {
973 DBG_8723A("short WME "
974 "information element ignored "
975 "(len =%lu)\n",
976 (unsigned long) elen);
977 return -1;
978 }
979 switch (pos[4]) {
980 case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
981 case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
982 elems->wme = pos;
983 elems->wme_len = elen;
984 break;
985 case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
986 elems->wme_tspec = pos;
987 elems->wme_tspec_len = elen;
988 break;
989 default:
990 DBG_8723A("unknown WME "
991 "information element ignored "
992 "(subtype =%d len =%lu)\n",
993 pos[4], (unsigned long) elen);
994 return -1;
995 }
996 break;
997 case 4:
998 /* Wi-Fi Protected Setup (WPS) IE */
999 elems->wps_ie = pos;
1000 elems->wps_ie_len = elen;
1001 break;
1002 default:
1003 DBG_8723A("Unknown Microsoft "
1004 "information element ignored "
1005 "(type =%d len =%lu)\n",
1006 pos[3], (unsigned long) elen);
1007 return -1;
1008 }
1009 break;
1010
1011 case OUI_BROADCOM:
1012 switch (pos[3]) {
1013 case VENDOR_HT_CAPAB_OUI_TYPE:
1014 elems->vendor_ht_cap = pos;
1015 elems->vendor_ht_cap_len = elen;
1016 break;
1017 default:
1018 DBG_8723A("Unknown Broadcom "
1019 "information element ignored "
1020 "(type =%d len =%lu)\n",
1021 pos[3], (unsigned long) elen);
1022 return -1;
1023 }
1024 break;
1025
1026 default:
1027 DBG_8723A("unknown vendor specific information "
1028 "element ignored (vendor OUI %02x:%02x:%02x "
1029 "len =%lu)\n",
1030 pos[0], pos[1], pos[2], (unsigned long) elen);
1031 return -1;
1032 }
1033
1034 return 0;
1035}
1036
1037/**
1038 * ieee802_11_parse_elems - Parse information elements in management frames
1039 * @start: Pointer to the start of IEs
1040 * @len: Length of IE buffer in octets
1041 * @elems: Data structure for parsed elements
1042 * @show_errors: Whether to show parsing errors in debug log
1043 * Returns: Parsing result
1044 */
1045enum parse_res rtw_ieee802_11_parse_elems23a(u8 *start, uint len,
1046 struct rtw_ieee802_11_elems *elems,
1047 int show_errors)
1048{
1049 uint left = len;
1050 u8 *pos = start;
1051 int unknown = 0;
1052
1053 memset(elems, 0, sizeof(*elems));
1054
1055 while (left >= 2) {
1056 u8 id, elen;
1057
1058 id = *pos++;
1059 elen = *pos++;
1060 left -= 2;
1061
1062 if (elen > left) {
1063 if (show_errors) {
1064 DBG_8723A("IEEE 802.11 element "
1065 "parse failed (id =%d elen =%d "
1066 "left =%lu)\n",
1067 id, elen, (unsigned long) left);
1068 }
1069 return ParseFailed;
1070 }
1071
1072 switch (id) {
1073 case WLAN_EID_SSID:
1074 elems->ssid = pos;
1075 elems->ssid_len = elen;
1076 break;
1077 case WLAN_EID_SUPP_RATES:
1078 elems->supp_rates = pos;
1079 elems->supp_rates_len = elen;
1080 break;
1081 case WLAN_EID_FH_PARAMS:
1082 elems->fh_params = pos;
1083 elems->fh_params_len = elen;
1084 break;
1085 case WLAN_EID_DS_PARAMS:
1086 elems->ds_params = pos;
1087 elems->ds_params_len = elen;
1088 break;
1089 case WLAN_EID_CF_PARAMS:
1090 elems->cf_params = pos;
1091 elems->cf_params_len = elen;
1092 break;
1093 case WLAN_EID_TIM:
1094 elems->tim = pos;
1095 elems->tim_len = elen;
1096 break;
1097 case WLAN_EID_IBSS_PARAMS:
1098 elems->ibss_params = pos;
1099 elems->ibss_params_len = elen;
1100 break;
1101 case WLAN_EID_CHALLENGE:
1102 elems->challenge = pos;
1103 elems->challenge_len = elen;
1104 break;
1105 case WLAN_EID_ERP_INFO:
1106 elems->erp_info = pos;
1107 elems->erp_info_len = elen;
1108 break;
1109 case WLAN_EID_EXT_SUPP_RATES:
1110 elems->ext_supp_rates = pos;
1111 elems->ext_supp_rates_len = elen;
1112 break;
1113 case WLAN_EID_VENDOR_SPECIFIC:
1114 if (rtw_ieee802_11_parse_vendor_specific(pos, elen,
1115 elems,
1116 show_errors))
1117 unknown++;
1118 break;
1119 case WLAN_EID_RSN:
1120 elems->rsn_ie = pos;
1121 elems->rsn_ie_len = elen;
1122 break;
1123 case WLAN_EID_PWR_CAPABILITY:
1124 elems->power_cap = pos;
1125 elems->power_cap_len = elen;
1126 break;
1127 case WLAN_EID_SUPPORTED_CHANNELS:
1128 elems->supp_channels = pos;
1129 elems->supp_channels_len = elen;
1130 break;
1131 case WLAN_EID_MOBILITY_DOMAIN:
1132 elems->mdie = pos;
1133 elems->mdie_len = elen;
1134 break;
1135 case WLAN_EID_FAST_BSS_TRANSITION:
1136 elems->ftie = pos;
1137 elems->ftie_len = elen;
1138 break;
1139 case WLAN_EID_TIMEOUT_INTERVAL:
1140 elems->timeout_int = pos;
1141 elems->timeout_int_len = elen;
1142 break;
1143 case WLAN_EID_HT_CAPABILITY:
1144 elems->ht_capabilities = pos;
1145 elems->ht_capabilities_len = elen;
1146 break;
1147 case WLAN_EID_HT_OPERATION:
1148 elems->ht_operation = pos;
1149 elems->ht_operation_len = elen;
1150 break;
1151 default:
1152 unknown++;
1153 if (!show_errors)
1154 break;
1155 DBG_8723A("IEEE 802.11 element parse "
1156 "ignored unknown element (id =%d elen =%d)\n",
1157 id, elen);
1158 break;
1159 }
1160
1161 left -= elen;
1162 pos += elen;
1163 }
1164
1165 if (left)
1166 return ParseFailed;
1167
1168 return unknown ? ParseUnknown : ParseOK;
1169}
1170
1171static u8 key_char2num(u8 ch)
1172{
1173 if ((ch >= '0') && (ch <= '9'))
1174 return ch - '0';
1175 else if ((ch >= 'a') && (ch <= 'f'))
1176 return ch - 'a' + 10;
1177 else if ((ch >= 'A') && (ch <= 'F'))
1178 return ch - 'A' + 10;
1179 else
1180 return 0xff;
1181}
1182
1183u8 str_2char2num23a(u8 hch, u8 lch)
1184{
1185 return (key_char2num(hch) * 10) + key_char2num(lch);
1186}
1187
1188u8 key_2char2num23a(u8 hch, u8 lch)
1189{
1190 return (key_char2num(hch) << 4) | key_char2num(lch);
1191}
1192
1193void rtw_macaddr_cfg23a(u8 *mac_addr)
1194{
1195 u8 mac[ETH_ALEN];
1196 if (!mac_addr)
1197 return;
1198
1199 memcpy(mac, mac_addr, ETH_ALEN);
1200
1201 if (is_broadcast_ether_addr(mac) || is_zero_ether_addr(mac)) {
1202 mac[0] = 0x00;
1203 mac[1] = 0xe0;
1204 mac[2] = 0x4c;
1205 mac[3] = 0x87;
1206 mac[4] = 0x00;
1207 mac[5] = 0x00;
1208 /* use default mac addresss */
1209 memcpy(mac_addr, mac, ETH_ALEN);
1210 DBG_8723A("MAC Address from efuse error, assign default "
1211 "one !!!\n");
1212 }
1213 DBG_8723A("rtw_macaddr_cfg23a MAC Address = "MAC_FMT"\n",
1214 MAC_ARG(mac_addr));
1215}
1216
1217void dump_ies23a(u8 *buf, u32 buf_len) {
1218 u8* pos = (u8*)buf;
1219 u8 id, len;
1220
1221 while (pos-buf <= buf_len) {
1222 id = *pos;
1223 len = *(pos + 1);
1224
1225 DBG_8723A("%s ID:%u, LEN:%u\n", __func__, id, len);
1226#ifdef CONFIG_8723AU_P2P
1227 dump_p2p_ie23a(pos, len);
1228#endif
1229 dump_wps_ie23a(pos, len);
1230
1231 pos += (2 + len);
1232 }
1233}
1234
1235void dump_wps_ie23a(u8 *ie, u32 ie_len) {
1236 u8* pos = (u8*)ie;
1237 u16 id;
1238 u16 len;
1239
1240 u8 *wps_ie;
1241 uint wps_ielen;
1242
1243 wps_ie = rtw_get_wps_ie23a(ie, ie_len, NULL, &wps_ielen);
1244 if (wps_ie != ie || wps_ielen == 0)
1245 return;
1246
1247 pos+= 6;
1248 while (pos-ie < ie_len) {
1249 id = get_unaligned_be16(pos);
1250 len = get_unaligned_be16(pos + 2);
1251
1252 DBG_8723A("%s ID:0x%04x, LEN:%u\n", __func__, id, len);
1253
1254 pos += (4 + len);
1255 }
1256}
1257
1258#ifdef CONFIG_8723AU_P2P
1259void dump_p2p_ie23a(u8 *ie, u32 ie_len) {
1260 u8* pos = (u8*)ie;
1261 u8 id;
1262 u16 len;
1263
1264 u8 *p2p_ie;
1265 uint p2p_ielen;
1266
1267 p2p_ie = rtw_get_p2p_ie23a(ie, ie_len, NULL, &p2p_ielen);
1268 if (p2p_ie != ie || p2p_ielen == 0)
1269 return;
1270
1271 pos += 6;
1272 while (pos-ie < ie_len) {
1273 id = *pos;
1274 len = get_unaligned_le16(pos+1);
1275
1276 DBG_8723A("%s ID:%u, LEN:%u\n", __func__, id, len);
1277
1278 pos+= (3+len);
1279 }
1280}
1281
1282/**
1283 * rtw_get_p2p_ie23a - Search P2P IE from a series of IEs
1284 * @in_ie: Address of IEs to search
1285 * @in_len: Length limit from in_ie
1286 * @p2p_ie: If not NULL and P2P IE is found, P2P IE will be copied to the
1287 * buf starting from p2p_ie
1288 * @p2p_ielen: If not NULL and P2P IE is found, will set to the length of
1289 * the entire P2P IE
1290 *
1291 * Returns: The address of the P2P IE found, or NULL
1292 */
1293u8 *rtw_get_p2p_ie23a(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen)
1294{
1295 uint cnt = 0;
1296 u8 *p2p_ie_ptr;
1297 u8 eid, p2p_oui[4]={0x50, 0x6F, 0x9A, 0x09};
1298
1299 if (p2p_ielen)
1300 *p2p_ielen = 0;
1301
1302 while (cnt<in_len) {
1303 eid = in_ie[cnt];
1304 if ((in_len < 0) || (cnt > MAX_IE_SZ)) {
1305 dump_stack();
1306 return NULL;
1307 }
1308 if ((eid == _VENDOR_SPECIFIC_IE_) &&
1309 !memcmp(&in_ie[cnt + 2], p2p_oui, 4)) {
1310 p2p_ie_ptr = in_ie + cnt;
1311
1312 if (p2p_ie != NULL) {
1313 memcpy(p2p_ie, &in_ie[cnt],
1314 in_ie[cnt + 1] + 2);
1315 }
1316
1317 if (p2p_ielen != NULL) {
1318 *p2p_ielen = in_ie[cnt + 1] + 2;
1319 }
1320
1321 return p2p_ie_ptr;
1322
1323 break;
1324 } else {
1325 cnt += in_ie[cnt + 1] + 2; /* goto next */
1326 }
1327 }
1328
1329 return NULL;
1330}
1331
1332/**
1333 * rtw_get_p2p_attr23a - Search a specific P2P attribute from a given P2P IE
1334 * @p2p_ie: Address of P2P IE to search
1335 * @p2p_ielen: Length limit from p2p_ie
1336 * @target_attr_id: The attribute ID of P2P attribute to search
1337 * @buf_attr: If not NULL and the P2P attribute is found, P2P attribute will
1338 * be copied to the buf starting from buf_attr
1339 * @len_attr: If not NULL and the P2P attribute is found, will set to the
1340 * length of the entire P2P attribute
1341 *
1342 * Returns: the address of the specific WPS attribute found, or NULL
1343 */
1344u8 *rtw_get_p2p_attr23a(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id,
1345 u8 *buf_attr, u32 *len_attr)
1346{
1347 u8 *attr_ptr = NULL;
1348 u8 *target_attr_ptr = NULL;
1349 u8 p2p_oui[4]={0x50, 0x6F, 0x9A, 0x09};
1350
1351 if (len_attr)
1352 *len_attr = 0;
1353
1354 if (!p2p_ie || (p2p_ie[0] != _VENDOR_SPECIFIC_IE_) ||
1355 memcmp(p2p_ie + 2, p2p_oui, 4)) {
1356 return attr_ptr;
1357 }
1358
1359 /* 6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type) */
1360 attr_ptr = p2p_ie + 6; /* goto first attr */
1361
1362 while (attr_ptr - p2p_ie < p2p_ielen) {
1363 /* 3 = 1(Attribute ID) + 2(Length) */
1364 u8 attr_id = *attr_ptr;
1365 u16 attr_data_len = get_unaligned_le16(attr_ptr + 1);
1366 u16 attr_len = attr_data_len + 3;
1367
1368 /* DBG_8723A("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); */
1369 if (attr_id == target_attr_id) {
1370 target_attr_ptr = attr_ptr;
1371
1372 if (buf_attr)
1373 memcpy(buf_attr, attr_ptr, attr_len);
1374
1375 if (len_attr)
1376 *len_attr = attr_len;
1377
1378 break;
1379 } else {
1380 attr_ptr += attr_len; /* goto next */
1381 }
1382 }
1383
1384 return target_attr_ptr;
1385}
1386
1387/**
1388 * rtw_get_p2p_attr23a_content - Search a specific P2P attribute content from
1389 * a given P2P IE
1390 * @p2p_ie: Address of P2P IE to search
1391 * @p2p_ielen: Length limit from p2p_ie
1392 * @target_attr_id: The attribute ID of P2P attribute to search
1393 * @buf_content: If not NULL and the P2P attribute is found, P2P attribute
1394 * content will be copied to the buf starting from buf_content
1395 * @len_content: If not NULL and the P2P attribute is found, will set to the
1396 * length of the P2P attribute content
1397 *
1398 * Returns: the address of the specific P2P attribute content found, or NULL
1399 */
1400u8 *rtw_get_p2p_attr23a_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id,
1401 u8 *buf_content, uint *len_content)
1402{
1403 u8 *attr_ptr;
1404 u32 attr_len;
1405
1406 if (len_content)
1407 *len_content = 0;
1408
1409 attr_ptr = rtw_get_p2p_attr23a(p2p_ie, p2p_ielen, target_attr_id,
1410 NULL, &attr_len);
1411
1412 if (attr_ptr && attr_len) {
1413 if (buf_content)
1414 memcpy(buf_content, attr_ptr + 3, attr_len - 3);
1415
1416 if (len_content)
1417 *len_content = attr_len - 3;
1418
1419 return attr_ptr+3;
1420 }
1421
1422 return NULL;
1423}
1424
1425u32 rtw_set_p2p_attr_content23a(u8 *pbuf, u8 attr_id, u16 attr_len, u8 *pdata_attr)
1426{
1427 u32 a_len;
1428
1429 *pbuf = attr_id;
1430
1431 /* u16*)(pbuf + 1) = cpu_to_le16(attr_len); */
1432 put_unaligned_le16(attr_len, pbuf + 1);
1433
1434 if (pdata_attr)
1435 memcpy(pbuf + 3, pdata_attr, attr_len);
1436
1437 a_len = attr_len + 3;
1438
1439 return a_len;
1440}
1441
1442static uint rtw_p2p_attr_remove(u8 *ie, uint ielen_ori, u8 attr_id)
1443{
1444 u8 *target_attr;
1445 u32 target_attr_len;
1446 uint ielen = ielen_ori;
1447
1448 while(1) {
1449 target_attr = rtw_get_p2p_attr23a(ie, ielen, attr_id, NULL,
1450 &target_attr_len);
1451 if (target_attr && target_attr_len) {
1452 u8 *next_attr = target_attr+target_attr_len;
1453 uint remain_len = ielen-(next_attr-ie);
1454 /* dump_ies23a(ie, ielen); */
1455
1456 memset(target_attr, 0, target_attr_len);
1457 memcpy(target_attr, next_attr, remain_len);
1458 memset(target_attr+remain_len, 0, target_attr_len);
1459 *(ie + 1) -= target_attr_len;
1460 ielen -= target_attr_len;
1461 } else {
1462 /* if (index>0) */
1463 /* dump_ies23a(ie, ielen); */
1464 break;
1465 }
1466 }
1467
1468 return ielen;
1469}
1470
1471void rtw_wlan_bssid_ex_remove_p2p_attr23a(struct wlan_bssid_ex *bss_ex, u8 attr_id)
1472{
1473 u8 *p2p_ie;
1474 uint p2p_ielen, p2p_ielen_ori;
1475
1476 if ((p2p_ie = rtw_get_p2p_ie23a(bss_ex->IEs + _FIXED_IE_LENGTH_,
1477 bss_ex->IELength - _FIXED_IE_LENGTH_,
1478 NULL, &p2p_ielen_ori))) {
1479 p2p_ielen = rtw_p2p_attr_remove(p2p_ie, p2p_ielen_ori, attr_id);
1480 if (p2p_ielen != p2p_ielen_ori) {
1481 u8 *next_ie_ori = p2p_ie+p2p_ielen_ori;
1482 u8 *next_ie = p2p_ie+p2p_ielen;
1483 uint remain_len;
1484 remain_len = bss_ex->IELength-(next_ie_ori-bss_ex->IEs);
1485
1486 memcpy(next_ie, next_ie_ori, remain_len);
1487 memset(next_ie+remain_len, 0, p2p_ielen_ori-p2p_ielen);
1488 bss_ex->IELength -= p2p_ielen_ori-p2p_ielen;
1489 }
1490 }
1491}
1492
1493#endif /* CONFIG_8723AU_P2P */
1494
1495#ifdef CONFIG_8723AU_P2P
1496int rtw_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen)
1497{
1498 int match;
1499 uint cnt = 0;
1500 u8 eid, wfd_oui[4] = {0x50, 0x6F, 0x9A, 0x0A};
1501
1502 match = false;
1503
1504 if (in_len < 0) {
1505 return match;
1506 }
1507
1508 while (cnt < in_len)
1509 {
1510 eid = in_ie[cnt];
1511
1512 if ((eid == _VENDOR_SPECIFIC_IE_) &&
1513 !memcmp(&in_ie[cnt+2], wfd_oui, 4)) {
1514 if (wfd_ie != NULL) {
1515 memcpy(wfd_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
1516
1517 } else {
1518 if (wfd_ielen != NULL) {
1519 *wfd_ielen = 0;
1520 }
1521 }
1522
1523 if (wfd_ielen != NULL) {
1524 *wfd_ielen = in_ie[cnt + 1] + 2;
1525 }
1526
1527 cnt += in_ie[cnt + 1] + 2;
1528
1529 match = true;
1530 break;
1531 } else {
1532 cnt += in_ie[cnt + 1] +2; /* goto next */
1533 }
1534 }
1535
1536 if (match == true) {
1537 match = cnt;
1538 }
1539
1540 return match;
1541}
1542
1543/* attr_content: The output buffer, contains the "body field" of
1544 WFD attribute. */
1545/* attr_contentlen: The data length of the "body field" of WFD
1546 attribute. */
1547int rtw_get_wfd_attr_content(u8 *wfd_ie, uint wfd_ielen, u8 target_attr_id,
1548 u8 *attr_content, uint *attr_contentlen)
1549{
1550 int match;
1551 uint cnt = 0;
1552 u8 attr_id, wfd_oui[4] = {0x50, 0x6F, 0x9A, 0x0A};
1553
1554 match = false;
1555
1556 if ((wfd_ie[0] != _VENDOR_SPECIFIC_IE_) ||
1557 memcmp(wfd_ie + 2, wfd_oui, 4)) {
1558 return match;
1559 }
1560
1561 /* 1 (WFD IE) + 1 (Length) + 3 (OUI) + 1 (OUI Type) */
1562 cnt = 6;
1563 while (cnt < wfd_ielen) {
1564 u16 attrlen = get_unaligned_be16(wfd_ie + cnt + 1);
1565
1566 attr_id = wfd_ie[cnt];
1567 if (attr_id == target_attr_id) {
1568 /* 3 -> 1 byte for attribute ID field, 2
1569 bytes for length field */
1570 if (attr_content)
1571 memcpy(attr_content, &wfd_ie[cnt + 3], attrlen);
1572
1573 if (attr_contentlen)
1574 *attr_contentlen = attrlen;
1575
1576 cnt += attrlen + 3;
1577
1578 match = true;
1579 break;
1580 } else {
1581 cnt += attrlen + 3; /* goto next */
1582 }
1583 }
1584
1585 return match;
1586}
1587#endif /* CONFIG_8723AU_P2P */
1588
1589/* Baron adds to avoid FreeBSD warning */
1590int ieee80211_is_empty_essid23a(const char *essid, int essid_len)
1591{
1592 /* Single white space is for Linksys APs */
1593 if (essid_len == 1 && essid[0] == ' ')
1594 return 1;
1595
1596 /* Otherwise, if the entire essid is 0, we assume it is hidden */
1597 while (essid_len) {
1598 essid_len--;
1599 if (essid[essid_len] != '\0')
1600 return 0;
1601 }
1602
1603 return 1;
1604}
1605
1606static int rtw_get_cipher_info(struct wlan_network *pnetwork)
1607{
1608 u32 wpa_ielen;
1609 unsigned char *pbuf;
1610 int group_cipher = 0, pairwise_cipher = 0, is8021x = 0;
1611 int ret = _FAIL;
1612 int r;
1613 pbuf = rtw_get_wpa_ie23a(&pnetwork->network.IEs[12], &wpa_ielen,
1614 pnetwork->network.IELength - 12);
1615
1616 if (pbuf && (wpa_ielen > 0)) {
1617 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1618 ("rtw_get_cipher_info: wpa_ielen: %d", wpa_ielen));
1619 r = rtw_parse_wpa_ie23a(pbuf, wpa_ielen + 2, &group_cipher,
1620 &pairwise_cipher, &is8021x);
1621 if (r == _SUCCESS) {
1622 pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
1623 pnetwork->BcnInfo.group_cipher = group_cipher;
1624 pnetwork->BcnInfo.is_8021x = is8021x;
1625 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1626 ("%s: pnetwork->pairwise_cipher: %d, is_"
1627 "8021x is %d", __func__,
1628 pnetwork->BcnInfo.pairwise_cipher,
1629 pnetwork->BcnInfo.is_8021x));
1630 ret = _SUCCESS;
1631 }
1632 } else {
1633 pbuf = rtw_get_wpa2_ie23a(&pnetwork->network.IEs[12], &wpa_ielen,
1634 pnetwork->network.IELength - 12);
1635
1636 if (pbuf && (wpa_ielen > 0)) {
1637 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1638 ("get RSN IE\n"));
1639 r = rtw_parse_wpa2_ie23a(pbuf, wpa_ielen + 2,
1640 &group_cipher, &pairwise_cipher,
1641 &is8021x);
1642 if (r == _SUCCESS) {
1643 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1644 ("get RSN IE OK!!!\n"));
1645 pnetwork->BcnInfo.pairwise_cipher =
1646 pairwise_cipher;
1647 pnetwork->BcnInfo.group_cipher = group_cipher;
1648 pnetwork->BcnInfo.is_8021x = is8021x;
1649 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1650 ("%s: pnetwork->pairwise_cipher: %d,"
1651 "pnetwork->group_cipher is %d, "
1652 "is_8021x is %d", __func__,
1653 pnetwork->BcnInfo.pairwise_cipher,
1654 pnetwork->BcnInfo.group_cipher,
1655 pnetwork->BcnInfo.is_8021x));
1656 ret = _SUCCESS;
1657 }
1658 }
1659 }
1660
1661 return ret;
1662}
1663
1664void rtw_get_bcn_info23a(struct wlan_network *pnetwork)
1665{
1666 unsigned short cap = 0;
1667 u8 bencrypt = 0;
1668 /* u8 wpa_ie[255], rsn_ie[255]; */
1669 u16 wpa_len = 0, rsn_len = 0;
1670 struct HT_info_element *pht_info = NULL;
1671 struct ieee80211_ht_cap *pht_cap = NULL;
1672 unsigned int len;
1673 unsigned char *p;
1674
1675 memcpy(&cap, rtw_get_capability23a_from_ie(pnetwork->network.IEs), 2);
1676 cap = le16_to_cpu(cap);
1677 if (cap & WLAN_CAPABILITY_PRIVACY) {
1678 bencrypt = 1;
1679 pnetwork->network.Privacy = 1;
1680 } else {
1681 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
1682 }
1683 rtw_get_sec_ie23a(pnetwork->network.IEs, pnetwork->network.IELength,
1684 NULL, &rsn_len, NULL, &wpa_len);
1685 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1686 ("rtw_get_bcn_info23a: ssid =%s\n", pnetwork->network.Ssid.ssid));
1687 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1688 ("rtw_get_bcn_info23a: wpa_len =%d rsn_len =%d\n",
1689 wpa_len, rsn_len));
1690 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1691 ("rtw_get_bcn_info23a: ssid =%s\n", pnetwork->network.Ssid.ssid));
1692 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1693 ("rtw_get_bcn_info23a: wpa_len =%d rsn_len =%d\n",
1694 wpa_len, rsn_len));
1695
1696 if (rsn_len > 0) {
1697 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2;
1698 } else if (wpa_len > 0) {
1699 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA;
1700 } else {
1701 if (bencrypt)
1702 pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP;
1703 }
1704 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1705 ("rtw_get_bcn_info23a: pnetwork->encryp_protocol is %x\n",
1706 pnetwork->BcnInfo.encryp_protocol));
1707 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1708 ("rtw_get_bcn_info23a: pnetwork->encryp_protocol is %x\n",
1709 pnetwork->BcnInfo.encryp_protocol));
1710 rtw_get_cipher_info(pnetwork);
1711
1712 /* get bwmode and ch_offset */
1713 /* parsing HT_CAP_IE */
1714 p = rtw_get_ie23a(pnetwork->network.IEs + _FIXED_IE_LENGTH_,
1715 _HT_CAPABILITY_IE_, &len,
1716 pnetwork->network.IELength - _FIXED_IE_LENGTH_);
1717 if (p && len > 0) {
1718 pht_cap = (struct ieee80211_ht_cap *)(p + 2);
1719 pnetwork->BcnInfo.ht_cap_info = pht_cap->cap_info;
1720 } else {
1721 pnetwork->BcnInfo.ht_cap_info = 0;
1722 }
1723 /* parsing HT_INFO_IE */
1724 p = rtw_get_ie23a(pnetwork->network.IEs + _FIXED_IE_LENGTH_,
1725 _HT_ADD_INFO_IE_, &len,
1726 pnetwork->network.IELength - _FIXED_IE_LENGTH_);
1727 if (p && len > 0) {
1728 pht_info = (struct HT_info_element *)(p + 2);
1729 pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0];
1730 } else {
1731 pnetwork->BcnInfo.ht_info_infos_0 = 0;
1732 }
1733}
1734
1735/* show MCS rate, unit: 100Kbps */
1736u16 rtw_mcs_rate23a(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40,
1737 unsigned char * MCS_rate)
1738{
1739 u16 max_rate = 0;
1740
1741 if (rf_type == RF_1T1R) {
1742 if (MCS_rate[0] & BIT(7))
1743 max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350):
1744 ((short_GI_20)?722:650);
1745 else if (MCS_rate[0] & BIT(6))
1746 max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215):
1747 ((short_GI_20)?650:585);
1748 else if (MCS_rate[0] & BIT(5))
1749 max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):
1750 ((short_GI_20)?578:520);
1751 else if (MCS_rate[0] & BIT(4))
1752 max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):
1753 ((short_GI_20)?433:390);
1754 else if (MCS_rate[0] & BIT(3))
1755 max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):
1756 ((short_GI_20)?289:260);
1757 else if (MCS_rate[0] & BIT(2))
1758 max_rate = (bw_40MHz) ? ((short_GI_40)?450:405):
1759 ((short_GI_20)?217:195);
1760 else if (MCS_rate[0] & BIT(1))
1761 max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):
1762 ((short_GI_20)?144:130);
1763 else if (MCS_rate[0] & BIT(0))
1764 max_rate = (bw_40MHz) ? ((short_GI_40)?150:135):
1765 ((short_GI_20)?72:65);
1766 } else {
1767 if (MCS_rate[1]) {
1768 if (MCS_rate[1] & BIT(7))
1769 max_rate = (bw_40MHz) ? ((short_GI_40)?3000:2700):((short_GI_20)?1444:1300);
1770 else if (MCS_rate[1] & BIT(6))
1771 max_rate = (bw_40MHz) ? ((short_GI_40)?2700:2430):((short_GI_20)?1300:1170);
1772 else if (MCS_rate[1] & BIT(5))
1773 max_rate = (bw_40MHz) ? ((short_GI_40)?2400:2160):((short_GI_20)?1156:1040);
1774 else if (MCS_rate[1] & BIT(4))
1775 max_rate = (bw_40MHz) ? ((short_GI_40)?1800:1620):((short_GI_20)?867:780);
1776 else if (MCS_rate[1] & BIT(3))
1777 max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520);
1778 else if (MCS_rate[1] & BIT(2))
1779 max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390);
1780 else if (MCS_rate[1] & BIT(1))
1781 max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260);
1782 else if (MCS_rate[1] & BIT(0))
1783 max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130);
1784 } else {
1785 if (MCS_rate[0] & BIT(7))
1786 max_rate = (bw_40MHz) ? ((short_GI_40)?1500:1350):((short_GI_20)?722:650);
1787 else if (MCS_rate[0] & BIT(6))
1788 max_rate = (bw_40MHz) ? ((short_GI_40)?1350:1215):((short_GI_20)?650:585);
1789 else if (MCS_rate[0] & BIT(5))
1790 max_rate = (bw_40MHz) ? ((short_GI_40)?1200:1080):((short_GI_20)?578:520);
1791 else if (MCS_rate[0] & BIT(4))
1792 max_rate = (bw_40MHz) ? ((short_GI_40)?900:810):((short_GI_20)?433:390);
1793 else if (MCS_rate[0] & BIT(3))
1794 max_rate = (bw_40MHz) ? ((short_GI_40)?600:540):((short_GI_20)?289:260);
1795 else if (MCS_rate[0] & BIT(2))
1796 max_rate = (bw_40MHz) ? ((short_GI_40)?450:405):((short_GI_20)?217:195);
1797 else if (MCS_rate[0] & BIT(1))
1798 max_rate = (bw_40MHz) ? ((short_GI_40)?300:270):((short_GI_20)?144:130);
1799 else if (MCS_rate[0] & BIT(0))
1800 max_rate = (bw_40MHz) ? ((short_GI_40)?150:135):((short_GI_20)?72:65);
1801 }
1802 }
1803 return max_rate;
1804}
1805
1806int rtw_action_frame_parse23a(const u8 *frame, u32 frame_len, u8* category,
1807 u8 *action)
1808{
1809 const u8 *frame_body = frame + sizeof(struct ieee80211_hdr_3addr);
1810 u16 fc;
1811 u8 c, a = 0;
1812
1813 fc = le16_to_cpu(((struct ieee80211_hdr_3addr *)frame)->frame_control);
1814
1815 if ((fc & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE)) !=
1816 (IEEE80211_FTYPE_MGMT|IEEE80211_STYPE_ACTION)) {
1817 return false;
1818 }
1819
1820 c = frame_body[0];
1821
1822 switch (c) {
1823 case WLAN_CATEGORY_VENDOR_SPECIFIC: /* vendor-specific */
1824 break;
1825 default:
1826 a = frame_body[1];
1827 }
1828
1829 if (category)
1830 *category = c;
1831 if (action)
1832 *action = a;
1833
1834 return true;
1835}
1836
1837static const char *_action_public_str23a[] = {
1838 "ACT_PUB_BSSCOEXIST",
1839 "ACT_PUB_DSE_ENABLE",
1840 "ACT_PUB_DSE_DEENABLE",
1841 "ACT_PUB_DSE_REG_LOCATION",
1842 "ACT_PUB_EXT_CHL_SWITCH",
1843 "ACT_PUB_DSE_MSR_REQ",
1844 "ACT_PUB_DSE_MSR_RPRT",
1845 "ACT_PUB_MP",
1846 "ACT_PUB_DSE_PWR_CONSTRAINT",
1847 "ACT_PUB_VENDOR",
1848 "ACT_PUB_GAS_INITIAL_REQ",
1849 "ACT_PUB_GAS_INITIAL_RSP",
1850 "ACT_PUB_GAS_COMEBACK_REQ",
1851 "ACT_PUB_GAS_COMEBACK_RSP",
1852 "ACT_PUB_TDLS_DISCOVERY_RSP",
1853 "ACT_PUB_LOCATION_TRACK",
1854 "ACT_PUB_RSVD",
1855};
1856
1857const char *action_public_str23a(u8 action)
1858{
1859 action = (action >= ACT_PUBLIC_MAX) ? ACT_PUBLIC_MAX : action;
1860 return _action_public_str23a[action];
1861}
diff --git a/drivers/staging/rtl8723au/core/rtw_io.c b/drivers/staging/rtl8723au/core/rtw_io.c
new file mode 100644
index 000000000000..1cae8d7659b9
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_io.c
@@ -0,0 +1,266 @@
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 ******************************************************************************/
15/*
16
17The purpose of rtw_io.c
18
19a. provides the API
20
21b. provides the protocol engine
22
23c. provides the software interface between caller and the hardware interface
24
25Compiler Flag Option:
26
271. For USB:
28 a. USE_ASYNC_IRP: Both sync/async operations are provided.
29
30Only sync read/rtw_write_mem operations are provided.
31
32jackson@realtek.com.tw
33
34*/
35
36#define _RTW_IO_C_
37#include <osdep_service.h>
38#include <drv_types.h>
39#include <rtw_io.h>
40#include <osdep_intf.h>
41
42#include <usb_ops.h>
43
44u8 _rtw_read823a(struct rtw_adapter *adapter, u32 addr)
45{
46 u8 r_val;
47 struct io_priv *pio_priv = &adapter->iopriv;
48 struct intf_hdl *pintfhdl = &pio_priv->intf;
49
50 r_val = pintfhdl->io_ops._read8(pintfhdl, addr);
51
52 return r_val;
53}
54
55u16 _rtw_read1623a(struct rtw_adapter *adapter, u32 addr)
56{
57 u16 r_val;
58 struct io_priv *pio_priv = &adapter->iopriv;
59 struct intf_hdl *pintfhdl = &pio_priv->intf;
60
61 r_val = pintfhdl->io_ops._read16(pintfhdl, addr);
62
63 return le16_to_cpu(r_val);
64}
65
66u32 _rtw_read3223a(struct rtw_adapter *adapter, u32 addr)
67{
68 u32 r_val;
69 struct io_priv *pio_priv = &adapter->iopriv;
70 struct intf_hdl *pintfhdl = &pio_priv->intf;
71
72 r_val = pintfhdl->io_ops._read32(pintfhdl, addr);
73
74 return le32_to_cpu(r_val);
75}
76
77int _rtw_write823a(struct rtw_adapter *adapter, u32 addr, u8 val)
78{
79 struct io_priv *pio_priv = &adapter->iopriv;
80 struct intf_hdl *pintfhdl = &pio_priv->intf;
81 int ret;
82
83 ret = pintfhdl->io_ops._write8(pintfhdl, addr, val);
84
85 return RTW_STATUS_CODE23a(ret);
86}
87
88int _rtw_write1623a(struct rtw_adapter *adapter, u32 addr, u16 val)
89{
90 struct io_priv *pio_priv = &adapter->iopriv;
91 struct intf_hdl *pintfhdl = &pio_priv->intf;
92 int ret;
93
94 val = cpu_to_le16(val);
95 ret = pintfhdl->io_ops._write16(pintfhdl, addr, val);
96
97 return RTW_STATUS_CODE23a(ret);
98}
99int _rtw_write3223a(struct rtw_adapter *adapter, u32 addr, u32 val)
100{
101 struct io_priv *pio_priv = &adapter->iopriv;
102 struct intf_hdl *pintfhdl = &pio_priv->intf;
103 int ret;
104
105 val = cpu_to_le32(val);
106 ret = pintfhdl->io_ops._write32(pintfhdl, addr, val);
107
108 return RTW_STATUS_CODE23a(ret);
109}
110
111int _rtw_writeN23a(struct rtw_adapter *adapter, u32 addr , u32 length , u8 *pdata)
112{
113 struct io_priv *pio_priv = &adapter->iopriv;
114 struct intf_hdl *pintfhdl = (struct intf_hdl*)&pio_priv->intf;
115 int ret;
116
117 ret = pintfhdl->io_ops._writeN(pintfhdl, addr, length, pdata);
118
119 return RTW_STATUS_CODE23a(ret);
120}
121int _rtw_write823a_async23a(struct rtw_adapter *adapter, u32 addr, u8 val)
122{
123 struct io_priv *pio_priv = &adapter->iopriv;
124 struct intf_hdl *pintfhdl = &pio_priv->intf;
125 int ret;
126
127 ret = pintfhdl->io_ops._write8_async(pintfhdl, addr, val);
128
129 return RTW_STATUS_CODE23a(ret);
130}
131int _rtw_write1623a_async(struct rtw_adapter *adapter, u32 addr, u16 val)
132{
133 struct io_priv *pio_priv = &adapter->iopriv;
134 struct intf_hdl *pintfhdl = &pio_priv->intf;
135 int ret;
136
137 val = cpu_to_le16(val);
138 ret = pintfhdl->io_ops._write16_async(pintfhdl, addr, val);
139
140 return RTW_STATUS_CODE23a(ret);
141}
142int _rtw_write3223a_async23a(struct rtw_adapter *adapter, u32 addr, u32 val)
143{
144 struct io_priv *pio_priv = &adapter->iopriv;
145 struct intf_hdl *pintfhdl = &pio_priv->intf;
146 int ret;
147
148 val = cpu_to_le32(val);
149 ret = pintfhdl->io_ops._write32_async(pintfhdl, addr, val);
150
151 return RTW_STATUS_CODE23a(ret);
152}
153
154void _rtw_read_mem23a(struct rtw_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
155{
156 struct io_priv *pio_priv = &adapter->iopriv;
157 struct intf_hdl *pintfhdl = &pio_priv->intf;
158
159 if ((adapter->bDriverStopped == true) ||
160 (adapter->bSurpriseRemoved == true)) {
161 RT_TRACE(_module_rtl871x_io_c_, _drv_info_,
162 ("rtw_read_mem:bDriverStopped(%d) OR "
163 "bSurpriseRemoved(%d)", adapter->bDriverStopped,
164 adapter->bSurpriseRemoved));
165 return;
166 }
167
168 pintfhdl->io_ops._read_mem(pintfhdl, addr, cnt, pmem);
169}
170
171void _rtw_write_mem23a(struct rtw_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
172{
173 struct io_priv *pio_priv = &adapter->iopriv;
174 struct intf_hdl *pintfhdl = &pio_priv->intf;
175
176 pintfhdl->io_ops._write_mem(pintfhdl, addr, cnt, pmem);
177}
178
179void _rtw_read_port23a(struct rtw_adapter *adapter, u32 addr, u32 cnt,
180 struct recv_buf *rbuf)
181{
182 struct io_priv *pio_priv = &adapter->iopriv;
183 struct intf_hdl *pintfhdl = &pio_priv->intf;
184
185 if ((adapter->bDriverStopped == true) ||
186 (adapter->bSurpriseRemoved == true)) {
187 RT_TRACE(_module_rtl871x_io_c_, _drv_info_,
188 ("rtw_read_port:bDriverStopped(%d) OR "
189 "bSurpriseRemoved(%d)", adapter->bDriverStopped,
190 adapter->bSurpriseRemoved));
191 return;
192 }
193
194 pintfhdl->io_ops._read_port(pintfhdl, addr, cnt, rbuf);
195}
196
197void _rtw_read_port23a_cancel(struct rtw_adapter *adapter)
198{
199 void (*_read_port_cancel)(struct intf_hdl *pintfhdl);
200 struct io_priv *pio_priv = &adapter->iopriv;
201 struct intf_hdl *pintfhdl = &pio_priv->intf;
202
203 _read_port_cancel = pintfhdl->io_ops._read_port_cancel;
204
205 if (_read_port_cancel)
206 _read_port_cancel(pintfhdl);
207}
208
209u32 _rtw_write_port23a(struct rtw_adapter *adapter, u32 addr, u32 cnt,
210 struct xmit_buf *xbuf)
211{
212 struct io_priv *pio_priv = &adapter->iopriv;
213 struct intf_hdl *pintfhdl = &pio_priv->intf;
214 u32 ret = _SUCCESS;
215
216 ret = pintfhdl->io_ops._write_port(pintfhdl, addr, cnt, xbuf);
217
218 return ret;
219}
220
221u32 _rtw_write_port23a_and_wait23a(struct rtw_adapter *adapter, u32 addr, u32 cnt,
222 struct xmit_buf *pxmitbuf, int timeout_ms)
223{
224 int ret = _SUCCESS;
225 struct submit_ctx sctx;
226
227 rtw_sctx_init23a(&sctx, timeout_ms);
228 pxmitbuf->sctx = &sctx;
229
230 ret = _rtw_write_port23a(adapter, addr, cnt, pxmitbuf);
231
232 if (ret == _SUCCESS)
233 ret = rtw_sctx_wait23a(&sctx);
234
235 return ret;
236}
237
238void _rtw_write_port23a_cancel(struct rtw_adapter *adapter)
239{
240 void (*_write_port_cancel)(struct intf_hdl *pintfhdl);
241 struct io_priv *pio_priv = &adapter->iopriv;
242 struct intf_hdl *pintfhdl = &pio_priv->intf;
243
244 _write_port_cancel = pintfhdl->io_ops._write_port_cancel;
245
246 if (_write_port_cancel)
247 _write_port_cancel(pintfhdl);
248}
249
250int rtw_init_io_priv23a(struct rtw_adapter *padapter,
251 void (*set_intf_ops)(struct _io_ops *pops))
252{
253 struct io_priv *piopriv = &padapter->iopriv;
254 struct intf_hdl *pintf = &piopriv->intf;
255
256 if (set_intf_ops == NULL)
257 return _FAIL;
258
259 piopriv->padapter = padapter;
260 pintf->padapter = padapter;
261 pintf->pintf_dev = adapter_to_dvobj(padapter);
262
263 set_intf_ops(&pintf->io_ops);
264
265 return _SUCCESS;
266}
diff --git a/drivers/staging/rtl8723au/core/rtw_ioctl_set.c b/drivers/staging/rtl8723au/core/rtw_ioctl_set.c
new file mode 100644
index 000000000000..30d7185e5637
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_ioctl_set.c
@@ -0,0 +1,601 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _RTW_IOCTL_SET_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <rtw_ioctl_set.h>
20#include <hal_intf.h>
21
22#include <usb_osintf.h>
23#include <usb_ops.h>
24#include <linux/ieee80211.h>
25
26u8 rtw_do_join23a(struct rtw_adapter *padapter)
27{
28 struct list_head *plist, *phead;
29 u8* pibss = NULL;
30 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
31 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
32 u8 ret = _SUCCESS;
33
34 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
35 phead = get_list_head(queue);
36 plist = phead->next;
37
38 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
39 ("\n rtw_do_join23a: phead = %p; plist = %p\n\n\n",
40 phead, plist));
41
42 pmlmepriv->cur_network.join_res = -2;
43
44 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
45
46 pmlmepriv->to_join = true;
47
48 if (_rtw_queue_empty23a(queue) == true) {
49 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
50 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
51
52 /* when set_ssid/set_bssid for rtw_do_join23a(), but
53 scanning queue is empty */
54 /* we try to issue sitesurvey firstly */
55
56 if (pmlmepriv->LinkDetectInfo.bBusyTraffic == false ||
57 rtw_to_roaming(padapter) > 0) {
58 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
59 ("rtw_do_join23a(): site survey if scanned_queue "
60 "is empty\n."));
61 /* submit site_survey23a_cmd */
62 ret = rtw_sitesurvey_cmd23a(padapter,
63 &pmlmepriv->assoc_ssid, 1,
64 NULL, 0);
65 if (ret != _SUCCESS) {
66 pmlmepriv->to_join = false;
67 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
68 ("rtw_do_join23a(): site survey return "
69 "error\n."));
70 }
71 } else {
72 pmlmepriv->to_join = false;
73 ret = _FAIL;
74 }
75
76 goto exit;
77 } else {
78 int select_ret;
79 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
80 select_ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv);
81 if (select_ret == _SUCCESS) {
82 pmlmepriv->to_join = false;
83 mod_timer(&pmlmepriv->assoc_timer,
84 jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
85 } else {
86 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
87 struct wlan_bssid_ex *pdev_network;
88 /* submit createbss_cmd to change to a
89 ADHOC_MASTER */
90
91 /* pmlmepriv->lock has been acquired by
92 caller... */
93 pdev_network =
94 &padapter->registrypriv.dev_network;
95
96 pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
97
98 pibss = padapter->registrypriv.dev_network.MacAddress;
99
100 memcpy(&pdev_network->Ssid,
101 &pmlmepriv->assoc_ssid,
102 sizeof(struct cfg80211_ssid));
103
104 rtw_update_registrypriv_dev_network23a(padapter);
105
106 rtw_generate_random_ibss23a(pibss);
107
108 if (rtw_createbss_cmd23a(padapter) != _SUCCESS) {
109 RT_TRACE(_module_rtl871x_ioctl_set_c_,
110 _drv_err_,
111 ("***Error =>do_goin: rtw_creat"
112 "ebss_cmd status FAIL***\n"));
113 ret = false;
114 goto exit;
115 }
116
117 pmlmepriv->to_join = false;
118
119 RT_TRACE(_module_rtl871x_ioctl_set_c_,
120 _drv_info_,
121 ("***Error => rtw_select_and_join_from"
122 "_scanned_queue FAIL under STA_Mode"
123 "***\n "));
124 } else {
125 /* can't associate ; reset under-linking */
126 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
127
128 /* when set_ssid/set_bssid for rtw_do_join23a(),
129 but there are no desired bss in scanning
130 queue */
131 /* we try to issue sitesurvey firstly */
132 if (pmlmepriv->LinkDetectInfo.bBusyTraffic ==
133 false || rtw_to_roaming(padapter) > 0) {
134 /* DBG_8723A("rtw_do_join23a() when no "
135 "desired bss in scanning queue\n");
136 */
137 ret = rtw_sitesurvey_cmd23a(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
138 if (ret != _SUCCESS) {
139 pmlmepriv->to_join = false;
140 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("do_join(): site survey return error\n."));
141 }
142 } else {
143 ret = _FAIL;
144 pmlmepriv->to_join = false;
145 }
146 }
147 }
148 }
149
150exit:
151
152 return ret;
153}
154
155u8 rtw_set_802_11_ssid23a(struct rtw_adapter* padapter, struct cfg80211_ssid *ssid)
156{
157 u8 status = _SUCCESS;
158 u32 cur_time = 0;
159
160 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
161 struct wlan_network *pnetwork = &pmlmepriv->cur_network;
162
163
164
165 DBG_8723A_LEVEL(_drv_always_, "set ssid [%s] fw_state = 0x%08x\n",
166 ssid->ssid, get_fwstate(pmlmepriv));
167
168 if (padapter->hw_init_completed == false) {
169 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
170 ("set_ssid: hw_init_completed == false =>exit!!!\n"));
171 status = _FAIL;
172 goto exit;
173 }
174
175 spin_lock_bh(&pmlmepriv->lock);
176
177 DBG_8723A("Set SSID under fw_state = 0x%08x\n", get_fwstate(pmlmepriv));
178 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
179 goto handle_tkip_countermeasure;
180 } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
181 goto release_mlme_lock;
182 }
183
184 if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == true)
185 {
186 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
187 ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
188
189 if ((pmlmepriv->assoc_ssid.ssid_len == ssid->ssid_len) &&
190 !memcmp(&pmlmepriv->assoc_ssid.ssid, ssid->ssid,
191 ssid->ssid_len)) {
192 if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == false))
193 {
194 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
195 ("Set SSID is the same ssid, fw_state = 0x%08x\n",
196 get_fwstate(pmlmepriv)));
197
198 if (rtw_is_same_ibss23a(padapter, pnetwork) == false)
199 {
200 /* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
201 rtw_disassoc_cmd23a(padapter, 0, true);
202
203 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
204 rtw_indicate_disconnect23a(padapter);
205
206 rtw_free_assoc_resources23a(padapter, 1);
207
208 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
209 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
210 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
211 }
212 } else {
213 goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
214 }
215 } else {
216 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_JOINBSS, 1);
217 }
218 } else {
219 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
220 ("Set SSID not the same ssid\n"));
221 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
222 ("set_ssid =[%s] len = 0x%x\n", ssid->ssid,
223 (unsigned int)ssid->ssid_len));
224 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
225 ("assoc_ssid =[%s] len = 0x%x\n",
226 pmlmepriv->assoc_ssid.ssid,
227 (unsigned int)pmlmepriv->assoc_ssid.ssid_len));
228
229 rtw_disassoc_cmd23a(padapter, 0, true);
230
231 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
232 rtw_indicate_disconnect23a(padapter);
233
234 rtw_free_assoc_resources23a(padapter, 1);
235
236 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
237 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
238 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
239 }
240 }
241 }
242
243handle_tkip_countermeasure:
244
245 if (padapter->securitypriv.btkip_countermeasure == true) {
246 cur_time = jiffies;
247
248 if ((cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ)
249 {
250 padapter->securitypriv.btkip_countermeasure = false;
251 padapter->securitypriv.btkip_countermeasure_time = 0;
252 }
253 else
254 {
255 status = _FAIL;
256 goto release_mlme_lock;
257 }
258 }
259
260 memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct cfg80211_ssid));
261 pmlmepriv->assoc_by_bssid = false;
262
263 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
264 pmlmepriv->to_join = true;
265 }
266 else {
267 status = rtw_do_join23a(padapter);
268 }
269
270release_mlme_lock:
271 spin_unlock_bh(&pmlmepriv->lock);
272
273exit:
274 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
275 ("-rtw_set_802_11_ssid23a: status =%d\n", status));
276
277
278
279 return status;
280}
281
282u8 rtw_set_802_11_infrastructure_mode23a(struct rtw_adapter* padapter,
283 enum ndis_802_11_net_infra networktype)
284{
285 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
286 struct wlan_network *cur_network = &pmlmepriv->cur_network;
287 enum ndis_802_11_net_infra* pold_state = &cur_network->network.InfrastructureMode;
288
289
290
291 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_notice_,
292 ("+rtw_set_802_11_infrastructure_mode23a: old =%d new =%d fw_state = 0x%08x\n",
293 *pold_state, networktype, get_fwstate(pmlmepriv)));
294
295 if (*pold_state != networktype)
296 {
297 spin_lock_bh(&pmlmepriv->lock);
298
299 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, (" change mode!"));
300 /* DBG_8723A("change mode, old_mode =%d, new_mode =%d, fw_state = 0x%x\n", *pold_state, networktype, get_fwstate(pmlmepriv)); */
301
302 if (*pold_state == Ndis802_11APMode)
303 {
304 /* change to other mode from Ndis802_11APMode */
305 cur_network->join_res = -1;
306
307#ifdef CONFIG_8723AU_AP_MODE
308 stop_ap_mode23a(padapter);
309#endif
310 }
311
312 if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||(*pold_state == Ndis802_11IBSS))
313 rtw_disassoc_cmd23a(padapter, 0, true);
314
315 if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
316 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true))
317 rtw_free_assoc_resources23a(padapter, 1);
318
319 if ((*pold_state == Ndis802_11Infrastructure) ||(*pold_state == Ndis802_11IBSS))
320 {
321 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
322 {
323 rtw_indicate_disconnect23a(padapter); /* will clr Linked_state; before this function, we must have chked whether issue dis-assoc_cmd or not */
324 }
325 }
326
327 *pold_state = networktype;
328
329 _clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
330
331 switch (networktype)
332 {
333 case Ndis802_11IBSS:
334 set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
335 break;
336
337 case Ndis802_11Infrastructure:
338 set_fwstate(pmlmepriv, WIFI_STATION_STATE);
339 break;
340
341 case Ndis802_11APMode:
342 set_fwstate(pmlmepriv, WIFI_AP_STATE);
343#ifdef CONFIG_8723AU_AP_MODE
344 start_ap_mode23a(padapter);
345 /* rtw_indicate_connect23a(padapter); */
346#endif
347
348 break;
349
350 case Ndis802_11AutoUnknown:
351 case Ndis802_11InfrastructureMax:
352 break;
353 }
354
355 /* SecClearAllKeys(adapter); */
356
357 /* RT_TRACE(COMP_OID_SET, DBG_LOUD, ("set_infrastructure: fw_state:%x after changing mode\n", */
358 /* get_fwstate(pmlmepriv))); */
359
360 spin_unlock_bh(&pmlmepriv->lock);
361 }
362
363
364
365 return true;
366}
367
368u8 rtw_set_802_11_bssid23a_list_scan(struct rtw_adapter *padapter,
369 struct cfg80211_ssid *pssid, int ssid_max_num)
370{
371 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
372 u8 res = true;
373
374 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
375 ("+rtw_set_802_11_bssid23a_list_scan(), fw_state =%x\n",
376 get_fwstate(pmlmepriv)));
377
378 if (!padapter) {
379 res = false;
380 goto exit;
381 }
382 if (padapter->hw_init_completed == false) {
383 res = false;
384 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
385 ("\n === rtw_set_802_11_bssid23a_list_scan:"
386 "hw_init_completed == false ===\n"));
387 goto exit;
388 }
389
390 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ||
391 (pmlmepriv->LinkDetectInfo.bBusyTraffic == true)) {
392 /* Scan or linking is in progress, do nothing. */
393 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
394 ("rtw_set_802_11_bssid23a_list_scan fail since fw_state "
395 "= %x\n", get_fwstate(pmlmepriv)));
396 res = true;
397
398 if (check_fwstate(pmlmepriv,
399 (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) {
400 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
401 ("\n###_FW_UNDER_SURVEY|_FW_UNDER_LINKING\n"));
402 } else {
403 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
404 ("\n###pmlmepriv->sitesurveyctrl.traffic_"
405 "busy == true\n"));
406 }
407 } else {
408 if (rtw_is_scan_deny(padapter)) {
409 DBG_8723A(FUNC_ADPT_FMT": scan deny\n",
410 FUNC_ADPT_ARG(padapter));
411 return _SUCCESS;
412 }
413
414 spin_lock_bh(&pmlmepriv->lock);
415
416 res = rtw_sitesurvey_cmd23a(padapter, pssid, ssid_max_num,
417 NULL, 0);
418
419 spin_unlock_bh(&pmlmepriv->lock);
420 }
421exit:
422 return res;
423}
424
425u8 rtw_set_802_11_authentication_mode23a(struct rtw_adapter* padapter,
426 enum ndis_802_11_auth_mode authmode)
427{
428 struct security_priv *psecuritypriv = &padapter->securitypriv;
429 int res;
430 u8 ret;
431
432 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
433 ("set_802_11_auth.mode(): mode =%x\n", authmode));
434
435 psecuritypriv->ndisauthtype = authmode;
436
437 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
438 ("rtw_set_802_11_authentication_mode23a:"
439 "psecuritypriv->ndisauthtype =%d",
440 psecuritypriv->ndisauthtype));
441
442 if (psecuritypriv->ndisauthtype > 3)
443 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
444
445 res = rtw_set_auth23a(padapter, psecuritypriv);
446
447 if (res == _SUCCESS)
448 ret = true;
449 else
450 ret = false;
451
452 return ret;
453}
454
455u8 rtw_set_802_11_add_wep23a(struct rtw_adapter* padapter,
456 struct ndis_802_11_wep *wep)
457{
458 u8 bdefaultkey;
459 u8 btransmitkey;
460 int keyid, res;
461 struct security_priv *psecuritypriv = &padapter->securitypriv;
462 u8 ret = _SUCCESS;
463
464 bdefaultkey = (wep->KeyIndex & 0x40000000) > 0 ? false : true;
465 btransmitkey = (wep->KeyIndex & 0x80000000) > 0 ? true : false;
466 keyid = wep->KeyIndex & 0x3fffffff;
467
468 if (keyid >= 4) {
469 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
470 ("MgntActrtw_set_802_11_add_wep23a:keyid>4 =>fail\n"));
471 ret = false;
472 goto exit;
473 }
474
475 switch (wep->KeyLength)
476 {
477 case 5:
478 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
479 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
480 ("MgntActrtw_set_802_11_add_wep23a:wep->KeyLength = 5\n"));
481 break;
482 case 13:
483 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
484 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
485 ("MgntActrtw_set_802_11_add_wep23a:wep->KeyLength = 13\n"));
486 break;
487 default:
488 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
489 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
490 ("MgntActrtw_set_802_11_add_wep23a:wep->KeyLength!= 5 "
491 "or 13\n"));
492 break;
493 }
494
495 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
496 ("rtw_set_802_11_add_wep23a:befor memcpy, wep->KeyLength = 0x%x "
497 "wep->KeyIndex = 0x%x keyid =%x\n",
498 wep->KeyLength, wep->KeyIndex, keyid));
499
500 memcpy(&psecuritypriv->dot11DefKey[keyid].skey[0],
501 &wep->KeyMaterial, wep->KeyLength);
502
503 psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
504
505 psecuritypriv->dot11PrivacyKeyIndex = keyid;
506
507 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
508 ("rtw_set_802_11_add_wep23a:security key material : %x %x %x %x "
509 "%x %x %x %x %x %x %x %x %x\n",
510 psecuritypriv->dot11DefKey[keyid].skey[0],
511 psecuritypriv->dot11DefKey[keyid].skey[1],
512 psecuritypriv->dot11DefKey[keyid].skey[2],
513 psecuritypriv->dot11DefKey[keyid].skey[3],
514 psecuritypriv->dot11DefKey[keyid].skey[4],
515 psecuritypriv->dot11DefKey[keyid].skey[5],
516 psecuritypriv->dot11DefKey[keyid].skey[6],
517 psecuritypriv->dot11DefKey[keyid].skey[7],
518 psecuritypriv->dot11DefKey[keyid].skey[8],
519 psecuritypriv->dot11DefKey[keyid].skey[9],
520 psecuritypriv->dot11DefKey[keyid].skey[10],
521 psecuritypriv->dot11DefKey[keyid].skey[11],
522 psecuritypriv->dot11DefKey[keyid].skey[12]));
523
524 res = rtw_set_key23a(padapter, psecuritypriv, keyid, 1);
525
526 if (res == _FAIL)
527 ret = false;
528exit:
529
530 return ret;
531}
532
533/*
534* rtw_get_cur_max_rate23a -
535* @adapter: pointer to _adapter structure
536*
537* Return 0 or 100Kbps
538*/
539u16 rtw_get_cur_max_rate23a(struct rtw_adapter *adapter)
540{
541 int i = 0;
542 u8 *p;
543 u16 rate = 0, max_rate = 0;
544 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
545 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
546 struct registry_priv *pregistrypriv = &adapter->registrypriv;
547 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
548 struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
549 struct ieee80211_ht_cap *pht_capie;
550 u8 rf_type = 0;
551 u8 bw_40MHz = 0, short_GI_20 = 0, short_GI_40 = 0;
552 u16 mcs_rate = 0;
553 u32 ht_ielen = 0;
554
555 if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
556 !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
557 return 0;
558
559 if (pmlmeext->cur_wireless_mode & (WIRELESS_11_24N|WIRELESS_11_5N)) {
560 p = rtw_get_ie23a(&pcur_bss->IEs[12], _HT_CAPABILITY_IE_,
561 &ht_ielen, pcur_bss->IELength - 12);
562 if (p && ht_ielen > 0) {
563 pht_capie = (struct ieee80211_ht_cap *)(p + 2);
564
565 memcpy(&mcs_rate, &pht_capie->mcs, 2);
566
567 /* bw_40MHz = (pht_capie->cap_info&
568 IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1:0; */
569 /* cur_bwmod is updated by beacon, pmlmeinfo is
570 updated by association response */
571 bw_40MHz = (pmlmeext->cur_bwmode &&
572 (HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH &
573 pmlmeinfo->HT_info.infos[0])) ? 1:0;
574
575 /* short_GI = (pht_capie->cap_info & (IEEE80211_HT_CAP
576 _SGI_20|IEEE80211_HT_CAP_SGI_40)) ? 1 : 0; */
577 short_GI_20 = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info&IEEE80211_HT_CAP_SGI_20) ? 1:0;
578 short_GI_40 = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info&IEEE80211_HT_CAP_SGI_40) ? 1:0;
579
580 rtw23a_hal_get_hwreg(adapter, HW_VAR_RF_TYPE,
581 (u8 *)(&rf_type));
582 max_rate = rtw_mcs_rate23a(rf_type, bw_40MHz &
583 pregistrypriv->cbw40_enable,
584 short_GI_20, short_GI_40,
585 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate
586 );
587 }
588 } else {
589 while ((pcur_bss->SupportedRates[i] != 0) &&
590 (pcur_bss->SupportedRates[i] != 0xFF)) {
591 rate = pcur_bss->SupportedRates[i] & 0x7F;
592 if (rate>max_rate)
593 max_rate = rate;
594 i++;
595 }
596
597 max_rate = max_rate * 10 / 2;
598 }
599
600 return max_rate;
601}
diff --git a/drivers/staging/rtl8723au/core/rtw_led.c b/drivers/staging/rtl8723au/core/rtw_led.c
new file mode 100644
index 000000000000..68532a3b2c14
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_led.c
@@ -0,0 +1,1899 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15
16#include <drv_types.h>
17#include <rtl8723a_led.h>
18
19/* */
20/* Description: */
21/* Callback function of LED BlinkTimer, */
22/* it just schedules to corresponding BlinkWorkItem/led_blink_hdl23a */
23/* */
24static void BlinkTimerCallback(unsigned long data)
25{
26 struct led_8723a *pLed = (struct led_8723a *)data;
27 struct rtw_adapter *padapter = pLed->padapter;
28
29 /* DBG_8723A("%s\n", __func__); */
30
31 if ((padapter->bSurpriseRemoved == true) || (padapter->bDriverStopped == true))
32 {
33 /* DBG_8723A("%s bSurpriseRemoved:%d, bDriverStopped:%d\n", __func__, padapter->bSurpriseRemoved, padapter->bDriverStopped); */
34 return;
35 }
36 schedule_work(&pLed->BlinkWorkItem);
37}
38
39/* */
40/* Description: */
41/* Callback function of LED BlinkWorkItem. */
42/* We dispatch acture LED blink action according to LedStrategy. */
43/* */
44void BlinkWorkItemCallback23a(struct work_struct *work)
45{
46 struct led_8723a *pLed = container_of(work, struct led_8723a, BlinkWorkItem);
47 BlinkHandler23a(pLed);
48}
49
50/* */
51/* Description: */
52/* Reset status of led_8723a object. */
53/* */
54void ResetLedStatus23a(struct led_8723a * pLed) {
55
56 pLed->CurrLedState = RTW_LED_OFF; /* Current LED state. */
57 pLed->bLedOn = false; /* true if LED is ON, false if LED is OFF. */
58
59 pLed->bLedBlinkInProgress = false; /* true if it is blinking, false o.w.. */
60 pLed->bLedWPSBlinkInProgress = false;
61
62 pLed->BlinkTimes = 0; /* Number of times to toggle led state for blinking. */
63 pLed->BlinkingLedState = LED_UNKNOWN; /* Next state for blinking, either RTW_LED_ON or RTW_LED_OFF are. */
64
65 pLed->bLedNoLinkBlinkInProgress = false;
66 pLed->bLedLinkBlinkInProgress = false;
67 pLed->bLedStartToLinkBlinkInProgress = false;
68 pLed->bLedScanBlinkInProgress = false;
69}
70
71 /* */
72/* Description: */
73/* Initialize an led_8723a object. */
74/* */
75void
76InitLed871x23a(struct rtw_adapter *padapter, struct led_8723a *pLed, enum led_pin_8723a LedPin)
77{
78 pLed->padapter = padapter;
79 pLed->LedPin = LedPin;
80
81 ResetLedStatus23a(pLed);
82
83 setup_timer(&pLed->BlinkTimer, BlinkTimerCallback, (unsigned long)pLed);
84
85 INIT_WORK(&pLed->BlinkWorkItem, BlinkWorkItemCallback23a);
86}
87
88/* */
89/* Description: */
90/* DeInitialize an led_8723a object. */
91/* */
92void
93DeInitLed871x23a(struct led_8723a *pLed)
94{
95 cancel_work_sync(&pLed->BlinkWorkItem);
96 del_timer_sync(&pLed->BlinkTimer);
97 ResetLedStatus23a(pLed);
98}
99
100/* Description: */
101/* Implementation of LED blinking behavior. */
102/* It toggle off LED and schedule corresponding timer if necessary. */
103
104static void SwLedBlink(struct led_8723a *pLed)
105{
106 struct rtw_adapter *padapter = pLed->padapter;
107 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
108 u8 bStopBlinking = false;
109
110 /* Change LED according to BlinkingLedState specified. */
111 if (pLed->BlinkingLedState == RTW_LED_ON) {
112 SwLedOn23a(padapter, pLed);
113 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
114 } else {
115 SwLedOff23a(padapter, pLed);
116 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
117 }
118
119 /* Determine if we shall change LED state again. */
120 pLed->BlinkTimes--;
121 switch (pLed->CurrLedState) {
122
123 case LED_BLINK_NORMAL:
124 if (pLed->BlinkTimes == 0)
125 bStopBlinking = true;
126 break;
127 case LED_BLINK_StartToBlink:
128 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
129 check_fwstate(pmlmepriv, WIFI_STATION_STATE))
130 bStopBlinking = true;
131 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
132 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
133 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
134 bStopBlinking = true;
135 else if (pLed->BlinkTimes == 0)
136 bStopBlinking = true;
137 break;
138 case LED_BLINK_WPS:
139 if (pLed->BlinkTimes == 0)
140 bStopBlinking = true;
141 break;
142 default:
143 bStopBlinking = true;
144 break;
145 }
146
147 if (bStopBlinking) {
148 if ((check_fwstate(pmlmepriv, _FW_LINKED)) && !pLed->bLedOn)
149 SwLedOn23a(padapter, pLed);
150 else if ((check_fwstate(pmlmepriv, _FW_LINKED)) && pLed->bLedOn)
151 SwLedOff23a(padapter, pLed);
152
153 pLed->BlinkTimes = 0;
154 pLed->bLedBlinkInProgress = false;
155 } else {
156 /* Assign LED state to toggle. */
157 if (pLed->BlinkingLedState == RTW_LED_ON)
158 pLed->BlinkingLedState = RTW_LED_OFF;
159 else
160 pLed->BlinkingLedState = RTW_LED_ON;
161
162 /* Schedule a timer to toggle LED state. */
163 switch (pLed->CurrLedState) {
164 case LED_BLINK_NORMAL:
165 mod_timer(&pLed->BlinkTimer, jiffies +
166 msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
167 break;
168 case LED_BLINK_SLOWLY:
169 case LED_BLINK_StartToBlink:
170 mod_timer(&pLed->BlinkTimer, jiffies +
171 msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
172 break;
173 case LED_BLINK_WPS:
174 mod_timer(&pLed->BlinkTimer, jiffies +
175 msecs_to_jiffies(LED_BLINK_LONG_INTERVAL));
176 break;
177 default:
178 mod_timer(&pLed->BlinkTimer, jiffies +
179 msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
180 break;
181 }
182 }
183}
184
185static void SwLedBlink1(struct led_8723a *pLed)
186{
187 struct rtw_adapter *padapter = pLed->padapter;
188 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
189 unsigned long delay = 0;
190 u8 bStopBlinking = false;
191
192 /* Change LED according to BlinkingLedState specified. */
193 if (pLed->BlinkingLedState == RTW_LED_ON) {
194 SwLedOn23a(padapter, pLed);
195 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
196 ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
197 } else {
198 SwLedOff23a(padapter, pLed);
199 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
200 ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
201 }
202
203 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
204 SwLedOff23a(padapter, pLed);
205 ResetLedStatus23a(pLed);
206 return;
207 }
208 switch (pLed->CurrLedState) {
209 case LED_BLINK_SLOWLY:
210 if (pLed->bLedOn)
211 pLed->BlinkingLedState = RTW_LED_OFF;
212 else
213 pLed->BlinkingLedState = RTW_LED_ON;
214 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
215 break;
216 case LED_BLINK_NORMAL:
217 if (pLed->bLedOn)
218 pLed->BlinkingLedState = RTW_LED_OFF;
219 else
220 pLed->BlinkingLedState = RTW_LED_ON;
221 delay = LED_BLINK_LINK_INTERVAL_ALPHA;
222 break;
223 case LED_BLINK_SCAN:
224 pLed->BlinkTimes--;
225 if (pLed->BlinkTimes == 0)
226 bStopBlinking = true;
227 if (bStopBlinking) {
228 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
229 pLed->bLedLinkBlinkInProgress = true;
230 pLed->CurrLedState = LED_BLINK_NORMAL;
231 if (pLed->bLedOn)
232 pLed->BlinkingLedState = RTW_LED_OFF;
233 else
234 pLed->BlinkingLedState = RTW_LED_ON;
235 delay = LED_BLINK_LINK_INTERVAL_ALPHA;
236 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
237 } else if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
238 pLed->bLedNoLinkBlinkInProgress = true;
239 pLed->CurrLedState = LED_BLINK_SLOWLY;
240 if (pLed->bLedOn)
241 pLed->BlinkingLedState = RTW_LED_OFF;
242 else
243 pLed->BlinkingLedState = RTW_LED_ON;
244 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
245 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
246 }
247 pLed->bLedScanBlinkInProgress = false;
248 } else {
249 if (pLed->bLedOn)
250 pLed->BlinkingLedState = RTW_LED_OFF;
251 else
252 pLed->BlinkingLedState = RTW_LED_ON;
253 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
254 }
255 break;
256 case LED_BLINK_TXRX:
257 pLed->BlinkTimes--;
258 if (pLed->BlinkTimes == 0)
259 bStopBlinking = true;
260 if (bStopBlinking) {
261 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
262 pLed->bLedLinkBlinkInProgress = true;
263 pLed->CurrLedState = LED_BLINK_NORMAL;
264 if (pLed->bLedOn)
265 pLed->BlinkingLedState = RTW_LED_OFF;
266 else
267 pLed->BlinkingLedState = RTW_LED_ON;
268 delay = LED_BLINK_LINK_INTERVAL_ALPHA;
269 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
270 } else if (check_fwstate(pmlmepriv,
271 _FW_LINKED) == false) {
272 pLed->bLedNoLinkBlinkInProgress = true;
273 pLed->CurrLedState = LED_BLINK_SLOWLY;
274 if (pLed->bLedOn)
275 pLed->BlinkingLedState = RTW_LED_OFF;
276 else
277 pLed->BlinkingLedState = RTW_LED_ON;
278 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
279 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
280 }
281 pLed->BlinkTimes = 0;
282 pLed->bLedBlinkInProgress = false;
283 } else {
284 if (pLed->bLedOn)
285 pLed->BlinkingLedState = RTW_LED_OFF;
286 else
287 pLed->BlinkingLedState = RTW_LED_ON;
288 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
289 }
290 break;
291 case LED_BLINK_WPS:
292 if (pLed->bLedOn)
293 pLed->BlinkingLedState = RTW_LED_OFF;
294 else
295 pLed->BlinkingLedState = RTW_LED_ON;
296 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
297 break;
298 case LED_BLINK_WPS_STOP: /* WPS success */
299 if (pLed->BlinkingLedState == RTW_LED_ON)
300 bStopBlinking = false;
301 else
302 bStopBlinking = true;
303 if (bStopBlinking) {
304 pLed->bLedLinkBlinkInProgress = true;
305 pLed->CurrLedState = LED_BLINK_NORMAL;
306 if (pLed->bLedOn)
307 pLed->BlinkingLedState = RTW_LED_OFF;
308 else
309 pLed->BlinkingLedState = RTW_LED_ON;
310 delay = LED_BLINK_LINK_INTERVAL_ALPHA;
311 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
312
313 pLed->bLedWPSBlinkInProgress = false;
314 } else {
315 pLed->BlinkingLedState = RTW_LED_OFF;
316 delay = LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA;
317 }
318 break;
319 default:
320 break;
321 }
322 if (delay)
323 mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(delay));
324}
325
326static void SwLedBlink2(struct led_8723a *pLed)
327{
328 struct rtw_adapter *padapter = pLed->padapter;
329 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
330 u8 bStopBlinking = false;
331
332 /* Change LED according to BlinkingLedState specified. */
333 if (pLed->BlinkingLedState == RTW_LED_ON) {
334 SwLedOn23a(padapter, pLed);
335 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
336 ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
337 } else {
338 SwLedOff23a(padapter, pLed);
339 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
340 ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
341 }
342 switch (pLed->CurrLedState) {
343 case LED_BLINK_SCAN:
344 pLed->BlinkTimes--;
345 if (pLed->BlinkTimes == 0)
346 bStopBlinking = true;
347 if (bStopBlinking) {
348 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
349 SwLedOff23a(padapter, pLed);
350 } else if (check_fwstate(pmlmepriv, _FW_LINKED)) {
351 pLed->CurrLedState = RTW_LED_ON;
352 pLed->BlinkingLedState = RTW_LED_ON;
353 SwLedOn23a(padapter, pLed);
354 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
355 ("stop scan blink CurrLedState %d\n",
356 pLed->CurrLedState));
357 } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
358 pLed->CurrLedState = RTW_LED_OFF;
359 pLed->BlinkingLedState = RTW_LED_OFF;
360 SwLedOff23a(padapter, pLed);
361 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
362 ("stop scan blink CurrLedState %d\n",
363 pLed->CurrLedState));
364 }
365 pLed->bLedScanBlinkInProgress = false;
366 } else {
367 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
368 SwLedOff23a(padapter, pLed);
369 } else {
370 if (pLed->bLedOn)
371 pLed->BlinkingLedState = RTW_LED_OFF;
372 else
373 pLed->BlinkingLedState = RTW_LED_ON;
374 mod_timer(&pLed->BlinkTimer,
375 jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
376 }
377 }
378 break;
379 case LED_BLINK_TXRX:
380 pLed->BlinkTimes--;
381 if (pLed->BlinkTimes == 0)
382 bStopBlinking = true;
383 if (bStopBlinking) {
384 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
385 SwLedOff23a(padapter, pLed);
386 } else if (check_fwstate(pmlmepriv, _FW_LINKED)) {
387 pLed->CurrLedState = RTW_LED_ON;
388 pLed->BlinkingLedState = RTW_LED_ON;
389 SwLedOn23a(padapter, pLed);
390 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
391 ("stop CurrLedState %d\n", pLed->CurrLedState));
392
393 } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
394 pLed->CurrLedState = RTW_LED_OFF;
395 pLed->BlinkingLedState = RTW_LED_OFF;
396 SwLedOff23a(padapter, pLed);
397 RT_TRACE(_module_rtl8712_led_c_, _drv_info_,
398 ("stop CurrLedState %d\n", pLed->CurrLedState));
399 }
400 pLed->bLedBlinkInProgress = false;
401 } else {
402 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
403 SwLedOff23a(padapter, pLed);
404 } else {
405 if (pLed->bLedOn)
406 pLed->BlinkingLedState = RTW_LED_OFF;
407 else
408 pLed->BlinkingLedState = RTW_LED_ON;
409 mod_timer(&pLed->BlinkTimer,
410 jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
411 }
412 }
413 break;
414 default:
415 break;
416 }
417}
418
419static void SwLedBlink3(struct led_8723a *pLed)
420{
421 struct rtw_adapter *padapter = pLed->padapter;
422 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
423 u8 bStopBlinking = false;
424
425 /* Change LED according to BlinkingLedState specified. */
426 if (pLed->BlinkingLedState == RTW_LED_ON)
427 {
428 SwLedOn23a(padapter, pLed);
429 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
430 }
431 else
432 {
433 if (pLed->CurrLedState != LED_BLINK_WPS_STOP)
434 SwLedOff23a(padapter, pLed);
435 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
436 }
437
438 switch (pLed->CurrLedState)
439 {
440 case LED_BLINK_SCAN:
441 pLed->BlinkTimes--;
442 if (pLed->BlinkTimes == 0)
443 {
444 bStopBlinking = true;
445 }
446
447 if (bStopBlinking)
448 {
449 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on)
450 {
451 SwLedOff23a(padapter, pLed);
452 }
453 else if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
454 {
455 pLed->CurrLedState = RTW_LED_ON;
456 pLed->BlinkingLedState = RTW_LED_ON;
457 if (!pLed->bLedOn)
458 SwLedOn23a(padapter, pLed);
459
460 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
461 }
462 else if (check_fwstate(pmlmepriv, _FW_LINKED) == false)
463 {
464 pLed->CurrLedState = RTW_LED_OFF;
465 pLed->BlinkingLedState = RTW_LED_OFF;
466 if (pLed->bLedOn)
467 SwLedOff23a(padapter, pLed);
468
469 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
470 }
471 pLed->bLedScanBlinkInProgress = false;
472 }
473 else
474 {
475 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on)
476 {
477 SwLedOff23a(padapter, pLed);
478 }
479 else
480 {
481 if (pLed->bLedOn)
482 pLed->BlinkingLedState = RTW_LED_OFF;
483 else
484 pLed->BlinkingLedState = RTW_LED_ON;
485 mod_timer(&pLed->BlinkTimer,
486 jiffies + msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
487 }
488 }
489 break;
490
491 case LED_BLINK_TXRX:
492 pLed->BlinkTimes--;
493 if (pLed->BlinkTimes == 0)
494 {
495 bStopBlinking = true;
496 }
497 if (bStopBlinking)
498 {
499 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on)
500 {
501 SwLedOff23a(padapter, pLed);
502 }
503 else if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
504 {
505 pLed->CurrLedState = RTW_LED_ON;
506 pLed->BlinkingLedState = RTW_LED_ON;
507
508 if (!pLed->bLedOn)
509 SwLedOn23a(padapter, pLed);
510
511 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
512 }
513 else if (check_fwstate(pmlmepriv, _FW_LINKED) == false)
514 {
515 pLed->CurrLedState = RTW_LED_OFF;
516 pLed->BlinkingLedState = RTW_LED_OFF;
517
518 if (pLed->bLedOn)
519 SwLedOff23a(padapter, pLed);
520
521 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
522 }
523 pLed->bLedBlinkInProgress = false;
524 }
525 else
526 {
527 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on)
528 {
529 SwLedOff23a(padapter, pLed);
530 }
531 else
532 {
533 if (pLed->bLedOn)
534 pLed->BlinkingLedState = RTW_LED_OFF;
535 else
536 pLed->BlinkingLedState = RTW_LED_ON;
537 mod_timer(&pLed->BlinkTimer,
538 jiffies + msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
539 }
540 }
541 break;
542
543 case LED_BLINK_WPS:
544 if (pLed->bLedOn)
545 pLed->BlinkingLedState = RTW_LED_OFF;
546 else
547 pLed->BlinkingLedState = RTW_LED_ON;
548 mod_timer(&pLed->BlinkTimer, jiffies +
549 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
550 break;
551
552 case LED_BLINK_WPS_STOP: /* WPS success */
553 if (pLed->BlinkingLedState == RTW_LED_ON)
554 {
555 pLed->BlinkingLedState = RTW_LED_OFF;
556 mod_timer(&pLed->BlinkTimer, jiffies +
557 msecs_to_jiffies(LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA));
558 bStopBlinking = false;
559 } else {
560 bStopBlinking = true;
561 }
562
563 if (bStopBlinking)
564 {
565 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on)
566 {
567 SwLedOff23a(padapter, pLed);
568 }
569 else
570 {
571 pLed->CurrLedState = RTW_LED_ON;
572 pLed->BlinkingLedState = RTW_LED_ON;
573 SwLedOn23a(padapter, pLed);
574 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
575 }
576 pLed->bLedWPSBlinkInProgress = false;
577 }
578 break;
579
580 default:
581 break;
582 }
583}
584
585static void SwLedBlink4(struct led_8723a *pLed)
586{
587 struct rtw_adapter *padapter = pLed->padapter;
588 struct led_priv *ledpriv = &padapter->ledpriv;
589 struct led_8723a *pLed1 = &ledpriv->SwLed1;
590 u8 bStopBlinking = false;
591 unsigned long delay = 0;
592
593 /* Change LED according to BlinkingLedState specified. */
594 if (pLed->BlinkingLedState == RTW_LED_ON)
595 {
596 SwLedOn23a(padapter, pLed);
597 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
598 } else {
599 SwLedOff23a(padapter, pLed);
600 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
601 }
602
603 if (!pLed1->bLedWPSBlinkInProgress && pLed1->BlinkingLedState == LED_UNKNOWN)
604 {
605 pLed1->BlinkingLedState = RTW_LED_OFF;
606 pLed1->CurrLedState = RTW_LED_OFF;
607 SwLedOff23a(padapter, pLed1);
608 }
609
610 switch (pLed->CurrLedState)
611 {
612 case LED_BLINK_SLOWLY:
613 if (pLed->bLedOn)
614 pLed->BlinkingLedState = RTW_LED_OFF;
615 else
616 pLed->BlinkingLedState = RTW_LED_ON;
617 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
618 break;
619
620 case LED_BLINK_StartToBlink:
621 if (pLed->bLedOn) {
622 pLed->BlinkingLedState = RTW_LED_OFF;
623 delay = LED_BLINK_SLOWLY_INTERVAL;
624 } else {
625 pLed->BlinkingLedState = RTW_LED_ON;
626 delay = LED_BLINK_NORMAL_INTERVAL;
627 }
628 break;
629
630 case LED_BLINK_SCAN:
631 pLed->BlinkTimes--;
632 if (pLed->BlinkTimes == 0) {
633 bStopBlinking = false;
634 }
635
636 if (bStopBlinking) {
637 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
638 SwLedOff23a(padapter, pLed);
639 } else {
640 pLed->bLedNoLinkBlinkInProgress = false;
641 pLed->CurrLedState = LED_BLINK_SLOWLY;
642 if (pLed->bLedOn)
643 pLed->BlinkingLedState = RTW_LED_OFF;
644 else
645 pLed->BlinkingLedState = RTW_LED_ON;
646 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
647 }
648 pLed->bLedScanBlinkInProgress = false;
649 } else {
650 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
651 SwLedOff23a(padapter, pLed);
652 } else {
653 if (pLed->bLedOn)
654 pLed->BlinkingLedState = RTW_LED_OFF;
655 else
656 pLed->BlinkingLedState = RTW_LED_ON;
657 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
658 }
659 }
660 break;
661
662 case LED_BLINK_TXRX:
663 pLed->BlinkTimes--;
664 if (pLed->BlinkTimes == 0) {
665 bStopBlinking = true;
666 }
667 if (bStopBlinking) {
668 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
669 SwLedOff23a(padapter, pLed);
670 } else {
671 pLed->bLedNoLinkBlinkInProgress = true;
672 pLed->CurrLedState = LED_BLINK_SLOWLY;
673 if (pLed->bLedOn)
674 pLed->BlinkingLedState = RTW_LED_OFF;
675 else
676 pLed->BlinkingLedState = RTW_LED_ON;
677 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
678 }
679 pLed->bLedBlinkInProgress = false;
680 } else {
681 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
682 SwLedOff23a(padapter, pLed);
683 } else {
684 if (pLed->bLedOn)
685 pLed->BlinkingLedState = RTW_LED_OFF;
686 else
687 pLed->BlinkingLedState = RTW_LED_ON;
688 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
689 }
690 }
691 break;
692
693 case LED_BLINK_WPS:
694 if (pLed->bLedOn) {
695 pLed->BlinkingLedState = RTW_LED_OFF;
696 delay = LED_BLINK_SLOWLY_INTERVAL;
697 } else {
698 pLed->BlinkingLedState = RTW_LED_ON;
699 delay = LED_BLINK_NORMAL_INTERVAL;
700 }
701 break;
702
703 case LED_BLINK_WPS_STOP: /* WPS authentication fail */
704 if (pLed->bLedOn)
705 pLed->BlinkingLedState = RTW_LED_OFF;
706 else
707 pLed->BlinkingLedState = RTW_LED_ON;
708
709 delay = LED_BLINK_NORMAL_INTERVAL;
710 break;
711
712 case LED_BLINK_WPS_STOP_OVERLAP: /* WPS session overlap */
713 pLed->BlinkTimes--;
714 if (pLed->BlinkTimes == 0) {
715 if (pLed->bLedOn) {
716 pLed->BlinkTimes = 1;
717 } else {
718 bStopBlinking = true;
719 }
720 }
721
722 if (bStopBlinking) {
723 pLed->BlinkTimes = 10;
724 pLed->BlinkingLedState = RTW_LED_ON;
725 delay = LED_BLINK_LINK_INTERVAL_ALPHA;
726 } else {
727 if (pLed->bLedOn)
728 pLed->BlinkingLedState = RTW_LED_OFF;
729 else
730 pLed->BlinkingLedState = RTW_LED_ON;
731
732 delay = LED_BLINK_NORMAL_INTERVAL;
733 }
734 break;
735
736 default:
737 break;
738 }
739 if (delay)
740 mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(delay));
741
742 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("SwLedBlink4 CurrLedState %d\n", pLed->CurrLedState));
743}
744
745static void SwLedBlink5(struct led_8723a *pLed)
746{
747 struct rtw_adapter *padapter = pLed->padapter;
748 u8 bStopBlinking = false;
749 unsigned long delay = 0;
750
751 /* Change LED according to BlinkingLedState specified. */
752 if (pLed->BlinkingLedState == RTW_LED_ON) {
753 SwLedOn23a(padapter, pLed);
754 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
755 } else {
756 SwLedOff23a(padapter, pLed);
757 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
758 }
759
760 switch (pLed->CurrLedState)
761 {
762 case LED_BLINK_SCAN:
763 pLed->BlinkTimes--;
764 if (pLed->BlinkTimes == 0) {
765 bStopBlinking = true;
766 }
767
768 if (bStopBlinking) {
769 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
770 pLed->CurrLedState = RTW_LED_OFF;
771 pLed->BlinkingLedState = RTW_LED_OFF;
772 if (pLed->bLedOn)
773 SwLedOff23a(padapter, pLed);
774 } else {
775 pLed->CurrLedState = RTW_LED_ON;
776 pLed->BlinkingLedState = RTW_LED_ON;
777 if (!pLed->bLedOn)
778 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
779 }
780
781 pLed->bLedScanBlinkInProgress = false;
782 } else {
783 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
784 SwLedOff23a(padapter, pLed);
785 } else {
786 if (pLed->bLedOn)
787 pLed->BlinkingLedState = RTW_LED_OFF;
788 else
789 pLed->BlinkingLedState = RTW_LED_ON;
790 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
791 }
792 }
793 break;
794
795 case LED_BLINK_TXRX:
796 pLed->BlinkTimes--;
797 if (pLed->BlinkTimes == 0) {
798 bStopBlinking = true;
799 }
800
801 if (bStopBlinking) {
802 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
803 pLed->CurrLedState = RTW_LED_OFF;
804 pLed->BlinkingLedState = RTW_LED_OFF;
805 if (pLed->bLedOn)
806 SwLedOff23a(padapter, pLed);
807 } else {
808 pLed->CurrLedState = RTW_LED_ON;
809 pLed->BlinkingLedState = RTW_LED_ON;
810 if (!pLed->bLedOn)
811 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
812 }
813
814 pLed->bLedBlinkInProgress = false;
815 } else {
816 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) {
817 SwLedOff23a(padapter, pLed);
818 } else {
819 if (pLed->bLedOn)
820 pLed->BlinkingLedState = RTW_LED_OFF;
821 else
822 pLed->BlinkingLedState = RTW_LED_ON;
823 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
824 }
825 }
826 break;
827
828 default:
829 break;
830 }
831
832 if (delay)
833 mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(delay));
834
835 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("SwLedBlink5 CurrLedState %d\n", pLed->CurrLedState));
836}
837
838static void SwLedBlink6(struct led_8723a *pLed)
839{
840 struct rtw_adapter *padapter = pLed->padapter;
841
842 /* Change LED according to BlinkingLedState specified. */
843 if (pLed->BlinkingLedState == RTW_LED_ON) {
844 SwLedOn23a(padapter, pLed);
845 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
846 } else {
847 SwLedOff23a(padapter, pLed);
848 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
849 }
850 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("<==== blink6\n"));
851}
852
853/* ALPHA, added by chiyoko, 20090106 */
854static void
855SwLedControlMode1(struct rtw_adapter *padapter, enum led_ctl_mode LedAction)
856{
857 struct led_priv *ledpriv = &padapter->ledpriv;
858 struct led_8723a *pLed = &ledpriv->SwLed0;
859 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
860
861 long delay = -1;
862
863 switch (LedAction)
864 {
865 case LED_CTL_POWER_ON:
866 case LED_CTL_START_TO_LINK:
867 case LED_CTL_NO_LINK:
868 if (pLed->bLedNoLinkBlinkInProgress == false) {
869 if (pLed->CurrLedState == LED_BLINK_SCAN ||
870 IS_LED_WPS_BLINKING(pLed)) {
871 return;
872 }
873 if (pLed->bLedLinkBlinkInProgress == true) {
874 del_timer_sync(&pLed->BlinkTimer);
875 pLed->bLedLinkBlinkInProgress = false;
876 }
877 if (pLed->bLedBlinkInProgress == true) {
878 del_timer_sync(&pLed->BlinkTimer);
879 pLed->bLedBlinkInProgress = false;
880 }
881
882 pLed->bLedNoLinkBlinkInProgress = true;
883 pLed->CurrLedState = LED_BLINK_SLOWLY;
884 if (pLed->bLedOn)
885 pLed->BlinkingLedState = RTW_LED_OFF;
886 else
887 pLed->BlinkingLedState = RTW_LED_ON;
888 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
889 }
890 break;
891
892 case LED_CTL_LINK:
893 if (pLed->bLedLinkBlinkInProgress == false) {
894 if (pLed->CurrLedState == LED_BLINK_SCAN ||
895 IS_LED_WPS_BLINKING(pLed)) {
896 return;
897 }
898 if (pLed->bLedNoLinkBlinkInProgress == true) {
899 del_timer_sync(&pLed->BlinkTimer);
900 pLed->bLedNoLinkBlinkInProgress = false;
901 }
902 if (pLed->bLedBlinkInProgress == true) {
903 del_timer_sync(&pLed->BlinkTimer);
904 pLed->bLedBlinkInProgress = false;
905 }
906 pLed->bLedLinkBlinkInProgress = true;
907 pLed->CurrLedState = LED_BLINK_NORMAL;
908 if (pLed->bLedOn)
909 pLed->BlinkingLedState = RTW_LED_OFF;
910 else
911 pLed->BlinkingLedState = RTW_LED_ON;
912 delay = LED_BLINK_LINK_INTERVAL_ALPHA;
913 }
914 break;
915
916 case LED_CTL_SITE_SURVEY:
917 if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) &&
918 (check_fwstate(pmlmepriv, _FW_LINKED) == true))
919 ;
920 else if (pLed->bLedScanBlinkInProgress == false) {
921 if (IS_LED_WPS_BLINKING(pLed))
922 return;
923
924 if (pLed->bLedNoLinkBlinkInProgress == true) {
925 del_timer_sync(&pLed->BlinkTimer);
926 pLed->bLedNoLinkBlinkInProgress = false;
927 }
928 if (pLed->bLedLinkBlinkInProgress == true) {
929 del_timer_sync(&pLed->BlinkTimer);
930 pLed->bLedLinkBlinkInProgress = false;
931 }
932 if (pLed->bLedBlinkInProgress == true) {
933 del_timer_sync(&pLed->BlinkTimer);
934 pLed->bLedBlinkInProgress = false;
935 }
936 pLed->bLedScanBlinkInProgress = true;
937 pLed->CurrLedState = LED_BLINK_SCAN;
938 pLed->BlinkTimes = 24;
939 if (pLed->bLedOn)
940 pLed->BlinkingLedState = RTW_LED_OFF;
941 else
942 pLed->BlinkingLedState = RTW_LED_ON;
943 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
944 }
945 break;
946
947 case LED_CTL_TX:
948 case LED_CTL_RX:
949 if (pLed->bLedBlinkInProgress == false) {
950 if (pLed->CurrLedState == LED_BLINK_SCAN ||
951 IS_LED_WPS_BLINKING(pLed)) {
952 return;
953 }
954 if (pLed->bLedNoLinkBlinkInProgress == true) {
955 del_timer_sync(&pLed->BlinkTimer);
956 pLed->bLedNoLinkBlinkInProgress = false;
957 }
958 if (pLed->bLedLinkBlinkInProgress == true) {
959 del_timer_sync(&pLed->BlinkTimer);
960 pLed->bLedLinkBlinkInProgress = false;
961 }
962 pLed->bLedBlinkInProgress = true;
963 pLed->CurrLedState = LED_BLINK_TXRX;
964 pLed->BlinkTimes = 2;
965 if (pLed->bLedOn)
966 pLed->BlinkingLedState = RTW_LED_OFF;
967 else
968 pLed->BlinkingLedState = RTW_LED_ON;
969 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
970 }
971 break;
972
973 case LED_CTL_START_WPS: /* wait until xinpin finish */
974 case LED_CTL_START_WPS_BOTTON:
975 if (pLed->bLedWPSBlinkInProgress == false) {
976 if (pLed->bLedNoLinkBlinkInProgress == true) {
977 del_timer_sync(&pLed->BlinkTimer);
978 pLed->bLedNoLinkBlinkInProgress = false;
979 }
980 if (pLed->bLedLinkBlinkInProgress == true) {
981 del_timer_sync(&pLed->BlinkTimer);
982 pLed->bLedLinkBlinkInProgress = false;
983 }
984 if (pLed->bLedBlinkInProgress == true) {
985 del_timer_sync(&pLed->BlinkTimer);
986 pLed->bLedBlinkInProgress = false;
987 }
988 if (pLed->bLedScanBlinkInProgress == true) {
989 del_timer_sync(&pLed->BlinkTimer);
990 pLed->bLedScanBlinkInProgress = false;
991 }
992 pLed->bLedWPSBlinkInProgress = true;
993 pLed->CurrLedState = LED_BLINK_WPS;
994 if (pLed->bLedOn)
995 pLed->BlinkingLedState = RTW_LED_OFF;
996 else
997 pLed->BlinkingLedState = RTW_LED_ON;
998 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
999 }
1000 break;
1001
1002 case LED_CTL_STOP_WPS:
1003 if (pLed->bLedNoLinkBlinkInProgress == true) {
1004 del_timer_sync(&pLed->BlinkTimer);
1005 pLed->bLedNoLinkBlinkInProgress = false;
1006 }
1007 if (pLed->bLedLinkBlinkInProgress == true) {
1008 del_timer_sync(&pLed->BlinkTimer);
1009 pLed->bLedLinkBlinkInProgress = false;
1010 }
1011 if (pLed->bLedBlinkInProgress == true) {
1012 del_timer_sync(&pLed->BlinkTimer);
1013 pLed->bLedBlinkInProgress = false;
1014 }
1015 if (pLed->bLedScanBlinkInProgress == true) {
1016 del_timer_sync(&pLed->BlinkTimer);
1017 pLed->bLedScanBlinkInProgress = false;
1018 }
1019 if (pLed->bLedWPSBlinkInProgress) {
1020 del_timer_sync(&pLed->BlinkTimer);
1021 } else {
1022 pLed->bLedWPSBlinkInProgress = true;
1023 }
1024
1025 pLed->CurrLedState = LED_BLINK_WPS_STOP;
1026 if (pLed->bLedOn) {
1027 pLed->BlinkingLedState = RTW_LED_OFF;
1028 delay = LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA;
1029 } else {
1030 pLed->BlinkingLedState = RTW_LED_ON;
1031 delay = 0;
1032 }
1033 break;
1034
1035 case LED_CTL_STOP_WPS_FAIL:
1036 if (pLed->bLedWPSBlinkInProgress) {
1037 del_timer_sync(&pLed->BlinkTimer);
1038 pLed->bLedWPSBlinkInProgress = false;
1039 }
1040
1041 pLed->bLedNoLinkBlinkInProgress = true;
1042 pLed->CurrLedState = LED_BLINK_SLOWLY;
1043 if (pLed->bLedOn)
1044 pLed->BlinkingLedState = RTW_LED_OFF;
1045 else
1046 pLed->BlinkingLedState = RTW_LED_ON;
1047 delay = LED_BLINK_NO_LINK_INTERVAL_ALPHA;
1048 break;
1049
1050 case LED_CTL_POWER_OFF:
1051 pLed->CurrLedState = RTW_LED_OFF;
1052 pLed->BlinkingLedState = RTW_LED_OFF;
1053 if (pLed->bLedNoLinkBlinkInProgress) {
1054 del_timer_sync(&pLed->BlinkTimer);
1055 pLed->bLedNoLinkBlinkInProgress = false;
1056 }
1057 if (pLed->bLedLinkBlinkInProgress) {
1058 del_timer_sync(&pLed->BlinkTimer);
1059 pLed->bLedLinkBlinkInProgress = false;
1060 }
1061 if (pLed->bLedBlinkInProgress) {
1062 del_timer_sync(&pLed->BlinkTimer);
1063 pLed->bLedBlinkInProgress = false;
1064 }
1065 if (pLed->bLedWPSBlinkInProgress) {
1066 del_timer_sync(&pLed->BlinkTimer);
1067 pLed->bLedWPSBlinkInProgress = false;
1068 }
1069 if (pLed->bLedScanBlinkInProgress) {
1070 del_timer_sync(&pLed->BlinkTimer);
1071 pLed->bLedScanBlinkInProgress = false;
1072 }
1073
1074 SwLedOff23a(padapter, pLed);
1075 break;
1076
1077 default:
1078 break;
1079
1080 }
1081
1082 if (delay != -1)
1083 mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(delay));
1084
1085 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Led %d\n", pLed->CurrLedState));
1086}
1087
1088 /* Arcadyan/Sitecom , added by chiyoko, 20090216 */
1089static void
1090SwLedControlMode2(struct rtw_adapter *padapter, enum led_ctl_mode LedAction)
1091{
1092 struct led_priv *ledpriv = &padapter->ledpriv;
1093 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1094 struct led_8723a *pLed = &ledpriv->SwLed0;
1095 long delay = -1;
1096
1097 switch (LedAction) {
1098 case LED_CTL_SITE_SURVEY:
1099 if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
1100 ;
1101 else if (pLed->bLedScanBlinkInProgress == false) {
1102 if (IS_LED_WPS_BLINKING(pLed))
1103 return;
1104
1105 if (pLed->bLedBlinkInProgress == true) {
1106 del_timer_sync(&pLed->BlinkTimer);
1107 pLed->bLedBlinkInProgress = false;
1108 }
1109 pLed->bLedScanBlinkInProgress = true;
1110 pLed->CurrLedState = LED_BLINK_SCAN;
1111 pLed->BlinkTimes = 24;
1112 if (pLed->bLedOn)
1113 pLed->BlinkingLedState = RTW_LED_OFF;
1114 else
1115 pLed->BlinkingLedState = RTW_LED_ON;
1116 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
1117 }
1118 break;
1119 case LED_CTL_TX:
1120 case LED_CTL_RX:
1121 if ((pLed->bLedBlinkInProgress == false) &&
1122 (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
1123 if (pLed->CurrLedState == LED_BLINK_SCAN ||
1124 IS_LED_WPS_BLINKING(pLed)) {
1125 return;
1126 }
1127
1128 pLed->bLedBlinkInProgress = true;
1129 pLed->CurrLedState = LED_BLINK_TXRX;
1130 pLed->BlinkTimes = 2;
1131 if (pLed->bLedOn)
1132 pLed->BlinkingLedState = RTW_LED_OFF;
1133 else
1134 pLed->BlinkingLedState = RTW_LED_ON;
1135 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
1136 }
1137 break;
1138 case LED_CTL_LINK:
1139 pLed->CurrLedState = RTW_LED_ON;
1140 pLed->BlinkingLedState = RTW_LED_ON;
1141 if (pLed->bLedBlinkInProgress) {
1142 del_timer_sync(&pLed->BlinkTimer);
1143 pLed->bLedBlinkInProgress = false;
1144 }
1145 if (pLed->bLedScanBlinkInProgress) {
1146 del_timer_sync(&pLed->BlinkTimer);
1147 pLed->bLedScanBlinkInProgress = false;
1148 }
1149
1150 delay = 0;
1151 break;
1152 case LED_CTL_START_WPS: /* wait until xinpin finish */
1153 case LED_CTL_START_WPS_BOTTON:
1154 if (pLed->bLedWPSBlinkInProgress == false) {
1155 if (pLed->bLedBlinkInProgress == true) {
1156 del_timer_sync(&pLed->BlinkTimer);
1157 pLed->bLedBlinkInProgress = false;
1158 }
1159 if (pLed->bLedScanBlinkInProgress == true) {
1160 del_timer_sync(&pLed->BlinkTimer);
1161 pLed->bLedScanBlinkInProgress = false;
1162 }
1163 pLed->bLedWPSBlinkInProgress = true;
1164 pLed->CurrLedState = RTW_LED_ON;
1165 pLed->BlinkingLedState = RTW_LED_ON;
1166 delay = 0;
1167 }
1168 break;
1169 case LED_CTL_STOP_WPS:
1170 pLed->bLedWPSBlinkInProgress = false;
1171 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
1172 SwLedOff23a(padapter, pLed);
1173 } else {
1174 pLed->CurrLedState = RTW_LED_ON;
1175 pLed->BlinkingLedState = RTW_LED_ON;
1176 delay = 0;
1177 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
1178 }
1179 break;
1180 case LED_CTL_STOP_WPS_FAIL:
1181 pLed->bLedWPSBlinkInProgress = false;
1182 if (padapter->pwrctrlpriv.rf_pwrstate != rf_on) {
1183 SwLedOff23a(padapter, pLed);
1184 } else {
1185 pLed->CurrLedState = RTW_LED_OFF;
1186 pLed->BlinkingLedState = RTW_LED_OFF;
1187 delay = 0;
1188 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
1189 }
1190 break;
1191 case LED_CTL_START_TO_LINK:
1192 case LED_CTL_NO_LINK:
1193 if (!IS_LED_BLINKING(pLed))
1194 {
1195 pLed->CurrLedState = RTW_LED_OFF;
1196 pLed->BlinkingLedState = RTW_LED_OFF;
1197 delay = 0;
1198 }
1199 break;
1200 case LED_CTL_POWER_OFF:
1201 pLed->CurrLedState = RTW_LED_OFF;
1202 pLed->BlinkingLedState = RTW_LED_OFF;
1203 if (pLed->bLedBlinkInProgress) {
1204 del_timer_sync(&pLed->BlinkTimer);
1205 pLed->bLedBlinkInProgress = false;
1206 }
1207 if (pLed->bLedScanBlinkInProgress) {
1208 del_timer_sync(&pLed->BlinkTimer);
1209 pLed->bLedScanBlinkInProgress = false;
1210 }
1211 if (pLed->bLedWPSBlinkInProgress) {
1212 del_timer_sync(&pLed->BlinkTimer);
1213 pLed->bLedWPSBlinkInProgress = false;
1214 }
1215
1216 delay = 0;
1217 break;
1218 default:
1219 break;
1220
1221 }
1222
1223 if (delay != -1)
1224 mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(delay));
1225
1226 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
1227}
1228
1229 /* COREGA, added by chiyoko, 20090316 */
1230static void
1231SwLedControlMode3(struct rtw_adapter *padapter, enum led_ctl_mode LedAction)
1232{
1233 struct led_priv *ledpriv = &padapter->ledpriv;
1234 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1235 struct led_8723a *pLed = &ledpriv->SwLed0;
1236 long delay = -1;
1237
1238 switch (LedAction)
1239 {
1240 case LED_CTL_SITE_SURVEY:
1241 if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
1242 ;
1243 else if (pLed->bLedScanBlinkInProgress == false) {
1244 if (IS_LED_WPS_BLINKING(pLed))
1245 return;
1246
1247 if (pLed->bLedBlinkInProgress == true) {
1248 del_timer_sync(&pLed->BlinkTimer);
1249 pLed->bLedBlinkInProgress = false;
1250 }
1251 pLed->bLedScanBlinkInProgress = true;
1252 pLed->CurrLedState = LED_BLINK_SCAN;
1253 pLed->BlinkTimes = 24;
1254 if (pLed->bLedOn)
1255 pLed->BlinkingLedState = RTW_LED_OFF;
1256 else
1257 pLed->BlinkingLedState = RTW_LED_ON;
1258 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
1259 }
1260 break;
1261
1262 case LED_CTL_TX:
1263 case LED_CTL_RX:
1264 if ((pLed->bLedBlinkInProgress == false) &&
1265 (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
1266 if (pLed->CurrLedState == LED_BLINK_SCAN ||
1267 IS_LED_WPS_BLINKING(pLed)) {
1268 return;
1269 }
1270
1271 pLed->bLedBlinkInProgress = true;
1272 pLed->CurrLedState = LED_BLINK_TXRX;
1273 pLed->BlinkTimes = 2;
1274 if (pLed->bLedOn)
1275 pLed->BlinkingLedState = RTW_LED_OFF;
1276 else
1277 pLed->BlinkingLedState = RTW_LED_ON;
1278 delay = LED_BLINK_FASTER_INTERVAL_ALPHA;
1279 }
1280 break;
1281
1282 case LED_CTL_LINK:
1283 if (IS_LED_WPS_BLINKING(pLed))
1284 return;
1285
1286 pLed->CurrLedState = RTW_LED_ON;
1287 pLed->BlinkingLedState = RTW_LED_ON;
1288 if (pLed->bLedBlinkInProgress) {
1289 del_timer_sync(&pLed->BlinkTimer);
1290 pLed->bLedBlinkInProgress = false;
1291 }
1292 if (pLed->bLedScanBlinkInProgress) {
1293 del_timer_sync(&pLed->BlinkTimer);
1294 pLed->bLedScanBlinkInProgress = false;
1295 }
1296
1297 delay = 0;
1298 break;
1299
1300 case LED_CTL_START_WPS: /* wait until xinpin finish */
1301 case LED_CTL_START_WPS_BOTTON:
1302 if (pLed->bLedWPSBlinkInProgress == false) {
1303 if (pLed->bLedBlinkInProgress == true) {
1304 del_timer_sync(&pLed->BlinkTimer);
1305 pLed->bLedBlinkInProgress = false;
1306 }
1307 if (pLed->bLedScanBlinkInProgress == true) {
1308 del_timer_sync(&pLed->BlinkTimer);
1309 pLed->bLedScanBlinkInProgress = false;
1310 }
1311 pLed->bLedWPSBlinkInProgress = true;
1312 pLed->CurrLedState = LED_BLINK_WPS;
1313 if (pLed->bLedOn)
1314 pLed->BlinkingLedState = RTW_LED_OFF;
1315 else
1316 pLed->BlinkingLedState = RTW_LED_ON;
1317 delay = LED_BLINK_SCAN_INTERVAL_ALPHA;
1318 }
1319 break;
1320
1321 case LED_CTL_STOP_WPS:
1322 if (pLed->bLedWPSBlinkInProgress) {
1323 del_timer_sync(&pLed->BlinkTimer);
1324 pLed->bLedWPSBlinkInProgress = false;
1325 } else {
1326 pLed->bLedWPSBlinkInProgress = true;
1327 }
1328
1329 pLed->CurrLedState = LED_BLINK_WPS_STOP;
1330 if (pLed->bLedOn) {
1331 pLed->BlinkingLedState = RTW_LED_OFF;
1332 delay = LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA;
1333 } else {
1334 pLed->BlinkingLedState = RTW_LED_ON;
1335 delay = 0;
1336 }
1337
1338 break;
1339
1340 case LED_CTL_STOP_WPS_FAIL:
1341 if (pLed->bLedWPSBlinkInProgress) {
1342 del_timer_sync(&pLed->BlinkTimer);
1343 pLed->bLedWPSBlinkInProgress = false;
1344 }
1345
1346 pLed->CurrLedState = RTW_LED_OFF;
1347 pLed->BlinkingLedState = RTW_LED_OFF;
1348 delay = 0;
1349 break;
1350
1351 case LED_CTL_START_TO_LINK:
1352 case LED_CTL_NO_LINK:
1353 if (!IS_LED_BLINKING(pLed))
1354 {
1355 pLed->CurrLedState = RTW_LED_OFF;
1356 pLed->BlinkingLedState = RTW_LED_OFF;
1357 delay = 0;
1358 }
1359 break;
1360
1361 case LED_CTL_POWER_OFF:
1362 pLed->CurrLedState = RTW_LED_OFF;
1363 pLed->BlinkingLedState = RTW_LED_OFF;
1364 if (pLed->bLedBlinkInProgress) {
1365 del_timer_sync(&pLed->BlinkTimer);
1366 pLed->bLedBlinkInProgress = false;
1367 }
1368 if (pLed->bLedScanBlinkInProgress) {
1369 del_timer_sync(&pLed->BlinkTimer);
1370 pLed->bLedScanBlinkInProgress = false;
1371 }
1372 if (pLed->bLedWPSBlinkInProgress) {
1373 del_timer_sync(&pLed->BlinkTimer);
1374 pLed->bLedWPSBlinkInProgress = false;
1375 }
1376
1377 delay = 0;
1378 break;
1379
1380 default:
1381 break;
1382
1383 }
1384
1385 if (delay != -1)
1386 mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(delay));
1387
1388 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("CurrLedState %d\n", pLed->CurrLedState));
1389}
1390
1391 /* Edimax-Belkin, added by chiyoko, 20090413 */
1392static void
1393SwLedControlMode4(struct rtw_adapter *padapter, enum led_ctl_mode LedAction)
1394{
1395 struct led_priv *ledpriv = &padapter->ledpriv;
1396 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1397 struct led_8723a *pLed = &ledpriv->SwLed0;
1398 struct led_8723a *pLed1 = &ledpriv->SwLed1;
1399
1400 switch (LedAction)
1401 {
1402 case LED_CTL_START_TO_LINK:
1403 if (pLed1->bLedWPSBlinkInProgress) {
1404 pLed1->bLedWPSBlinkInProgress = false;
1405 del_timer_sync(&pLed1->BlinkTimer);
1406
1407 pLed1->BlinkingLedState = RTW_LED_OFF;
1408 pLed1->CurrLedState = RTW_LED_OFF;
1409
1410 if (pLed1->bLedOn)
1411 mod_timer(&pLed->BlinkTimer, jiffies);
1412 }
1413
1414 if (pLed->bLedStartToLinkBlinkInProgress == false) {
1415 if (pLed->CurrLedState == LED_BLINK_SCAN ||
1416 IS_LED_WPS_BLINKING(pLed)) {
1417 return;
1418 }
1419 if (pLed->bLedBlinkInProgress == true) {
1420 del_timer_sync(&pLed->BlinkTimer);
1421 pLed->bLedBlinkInProgress = false;
1422 }
1423 if (pLed->bLedNoLinkBlinkInProgress == true) {
1424 del_timer_sync(&pLed->BlinkTimer);
1425 pLed->bLedNoLinkBlinkInProgress = false;
1426 }
1427
1428 pLed->bLedStartToLinkBlinkInProgress = true;
1429 pLed->CurrLedState = LED_BLINK_StartToBlink;
1430 if (pLed->bLedOn) {
1431 pLed->BlinkingLedState = RTW_LED_OFF;
1432 mod_timer(&pLed->BlinkTimer,
1433 jiffies + msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
1434 } else {
1435 pLed->BlinkingLedState = RTW_LED_ON;
1436 mod_timer(&pLed->BlinkTimer,
1437 jiffies + msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
1438 }
1439 }
1440 break;
1441
1442 case LED_CTL_LINK:
1443 case LED_CTL_NO_LINK:
1444 /* LED1 settings */
1445 if (LedAction == LED_CTL_LINK) {
1446 if (pLed1->bLedWPSBlinkInProgress) {
1447 pLed1->bLedWPSBlinkInProgress = false;
1448 del_timer_sync(&pLed1->BlinkTimer);
1449
1450 pLed1->BlinkingLedState = RTW_LED_OFF;
1451 pLed1->CurrLedState = RTW_LED_OFF;
1452
1453 if (pLed1->bLedOn)
1454 mod_timer(&pLed->BlinkTimer, jiffies);
1455 }
1456 }
1457
1458 if (pLed->bLedNoLinkBlinkInProgress == false) {
1459 if (pLed->CurrLedState == LED_BLINK_SCAN ||
1460 IS_LED_WPS_BLINKING(pLed)) {
1461 return;
1462 }
1463 if (pLed->bLedBlinkInProgress == true) {
1464 del_timer_sync(&pLed->BlinkTimer);
1465 pLed->bLedBlinkInProgress = false;
1466 }
1467
1468 pLed->bLedNoLinkBlinkInProgress = true;
1469 pLed->CurrLedState = LED_BLINK_SLOWLY;
1470 if (pLed->bLedOn)
1471 pLed->BlinkingLedState = RTW_LED_OFF;
1472 else
1473 pLed->BlinkingLedState = RTW_LED_ON;
1474 mod_timer(&pLed->BlinkTimer, jiffies +
1475 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
1476 }
1477 break;
1478
1479 case LED_CTL_SITE_SURVEY:
1480 if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) &&
1481 (check_fwstate(pmlmepriv, _FW_LINKED) == true))
1482 ;
1483 else if (pLed->bLedScanBlinkInProgress == false) {
1484 if (IS_LED_WPS_BLINKING(pLed))
1485 return;
1486
1487 if (pLed->bLedNoLinkBlinkInProgress == true) {
1488 del_timer_sync(&pLed->BlinkTimer);
1489 pLed->bLedNoLinkBlinkInProgress = false;
1490 }
1491 if (pLed->bLedBlinkInProgress == true) {
1492 del_timer_sync(&pLed->BlinkTimer);
1493 pLed->bLedBlinkInProgress = false;
1494 }
1495 pLed->bLedScanBlinkInProgress = true;
1496 pLed->CurrLedState = LED_BLINK_SCAN;
1497 pLed->BlinkTimes = 24;
1498 if (pLed->bLedOn)
1499 pLed->BlinkingLedState = RTW_LED_OFF;
1500 else
1501 pLed->BlinkingLedState = RTW_LED_ON;
1502 mod_timer(&pLed->BlinkTimer, jiffies +
1503 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
1504 }
1505 break;
1506
1507 case LED_CTL_TX:
1508 case LED_CTL_RX:
1509 if (pLed->bLedBlinkInProgress == false) {
1510 if (pLed->CurrLedState == LED_BLINK_SCAN ||
1511 IS_LED_WPS_BLINKING(pLed)) {
1512 return;
1513 }
1514 if (pLed->bLedNoLinkBlinkInProgress == true) {
1515 del_timer_sync(&pLed->BlinkTimer);
1516 pLed->bLedNoLinkBlinkInProgress = false;
1517 }
1518 pLed->bLedBlinkInProgress = true;
1519 pLed->CurrLedState = LED_BLINK_TXRX;
1520 pLed->BlinkTimes = 2;
1521 if (pLed->bLedOn)
1522 pLed->BlinkingLedState = RTW_LED_OFF;
1523 else
1524 pLed->BlinkingLedState = RTW_LED_ON;
1525 mod_timer(&pLed->BlinkTimer, jiffies +
1526 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
1527 }
1528 break;
1529
1530 case LED_CTL_START_WPS: /* wait until xinpin finish */
1531 case LED_CTL_START_WPS_BOTTON:
1532 if (pLed1->bLedWPSBlinkInProgress) {
1533 pLed1->bLedWPSBlinkInProgress = false;
1534 del_timer_sync(&pLed1->BlinkTimer);
1535
1536 pLed1->BlinkingLedState = RTW_LED_OFF;
1537 pLed1->CurrLedState = RTW_LED_OFF;
1538
1539 if (pLed1->bLedOn)
1540 mod_timer(&pLed->BlinkTimer, jiffies);
1541 }
1542
1543 if (pLed->bLedWPSBlinkInProgress == false) {
1544 if (pLed->bLedNoLinkBlinkInProgress == true) {
1545 del_timer_sync(&pLed->BlinkTimer);
1546 pLed->bLedNoLinkBlinkInProgress = false;
1547 }
1548 if (pLed->bLedBlinkInProgress == true) {
1549 del_timer_sync(&pLed->BlinkTimer);
1550 pLed->bLedBlinkInProgress = false;
1551 }
1552 if (pLed->bLedScanBlinkInProgress == true) {
1553 del_timer_sync(&pLed->BlinkTimer);
1554 pLed->bLedScanBlinkInProgress = false;
1555 }
1556 pLed->bLedWPSBlinkInProgress = true;
1557 pLed->CurrLedState = LED_BLINK_WPS;
1558 if (pLed->bLedOn)
1559 {
1560 pLed->BlinkingLedState = RTW_LED_OFF;
1561 mod_timer(&pLed->BlinkTimer, jiffies +
1562 msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
1563 } else {
1564 pLed->BlinkingLedState = RTW_LED_ON;
1565 mod_timer(&pLed->BlinkTimer, jiffies +
1566 msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
1567 }
1568 }
1569 break;
1570
1571 case LED_CTL_STOP_WPS: /* WPS connect success */
1572 if (pLed->bLedWPSBlinkInProgress) {
1573 del_timer_sync(&pLed->BlinkTimer);
1574 pLed->bLedWPSBlinkInProgress = false;
1575 }
1576
1577 pLed->bLedNoLinkBlinkInProgress = true;
1578 pLed->CurrLedState = LED_BLINK_SLOWLY;
1579 if (pLed->bLedOn)
1580 pLed->BlinkingLedState = RTW_LED_OFF;
1581 else
1582 pLed->BlinkingLedState = RTW_LED_ON;
1583 mod_timer(&pLed->BlinkTimer, jiffies +
1584 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
1585 break;
1586
1587 case LED_CTL_STOP_WPS_FAIL: /* WPS authentication fail */
1588 if (pLed->bLedWPSBlinkInProgress) {
1589 del_timer_sync(&pLed->BlinkTimer);
1590 pLed->bLedWPSBlinkInProgress = false;
1591 }
1592
1593 pLed->bLedNoLinkBlinkInProgress = true;
1594 pLed->CurrLedState = LED_BLINK_SLOWLY;
1595 if (pLed->bLedOn)
1596 pLed->BlinkingLedState = RTW_LED_OFF;
1597 else
1598 pLed->BlinkingLedState = RTW_LED_ON;
1599 mod_timer(&pLed->BlinkTimer, jiffies +
1600 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
1601
1602 /* LED1 settings */
1603 if (pLed1->bLedWPSBlinkInProgress)
1604 del_timer_sync(&pLed1->BlinkTimer);
1605 else
1606 pLed1->bLedWPSBlinkInProgress = true;
1607
1608 pLed1->CurrLedState = LED_BLINK_WPS_STOP;
1609 if (pLed1->bLedOn)
1610 pLed1->BlinkingLedState = RTW_LED_OFF;
1611 else
1612 pLed1->BlinkingLedState = RTW_LED_ON;
1613 mod_timer(&pLed->BlinkTimer, jiffies +
1614 msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
1615
1616 break;
1617
1618 case LED_CTL_STOP_WPS_FAIL_OVERLAP: /* WPS session overlap */
1619 if (pLed->bLedWPSBlinkInProgress) {
1620 del_timer_sync(&pLed->BlinkTimer);
1621 pLed->bLedWPSBlinkInProgress = false;
1622 }
1623
1624 pLed->bLedNoLinkBlinkInProgress = true;
1625 pLed->CurrLedState = LED_BLINK_SLOWLY;
1626 if (pLed->bLedOn)
1627 pLed->BlinkingLedState = RTW_LED_OFF;
1628 else
1629 pLed->BlinkingLedState = RTW_LED_ON;
1630 mod_timer(&pLed->BlinkTimer, jiffies +
1631 msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
1632
1633 /* LED1 settings */
1634 if (pLed1->bLedWPSBlinkInProgress)
1635 del_timer_sync(&pLed1->BlinkTimer);
1636 else
1637 pLed1->bLedWPSBlinkInProgress = true;
1638
1639 pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP;
1640 pLed1->BlinkTimes = 10;
1641 if (pLed1->bLedOn)
1642 pLed1->BlinkingLedState = RTW_LED_OFF;
1643 else
1644 pLed1->BlinkingLedState = RTW_LED_ON;
1645 mod_timer(&pLed->BlinkTimer, jiffies +
1646 msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
1647
1648 break;
1649
1650 case LED_CTL_POWER_OFF:
1651 pLed->CurrLedState = RTW_LED_OFF;
1652 pLed->BlinkingLedState = RTW_LED_OFF;
1653
1654 if (pLed->bLedNoLinkBlinkInProgress) {
1655 del_timer_sync(&pLed->BlinkTimer);
1656 pLed->bLedNoLinkBlinkInProgress = false;
1657 }
1658 if (pLed->bLedLinkBlinkInProgress) {
1659 del_timer_sync(&pLed->BlinkTimer);
1660 pLed->bLedLinkBlinkInProgress = false;
1661 }
1662 if (pLed->bLedBlinkInProgress) {
1663 del_timer_sync(&pLed->BlinkTimer);
1664 pLed->bLedBlinkInProgress = false;
1665 }
1666 if (pLed->bLedWPSBlinkInProgress) {
1667 del_timer_sync(&pLed->BlinkTimer);
1668 pLed->bLedWPSBlinkInProgress = false;
1669 }
1670 if (pLed->bLedScanBlinkInProgress) {
1671 del_timer_sync(&pLed->BlinkTimer);
1672 pLed->bLedScanBlinkInProgress = false;
1673 }
1674 if (pLed->bLedStartToLinkBlinkInProgress) {
1675 del_timer_sync(&pLed->BlinkTimer);
1676 pLed->bLedStartToLinkBlinkInProgress = false;
1677 }
1678
1679 if (pLed1->bLedWPSBlinkInProgress) {
1680 del_timer_sync(&pLed1->BlinkTimer);
1681 pLed1->bLedWPSBlinkInProgress = false;
1682 }
1683
1684 pLed1->BlinkingLedState = LED_UNKNOWN;
1685 SwLedOff23a(padapter, pLed);
1686 SwLedOff23a(padapter, pLed1);
1687 break;
1688
1689 default:
1690 break;
1691
1692 }
1693
1694 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Led %d\n", pLed->CurrLedState));
1695}
1696
1697 /* Sercomm-Belkin, added by chiyoko, 20090415 */
1698static void
1699SwLedControlMode5(struct rtw_adapter *padapter, enum led_ctl_mode LedAction)
1700{
1701 struct led_priv *ledpriv = &padapter->ledpriv;
1702 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1703 struct led_8723a *pLed = &ledpriv->SwLed0;
1704
1705 switch (LedAction)
1706 {
1707 case LED_CTL_POWER_ON:
1708 case LED_CTL_NO_LINK:
1709 case LED_CTL_LINK: /* solid blue */
1710 pLed->CurrLedState = RTW_LED_ON;
1711 pLed->BlinkingLedState = RTW_LED_ON;
1712
1713 mod_timer(&pLed->BlinkTimer, jiffies);
1714 break;
1715
1716 case LED_CTL_SITE_SURVEY:
1717 if ((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED) == true))
1718 ;
1719 else if (pLed->bLedScanBlinkInProgress == false)
1720 {
1721 if (pLed->bLedBlinkInProgress == true)
1722 {
1723 del_timer_sync(&pLed->BlinkTimer);
1724 pLed->bLedBlinkInProgress = false;
1725 }
1726 pLed->bLedScanBlinkInProgress = true;
1727 pLed->CurrLedState = LED_BLINK_SCAN;
1728 pLed->BlinkTimes = 24;
1729 if (pLed->bLedOn)
1730 pLed->BlinkingLedState = RTW_LED_OFF;
1731 else
1732 pLed->BlinkingLedState = RTW_LED_ON;
1733 mod_timer(&pLed->BlinkTimer, jiffies +
1734 msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
1735 }
1736 break;
1737
1738 case LED_CTL_TX:
1739 case LED_CTL_RX:
1740 if (pLed->bLedBlinkInProgress == false) {
1741 if (pLed->CurrLedState == LED_BLINK_SCAN) {
1742 return;
1743 }
1744 pLed->bLedBlinkInProgress = true;
1745 pLed->CurrLedState = LED_BLINK_TXRX;
1746 pLed->BlinkTimes = 2;
1747 if (pLed->bLedOn)
1748 pLed->BlinkingLedState = RTW_LED_OFF;
1749 else
1750 pLed->BlinkingLedState = RTW_LED_ON;
1751 mod_timer(&pLed->BlinkTimer, jiffies +
1752 msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
1753 }
1754 break;
1755
1756 case LED_CTL_POWER_OFF:
1757 pLed->CurrLedState = RTW_LED_OFF;
1758 pLed->BlinkingLedState = RTW_LED_OFF;
1759
1760 if (pLed->bLedBlinkInProgress) {
1761 del_timer_sync(&pLed->BlinkTimer);
1762 pLed->bLedBlinkInProgress = false;
1763 }
1764
1765 SwLedOff23a(padapter, pLed);
1766 break;
1767
1768 default:
1769 break;
1770
1771 }
1772
1773 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("Led %d\n", pLed->CurrLedState));
1774}
1775
1776 /* WNC-Corega, added by chiyoko, 20090902 */
1777static void SwLedControlMode6(struct rtw_adapter *padapter,
1778 enum led_ctl_mode LedAction)
1779{
1780 struct led_priv *ledpriv = &padapter->ledpriv;
1781 struct led_8723a *pLed0 = &ledpriv->SwLed0;
1782
1783 switch (LedAction) {
1784 case LED_CTL_POWER_ON:
1785 case LED_CTL_LINK:
1786 case LED_CTL_NO_LINK:
1787 del_timer_sync(&pLed0->BlinkTimer);
1788 pLed0->CurrLedState = RTW_LED_ON;
1789 pLed0->BlinkingLedState = RTW_LED_ON;
1790 mod_timer(&pLed0->BlinkTimer, jiffies);
1791 break;
1792 case LED_CTL_POWER_OFF:
1793 SwLedOff23a(padapter, pLed0);
1794 break;
1795 default:
1796 break;
1797 }
1798
1799 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("ledcontrol 6 Led %d\n", pLed0->CurrLedState));
1800}
1801
1802/* */
1803/* Description: */
1804/* Handler function of LED Blinking. */
1805/* We dispatch acture LED blink action according to LedStrategy. */
1806/* */
1807void BlinkHandler23a(struct led_8723a *pLed)
1808{
1809 struct rtw_adapter *padapter = pLed->padapter;
1810 struct led_priv *ledpriv = &padapter->ledpriv;
1811
1812 /* DBG_8723A("%s (%s:%d)\n", __func__, current->comm, current->pid); */
1813
1814 if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
1815 return;
1816
1817 switch (ledpriv->LedStrategy) {
1818 case SW_LED_MODE0:
1819 SwLedBlink(pLed);
1820 break;
1821 case SW_LED_MODE1:
1822 SwLedBlink1(pLed);
1823 break;
1824 case SW_LED_MODE2:
1825 SwLedBlink2(pLed);
1826 break;
1827 case SW_LED_MODE3:
1828 SwLedBlink3(pLed);
1829 break;
1830 case SW_LED_MODE4:
1831 SwLedBlink4(pLed);
1832 break;
1833 case SW_LED_MODE5:
1834 SwLedBlink5(pLed);
1835 break;
1836 case SW_LED_MODE6:
1837 SwLedBlink6(pLed);
1838 break;
1839 default:
1840 break;
1841 }
1842}
1843
1844void
1845LedControl871x23a(struct rtw_adapter *padapter, enum led_ctl_mode LedAction) {
1846 struct led_priv *ledpriv = &padapter->ledpriv;
1847
1848 if ((padapter->bSurpriseRemoved == true) ||
1849 (padapter->bDriverStopped == true) ||
1850 (padapter->hw_init_completed == false)) {
1851 return;
1852 }
1853
1854 if (ledpriv->bRegUseLed == false)
1855 return;
1856
1857 /* if (!priv->up) */
1858 /* return; */
1859
1860 /* if (priv->bInHctTest) */
1861 /* return; */
1862
1863 if ((padapter->pwrctrlpriv.rf_pwrstate != rf_on &&
1864 padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) &&
1865 (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX ||
1866 LedAction == LED_CTL_SITE_SURVEY ||
1867 LedAction == LED_CTL_LINK ||
1868 LedAction == LED_CTL_NO_LINK ||
1869 LedAction == LED_CTL_POWER_ON)) {
1870 return;
1871 }
1872
1873 switch (ledpriv->LedStrategy) {
1874 case SW_LED_MODE0:
1875 break;
1876 case SW_LED_MODE1:
1877 SwLedControlMode1(padapter, LedAction);
1878 break;
1879 case SW_LED_MODE2:
1880 SwLedControlMode2(padapter, LedAction);
1881 break;
1882 case SW_LED_MODE3:
1883 SwLedControlMode3(padapter, LedAction);
1884 break;
1885 case SW_LED_MODE4:
1886 SwLedControlMode4(padapter, LedAction);
1887 break;
1888 case SW_LED_MODE5:
1889 SwLedControlMode5(padapter, LedAction);
1890 break;
1891 case SW_LED_MODE6:
1892 SwLedControlMode6(padapter, LedAction);
1893 break;
1894 default:
1895 break;
1896 }
1897
1898 RT_TRACE(_module_rtl8712_led_c_, _drv_info_, ("LedStrategy:%d, LedAction %d\n", ledpriv->LedStrategy, LedAction));
1899}
diff --git a/drivers/staging/rtl8723au/core/rtw_mlme.c b/drivers/staging/rtl8723au/core/rtw_mlme.c
new file mode 100644
index 000000000000..6cee78785bdc
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_mlme.c
@@ -0,0 +1,2500 @@
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 ******************************************************************************/
15#define _RTW_MLME_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <recv_osdep.h>
20#include <xmit_osdep.h>
21#include <hal_intf.h>
22#include <mlme_osdep.h>
23#include <sta_info.h>
24#include <linux/ieee80211.h>
25#include <wifi.h>
26#include <wlan_bssdef.h>
27#include <rtw_ioctl_set.h>
28
29extern u8 rtw_do_join23a(struct rtw_adapter * padapter);
30
31static void rtw_init_mlme_timer(struct rtw_adapter *padapter)
32{
33 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
34
35 setup_timer(&pmlmepriv->assoc_timer, rtw23a_join_to_handler,
36 (unsigned long)padapter);
37
38 setup_timer(&pmlmepriv->scan_to_timer, rtw_scan_timeout_handler23a,
39 (unsigned long)padapter);
40
41 setup_timer(&pmlmepriv->dynamic_chk_timer,
42 rtw_dynamic_check_timer_handler, (unsigned long)padapter);
43
44 setup_timer(&pmlmepriv->set_scan_deny_timer,
45 rtw_set_scan_deny_timer_hdl, (unsigned long)padapter);
46}
47
48int _rtw_init_mlme_priv23a(struct rtw_adapter *padapter)
49{
50 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
51 int res = _SUCCESS;
52
53 pmlmepriv->nic_hdl = padapter;
54
55 pmlmepriv->fw_state = 0;
56 pmlmepriv->cur_network.network.InfrastructureMode = Ndis802_11AutoUnknown;
57 pmlmepriv->scan_mode=SCAN_ACTIVE;/* 1: active, 0: pasive. Maybe someday we should rename this varable to "active_mode" (Jeff) */
58
59 spin_lock_init(&pmlmepriv->lock);
60 _rtw_init_queue23a(&pmlmepriv->scanned_queue);
61
62 memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct cfg80211_ssid));
63
64 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
65
66 rtw_clear_scan_deny(padapter);
67
68 rtw_init_mlme_timer(padapter);
69 return res;
70}
71
72#ifdef CONFIG_8723AU_AP_MODE
73static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
74{
75 if(*ppie)
76 {
77 kfree(*ppie);
78 *plen = 0;
79 *ppie=NULL;
80 }
81}
82#endif
83
84void rtw23a_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
85{
86#ifdef CONFIG_8723AU_AP_MODE
87 kfree(pmlmepriv->assoc_req);
88 kfree(pmlmepriv->assoc_rsp);
89 rtw_free_mlme_ie_data(&pmlmepriv->wps_beacon_ie, &pmlmepriv->wps_beacon_ie_len);
90 rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, &pmlmepriv->wps_probe_req_ie_len);
91 rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie, &pmlmepriv->wps_probe_resp_ie_len);
92 rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie, &pmlmepriv->wps_assoc_resp_ie_len);
93
94 rtw_free_mlme_ie_data(&pmlmepriv->p2p_beacon_ie, &pmlmepriv->p2p_beacon_ie_len);
95 rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_req_ie, &pmlmepriv->p2p_probe_req_ie_len);
96 rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_resp_ie, &pmlmepriv->p2p_probe_resp_ie_len);
97 rtw_free_mlme_ie_data(&pmlmepriv->p2p_go_probe_resp_ie, &pmlmepriv->p2p_go_probe_resp_ie_len);
98 rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_req_ie, &pmlmepriv->p2p_assoc_req_ie_len);
99
100 rtw_free_mlme_ie_data(&pmlmepriv->wfd_beacon_ie, &pmlmepriv->wfd_beacon_ie_len);
101 rtw_free_mlme_ie_data(&pmlmepriv->wfd_probe_req_ie, &pmlmepriv->wfd_probe_req_ie_len);
102 rtw_free_mlme_ie_data(&pmlmepriv->wfd_probe_resp_ie, &pmlmepriv->wfd_probe_resp_ie_len);
103 rtw_free_mlme_ie_data(&pmlmepriv->wfd_go_probe_resp_ie, &pmlmepriv->wfd_go_probe_resp_ie_len);
104 rtw_free_mlme_ie_data(&pmlmepriv->wfd_assoc_req_ie, &pmlmepriv->wfd_assoc_req_ie_len);
105#endif
106}
107
108void _rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv)
109{
110
111 rtw23a_free_mlme_priv_ie_data(pmlmepriv);
112
113}
114
115struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)
116{
117 struct wlan_network *pnetwork;
118
119 pnetwork = kzalloc(sizeof(struct wlan_network), GFP_ATOMIC);
120 if (pnetwork) {
121 INIT_LIST_HEAD(&pnetwork->list);
122 pnetwork->network_type = 0;
123 pnetwork->fixed = false;
124 pnetwork->last_scanned = jiffies;
125 pnetwork->aid = 0;
126 pnetwork->join_res = 0;
127 }
128
129 return pnetwork;
130}
131
132void _rtw_free_network23a(struct mlme_priv *pmlmepriv,
133 struct wlan_network *pnetwork, u8 isfreeall)
134{
135 u32 lifetime = SCANQUEUE_LIFETIME;
136
137 if (!pnetwork)
138 return;
139
140 if (pnetwork->fixed == true)
141 return;
142
143 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
144 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
145 lifetime = 1;
146
147 list_del_init(&pnetwork->list);
148
149 kfree(pnetwork);
150}
151
152void _rtw_free_network23a_nolock23a(struct mlme_priv *pmlmepriv,
153 struct wlan_network *pnetwork)
154{
155
156 if (pnetwork == NULL)
157 return;
158
159 if (pnetwork->fixed == true)
160 return;
161
162 list_del_init(&pnetwork->list);
163
164 kfree(pnetwork);
165}
166
167/*
168 return the wlan_network with the matching addr
169
170 Shall be calle under atomic context... to avoid possible racing condition...
171*/
172struct wlan_network *
173_rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr)
174{
175 struct list_head *phead, *plist;
176 struct wlan_network *pnetwork = NULL;
177
178 if (is_zero_ether_addr(addr)) {
179 pnetwork = NULL;
180 goto exit;
181 }
182
183 /* spin_lock_bh(&scanned_queue->lock); */
184
185 phead = get_list_head(scanned_queue);
186 plist = phead->next;
187
188 while (plist != phead) {
189 pnetwork = container_of(plist, struct wlan_network, list);
190
191 if (ether_addr_equal(addr, pnetwork->network.MacAddress))
192 break;
193
194 plist = plist->next;
195 }
196
197 if(plist == phead)
198 pnetwork = NULL;
199
200 /* spin_unlock_bh(&scanned_queue->lock); */
201
202exit:
203
204 return pnetwork;
205}
206
207void _rtw_free_network23a_queue23a(struct rtw_adapter *padapter, u8 isfreeall)
208{
209 struct list_head *phead, *plist, *ptmp;
210 struct wlan_network *pnetwork;
211 struct mlme_priv* pmlmepriv = &padapter->mlmepriv;
212 struct rtw_queue *scanned_queue = &pmlmepriv->scanned_queue;
213
214 spin_lock_bh(&scanned_queue->lock);
215
216 phead = get_list_head(scanned_queue);
217
218 list_for_each_safe(plist, ptmp, phead) {
219 pnetwork = container_of(plist, struct wlan_network, list);
220
221 _rtw_free_network23a(pmlmepriv,pnetwork, isfreeall);
222 }
223
224 spin_unlock_bh(&scanned_queue->lock);
225
226}
227
228int rtw_if_up23a(struct rtw_adapter *padapter) {
229
230 int res;
231
232 if(padapter->bDriverStopped || padapter->bSurpriseRemoved ||
233 (check_fwstate(&padapter->mlmepriv, _FW_LINKED)== false)) {
234 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_if_up23a:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved));
235 res=false;
236 }
237 else
238 res= true;
239
240 return res;
241}
242
243void rtw_generate_random_ibss23a(u8* pibss)
244{
245 unsigned long curtime = jiffies;
246
247 pibss[0] = 0x02; /* in ad-hoc mode bit1 must set to 1 */
248 pibss[1] = 0x11;
249 pibss[2] = 0x87;
250 pibss[3] = (u8)(curtime & 0xff) ;/* p[0]; */
251 pibss[4] = (u8)((curtime>>8) & 0xff) ;/* p[1]; */
252 pibss[5] = (u8)((curtime>>16) & 0xff) ;/* p[2]; */
253
254 return;
255}
256
257u8 *rtw_get_capability23a_from_ie(u8 *ie)
258{
259 return ie + 8 + 2;
260}
261
262u16 rtw_get_capability23a(struct wlan_bssid_ex *bss)
263{
264 u16 val;
265
266 memcpy((u8 *)&val, rtw_get_capability23a_from_ie(bss->IEs), 2);
267
268 return le16_to_cpu(val);
269}
270
271u8 *rtw_get_timestampe_from_ie23a(u8 *ie)
272{
273 return ie + 0;
274}
275
276u8 *rtw_get_beacon_interval23a_from_ie(u8 *ie)
277{
278 return ie + 8;
279}
280
281int rtw_init_mlme_priv23a (struct rtw_adapter *padapter)/* struct mlme_priv *pmlmepriv) */
282{
283 int res;
284
285 res = _rtw_init_mlme_priv23a(padapter);/* (pmlmepriv); */
286
287 return res;
288}
289
290void rtw_free_mlme_priv23a (struct mlme_priv *pmlmepriv)
291{
292
293 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_mlme_priv23a\n"));
294 _rtw_free_mlme_priv23a(pmlmepriv);
295
296}
297
298void rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 is_freeall);
299void rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 is_freeall)/* struct wlan_network *pnetwork, _queue *free_queue) */
300{
301
302 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
303 ("rtw_free_network ==> ssid = %s\n\n" ,
304 pnetwork->network.Ssid.ssid));
305 _rtw_free_network23a(pmlmepriv, pnetwork, is_freeall);
306
307}
308
309void rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork);
310void rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork)
311{
312
313 /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_network ==> ssid = %s\n\n" , pnetwork->network.Ssid.ssid)); */
314 _rtw_free_network23a_nolock23a(pmlmepriv, pnetwork);
315
316}
317
318void rtw_free_network_queue23a(struct rtw_adapter* dev, u8 isfreeall)
319{
320
321 _rtw_free_network23a_queue23a(dev, isfreeall);
322
323}
324
325/*
326 return the wlan_network with the matching addr
327
328 Shall be calle under atomic context... to avoid possible racing condition...
329*/
330struct wlan_network *
331rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr)
332{
333 struct wlan_network *pnetwork;
334
335 pnetwork = _rtw_find_network23a(scanned_queue, addr);
336
337 return pnetwork;
338}
339
340int rtw_is_same_ibss23a(struct rtw_adapter *adapter, struct wlan_network *pnetwork)
341{
342 int ret = true;
343 struct security_priv *psecuritypriv = &adapter->securitypriv;
344
345 if ((psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_) &&
346 (pnetwork->network.Privacy == 0))
347 {
348 ret = false;
349 }
350 else if ((psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_) &&
351 (pnetwork->network.Privacy == 1))
352 {
353 ret = false;
354 }
355 else
356 {
357 ret = true;
358 }
359
360 return ret;
361}
362
363inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b);
364inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
365{
366 /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("(%s,%d)(%s,%d)\n", */
367 /* a->Ssid.Ssid, a->Ssid.SsidLength, b->Ssid.Ssid, b->Ssid.SsidLength)); */
368 return (a->Ssid.ssid_len == b->Ssid.ssid_len) &&
369 !memcmp(a->Ssid.ssid, b->Ssid.ssid, a->Ssid.ssid_len);
370}
371
372int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
373{
374 u16 s_cap, d_cap;
375
376 memcpy((u8 *)&s_cap, rtw_get_capability23a_from_ie(src->IEs), 2);
377 memcpy((u8 *)&d_cap, rtw_get_capability23a_from_ie(dst->IEs), 2);
378
379 s_cap = le16_to_cpu(s_cap);
380 d_cap = le16_to_cpu(d_cap);
381
382 return ((src->Ssid.ssid_len == dst->Ssid.ssid_len) &&
383 /* (src->Configuration.DSConfig == dst->Configuration.DSConfig) && */
384 ether_addr_equal(src->MacAddress, dst->MacAddress) &&
385 ((!memcmp(src->Ssid.ssid, dst->Ssid.ssid, src->Ssid.ssid_len))) &&
386 ((s_cap & WLAN_CAPABILITY_IBSS) ==
387 (d_cap & WLAN_CAPABILITY_IBSS)) &&
388 ((s_cap & WLAN_CAPABILITY_ESS) ==
389 (d_cap & WLAN_CAPABILITY_ESS)));
390}
391
392struct wlan_network *rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_queue)
393{
394 struct list_head *plist, *phead;
395
396 struct wlan_network *pwlan;
397 struct wlan_network *oldest = NULL;
398
399 phead = get_list_head(scanned_queue);
400
401 list_for_each(plist, phead) {
402 pwlan = container_of(plist, struct wlan_network, list);
403
404 if (pwlan->fixed != true) {
405 if (!oldest || time_after(oldest->last_scanned,
406 pwlan->last_scanned))
407 oldest = pwlan;
408 }
409 }
410
411 return oldest;
412}
413
414void update_network23a(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
415 struct rtw_adapter * padapter, bool update_ie)
416{
417 u8 ss_ori = dst->PhyInfo.SignalStrength;
418 u8 sq_ori = dst->PhyInfo.SignalQuality;
419 long rssi_ori = dst->Rssi;
420
421 u8 ss_smp = src->PhyInfo.SignalStrength;
422 u8 sq_smp = src->PhyInfo.SignalQuality;
423 long rssi_smp = src->Rssi;
424
425 u8 ss_final;
426 u8 sq_final;
427 long rssi_final;
428
429 DBG_8723A("%s %s(%pM, ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n",
430 __func__, src->Ssid.ssid, src->MacAddress,
431 src->Configuration.DSConfig, ss_ori, sq_ori, rssi_ori,
432 ss_smp, sq_smp, rssi_smp
433 );
434
435 /* The rule below is 1/5 for sample value, 4/5 for history value */
436 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network23a(&padapter->mlmepriv.cur_network.network, src)) {
437 /* Take the recvpriv's value for the connected AP*/
438 ss_final = padapter->recvpriv.signal_strength;
439 sq_final = padapter->recvpriv.signal_qual;
440 /* the rssi value here is undecorated, and will be used for antenna diversity */
441 if (sq_smp != 101) /* from the right channel */
442 rssi_final = (src->Rssi+dst->Rssi*4)/5;
443 else
444 rssi_final = rssi_ori;
445 }
446 else {
447 if (sq_smp != 101) { /* from the right channel */
448 ss_final = ((u32)(src->PhyInfo.SignalStrength)+(u32)(dst->PhyInfo.SignalStrength)*4)/5;
449 sq_final = ((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5;
450 rssi_final = (src->Rssi+dst->Rssi*4)/5;
451 } else {
452 /* bss info not receving from the right channel, use the original RX signal infos */
453 ss_final = dst->PhyInfo.SignalStrength;
454 sq_final = dst->PhyInfo.SignalQuality;
455 rssi_final = dst->Rssi;
456 }
457
458 }
459
460 if (update_ie)
461 memcpy((u8 *)dst, (u8 *)src, get_wlan_bssid_ex_sz(src));
462
463 dst->PhyInfo.SignalStrength = ss_final;
464 dst->PhyInfo.SignalQuality = sq_final;
465 dst->Rssi = rssi_final;
466
467 DBG_8723A("%s %s(%pM), SignalStrength:%u, SignalQuality:%u, RawRSSI:%ld\n",
468 __func__, dst->Ssid.ssid, dst->MacAddress,
469 dst->PhyInfo.SignalStrength,
470 dst->PhyInfo.SignalQuality, dst->Rssi);
471
472}
473
474static void update_current_network(struct rtw_adapter *adapter, struct wlan_bssid_ex *pnetwork)
475{
476 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
477
478 if ((check_fwstate(pmlmepriv, _FW_LINKED)== true) && (is_same_network23a(&pmlmepriv->cur_network.network, pnetwork)))
479 {
480 /* RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,"Same Network\n"); */
481
482 /* if(pmlmepriv->cur_network.network.IELength<= pnetwork->IELength) */
483 {
484 update_network23a(&pmlmepriv->cur_network.network, pnetwork,adapter, true);
485 rtw_update_protection23a(adapter, (pmlmepriv->cur_network.network.IEs) + sizeof (struct ndis_802_11_fixed_ies),
486 pmlmepriv->cur_network.network.IELength);
487 }
488 }
489
490}
491
492/*
493
494Caller must hold pmlmepriv->lock first.
495
496*/
497void rtw_update_scanned_network23a(struct rtw_adapter *adapter, struct wlan_bssid_ex *target)
498{
499 struct list_head *plist, *phead;
500 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
501 struct wlan_network *pnetwork = NULL;
502 struct wlan_network *oldest = NULL;
503 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
504 u32 bssid_ex_sz;
505 int found = 0;
506
507 spin_lock_bh(&queue->lock);
508 phead = get_list_head(queue);
509
510 list_for_each(plist, phead) {
511 pnetwork = container_of(plist, struct wlan_network, list);
512
513 if (is_same_network23a(&pnetwork->network, target)) {
514 found = 1;
515 break;
516 }
517 if (!oldest || time_after(oldest->last_scanned,
518 pnetwork->last_scanned))
519 oldest = pnetwork;
520 }
521
522 /* If we didn't find a match, then get a new network slot to initialize
523 * with this beacon's information */
524 if (!found) {
525 pnetwork = rtw_alloc_network(pmlmepriv);
526 if (!pnetwork) {
527 if (!oldest) {
528 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
529 ("\n\n\nsomething wrong here\n\n\n"));
530 goto exit;
531 }
532 pnetwork = oldest;
533 } else
534 list_add_tail(&pnetwork->list, &queue->queue);
535
536 bssid_ex_sz = get_wlan_bssid_ex_sz(target);
537 target->Length = bssid_ex_sz;
538 memcpy(&pnetwork->network, target, bssid_ex_sz);
539
540 /* variable initialize */
541 pnetwork->fixed = false;
542 pnetwork->last_scanned = jiffies;
543
544 pnetwork->network_type = 0;
545 pnetwork->aid = 0;
546 pnetwork->join_res = 0;
547
548 /* bss info not receving from the right channel */
549 if (pnetwork->network.PhyInfo.SignalQuality == 101)
550 pnetwork->network.PhyInfo.SignalQuality = 0;
551 } else {
552 /*
553 * we have an entry and we are going to update it. But
554 * this entry may be already expired. In this case we
555 * do the same as we found a new net and call the
556 * new_net handler
557 */
558 bool update_ie = true;
559
560 pnetwork->last_scanned = jiffies;
561
562 /* target.reserved == 1, means that scanned network is
563 * a bcn frame. */
564 if ((pnetwork->network.IELength>target->IELength) &&
565 (target->reserved == 1))
566 update_ie = false;
567
568 update_network23a(&pnetwork->network, target,adapter, update_ie);
569 }
570
571exit:
572 spin_unlock_bh(&queue->lock);
573
574}
575
576void rtw_add_network(struct rtw_adapter *adapter, struct wlan_bssid_ex *pnetwork)
577{
578 update_current_network(adapter, pnetwork);
579 rtw_update_scanned_network23a(adapter, pnetwork);
580}
581
582/* select the desired network based on the capability of the (i)bss. */
583/* check items: (1) security */
584/* (2) network_type */
585/* (3) WMM */
586/* (4) HT */
587/* (5) others */
588int rtw_is_desired_network(struct rtw_adapter *adapter, struct wlan_network *pnetwork)
589{
590 struct security_priv *psecuritypriv = &adapter->securitypriv;
591 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
592 u32 desired_encmode;
593 u32 privacy;
594
595 /* u8 wps_ie[512]; */
596 uint wps_ielen;
597
598 int bselected = true;
599
600 desired_encmode = psecuritypriv->ndisencryptstatus;
601 privacy = pnetwork->network.Privacy;
602
603 if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS))
604 {
605 if (rtw_get_wps_ie23a(pnetwork->network.IEs+_FIXED_IE_LENGTH_, pnetwork->network.IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen)!= NULL)
606 {
607 return true;
608 }
609 else
610 {
611 return false;
612 }
613 }
614 if (adapter->registrypriv.wifi_spec == 1) /* for correct flow of 8021X to do.... */
615 {
616 if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0))
617 bselected = false;
618 }
619
620 if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0)) {
621 DBG_8723A("desired_encmode: %d, privacy: %d\n", desired_encmode, privacy);
622 bselected = false;
623 }
624
625 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)
626 {
627 if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
628 bselected = false;
629 }
630
631 return bselected;
632}
633
634/* TODO: Perry : For Power Management */
635void rtw_atimdone_event_callback23a(struct rtw_adapter *adapter , u8 *pbuf)
636{
637
638 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("receive atimdone_evet\n"));
639
640 return;
641}
642
643void rtw_survey_event_cb23a(struct rtw_adapter *adapter, u8 *pbuf)
644{
645 u32 len;
646 struct wlan_bssid_ex *pnetwork;
647 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
648
649 pnetwork = (struct wlan_bssid_ex *)pbuf;
650
651 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_survey_event_cb23a, ssid=%s\n", pnetwork->Ssid.ssid));
652
653 len = get_wlan_bssid_ex_sz(pnetwork);
654 if(len > (sizeof(struct wlan_bssid_ex)))
655 {
656 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n ****rtw_survey_event_cb23a: return a wrong bss ***\n"));
657 return;
658 }
659
660 spin_lock_bh(&pmlmepriv->lock);
661
662 /* update IBSS_network 's timestamp */
663 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true)
664 {
665 /* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,"rtw_survey_event_cb23a : WIFI_ADHOC_MASTER_STATE\n\n"); */
666 if (ether_addr_equal(pmlmepriv->cur_network.network.MacAddress,
667 pnetwork->MacAddress)) {
668 struct wlan_network* ibss_wlan = NULL;
669
670 memcpy(pmlmepriv->cur_network.network.IEs, pnetwork->IEs, 8);
671 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
672 ibss_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->MacAddress);
673 if (ibss_wlan)
674 {
675 memcpy(ibss_wlan->network.IEs , pnetwork->IEs, 8);
676 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
677 goto exit;
678 }
679 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
680 }
681 }
682
683 /* lock pmlmepriv->lock when you accessing network_q */
684 if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == false)
685 {
686 if (pnetwork->Ssid.ssid[0] == 0)
687 pnetwork->Ssid.ssid_len = 0;
688
689 rtw_add_network(adapter, pnetwork);
690 }
691
692exit:
693
694 spin_unlock_bh(&pmlmepriv->lock);
695
696 return;
697}
698
699void rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
700{
701 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
702 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
703
704 spin_lock_bh(&pmlmepriv->lock);
705
706 if (pmlmepriv->wps_probe_req_ie) {
707 pmlmepriv->wps_probe_req_ie_len = 0;
708 kfree(pmlmepriv->wps_probe_req_ie);
709 pmlmepriv->wps_probe_req_ie = NULL;
710 }
711
712 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_surveydone_event_callback23a: fw_state:%x\n\n", get_fwstate(pmlmepriv)));
713
714 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
715 del_timer_sync(&pmlmepriv->scan_to_timer);
716
717 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
718 } else {
719
720 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("nic status =%x, survey done event comes too late!\n", get_fwstate(pmlmepriv)));
721 }
722
723 rtw_set_signal_stat_timer(&adapter->recvpriv);
724
725 if (pmlmepriv->to_join == true) {
726 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
727 if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
728 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
729
730 if (rtw_select_and_join_from_scanned_queue23a(pmlmepriv) == _SUCCESS) {
731 mod_timer(&pmlmepriv->assoc_timer,
732 jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
733 } else {
734 struct wlan_bssid_ex *pdev_network = &adapter->registrypriv.dev_network;
735 u8 *pibss = adapter->registrypriv.dev_network.MacAddress;
736
737 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
738
739 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("switching to adhoc master\n"));
740
741 memset(&pdev_network->Ssid, 0, sizeof(struct cfg80211_ssid));
742 memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct cfg80211_ssid));
743
744 rtw_update_registrypriv_dev_network23a(adapter);
745 rtw_generate_random_ibss23a(pibss);
746
747 pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
748
749 if (rtw_createbss_cmd23a(adapter)!= _SUCCESS)
750 {
751 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error =>rtw_createbss_cmd23a status FAIL\n"));
752 }
753
754 pmlmepriv->to_join = false;
755 }
756 }
757 } else {
758 int ret;
759 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
760 pmlmepriv->to_join = false;
761 ret = rtw_select_and_join_from_scanned_queue23a(pmlmepriv);
762 if (ret == _SUCCESS) {
763 unsigned long e;
764 e = msecs_to_jiffies(MAX_JOIN_TIMEOUT);
765 mod_timer(&pmlmepriv->assoc_timer, jiffies + e);
766 } else if (ret == 2)/* there is no need to wait for join */
767 {
768 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
769 rtw_indicate_connect23a(adapter);
770 } else {
771 DBG_8723A("try_to_join, but select scanning queue fail, to_roaming:%d\n", rtw_to_roaming(adapter));
772 if (rtw_to_roaming(adapter) != 0) {
773 if (--pmlmepriv->to_roaming == 0
774 || _SUCCESS != rtw_sitesurvey_cmd23a(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)
775 ) {
776 rtw_set_roaming(adapter, 0);
777 rtw_free_assoc_resources23a(adapter, 1);
778 rtw_indicate_disconnect23a(adapter);
779 } else {
780 pmlmepriv->to_join = true;
781 }
782 }
783 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
784 }
785 }
786 }
787
788 spin_unlock_bh(&pmlmepriv->lock);
789
790#ifdef CONFIG_8723AU_P2P
791 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
792 p2p_ps_wk_cmd23a(adapter, P2P_PS_SCAN_DONE, 0);
793#endif /* CONFIG_8723AU_P2P */
794
795 rtw_os_xmit_schedule23a(adapter);
796
797 if(pmlmeext->sitesurvey_res.bss_cnt == 0)
798 rtw_hal_sreset_reset23a(adapter);
799
800 rtw_cfg80211_surveydone_event_callback(adapter);
801
802}
803
804void rtw_dummy_event_callback23a(struct rtw_adapter *adapter , u8 *pbuf)
805{
806}
807
808void rtw23a_fwdbg_event_callback(struct rtw_adapter *adapter , u8 *pbuf)
809{
810}
811
812static void free_scanqueue(struct mlme_priv *pmlmepriv)
813{
814 struct wlan_network *pnetwork;
815 struct rtw_queue *scan_queue = &pmlmepriv->scanned_queue;
816 struct list_head *plist, *phead, *ptemp;
817
818 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+free_scanqueue\n"));
819 spin_lock_bh(&scan_queue->lock);
820
821 phead = get_list_head(scan_queue);
822
823 list_for_each_safe(plist, ptemp, phead) {
824 list_del_init(plist);
825 pnetwork = container_of(plist, struct wlan_network, list);
826 kfree(pnetwork);
827 }
828
829 spin_unlock_bh(&scan_queue->lock);
830
831}
832
833/*
834*rtw_free_assoc_resources23a: the caller has to lock pmlmepriv->lock
835*/
836void rtw_free_assoc_resources23a(struct rtw_adapter *adapter, int lock_scanned_queue)
837{
838 struct wlan_network* pwlan = NULL;
839 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
840 struct sta_priv *pstapriv = &adapter->stapriv;
841 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
842
843 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_free_assoc_resources23a\n"));
844 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("tgt_network->network.MacAddress="MAC_FMT" ssid=%s\n",
845 MAC_ARG(tgt_network->network.MacAddress), tgt_network->network.Ssid.ssid));
846
847 if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE))
848 {
849 struct sta_info* psta;
850
851 psta = rtw_get_stainfo23a(&adapter->stapriv, tgt_network->network.MacAddress);
852
853 {
854 spin_lock_bh(&pstapriv->sta_hash_lock);
855 rtw_free_stainfo23a(adapter, psta);
856 }
857
858 spin_unlock_bh(&pstapriv->sta_hash_lock);
859
860 }
861
862 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE))
863 {
864 struct sta_info* psta;
865
866 rtw_free_all_stainfo23a(adapter);
867
868 psta = rtw_get_bcmc_stainfo23a(adapter);
869 spin_lock_bh(&pstapriv->sta_hash_lock);
870 rtw_free_stainfo23a(adapter, psta);
871 spin_unlock_bh(&pstapriv->sta_hash_lock);
872
873 rtw_init_bcmc_stainfo23a(adapter);
874 }
875
876 if(lock_scanned_queue)
877 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
878
879 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
880 if(pwlan)
881 pwlan->fixed = false;
882 else
883 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("rtw_free_assoc_resources23a : pwlan== NULL\n\n"));
884
885 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count == 1))
886 rtw_free_network_nolock(pmlmepriv, pwlan);
887
888 if(lock_scanned_queue)
889 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
890
891 pmlmepriv->key_mask = 0;
892
893}
894
895/*
896*rtw_indicate_connect23a: the caller has to lock pmlmepriv->lock
897*/
898void rtw_indicate_connect23a(struct rtw_adapter *padapter)
899{
900 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
901
902 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_connect23a\n"));
903
904 pmlmepriv->to_join = false;
905
906 if(!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
907 set_fwstate(pmlmepriv, _FW_LINKED);
908
909 rtw_led_control(padapter, LED_CTL_LINK);
910
911 rtw_os_indicate_connect23a(padapter);
912 }
913
914 rtw_set_roaming(padapter, 0);
915
916 rtw_set_scan_deny(padapter, 3000);
917
918 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("-rtw_indicate_connect23a: fw_state=0x%08x\n", get_fwstate(pmlmepriv)));
919
920}
921
922/*
923*rtw_indicate_disconnect23a: the caller has to lock pmlmepriv->lock
924*/
925void rtw_indicate_disconnect23a(struct rtw_adapter *padapter)
926{
927 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
928
929 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_disconnect23a\n"));
930
931 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS);
932
933 /* DBG_8723A("clear wps when %s\n", __func__); */
934
935 if (rtw_to_roaming(padapter) > 0)
936 _clr_fwstate_(pmlmepriv, _FW_LINKED);
937
938 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) ||
939 (rtw_to_roaming(padapter) <= 0)) {
940 rtw_os_indicate_disconnect23a(padapter);
941
942 /* set ips_deny_time to avoid enter IPS before LPS leave */
943 padapter->pwrctrlpriv.ips_deny_time =
944 jiffies + msecs_to_jiffies(3000);
945
946 _clr_fwstate_(pmlmepriv, _FW_LINKED);
947
948 rtw_led_control(padapter, LED_CTL_NO_LINK);
949
950 rtw_clear_scan_deny(padapter);
951
952 }
953
954#ifdef CONFIG_8723AU_P2P
955 p2p_ps_wk_cmd23a(padapter, P2P_PS_DISABLE, 1);
956#endif /* CONFIG_8723AU_P2P */
957
958 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_DISCONNECT, 1);
959
960}
961
962inline void rtw_indicate_scan_done23a(struct rtw_adapter *padapter, bool aborted)
963{
964 rtw_os_indicate_scan_done23a(padapter, aborted);
965}
966
967void rtw_scan_abort23a(struct rtw_adapter *adapter)
968{
969 unsigned long start;
970 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
971 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
972
973 start = jiffies;
974 pmlmeext->scan_abort = true;
975 while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) &&
976 jiffies_to_msecs(jiffies - start) <= 200) {
977
978 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
979 break;
980
981 DBG_8723A(FUNC_NDEV_FMT"fw_state = _FW_UNDER_SURVEY!\n", FUNC_NDEV_ARG(adapter->pnetdev));
982 msleep(20);
983 }
984
985 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
986 if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved)
987 DBG_8723A(FUNC_NDEV_FMT"waiting for scan_abort time out!\n", FUNC_NDEV_ARG(adapter->pnetdev));
988 rtw_indicate_scan_done23a(adapter, true);
989 }
990 pmlmeext->scan_abort = false;
991}
992
993static struct sta_info *rtw_joinbss_update_stainfo(struct rtw_adapter *padapter, struct wlan_network *pnetwork)
994{
995 int i;
996 struct sta_info *bmc_sta, *psta = NULL;
997 struct recv_reorder_ctrl *preorder_ctrl;
998 struct sta_priv *pstapriv = &padapter->stapriv;
999
1000 psta = rtw_get_stainfo23a(pstapriv, pnetwork->network.MacAddress);
1001 if (psta == NULL) {
1002 psta = rtw_alloc_stainfo23a(pstapriv, pnetwork->network.MacAddress);
1003 }
1004
1005 if (psta) /* update ptarget_sta */
1006 {
1007 DBG_8723A("%s\n", __func__);
1008
1009 psta->aid = pnetwork->join_res;
1010 psta->mac_id = 0;
1011
1012 /* sta mode */
1013 rtw_hal_set_odm_var23a(padapter, HAL_ODM_STA_INFO, psta, true);
1014
1015 /* security related */
1016 if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1017 {
1018 padapter->securitypriv.binstallGrpkey = false;
1019 padapter->securitypriv.busetkipkey = false;
1020 padapter->securitypriv.bgrpkey_handshake = false;
1021
1022 psta->ieee8021x_blocked = true;
1023 psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
1024
1025 memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof (union Keytype));
1026
1027 memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof (union Keytype));
1028 memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof (union Keytype));
1029
1030 memset((u8 *)&psta->dot11txpn, 0, sizeof (union pn48));
1031 memset((u8 *)&psta->dot11rxpn, 0, sizeof (union pn48));
1032 }
1033
1034 /* Commented by Albert 2012/07/21 */
1035 /* When doing the WPS, the wps_ie_len won't equal to 0 */
1036 /* And the Wi-Fi driver shouldn't allow the data packet to be tramsmitted. */
1037 if (padapter->securitypriv.wps_ie_len != 0)
1038 {
1039 psta->ieee8021x_blocked = true;
1040 padapter->securitypriv.wps_ie_len = 0;
1041 }
1042
1043 /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info */
1044 /* if A-MPDU Rx is enabled, reseting rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
1045 /* todo: check if AP can send A-MPDU packets */
1046 for (i = 0; i < 16 ; i++)
1047 {
1048 /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
1049 preorder_ctrl = &psta->recvreorder_ctrl[i];
1050 preorder_ctrl->enable = false;
1051 preorder_ctrl->indicate_seq = 0xffff;
1052 preorder_ctrl->wend_b = 0xffff;
1053 preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
1054 }
1055
1056 bmc_sta = rtw_get_bcmc_stainfo23a(padapter);
1057 if (bmc_sta)
1058 {
1059 for (i = 0; i < 16 ; i++)
1060 {
1061 /* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
1062 preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
1063 preorder_ctrl->enable = false;
1064 preorder_ctrl->indicate_seq = 0xffff;
1065 preorder_ctrl->wend_b = 0xffff;
1066 preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
1067 }
1068 }
1069
1070 /* misc. */
1071 update_sta_info23a(padapter, psta);
1072
1073 }
1074
1075 return psta;
1076}
1077
1078/* pnetwork : returns from rtw23a_joinbss_event_cb */
1079/* ptarget_wlan: found from scanned_queue */
1080static void rtw_joinbss_update_network23a(struct rtw_adapter *padapter, struct wlan_network *ptarget_wlan, struct wlan_network *pnetwork)
1081{
1082 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1083 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1084
1085 DBG_8723A("%s\n", __func__);
1086
1087 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\nfw_state:%x, BSSID:"MAC_FMT"\n"
1088 , get_fwstate(pmlmepriv), MAC_ARG(pnetwork->network.MacAddress)));
1089
1090 /* why not use ptarget_wlan?? */
1091 memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length);
1092 /* some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */
1093 cur_network->network.IELength = ptarget_wlan->network.IELength;
1094 memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0], MAX_IE_SZ);
1095
1096 cur_network->aid = pnetwork->join_res;
1097
1098 rtw_set_signal_stat_timer(&padapter->recvpriv);
1099 padapter->recvpriv.signal_strength = ptarget_wlan->network.PhyInfo.SignalStrength;
1100 padapter->recvpriv.signal_qual = ptarget_wlan->network.PhyInfo.SignalQuality;
1101 /* the ptarget_wlan->network.Rssi is raw data, we use ptarget_wlan->network.PhyInfo.SignalStrength instead (has scaled) */
1102 padapter->recvpriv.rssi = translate_percentage_to_dbm(ptarget_wlan->network.PhyInfo.SignalStrength);
1103 DBG_8723A("%s signal_strength:%3u, rssi:%3d, signal_qual:%3u\n",
1104 __func__, padapter->recvpriv.signal_strength,
1105 padapter->recvpriv.rssi, padapter->recvpriv.signal_qual);
1106 rtw_set_signal_stat_timer(&padapter->recvpriv);
1107
1108 /* update fw_state will clr _FW_UNDER_LINKING here indirectly */
1109 switch (pnetwork->network.InfrastructureMode) {
1110 case Ndis802_11Infrastructure:
1111 if (pmlmepriv->fw_state&WIFI_UNDER_WPS)
1112 pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS;
1113 else
1114 pmlmepriv->fw_state = WIFI_STATION_STATE;
1115 break;
1116 case Ndis802_11IBSS:
1117 pmlmepriv->fw_state = WIFI_ADHOC_STATE;
1118 break;
1119 default:
1120 pmlmepriv->fw_state = WIFI_NULL_STATE;
1121 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Invalid network_mode\n"));
1122 break;
1123 }
1124
1125 rtw_update_protection23a(padapter, (cur_network->network.IEs) + sizeof (struct ndis_802_11_fixed_ies),
1126 (cur_network->network.IELength));
1127
1128 rtw_update_ht_cap23a(padapter, cur_network->network.IEs, cur_network->network.IELength);
1129}
1130
1131/* Notes: the fucntion could be > passive_level (the same context as Rx tasklet) */
1132/* pnetwork : returns from rtw23a_joinbss_event_cb */
1133/* ptarget_wlan: found from scanned_queue */
1134/* if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if "ptarget_sta" & "ptarget_wlan" exist. */
1135/* if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check if "ptarget_wlan" exist. */
1136/* if join_res > 0, update "cur_network->network" from "pnetwork->network" if (ptarget_wlan !=NULL). */
1137
1138void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf)
1139{
1140 static u8 retry=0;
1141 struct sta_info *ptarget_sta= NULL, *pcur_sta = NULL;
1142 struct sta_priv *pstapriv = &adapter->stapriv;
1143 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1144 struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
1145 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1146 struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL;
1147 unsigned int the_same_macaddr = false;
1148
1149 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("joinbss event call back received with res=%d\n", pnetwork->join_res));
1150
1151 rtw_get_encrypt_decrypt_from_registrypriv23a(adapter);
1152
1153 if (pmlmepriv->assoc_ssid.ssid_len == 0) {
1154 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("@@@@@ joinbss event call back for Any SSid\n"));
1155 } else {
1156 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
1157 ("@@@@@ rtw23a_joinbss_event_cb for SSid:%s\n",
1158 pmlmepriv->assoc_ssid.ssid));
1159 }
1160
1161 if (ether_addr_equal(pnetwork->network.MacAddress,
1162 cur_network->network.MacAddress))
1163 the_same_macaddr = true;
1164 else
1165 the_same_macaddr = false;
1166
1167 pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network);
1168 if(pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
1169 {
1170 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n\n ***joinbss_evt_callback return a wrong bss ***\n\n"));
1171 return;
1172 }
1173
1174 spin_lock_bh(&pmlmepriv->lock);
1175
1176 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n rtw23a_joinbss_event_cb !! _enter_critical\n"));
1177
1178 if(pnetwork->join_res > 0)
1179 {
1180 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1181 retry = 0;
1182 if (check_fwstate(pmlmepriv,_FW_UNDER_LINKING))
1183 {
1184 /* s1. find ptarget_wlan */
1185 if(check_fwstate(pmlmepriv, _FW_LINKED))
1186 {
1187 if(the_same_macaddr == true)
1188 {
1189 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1190 }
1191 else
1192 {
1193 pcur_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1194 if(pcur_wlan) pcur_wlan->fixed = false;
1195
1196 pcur_sta = rtw_get_stainfo23a(pstapriv, cur_network->network.MacAddress);
1197 if(pcur_sta) {
1198 spin_lock_bh(&pstapriv->sta_hash_lock);
1199 rtw_free_stainfo23a(adapter, pcur_sta);
1200 spin_unlock_bh(&pstapriv->sta_hash_lock);
1201 }
1202
1203 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
1204 if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1205 if(ptarget_wlan) ptarget_wlan->fixed = true;
1206 }
1207 }
1208
1209 }
1210 else
1211 {
1212 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
1213 if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1214 if(ptarget_wlan) ptarget_wlan->fixed = true;
1215 }
1216 }
1217
1218 /* s2. update cur_network */
1219 if(ptarget_wlan)
1220 {
1221 rtw_joinbss_update_network23a(adapter, ptarget_wlan, pnetwork);
1222 }
1223 else
1224 {
1225 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't find ptarget_wlan when joinbss_event callback\n"));
1226 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1227 goto ignore_joinbss_callback;
1228 }
1229
1230 /* s3. find ptarget_sta & update ptarget_sta after update cur_network only for station mode */
1231 if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
1232 {
1233 ptarget_sta = rtw_joinbss_update_stainfo(adapter, pnetwork);
1234 if(ptarget_sta==NULL)
1235 {
1236 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't update stainfo when joinbss_event callback\n"));
1237 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1238 goto ignore_joinbss_callback;
1239 }
1240 }
1241
1242 /* s4. indicate connect */
1243 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
1244 {
1245 rtw_indicate_connect23a(adapter);
1246 } else {
1247 /* adhoc mode will rtw_indicate_connect23a when rtw_stassoc_event_callback23a */
1248 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("adhoc mode, fw_state:%x", get_fwstate(pmlmepriv)));
1249 }
1250
1251 /* s5. Cancle assoc_timer */
1252 del_timer_sync(&pmlmepriv->assoc_timer);
1253
1254 RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("Cancle assoc_timer\n"));
1255 } else {
1256 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1257 ("rtw23a_joinbss_event_cb err: fw_state:%x",
1258 get_fwstate(pmlmepriv)));
1259 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1260 goto ignore_joinbss_callback;
1261 }
1262 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1263 } else if(pnetwork->join_res == -4) {
1264 rtw_reset_securitypriv23a(adapter);
1265 mod_timer(&pmlmepriv->assoc_timer,
1266 jiffies + msecs_to_jiffies(1));
1267
1268 /* rtw_free_assoc_resources23a(adapter, 1); */
1269
1270 if((check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) {
1271 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1272 ("fail! clear _FW_UNDER_LINKING ^^^fw_state=%x\n",
1273 get_fwstate(pmlmepriv)));
1274 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1275 }
1276
1277 } else {
1278 /* if join_res < 0 (join fails), then try again */
1279 mod_timer(&pmlmepriv->assoc_timer,
1280 jiffies + msecs_to_jiffies(1));
1281 _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1282 }
1283
1284ignore_joinbss_callback:
1285
1286 spin_unlock_bh(&pmlmepriv->lock);
1287}
1288
1289void rtw23a_joinbss_event_cb(struct rtw_adapter *adapter, u8 *pbuf)
1290{
1291 struct wlan_network *pnetwork = (struct wlan_network *)pbuf;
1292
1293 mlmeext_joinbss_event_callback23a(adapter, pnetwork->join_res);
1294
1295 rtw_os_xmit_schedule23a(adapter);
1296
1297}
1298
1299/* FOR AP , AD-HOC mode */
1300void rtw_stassoc_hw_rpt23a(struct rtw_adapter *adapter, struct sta_info *psta)
1301{
1302 u16 media_status;
1303
1304 if (psta == NULL) return;
1305
1306 media_status = (psta->mac_id<<8)|1; /* MACID|OPMODE:1 connect */
1307 rtw_hal_set_hwreg23a(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
1308}
1309
1310void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
1311{
1312 struct sta_info *psta;
1313 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1314 struct stassoc_event *pstassoc = (struct stassoc_event*)pbuf;
1315 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1316 struct wlan_network *ptarget_wlan = NULL;
1317
1318 if(rtw_access_ctrl23a(adapter, pstassoc->macaddr) == false)
1319 return;
1320
1321#ifdef CONFIG_8723AU_AP_MODE
1322 if(check_fwstate(pmlmepriv, WIFI_AP_STATE))
1323 {
1324 psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1325 if (psta) {
1326 /* bss_cap_update_on_sta_join23a(adapter, psta); */
1327 /* sta_info_update23a(adapter, psta); */
1328 ap_sta_info_defer_update23a(adapter, psta);
1329
1330 rtw_stassoc_hw_rpt23a(adapter,psta);
1331 }
1332 return;
1333 }
1334#endif
1335 /* for AD-HOC mode */
1336 psta = rtw_get_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1337 if (psta != NULL) {
1338 /* the sta have been in sta_info_queue => do nothing */
1339 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Error: rtw_stassoc_event_callback23a: sta has been in sta_hash_queue\n"));
1340 return; /* between drv has received this event before and fw have not yet to set key to CAM_ENTRY) */
1341 }
1342
1343 psta = rtw_alloc_stainfo23a(&adapter->stapriv, pstassoc->macaddr);
1344 if (psta == NULL) {
1345 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't alloc sta_info when rtw_stassoc_event_callback23a\n"));
1346 return;
1347 }
1348
1349 /* to do : init sta_info variable */
1350 psta->qos_option = 0;
1351 psta->mac_id = (uint)pstassoc->cam_id;
1352 /* psta->aid = (uint)pstassoc->cam_id; */
1353 DBG_8723A("%s\n",__func__);
1354 /* for ad-hoc mode */
1355 rtw_hal_set_odm_var23a(adapter,HAL_ODM_STA_INFO,psta,true);
1356
1357 rtw_stassoc_hw_rpt23a(adapter,psta);
1358
1359 if(adapter->securitypriv.dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)
1360 psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm;
1361
1362 psta->ieee8021x_blocked = false;
1363
1364 spin_lock_bh(&pmlmepriv->lock);
1365
1366 if ( (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)==true ) ||
1367 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)==true ) )
1368 {
1369 if(adapter->stapriv.asoc_sta_count== 2)
1370 {
1371 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1372 ptarget_wlan = rtw_find_network23a(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1373 if(ptarget_wlan) ptarget_wlan->fixed = true;
1374 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1375 /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1376 rtw_indicate_connect23a(adapter);
1377 }
1378 }
1379
1380 spin_unlock_bh(&pmlmepriv->lock);
1381
1382 mlmeext_sta_add_event_callback23a(adapter, psta);
1383}
1384
1385void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf)
1386{
1387 int mac_id=-1;
1388 struct sta_info *psta;
1389 struct wlan_network* pwlan = NULL;
1390 struct wlan_bssid_ex *pdev_network=NULL;
1391 u8* pibss = NULL;
1392 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1393 struct stadel_event *pstadel = (struct stadel_event*)pbuf;
1394 struct sta_priv *pstapriv = &adapter->stapriv;
1395 struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1396
1397 psta = rtw_get_stainfo23a(&adapter->stapriv, pstadel->macaddr);
1398 if(psta)
1399 mac_id = psta->mac_id;
1400 else
1401 mac_id = pstadel->mac_id;
1402
1403 DBG_8723A("%s(mac_id=%d)=" MAC_FMT "\n", __func__, mac_id, MAC_ARG(pstadel->macaddr));
1404
1405 if(mac_id>=0) {
1406 u16 media_status;
1407 media_status = (mac_id<<8)|0; /* MACID|OPMODE:0 means disconnect */
1408 /* for STA,AP,ADHOC mode, report disconnect stauts to FW */
1409 rtw_hal_set_hwreg23a(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
1410 }
1411
1412 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
1413 {
1414 return;
1415 }
1416
1417 mlmeext_sta_del_event_callback23a(adapter);
1418
1419 spin_lock_bh(&pmlmepriv->lock);
1420
1421 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
1422 {
1423 if (rtw_to_roaming(adapter) > 0)
1424 pmlmepriv->to_roaming--; /* this stadel_event is caused by roaming, decrease to_roaming */
1425 else if (rtw_to_roaming(adapter) == 0)
1426 rtw_set_roaming(adapter, adapter->registrypriv.max_roaming_times);
1427 if (*((unsigned short *)(pstadel->rsvd)) != WLAN_REASON_EXPIRATION_CHK)
1428 rtw_set_roaming(adapter, 0); /* don't roam */
1429
1430 rtw_free_uc_swdec_pending_queue23a(adapter);
1431
1432 rtw_free_assoc_resources23a(adapter, 1);
1433 rtw_indicate_disconnect23a(adapter);
1434 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1435 /* remove the network entry in scanned_queue */
1436 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
1437 if (pwlan) {
1438 pwlan->fixed = false;
1439 rtw_free_network_nolock(pmlmepriv, pwlan);
1440 }
1441 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1442
1443 _rtw23a_roaming(adapter, tgt_network);
1444 }
1445
1446 if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1447 check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
1448 {
1449
1450 spin_lock_bh(&pstapriv->sta_hash_lock);
1451 rtw_free_stainfo23a(adapter, psta);
1452 spin_unlock_bh(&pstapriv->sta_hash_lock);
1453
1454 if (adapter->stapriv.asoc_sta_count == 1) /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1455 {
1456 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1457 /* free old ibss network */
1458 /* pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, pstadel->macaddr); */
1459 pwlan = rtw_find_network23a(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
1460 if (pwlan)
1461 {
1462 pwlan->fixed = false;
1463 rtw_free_network_nolock(pmlmepriv, pwlan);
1464 }
1465 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1466 /* re-create ibss */
1467 pdev_network = &adapter->registrypriv.dev_network;
1468 pibss = adapter->registrypriv.dev_network.MacAddress;
1469
1470 memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network));
1471
1472 memset(&pdev_network->Ssid, 0,
1473 sizeof(struct cfg80211_ssid));
1474 memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid,
1475 sizeof(struct cfg80211_ssid));
1476
1477 rtw_update_registrypriv_dev_network23a(adapter);
1478
1479 rtw_generate_random_ibss23a(pibss);
1480
1481 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
1482 {
1483 set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
1484 _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
1485 }
1486
1487 if (rtw_createbss_cmd23a(adapter)!= _SUCCESS)
1488 {
1489
1490 RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error =>stadel_event_callback: rtw_createbss_cmd23a status FAIL***\n "));
1491
1492 }
1493
1494 }
1495
1496 }
1497
1498 spin_unlock_bh(&pmlmepriv->lock);
1499
1500}
1501
1502void rtw_cpwm_event_callback23a(struct rtw_adapter *padapter, u8 *pbuf)
1503{
1504
1505 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("+rtw_cpwm_event_callback23a !!!\n"));
1506
1507}
1508
1509/*
1510* rtw23a_join_to_handler - Timeout/faliure handler for CMD JoinBss
1511* @adapter: pointer to _adapter structure
1512*/
1513void rtw23a_join_to_handler (unsigned long data)
1514{
1515 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1516 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1517 int do_join_r;
1518
1519 DBG_8723A("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv));
1520
1521 if(adapter->bDriverStopped ||adapter->bSurpriseRemoved)
1522 return;
1523
1524 spin_lock_bh(&pmlmepriv->lock);
1525
1526 if (rtw_to_roaming(adapter) > 0) { /* join timeout caused by roaming */
1527 while(1) {
1528 pmlmepriv->to_roaming--;
1529 if (rtw_to_roaming(adapter) != 0) { /* try another */
1530 DBG_8723A("%s try another roaming\n", __func__);
1531 if (_SUCCESS!= (do_join_r = rtw_do_join23a(adapter))) {
1532 DBG_8723A("%s roaming do_join return %d\n", __func__ , do_join_r);
1533 continue;
1534 }
1535 break;
1536 } else {
1537 DBG_8723A("%s We've try roaming but fail\n", __func__);
1538 rtw_indicate_disconnect23a(adapter);
1539 break;
1540 }
1541 }
1542 } else {
1543 rtw_indicate_disconnect23a(adapter);
1544 free_scanqueue(pmlmepriv);/* */
1545
1546 /* indicate disconnect for the case that join_timeout and check_fwstate != FW_LINKED */
1547 rtw_cfg80211_indicate_disconnect(adapter);
1548 }
1549
1550 spin_unlock_bh(&pmlmepriv->lock);
1551
1552}
1553
1554/*
1555* rtw_scan_timeout_handler23a - Timeout/Faliure handler for CMD SiteSurvey
1556* @data: pointer to _adapter structure
1557*/
1558void rtw_scan_timeout_handler23a(unsigned long data)
1559{
1560 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1561 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1562
1563 DBG_8723A(FUNC_ADPT_FMT" fw_state =%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
1564
1565 spin_lock_bh(&pmlmepriv->lock);
1566
1567 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1568
1569 spin_unlock_bh(&pmlmepriv->lock);
1570
1571 rtw_indicate_scan_done23a(adapter, true);
1572}
1573
1574static void rtw_auto_scan_handler(struct rtw_adapter *padapter)
1575{
1576 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1577
1578 /* auto site survey per 60sec */
1579 if (pmlmepriv->scan_interval > 0) {
1580 pmlmepriv->scan_interval--;
1581 if (pmlmepriv->scan_interval == 0) {
1582 DBG_8723A("%s\n", __func__);
1583 rtw_set_802_11_bssid23a_list_scan(padapter, NULL, 0);
1584 pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
1585 }
1586 }
1587}
1588
1589void rtw_dynamic_check_timer_handler(unsigned long data)
1590{
1591 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1592 struct registry_priv *pregistrypriv = &adapter->registrypriv;
1593
1594 if (adapter->hw_init_completed == false)
1595 goto out;
1596
1597 if ((adapter->bDriverStopped == true)||(adapter->bSurpriseRemoved == true))
1598 goto out;
1599
1600 if (adapter->net_closed == true)
1601 goto out;
1602
1603 rtw_dynamic_chk_wk_cmd23a(adapter);
1604
1605 if (pregistrypriv->wifi_spec == 1)
1606 {
1607#ifdef CONFIG_8723AU_P2P
1608 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
1609 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1610#endif
1611 {
1612 /* auto site survey */
1613 rtw_auto_scan_handler(adapter);
1614 }
1615 }
1616out:
1617 mod_timer(&adapter->mlmepriv.dynamic_chk_timer,
1618 jiffies + msecs_to_jiffies(2000));
1619}
1620
1621inline bool rtw_is_scan_deny(struct rtw_adapter *adapter)
1622{
1623 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1624 return (atomic_read(&mlmepriv->set_scan_deny) != 0) ? true : false;
1625}
1626
1627void rtw_clear_scan_deny(struct rtw_adapter *adapter)
1628{
1629 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1630 atomic_set(&mlmepriv->set_scan_deny, 0);
1631 if (0)
1632 DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
1633}
1634
1635void rtw_set_scan_deny_timer_hdl(unsigned long data)
1636{
1637 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
1638 rtw_clear_scan_deny(adapter);
1639}
1640
1641void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms)
1642{
1643 struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1644
1645 if (0)
1646 DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
1647 atomic_set(&mlmepriv->set_scan_deny, 1);
1648 mod_timer(&mlmepriv->set_scan_deny_timer,
1649 jiffies + msecs_to_jiffies(ms));
1650
1651}
1652
1653#if defined(IEEE80211_SCAN_RESULT_EXPIRE)
1654#define RTW_SCAN_RESULT_EXPIRE IEEE80211_SCAN_RESULT_EXPIRE/HZ*1000 -1000 /* 3000 -1000 */
1655#else
1656#define RTW_SCAN_RESULT_EXPIRE 2000
1657#endif
1658
1659/*
1660* Select a new join candidate from the original @param candidate and @param competitor
1661* @return true: candidate is updated
1662* @return false: candidate is not updated
1663*/
1664static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
1665 , struct wlan_network **candidate, struct wlan_network *competitor)
1666{
1667 int updated = false;
1668 struct rtw_adapter *adapter = container_of(pmlmepriv, struct rtw_adapter, mlmepriv);
1669
1670 /* check bssid, if needed */
1671 if (pmlmepriv->assoc_by_bssid == true) {
1672 if (!ether_addr_equal(competitor->network.MacAddress,
1673 pmlmepriv->assoc_bssid))
1674 goto exit;
1675 }
1676
1677 /* check ssid, if needed */
1678 if (pmlmepriv->assoc_ssid.ssid_len) {
1679 if (competitor->network.Ssid.ssid_len !=
1680 pmlmepriv->assoc_ssid.ssid_len ||
1681 memcmp(competitor->network.Ssid.ssid,
1682 pmlmepriv->assoc_ssid.ssid,
1683 pmlmepriv->assoc_ssid.ssid_len))
1684 goto exit;
1685 }
1686
1687 if (rtw_is_desired_network(adapter, competitor) == false)
1688 goto exit;
1689
1690 if (rtw_to_roaming(adapter) > 0) {
1691 unsigned int passed;
1692
1693 passed = jiffies_to_msecs(jiffies - competitor->last_scanned);
1694 if (passed >= RTW_SCAN_RESULT_EXPIRE ||
1695 is_same_ess(&competitor->network,
1696 &pmlmepriv->cur_network.network) == false)
1697 goto exit;
1698 }
1699
1700 if (*candidate == NULL ||(*candidate)->network.Rssi<competitor->network.Rssi) {
1701 *candidate = competitor;
1702 updated = true;
1703 }
1704
1705 if (updated) {
1706 DBG_8723A("[by_bssid:%u][assoc_ssid:%s][to_roaming:%u] new candidate: %s("MAC_FMT") rssi:%d\n",
1707 pmlmepriv->assoc_by_bssid,
1708 pmlmepriv->assoc_ssid.ssid,
1709 rtw_to_roaming(adapter),
1710 (*candidate)->network.Ssid.ssid,
1711 MAC_ARG((*candidate)->network.MacAddress),
1712 (int)(*candidate)->network.Rssi);
1713 }
1714
1715exit:
1716 return updated;
1717}
1718
1719/*
1720Calling context:
1721The caller of the sub-routine will be in critical section...
1722
1723The caller must hold the following spinlock
1724
1725pmlmepriv->lock
1726
1727*/
1728
1729int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv)
1730{
1731 int ret;
1732 struct list_head *phead, *plist, *ptmp;
1733 struct rtw_adapter *adapter;
1734 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1735 struct wlan_network *pnetwork = NULL;
1736 struct wlan_network *candidate = NULL;
1737
1738 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1739 phead = get_list_head(queue);
1740 adapter = pmlmepriv->nic_hdl;
1741
1742 list_for_each_safe(plist, ptmp, phead) {
1743 pnetwork = container_of(plist, struct wlan_network, list);
1744 if (!pnetwork) {
1745 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1746 ("%s return _FAIL:(pnetwork == NULL)\n",
1747 __func__));
1748 ret = _FAIL;
1749 goto exit;
1750 }
1751
1752 rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
1753 }
1754
1755 if (!candidate) {
1756 DBG_8723A("%s: return _FAIL(candidate == NULL)\n", __func__);
1757 ret = _FAIL;
1758 goto exit;
1759 } else {
1760 DBG_8723A("%s: candidate: %s("MAC_FMT", ch:%u)\n", __func__,
1761 candidate->network.Ssid.ssid,
1762 MAC_ARG(candidate->network.MacAddress),
1763 candidate->network.Configuration.DSConfig);
1764 }
1765
1766 /* check for situation of _FW_LINKED */
1767 if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
1768 DBG_8723A("%s: _FW_LINKED while ask_for_joinbss!!!\n",
1769 __func__);
1770
1771 rtw_disassoc_cmd23a(adapter, 0, true);
1772 rtw_indicate_disconnect23a(adapter);
1773 rtw_free_assoc_resources23a(adapter, 0);
1774 }
1775 set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
1776 ret = rtw_joinbss_cmd23a(adapter, candidate);
1777
1778exit:
1779 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1780
1781 return ret;
1782}
1783
1784int rtw_set_auth23a(struct rtw_adapter * adapter,
1785 struct security_priv *psecuritypriv)
1786{
1787 struct cmd_obj* pcmd;
1788 struct setauth_parm *psetauthparm;
1789 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1790 int res = _SUCCESS;
1791
1792 pcmd = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1793 if (!pcmd) {
1794 res = _FAIL; /* try again */
1795 goto exit;
1796 }
1797
1798 psetauthparm = (struct setauth_parm*)
1799 kzalloc(sizeof(struct setauth_parm), GFP_KERNEL);
1800 if (!psetauthparm) {
1801 kfree(pcmd);
1802 res = _FAIL;
1803 goto exit;
1804 }
1805
1806 psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm;
1807
1808 pcmd->cmdcode = _SetAuth_CMD_;
1809 pcmd->parmbuf = (unsigned char *)psetauthparm;
1810 pcmd->cmdsz = (sizeof(struct setauth_parm));
1811 pcmd->rsp = NULL;
1812 pcmd->rspsz = 0;
1813
1814 INIT_LIST_HEAD(&pcmd->list);
1815
1816 RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
1817 ("after enqueue set_auth_cmd, auth_mode=%x\n",
1818 psecuritypriv->dot11AuthAlgrthm));
1819
1820 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
1821
1822exit:
1823
1824 return res;
1825}
1826
1827int rtw_set_key23a(struct rtw_adapter *adapter,
1828 struct security_priv *psecuritypriv, int keyid, u8 set_tx)
1829{
1830 u8 keylen;
1831 struct cmd_obj *pcmd;
1832 struct setkey_parm *psetkeyparm;
1833 struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1834 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1835 int res = _SUCCESS;
1836
1837 pcmd = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1838 if (!pcmd) {
1839 res = _FAIL; /* try again */
1840 goto exit;
1841 }
1842 psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
1843 if (!psetkeyparm) {
1844 kfree(pcmd);
1845 res = _FAIL;
1846 goto exit;
1847 }
1848
1849 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
1850 psetkeyparm->algorithm = (unsigned char)
1851 psecuritypriv->dot118021XGrpPrivacy;
1852 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1853 ("\n rtw_set_key23a: psetkeyparm->algorithm = (unsigned "
1854 "char)psecuritypriv->dot118021XGrpPrivacy =%d\n",
1855 psetkeyparm->algorithm));
1856 } else {
1857 psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm;
1858 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1859 ("\n rtw_set_key23a: psetkeyparm->algorithm = (u8)"
1860 "psecuritypriv->dot11PrivacyAlgrthm =%d\n",
1861 psetkeyparm->algorithm));
1862 }
1863 psetkeyparm->keyid = (u8)keyid;/* 0~3 */
1864 psetkeyparm->set_tx = set_tx;
1865 if (is_wep_enc(psetkeyparm->algorithm))
1866 pmlmepriv->key_mask |= CHKBIT(psetkeyparm->keyid);
1867
1868 DBG_8723A("==> rtw_set_key23a algorithm(%x), keyid(%x), key_mask(%x)\n",
1869 psetkeyparm->algorithm, psetkeyparm->keyid,
1870 pmlmepriv->key_mask);
1871 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1872 ("\n rtw_set_key23a: psetkeyparm->algorithm =%d psetkeyparm->"
1873 "keyid = (u8)keyid =%d\n", psetkeyparm->algorithm, keyid));
1874
1875 switch (psetkeyparm->algorithm) {
1876 case _WEP40_:
1877 keylen = 5;
1878 memcpy(&psetkeyparm->key[0],
1879 &psecuritypriv->dot11DefKey[keyid].skey[0], keylen);
1880 break;
1881 case _WEP104_:
1882 keylen = 13;
1883 memcpy(&psetkeyparm->key[0],
1884 &psecuritypriv->dot11DefKey[keyid].skey[0], keylen);
1885 break;
1886 case _TKIP_:
1887 keylen = 16;
1888 memcpy(&psetkeyparm->key,
1889 &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1890 psetkeyparm->grpkey = 1;
1891 break;
1892 case _AES_:
1893 keylen = 16;
1894 memcpy(&psetkeyparm->key,
1895 &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1896 psetkeyparm->grpkey = 1;
1897 break;
1898 default:
1899 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1900 ("\n rtw_set_key23a:psecuritypriv->dot11PrivacyAlgrthm = "
1901 "%x (must be 1 or 2 or 4 or 5)\n",
1902 psecuritypriv->dot11PrivacyAlgrthm));
1903 res = _FAIL;
1904 kfree(pcmd);
1905 kfree(psetkeyparm);
1906 goto exit;
1907 }
1908
1909 pcmd->cmdcode = _SetKey_CMD_;
1910 pcmd->parmbuf = (u8 *)psetkeyparm;
1911 pcmd->cmdsz = (sizeof(struct setkey_parm));
1912 pcmd->rsp = NULL;
1913 pcmd->rspsz = 0;
1914
1915 INIT_LIST_HEAD(&pcmd->list);
1916
1917 /* sema_init(&pcmd->cmd_sem, 0); */
1918
1919 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
1920
1921exit:
1922
1923 return res;
1924}
1925
1926/* adjust IEs for rtw_joinbss_cmd23a in WMM */
1927int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie,
1928 u8 *out_ie, uint in_len, uint initial_out_len)
1929{
1930 unsigned int ielength = 0;
1931 unsigned int i, j;
1932
1933 i = 12; /* after the fixed IE */
1934 while(i < in_len) {
1935 ielength = initial_out_len;
1936
1937 /* WMM element ID and OUI */
1938 if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
1939 in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
1940 in_ie[i + 5] == 0x02 && i+5 < in_len) {
1941
1942 /* Append WMM IE to the last index of out_ie */
1943 for (j = i; j < i + 9; j++) {
1944 out_ie[ielength] = in_ie[j];
1945 ielength++;
1946 }
1947 out_ie[initial_out_len + 1] = 0x07;
1948 out_ie[initial_out_len + 6] = 0x00;
1949 out_ie[initial_out_len + 8] = 0x00;
1950
1951 break;
1952 }
1953
1954 i += (in_ie[i + 1] + 2); /* to the next IE element */
1955 }
1956
1957 return ielength;
1958}
1959
1960/* */
1961/* Ported from 8185: IsInPreAuthKeyList().
1962 (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.) */
1963/* Added by Annie, 2006-05-07. */
1964/* */
1965/* Search by BSSID, */
1966/* Return Value: */
1967/* -1 :if there is no pre-auth key in the table */
1968/* >= 0 :if there is pre-auth key, and return the entry id */
1969/* */
1970/* */
1971
1972static int SecIsInPMKIDList(struct rtw_adapter *Adapter, u8 *bssid)
1973{
1974 struct security_priv *psecuritypriv = &Adapter->securitypriv;
1975 int i = 0;
1976
1977 do {
1978 if (psecuritypriv->PMKIDList[i].bUsed &&
1979 ether_addr_equal(psecuritypriv->PMKIDList[i].Bssid, bssid)) {
1980 break;
1981 } else {
1982 i++;
1983 /* continue; */
1984 }
1985 } while(i < NUM_PMKID_CACHE);
1986
1987 if (i == NUM_PMKID_CACHE) {
1988 i = -1;/* Could not find. */
1989 } else {
1990 /* There is one Pre-Authentication Key for
1991 the specific BSSID. */
1992 }
1993
1994 return i;
1995}
1996
1997/* */
1998/* Check the RSN IE length */
1999/* If the RSN IE length <= 20, the RSN IE didn't include
2000 the PMKID information */
2001/* 0-11th element in the array are the fixed IE */
2002/* 12th element in the array is the IE */
2003/* 13th element in the array is the IE length */
2004/* */
2005
2006static int rtw_append_pmkid(struct rtw_adapter *Adapter, int iEntry,
2007 u8 *ie, uint ie_len)
2008{
2009 struct security_priv *psecuritypriv = &Adapter->securitypriv;
2010
2011 if (ie[13] <= 20) {
2012 /* The RSN IE didn't include the PMK ID,
2013 append the PMK information */
2014 ie[ie_len] = 1;
2015 ie_len++;
2016 ie[ie_len] = 0; /* PMKID count = 0x0100 */
2017 ie_len++;
2018 memcpy(&ie[ie_len],
2019 &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
2020
2021 ie_len += 16;
2022 ie[13] += 18;/* PMKID length = 2+16 */
2023 }
2024 return ie_len;
2025}
2026int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie,
2027 uint in_len)
2028{
2029 u8 authmode;
2030 uint ielength;
2031 int iEntry;
2032 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2033 struct security_priv *psecuritypriv = &adapter->securitypriv;
2034 uint ndisauthmode = psecuritypriv->ndisauthtype;
2035 uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
2036
2037 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2038 ("+rtw_restruct_sec_ie23a: ndisauthmode=%d ndissecuritytype=%d\n",
2039 ndisauthmode, ndissecuritytype));
2040
2041 /* copy fixed ie only */
2042 memcpy(out_ie, in_ie, 12);
2043 ielength = 12;
2044 if ((ndisauthmode==Ndis802_11AuthModeWPA) ||
2045 (ndisauthmode==Ndis802_11AuthModeWPAPSK))
2046 authmode=_WPA_IE_ID_;
2047 if ((ndisauthmode==Ndis802_11AuthModeWPA2) ||
2048 (ndisauthmode==Ndis802_11AuthModeWPA2PSK))
2049 authmode=_WPA2_IE_ID_;
2050
2051 if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
2052 memcpy(out_ie + ielength, psecuritypriv->wps_ie,
2053 psecuritypriv->wps_ie_len);
2054
2055 ielength += psecuritypriv->wps_ie_len;
2056 } else if ((authmode==_WPA_IE_ID_) || (authmode==_WPA2_IE_ID_)) {
2057 /* copy RSN or SSN */
2058 memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0],
2059 psecuritypriv->supplicant_ie[1] + 2);
2060 ielength += psecuritypriv->supplicant_ie[1] + 2;
2061 rtw_report_sec_ie23a(adapter, authmode,
2062 psecuritypriv->supplicant_ie);
2063 }
2064
2065 iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
2066 if (iEntry < 0) {
2067 return ielength;
2068 } else {
2069 if (authmode == _WPA2_IE_ID_) {
2070 ielength=rtw_append_pmkid(adapter, iEntry,
2071 out_ie, ielength);
2072 }
2073 }
2074
2075 return ielength;
2076}
2077
2078void rtw_init_registrypriv_dev_network23a(struct rtw_adapter* adapter)
2079{
2080 struct registry_priv* pregistrypriv = &adapter->registrypriv;
2081 struct eeprom_priv* peepriv = &adapter->eeprompriv;
2082 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2083 u8 *myhwaddr = myid(peepriv);
2084
2085 ether_addr_copy(pdev_network->MacAddress, myhwaddr);
2086
2087 memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
2088 sizeof(struct cfg80211_ssid));
2089
2090 pdev_network->Configuration.Length=sizeof(struct ndis_802_11_config);
2091 pdev_network->Configuration.BeaconPeriod = 100;
2092 pdev_network->Configuration.FHConfig.Length = 0;
2093 pdev_network->Configuration.FHConfig.HopPattern = 0;
2094 pdev_network->Configuration.FHConfig.HopSet = 0;
2095 pdev_network->Configuration.FHConfig.DwellTime = 0;
2096
2097}
2098
2099void rtw_update_registrypriv_dev_network23a(struct rtw_adapter* adapter)
2100{
2101 int sz = 0;
2102 struct registry_priv* pregistrypriv = &adapter->registrypriv;
2103 struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
2104 struct security_priv *psecuritypriv = &adapter->securitypriv;
2105 struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
2106 /* struct xmit_priv *pxmitpriv = &adapter->xmitpriv; */
2107
2108 pdev_network->Privacy =
2109 (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0);
2110
2111 pdev_network->Rssi = 0;
2112
2113 switch (pregistrypriv->wireless_mode)
2114 {
2115 case WIRELESS_11B:
2116 pdev_network->NetworkTypeInUse = Ndis802_11DS;
2117 break;
2118 case WIRELESS_11G:
2119 case WIRELESS_11BG:
2120 case WIRELESS_11_24N:
2121 case WIRELESS_11G_24N:
2122 case WIRELESS_11BG_24N:
2123 pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
2124 break;
2125 case WIRELESS_11A:
2126 case WIRELESS_11A_5N:
2127 pdev_network->NetworkTypeInUse = Ndis802_11OFDM5;
2128 break;
2129 case WIRELESS_11ABGN:
2130 if (pregistrypriv->channel > 14)
2131 pdev_network->NetworkTypeInUse = Ndis802_11OFDM5;
2132 else
2133 pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
2134 break;
2135 default :
2136 /* TODO */
2137 break;
2138 }
2139
2140 pdev_network->Configuration.DSConfig = pregistrypriv->channel;
2141 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
2142 ("pregistrypriv->channel =%d, pdev_network->Configuration."
2143 "DSConfig = 0x%x\n", pregistrypriv->channel,
2144 pdev_network->Configuration.DSConfig));
2145
2146 if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
2147 pdev_network->Configuration.ATIMWindow = 0;
2148
2149 pdev_network->InfrastructureMode =
2150 cur_network->network.InfrastructureMode;
2151
2152 /* 1. Supported rates */
2153 /* 2. IE */
2154
2155 sz = rtw_generate_ie23a(pregistrypriv);
2156
2157 pdev_network->IELength = sz;
2158
2159 pdev_network->Length =
2160 get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pdev_network);
2161
2162 /* notes: translate IELength & Length after assign the
2163 Length to cmdsz in createbss_cmd(); */
2164 /* pdev_network->IELength = cpu_to_le32(sz); */
2165
2166}
2167
2168void rtw_get_encrypt_decrypt_from_registrypriv23a(struct rtw_adapter* adapter)
2169{
2170
2171}
2172
2173/* the fucntion is at passive_level */
2174void rtw_joinbss_reset23a(struct rtw_adapter *padapter)
2175{
2176 u8 threshold;
2177 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2178 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2179
2180 /* todo: if you want to do something io/reg/hw setting
2181 before join_bss, please add code here */
2182
2183 pmlmepriv->num_FortyMHzIntolerant = 0;
2184
2185 pmlmepriv->num_sta_no_ht = 0;
2186
2187 phtpriv->ampdu_enable = false;/* reset to disabled */
2188
2189 /* TH = 1 => means that invalidate usb rx aggregation */
2190 /* TH = 0 => means that validate usb rx aggregation, use init value. */
2191 if (phtpriv->ht_option) {
2192 if (padapter->registrypriv.wifi_spec == 1)
2193 threshold = 1;
2194 else
2195 threshold = 0;
2196 rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH,
2197 (u8 *)(&threshold));
2198 } else {
2199 threshold = 1;
2200 rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH,
2201 (u8 *)(&threshold));
2202 }
2203}
2204
2205/* the fucntion is >= passive_level */
2206unsigned int rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie,
2207 u8 *out_ie, uint in_len, uint *pout_len)
2208{
2209 u32 ielen, out_len;
2210 int max_rx_ampdu_factor;
2211 unsigned char *p, *pframe;
2212 struct ieee80211_ht_cap ht_capie;
2213 unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
2214 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2215 struct qos_priv *pqospriv = &pmlmepriv->qospriv;
2216 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2217
2218 phtpriv->ht_option = false;
2219
2220 p = rtw_get_ie23a(in_ie + 12, _HT_CAPABILITY_IE_, &ielen, in_len - 12);
2221
2222 if (p && ielen > 0) {
2223 u32 rx_packet_offset, max_recvbuf_sz;
2224 if (pqospriv->qos_option == 0) {
2225 out_len = *pout_len;
2226 pframe = rtw_set_ie23a(out_ie + out_len,
2227 _VENDOR_SPECIFIC_IE_,
2228 _WMM_IE_Length_, WMM_IE, pout_len);
2229
2230 pqospriv->qos_option = 1;
2231 }
2232
2233 out_len = *pout_len;
2234
2235 memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
2236
2237 ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
2238 IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 |
2239 IEEE80211_HT_CAP_TX_STBC | IEEE80211_HT_CAP_DSSSCCK40;
2240
2241 rtw_hal_get_def_var23a(padapter, HAL_DEF_RX_PACKET_OFFSET,
2242 &rx_packet_offset);
2243 rtw_hal_get_def_var23a(padapter, HAL_DEF_MAX_RECVBUF_SZ,
2244 &max_recvbuf_sz);
2245
2246 rtw_hal_get_def_var23a(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
2247 &max_rx_ampdu_factor);
2248 ht_capie.ampdu_params_info = max_rx_ampdu_factor & 0x03;
2249
2250 if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
2251 ht_capie.ampdu_params_info |=
2252 (IEEE80211_HT_AMPDU_PARM_DENSITY& (0x07 << 2));
2253 else
2254 ht_capie.ampdu_params_info |=
2255 (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
2256
2257 pframe = rtw_set_ie23a(out_ie + out_len, _HT_CAPABILITY_IE_,
2258 sizeof(struct ieee80211_ht_cap),
2259 (unsigned char*)&ht_capie, pout_len);
2260
2261 phtpriv->ht_option = true;
2262
2263 p = rtw_get_ie23a(in_ie + 12, _HT_ADD_INFO_IE_, &ielen, in_len-12);
2264 if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
2265 out_len = *pout_len;
2266 pframe = rtw_set_ie23a(out_ie + out_len, _HT_ADD_INFO_IE_,
2267 ielen, p + 2 , pout_len);
2268 }
2269 }
2270
2271 return phtpriv->ht_option;
2272}
2273
2274/* the fucntion is > passive_level (in critical_section) */
2275void rtw_update_ht_cap23a(struct rtw_adapter *padapter, u8 *pie, uint ie_len)
2276{
2277 u8 *p, max_ampdu_sz;
2278 int len;
2279 /* struct sta_info *bmc_sta, *psta; */
2280 struct ieee80211_ht_cap *pht_capie;
2281 struct ieee80211_ht_addt_info *pht_addtinfo;
2282 /* struct recv_reorder_ctrl *preorder_ctrl; */
2283 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2284 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2285 /* struct recv_priv *precvpriv = &padapter->recvpriv; */
2286 struct registry_priv *pregistrypriv = &padapter->registrypriv;
2287 /* struct wlan_network *pcur_network = &pmlmepriv->cur_network;; */
2288 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2289 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2290
2291 if (!phtpriv->ht_option)
2292 return;
2293
2294 if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable))
2295 return;
2296
2297 DBG_8723A("+rtw_update_ht_cap23a()\n");
2298
2299 /* maybe needs check if ap supports rx ampdu. */
2300 if ((phtpriv->ampdu_enable == false) && (pregistrypriv->ampdu_enable == 1)) {
2301 if (pregistrypriv->wifi_spec == 1)
2302 phtpriv->ampdu_enable = false;
2303 else
2304 phtpriv->ampdu_enable = true;
2305 } else if (pregistrypriv->ampdu_enable == 2) {
2306 phtpriv->ampdu_enable = true;
2307 }
2308
2309 /* check Max Rx A-MPDU Size */
2310 len = 0;
2311 p = rtw_get_ie23a(pie+sizeof (struct ndis_802_11_fixed_ies), _HT_CAPABILITY_IE_, &len, ie_len-sizeof (struct ndis_802_11_fixed_ies));
2312 if (p && len > 0) {
2313 pht_capie = (struct ieee80211_ht_cap *)(p+2);
2314 max_ampdu_sz = (pht_capie->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR);
2315 max_ampdu_sz = 1 << (max_ampdu_sz+3); /* max_ampdu_sz (kbytes); */
2316
2317 /* DBG_8723A("rtw_update_ht_cap23a(): max_ampdu_sz =%d\n", max_ampdu_sz); */
2318 phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
2319
2320 }
2321
2322 len = 0;
2323 p = rtw_get_ie23a(pie+sizeof (struct ndis_802_11_fixed_ies), _HT_ADD_INFO_IE_, &len, ie_len-sizeof (struct ndis_802_11_fixed_ies));
2324 if (p && len>0)
2325 {
2326 pht_addtinfo = (struct ieee80211_ht_addt_info *)(p+2);
2327 /* todo: */
2328 }
2329
2330 /* update cur_bwmode & cur_ch_offset */
2331 if ((pregistrypriv->cbw40_enable) &&
2332 (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & BIT(1)) &&
2333 (pmlmeinfo->HT_info.infos[0] & BIT(2)))
2334 {
2335 int i;
2336 u8 rf_type;
2337
2338 padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
2339
2340 /* update the MCS rates */
2341 for (i = 0; i < 16; i++)
2342 {
2343 if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R))
2344 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R23A[i];
2345 else
2346 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R23A[i];
2347 }
2348 /* switch to the 40M Hz mode accoring to the AP */
2349 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
2350 switch ((pmlmeinfo->HT_info.infos[0] & 0x3))
2351 {
2352 case HT_EXTCHNL_OFFSET_UPPER:
2353 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
2354 break;
2355
2356 case HT_EXTCHNL_OFFSET_LOWER:
2357 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
2358 break;
2359
2360 default:
2361 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2362 break;
2363 }
2364 }
2365
2366 /* */
2367 /* Config SM Power Save setting */
2368 /* */
2369 pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
2370 if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
2371 DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
2372
2373 /* */
2374 /* Config current HT Protection mode. */
2375 /* */
2376 pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
2377}
2378
2379void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
2380{
2381 u8 issued;
2382 int priority;
2383 struct sta_info *psta = NULL;
2384 struct ht_priv *phtpriv;
2385 struct pkt_attrib *pattrib = &pxmitframe->attrib;
2386 s32 bmcst = is_multicast_ether_addr(pattrib->ra);
2387
2388 if (bmcst || (padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod<100))
2389 return;
2390
2391 priority = pattrib->priority;
2392
2393 if (pattrib->psta)
2394 psta = pattrib->psta;
2395 else
2396 {
2397 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
2398 psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
2399 }
2400
2401 if (psta == NULL)
2402 {
2403 DBG_8723A("%s, psta == NUL\n", __func__);
2404 return;
2405 }
2406
2407 if (!(psta->state &_FW_LINKED))
2408 {
2409 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
2410 return;
2411 }
2412
2413 phtpriv = &psta->htpriv;
2414
2415 if ((phtpriv->ht_option == true) && (phtpriv->ampdu_enable == true))
2416 {
2417 issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
2418 issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
2419
2420 if (0 == issued)
2421 {
2422 DBG_8723A("rtw_issue_addbareq_cmd23a, p =%d\n", priority);
2423 psta->htpriv.candidate_tid_bitmap |= CHKBIT((u8)priority);
2424 rtw_addbareq_cmd23a(padapter, (u8) priority, pattrib->ra);
2425 }
2426 }
2427}
2428
2429inline void rtw_set_roaming(struct rtw_adapter *adapter, u8 to_roaming)
2430{
2431 if (to_roaming == 0)
2432 adapter->mlmepriv.to_join = false;
2433 adapter->mlmepriv.to_roaming = to_roaming;
2434}
2435
2436inline u8 rtw_to_roaming(struct rtw_adapter *adapter)
2437{
2438 return adapter->mlmepriv.to_roaming;
2439}
2440
2441void rtw23a_roaming(struct rtw_adapter *padapter, struct wlan_network *tgt_network)
2442{
2443 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2444
2445 spin_lock_bh(&pmlmepriv->lock);
2446 _rtw23a_roaming(padapter, tgt_network);
2447 spin_unlock_bh(&pmlmepriv->lock);
2448}
2449void _rtw23a_roaming(struct rtw_adapter *padapter, struct wlan_network *tgt_network)
2450{
2451 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2452 struct wlan_network *pnetwork;
2453 int do_join_r;
2454
2455 if (tgt_network != NULL)
2456 pnetwork = tgt_network;
2457 else
2458 pnetwork = &pmlmepriv->cur_network;
2459
2460 if (0 < rtw_to_roaming(padapter)) {
2461 DBG_8723A("roaming from %s("MAC_FMT"), length:%d\n",
2462 pnetwork->network.Ssid.ssid,
2463 MAC_ARG(pnetwork->network.MacAddress),
2464 pnetwork->network.Ssid.ssid_len);
2465 memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid,
2466 sizeof(struct cfg80211_ssid));
2467
2468 pmlmepriv->assoc_by_bssid = false;
2469
2470 while(1) {
2471 if (_SUCCESS == (do_join_r = rtw_do_join23a(padapter))) {
2472 break;
2473 } else {
2474 DBG_8723A("roaming do_join return %d\n", do_join_r);
2475 pmlmepriv->to_roaming--;
2476
2477 if (0 < rtw_to_roaming(padapter)) {
2478 continue;
2479 } else {
2480 DBG_8723A("%s(%d) -to roaming fail, indicate_disconnect\n", __func__, __LINE__);
2481 rtw_indicate_disconnect23a(padapter);
2482 break;
2483 }
2484 }
2485 }
2486 }
2487}
2488
2489int rtw_linked_check(struct rtw_adapter *padapter)
2490{
2491 if ((check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE)) ||
2492 (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE))) {
2493 if (padapter->stapriv.asoc_sta_count > 2)
2494 return true;
2495 } else { /* Station mode */
2496 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == true)
2497 return true;
2498 }
2499 return false;
2500}
diff --git a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c
new file mode 100644
index 000000000000..4c753639ea5a
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c
@@ -0,0 +1,9990 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _RTW_MLME_EXT_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <wifi.h>
20#include <rtw_mlme_ext.h>
21#include <wlan_bssdef.h>
22#include <mlme_osdep.h>
23#include <recv_osdep.h>
24#include <ethernet.h>
25#include <linux/ieee80211.h>
26
27#ifdef CONFIG_8723AU_BT_COEXIST
28#include <rtl8723a_hal.h>
29#endif
30
31static struct mlme_handler mlme_sta_tbl[]={
32 {"OnAssocReq23a", &OnAssocReq23a},
33 {"OnAssocRsp23a", &OnAssocRsp23a},
34 {"OnReAssocReq", &OnAssocReq23a},
35 {"OnReAssocRsp", &OnAssocRsp23a},
36 {"OnProbeReq23a", &OnProbeReq23a},
37 {"OnProbeRsp23a", &OnProbeRsp23a},
38
39 /*----------------------------------------------------------
40 below 2 are reserved
41 -----------------------------------------------------------*/
42 {"DoReserved23a", &DoReserved23a},
43 {"DoReserved23a", &DoReserved23a},
44 {"OnBeacon23a", &OnBeacon23a},
45 {"OnATIM", &OnAtim23a},
46 {"OnDisassoc23a", &OnDisassoc23a},
47 {"OnAuth23a", &OnAuth23aClient23a},
48 {"OnDeAuth23a", &OnDeAuth23a},
49 {"OnAction23a", &OnAction23a},
50};
51
52static struct action_handler OnAction23a_tbl[]={
53 {WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct23a},
54 {WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction23a_qos},
55 {WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction23a_dls},
56 {WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction23a_back23a},
57 {WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public23a},
58 {WLAN_CATEGORY_HT, "ACTION_HT", &OnAction23a_ht},
59 {WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved23a},
60 {WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction23a_wmm},
61 {WLAN_CATEGORY_VENDOR_SPECIFIC, "ACTION_P2P", &OnAction23a_p2p},
62};
63
64static u8 null_addr[ETH_ALEN]= {0, 0, 0, 0, 0, 0};
65
66/**************************************************
67OUI definitions for the vendor specific IE
68***************************************************/
69unsigned char RTW_WPA_OUI23A[] = {0x00, 0x50, 0xf2, 0x01};
70unsigned char WMM_OUI23A[] = {0x00, 0x50, 0xf2, 0x02};
71unsigned char WPS_OUI23A[] = {0x00, 0x50, 0xf2, 0x04};
72unsigned char P2P_OUI23A[] = {0x50, 0x6F, 0x9A, 0x09};
73unsigned char WFD_OUI23A[] = {0x50, 0x6F, 0x9A, 0x0A};
74
75unsigned char WMM_INFO_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
76unsigned char WMM_PARA_OUI23A[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
77
78unsigned char WPA_TKIP_CIPHER23A[4] = {0x00, 0x50, 0xf2, 0x02};
79unsigned char RSN_TKIP_CIPHER23A[4] = {0x00, 0x0f, 0xac, 0x02};
80
81
82/********************************************************
83MCS rate definitions
84*********************************************************/
85unsigned char MCS_rate_2R23A[16] = {
86 0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
87unsigned char MCS_rate_1R23A[16] = {
88 0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
89
90/********************************************************
91ChannelPlan definitions
92*********************************************************/
93
94static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
95 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
96 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
97 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
98 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
99 {{10, 11, 12, 13}, 4}, /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
100 {{}, 0}, /* 0x05, RT_CHANNEL_DOMAIN_2G_NULL */
101};
102
103static struct rt_channel_plan_5g RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
104 {{}, 0}, /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */
105 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19}, /* 0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */
106 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, /* 0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */
107 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22}, /* 0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */
108 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, /* 0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */
109 {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, /* 0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */
110 {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, /* 0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */
111 {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12}, /* 0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */
112 {{149, 153, 157, 161, 165}, 5}, /* 0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */
113 {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */
114 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20}, /* 0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */
115 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, 165}, 20}, /* 0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */
116 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19}, /* 0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */
117 {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */
118 {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, /* 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */
119 {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 15}, /* 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */
120 {{56, 60, 64, 149, 153, 157, 161, 165}, 8}, /* 0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */
121
122 /* Driver self defined for old channel plan Compatible , Remember to modify if have new channel plan definition ===== */
123 {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21}, /* 0x11, RT_CHANNEL_DOMAIN_5G_FCC */
124 {{36, 40, 44, 48}, 4}, /* 0x12, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */
125 {{36, 40, 44, 48, 149, 153, 157, 161}, 8}, /* 0x13, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */
126};
127
128static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
129 /* 0x00 ~ 0x1F , Old Define ===== */
130 {0x02, 0x11}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
131 {0x02, 0x0A}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
132 {0x01, 0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
133 {0x01, 0x00}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
134 {0x01, 0x00}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
135 {0x03, 0x00}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
136 {0x03, 0x00}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
137 {0x01, 0x09}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
138 {0x03, 0x09}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
139 {0x03, 0x00}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
140 {0x00, 0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
141 {0x02, 0x0F}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
142 {0x01, 0x08}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
143 {0x02, 0x06}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
144 {0x02, 0x0B}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
145 {0x02, 0x09}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
146 {0x01, 0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
147 {0x02, 0x05}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
148 {0x01, 0x12}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
149 {0x00, 0x04}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
150 {0x02, 0x10}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
151 {0x00, 0x12}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
152 {0x00, 0x13}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
153 {0x03, 0x12}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
154 {0x05, 0x08}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
155 {0x02, 0x08}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
156 {0x00, 0x00}, /* 0x1A, */
157 {0x00, 0x00}, /* 0x1B, */
158 {0x00, 0x00}, /* 0x1C, */
159 {0x00, 0x00}, /* 0x1D, */
160 {0x00, 0x00}, /* 0x1E, */
161 {0x05, 0x04}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
162 /* 0x20 ~ 0x7F , New Define ===== */
163 {0x00, 0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
164 {0x01, 0x00}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
165 {0x02, 0x00}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
166 {0x03, 0x00}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
167 {0x04, 0x00}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
168 {0x02, 0x04}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
169 {0x00, 0x01}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
170 {0x03, 0x0C}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
171 {0x00, 0x0B}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
172 {0x00, 0x05}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
173 {0x00, 0x00}, /* 0x2A, */
174 {0x00, 0x00}, /* 0x2B, */
175 {0x00, 0x00}, /* 0x2C, */
176 {0x00, 0x00}, /* 0x2D, */
177 {0x00, 0x00}, /* 0x2E, */
178 {0x00, 0x00}, /* 0x2F, */
179 {0x00, 0x06}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
180 {0x00, 0x07}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
181 {0x00, 0x08}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
182 {0x00, 0x09}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
183 {0x02, 0x0A}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
184 {0x00, 0x02}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
185 {0x00, 0x03}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
186 {0x03, 0x0D}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
187 {0x03, 0x0E}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
188 {0x02, 0x0F}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
189 {0x00, 0x00}, /* 0x3A, */
190 {0x00, 0x00}, /* 0x3B, */
191 {0x00, 0x00}, /* 0x3C, */
192 {0x00, 0x00}, /* 0x3D, */
193 {0x00, 0x00}, /* 0x3E, */
194 {0x00, 0x00}, /* 0x3F, */
195 {0x02, 0x10}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
196 {0x03, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
197};
198
199static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; /* use the conbination for max channel numbers */
200
201static struct fwevent wlanevents[] =
202{
203 {0, rtw_dummy_event_callback23a}, /*0*/
204 {0, NULL},
205 {0, NULL},
206 {0, NULL},
207 {0, NULL},
208 {0, NULL},
209 {0, NULL},
210 {0, NULL},
211 {0, &rtw_survey_event_cb23a}, /*8*/
212 {sizeof (struct surveydone_event), &rtw_surveydone_event_callback23a}, /*9*/
213
214 {0, &rtw23a_joinbss_event_cb}, /*10*/
215 {sizeof(struct stassoc_event), &rtw_stassoc_event_callback23a},
216 {sizeof(struct stadel_event), &rtw_stadel_event_callback23a},
217 {0, &rtw_atimdone_event_callback23a},
218 {0, rtw_dummy_event_callback23a},
219 {0, NULL}, /*15*/
220 {0, NULL},
221 {0, NULL},
222 {0, NULL},
223 {0, rtw23a_fwdbg_event_callback},
224 {0, NULL}, /*20*/
225 {0, NULL},
226 {0, NULL},
227 {0, &rtw_cpwm_event_callback23a},
228 {0, NULL},
229};
230
231
232/*
233 * Search the @param channel_num in given @param channel_set
234 * @ch_set: the given channel set
235 * @ch: the given channel number
236 *
237 * return the index of channel_num in channel_set, -1 if not found
238 */
239int rtw_ch_set_search_ch23a(struct rt_channel_info *ch_set, const u32 ch)
240{
241 int i;
242 for (i = 0; ch_set[i]. ChannelNum != 0; i++) {
243 if (ch == ch_set[i].ChannelNum)
244 break;
245 }
246
247 if (i >= ch_set[i].ChannelNum)
248 return -1;
249 return i;
250}
251
252/****************************************************************************
253
254Following are the initialization functions for WiFi MLME
255
256*****************************************************************************/
257
258int init_hw_mlme_ext23a(struct rtw_adapter *padapter)
259{
260 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
261
262 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
263 pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
264 return _SUCCESS;
265}
266
267static void init_mlme_ext_priv23a_value(struct rtw_adapter* padapter)
268{
269 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
270 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
271 unsigned char mixed_datarate[NumRates] = {
272 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
273 _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
274 _48M_RATE_, _54M_RATE_, 0xff};
275 unsigned char mixed_basicrate[NumRates] = {
276 _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
277 _12M_RATE_, _24M_RATE_, 0xff,};
278
279 atomic_set(&pmlmeext->event_seq, 0);
280 /* reset to zero when disconnect at client mode */
281 pmlmeext->mgnt_seq = 0;
282
283 pmlmeext->cur_channel = padapter->registrypriv.channel;
284 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
285 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
286
287 pmlmeext->retry = 0;
288
289 pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
290
291 memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
292 memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
293
294 if (pmlmeext->cur_channel > 14)
295 pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;
296 else
297 pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
298
299 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
300 pmlmeext->sitesurvey_res.channel_idx = 0;
301 pmlmeext->sitesurvey_res.bss_cnt = 0;
302 pmlmeext->scan_abort = false;
303
304 pmlmeinfo->state = WIFI_FW_NULL_STATE;
305 pmlmeinfo->reauth_count = 0;
306 pmlmeinfo->reassoc_count = 0;
307 pmlmeinfo->link_count = 0;
308 pmlmeinfo->auth_seq = 0;
309 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
310 pmlmeinfo->key_index = 0;
311 pmlmeinfo->iv = 0;
312
313 pmlmeinfo->enc_algo = _NO_PRIVACY_;
314 pmlmeinfo->authModeToggle = 0;
315
316 memset(pmlmeinfo->chg_txt, 0, 128);
317
318 pmlmeinfo->slotTime = SHORT_SLOT_TIME;
319 pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
320
321 pmlmeinfo->dialogToken = 0;
322
323 pmlmeext->action_public_rxseq = 0xffff;
324 pmlmeext->action_public_dialog_token = 0xff;
325}
326
327static int has_channel(struct rt_channel_info *channel_set,
328 u8 chanset_size, u8 chan) {
329 int i;
330
331 for (i = 0; i < chanset_size; i++) {
332 if (channel_set[i].ChannelNum == chan)
333 return 1;
334 }
335
336 return 0;
337}
338
339static void init_channel_list(struct rtw_adapter *padapter,
340 struct rt_channel_info *channel_set,
341 u8 chanset_size,
342 struct p2p_channels *channel_list) {
343
344 struct p2p_oper_class_map op_class[] = {
345 { IEEE80211G, 81, 1, 13, 1, BW20 },
346 { IEEE80211G, 82, 14, 14, 1, BW20 },
347 { IEEE80211A, 115, 36, 48, 4, BW20 },
348 { IEEE80211A, 116, 36, 44, 8, BW40PLUS },
349 { IEEE80211A, 117, 40, 48, 8, BW40MINUS },
350 { IEEE80211A, 124, 149, 161, 4, BW20 },
351 { IEEE80211A, 125, 149, 169, 4, BW20 },
352 { IEEE80211A, 126, 149, 157, 8, BW40PLUS },
353 { IEEE80211A, 127, 153, 161, 8, BW40MINUS },
354 { -1, 0, 0, 0, 0, BW20 }
355 };
356
357 int cla, op;
358
359 cla = 0;
360
361 for (op = 0; op_class[op].op_class; op++) {
362 u8 ch;
363 struct p2p_oper_class_map *o = &op_class[op];
364 struct p2p_reg_class *reg = NULL;
365
366 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
367 if (!has_channel(channel_set, chanset_size, ch))
368 continue;
369
370 if ((0 == padapter->registrypriv.ht_enable) &&
371 (o->inc == 8))
372 continue;
373
374 if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
375 ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
376 continue;
377
378 if (reg == NULL) {
379 reg = &channel_list->reg_class[cla];
380 cla++;
381 reg->reg_class = o->op_class;
382 reg->channels = 0;
383 }
384 reg->channel[reg->channels] = ch;
385 reg->channels++;
386 }
387 }
388 channel_list->reg_classes = cla;
389}
390
391static u8 init_channel_set(struct rtw_adapter* padapter, u8 ChannelPlan,
392 struct rt_channel_info *channel_set)
393{
394 u8 index, chanset_size = 0;
395 u8 b5GBand = false, b2_4GBand = false;
396 u8 Index2G = 0, Index5G = 0;
397
398 memset(channel_set, 0, sizeof(struct rt_channel_info)*MAX_CHANNEL_NUM);
399
400 if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX &&
401 ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
402 DBG_8723A("ChannelPlan ID %x error !!!!!\n", ChannelPlan);
403 return chanset_size;
404 }
405
406 if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
407 b2_4GBand = true;
408 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
409 Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
410 else
411 Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
412 }
413
414 if (padapter->registrypriv.wireless_mode & WIRELESS_11A) {
415 b5GBand = true;
416 if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
417 Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G;
418 else
419 Index5G = RTW_ChannelPlanMap[ChannelPlan].Index5G;
420 }
421
422 if (b2_4GBand) {
423 for (index = 0; index<RTW_ChannelPlan2G[Index2G].Len; index++) {
424 channel_set[chanset_size].ChannelNum =
425 RTW_ChannelPlan2G[Index2G].Channel[index];
426
427 if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||
428 /* Channel 1~11 is active, and 12~14 is passive */
429 (RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == ChannelPlan)){
430 if (channel_set[chanset_size].ChannelNum >= 1 &&
431 channel_set[chanset_size].ChannelNum <= 11)
432 channel_set[chanset_size].ScanType =
433 SCAN_ACTIVE;
434 else if ((channel_set[chanset_size].ChannelNum >= 12 &&
435 channel_set[chanset_size].ChannelNum <= 14))
436 channel_set[chanset_size].ScanType =
437 SCAN_PASSIVE;
438 } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 ==
439 ChannelPlan ||
440 RT_CHANNEL_DOMAIN_WORLD_WIDE_5G ==
441 ChannelPlan ||
442 RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {
443 /* channel 12~13, passive scan */
444 if (channel_set[chanset_size].ChannelNum <= 11)
445 channel_set[chanset_size].ScanType =
446 SCAN_ACTIVE;
447 else
448 channel_set[chanset_size].ScanType =
449 SCAN_PASSIVE;
450 } else
451 channel_set[chanset_size].ScanType =
452 SCAN_ACTIVE;
453
454 chanset_size++;
455 }
456 }
457
458 if (b5GBand) {
459 for (index = 0;index<RTW_ChannelPlan5G[Index5G].Len;index++) {
460 if (RTW_ChannelPlan5G[Index5G].Channel[index] <= 48 ||
461 RTW_ChannelPlan5G[Index5G].Channel[index] >= 149) {
462 channel_set[chanset_size].ChannelNum =
463 RTW_ChannelPlan5G[Index5G].Channel[index];
464 if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G ==
465 ChannelPlan) {
466 /* passive scan for all 5G channels */
467 channel_set[chanset_size].ScanType =
468 SCAN_PASSIVE;
469 } else
470 channel_set[chanset_size].ScanType =
471 SCAN_ACTIVE;
472 DBG_8723A("%s(): channel_set[%d].ChannelNum = "
473 "%d\n", __func__, chanset_size,
474 channel_set[chanset_size].ChannelNum);
475 chanset_size++;
476 }
477 }
478 }
479
480 return chanset_size;
481}
482
483int init_mlme_ext_priv23a(struct rtw_adapter* padapter)
484{
485 int res = _SUCCESS;
486 struct registry_priv* pregistrypriv = &padapter->registrypriv;
487 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
488 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
489 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
490
491 pmlmeext->padapter = padapter;
492
493 init_mlme_ext_priv23a_value(padapter);
494 pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
495
496 init_mlme_ext_timer23a(padapter);
497
498#ifdef CONFIG_8723AU_AP_MODE
499 init_mlme_ap_info23a(padapter);
500#endif
501
502 pmlmeext->max_chan_nums = init_channel_set(padapter,
503 pmlmepriv->ChannelPlan,
504 pmlmeext->channel_set);
505 init_channel_list(padapter, pmlmeext->channel_set,
506 pmlmeext->max_chan_nums, &pmlmeext->channel_list);
507
508 pmlmeext->chan_scan_time = SURVEY_TO;
509 pmlmeext->mlmeext_init = true;
510
511 pmlmeext->active_keep_alive_check = true;
512 return res;
513}
514
515void free_mlme_ext_priv23a (struct mlme_ext_priv *pmlmeext)
516{
517 struct rtw_adapter *padapter = pmlmeext->padapter;
518
519 if (!padapter)
520 return;
521
522 if (padapter->bDriverStopped == true) {
523 del_timer_sync(&pmlmeext->survey_timer);
524 del_timer_sync(&pmlmeext->link_timer);
525 /* del_timer_sync(&pmlmeext->ADDBA_timer); */
526 }
527}
528
529static void
530_mgt_dispatcher23a(struct rtw_adapter *padapter, struct mlme_handler *ptable,
531 struct recv_frame *precv_frame)
532{
533 struct sk_buff *skb = precv_frame->pkt;
534 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
535
536 if (ptable->func) {
537 /* receive the frames that ra(a1) is my address
538 or ra(a1) is bc address. */
539 if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv))&&
540 !is_broadcast_ether_addr(hdr->addr1))
541 return;
542
543 ptable->func(padapter, precv_frame);
544 }
545}
546
547void mgt_dispatcher23a(struct rtw_adapter *padapter,
548 struct recv_frame *precv_frame)
549{
550 int index;
551 struct mlme_handler *ptable;
552#ifdef CONFIG_8723AU_AP_MODE
553 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
554#endif /* CONFIG_8723AU_AP_MODE */
555 struct sk_buff *skb = precv_frame->pkt;
556 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
557 u16 stype;
558 struct sta_info *psta;
559
560 if (!ieee80211_is_mgmt(hdr->frame_control))
561 return;
562
563 /* receive the frames that ra(a1) is my address or ra(a1) is
564 bc address. */
565 if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv)) &&
566 !is_broadcast_ether_addr(hdr->addr1))
567 return;
568
569 ptable = mlme_sta_tbl;
570
571 stype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE;
572 index = stype >> 4;
573
574 if (index > 13) {
575 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
576 ("Currently we do not support reserved sub-fr-type ="
577 "%d\n", index));
578 return;
579 }
580 ptable += index;
581
582 psta = rtw_get_stainfo23a(&padapter->stapriv, hdr->addr2);
583
584 if (psta) {
585 if (ieee80211_has_retry(hdr->frame_control)) {
586 if (precv_frame->attrib.seq_num ==
587 psta->RxMgmtFrameSeqNum) {
588 /* drop the duplicate management frame */
589 DBG_8723A("Drop duplicate management frame "
590 "with seq_num = %d.\n",
591 precv_frame->attrib.seq_num);
592 return;
593 }
594 }
595 psta->RxMgmtFrameSeqNum = precv_frame->attrib.seq_num;
596 }
597
598#ifdef CONFIG_8723AU_AP_MODE
599 switch (stype)
600 {
601 case IEEE80211_STYPE_AUTH:
602 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
603 ptable->func = &OnAuth23a;
604 else
605 ptable->func = &OnAuth23aClient23a;
606 /* pass through */
607 case IEEE80211_STYPE_ASSOC_REQ:
608 case IEEE80211_STYPE_REASSOC_REQ:
609 _mgt_dispatcher23a(padapter, ptable, precv_frame);
610 break;
611 case IEEE80211_STYPE_PROBE_REQ:
612 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
613 _mgt_dispatcher23a(padapter, ptable, precv_frame);
614 else
615 _mgt_dispatcher23a(padapter, ptable, precv_frame);
616 break;
617 case IEEE80211_STYPE_BEACON:
618 _mgt_dispatcher23a(padapter, ptable, precv_frame);
619 break;
620 case IEEE80211_STYPE_ACTION:
621 /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) */
622 _mgt_dispatcher23a(padapter, ptable, precv_frame);
623 break;
624 default:
625 _mgt_dispatcher23a(padapter, ptable, precv_frame);
626 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
627 rtw_hostapd_mlme_rx23a(padapter, precv_frame);
628 break;
629 }
630#else
631 _mgt_dispatcher23a(padapter, ptable, precv_frame);
632#endif
633}
634
635#ifdef CONFIG_8723AU_P2P
636static u32 p2p_listen_state_process(struct rtw_adapter *padapter,
637 unsigned char *da)
638{
639 bool response = true;
640
641 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == false ||
642 padapter->mlmepriv.wps_probe_resp_ie == NULL ||
643 padapter->mlmepriv.p2p_probe_resp_ie == NULL) {
644 DBG_8723A("DON'T issue_probersp23a_p2p23a: p2p_enabled:%d, "
645 "wps_probe_resp_ie:%p, p2p_probe_resp_ie:%p\n",
646 wdev_to_priv(padapter->rtw_wdev)->p2p_enabled,
647 padapter->mlmepriv.wps_probe_resp_ie,
648 padapter->mlmepriv.p2p_probe_resp_ie);
649 response = false;
650 }
651
652 if (response == true)
653 issue_probersp23a_p2p23a(padapter, da);
654
655 return _SUCCESS;
656}
657#endif /* CONFIG_8723AU_P2P */
658
659/****************************************************************************
660
661Following are the callback functions for each subtype of the management frames
662
663*****************************************************************************/
664
665unsigned int OnProbeReq23a(struct rtw_adapter *padapter,
666 struct recv_frame *precv_frame)
667{
668 unsigned int ielen;
669 unsigned char *p;
670 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
671 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
672 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
673 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
674 struct sk_buff *skb = precv_frame->pkt;
675 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
676 u8 *pframe = skb->data;
677 uint len = skb->len;
678 u8 is_valid_p2p_probereq = false;
679
680#ifdef CONFIG_8723AU_P2P
681 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
682 u8 wifi_test_chk_rate = 1;
683
684 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
685 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) &&
686 !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) &&
687 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) &&
688 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)) {
689 /* mcs_rate = 0 -> CCK 1M rate */
690 /* mcs_rate = 1 -> CCK 2M rate */
691 /* mcs_rate = 2 -> CCK 5.5M rate */
692 /* mcs_rate = 3 -> CCK 11M rate */
693 /* In the P2P mode, the driver should not support
694 the CCK rate */
695
696 /* IOT issue: Google Nexus7 use 1M rate to send
697 p2p_probe_req after GO nego completed and Nexus7
698 is client */
699 if (wifi_test_chk_rate == 1) {
700 if ((is_valid_p2p_probereq =
701 process_probe_req_p2p_ie23a(pwdinfo, pframe,
702 len)) == true) {
703 if (rtw_p2p_chk_role(pwdinfo,
704 P2P_ROLE_DEVICE)) {
705 u8 *sa = ieee80211_get_SA(hdr);
706 p2p_listen_state_process(padapter, sa);
707 return _SUCCESS;
708 }
709
710 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
711 goto _continue;
712 }
713 }
714 }
715 }
716
717_continue:
718#endif /* CONFIG_8723AU_P2P */
719
720 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
721 return _SUCCESS;
722 }
723
724 if (check_fwstate(pmlmepriv, _FW_LINKED) == false &&
725 check_fwstate(pmlmepriv,
726 WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == false) {
727 return _SUCCESS;
728 }
729
730 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) +
731 _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
732 len - sizeof(struct ieee80211_hdr_3addr) -
733 _PROBEREQ_IE_OFFSET_);
734
735 /* check (wildcard) SSID */
736 if (p) {
737 if (is_valid_p2p_probereq == true) {
738 goto _issue_probersp23a;
739 }
740
741 if ((ielen != 0 &&
742 memcmp((void *)(p+2), cur->Ssid.ssid,
743 cur->Ssid.ssid_len)) ||
744 (ielen == 0 && pmlmeinfo->hidden_ssid_mode)) {
745 return _SUCCESS;
746 }
747
748_issue_probersp23a:
749
750 if (check_fwstate(pmlmepriv, _FW_LINKED) == true &&
751 pmlmepriv->cur_network.join_res == true) {
752 /* DBG_8723A("+issue_probersp23a during ap mode\n"); */
753 issue_probersp23a(padapter, ieee80211_get_SA(hdr),
754 is_valid_p2p_probereq);
755 }
756 }
757
758 return _SUCCESS;
759}
760
761unsigned int OnProbeRsp23a(struct rtw_adapter *padapter,
762 struct recv_frame *precv_frame)
763{
764 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
765#ifdef CONFIG_8723AU_P2P
766 struct sk_buff *skb = precv_frame->pkt;
767 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
768 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
769#endif
770
771#ifdef CONFIG_8723AU_P2P
772 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
773 if (pwdinfo->tx_prov_disc_info.benable == true) {
774 if (ether_addr_equal(pwdinfo->tx_prov_disc_info.peerIFAddr,
775 hdr->addr2)) {
776 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
777 pwdinfo->tx_prov_disc_info.benable = false;
778 issue_p2p_provision_request23a(padapter,
779 pwdinfo->tx_prov_disc_info.ssid.ssid,
780 pwdinfo->tx_prov_disc_info.ssid.ssid_len,
781 pwdinfo->tx_prov_disc_info.peerDevAddr);
782 }
783 else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
784 {
785 pwdinfo->tx_prov_disc_info.benable = false;
786 issue_p2p_provision_request23a(padapter,
787 NULL,
788 0,
789 pwdinfo->tx_prov_disc_info.peerDevAddr);
790 }
791 }
792 }
793 return _SUCCESS;
794 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
795 if (pwdinfo->nego_req_info.benable == true) {
796 DBG_8723A("[%s] P2P State is GONEGO ING!\n", __func__);
797 if (ether_addr_equal(pwdinfo->nego_req_info.peerDevAddr,
798 hdr->addr2)) {
799 pwdinfo->nego_req_info.benable = false;
800 issue_p2p_GO_request23a(padapter, pwdinfo->nego_req_info.peerDevAddr);
801 }
802 }
803 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
804 if (pwdinfo->invitereq_info.benable == true) {
805 DBG_8723A("[%s] P2P_STATE_TX_INVITE_REQ!\n", __func__);
806 if (ether_addr_equal(
807 pwdinfo->invitereq_info.peer_macaddr,
808 hdr->addr2)) {
809 pwdinfo->invitereq_info.benable = false;
810 issue_p2p_invitation_request23a(padapter, pwdinfo->invitereq_info.peer_macaddr);
811 }
812 }
813 }
814#endif
815
816 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
817 report_survey_event23a(padapter, precv_frame);
818 return _SUCCESS;
819 }
820
821 return _SUCCESS;
822}
823
824unsigned int OnBeacon23a(struct rtw_adapter *padapter,
825 struct recv_frame *precv_frame)
826{
827 int cam_idx;
828 struct sta_info *psta;
829 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
830 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
831 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
832 struct sta_priv *pstapriv = &padapter->stapriv;
833 struct sk_buff *skb = precv_frame->pkt;
834 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
835 u8 *pframe = skb->data;
836 uint len = skb->len;
837 struct wlan_bssid_ex *pbss;
838 int ret = _SUCCESS;
839 u8 *p = NULL;
840 u32 ielen = 0;
841
842 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) +
843 _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ielen,
844 len - sizeof(struct ieee80211_hdr_3addr) -
845 _BEACON_IE_OFFSET_);
846 if ((p != NULL) && (ielen > 0)) {
847 if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D)) {
848 /* Invalid value 0x2D is detected in Extended Supported
849 * Rates (ESR) IE. Try to fix the IE length to avoid
850 * failed Beacon parsing.
851 */
852 DBG_8723A("[WIFIDBG] Error in ESR IE is detected in "
853 "Beacon of BSSID: %pM. Fix the length of "
854 "ESR IE to avoid failed Beacon parsing.\n",
855 hdr->addr3);
856 *(p + 1) = ielen - 1;
857 }
858 }
859
860 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
861 report_survey_event23a(padapter, precv_frame);
862 return _SUCCESS;
863 }
864
865 if (ether_addr_equal(hdr->addr3, get_my_bssid23a(&pmlmeinfo->network))){
866 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
867 /* we should update current network before auth,
868 or some IE is wrong */
869 pbss = (struct wlan_bssid_ex *)
870 kmalloc(sizeof(struct wlan_bssid_ex),
871 GFP_ATOMIC);
872 if (pbss) {
873 if (collect_bss_info23a(padapter, precv_frame,
874 pbss) == _SUCCESS) {
875 update_network23a(&pmlmepriv->cur_network.network, pbss, padapter, true);
876 rtw_get_bcn_info23a(&pmlmepriv->cur_network);
877 }
878 kfree(pbss);
879 }
880
881 /* check the vendor of the assoc AP */
882 pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pframe + sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr));
883
884 /* update TSF Value */
885 update_TSF23a(pmlmeext, pframe, len);
886
887 /* start auth */
888 start_clnt_auth23a(padapter);
889
890 return _SUCCESS;
891 }
892
893 if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) &&
894 (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
895 psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
896 if (psta) {
897 ret = rtw_check_bcn_info23a(padapter, pframe,
898 len);
899 if (!ret) {
900 DBG_8723A_LEVEL(_drv_always_,
901 "ap has changed, "
902 "disconnect now\n");
903 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress, 65535);
904 return _SUCCESS;
905 }
906 /* update WMM, ERP in the beacon */
907 /* todo: the timer is used instead of
908 the number of the beacon received */
909 if ((sta_rx_pkts(psta) & 0xf) == 0) {
910 /* DBG_8723A("update_bcn_info\n"); */
911 update_beacon23a_info(padapter, pframe,
912 len, psta);
913 }
914
915#ifdef CONFIG_8723AU_P2P
916 process_p2p_ps_ie23a(padapter, (pframe + sizeof(struct ieee80211_hdr_3addr)), (len - sizeof(struct ieee80211_hdr_3addr)));
917#endif /* CONFIG_8723AU_P2P */
918 }
919 } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
920 psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
921 if (psta) {
922 /* update WMM, ERP in the beacon */
923 /* todo: the timer is used instead of the
924 number of the beacon received */
925 if ((sta_rx_pkts(psta) & 0xf) == 0) {
926 /* DBG_8723A("update_bcn_info\n"); */
927 update_beacon23a_info(padapter, pframe,
928 len, psta);
929 }
930 } else {
931 /* allocate a new CAM entry for IBSS station */
932 cam_idx = allocate_fw_sta_entry23a(padapter);
933 if (cam_idx == NUM_STA)
934 goto _END_ONBEACON_;
935
936 /* get supported rate */
937 if (update_sta_support_rate23a(padapter, (pframe + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_), (len - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) {
938 pmlmeinfo->FW_sta_info[cam_idx].status = 0;
939 goto _END_ONBEACON_;
940 }
941
942 /* update TSF Value */
943 update_TSF23a(pmlmeext, pframe, len);
944
945 /* report sta add event */
946 report_add_sta_event23a(padapter, hdr->addr2,
947 cam_idx);
948 }
949 }
950 }
951
952_END_ONBEACON_:
953
954 return _SUCCESS;
955}
956
957unsigned int OnAuth23a(struct rtw_adapter *padapter,
958 struct recv_frame *precv_frame)
959{
960#ifdef CONFIG_8723AU_AP_MODE
961 unsigned int auth_mode, seq, ie_len;
962 unsigned char *sa, *p;
963 u16 algorithm;
964 int status;
965 static struct sta_info stat;
966 struct sta_info *pstat = NULL;
967 struct sta_priv *pstapriv = &padapter->stapriv;
968 struct security_priv *psecuritypriv = &padapter->securitypriv;
969 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
970 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
971 struct sk_buff *skb = precv_frame->pkt;
972 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
973 u8 *pframe = skb->data;
974 uint len = skb->len;
975
976 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
977 return _FAIL;
978
979 DBG_8723A("+OnAuth23a\n");
980
981 sa = hdr->addr2;
982
983 auth_mode = psecuritypriv->dot11AuthAlgrthm;
984 seq = cpu_to_le16(*(u16*)((unsigned long)pframe +
985 sizeof(struct ieee80211_hdr_3addr) + 2));
986 algorithm = cpu_to_le16(*(u16*)((unsigned long)pframe +
987 sizeof(struct ieee80211_hdr_3addr)));
988
989 DBG_8723A("auth alg =%x, seq =%X\n", algorithm, seq);
990
991 if (auth_mode == 2 &&
992 psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
993 psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
994 auth_mode = 0;
995
996 /* rx a shared-key auth but shared not enabled, or */
997 /* rx a open-system auth but shared-key is enabled */
998 if ((algorithm > 0 && auth_mode == 0) ||
999 (algorithm == 0 && auth_mode == 1)) {
1000 DBG_8723A("auth rejected due to bad alg [alg =%d, auth_mib "
1001 "=%d] %02X%02X%02X%02X%02X%02X\n",
1002 algorithm, auth_mode,
1003 sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
1004
1005 status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1006
1007 goto auth_fail;
1008 }
1009
1010 if (rtw_access_ctrl23a(padapter, sa) == false) {
1011 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1012 goto auth_fail;
1013 }
1014
1015 pstat = rtw_get_stainfo23a(pstapriv, sa);
1016 if (!pstat) {
1017 /* allocate a new one */
1018 DBG_8723A("going to alloc stainfo for sa ="MAC_FMT"\n",
1019 MAC_ARG(sa));
1020 pstat = rtw_alloc_stainfo23a(pstapriv, sa);
1021 if (!pstat) {
1022 DBG_8723A(" Exceed the upper limit of supported "
1023 "clients...\n");
1024 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1025 goto auth_fail;
1026 }
1027
1028 pstat->state = WIFI_FW_AUTH_NULL;
1029 pstat->auth_seq = 0;
1030
1031 /* pstat->flags = 0; */
1032 /* pstat->capability = 0; */
1033 } else {
1034 spin_lock_bh(&pstapriv->asoc_list_lock);
1035 if (!list_empty(&pstat->asoc_list)) {
1036 list_del_init(&pstat->asoc_list);
1037 pstapriv->asoc_list_cnt--;
1038 if (pstat->expire_to > 0)
1039 {
1040 /* TODO: STA re_auth within expire_to */
1041 }
1042 }
1043 spin_unlock_bh(&pstapriv->asoc_list_lock);
1044
1045 if (seq == 1) {
1046 /* TODO: STA re_auth and auth timeout */
1047 }
1048 }
1049
1050 spin_lock_bh(&pstapriv->auth_list_lock);
1051 if (list_empty(&pstat->auth_list)) {
1052 list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
1053 pstapriv->auth_list_cnt++;
1054 }
1055 spin_unlock_bh(&pstapriv->auth_list_lock);
1056
1057 if (pstat->auth_seq == 0)
1058 pstat->expire_to = pstapriv->auth_to;
1059
1060 if ((pstat->auth_seq + 1) != seq) {
1061 DBG_8723A("(1)auth rejected because out of seq [rx_seq =%d, "
1062 "exp_seq =%d]!\n", seq, pstat->auth_seq+1);
1063 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1064 goto auth_fail;
1065 }
1066
1067 if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) {
1068 if (seq == 1) {
1069 pstat->state &= ~WIFI_FW_AUTH_NULL;
1070 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1071 pstat->expire_to = pstapriv->assoc_to;
1072 pstat->authalg = algorithm;
1073 } else {
1074 DBG_8723A("(2)auth rejected because out of seq "
1075 "[rx_seq =%d, exp_seq =%d]!\n",
1076 seq, pstat->auth_seq+1);
1077 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1078 goto auth_fail;
1079 }
1080 } else { /* shared system or auto authentication */
1081 if (seq == 1) {
1082 /* prepare for the challenging txt... */
1083 pstat->state &= ~WIFI_FW_AUTH_NULL;
1084 pstat->state |= WIFI_FW_AUTH_STATE;
1085 pstat->authalg = algorithm;
1086 pstat->auth_seq = 2;
1087 } else if (seq == 3) {
1088 /* checking for challenging txt... */
1089 DBG_8723A("checking for challenging txt...\n");
1090
1091 p = rtw_get_ie23a(pframe +
1092 sizeof(struct ieee80211_hdr_3addr) +
1093 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_,
1094 (int *)&ie_len, len -
1095 sizeof(struct ieee80211_hdr_3addr) -
1096 _AUTH_IE_OFFSET_ - 4);
1097
1098 if ((p == NULL) || (ie_len<= 0)) {
1099 DBG_8723A("auth rejected because challenge "
1100 "failure!(1)\n");
1101 status = WLAN_STATUS_CHALLENGE_FAIL;
1102 goto auth_fail;
1103 }
1104
1105 if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
1106 pstat->state &= (~WIFI_FW_AUTH_STATE);
1107 pstat->state |= WIFI_FW_AUTH_SUCCESS;
1108 /* challenging txt is correct... */
1109 pstat->expire_to = pstapriv->assoc_to;
1110 } else {
1111 DBG_8723A("auth rejected because challenge "
1112 "failure!\n");
1113 status = WLAN_STATUS_CHALLENGE_FAIL;
1114 goto auth_fail;
1115 }
1116 } else {
1117 DBG_8723A("(3)auth rejected because out of seq "
1118 "[rx_seq =%d, exp_seq =%d]!\n",
1119 seq, pstat->auth_seq+1);
1120 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1121 goto auth_fail;
1122 }
1123 }
1124
1125 /* Now, we are going to issue_auth23a... */
1126 pstat->auth_seq = seq + 1;
1127
1128 issue_auth23a(padapter, pstat, (unsigned short)WLAN_STATUS_SUCCESS);
1129
1130 if (pstat->state & WIFI_FW_AUTH_SUCCESS)
1131 pstat->auth_seq = 0;
1132
1133 return _SUCCESS;
1134
1135auth_fail:
1136
1137 if (pstat)
1138 rtw_free_stainfo23a(padapter, pstat);
1139
1140 pstat = &stat;
1141 memset((char *)pstat, '\0', sizeof(stat));
1142 pstat->auth_seq = 2;
1143 memcpy(pstat->hwaddr, sa, 6);
1144
1145 issue_auth23a(padapter, pstat, (unsigned short)status);
1146
1147#endif
1148 return _FAIL;
1149}
1150
1151unsigned int OnAuth23aClient23a(struct rtw_adapter *padapter,
1152 struct recv_frame *precv_frame)
1153{
1154 unsigned int seq, len, status, algthm, offset;
1155 unsigned char *p;
1156 unsigned int go2asoc = 0;
1157 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1158 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1159 struct sk_buff *skb = precv_frame->pkt;
1160 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1161 u8 *pframe = skb->data;
1162 uint pkt_len = skb->len;
1163
1164 DBG_8723A("%s\n", __func__);
1165
1166 /* check A1 matches or not */
1167 if (!ether_addr_equal(myid(&padapter->eeprompriv),
1168 ieee80211_get_DA(hdr)))
1169 return _SUCCESS;
1170
1171 if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
1172 return _SUCCESS;
1173
1174 offset = ieee80211_has_protected(hdr->frame_control) ? 4: 0;
1175
1176 algthm = le16_to_cpu(*(unsigned short *)((unsigned long)pframe + sizeof(struct ieee80211_hdr_3addr) + offset));
1177 seq = le16_to_cpu(*(unsigned short *)((unsigned long)pframe + sizeof(struct ieee80211_hdr_3addr) + offset + 2));
1178 status = le16_to_cpu(*(unsigned short *)((unsigned long)pframe + sizeof(struct ieee80211_hdr_3addr) + offset + 4));
1179
1180 if (status != 0)
1181 {
1182 DBG_8723A("clnt auth fail, status: %d\n", status);
1183 if (status == 13)/* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
1184 {
1185 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1186 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
1187 else
1188 pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
1189 /* pmlmeinfo->reauth_count = 0; */
1190 }
1191
1192 set_link_timer(pmlmeext, 1);
1193 goto authclnt_fail;
1194 }
1195
1196 if (seq == 2)
1197 {
1198 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1199 {
1200 /* legendary shared system */
1201 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
1202 pkt_len - sizeof(struct ieee80211_hdr_3addr) - _AUTH_IE_OFFSET_);
1203
1204 if (p == NULL)
1205 {
1206 /* DBG_8723A("marc: no challenge text?\n"); */
1207 goto authclnt_fail;
1208 }
1209
1210 memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
1211 pmlmeinfo->auth_seq = 3;
1212 issue_auth23a(padapter, NULL, 0);
1213 set_link_timer(pmlmeext, REAUTH_TO);
1214
1215 return _SUCCESS;
1216 }
1217 else
1218 {
1219 /* open system */
1220 go2asoc = 1;
1221 }
1222 }
1223 else if (seq == 4)
1224 {
1225 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1226 {
1227 go2asoc = 1;
1228 }
1229 else
1230 {
1231 goto authclnt_fail;
1232 }
1233 }
1234 else
1235 {
1236 /* this is also illegal */
1237 /* DBG_8723A("marc: clnt auth failed due to illegal seq =%x\n", seq); */
1238 goto authclnt_fail;
1239 }
1240
1241 if (go2asoc)
1242 {
1243 DBG_8723A_LEVEL(_drv_always_, "auth success, start assoc\n");
1244 start_clnt_assoc23a(padapter);
1245 return _SUCCESS;
1246 }
1247
1248authclnt_fail:
1249
1250 /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
1251
1252 return _FAIL;
1253}
1254
1255unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1256{
1257#ifdef CONFIG_8723AU_AP_MODE
1258 u16 capab_info, listen_interval;
1259 struct rtw_ieee802_11_elems elems;
1260 struct sta_info *pstat;
1261 unsigned char reassoc, *p, *pos, *wpa_ie;
1262 unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
1263 int i, ie_len, wpa_ie_len, left;
1264 unsigned char supportRate[16];
1265 int supportRateNum;
1266 unsigned short status = WLAN_STATUS_SUCCESS;
1267 unsigned short ie_offset;
1268 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1269 struct security_priv *psecuritypriv = &padapter->securitypriv;
1270 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1271 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1272 struct wlan_bssid_ex *cur = &pmlmeinfo->network;
1273 struct sta_priv *pstapriv = &padapter->stapriv;
1274 struct sk_buff *skb = precv_frame->pkt;
1275 u8 *pframe = skb->data;
1276 uint pkt_len = skb->len;
1277 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1278 u16 frame_control;
1279#ifdef CONFIG_8723AU_P2P
1280 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1281 u8 p2p_status_code = P2P_STATUS_SUCCESS;
1282 u8 *p2pie;
1283 u32 p2pielen = 0;
1284 u8 wfd_ie[ 128 ] = { 0x00 };
1285 u32 wfd_ielen = 0;
1286#endif /* CONFIG_8723AU_P2P */
1287
1288 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1289 return _FAIL;
1290
1291 frame_control = hdr->frame_control;
1292 if (ieee80211_is_assoc_req(frame_control)) {
1293 reassoc = 0;
1294 ie_offset = _ASOCREQ_IE_OFFSET_;
1295 } else { /* WIFI_REASSOCREQ */
1296 reassoc = 1;
1297 ie_offset = _REASOCREQ_IE_OFFSET_;
1298 }
1299
1300 if (pkt_len < sizeof(struct ieee80211_hdr_3addr) + ie_offset) {
1301 DBG_8723A("handle_assoc(reassoc =%d) - too short payload (len =%lu)"
1302 "\n", reassoc, (unsigned long)pkt_len);
1303 return _FAIL;
1304 }
1305
1306 pstat = rtw_get_stainfo23a(pstapriv, hdr->addr2);
1307 if (!pstat) {
1308 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
1309 goto asoc_class2_error;
1310 }
1311
1312 capab_info = get_unaligned_le16(pframe + sizeof(struct ieee80211_hdr_3addr));
1313 /* capab_info = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr))); */
1314 /* listen_interval = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr)+2)); */
1315 listen_interval = get_unaligned_le16(pframe + sizeof(struct ieee80211_hdr_3addr)+2);
1316
1317 left = pkt_len - (sizeof(struct ieee80211_hdr_3addr) + ie_offset);
1318 pos = pframe + (sizeof(struct ieee80211_hdr_3addr) + ie_offset);
1319
1320 DBG_8723A("%s\n", __func__);
1321
1322 /* check if this stat has been successfully authenticated/assocated */
1323 if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS))
1324 {
1325 if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS))
1326 {
1327 status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
1328 goto asoc_class2_error;
1329 }
1330 else
1331 {
1332 pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1333 pstat->state |= WIFI_FW_ASSOC_STATE;
1334 }
1335 }
1336 else
1337 {
1338 pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1339 pstat->state |= WIFI_FW_ASSOC_STATE;
1340 }
1341
1342 pstat->capability = capab_info;
1343
1344 /* now parse all ieee802_11 ie to point to elems */
1345 if (rtw_ieee802_11_parse_elems23a(pos, left, &elems, 1) == ParseFailed ||
1346 !elems.ssid) {
1347 DBG_8723A("STA " MAC_FMT " sent invalid association request\n",
1348 MAC_ARG(pstat->hwaddr));
1349 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1350 goto OnAssocReq23aFail;
1351 }
1352
1353 /* now we should check all the fields... */
1354 /* checking SSID */
1355 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, _SSID_IE_, &ie_len,
1356 pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset);
1357 if (p == NULL)
1358 {
1359 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1360 }
1361
1362 if (ie_len == 0) /* broadcast ssid, however it is not allowed in assocreq */
1363 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1364 else {
1365 /* check if ssid match */
1366 if (memcmp((void *)(p+2), cur->Ssid.ssid, cur->Ssid.ssid_len))
1367 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1368
1369 if (ie_len != cur->Ssid.ssid_len)
1370 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1371 }
1372
1373 if (WLAN_STATUS_SUCCESS != status)
1374 goto OnAssocReq23aFail;
1375
1376 /* check if the supported rate is ok */
1377 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset);
1378 if (p == NULL) {
1379 DBG_8723A("Rx a sta assoc-req which supported rate is empty!\n");
1380 /* use our own rate set as statoin used */
1381 /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1382 /* supportRateNum = AP_BSSRATE_LEN; */
1383
1384 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1385 goto OnAssocReq23aFail;
1386 } else {
1387 memcpy(supportRate, p+2, ie_len);
1388 supportRateNum = ie_len;
1389
1390 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len,
1391 pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset);
1392 if (p != NULL) {
1393
1394 if (supportRateNum<= sizeof(supportRate))
1395 {
1396 memcpy(supportRate+supportRateNum, p+2, ie_len);
1397 supportRateNum += ie_len;
1398 }
1399 }
1400 }
1401
1402 /* todo: mask supportRate between AP & STA -> move to update raid */
1403 /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1404
1405 /* update station supportRate */
1406 pstat->bssratelen = supportRateNum;
1407 memcpy(pstat->bssrateset, supportRate, supportRateNum);
1408 Update23aTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1409
1410 /* check RSN/WPA/WPS */
1411 pstat->dot8021xalg = 0;
1412 pstat->wpa_psk = 0;
1413 pstat->wpa_group_cipher = 0;
1414 pstat->wpa2_group_cipher = 0;
1415 pstat->wpa_pairwise_cipher = 0;
1416 pstat->wpa2_pairwise_cipher = 0;
1417 memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1418 if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
1419
1420 int group_cipher = 0, pairwise_cipher = 0;
1421
1422 wpa_ie = elems.rsn_ie;
1423 wpa_ie_len = elems.rsn_ie_len;
1424
1425 if (rtw_parse_wpa2_ie23a(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1426 pstat->dot8021xalg = 1;/* psk, todo:802.1x */
1427 pstat->wpa_psk |= BIT(1);
1428
1429 pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;
1430 pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
1431
1432 if (!pstat->wpa2_group_cipher)
1433 status = WLAN_REASON_INVALID_GROUP_CIPHER;
1434
1435 if (!pstat->wpa2_pairwise_cipher)
1436 status = WLAN_REASON_INVALID_PAIRWISE_CIPHER;
1437 } else {
1438 status = WLAN_STATUS_INVALID_IE;
1439 }
1440
1441 } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
1442
1443 int group_cipher = 0, pairwise_cipher = 0;
1444
1445 wpa_ie = elems.wpa_ie;
1446 wpa_ie_len = elems.wpa_ie_len;
1447
1448 if (rtw_parse_wpa_ie23a(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1449 pstat->dot8021xalg = 1;/* psk, todo:802.1x */
1450 pstat->wpa_psk |= BIT(0);
1451
1452 pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;
1453 pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
1454
1455 if (!pstat->wpa_group_cipher)
1456 status = WLAN_STATUS_INVALID_GROUP_CIPHER;
1457
1458 if (!pstat->wpa_pairwise_cipher)
1459 status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
1460
1461 } else {
1462 status = WLAN_STATUS_INVALID_IE;
1463 }
1464
1465 } else {
1466 wpa_ie = NULL;
1467 wpa_ie_len = 0;
1468 }
1469
1470 if (WLAN_STATUS_SUCCESS != status)
1471 goto OnAssocReq23aFail;
1472
1473 pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1474 if (wpa_ie == NULL) {
1475 if (elems.wps_ie) {
1476 DBG_8723A("STA included WPS IE in "
1477 "(Re)Association Request - assume WPS is "
1478 "used\n");
1479 pstat->flags |= WLAN_STA_WPS;
1480 } else {
1481 DBG_8723A("STA did not include WPA/RSN IE "
1482 "in (Re)Association Request - possible WPS "
1483 "use\n");
1484 pstat->flags |= WLAN_STA_MAYBE_WPS;
1485 }
1486
1487 /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
1488 /* that the selected registrar of AP is _FLASE */
1489 if ((psecuritypriv->wpa_psk > 0) &&
1490 (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
1491 if (pmlmepriv->wps_beacon_ie) {
1492 u8 selected_registrar = 0;
1493
1494 rtw_get_wps_attr_content23a(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len,
1495 WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
1496
1497 if (!selected_registrar) {
1498 DBG_8723A("selected_registrar is false , or AP is not ready to do WPS\n");
1499
1500 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1501
1502 goto OnAssocReq23aFail;
1503 }
1504 }
1505 }
1506 } else {
1507 int copy_len;
1508
1509 if (psecuritypriv->wpa_psk == 0) {
1510 DBG_8723A("STA " MAC_FMT ": WPA/RSN IE in association "
1511 "request, but AP don't support WPA/RSN\n", MAC_ARG(pstat->hwaddr));
1512
1513 status = WLAN_STATUS_INVALID_IE;
1514
1515 goto OnAssocReq23aFail;
1516 }
1517
1518 if (elems.wps_ie) {
1519 DBG_8723A("STA included WPS IE in "
1520 "(Re)Association Request - WPS is "
1521 "used\n");
1522 pstat->flags |= WLAN_STA_WPS;
1523 copy_len = 0;
1524 } else {
1525 copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2);
1526 }
1527
1528 if (copy_len>0)
1529 memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
1530
1531 }
1532
1533 /* check if there is WMM IE & support WWM-PS */
1534 pstat->flags &= ~WLAN_STA_WME;
1535 pstat->qos_option = 0;
1536 pstat->qos_info = 0;
1537 pstat->has_legacy_ac = true;
1538 pstat->uapsd_vo = 0;
1539 pstat->uapsd_vi = 0;
1540 pstat->uapsd_be = 0;
1541 pstat->uapsd_bk = 0;
1542 if (pmlmepriv->qospriv.qos_option)
1543 {
1544 p = pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset; ie_len = 0;
1545 for (;;)
1546 {
1547 p = rtw_get_ie23a(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset);
1548 if (p != NULL) {
1549 if (!memcmp(p+2, WMM_IE, 6)) {
1550
1551 pstat->flags |= WLAN_STA_WME;
1552
1553 pstat->qos_option = 1;
1554 pstat->qos_info = *(p+8);
1555
1556 pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
1557
1558 if ((pstat->qos_info&0xf) != 0xf)
1559 pstat->has_legacy_ac = true;
1560 else
1561 pstat->has_legacy_ac = false;
1562
1563 if (pstat->qos_info&0xf)
1564 {
1565 if (pstat->qos_info&BIT(0))
1566 pstat->uapsd_vo = BIT(0)|BIT(1);
1567 else
1568 pstat->uapsd_vo = 0;
1569
1570 if (pstat->qos_info&BIT(1))
1571 pstat->uapsd_vi = BIT(0)|BIT(1);
1572 else
1573 pstat->uapsd_vi = 0;
1574
1575 if (pstat->qos_info&BIT(2))
1576 pstat->uapsd_bk = BIT(0)|BIT(1);
1577 else
1578 pstat->uapsd_bk = 0;
1579
1580 if (pstat->qos_info&BIT(3))
1581 pstat->uapsd_be = BIT(0)|BIT(1);
1582 else
1583 pstat->uapsd_be = 0;
1584
1585 }
1586
1587 break;
1588 }
1589 }
1590 else {
1591 break;
1592 }
1593 p = p + ie_len + 2;
1594 }
1595 }
1596
1597 /* save HT capabilities in the sta object */
1598 memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
1599 if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap))
1600 {
1601 pstat->flags |= WLAN_STA_HT;
1602
1603 pstat->flags |= WLAN_STA_WME;
1604
1605 memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct ieee80211_ht_cap));
1606
1607 } else
1608 pstat->flags &= ~WLAN_STA_HT;
1609
1610 if ((pmlmepriv->htpriv.ht_option == false) && (pstat->flags&WLAN_STA_HT))
1611 {
1612 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1613 goto OnAssocReq23aFail;
1614 }
1615
1616 if ((pstat->flags & WLAN_STA_HT) &&
1617 ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
1618 (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP)))
1619 {
1620 DBG_8723A("HT: " MAC_FMT " tried to "
1621 "use TKIP with HT association\n", MAC_ARG(pstat->hwaddr));
1622
1623 /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
1624 /* goto OnAssocReq23aFail; */
1625 }
1626
1627 /* */
1628 pstat->flags |= WLAN_STA_NONERP;
1629 for (i = 0; i < pstat->bssratelen; i++) {
1630 if ((pstat->bssrateset[i] & 0x7f) > 22) {
1631 pstat->flags &= ~WLAN_STA_NONERP;
1632 break;
1633 }
1634 }
1635
1636 if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1637 pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1638 else
1639 pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1640
1641 if (status != WLAN_STATUS_SUCCESS)
1642 goto OnAssocReq23aFail;
1643
1644#ifdef CONFIG_8723AU_P2P
1645 pstat->is_p2p_device = false;
1646 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
1647 {
1648 if ((p2pie = rtw_get_p2p_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset, NULL, &p2pielen)))
1649 {
1650 pstat->is_p2p_device = true;
1651 if ((p2p_status_code = (u8)process_assoc_req_p2p_ie23a(pwdinfo, pframe, pkt_len, pstat))>0)
1652 {
1653 pstat->p2p_status_code = p2p_status_code;
1654 status = WLAN_STATUS_CAPS_UNSUPPORTED;
1655 goto OnAssocReq23aFail;
1656 }
1657 }
1658#ifdef CONFIG_8723AU_P2P
1659 if (rtw_get_wfd_ie(pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset, pkt_len - sizeof(struct ieee80211_hdr_3addr) - ie_offset, wfd_ie, &wfd_ielen))
1660 {
1661 u8 attr_content[ 10 ] = { 0x00 };
1662 u32 attr_contentlen = 0;
1663
1664 DBG_8723A("[%s] WFD IE Found!!\n", __func__);
1665 rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
1666 if (attr_contentlen)
1667 {
1668 pwdinfo->wfd_info->peer_rtsp_ctrlport = get_unaligned_be16(attr_content + 2);
1669 DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
1670 }
1671 }
1672#endif
1673 }
1674 pstat->p2p_status_code = p2p_status_code;
1675#endif /* CONFIG_8723AU_P2P */
1676
1677 /* TODO: identify_proprietary_vendor_ie(); */
1678 /* Realtek proprietary IE */
1679 /* identify if this is Broadcom sta */
1680 /* identify if this is ralink sta */
1681 /* Customer proprietary IE */
1682
1683 /* get a unique AID */
1684 if (pstat->aid > 0) {
1685 DBG_8723A(" old AID %d\n", pstat->aid);
1686 } else {
1687 for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1688 if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
1689 break;
1690
1691 if (pstat->aid > NUM_STA)
1692 pstat->aid = NUM_STA;
1693 if (pstat->aid > pstapriv->max_num_sta) {
1694
1695 pstat->aid = 0;
1696
1697 DBG_8723A(" no room for more AIDs\n");
1698
1699 status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1700
1701 goto OnAssocReq23aFail;
1702
1703 } else {
1704 pstapriv->sta_aid[pstat->aid - 1] = pstat;
1705 DBG_8723A("allocate new AID = (%d)\n", pstat->aid);
1706 }
1707 }
1708
1709 pstat->state &= (~WIFI_FW_ASSOC_STATE);
1710 pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1711
1712 spin_lock_bh(&pstapriv->auth_list_lock);
1713 if (!list_empty(&pstat->auth_list)) {
1714 list_del_init(&pstat->auth_list);
1715 pstapriv->auth_list_cnt--;
1716 }
1717 spin_unlock_bh(&pstapriv->auth_list_lock);
1718
1719 spin_lock_bh(&pstapriv->asoc_list_lock);
1720 if (list_empty(&pstat->asoc_list)) {
1721 pstat->expire_to = pstapriv->expire_to;
1722 list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1723 pstapriv->asoc_list_cnt++;
1724 }
1725 spin_unlock_bh(&pstapriv->asoc_list_lock);
1726
1727 /* now the station is qualified to join our BSS... */
1728 if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) &&
1729 (WLAN_STATUS_SUCCESS == status)) {
1730#ifdef CONFIG_8723AU_AP_MODE
1731 /* 1 bss_cap_update & sta_info_update23a */
1732 bss_cap_update_on_sta_join23a(padapter, pstat);
1733 sta_info_update23a(padapter, pstat);
1734
1735 /* issue assoc rsp before notify station join event. */
1736 if (ieee80211_is_assoc_req(frame_control))
1737 issue_asocrsp23a(padapter, status, pstat, WIFI_ASSOCRSP);
1738 else
1739 issue_asocrsp23a(padapter, status, pstat, WIFI_REASSOCRSP);
1740
1741 /* 2 - report to upper layer */
1742 DBG_8723A("indicate_sta_join_event to upper layer - hostapd\n");
1743 rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len);
1744
1745 /* 3-(1) report sta add event */
1746 report_add_sta_event23a(padapter, pstat->hwaddr, pstat->aid);
1747#endif
1748 }
1749
1750 return _SUCCESS;
1751
1752asoc_class2_error:
1753
1754#ifdef CONFIG_8723AU_AP_MODE
1755 issue_deauth23a(padapter, hdr->addr2, status);
1756#endif
1757
1758 return _FAIL;
1759
1760OnAssocReq23aFail:
1761
1762#ifdef CONFIG_8723AU_AP_MODE
1763 pstat->aid = 0;
1764 if (ieee80211_is_assoc_req(frame_control))
1765 issue_asocrsp23a(padapter, status, pstat, WIFI_ASSOCRSP);
1766 else
1767 issue_asocrsp23a(padapter, status, pstat, WIFI_REASSOCRSP);
1768#endif
1769
1770#endif /* CONFIG_8723AU_AP_MODE */
1771
1772 return _FAIL;
1773}
1774
1775unsigned int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1776{
1777 uint i;
1778 int res;
1779 unsigned short status;
1780 struct ndis_802_11_var_ies *pIE;
1781 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1782 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1783 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1784 struct sk_buff *skb = precv_frame->pkt;
1785 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1786 u8 *pframe = skb->data;
1787 uint pkt_len = skb->len;
1788
1789 DBG_8723A("%s\n", __func__);
1790
1791 /* check A1 matches or not */
1792 if (!ether_addr_equal(myid(&padapter->eeprompriv),
1793 ieee80211_get_DA(hdr)))
1794 return _SUCCESS;
1795
1796 if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1797 return _SUCCESS;
1798
1799 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1800 return _SUCCESS;
1801
1802 del_timer_sync(&pmlmeext->link_timer);
1803
1804 /* status */
1805 if ((status = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr) + 2))) > 0)
1806 {
1807 DBG_8723A("assoc reject, status code: %d\n", status);
1808 pmlmeinfo->state = WIFI_FW_NULL_STATE;
1809 res = -4;
1810 goto report_assoc_result;
1811 }
1812
1813 /* get capabilities */
1814 pmlmeinfo->capability = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr)));
1815
1816 /* set slot time */
1817 pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20;
1818
1819 /* AID */
1820 res = pmlmeinfo->aid = (int)(le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr) + 4))&0x3fff);
1821
1822 /* following are moved to join event callback function */
1823 /* to handle HT, WMM, rate adaptive, update MAC reg */
1824 /* for not to handle the synchronous IO in the tasklet */
1825 for (i = (6 + sizeof(struct ieee80211_hdr_3addr)); i < pkt_len;) {
1826 pIE = (struct ndis_802_11_var_ies *)(pframe + i);
1827
1828 switch (pIE->ElementID)
1829 {
1830 case _VENDOR_SPECIFIC_IE_:
1831 if (!memcmp(pIE->data, WMM_PARA_OUI23A, 6))/* WMM */
1832 WMM_param_handler23a(padapter, pIE);
1833#if defined(CONFIG_8723AU_P2P)
1834 else if (!memcmp(pIE->data, WFD_OUI23A, 4)) { /* WFD */
1835 DBG_8723A("[%s] Found WFD IE\n", __func__);
1836 WFD_info_handler(padapter, pIE);
1837 }
1838#endif
1839 break;
1840
1841 case _HT_CAPABILITY_IE_: /* HT caps */
1842 HT_caps_handler23a(padapter, pIE);
1843 break;
1844
1845 case _HT_EXTRA_INFO_IE_: /* HT info */
1846 HT_info_handler23a(padapter, pIE);
1847 break;
1848
1849 case _ERPINFO_IE_:
1850 ERP_IE_handler23a(padapter, pIE);
1851
1852 default:
1853 break;
1854 }
1855
1856 i += (pIE->Length + 2);
1857 }
1858
1859 pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
1860 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1861
1862 /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1863 UpdateBrateTbl23a(padapter, pmlmeinfo->network.SupportedRates);
1864
1865report_assoc_result:
1866 pmlmepriv->assoc_rsp_len = 0;
1867 if (res > 0) {
1868 kfree(pmlmepriv->assoc_rsp);
1869 pmlmepriv->assoc_rsp = kmalloc(pkt_len, GFP_ATOMIC);
1870 if (pmlmepriv->assoc_rsp) {
1871 memcpy(pmlmepriv->assoc_rsp, pframe, pkt_len);
1872 pmlmepriv->assoc_rsp_len = pkt_len;
1873 }
1874 } else
1875 kfree(pmlmepriv->assoc_rsp);
1876
1877 report_join_res23a(padapter, res);
1878
1879 return _SUCCESS;
1880}
1881
1882unsigned int OnDeAuth23a(struct rtw_adapter *padapter,
1883 struct recv_frame *precv_frame)
1884{
1885 unsigned short reason;
1886 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1887 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1888 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1889 struct sk_buff *skb = precv_frame->pkt;
1890 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1891 u8 *pframe = skb->data;
1892#ifdef CONFIG_8723AU_P2P
1893 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1894#endif /* CONFIG_8723AU_P2P */
1895
1896 /* check A3 */
1897 if (!ether_addr_equal(hdr->addr3, get_my_bssid23a(&pmlmeinfo->network)))
1898 return _SUCCESS;
1899
1900#ifdef CONFIG_8723AU_P2P
1901 if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
1902 mod_timer(&pwdinfo->reset_ch_sitesurvey,
1903 jiffies + msecs_to_jiffies(10));
1904 }
1905#endif /* CONFIG_8723AU_P2P */
1906
1907 reason = le16_to_cpu(*(unsigned short *)(pframe + sizeof(struct ieee80211_hdr_3addr)));
1908
1909 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1910
1911#ifdef CONFIG_8723AU_AP_MODE
1912 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
1913 struct sta_info *psta;
1914 struct sta_priv *pstapriv = &padapter->stapriv;
1915
1916 DBG_8723A_LEVEL(_drv_always_, "ap recv deauth reason code(%d) "
1917 "sta:%pM\n", reason, hdr->addr2);
1918
1919 psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
1920 if (psta) {
1921 u8 updated = 0;
1922
1923 spin_lock_bh(&pstapriv->asoc_list_lock);
1924 if (!list_empty(&psta->asoc_list)) {
1925 list_del_init(&psta->asoc_list);
1926 pstapriv->asoc_list_cnt--;
1927 updated = ap_free_sta23a(padapter, psta,
1928 false, reason);
1929 }
1930 spin_unlock_bh(&pstapriv->asoc_list_lock);
1931
1932 associated_clients_update23a(padapter, updated);
1933 }
1934
1935 return _SUCCESS;
1936 }
1937 else
1938#endif
1939 {
1940 DBG_8723A_LEVEL(_drv_always_, "sta recv deauth reason code(%d) "
1941 "sta:%pM\n", reason, hdr->addr3);
1942
1943 receive_disconnect23a(padapter, hdr->addr3, reason);
1944 }
1945 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1946 return _SUCCESS;
1947}
1948
1949unsigned int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
1950{
1951 unsigned short reason;
1952 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1953 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1954 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1955 struct sk_buff *skb = precv_frame->pkt;
1956 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1957 u8 *pframe = skb->data;
1958#ifdef CONFIG_8723AU_P2P
1959 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1960#endif /* CONFIG_8723AU_P2P */
1961
1962 /* check A3 */
1963 if (!ether_addr_equal(hdr->addr3, get_my_bssid23a(&pmlmeinfo->network)))
1964 return _SUCCESS;
1965
1966#ifdef CONFIG_8723AU_P2P
1967 if (pwdinfo->rx_invitereq_info.scan_op_ch_only)
1968 {
1969 mod_timer(&pwdinfo->reset_ch_sitesurvey,
1970 jiffies + msecs_to_jiffies(10));
1971 }
1972#endif /* CONFIG_8723AU_P2P */
1973
1974 reason = le16_to_cpu(*(unsigned short *)
1975 (pframe + sizeof(struct ieee80211_hdr_3addr)));
1976
1977 DBG_8723A("%s Reason code(%d)\n", __func__, reason);
1978
1979#ifdef CONFIG_8723AU_AP_MODE
1980 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1981 struct sta_info *psta;
1982 struct sta_priv *pstapriv = &padapter->stapriv;
1983
1984 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason code(%d)"
1985 " sta:%pM\n", reason, hdr->addr2);
1986
1987 psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
1988 if (psta) {
1989 u8 updated = 0;
1990
1991 spin_lock_bh(&pstapriv->asoc_list_lock);
1992 if (!list_empty(&psta->asoc_list)) {
1993 list_del_init(&psta->asoc_list);
1994 pstapriv->asoc_list_cnt--;
1995 updated = ap_free_sta23a(padapter, psta,
1996 false, reason);
1997 }
1998 spin_unlock_bh(&pstapriv->asoc_list_lock);
1999
2000 associated_clients_update23a(padapter, updated);
2001 }
2002
2003 return _SUCCESS;
2004 }
2005 else
2006#endif
2007 {
2008 DBG_8723A_LEVEL(_drv_always_, "ap recv disassoc reason "
2009 "code(%d) sta:%pM\n", reason, hdr->addr3);
2010
2011 receive_disconnect23a(padapter, hdr->addr3, reason);
2012 }
2013 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
2014 return _SUCCESS;
2015}
2016
2017unsigned int OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2018{
2019 DBG_8723A("%s\n", __func__);
2020 return _SUCCESS;
2021}
2022
2023unsigned int on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2024{
2025 return _FAIL;
2026}
2027
2028unsigned int OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2029{
2030 return _SUCCESS;
2031}
2032
2033unsigned int OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2034{
2035 return _SUCCESS;
2036}
2037
2038unsigned int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
2039{
2040 u8 *addr;
2041 struct sta_info *psta = NULL;
2042 struct recv_reorder_ctrl *preorder_ctrl;
2043 unsigned char *frame_body;
2044 unsigned char category, action;
2045 unsigned short tid, status, reason_code = 0;
2046 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2047 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2048 struct sk_buff *skb = precv_frame->pkt;
2049 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2050 u8 *pframe = skb->data;
2051 struct sta_priv *pstapriv = &padapter->stapriv;
2052
2053 /* check RA matches or not */
2054 if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
2055 return _SUCCESS;
2056
2057 DBG_8723A("%s\n", __func__);
2058
2059 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
2060 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
2061 return _SUCCESS;
2062
2063 addr = hdr->addr2;
2064 psta = rtw_get_stainfo23a(pstapriv, addr);
2065
2066 if (!psta)
2067 return _SUCCESS;
2068
2069 frame_body = (unsigned char *)
2070 (pframe + sizeof(struct ieee80211_hdr_3addr));
2071
2072 category = frame_body[0];
2073 if (category == WLAN_CATEGORY_BACK) { /* representing Block Ack */
2074 if (!pmlmeinfo->HT_enable)
2075 return _SUCCESS;
2076 action = frame_body[1];
2077 DBG_8723A("%s, action =%d\n", __func__, action);
2078 switch (action) {
2079 case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
2080 memcpy(&pmlmeinfo->ADDBA_req, &frame_body[2],
2081 sizeof(struct ADDBA_request));
2082 process_addba_req23a(padapter,
2083 (u8 *)&pmlmeinfo->ADDBA_req, addr);
2084 if (pmlmeinfo->bAcceptAddbaReq == true)
2085 issue_action_BA23a(padapter, addr,
2086 WLAN_ACTION_ADDBA_RESP, 0);
2087 else {
2088 /* reject ADDBA Req */
2089 issue_action_BA23a(padapter, addr,
2090 WLAN_ACTION_ADDBA_RESP, 37);
2091 }
2092 break;
2093 case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
2094 status = get_unaligned_le16(&frame_body[3]);
2095 tid = ((frame_body[5] >> 2) & 0x7);
2096 if (status == 0) { /* successful */
2097 DBG_8723A("agg_enable for TID =%d\n", tid);
2098 psta->htpriv.agg_enable_bitmap |= 1 << tid;
2099 psta->htpriv.candidate_tid_bitmap &=
2100 ~CHKBIT(tid);
2101 } else
2102 psta->htpriv.agg_enable_bitmap &= ~CHKBIT(tid);
2103 break;
2104
2105 case WLAN_ACTION_DELBA: /* DELBA */
2106 if ((frame_body[3] & BIT(3)) == 0) {
2107 psta->htpriv.agg_enable_bitmap &=
2108 ~(1 << ((frame_body[3] >> 4) & 0xf));
2109 psta->htpriv.candidate_tid_bitmap &=
2110 ~(1 << ((frame_body[3] >> 4) & 0xf));
2111
2112 /* reason_code = frame_body[4] | (frame_body[5] << 8); */
2113 reason_code = get_unaligned_le16(&frame_body[4]);
2114 } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
2115 tid = (frame_body[3] >> 4) & 0x0F;
2116
2117 preorder_ctrl = &psta->recvreorder_ctrl[tid];
2118 preorder_ctrl->enable = false;
2119 preorder_ctrl->indicate_seq = 0xffff;
2120 }
2121
2122 DBG_8723A("%s(): DELBA: %x(%x)\n", __func__,
2123 pmlmeinfo->agg_enable_bitmap, reason_code);
2124 /* todo: how to notify the host while receiving
2125 DELETE BA */
2126 break;
2127 default:
2128 break;
2129 }
2130 }
2131 return _SUCCESS;
2132}
2133
2134#ifdef CONFIG_8723AU_P2P
2135
2136static int get_reg_classes_full_count(struct p2p_channels channel_list) {
2137 int cnt = 0;
2138 int i;
2139
2140 for (i = 0; i < channel_list.reg_classes; i++)
2141 cnt += channel_list.reg_class[i].channels;
2142
2143 return cnt;
2144}
2145
2146void issue_p2p_GO_request23a(struct rtw_adapter *padapter, u8* raddr)
2147{
2148 unsigned char category = WLAN_CATEGORY_PUBLIC;
2149 u8 action = P2P_PUB_ACTION_ACTION;
2150 u32 p2poui = cpu_to_be32(P2POUI);
2151 u8 oui_subtype = P2P_GO_NEGO_REQ;
2152 u8 wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
2153 u8 wpsielen = 0, p2pielen = 0;
2154 u16 len_channellist_attr = 0;
2155#ifdef CONFIG_8723AU_P2P
2156 u32 wfdielen = 0;
2157#endif /* CONFIG_8723AU_P2P */
2158
2159 struct xmit_frame *pmgntframe;
2160 struct pkt_attrib *pattrib;
2161 unsigned char *pframe;
2162 struct ieee80211_hdr *pwlanhdr;
2163 unsigned short *fctrl;
2164 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2165 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2166 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2167
2168 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
2169 return;
2170
2171 DBG_8723A("[%s] In\n", __func__);
2172 /* update attribute */
2173 pattrib = &pmgntframe->attrib;
2174 update_mgntframe_attrib23a(padapter, pattrib);
2175
2176 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2177
2178 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2179 pwlanhdr = (struct ieee80211_hdr *)pframe;
2180
2181 fctrl = &pwlanhdr->frame_control;
2182 *fctrl = 0;
2183
2184 ether_addr_copy(pwlanhdr->addr1, raddr);
2185 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
2186 ether_addr_copy(pwlanhdr->addr3, myid(&padapter->eeprompriv));
2187
2188 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2189 pmlmeext->mgnt_seq++;
2190 SetFrameSubType(pframe, WIFI_ACTION);
2191
2192 pframe += sizeof(struct ieee80211_hdr_3addr);
2193 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2194
2195 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
2196 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
2197 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
2198 &pattrib->pktlen);
2199 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
2200 pwdinfo->negotiation_dialog_token = 1; /*Initialize the dialog value*/
2201 pframe = rtw_set_fixed_ie23a(pframe, 1,
2202 &pwdinfo->negotiation_dialog_token,
2203 &pattrib->pktlen);
2204
2205 /* WPS Section */
2206 wpsielen = 0;
2207 /* WPS OUI */
2208 *(u32*) (wpsie) = cpu_to_be32(WPSOUI);
2209 wpsielen += 4;
2210
2211 /* WPS version */
2212 /* Type: */
2213 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
2214 wpsielen += 2;
2215
2216 /* Length: */
2217 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
2218 wpsielen += 2;
2219
2220 /* Value: */
2221 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
2222
2223 /* Device Password ID */
2224 /* Type: */
2225 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
2226 wpsielen += 2;
2227
2228 /* Length: */
2229 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
2230 wpsielen += 2;
2231
2232 /* Value: */
2233
2234 if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN)
2235 {
2236 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
2237 }
2238 else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN)
2239 {
2240 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
2241 }
2242 else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)
2243 {
2244 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
2245 }
2246
2247 wpsielen += 2;
2248
2249 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
2250
2251 /* P2P IE Section. */
2252
2253 /* P2P OUI */
2254 p2pielen = 0;
2255 p2pie[p2pielen++] = 0x50;
2256 p2pie[p2pielen++] = 0x6F;
2257 p2pie[p2pielen++] = 0x9A;
2258 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
2259
2260 /* Commented by Albert 20110306 */
2261 /* According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes */
2262 /* 1. P2P Capability */
2263 /* 2. Group Owner Intent */
2264 /* 3. Configuration Timeout */
2265 /* 4. Listen Channel */
2266 /* 5. Extended Listen Timing */
2267 /* 6. Intended P2P Interface Address */
2268 /* 7. Channel List */
2269 /* 8. P2P Device Info */
2270 /* 9. Operating Channel */
2271
2272 /* P2P Capability */
2273 /* Type: */
2274 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
2275
2276 /* Length: */
2277 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
2278 p2pielen += 2;
2279
2280 /* Value: */
2281 /* Device Capability Bitmap, 1 byte */
2282 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
2283
2284 /* Group Capability Bitmap, 1 byte */
2285 if (pwdinfo->persistent_supported)
2286 {
2287 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
2288 }
2289 else
2290 {
2291 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
2292 }
2293
2294 /* Group Owner Intent */
2295 /* Type: */
2296 p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
2297
2298 /* Length: */
2299 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
2300 p2pielen += 2;
2301
2302 /* Value: */
2303 /* Todo the tie breaker bit. */
2304 p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
2305
2306 /* Configuration Timeout */
2307 /* Type: */
2308 p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
2309
2310 /* Length: */
2311 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
2312 p2pielen += 2;
2313
2314 /* Value: */
2315 p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
2316 p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
2317
2318 /* Listen Channel */
2319 /* Type: */
2320 p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
2321
2322 /* Length: */
2323 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
2324 p2pielen += 2;
2325
2326 /* Value: */
2327 /* Country String */
2328 p2pie[p2pielen++] = 'X';
2329 p2pie[p2pielen++] = 'X';
2330
2331 /* The third byte should be set to 0x04. */
2332 /* Described in the "Operating Channel Attribute" section. */
2333 p2pie[p2pielen++] = 0x04;
2334
2335 /* Operating Class */
2336 p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
2337
2338 /* Channel Number */
2339 p2pie[p2pielen++] = pwdinfo->listen_channel; /* listening channel number */
2340
2341 /* Extended Listen Timing ATTR */
2342 /* Type: */
2343 p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
2344
2345 /* Length: */
2346 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004);
2347 p2pielen += 2;
2348
2349 /* Value: */
2350 /* Availability Period */
2351 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
2352 p2pielen += 2;
2353
2354 /* Availability Interval */
2355 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
2356 p2pielen += 2;
2357
2358 /* Intended P2P Interface Address */
2359 /* Type: */
2360 p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
2361
2362 /* Length: */
2363 *(u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2364 p2pielen += 2;
2365
2366 /* Value: */
2367 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2368 p2pielen += ETH_ALEN;
2369
2370 /* Channel List */
2371 /* Type: */
2372 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2373
2374 /* Length: */
2375 /* Country String(3) */
2376 /* + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
2377 /* + number of channels in all classes */
2378 len_channellist_attr = 3
2379 + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes)
2380 + get_reg_classes_full_count(pmlmeext->channel_list);
2381
2382 *(u16*) (p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2383 p2pielen += 2;
2384
2385 /* Value: */
2386 /* Country String */
2387 p2pie[p2pielen++] = 'X';
2388 p2pie[p2pielen++] = 'X';
2389
2390 /* The third byte should be set to 0x04. */
2391 /* Described in the "Operating Channel Attribute" section. */
2392 p2pie[p2pielen++] = 0x04;
2393
2394 /* Channel Entry List */
2395
2396 {
2397 int i, j;
2398 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2399 /* Operating Class */
2400 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2401
2402 /* Number of Channels */
2403 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2404
2405 /* Channel List */
2406 for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2407 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2408 }
2409 }
2410 }
2411
2412 /* Device Info */
2413 /* Type: */
2414 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2415
2416 /* Length: */
2417 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2418 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2419 *(u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
2420 p2pielen += 2;
2421
2422 /* Value: */
2423 /* P2P Device Address */
2424 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2425 p2pielen += ETH_ALEN;
2426
2427 /* Config Method */
2428 /* This field should be big endian. Noted by P2P specification. */
2429
2430 *(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
2431
2432 p2pielen += 2;
2433
2434 /* Primary Device Type */
2435 /* Category ID */
2436 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
2437 p2pielen += 2;
2438
2439 /* OUI */
2440 *(u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI);
2441 p2pielen += 4;
2442
2443 /* Sub Category ID */
2444 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
2445 p2pielen += 2;
2446
2447 /* Number of Secondary Device Types */
2448 p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
2449
2450 /* Device Name */
2451 /* Type: */
2452 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
2453 p2pielen += 2;
2454
2455 /* Length: */
2456 *(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
2457 p2pielen += 2;
2458
2459 /* Value: */
2460 memcpy(p2pie + p2pielen, pwdinfo->device_name,
2461 pwdinfo->device_name_len);
2462 p2pielen += pwdinfo->device_name_len;
2463
2464 /* Operating Channel */
2465 /* Type: */
2466 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2467
2468 /* Length: */
2469 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
2470 p2pielen += 2;
2471
2472 /* Value: */
2473 /* Country String */
2474 p2pie[p2pielen++] = 'X';
2475 p2pie[p2pielen++] = 'X';
2476
2477 /* The third byte should be set to 0x04. */
2478 /* Described in the "Operating Channel Attribute" section. */
2479 p2pie[p2pielen++] = 0x04;
2480
2481 /* Operating Class */
2482 if (pwdinfo->operating_channel <= 14)
2483 {
2484 /* Operating Class */
2485 p2pie[p2pielen++] = 0x51;
2486 }
2487 else if ((pwdinfo->operating_channel >= 36) && (pwdinfo->operating_channel <= 48))
2488 {
2489 /* Operating Class */
2490 p2pie[p2pielen++] = 0x73;
2491 }
2492 else
2493 {
2494 /* Operating Class */
2495 p2pie[p2pielen++] = 0x7c;
2496 }
2497
2498 /* Channel Number */
2499 p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
2500
2501 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);
2502
2503#ifdef CONFIG_8723AU_P2P
2504 wfdielen = build_nego_req_wfd_ie(pwdinfo, pframe);
2505 pframe += wfdielen;
2506 pattrib->pktlen += wfdielen;
2507#endif /* CONFIG_8723AU_P2P */
2508
2509 pattrib->last_txcmdsz = pattrib->pktlen;
2510
2511 dump_mgntframe23a(padapter, pmgntframe);
2512
2513 return;
2514}
2515
2516static void issue_p2p_GO_response(struct rtw_adapter *padapter, u8* raddr, u8* frame_body, uint len, u8 result)
2517{
2518
2519 unsigned char category = WLAN_CATEGORY_PUBLIC;
2520 u8 action = P2P_PUB_ACTION_ACTION;
2521 u32 p2poui = cpu_to_be32(P2POUI);
2522 u8 oui_subtype = P2P_GO_NEGO_RESP;
2523 u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
2524 u8 p2pielen = 0;
2525 uint wpsielen = 0;
2526 u16 wps_devicepassword_id = 0x0000;
2527 uint wps_devicepassword_id_len = 0;
2528 u16 len_channellist_attr = 0;
2529 int i, j;
2530 struct xmit_frame *pmgntframe;
2531 struct pkt_attrib *pattrib;
2532 unsigned char *pframe;
2533 struct ieee80211_hdr *pwlanhdr;
2534 unsigned short *fctrl;
2535 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2536 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2537 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2538#ifdef CONFIG_8723AU_P2P
2539 u32 wfdielen = 0;
2540#endif /* CONFIG_8723AU_P2P */
2541
2542 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
2543 return;
2544
2545 DBG_8723A("[%s] In, result = %d\n", __func__, result);
2546 /* update attribute */
2547 pattrib = &pmgntframe->attrib;
2548 update_mgntframe_attrib23a(padapter, pattrib);
2549
2550 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2551
2552 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2553 pwlanhdr = (struct ieee80211_hdr *)pframe;
2554
2555 fctrl = &pwlanhdr->frame_control;
2556 *fctrl = 0;
2557
2558 ether_addr_copy(pwlanhdr->addr1, raddr);
2559 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
2560 ether_addr_copy(pwlanhdr->addr3, myid(&padapter->eeprompriv));
2561
2562 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2563 pmlmeext->mgnt_seq++;
2564 SetFrameSubType(pframe, WIFI_ACTION);
2565
2566 pframe += sizeof(struct ieee80211_hdr_3addr);
2567 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2568
2569 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
2570 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
2571 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
2572 &pattrib->pktlen);
2573 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
2574 /* The Dialog Token of provisioning discovery request frame. */
2575 pwdinfo->negotiation_dialog_token = frame_body[7];
2576 pframe = rtw_set_fixed_ie23a(pframe, 1,
2577 &pwdinfo->negotiation_dialog_token,
2578 &pattrib->pktlen);
2579
2580 /* Commented by Albert 20110328 */
2581 /* Try to get the device password ID from the WPS IE of group
2582 negotiation request frame */
2583 /* WiFi Direct test plan 5.1.15 */
2584 rtw_get_wps_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
2585 len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
2586 rtw_get_wps_attr_content23a(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID,
2587 (u8 *)&wps_devicepassword_id,
2588 &wps_devicepassword_id_len);
2589 wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
2590
2591 memset(wpsie, 0x00, 255);
2592 wpsielen = 0;
2593
2594 /* WPS Section */
2595 wpsielen = 0;
2596 /* WPS OUI */
2597 *(u32*) (wpsie) = cpu_to_be32(WPSOUI);
2598 wpsielen += 4;
2599
2600 /* WPS version */
2601 /* Type: */
2602 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
2603 wpsielen += 2;
2604
2605 /* Length: */
2606 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
2607 wpsielen += 2;
2608
2609 /* Value: */
2610 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
2611
2612 /* Device Password ID */
2613 /* Type: */
2614 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
2615 wpsielen += 2;
2616
2617 /* Length: */
2618 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
2619 wpsielen += 2;
2620
2621 /* Value: */
2622 if (wps_devicepassword_id == WPS_DPID_USER_SPEC) {
2623 *(u16*) (wpsie + wpsielen) =
2624 cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
2625 } else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC) {
2626 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
2627 } else {
2628 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
2629 }
2630 wpsielen += 2;
2631
2632 /* Commented by Kurt 20120113 */
2633 /* If some device wants to do p2p handshake without sending prov_disc_req */
2634 /* We have to get peer_req_cm from here. */
2635 if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
2636 if (wps_devicepassword_id == WPS_DPID_USER_SPEC) {
2637 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2638 } else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC) {
2639 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2640 } else {
2641 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2642 }
2643 }
2644
2645 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
2646 (unsigned char *) wpsie, &pattrib->pktlen);
2647
2648 /* P2P IE Section. */
2649
2650 /* P2P OUI */
2651 p2pielen = 0;
2652 p2pie[p2pielen++] = 0x50;
2653 p2pie[p2pielen++] = 0x6F;
2654 p2pie[p2pielen++] = 0x9A;
2655 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
2656
2657 /* Commented by Albert 20100908 */
2658 /* According to the P2P Specification, the group negoitation
2659 response frame should contain 9 P2P attributes */
2660 /* 1. Status */
2661 /* 2. P2P Capability */
2662 /* 3. Group Owner Intent */
2663 /* 4. Configuration Timeout */
2664 /* 5. Operating Channel */
2665 /* 6. Intended P2P Interface Address */
2666 /* 7. Channel List */
2667 /* 8. Device Info */
2668 /* 9. Group ID (Only GO) */
2669
2670 /* ToDo: */
2671
2672 /* P2P Status */
2673 /* Type: */
2674 p2pie[p2pielen++] = P2P_ATTR_STATUS;
2675
2676 /* Length: */
2677 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
2678 p2pielen += 2;
2679
2680 /* Value: */
2681 p2pie[p2pielen++] = result;
2682
2683 /* P2P Capability */
2684 /* Type: */
2685 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
2686
2687 /* Length: */
2688 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
2689 p2pielen += 2;
2690
2691 /* Value: */
2692 /* Device Capability Bitmap, 1 byte */
2693
2694 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
2695 /* Commented by Albert 2011/03/08 */
2696 /* According to the P2P specification */
2697 /* if the sending device will be client, the P2P
2698 Capability should be reserved of group negotation
2699 response frame */
2700 p2pie[p2pielen++] = 0;
2701 } else {
2702 /* Be group owner or meet the error case */
2703 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
2704 }
2705
2706 /* Group Capability Bitmap, 1 byte */
2707 if (pwdinfo->persistent_supported) {
2708 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN |
2709 P2P_GRPCAP_PERSISTENT_GROUP;
2710 } else {
2711 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
2712 }
2713
2714 /* Group Owner Intent */
2715 /* Type: */
2716 p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
2717
2718 /* Length: */
2719 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
2720 p2pielen += 2;
2721
2722 /* Value: */
2723 if (pwdinfo->peer_intent & 0x01) {
2724 /* Peer's tie breaker bit is 1, our tie breaker
2725 bit should be 0 */
2726 p2pie[p2pielen++] = (pwdinfo->intent << 1);
2727 } else {
2728 /* Peer's tie breaker bit is 0, our tie breaker bit
2729 should be 1 */
2730 p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
2731 }
2732
2733 /* Configuration Timeout */
2734 /* Type: */
2735 p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
2736
2737 /* Length: */
2738 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
2739 p2pielen += 2;
2740
2741 /* Value: */
2742 /* 2 seconds needed to be the P2P GO */
2743 p2pie[p2pielen++] = 200;
2744 /* 2 seconds needed to be the P2P Client */
2745 p2pie[p2pielen++] = 200;
2746
2747 /* Operating Channel */
2748 /* Type: */
2749 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2750
2751 /* Length: */
2752 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
2753 p2pielen += 2;
2754
2755 /* Value: */
2756 /* Country String */
2757 p2pie[p2pielen++] = 'X';
2758 p2pie[p2pielen++] = 'X';
2759
2760 /* The third byte should be set to 0x04. */
2761 /* Described in the "Operating Channel Attribute" section. */
2762 p2pie[p2pielen++] = 0x04;
2763
2764 /* Operating Class */
2765 if (pwdinfo->operating_channel <= 14) {
2766 /* Operating Class */
2767 p2pie[p2pielen++] = 0x51;
2768 } else if ((pwdinfo->operating_channel >= 36) &&
2769 (pwdinfo->operating_channel <= 48)) {
2770 /* Operating Class */
2771 p2pie[p2pielen++] = 0x73;
2772 } else {
2773 /* Operating Class */
2774 p2pie[p2pielen++] = 0x7c;
2775 }
2776
2777 /* Channel Number */
2778 /* operating channel number */
2779 p2pie[p2pielen++] = pwdinfo->operating_channel;
2780
2781 /* Intended P2P Interface Address */
2782 /* Type: */
2783 p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
2784
2785 /* Length: */
2786 *(u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2787 p2pielen += 2;
2788
2789 /* Value: */
2790 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2791 p2pielen += ETH_ALEN;
2792
2793 /* Channel List */
2794 /* Type: */
2795 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2796
2797 /* Country String(3) */
2798 /* + (Operating Class (1) + Number of Channels(1)) *
2799 Operation Classes (?) */
2800 /* + number of channels in all classes */
2801 len_channellist_attr = 3 +
2802 (1 + 1) * (u16)pmlmeext->channel_list.reg_classes +
2803 get_reg_classes_full_count(pmlmeext->channel_list);
2804
2805 *(u16*) (p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2806
2807 p2pielen += 2;
2808
2809 /* Value: */
2810 /* Country String */
2811 p2pie[p2pielen++] = 'X';
2812 p2pie[p2pielen++] = 'X';
2813
2814 /* The third byte should be set to 0x04. */
2815 /* Described in the "Operating Channel Attribute" section. */
2816 p2pie[p2pielen++] = 0x04;
2817
2818 /* Channel Entry List */
2819
2820 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2821 /* Operating Class */
2822 p2pie[p2pielen++] =
2823 pmlmeext->channel_list.reg_class[j].reg_class;
2824
2825 /* Number of Channels */
2826 p2pie[p2pielen++] =
2827 pmlmeext->channel_list.reg_class[j].channels;
2828
2829 /* Channel List */
2830 for (i = 0;
2831 i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2832 p2pie[p2pielen++] =
2833 pmlmeext->channel_list.reg_class[j].channel[i];
2834 }
2835 }
2836
2837 /* Device Info */
2838 /* Type: */
2839 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2840
2841 /* Length: */
2842 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) +
2843 Primary Device Type (8bytes) */
2844 /* + NumofSecondDevType (1byte) + WPS Device Name ID field
2845 (2bytes) + WPS Device Name Len field (2bytes) */
2846 *(u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
2847 p2pielen += 2;
2848
2849 /* Value: */
2850 /* P2P Device Address */
2851 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2852 p2pielen += ETH_ALEN;
2853
2854 /* Config Method */
2855 /* This field should be big endian. Noted by P2P specification. */
2856
2857 *(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
2858
2859 p2pielen += 2;
2860
2861 /* Primary Device Type */
2862 /* Category ID */
2863 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
2864 p2pielen += 2;
2865
2866 /* OUI */
2867 *(u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI);
2868 p2pielen += 4;
2869
2870 /* Sub Category ID */
2871 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
2872 p2pielen += 2;
2873
2874 /* Number of Secondary Device Types */
2875 p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
2876
2877 /* Device Name */
2878 /* Type: */
2879 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
2880 p2pielen += 2;
2881
2882 /* Length: */
2883 *(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
2884 p2pielen += 2;
2885
2886 /* Value: */
2887 memcpy(p2pie + p2pielen, pwdinfo->device_name,
2888 pwdinfo->device_name_len);
2889 p2pielen += pwdinfo->device_name_len;
2890
2891 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2892 {
2893 /* Group ID Attribute */
2894 /* Type: */
2895 p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2896
2897 /* Length: */
2898 *(u16*) (p2pie + p2pielen) =
2899 cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
2900 p2pielen += 2;
2901
2902 /* Value: */
2903 /* p2P Device Address */
2904 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
2905 p2pielen += ETH_ALEN;
2906
2907 /* SSID */
2908 memcpy(p2pie + p2pielen, pwdinfo->nego_ssid,
2909 pwdinfo->nego_ssidlen);
2910 p2pielen += pwdinfo->nego_ssidlen;
2911
2912 }
2913
2914 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
2915 (unsigned char *) p2pie, &pattrib->pktlen);
2916
2917#ifdef CONFIG_8723AU_P2P
2918 wfdielen = build_nego_resp_wfd_ie(pwdinfo, pframe);
2919 pframe += wfdielen;
2920 pattrib->pktlen += wfdielen;
2921#endif /* CONFIG_8723AU_P2P */
2922
2923 pattrib->last_txcmdsz = pattrib->pktlen;
2924
2925 dump_mgntframe23a(padapter, pmgntframe);
2926
2927 return;
2928}
2929
2930static void issue_p2p_GO_confirm(struct rtw_adapter *padapter, u8* raddr,
2931 u8 result)
2932{
2933
2934 unsigned char category = WLAN_CATEGORY_PUBLIC;
2935 u8 action = P2P_PUB_ACTION_ACTION;
2936 u32 p2poui = cpu_to_be32(P2POUI);
2937 u8 oui_subtype = P2P_GO_NEGO_CONF;
2938 u8 p2pie[ 255 ] = { 0x00 };
2939 u8 p2pielen = 0;
2940 struct xmit_frame *pmgntframe;
2941 struct pkt_attrib *pattrib;
2942 unsigned char *pframe;
2943 struct ieee80211_hdr *pwlanhdr;
2944 unsigned short *fctrl;
2945 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2946 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2947 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
2948#ifdef CONFIG_8723AU_P2P
2949 u32 wfdielen = 0;
2950#endif /* CONFIG_8723AU_P2P */
2951
2952 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
2953 return;
2954
2955 DBG_8723A("[%s] In\n", __func__);
2956 /* update attribute */
2957 pattrib = &pmgntframe->attrib;
2958 update_mgntframe_attrib23a(padapter, pattrib);
2959
2960 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2961
2962 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2963 pwlanhdr = (struct ieee80211_hdr *)pframe;
2964
2965 fctrl = &pwlanhdr->frame_control;
2966 *fctrl = 0;
2967
2968 ether_addr_copy(pwlanhdr->addr1, raddr);
2969 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
2970 ether_addr_copy(pwlanhdr->addr3, myid(&padapter->eeprompriv));
2971
2972 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2973 pmlmeext->mgnt_seq++;
2974 SetFrameSubType(pframe, WIFI_ACTION);
2975
2976 pframe += sizeof(struct ieee80211_hdr_3addr);
2977 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2978
2979 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
2980 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
2981 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
2982 &pattrib->pktlen);
2983 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
2984 pframe = rtw_set_fixed_ie23a(pframe, 1,
2985 &pwdinfo->negotiation_dialog_token,
2986 &pattrib->pktlen);
2987 /* P2P OUI */
2988 p2pielen = 0;
2989 p2pie[p2pielen++] = 0x50;
2990 p2pie[p2pielen++] = 0x6F;
2991 p2pie[p2pielen++] = 0x9A;
2992 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
2993
2994 /* Commented by Albert 20110306 */
2995 /* According to the P2P Specification, the group negoitation
2996 request frame should contain 5 P2P attributes */
2997 /* 1. Status */
2998 /* 2. P2P Capability */
2999 /* 3. Operating Channel */
3000 /* 4. Channel List */
3001 /* 5. Group ID (if this WiFi is GO) */
3002
3003 /* P2P Status */
3004 /* Type: */
3005 p2pie[p2pielen++] = P2P_ATTR_STATUS;
3006
3007 /* Length: */
3008 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
3009 p2pielen += 2;
3010
3011 /* Value: */
3012 p2pie[p2pielen++] = result;
3013
3014 /* P2P Capability */
3015 /* Type: */
3016 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
3017
3018 /* Length: */
3019 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
3020 p2pielen += 2;
3021
3022 /* Value: */
3023 /* Device Capability Bitmap, 1 byte */
3024 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
3025
3026 /* Group Capability Bitmap, 1 byte */
3027 if (pwdinfo->persistent_supported) {
3028 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN |
3029 P2P_GRPCAP_PERSISTENT_GROUP;
3030 } else {
3031 p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
3032 }
3033
3034 /* Operating Channel */
3035 /* Type: */
3036 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
3037
3038 /* Length: */
3039 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
3040 p2pielen += 2;
3041
3042 /* Value: */
3043 /* Country String */
3044 p2pie[p2pielen++] = 'X';
3045 p2pie[p2pielen++] = 'X';
3046
3047 /* The third byte should be set to 0x04. */
3048 /* Described in the "Operating Channel Attribute" section. */
3049 p2pie[p2pielen++] = 0x04;
3050
3051 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
3052 if (pwdinfo->peer_operating_ch <= 14) {
3053 /* Operating Class */
3054 p2pie[p2pielen++] = 0x51;
3055 } else if ((pwdinfo->peer_operating_ch >= 36) &&
3056 (pwdinfo->peer_operating_ch <= 48)) {
3057 /* Operating Class */
3058 p2pie[p2pielen++] = 0x73;
3059 } else {
3060 /* Operating Class */
3061 p2pie[p2pielen++] = 0x7c;
3062 }
3063
3064 p2pie[p2pielen++] = pwdinfo->peer_operating_ch;
3065 } else {
3066 if (pwdinfo->operating_channel <= 14) {
3067 /* Operating Class */
3068 p2pie[p2pielen++] = 0x51;
3069 }
3070 else if ((pwdinfo->operating_channel >= 36) &&
3071 (pwdinfo->operating_channel <= 48)) {
3072 /* Operating Class */
3073 p2pie[p2pielen++] = 0x73;
3074 } else {
3075 /* Operating Class */
3076 p2pie[p2pielen++] = 0x7c;
3077 }
3078
3079 /* Channel Number */
3080 /* Use the listen channel as the operating channel */
3081 p2pie[p2pielen++] = pwdinfo->operating_channel;
3082 }
3083
3084 /* Channel List */
3085 /* Type: */
3086 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
3087
3088 /* Length: */
3089 *(u16*) (p2pie + p2pielen) =
3090 cpu_to_le16(pwdinfo->channel_list_attr_len);
3091 p2pielen += 2;
3092
3093 /* Value: */
3094 memcpy(p2pie + p2pielen, pwdinfo->channel_list_attr,
3095 pwdinfo->channel_list_attr_len);
3096 p2pielen += pwdinfo->channel_list_attr_len;
3097
3098 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
3099 /* Group ID Attribute */
3100 /* Type: */
3101 p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
3102
3103 /* Length: */
3104 *(u16*) (p2pie + p2pielen) =
3105 cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
3106 p2pielen += 2;
3107
3108 /* Value: */
3109 /* p2P Device Address */
3110 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
3111 p2pielen += ETH_ALEN;
3112
3113 /* SSID */
3114 memcpy(p2pie + p2pielen, pwdinfo->nego_ssid,
3115 pwdinfo->nego_ssidlen);
3116 p2pielen += pwdinfo->nego_ssidlen;
3117 }
3118
3119 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
3120 (unsigned char *)p2pie, &pattrib->pktlen);
3121
3122#ifdef CONFIG_8723AU_P2P
3123 wfdielen = build_nego_confirm_wfd_ie(pwdinfo, pframe);
3124 pframe += wfdielen;
3125 pattrib->pktlen += wfdielen;
3126#endif /* CONFIG_8723AU_P2P */
3127
3128 pattrib->last_txcmdsz = pattrib->pktlen;
3129
3130 dump_mgntframe23a(padapter, pmgntframe);
3131
3132 return;
3133}
3134
3135void issue_p2p_invitation_request23a(struct rtw_adapter *padapter, u8* raddr)
3136{
3137 unsigned char category = WLAN_CATEGORY_PUBLIC;
3138 u8 action = P2P_PUB_ACTION_ACTION;
3139 u32 p2poui = cpu_to_be32(P2POUI);
3140 u8 oui_subtype = P2P_INVIT_REQ;
3141 u8 p2pie[ 255 ] = { 0x00 };
3142 u8 p2pielen = 0;
3143 u8 dialogToken = 3;
3144 u16 len_channellist_attr = 0;
3145#ifdef CONFIG_8723AU_P2P
3146 u32 wfdielen = 0;
3147#endif /* CONFIG_8723AU_P2P */
3148 int i, j;
3149 struct xmit_frame *pmgntframe;
3150 struct pkt_attrib *pattrib;
3151 unsigned char *pframe;
3152 struct ieee80211_hdr *pwlanhdr;
3153 unsigned short *fctrl;
3154 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3155 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3156 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3157
3158 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
3159 return;
3160
3161 /* update attribute */
3162 pattrib = &pmgntframe->attrib;
3163 update_mgntframe_attrib23a(padapter, pattrib);
3164
3165 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3166
3167 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3168 pwlanhdr = (struct ieee80211_hdr *)pframe;
3169
3170 fctrl = &pwlanhdr->frame_control;
3171 *fctrl = 0;
3172
3173 ether_addr_copy(pwlanhdr->addr1, raddr);
3174 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3175 ether_addr_copy(pwlanhdr->addr3, raddr);
3176
3177 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3178 pmlmeext->mgnt_seq++;
3179 SetFrameSubType(pframe, WIFI_ACTION);
3180
3181 pframe += sizeof(struct ieee80211_hdr_3addr);
3182 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3183
3184 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
3185 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
3186 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
3187 &pattrib->pktlen);
3188 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
3189 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
3190
3191 /* P2P IE Section. */
3192
3193 /* P2P OUI */
3194 p2pielen = 0;
3195 p2pie[p2pielen++] = 0x50;
3196 p2pie[p2pielen++] = 0x6F;
3197 p2pie[p2pielen++] = 0x9A;
3198 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
3199
3200 /* Commented by Albert 20101011 */
3201 /* According to the P2P Specification, the P2P Invitation
3202 request frame should contain 7 P2P attributes */
3203 /* 1. Configuration Timeout */
3204 /* 2. Invitation Flags */
3205 /* 3. Operating Channel (Only GO) */
3206 /* 4. P2P Group BSSID (Should be included if I am the GO) */
3207 /* 5. Channel List */
3208 /* 6. P2P Group ID */
3209 /* 7. P2P Device Info */
3210
3211 /* Configuration Timeout */
3212 /* Type: */
3213 p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
3214
3215 /* Length: */
3216 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
3217 p2pielen += 2;
3218
3219 /* Value: */
3220 /* 2 seconds needed to be the P2P GO */
3221 p2pie[p2pielen++] = 200;
3222 /* 2 seconds needed to be the P2P Client */
3223 p2pie[p2pielen++] = 200;
3224
3225 /* Invitation Flags */
3226 /* Type: */
3227 p2pie[p2pielen++] = P2P_ATTR_INVITATION_FLAGS;
3228
3229 /* Length: */
3230 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
3231 p2pielen += 2;
3232
3233 /* Value: */
3234 p2pie[p2pielen++] = P2P_INVITATION_FLAGS_PERSISTENT;
3235
3236 /* Operating Channel */
3237 /* Type: */
3238 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
3239
3240 /* Length: */
3241 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
3242 p2pielen += 2;
3243
3244 /* Value: */
3245 /* Country String */
3246 p2pie[p2pielen++] = 'X';
3247 p2pie[p2pielen++] = 'X';
3248
3249 /* The third byte should be set to 0x04. */
3250 /* Described in the "Operating Channel Attribute" section. */
3251 p2pie[p2pielen++] = 0x04;
3252
3253 /* Operating Class */
3254 if (pwdinfo->invitereq_info.operating_ch <= 14)
3255 p2pie[p2pielen++] = 0x51;
3256 else if ((pwdinfo->invitereq_info.operating_ch >= 36) &&
3257 (pwdinfo->invitereq_info.operating_ch <= 48))
3258 p2pie[p2pielen++] = 0x73;
3259 else
3260 p2pie[p2pielen++] = 0x7c;
3261
3262 /* Channel Number */
3263 /* operating channel number */
3264 p2pie[p2pielen++] = pwdinfo->invitereq_info.operating_ch;
3265
3266 if (ether_addr_equal(myid(&padapter->eeprompriv),
3267 pwdinfo->invitereq_info.go_bssid)) {
3268 /* P2P Group BSSID */
3269 /* Type: */
3270 p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
3271
3272 /* Length: */
3273 *(u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
3274 p2pielen += 2;
3275
3276 /* Value: */
3277 /* P2P Device Address for GO */
3278 memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid,
3279 ETH_ALEN);
3280 p2pielen += ETH_ALEN;
3281 }
3282
3283 /* Channel List */
3284 /* Type: */
3285 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
3286
3287 /* Length: */
3288 /* Country String(3) */
3289 /* + (Operating Class (1) + Number of Channels(1)) *
3290 Operation Classes (?) */
3291 /* + number of channels in all classes */
3292 len_channellist_attr = 3 +
3293 (1 + 1) * (u16)pmlmeext->channel_list.reg_classes +
3294 get_reg_classes_full_count(pmlmeext->channel_list);
3295
3296 *(u16*) (p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
3297 p2pielen += 2;
3298
3299 /* Value: */
3300 /* Country String */
3301 p2pie[p2pielen++] = 'X';
3302 p2pie[p2pielen++] = 'X';
3303
3304 /* The third byte should be set to 0x04. */
3305 /* Described in the "Operating Channel Attribute" section. */
3306 p2pie[p2pielen++] = 0x04;
3307
3308 /* Channel Entry List */
3309 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3310 /* Operating Class */
3311 p2pie[p2pielen++] =
3312 pmlmeext->channel_list.reg_class[j].reg_class;
3313
3314 /* Number of Channels */
3315 p2pie[p2pielen++] =
3316 pmlmeext->channel_list.reg_class[j].channels;
3317
3318 /* Channel List */
3319 for (i = 0;
3320 i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3321 p2pie[p2pielen++] =
3322 pmlmeext->channel_list.reg_class[j].channel[i];
3323 }
3324 }
3325
3326 /* P2P Group ID */
3327 /* Type: */
3328 p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
3329
3330 /* Length: */
3331 *(u16*) (p2pie + p2pielen) =
3332 cpu_to_le16(6 + pwdinfo->invitereq_info.ssidlen);
3333 p2pielen += 2;
3334
3335 /* Value: */
3336 /* P2P Device Address for GO */
3337 memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
3338 p2pielen += ETH_ALEN;
3339
3340 /* SSID */
3341 memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid,
3342 pwdinfo->invitereq_info.ssidlen);
3343 p2pielen += pwdinfo->invitereq_info.ssidlen;
3344
3345 /* Device Info */
3346 /* Type: */
3347 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
3348
3349 /* Length: */
3350 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) +
3351 Primary Device Type (8bytes) */
3352 /* + NumofSecondDevType (1byte) + WPS Device Name ID field
3353 (2bytes) + WPS Device Name Len field (2bytes) */
3354 *(u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
3355 p2pielen += 2;
3356
3357 /* Value: */
3358 /* P2P Device Address */
3359 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
3360 p2pielen += ETH_ALEN;
3361
3362 /* Config Method */
3363 /* This field should be big endian. Noted by P2P specification. */
3364 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
3365 p2pielen += 2;
3366
3367 /* Primary Device Type */
3368 /* Category ID */
3369 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
3370 p2pielen += 2;
3371
3372 /* OUI */
3373 *(u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI);
3374 p2pielen += 4;
3375
3376 /* Sub Category ID */
3377 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
3378 p2pielen += 2;
3379
3380 /* Number of Secondary Device Types */
3381 p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
3382
3383 /* Device Name */
3384 /* Type: */
3385 *(u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
3386 p2pielen += 2;
3387
3388 /* Length: */
3389 *(u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
3390 p2pielen += 2;
3391
3392 /* Value: */
3393 memcpy(p2pie + p2pielen, pwdinfo->device_name,
3394 pwdinfo->device_name_len);
3395 p2pielen += pwdinfo->device_name_len;
3396
3397 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
3398 (unsigned char *) p2pie, &pattrib->pktlen);
3399
3400#ifdef CONFIG_8723AU_P2P
3401 wfdielen = build_invitation_req_wfd_ie(pwdinfo, pframe);
3402 pframe += wfdielen;
3403 pattrib->pktlen += wfdielen;
3404#endif /* CONFIG_8723AU_P2P */
3405
3406 pattrib->last_txcmdsz = pattrib->pktlen;
3407
3408 dump_mgntframe23a(padapter, pmgntframe);
3409
3410 return;
3411}
3412
3413void issue_p2p_invitation_response23a(struct rtw_adapter *padapter, u8 *raddr,
3414 u8 dialogToken, u8 status_code)
3415{
3416 unsigned char category = WLAN_CATEGORY_PUBLIC;
3417 u8 action = P2P_PUB_ACTION_ACTION;
3418 u32 p2poui = cpu_to_be32(P2POUI);
3419 u8 oui_subtype = P2P_INVIT_RESP;
3420 u8 p2pie[ 255 ] = { 0x00 };
3421 u8 p2pielen = 0;
3422 u16 len_channellist_attr = 0;
3423#ifdef CONFIG_8723AU_P2P
3424 u32 wfdielen = 0;
3425#endif /* CONFIG_8723AU_P2P */
3426 int i, j;
3427
3428 struct xmit_frame *pmgntframe;
3429 struct pkt_attrib *pattrib;
3430 unsigned char *pframe;
3431 struct ieee80211_hdr *pwlanhdr;
3432 unsigned short *fctrl;
3433 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3434 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3435 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3436
3437 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
3438 return;
3439
3440 /* update attribute */
3441 pattrib = &pmgntframe->attrib;
3442 update_mgntframe_attrib23a(padapter, pattrib);
3443
3444 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3445
3446 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3447 pwlanhdr = (struct ieee80211_hdr *)pframe;
3448
3449 fctrl = &pwlanhdr->frame_control;
3450 *fctrl = 0;
3451
3452 ether_addr_copy(pwlanhdr->addr1, raddr);
3453 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3454 ether_addr_copy(pwlanhdr->addr3, raddr);
3455
3456 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3457 pmlmeext->mgnt_seq++;
3458 SetFrameSubType(pframe, WIFI_ACTION);
3459
3460 pframe += sizeof(struct ieee80211_hdr_3addr);
3461 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3462
3463 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
3464 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
3465 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
3466 &pattrib->pktlen);
3467 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
3468 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
3469
3470 /* P2P IE Section. */
3471
3472 /* P2P OUI */
3473 p2pielen = 0;
3474 p2pie[p2pielen++] = 0x50;
3475 p2pie[p2pielen++] = 0x6F;
3476 p2pie[p2pielen++] = 0x9A;
3477 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
3478
3479 /* Commented by Albert 20101005 */
3480 /* According to the P2P Specification, the P2P Invitation
3481 response frame should contain 5 P2P attributes */
3482 /* 1. Status */
3483 /* 2. Configuration Timeout */
3484 /* 3. Operating Channel (Only GO) */
3485 /* 4. P2P Group BSSID (Only GO) */
3486 /* 5. Channel List */
3487
3488 /* P2P Status */
3489 /* Type: */
3490 p2pie[p2pielen++] = P2P_ATTR_STATUS;
3491
3492 /* Length: */
3493 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0001);
3494 p2pielen += 2;
3495
3496 /* Value: */
3497 /* When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE. */
3498 /* Sent the event receiving the P2P Invitation Req frame
3499 to DMP UI. */
3500 /* DMP had to compare the MAC address to find out the profile. */
3501 /* So, the WiFi driver will send the
3502 P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB. */
3503 /* If the UI found the corresponding profile, the WiFi driver
3504 sends the P2P Invitation Req */
3505 /* to NB to rebuild the persistent group. */
3506 p2pie[p2pielen++] = status_code;
3507
3508 /* Configuration Timeout */
3509 /* Type: */
3510 p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
3511
3512 /* Length: */
3513 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
3514 p2pielen += 2;
3515
3516 /* Value: */
3517 /* 2 seconds needed to be the P2P GO */
3518 p2pie[p2pielen++] = 200;
3519 /* 2 seconds needed to be the P2P Client */
3520 p2pie[p2pielen++] = 200;
3521
3522 if (status_code == P2P_STATUS_SUCCESS) {
3523 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
3524 /* The P2P Invitation request frame asks this
3525 Wi-Fi device to be the P2P GO */
3526 /* In this case, the P2P Invitation response
3527 frame should carry the two more P2P attributes. */
3528 /* First one is operating channel attribute. */
3529 /* Second one is P2P Group BSSID attribute. */
3530
3531 /* Operating Channel */
3532 /* Type: */
3533 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
3534
3535 /* Length: */
3536 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
3537 p2pielen += 2;
3538
3539 /* Value: */
3540 /* Country String */
3541 p2pie[p2pielen++] = 'X';
3542 p2pie[p2pielen++] = 'X';
3543
3544 /* The third byte should be set to 0x04. */
3545 /* Described in the "Operating Channel Attribute"
3546 section. */
3547 p2pie[p2pielen++] = 0x04;
3548
3549 /* Operating Class */
3550 /* Copy from SD7 */
3551 p2pie[p2pielen++] = 0x51;
3552
3553 /* Channel Number */
3554 /* operating channel number */
3555 p2pie[p2pielen++] = pwdinfo->operating_channel;
3556
3557 /* P2P Group BSSID */
3558 /* Type: */
3559 p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
3560
3561 /* Length: */
3562 *(u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
3563 p2pielen += 2;
3564
3565 /* Value: */
3566 /* P2P Device Address for GO */
3567 memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv),
3568 ETH_ALEN);
3569 p2pielen += ETH_ALEN;
3570 }
3571
3572 /* Channel List */
3573 /* Type: */
3574 p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
3575
3576 /* Length: */
3577 /* Country String(3) */
3578 /* + (Operating Class (1) + Number of Channels(1)) *
3579 Operation Classes (?) */
3580 /* + number of channels in all classes */
3581 len_channellist_attr = 3 +
3582 (1 + 1) * (u16)pmlmeext->channel_list.reg_classes +
3583 get_reg_classes_full_count(pmlmeext->channel_list);
3584
3585 *(u16*) (p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
3586 p2pielen += 2;
3587
3588 /* Value: */
3589 /* Country String */
3590 p2pie[p2pielen++] = 'X';
3591 p2pie[p2pielen++] = 'X';
3592
3593 /* The third byte should be set to 0x04. */
3594 /* Described in the "Operating Channel Attribute" section. */
3595 p2pie[p2pielen++] = 0x04;
3596
3597 /* Channel Entry List */
3598 for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3599 /* Operating Class */
3600 p2pie[p2pielen++] =
3601 pmlmeext->channel_list.reg_class[j].reg_class;
3602
3603 /* Number of Channels */
3604 p2pie[p2pielen++] =
3605 pmlmeext->channel_list.reg_class[j].channels;
3606
3607 /* Channel List */
3608 for (i = 0;
3609 i < pmlmeext->channel_list.reg_class[j].channels;
3610 i++) {
3611 p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3612 }
3613 }
3614 }
3615
3616 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
3617 (unsigned char *)p2pie, &pattrib->pktlen);
3618
3619#ifdef CONFIG_8723AU_P2P
3620 wfdielen = build_invitation_resp_wfd_ie(pwdinfo, pframe);
3621 pframe += wfdielen;
3622 pattrib->pktlen += wfdielen;
3623#endif /* CONFIG_8723AU_P2P */
3624
3625 pattrib->last_txcmdsz = pattrib->pktlen;
3626
3627 dump_mgntframe23a(padapter, pmgntframe);
3628
3629 return;
3630}
3631
3632void issue_p2p_provision_request23a(struct rtw_adapter *padapter, u8 *pssid,
3633 u8 ussidlen, u8 *pdev_raddr)
3634{
3635 unsigned char category = WLAN_CATEGORY_PUBLIC;
3636 u8 action = P2P_PUB_ACTION_ACTION;
3637 u8 dialogToken = 1;
3638 u32 p2poui = cpu_to_be32(P2POUI);
3639 u8 oui_subtype = P2P_PROVISION_DISC_REQ;
3640 u8 wpsie[100] = { 0x00 };
3641 u8 wpsielen = 0;
3642 u32 p2pielen = 0;
3643#ifdef CONFIG_8723AU_P2P
3644 u32 wfdielen = 0;
3645#endif /* CONFIG_8723AU_P2P */
3646 struct xmit_frame *pmgntframe;
3647 struct pkt_attrib *pattrib;
3648 unsigned char *pframe;
3649 struct ieee80211_hdr *pwlanhdr;
3650 unsigned short *fctrl;
3651 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3652 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3653 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3654
3655 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
3656 return;
3657
3658 DBG_8723A("[%s] In\n", __func__);
3659 /* update attribute */
3660 pattrib = &pmgntframe->attrib;
3661 update_mgntframe_attrib23a(padapter, pattrib);
3662
3663 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3664
3665 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3666 pwlanhdr = (struct ieee80211_hdr *)pframe;
3667
3668 fctrl = &pwlanhdr->frame_control;
3669 *fctrl = 0;
3670
3671 ether_addr_copy(pwlanhdr->addr1, pdev_raddr);
3672 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
3673 ether_addr_copy(pwlanhdr->addr3, pdev_raddr);
3674
3675 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3676 pmlmeext->mgnt_seq++;
3677 SetFrameSubType(pframe, WIFI_ACTION);
3678
3679 pframe += sizeof(struct ieee80211_hdr_3addr);
3680 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3681
3682 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
3683 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
3684 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
3685 &pattrib->pktlen);
3686 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
3687 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
3688
3689 p2pielen = build_prov_disc_request_p2p_ie23a(pwdinfo, pframe, pssid,
3690 ussidlen, pdev_raddr);
3691
3692 pframe += p2pielen;
3693 pattrib->pktlen += p2pielen;
3694
3695 wpsielen = 0;
3696 /* WPS OUI */
3697 *(u32*) (wpsie) = cpu_to_be32(WPSOUI);
3698 wpsielen += 4;
3699
3700 /* WPS version */
3701 /* Type: */
3702 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3703 wpsielen += 2;
3704
3705 /* Length: */
3706 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
3707 wpsielen += 2;
3708
3709 /* Value: */
3710 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
3711
3712 /* Config Method */
3713 /* Type: */
3714 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3715 wpsielen += 2;
3716
3717 /* Length: */
3718 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
3719 wpsielen += 2;
3720
3721 /* Value: */
3722 *(u16*) (wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);
3723 wpsielen += 2;
3724
3725 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
3726 (unsigned char *) wpsie, &pattrib->pktlen);
3727
3728#ifdef CONFIG_8723AU_P2P
3729 wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);
3730 pframe += wfdielen;
3731 pattrib->pktlen += wfdielen;
3732#endif /* CONFIG_8723AU_P2P */
3733
3734 pattrib->last_txcmdsz = pattrib->pktlen;
3735
3736 dump_mgntframe23a(padapter, pmgntframe);
3737
3738 return;
3739}
3740
3741static u8 is_matched_in_profilelist(u8 *peermacaddr,
3742 struct profile_info *profileinfo)
3743{
3744 u8 i, match_result = 0;
3745
3746 DBG_8723A("[%s] peermac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
3747 peermacaddr[0], peermacaddr[1], peermacaddr[2],
3748 peermacaddr[3], peermacaddr[4], peermacaddr[5]);
3749
3750 for (i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++) {
3751 DBG_8723A("[%s] profileinfo_mac = %.2X %.2X %.2X %.2X %.2X "
3752 "%.2X\n", __func__, profileinfo->peermac[0],
3753 profileinfo->peermac[1], profileinfo->peermac[2],
3754 profileinfo->peermac[3], profileinfo->peermac[4],
3755 profileinfo->peermac[5]);
3756 if (ether_addr_equal(peermacaddr, profileinfo->peermac)) {
3757 match_result = 1;
3758 DBG_8723A("[%s] Match!\n", __func__);
3759 break;
3760 }
3761 }
3762
3763 return match_result;
3764}
3765
3766void issue_probersp23a_p2p23a(struct rtw_adapter *padapter, unsigned char *da)
3767{
3768 struct xmit_frame *pmgntframe;
3769 struct pkt_attrib *pattrib;
3770 unsigned char *pframe;
3771 struct ieee80211_hdr *pwlanhdr;
3772 unsigned short *fctrl;
3773 unsigned char *mac;
3774 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3775 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3776 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3777 u16 beacon_interval = 100;
3778 u16 capInfo = 0;
3779 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3780 u8 wpsie[255] = { 0x00 };
3781 u32 wpsielen = 0, p2pielen = 0;
3782#ifdef CONFIG_8723AU_P2P
3783 u32 wfdielen = 0;
3784#endif /* CONFIG_8723AU_P2P */
3785 struct cfg80211_wifidirect_info *pcfg80211_wdinfo =
3786 &padapter->cfg80211_wdinfo;
3787 struct ieee80211_channel *ieee_ch =
3788 &pcfg80211_wdinfo->remain_on_ch_channel;
3789 u8 listen_channel =
3790 (u8)ieee80211_frequency_to_channel(ieee_ch->center_freq);
3791
3792 /* DBG_8723A("%s\n", __func__); */
3793
3794 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
3795 {
3796 return;
3797 }
3798
3799 /* update attribute */
3800 pattrib = &pmgntframe->attrib;
3801 update_mgntframe_attrib23a(padapter, pattrib);
3802
3803 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3804
3805 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3806 pwlanhdr = (struct ieee80211_hdr *)pframe;
3807
3808 mac = myid(&padapter->eeprompriv);
3809
3810 fctrl = &pwlanhdr->frame_control;
3811 *fctrl = 0;
3812 ether_addr_copy(pwlanhdr->addr1, da);
3813 ether_addr_copy(pwlanhdr->addr2, mac);
3814
3815 /* Use the device address for BSSID field. */
3816 ether_addr_copy(pwlanhdr->addr3, mac);
3817
3818 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3819 pmlmeext->mgnt_seq++;
3820 SetFrameSubType(fctrl, WIFI_PROBERSP);
3821
3822 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3823 pattrib->pktlen = pattrib->hdrlen;
3824 pframe += pattrib->hdrlen;
3825
3826 /* timestamp will be inserted by hardware */
3827 pframe += 8;
3828 pattrib->pktlen += 8;
3829
3830 /* beacon interval: 2 bytes */
3831 memcpy(pframe, (unsigned char *) &beacon_interval, 2);
3832 pframe += 2;
3833 pattrib->pktlen += 2;
3834
3835 /* capability info: 2 bytes */
3836 /* ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of
3837 WiFi Direct Spec) */
3838 capInfo |= cap_ShortPremble;
3839 capInfo |= cap_ShortSlot;
3840
3841 memcpy(pframe, (unsigned char *) &capInfo, 2);
3842 pframe += 2;
3843 pattrib->pktlen += 2;
3844
3845 /* SSID */
3846 pframe = rtw_set_ie23a(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid,
3847 &pattrib->pktlen);
3848
3849 /* supported rates... */
3850 /* Use the OFDM rate in the P2P probe response frame.
3851 (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
3852 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
3853 pwdinfo->support_rate, &pattrib->pktlen);
3854
3855 /* DS parameter set */
3856 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled &&
3857 listen_channel != 0) {
3858 pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)
3859 &listen_channel, &pattrib->pktlen);
3860 } else {
3861 pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)
3862 &pwdinfo->listen_channel,
3863 &pattrib->pktlen);
3864 }
3865
3866 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
3867 if (pmlmepriv->wps_probe_resp_ie &&
3868 pmlmepriv->p2p_probe_resp_ie) {
3869 /* WPS IE */
3870 memcpy(pframe, pmlmepriv->wps_probe_resp_ie,
3871 pmlmepriv->wps_probe_resp_ie_len);
3872 pattrib->pktlen += pmlmepriv->wps_probe_resp_ie_len;
3873 pframe += pmlmepriv->wps_probe_resp_ie_len;
3874
3875 /* P2P IE */
3876 memcpy(pframe, pmlmepriv->p2p_probe_resp_ie,
3877 pmlmepriv->p2p_probe_resp_ie_len);
3878 pattrib->pktlen += pmlmepriv->p2p_probe_resp_ie_len;
3879 pframe += pmlmepriv->p2p_probe_resp_ie_len;
3880 }
3881 } else {
3882
3883 /* Todo: WPS IE */
3884 /* Noted by Albert 20100907 */
3885 /* According to the WPS specification, all the WPS
3886 attribute is presented by Big Endian. */
3887
3888 wpsielen = 0;
3889 /* WPS OUI */
3890 *(u32*) (wpsie) = cpu_to_be32(WPSOUI);
3891 wpsielen += 4;
3892
3893 /* WPS version */
3894 /* Type: */
3895 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3896 wpsielen += 2;
3897
3898 /* Length: */
3899 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
3900 wpsielen += 2;
3901
3902 /* Value: */
3903 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
3904
3905 /* WiFi Simple Config State */
3906 /* Type: */
3907 *(u16*) (wpsie + wpsielen) =
3908 cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE);
3909 wpsielen += 2;
3910
3911 /* Length: */
3912 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
3913 wpsielen += 2;
3914
3915 /* Value: */
3916 wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG;
3917
3918 /* Response Type */
3919 /* Type: */
3920 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE);
3921 wpsielen += 2;
3922
3923 /* Length: */
3924 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
3925 wpsielen += 2;
3926
3927 /* Value: */
3928 wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
3929
3930 /* UUID-E */
3931 /* Type: */
3932 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
3933 wpsielen += 2;
3934
3935 /* Length: */
3936 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0010);
3937 wpsielen += 2;
3938
3939 /* Value: */
3940 memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
3941 wpsielen += 0x10;
3942
3943 /* Manufacturer */
3944 /* Type: */
3945 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER);
3946 wpsielen += 2;
3947
3948 /* Length: */
3949 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0007);
3950 wpsielen += 2;
3951
3952 /* Value: */
3953 memcpy(wpsie + wpsielen, "Realtek", 7);
3954 wpsielen += 7;
3955
3956 /* Model Name */
3957 /* Type: */
3958 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME);
3959 wpsielen += 2;
3960
3961 /* Length: */
3962 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0006);
3963 wpsielen += 2;
3964
3965 /* Value: */
3966 memcpy(wpsie + wpsielen, "8192CU", 6);
3967 wpsielen += 6;
3968
3969 /* Model Number */
3970 /* Type: */
3971 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER);
3972 wpsielen += 2;
3973
3974 /* Length: */
3975 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
3976 wpsielen += 2;
3977
3978 /* Value: */
3979 wpsie[ wpsielen++ ] = 0x31; /* character 1 */
3980
3981 /* Serial Number */
3982 /* Type: */
3983 *(u16*) (wpsie + wpsielen) =
3984 cpu_to_be16(WPS_ATTR_SERIAL_NUMBER);
3985 wpsielen += 2;
3986
3987 /* Length: */
3988 *(u16*) (wpsie + wpsielen) = cpu_to_be16(ETH_ALEN);
3989 wpsielen += 2;
3990
3991 /* Value: */
3992 memcpy(wpsie + wpsielen, "123456", ETH_ALEN);
3993 wpsielen += ETH_ALEN;
3994
3995 /* Primary Device Type */
3996 /* Type: */
3997 *(u16*) (wpsie + wpsielen) =
3998 cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
3999 wpsielen += 2;
4000
4001 /* Length: */
4002 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0008);
4003 wpsielen += 2;
4004
4005 /* Value: */
4006 /* Category ID */
4007 *(u16*) (wpsie + wpsielen) =
4008 cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
4009 wpsielen += 2;
4010
4011 /* OUI */
4012 *(u32*) (wpsie + wpsielen) = cpu_to_be32(WPSOUI);
4013 wpsielen += 4;
4014
4015 /* Sub Category ID */
4016 *(u16*) (wpsie + wpsielen) =
4017 cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
4018 wpsielen += 2;
4019
4020 /* Device Name */
4021 /* Type: */
4022 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
4023 wpsielen += 2;
4024
4025 /* Length: */
4026 *(u16*) (wpsie + wpsielen) =
4027 cpu_to_be16(pwdinfo->device_name_len);
4028 wpsielen += 2;
4029
4030 /* Value: */
4031 if (pwdinfo->device_name_len) {
4032 memcpy(wpsie + wpsielen, pwdinfo->device_name,
4033 pwdinfo->device_name_len);
4034 wpsielen += pwdinfo->device_name_len;
4035 }
4036
4037 /* Config Method */
4038 /* Type: */
4039 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
4040 wpsielen += 2;
4041
4042 /* Length: */
4043 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
4044 wpsielen += 2;
4045
4046 /* Value: */
4047 *(u16*) (wpsie + wpsielen) =
4048 cpu_to_be16(pwdinfo->supported_wps_cm);
4049 wpsielen += 2;
4050
4051 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
4052 (unsigned char *)wpsie,
4053 &pattrib->pktlen);
4054
4055 p2pielen = build_probe_resp_p2p_ie23a(pwdinfo, pframe);
4056 pframe += p2pielen;
4057 pattrib->pktlen += p2pielen;
4058 }
4059
4060#ifdef CONFIG_8723AU_P2P
4061 if (pwdinfo->wfd_info->wfd_enable) {
4062 wfdielen = build_probe_resp_wfd_ie(pwdinfo, pframe, 0);
4063 pframe += wfdielen;
4064 pattrib->pktlen += wfdielen;
4065 } else if (pmlmepriv->wfd_probe_resp_ie &&
4066 pmlmepriv->wfd_probe_resp_ie_len > 0) {
4067 /* WFD IE */
4068 memcpy(pframe, pmlmepriv->wfd_probe_resp_ie,
4069 pmlmepriv->wfd_probe_resp_ie_len);
4070 pattrib->pktlen += pmlmepriv->wfd_probe_resp_ie_len;
4071 pframe += pmlmepriv->wfd_probe_resp_ie_len;
4072 }
4073#endif /* CONFIG_8723AU_P2P */
4074
4075 pattrib->last_txcmdsz = pattrib->pktlen;
4076
4077 dump_mgntframe23a(padapter, pmgntframe);
4078
4079 return;
4080}
4081
4082static int _issue23a_probereq_p2p(struct rtw_adapter *padapter, u8 *da,
4083 int wait_ack)
4084{
4085 int ret = _FAIL;
4086 struct xmit_frame *pmgntframe;
4087 struct pkt_attrib *pattrib;
4088 unsigned char *pframe;
4089 struct ieee80211_hdr *pwlanhdr;
4090 unsigned short *fctrl;
4091 unsigned char *mac;
4092 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
4093 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4094 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4095 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4096 u8 wpsie[255] = {0x00}, p2pie[255] = {0x00};
4097 u16 wpsielen = 0, p2pielen = 0;
4098#ifdef CONFIG_8723AU_P2P
4099 u32 wfdielen = 0;
4100#endif /* CONFIG_8723AU_P2P */
4101 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4102
4103 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
4104 goto exit;
4105
4106 /* update attribute */
4107 pattrib = &pmgntframe->attrib;
4108 update_mgntframe_attrib23a(padapter, pattrib);
4109
4110 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4111
4112 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4113 pwlanhdr = (struct ieee80211_hdr *)pframe;
4114
4115 mac = myid(&padapter->eeprompriv);
4116
4117 fctrl = &pwlanhdr->frame_control;
4118 *fctrl = 0;
4119
4120 if (da) {
4121 ether_addr_copy(pwlanhdr->addr1, da);
4122 ether_addr_copy(pwlanhdr->addr3, da);
4123 } else {
4124 if ((pwdinfo->p2p_info.scan_op_ch_only) ||
4125 (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
4126 /* This two flags will be set when this is
4127 only the P2P client mode. */
4128 ether_addr_copy(pwlanhdr->addr1,
4129 pwdinfo->p2p_peer_interface_addr);
4130 ether_addr_copy(pwlanhdr->addr3,
4131 pwdinfo->p2p_peer_interface_addr);
4132 } else {
4133 /* broadcast probe request frame */
4134 ether_addr_copy(pwlanhdr->addr1, bc_addr);
4135 ether_addr_copy(pwlanhdr->addr3, bc_addr);
4136 }
4137 }
4138 ether_addr_copy(pwlanhdr->addr2, mac);
4139
4140 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4141 pmlmeext->mgnt_seq++;
4142 SetFrameSubType(pframe, WIFI_PROBEREQ);
4143
4144 pframe += sizeof (struct ieee80211_hdr_3addr);
4145 pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr);
4146
4147 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
4148 pframe = rtw_set_ie23a(pframe, _SSID_IE_,
4149 pwdinfo->tx_prov_disc_info.ssid.ssid_len,
4150 pwdinfo->tx_prov_disc_info.ssid.ssid,
4151 &pattrib->pktlen);
4152 } else {
4153 pframe = rtw_set_ie23a(pframe, _SSID_IE_,
4154 P2P_WILDCARD_SSID_LEN,
4155 pwdinfo->p2p_wildcard_ssid,
4156 &pattrib->pktlen);
4157 }
4158 /* Use the OFDM rate in the P2P probe request frame.
4159 (6(B), 9(B), 12(B), 24(B), 36, 48, 54) */
4160 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
4161 pwdinfo->support_rate, &pattrib->pktlen);
4162
4163 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
4164 if (pmlmepriv->wps_probe_req_ie &&
4165 pmlmepriv->p2p_probe_req_ie) {
4166 /* WPS IE */
4167 memcpy(pframe, pmlmepriv->wps_probe_req_ie,
4168 pmlmepriv->wps_probe_req_ie_len);
4169 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
4170 pframe += pmlmepriv->wps_probe_req_ie_len;
4171
4172 /* P2P IE */
4173 memcpy(pframe, pmlmepriv->p2p_probe_req_ie,
4174 pmlmepriv->p2p_probe_req_ie_len);
4175 pattrib->pktlen += pmlmepriv->p2p_probe_req_ie_len;
4176 pframe += pmlmepriv->p2p_probe_req_ie_len;
4177 }
4178 } else {
4179
4180 /* WPS IE */
4181 /* Noted by Albert 20110221 */
4182 /* According to the WPS specification, all the WPS
4183 attribute is presented by Big Endian. */
4184
4185 wpsielen = 0;
4186 /* WPS OUI */
4187 *(u32*) (wpsie) = cpu_to_be32(WPSOUI);
4188 wpsielen += 4;
4189
4190 /* WPS version */
4191 /* Type: */
4192 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
4193 wpsielen += 2;
4194
4195 /* Length: */
4196 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0001);
4197 wpsielen += 2;
4198
4199 /* Value: */
4200 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
4201
4202 if (pmlmepriv->wps_probe_req_ie == NULL) {
4203 /* UUID-E */
4204 /* Type: */
4205 *(u16*) (wpsie + wpsielen) =
4206 cpu_to_be16(WPS_ATTR_UUID_E);
4207 wpsielen += 2;
4208
4209 /* Length: */
4210 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0010);
4211 wpsielen += 2;
4212
4213 /* Value: */
4214 memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv),
4215 ETH_ALEN);
4216 wpsielen += 0x10;
4217
4218 /* Config Method */
4219 /* Type: */
4220 *(u16*) (wpsie + wpsielen) =
4221 cpu_to_be16(WPS_ATTR_CONF_METHOD);
4222 wpsielen += 2;
4223
4224 /* Length: */
4225 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
4226 wpsielen += 2;
4227
4228 /* Value: */
4229 *(u16*) (wpsie + wpsielen) =
4230 cpu_to_be16(pwdinfo->supported_wps_cm);
4231 wpsielen += 2;
4232 }
4233
4234 /* Device Name */
4235 /* Type: */
4236 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
4237 wpsielen += 2;
4238
4239 /* Length: */
4240 *(u16*) (wpsie + wpsielen) =
4241 cpu_to_be16(pwdinfo->device_name_len);
4242 wpsielen += 2;
4243
4244 /* Value: */
4245 memcpy(wpsie + wpsielen, pwdinfo->device_name,
4246 pwdinfo->device_name_len);
4247 wpsielen += pwdinfo->device_name_len;
4248
4249 /* Primary Device Type */
4250 /* Type: */
4251 *(u16*) (wpsie + wpsielen) =
4252 cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
4253 wpsielen += 2;
4254
4255 /* Length: */
4256 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0008);
4257 wpsielen += 2;
4258
4259 /* Value: */
4260 /* Category ID */
4261 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_RTK_WIDI);
4262 wpsielen += 2;
4263
4264 /* OUI */
4265 *(u32*) (wpsie + wpsielen) = cpu_to_be32(WPSOUI);
4266 wpsielen += 4;
4267
4268 /* Sub Category ID */
4269 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_RTK_DMP);
4270 wpsielen += 2;
4271
4272 /* Device Password ID */
4273 /* Type: */
4274 *(u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
4275 wpsielen += 2;
4276
4277 /* Length: */
4278 *(u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002);
4279 wpsielen += 2;
4280
4281 /* Value: */
4282 /* Registrar-specified */
4283 *(u16*) (wpsie + wpsielen) =
4284 cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
4285 wpsielen += 2;
4286
4287 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
4288 (unsigned char *)wpsie,
4289 &pattrib->pktlen);
4290
4291 /* P2P OUI */
4292 p2pielen = 0;
4293 p2pie[p2pielen++] = 0x50;
4294 p2pie[p2pielen++] = 0x6F;
4295 p2pie[p2pielen++] = 0x9A;
4296 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
4297
4298 /* Commented by Albert 20110221 */
4299 /* According to the P2P Specification, the probe request
4300 frame should contain 5 P2P attributes */
4301 /* 1. P2P Capability */
4302 /* 2. P2P Device ID if this probe request wants to
4303 find the specific P2P device */
4304 /* 3. Listen Channel */
4305 /* 4. Extended Listen Timing */
4306 /* 5. Operating Channel if this WiFi is working as
4307 the group owner now */
4308
4309 /* P2P Capability */
4310 /* Type: */
4311 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
4312
4313 /* Length: */
4314 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
4315 p2pielen += 2;
4316
4317 /* Value: */
4318 /* Device Capability Bitmap, 1 byte */
4319 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
4320
4321 /* Group Capability Bitmap, 1 byte */
4322 if (pwdinfo->persistent_supported)
4323 p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP |
4324 DMP_P2P_GRPCAP_SUPPORT;
4325 else
4326 p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
4327
4328 /* Listen Channel */
4329 /* Type: */
4330 p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
4331
4332 /* Length: */
4333 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
4334 p2pielen += 2;
4335
4336 /* Value: */
4337 /* Country String */
4338 p2pie[p2pielen++] = 'X';
4339 p2pie[p2pielen++] = 'X';
4340
4341 /* The third byte should be set to 0x04. */
4342 /* Described in the "Operating Channel Attribute" section. */
4343 p2pie[p2pielen++] = 0x04;
4344
4345 /* Operating Class */
4346 p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
4347
4348 /* Channel Number */
4349 /* listen channel */
4350 p2pie[p2pielen++] = pwdinfo->listen_channel;
4351
4352 /* Extended Listen Timing */
4353 /* Type: */
4354 p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
4355
4356 /* Length: */
4357 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004);
4358 p2pielen += 2;
4359
4360 /* Value: */
4361 /* Availability Period */
4362 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
4363 p2pielen += 2;
4364
4365 /* Availability Interval */
4366 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
4367 p2pielen += 2;
4368
4369 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
4370 /* Operating Channel (if this WiFi is working as
4371 the group owner now) */
4372 /* Type: */
4373 p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
4374
4375 /* Length: */
4376 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0005);
4377 p2pielen += 2;
4378
4379 /* Value: */
4380 /* Country String */
4381 p2pie[p2pielen++] = 'X';
4382 p2pie[p2pielen++] = 'X';
4383
4384 /* The third byte should be set to 0x04. */
4385 /* Described in the "Operating Channel Attribute"
4386 section. */
4387 p2pie[p2pielen++] = 0x04;
4388
4389 /* Operating Class */
4390 p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
4391
4392 /* Channel Number */
4393 /* operating channel number */
4394 p2pie[p2pielen++] = pwdinfo->operating_channel;
4395 }
4396
4397 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
4398 (unsigned char *)p2pie,
4399 &pattrib->pktlen);
4400
4401 if (pmlmepriv->wps_probe_req_ie) {
4402 /* WPS IE */
4403 memcpy(pframe, pmlmepriv->wps_probe_req_ie,
4404 pmlmepriv->wps_probe_req_ie_len);
4405 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
4406 pframe += pmlmepriv->wps_probe_req_ie_len;
4407 }
4408 }
4409
4410#ifdef CONFIG_8723AU_P2P
4411 if (pwdinfo->wfd_info->wfd_enable) {
4412 wfdielen = build_probe_req_wfd_ie(pwdinfo, pframe);
4413 pframe += wfdielen;
4414 pattrib->pktlen += wfdielen;
4415 } else if (pmlmepriv->wfd_probe_req_ie &&
4416 pmlmepriv->wfd_probe_req_ie_len>0) {
4417 /* WFD IE */
4418 memcpy(pframe, pmlmepriv->wfd_probe_req_ie,
4419 pmlmepriv->wfd_probe_req_ie_len);
4420 pattrib->pktlen += pmlmepriv->wfd_probe_req_ie_len;
4421 pframe += pmlmepriv->wfd_probe_req_ie_len;
4422 }
4423#endif /* CONFIG_8723AU_P2P */
4424
4425 pattrib->last_txcmdsz = pattrib->pktlen;
4426
4427 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
4428 ("issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz));
4429
4430 if (wait_ack) {
4431 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
4432 } else {
4433 dump_mgntframe23a(padapter, pmgntframe);
4434 ret = _SUCCESS;
4435 }
4436
4437exit:
4438 return ret;
4439}
4440
4441inline void issue23a_probereq_p2p(struct rtw_adapter *adapter, u8 *da)
4442{
4443 _issue23a_probereq_p2p(adapter, da, false);
4444}
4445
4446int issue23a_probereq_p2p_ex(struct rtw_adapter *adapter, u8 *da,
4447 int try_cnt, int wait_ms)
4448{
4449 int ret;
4450 int i = 0;
4451 unsigned long start = jiffies;
4452
4453 do {
4454 ret = _issue23a_probereq_p2p(adapter, da,
4455 wait_ms > 0 ? true : false);
4456
4457 i++;
4458
4459 if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
4460 break;
4461
4462 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
4463 msleep(wait_ms);
4464
4465 } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
4466
4467 if (ret != _FAIL) {
4468 ret = _SUCCESS;
4469 goto exit;
4470 }
4471
4472 if (try_cnt && wait_ms) {
4473 if (da)
4474 DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d "
4475 "in %u ms\n", FUNC_ADPT_ARG(adapter),
4476 MAC_ARG(da), rtw_get_oper_ch23a(adapter),
4477 ret == _SUCCESS?", acked":"", i, try_cnt,
4478 jiffies_to_msecs(jiffies - start));
4479 else
4480 DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
4481 FUNC_ADPT_ARG(adapter),
4482 rtw_get_oper_ch23a(adapter),
4483 ret == _SUCCESS?", acked":"", i, try_cnt,
4484 jiffies_to_msecs(jiffies - start));
4485 }
4486exit:
4487 return ret;
4488}
4489
4490#endif /* CONFIG_8723AU_P2P */
4491
4492static s32 rtw_action_public_decache(struct recv_frame *recv_frame, s32 token)
4493{
4494 struct rtw_adapter *adapter = recv_frame->adapter;
4495 struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
4496 struct sk_buff *skb = recv_frame->pkt;
4497 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
4498 u16 seq_ctrl;
4499
4500 seq_ctrl = ((recv_frame->attrib.seq_num&0xffff) << 4) |
4501 (recv_frame->attrib.frag_num & 0xf);
4502
4503 if (ieee80211_has_retry(hdr->frame_control)) {
4504 if (token >= 0) {
4505 if ((seq_ctrl == mlmeext->action_public_rxseq) &&
4506 (token == mlmeext->action_public_dialog_token)) {
4507 DBG_8723A(FUNC_ADPT_FMT" seq_ctrl = 0x%x, "
4508 "rxseq = 0x%x, token:%d\n",
4509 FUNC_ADPT_ARG(adapter), seq_ctrl,
4510 mlmeext->action_public_rxseq, token);
4511 return _FAIL;
4512 }
4513 } else {
4514 if (seq_ctrl == mlmeext->action_public_rxseq) {
4515 DBG_8723A(FUNC_ADPT_FMT" seq_ctrl = 0x%x, "
4516 "rxseq = 0x%x\n",
4517 FUNC_ADPT_ARG(adapter), seq_ctrl,
4518 mlmeext->action_public_rxseq);
4519 return _FAIL;
4520 }
4521 }
4522 }
4523
4524 mlmeext->action_public_rxseq = seq_ctrl;
4525
4526 if (token >= 0)
4527 mlmeext->action_public_dialog_token = token;
4528
4529 return _SUCCESS;
4530}
4531
4532static unsigned int on_action_public23a_p2p(struct recv_frame *precv_frame)
4533{
4534 struct sk_buff *skb = precv_frame->pkt;
4535 u8 *pframe = skb->data;
4536 u8 *frame_body;
4537 u8 dialogToken = 0;
4538#ifdef CONFIG_8723AU_P2P
4539 struct rtw_adapter *padapter = precv_frame->adapter;
4540 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
4541 uint len = skb->len;
4542 u8 *p2p_ie;
4543 u32 p2p_ielen;
4544 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4545 u8 result = P2P_STATUS_SUCCESS;
4546#endif /* CONFIG_8723AU_P2P */
4547
4548 frame_body = (unsigned char *)
4549 (pframe + sizeof(struct ieee80211_hdr_3addr));
4550
4551 dialogToken = frame_body[7];
4552
4553 if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
4554 return _FAIL;
4555
4556#ifdef CONFIG_8723AU_P2P
4557 del_timer_sync(&pwdinfo->reset_ch_sitesurvey);
4558 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
4559 rtw_cfg80211_rx_p2p_action_public(padapter, pframe, len);
4560 } else {
4561 /* Do nothing if the driver doesn't enable the P2P function. */
4562 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
4563 return _SUCCESS;
4564
4565 len -= sizeof(struct ieee80211_hdr_3addr);
4566
4567 switch (frame_body[ 6 ])/* OUI Subtype */
4568 {
4569 case P2P_GO_NEGO_REQ:
4570 DBG_8723A("[%s] Got GO Nego Req Frame\n", __func__);
4571 memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
4572
4573 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
4574 {
4575 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
4576 }
4577
4578 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
4579 {
4580 /* Commented by Albert 20110526 */
4581 /* In this case, this means the previous nego fail doesn't be reset yet. */
4582 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
4583 /* Restore the previous p2p state */
4584 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
4585 DBG_8723A("[%s] Restore the previous p2p state to %d\n", __func__, rtw_p2p_state(pwdinfo));
4586 }
4587
4588 /* Commented by Kurt 20110902 */
4589 /* Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
4590 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
4591 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
4592
4593 /* Commented by Kurt 20120113 */
4594 /* Get peer_dev_addr here if peer doesn't issue prov_disc frame. */
4595 if (is_zero_ether_addr(pwdinfo->rx_prov_disc_info.peerDevAddr))
4596 ether_addr_copy(pwdinfo->rx_prov_disc_info.peerDevAddr, hdr->addr2);
4597
4598 result = process_p2p_group_negotation_req23a(pwdinfo, frame_body, len);
4599 issue_p2p_GO_response(padapter, hdr->addr2,
4600 frame_body, len, result);
4601
4602 /* Commented by Albert 20110718 */
4603 /* No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer. */
4604 mod_timer(&pwdinfo->restore_p2p_state_timer,
4605 jiffies + msecs_to_jiffies(5000));
4606 break;
4607
4608 case P2P_GO_NEGO_RESP:
4609 DBG_8723A("[%s] Got GO Nego Resp Frame\n", __func__);
4610
4611 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
4612 {
4613 /* Commented by Albert 20110425 */
4614 /* The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function. */
4615 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
4616 pwdinfo->nego_req_info.benable = false;
4617 result = process_p2p_group_negotation_resp23a(pwdinfo, frame_body, len);
4618 issue_p2p_GO_confirm(pwdinfo->padapter,
4619 hdr->addr2,
4620 result);
4621 if (result == P2P_STATUS_SUCCESS) {
4622 if (rtw_p2p_role(pwdinfo) ==
4623 P2P_ROLE_CLIENT) {
4624 pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch;
4625 pwdinfo->p2p_info.scan_op_ch_only = 1;
4626 mod_timer(&pwdinfo->reset_ch_sitesurvey2, jiffies + msecs_to_jiffies(P2P_RESET_SCAN_CH));
4627 }
4628 }
4629
4630 /* Reset the dialog token for group negotiation frames. */
4631 pwdinfo->negotiation_dialog_token = 1;
4632
4633 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
4634 {
4635 mod_timer(&pwdinfo->restore_p2p_state_timer, jiffies + msecs_to_jiffies(5000));
4636 }
4637 } else {
4638 DBG_8723A("[%s] Skipped GO Nego Resp Frame (p2p_state != P2P_STATE_GONEGO_ING)\n", __func__);
4639 }
4640
4641 break;
4642
4643 case P2P_GO_NEGO_CONF:
4644
4645 DBG_8723A("[%s] Got GO Nego Confirm Frame\n", __func__);
4646 result = process_p2p_group_negotation_confirm23a(pwdinfo, frame_body, len);
4647 if (P2P_STATUS_SUCCESS == result)
4648 {
4649 if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT)
4650 {
4651 pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch;
4652 pwdinfo->p2p_info.scan_op_ch_only = 1;
4653 mod_timer(&pwdinfo->reset_ch_sitesurvey2, jiffies + msecs_to_jiffies(P2P_RESET_SCAN_CH));
4654 }
4655 }
4656 break;
4657
4658 case P2P_INVIT_REQ:
4659 /* Added by Albert 2010/10/05 */
4660 /* Received the P2P Invite Request frame. */
4661
4662 DBG_8723A("[%s] Got invite request frame!\n", __func__);
4663 if ((p2p_ie = rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)))
4664 {
4665 /* Parse the necessary information from the P2P Invitation Request frame. */
4666 /* For example: The MAC address of sending this P2P Invitation Request frame. */
4667 u32 attr_contentlen = 0;
4668 u8 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4669 struct group_id_info group_id;
4670 u8 invitation_flag = 0;
4671
4672 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);
4673 if (attr_contentlen)
4674 {
4675
4676 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);
4677 /* Commented by Albert 20120510 */
4678 /* Copy to the pwdinfo->p2p_peer_interface_addr. */
4679 /* So that the WFD UI (or Sigma) can get the peer interface address by using the following command. */
4680 /* #> iwpriv wlan0 p2p_get peer_ifa */
4681 /* After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant. */
4682
4683 if (attr_contentlen)
4684 {
4685 DBG_8723A("[%s] GO's BSSID = %.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
4686 pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1],
4687 pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3],
4688 pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
4689 }
4690
4691 if (invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT)
4692 {
4693 /* Re-invoke the persistent group. */
4694
4695 memset(&group_id, 0x00, sizeof(struct group_id_info));
4696 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8*) &group_id, &attr_contentlen);
4697 if (attr_contentlen) {
4698 if (ether_addr_equal(group_id.go_device_addr, myid(&padapter->eeprompriv))) {
4699 /* The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO. */
4700 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO);
4701 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
4702 status_code = P2P_STATUS_SUCCESS;
4703 }
4704 else
4705 {
4706 /* The p2p device sending this p2p invitation request wants to be the persistent GO. */
4707 if (is_matched_in_profilelist(pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[ 0 ]))
4708 {
4709 u8 operatingch_info[5] = { 0x00 };
4710 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
4711 {
4712 if (rtw_ch_set_search_ch23a(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4]))
4713 {
4714 /* The operating channel is acceptable for this device. */
4715 pwdinfo->rx_invitereq_info.operation_ch[0]= operatingch_info[4];
4716 pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;
4717 mod_timer(&pwdinfo->reset_ch_sitesurvey, jiffies + msecs_to_jiffies(P2P_RESET_SCAN_CH));
4718 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
4719 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4720 status_code = P2P_STATUS_SUCCESS;
4721 }
4722 else
4723 {
4724 /* The operating channel isn't supported by this device. */
4725 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
4726 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4727 status_code = P2P_STATUS_FAIL_NO_COMMON_CH;
4728 mod_timer(&pwdinfo->restore_p2p_state_timer, jiffies + msecs_to_jiffies(3000));
4729 }
4730 }
4731 else {
4732 /* Commented by Albert 20121130 */
4733 /* Intel will use the different P2P IE to store the operating channel information */
4734 /* Workaround for Intel WiDi 3.5 */
4735 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
4736 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4737 status_code = P2P_STATUS_SUCCESS;
4738 }
4739 }
4740 else
4741 {
4742 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
4743
4744 status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
4745 }
4746 }
4747 }
4748 else
4749 {
4750 DBG_8723A("[%s] P2P Group ID Attribute NOT FOUND!\n", __func__);
4751 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4752 }
4753 }
4754 else
4755 {
4756 /* Received the invitation to join a P2P group. */
4757
4758 memset(&group_id, 0x00, sizeof(struct group_id_info));
4759 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8*) &group_id, &attr_contentlen);
4760 if (attr_contentlen)
4761 {
4762 if (ether_addr_equal(group_id.go_device_addr, myid(&padapter->eeprompriv))) {
4763 /* In this case, the GO can't be myself. */
4764 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
4765 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4766 }
4767 else
4768 {
4769 /* The p2p device sending this p2p invitation request wants to join an existing P2P group */
4770 /* Commented by Albert 2012/06/28 */
4771 /* In this case, this Wi-Fi device should use the iwpriv command to get the peer device address. */
4772 /* The peer device address should be the destination address for the provisioning discovery request. */
4773 /* Then, this Wi-Fi device should use the iwpriv command to get the peer interface address. */
4774 /* The peer interface address should be the address for WPS mac address */
4775 ether_addr_copy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr);
4776 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4777 rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN);
4778 status_code = P2P_STATUS_SUCCESS;
4779 }
4780 }
4781 else
4782 {
4783 DBG_8723A("[%s] P2P Group ID Attribute NOT FOUND!\n", __func__);
4784 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4785 }
4786 }
4787 }
4788 else
4789 {
4790 DBG_8723A("[%s] P2P Invitation Flags Attribute NOT FOUND!\n", __func__);
4791 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4792 }
4793
4794 DBG_8723A("[%s] status_code = %d\n", __func__, status_code);
4795
4796 pwdinfo->inviteresp_info.token = frame_body[ 7 ];
4797 issue_p2p_invitation_response23a(padapter, hdr->addr2, pwdinfo->inviteresp_info.token, status_code);
4798 }
4799 break;
4800
4801 case P2P_INVIT_RESP:
4802 {
4803 u8 attr_content = 0x00;
4804 u32 attr_contentlen = 0;
4805
4806 DBG_8723A("[%s] Got invite response frame!\n", __func__);
4807 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
4808 if ((p2p_ie = rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)))
4809 {
4810 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
4811
4812 if (attr_contentlen == 1)
4813 {
4814 DBG_8723A("[%s] Status = %d\n", __func__, attr_content);
4815 pwdinfo->invitereq_info.benable = false;
4816
4817 if (attr_content == P2P_STATUS_SUCCESS)
4818 {
4819 if (ether_addr_equal(pwdinfo->invitereq_info.go_bssid, myid(&padapter->eeprompriv))) {
4820 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
4821 }
4822 else
4823 {
4824 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4825 }
4826 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_OK);
4827 }
4828 else
4829 {
4830 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4831 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
4832 }
4833 }
4834 else
4835 {
4836 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4837 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
4838 }
4839 }
4840 else
4841 {
4842 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4843 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
4844 }
4845
4846 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL)) {
4847 mod_timer(&pwdinfo->restore_p2p_state_timer, jiffies + msecs_to_jiffies(5000));
4848 }
4849 break;
4850 }
4851 case P2P_DEVDISC_REQ:
4852
4853 process_p2p_devdisc_req23a(pwdinfo, pframe, len);
4854
4855 break;
4856
4857 case P2P_DEVDISC_RESP:
4858
4859 process_p2p_devdisc_resp23a(pwdinfo, pframe, len);
4860
4861 break;
4862
4863 case P2P_PROVISION_DISC_REQ:
4864 DBG_8723A("[%s] Got Provisioning Discovery Request Frame\n", __func__);
4865 process_p2p_provdisc_req23a(pwdinfo, pframe, len);
4866 ether_addr_copy(pwdinfo->rx_prov_disc_info.peerDevAddr, hdr->addr2);
4867
4868 /* 20110902 Kurt */
4869 /* Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
4870 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
4871 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
4872
4873 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);
4874 mod_timer(&pwdinfo->restore_p2p_state_timer,
4875 jiffies + msecs_to_jiffies(P2P_PROVISION_TIMEOUT));
4876 break;
4877
4878 case P2P_PROVISION_DISC_RESP:
4879 /* Commented by Albert 20110707 */
4880 /* Should we check the pwdinfo->tx_prov_disc_info.bsent flag here?? */
4881 DBG_8723A("[%s] Got Provisioning Discovery Response Frame\n", __func__);
4882 /* Commented by Albert 20110426 */
4883 /* The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function. */
4884 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
4885 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);
4886 process_p2p_provdisc_resp23a(pwdinfo, pframe);
4887 mod_timer(&pwdinfo->restore_p2p_state_timer,
4888 jiffies + msecs_to_jiffies(P2P_PROVISION_TIMEOUT));
4889 break;
4890
4891 }
4892 }
4893#endif /* CONFIG_8723AU_P2P */
4894
4895 return _SUCCESS;
4896}
4897
4898static unsigned int on_action_public23a_vendor(struct recv_frame *precv_frame)
4899{
4900 unsigned int ret = _FAIL;
4901 struct sk_buff *skb = precv_frame->pkt;
4902 u8 *pframe = skb->data;
4903 u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
4904
4905 if (!memcmp(frame_body + 2, P2P_OUI23A, 4)) {
4906 ret = on_action_public23a_p2p(precv_frame);
4907 }
4908
4909 return ret;
4910}
4911
4912static unsigned int
4913on_action_public23a_default(struct recv_frame *precv_frame, u8 action)
4914{
4915 unsigned int ret = _FAIL;
4916 struct sk_buff *skb = precv_frame->pkt;
4917 u8 *pframe = skb->data;
4918 uint frame_len = skb->len;
4919 u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
4920 u8 token;
4921 struct rtw_adapter *adapter = precv_frame->adapter;
4922 int cnt = 0;
4923 char msg[64];
4924
4925 token = frame_body[2];
4926
4927 if (rtw_action_public_decache(precv_frame, token) == _FAIL)
4928 goto exit;
4929
4930 cnt += sprintf((msg+cnt), "%s(token:%u)",
4931 action_public_str23a(action), token);
4932 rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
4933
4934 ret = _SUCCESS;
4935
4936exit:
4937 return ret;
4938}
4939
4940unsigned int on_action_public23a(struct rtw_adapter *padapter,
4941 struct recv_frame *precv_frame)
4942{
4943 unsigned int ret = _FAIL;
4944 struct sk_buff *skb = precv_frame->pkt;
4945 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
4946 u8 *pframe = skb->data;
4947 u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
4948 u8 category, action;
4949
4950 /* check RA matches or not */
4951 if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
4952 goto exit;
4953
4954 category = frame_body[0];
4955 if (category != WLAN_CATEGORY_PUBLIC)
4956 goto exit;
4957
4958 action = frame_body[1];
4959 switch (action) {
4960 case ACT_PUBLIC_VENDOR:
4961 ret = on_action_public23a_vendor(precv_frame);
4962 break;
4963 default:
4964 ret = on_action_public23a_default(precv_frame, action);
4965 break;
4966 }
4967
4968exit:
4969 return ret;
4970}
4971
4972unsigned int OnAction23a_ht(struct rtw_adapter *padapter,
4973 struct recv_frame *precv_frame)
4974{
4975 return _SUCCESS;
4976}
4977
4978unsigned int OnAction23a_wmm(struct rtw_adapter *padapter,
4979 struct recv_frame *precv_frame)
4980{
4981 return _SUCCESS;
4982}
4983
4984unsigned int OnAction23a_p2p(struct rtw_adapter *padapter,
4985 struct recv_frame *precv_frame)
4986{
4987#ifdef CONFIG_8723AU_P2P
4988 u8 *frame_body;
4989 u8 category, OUI_Subtype, dialogToken = 0;
4990 struct sk_buff *skb = precv_frame->pkt;
4991 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
4992 u8 *pframe = skb->data;
4993 uint len = skb->len;
4994 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
4995
4996 DBG_8723A("%s\n", __func__);
4997
4998 /* check RA matches or not */
4999 if (!ether_addr_equal(myid(&padapter->eeprompriv), hdr->addr1))
5000 return _SUCCESS;
5001
5002 frame_body = (unsigned char *)
5003 (pframe + sizeof(struct ieee80211_hdr_3addr));
5004
5005 category = frame_body[0];
5006 if (category != WLAN_CATEGORY_VENDOR_SPECIFIC)
5007 return _SUCCESS;
5008
5009 if (cpu_to_be32(*((u32*) (frame_body + 1))) != P2POUI)
5010 return _SUCCESS;
5011
5012 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
5013 rtw_cfg80211_rx_action_p2p(padapter, pframe, len);
5014 return _SUCCESS;
5015 } else {
5016 len -= sizeof(struct ieee80211_hdr_3addr);
5017 OUI_Subtype = frame_body[5];
5018 dialogToken = frame_body[6];
5019
5020 switch (OUI_Subtype)
5021 {
5022 case P2P_NOTICE_OF_ABSENCE:
5023 break;
5024
5025 case P2P_PRESENCE_REQUEST:
5026 process_p2p_presence_req23a(pwdinfo, pframe, len);
5027 break;
5028
5029 case P2P_PRESENCE_RESPONSE:
5030 break;
5031
5032 case P2P_GO_DISC_REQUEST:
5033 break;
5034
5035 default:
5036 break;
5037 }
5038 }
5039#endif /* CONFIG_8723AU_P2P */
5040
5041 return _SUCCESS;
5042}
5043
5044unsigned int OnAction23a(struct rtw_adapter *padapter,
5045 struct recv_frame *precv_frame)
5046{
5047 int i;
5048 unsigned char category;
5049 struct action_handler *ptable;
5050 unsigned char *frame_body;
5051 struct sk_buff *skb = precv_frame->pkt;
5052 u8 *pframe = skb->data;
5053
5054 frame_body = (unsigned char *)
5055 (pframe + sizeof(struct ieee80211_hdr_3addr));
5056
5057 category = frame_body[0];
5058
5059 for (i = 0;
5060 i < sizeof(OnAction23a_tbl) / sizeof(struct action_handler); i++) {
5061 ptable = &OnAction23a_tbl[i];
5062
5063 if (category == ptable->num)
5064 ptable->func(padapter, precv_frame);
5065 }
5066
5067 return _SUCCESS;
5068}
5069
5070unsigned int DoReserved23a(struct rtw_adapter *padapter,
5071 struct recv_frame *precv_frame)
5072{
5073 return _SUCCESS;
5074}
5075
5076struct xmit_frame *alloc_mgtxmitframe23a(struct xmit_priv *pxmitpriv)
5077{
5078 struct xmit_frame *pmgntframe;
5079 struct xmit_buf *pxmitbuf;
5080
5081 pmgntframe = rtw_alloc_xmitframe23a_ext(pxmitpriv);
5082
5083 if (!pmgntframe) {
5084 DBG_8723A(FUNC_ADPT_FMT" alloc xmitframe fail\n",
5085 FUNC_ADPT_ARG(pxmitpriv->adapter));
5086 goto exit;
5087 }
5088
5089 pxmitbuf = rtw_alloc_xmitbuf23a_ext(pxmitpriv);
5090 if (!pxmitbuf) {
5091 DBG_8723A(FUNC_ADPT_FMT" alloc xmitbuf fail\n",
5092 FUNC_ADPT_ARG(pxmitpriv->adapter));
5093 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
5094 pmgntframe = NULL;
5095 goto exit;
5096 }
5097
5098 pmgntframe->frame_tag = MGNT_FRAMETAG;
5099 pmgntframe->pxmitbuf = pxmitbuf;
5100 pmgntframe->buf_addr = pxmitbuf->pbuf;
5101 pxmitbuf->priv_data = pmgntframe;
5102
5103exit:
5104 return pmgntframe;
5105}
5106
5107/****************************************************************************
5108
5109Following are some TX fuctions for WiFi MLME
5110
5111*****************************************************************************/
5112
5113void update_mgnt_tx_rate23a(struct rtw_adapter *padapter, u8 rate)
5114{
5115 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5116
5117 pmlmeext->tx_rate = rate;
5118 DBG_8723A("%s(): rate = %x\n", __func__, rate);
5119}
5120
5121void update_mgntframe_attrib23a(struct rtw_adapter *padapter,
5122 struct pkt_attrib *pattrib)
5123{
5124 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5125
5126 memset((u8 *)pattrib, 0, sizeof(struct pkt_attrib));
5127
5128 pattrib->hdrlen = 24;
5129 pattrib->nr_frags = 1;
5130 pattrib->priority = 7;
5131 pattrib->mac_id = 0;
5132 pattrib->qsel = 0x12;
5133
5134 pattrib->pktlen = 0;
5135
5136 if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
5137 pattrib->raid = 6;/* b mode */
5138 else
5139 pattrib->raid = 5;/* a/g mode */
5140
5141 pattrib->encrypt = _NO_PRIVACY_;
5142 pattrib->bswenc = false;
5143
5144 pattrib->qos_en = false;
5145 pattrib->ht_en = false;
5146 pattrib->bwmode = HT_CHANNEL_WIDTH_20;
5147 pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5148 pattrib->sgi = false;
5149
5150 pattrib->seqnum = pmlmeext->mgnt_seq;
5151
5152 pattrib->retry_ctrl = true;
5153}
5154
5155void dump_mgntframe23a(struct rtw_adapter *padapter,
5156 struct xmit_frame *pmgntframe)
5157{
5158 if (padapter->bSurpriseRemoved == true ||
5159 padapter->bDriverStopped == true)
5160 return;
5161
5162 rtw_hal_mgnt_xmit23a(padapter, pmgntframe);
5163}
5164
5165s32 dump_mgntframe23a_and_wait(struct rtw_adapter *padapter,
5166 struct xmit_frame *pmgntframe, int timeout_ms)
5167{
5168 s32 ret = _FAIL;
5169 unsigned long irqL;
5170 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5171 struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
5172 struct submit_ctx sctx;
5173
5174 if (padapter->bSurpriseRemoved == true ||
5175 padapter->bDriverStopped == true)
5176 return ret;
5177
5178 rtw_sctx_init23a(&sctx, timeout_ms);
5179 pxmitbuf->sctx = &sctx;
5180
5181 ret = rtw_hal_mgnt_xmit23a(padapter, pmgntframe);
5182
5183 if (ret == _SUCCESS)
5184 ret = rtw_sctx_wait23a(&sctx);
5185
5186 spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
5187 pxmitbuf->sctx = NULL;
5188 spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
5189
5190 return ret;
5191}
5192
5193s32 dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter,
5194 struct xmit_frame *pmgntframe)
5195{
5196 s32 ret = _FAIL;
5197 u32 timeout_ms = 500;/* 500ms */
5198 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5199
5200 if (padapter->bSurpriseRemoved == true ||
5201 padapter->bDriverStopped == true)
5202 return -1;
5203
5204 mutex_lock(&pxmitpriv->ack_tx_mutex);
5205 pxmitpriv->ack_tx = true;
5206
5207 pmgntframe->ack_report = 1;
5208 if (rtw_hal_mgnt_xmit23a(padapter, pmgntframe) == _SUCCESS) {
5209 ret = rtw_ack_tx_wait23a(pxmitpriv, timeout_ms);
5210 }
5211
5212 pxmitpriv->ack_tx = false;
5213 mutex_unlock(&pxmitpriv->ack_tx_mutex);
5214
5215 return ret;
5216}
5217
5218static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
5219{
5220 u8 *ssid_ie;
5221 int ssid_len_ori;
5222 int len_diff = 0;
5223 u8 *next_ie;
5224 u32 remain_len;
5225
5226 ssid_ie = rtw_get_ie23a(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
5227
5228 /* DBG_8723A("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n",
5229 __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */
5230
5231 if (ssid_ie && ssid_len_ori > 0) {
5232 switch (hidden_ssid_mode)
5233 {
5234 case 1:
5235 next_ie = ssid_ie + 2 + ssid_len_ori;
5236 remain_len = 0;
5237
5238 remain_len = ies_len -(next_ie-ies);
5239
5240 ssid_ie[1] = 0;
5241 memcpy(ssid_ie+2, next_ie, remain_len);
5242 len_diff -= ssid_len_ori;
5243
5244 break;
5245 case 2:
5246 memset(&ssid_ie[2], 0, ssid_len_ori);
5247 break;
5248 default:
5249 break;
5250 }
5251 }
5252
5253 return len_diff;
5254}
5255
5256void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms)
5257{
5258 struct xmit_frame *pmgntframe;
5259 struct pkt_attrib *pattrib;
5260 unsigned char *pframe;
5261 struct ieee80211_hdr *pwlanhdr;
5262 unsigned short *fctrl;
5263 unsigned int rate_len;
5264 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5265 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5266 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5267 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5268 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
5269 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
5270#ifdef CONFIG_8723AU_P2P
5271 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
5272#endif /* CONFIG_8723AU_P2P */
5273 u8 *wps_ie;
5274 u32 wps_ielen;
5275 u8 sr = 0;
5276 int len_diff;
5277
5278 /* DBG_8723A("%s\n", __func__); */
5279
5280 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL) {
5281 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
5282 return;
5283 }
5284#ifdef CONFIG_8723AU_AP_MODE
5285 spin_lock_bh(&pmlmepriv->bcn_update_lock);
5286#endif
5287
5288 /* update attribute */
5289 pattrib = &pmgntframe->attrib;
5290 update_mgntframe_attrib23a(padapter, pattrib);
5291 pattrib->qsel = 0x10;
5292
5293 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5294
5295 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5296 pwlanhdr = (struct ieee80211_hdr *)pframe;
5297
5298 fctrl = &pwlanhdr->frame_control;
5299 *fctrl = 0;
5300
5301 ether_addr_copy(pwlanhdr->addr1, bc_addr);
5302 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
5303 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(cur_network));
5304
5305 SetSeqNum(pwlanhdr, 0 /*pmlmeext->mgnt_seq*/);
5306 /* pmlmeext->mgnt_seq++; */
5307 SetFrameSubType(pframe, WIFI_BEACON);
5308
5309 pframe += sizeof(struct ieee80211_hdr_3addr);
5310 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
5311
5312 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
5313 /* DBG_8723A("ie len =%d\n", cur_network->IELength); */
5314#ifdef CONFIG_8723AU_P2P
5315 /* for P2P : Primary Device Type & Device Name */
5316 u32 insert_len = 0;
5317 wps_ie = rtw_get_wps_ie23a(cur_network->IEs + _FIXED_IE_LENGTH_,
5318 cur_network->IELength -
5319 _FIXED_IE_LENGTH_, NULL, &wps_ielen);
5320
5321 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wps_ie &&
5322 wps_ielen > 0) {
5323 uint wps_offset, remainder_ielen;
5324 u8 *premainder_ie, *pframe_wscie;
5325
5326 wps_offset = (uint)(wps_ie - cur_network->IEs);
5327
5328 premainder_ie = wps_ie + wps_ielen;
5329
5330 remainder_ielen = cur_network->IELength - wps_offset -
5331 wps_ielen;
5332
5333 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
5334 if (pmlmepriv->wps_beacon_ie &&
5335 pmlmepriv->wps_beacon_ie_len>0) {
5336 memcpy(pframe, cur_network->IEs,
5337 wps_offset);
5338 pframe += wps_offset;
5339 pattrib->pktlen += wps_offset;
5340
5341 memcpy(pframe, pmlmepriv->wps_beacon_ie,
5342 pmlmepriv->wps_beacon_ie_len);
5343 pframe += pmlmepriv->wps_beacon_ie_len;
5344 pattrib->pktlen +=
5345 pmlmepriv->wps_beacon_ie_len;
5346
5347 /* copy remainder_ie to pframe */
5348 memcpy(pframe, premainder_ie,
5349 remainder_ielen);
5350 pframe += remainder_ielen;
5351 pattrib->pktlen += remainder_ielen;
5352 } else {
5353 memcpy(pframe, cur_network->IEs,
5354 cur_network->IELength);
5355 pframe += cur_network->IELength;
5356 pattrib->pktlen +=
5357 cur_network->IELength;
5358 }
5359 } else {
5360 pframe_wscie = pframe + wps_offset;
5361 memcpy(pframe, cur_network->IEs,
5362 wps_offset + wps_ielen);
5363 pframe += (wps_offset + wps_ielen);
5364 pattrib->pktlen += (wps_offset + wps_ielen);
5365
5366 /* now pframe is end of wsc ie, insert Primary
5367 Device Type & Device Name */
5368 /* Primary Device Type */
5369 /* Type: */
5370 *(u16*) (pframe + insert_len) =
5371 cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
5372 insert_len += 2;
5373
5374 /* Length: */
5375 *(u16*) (pframe + insert_len) =
5376 cpu_to_be16(0x0008);
5377 insert_len += 2;
5378
5379 /* Value: */
5380 /* Category ID */
5381 *(u16*) (pframe + insert_len) =
5382 cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
5383 insert_len += 2;
5384
5385 /* OUI */
5386 *(u32*) (pframe + insert_len) =
5387 cpu_to_be32(WPSOUI);
5388 insert_len += 4;
5389
5390 /* Sub Category ID */
5391 *(u16*) (pframe + insert_len) =
5392 cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
5393 insert_len += 2;
5394
5395 /* Device Name */
5396 /* Type: */
5397 *(u16*) (pframe + insert_len) =
5398 cpu_to_be16(WPS_ATTR_DEVICE_NAME);
5399 insert_len += 2;
5400
5401 /* Length: */
5402 *(u16*) (pframe + insert_len) =
5403 cpu_to_be16(pwdinfo->device_name_len);
5404 insert_len += 2;
5405
5406 /* Value: */
5407 memcpy(pframe + insert_len,
5408 pwdinfo->device_name,
5409 pwdinfo->device_name_len);
5410 insert_len += pwdinfo->device_name_len;
5411
5412 /* update wsc ie length */
5413 *(pframe_wscie+1) = (wps_ielen -2) + insert_len;
5414
5415 /* pframe move to end */
5416 pframe+= insert_len;
5417 pattrib->pktlen += insert_len;
5418
5419 /* copy remainder_ie to pframe */
5420 memcpy(pframe, premainder_ie, remainder_ielen);
5421 pframe += remainder_ielen;
5422 pattrib->pktlen += remainder_ielen;
5423 }
5424 } else
5425#endif /* CONFIG_8723AU_P2P */
5426 memcpy(pframe, cur_network->IEs, cur_network->IELength);
5427 len_diff = update_hidden_ssid(pframe + _BEACON_IE_OFFSET_,
5428 cur_network->IELength -
5429 _BEACON_IE_OFFSET_,
5430 pmlmeinfo->hidden_ssid_mode);
5431 pframe += (cur_network->IELength+len_diff);
5432 pattrib->pktlen += (cur_network->IELength+len_diff);
5433
5434 wps_ie = rtw_get_wps_ie23a(pmgntframe->buf_addr + TXDESC_OFFSET+
5435 sizeof (struct ieee80211_hdr_3addr) +
5436 _BEACON_IE_OFFSET_, pattrib->pktlen -
5437 sizeof (struct ieee80211_hdr_3addr) -
5438 _BEACON_IE_OFFSET_, NULL,
5439 &wps_ielen);
5440 if (wps_ie && wps_ielen > 0) {
5441 rtw_get_wps_attr_content23a(wps_ie, wps_ielen,
5442 WPS_ATTR_SELECTED_REGISTRAR,
5443 (u8*)&sr, NULL);
5444 }
5445 if (sr != 0)
5446 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
5447 else
5448 _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
5449
5450#ifdef CONFIG_8723AU_P2P
5451 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
5452 u32 len;
5453 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
5454 len = pmlmepriv->p2p_beacon_ie_len;
5455 if (pmlmepriv->p2p_beacon_ie && len > 0)
5456 memcpy(pframe,
5457 pmlmepriv->p2p_beacon_ie, len);
5458 } else
5459 len = build_beacon_p2p_ie23a(pwdinfo, pframe);
5460
5461 pframe += len;
5462 pattrib->pktlen += len;
5463
5464 if (true == pwdinfo->wfd_info->wfd_enable) {
5465 len = build_beacon_wfd_ie(pwdinfo, pframe);
5466 } else {
5467 len = 0;
5468 if (pmlmepriv->wfd_beacon_ie &&
5469 pmlmepriv->wfd_beacon_ie_len>0) {
5470 len = pmlmepriv->wfd_beacon_ie_len;
5471 memcpy(pframe,
5472 pmlmepriv->wfd_beacon_ie, len);
5473 }
5474 }
5475 pframe += len;
5476 pattrib->pktlen += len;
5477 }
5478#endif /* CONFIG_8723AU_P2P */
5479
5480 goto _issue_bcn;
5481 }
5482
5483 /* below for ad-hoc mode */
5484
5485 /* timestamp will be inserted by hardware */
5486 pframe += 8;
5487 pattrib->pktlen += 8;
5488
5489 /* beacon interval: 2 bytes */
5490
5491 memcpy(pframe, (unsigned char *)
5492 rtw_get_beacon_interval23a_from_ie(cur_network->IEs), 2);
5493
5494 pframe += 2;
5495 pattrib->pktlen += 2;
5496
5497 /* capability info: 2 bytes */
5498
5499 memcpy(pframe, (unsigned char *)
5500 rtw_get_capability23a_from_ie(cur_network->IEs), 2);
5501
5502 pframe += 2;
5503 pattrib->pktlen += 2;
5504
5505 /* SSID */
5506 pframe = rtw_set_ie23a(pframe, _SSID_IE_, cur_network->Ssid.ssid_len,
5507 cur_network->Ssid.ssid, &pattrib->pktlen);
5508
5509 /* supported rates... */
5510 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
5511 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
5512 ((rate_len > 8)? 8: rate_len),
5513 cur_network->SupportedRates, &pattrib->pktlen);
5514
5515 /* DS parameter set */
5516 pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)
5517 &cur_network->Configuration.DSConfig,
5518 &pattrib->pktlen);
5519
5520 /* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */
5521 {
5522 u8 erpinfo = 0;
5523 u32 ATIMWindow;
5524 /* IBSS Parameter Set... */
5525 /* ATIMWindow = cur->Configuration.ATIMWindow; */
5526 ATIMWindow = 0;
5527 pframe = rtw_set_ie23a(pframe, _IBSS_PARA_IE_, 2,
5528 (unsigned char *)&ATIMWindow,
5529 &pattrib->pktlen);
5530
5531 /* ERP IE */
5532 pframe = rtw_set_ie23a(pframe, _ERPINFO_IE_, 1,
5533 &erpinfo, &pattrib->pktlen);
5534 }
5535
5536 /* EXTERNDED SUPPORTED RATE */
5537 if (rate_len > 8)
5538 pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
5539 rate_len - 8,
5540 cur_network->SupportedRates + 8,
5541 &pattrib->pktlen);
5542
5543 /* todo:HT for adhoc */
5544
5545_issue_bcn:
5546
5547#ifdef CONFIG_8723AU_AP_MODE
5548 pmlmepriv->update_bcn = false;
5549
5550 spin_unlock_bh(&pmlmepriv->bcn_update_lock);
5551#endif
5552
5553 if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
5554 DBG_8723A("beacon frame too large\n");
5555 return;
5556 }
5557
5558 pattrib->last_txcmdsz = pattrib->pktlen;
5559
5560 /* DBG_8723A("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */
5561 if (timeout_ms > 0)
5562 dump_mgntframe23a_and_wait(padapter, pmgntframe, timeout_ms);
5563 else
5564 dump_mgntframe23a(padapter, pmgntframe);
5565}
5566
5567void issue_probersp23a(struct rtw_adapter *padapter, unsigned char *da,
5568 u8 is_valid_p2p_probereq)
5569{
5570 struct xmit_frame *pmgntframe;
5571 struct pkt_attrib *pattrib;
5572 unsigned char *pframe;
5573 struct ieee80211_hdr *pwlanhdr;
5574 unsigned short *fctrl;
5575 unsigned char *mac, *bssid;
5576 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5577#ifdef CONFIG_8723AU_AP_MODE
5578 u8 *pwps_ie;
5579 uint wps_ielen;
5580 u8 *ssid_ie;
5581 int ssid_ielen;
5582 int ssid_ielen_diff;
5583 u8 buf[MAX_IE_SZ];
5584 u8 *ies;
5585#endif
5586#if defined(CONFIG_8723AU_AP_MODE) || defined(CONFIG_8723AU_P2P)
5587 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5588#endif
5589 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5590 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5591 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
5592 unsigned int rate_len;
5593#ifdef CONFIG_8723AU_P2P
5594 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
5595#endif /* CONFIG_8723AU_P2P */
5596
5597 /* DBG_8723A("%s\n", __func__); */
5598
5599 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
5600 {
5601 DBG_8723A("%s, alloc mgnt frame fail\n", __func__);
5602 return;
5603 }
5604
5605 /* update attribute */
5606 pattrib = &pmgntframe->attrib;
5607 update_mgntframe_attrib23a(padapter, pattrib);
5608
5609 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5610
5611 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5612 pwlanhdr = (struct ieee80211_hdr *)pframe;
5613
5614 mac = myid(&padapter->eeprompriv);
5615 bssid = cur_network->MacAddress;
5616
5617 fctrl = &pwlanhdr->frame_control;
5618 *fctrl = 0;
5619 ether_addr_copy(pwlanhdr->addr1, da);
5620 ether_addr_copy(pwlanhdr->addr2, mac);
5621 ether_addr_copy(pwlanhdr->addr3, bssid);
5622
5623 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5624 pmlmeext->mgnt_seq++;
5625 SetFrameSubType(fctrl, WIFI_PROBERSP);
5626
5627 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
5628 pattrib->pktlen = pattrib->hdrlen;
5629 pframe += pattrib->hdrlen;
5630
5631 if (cur_network->IELength > MAX_IE_SZ)
5632 return;
5633
5634#ifdef CONFIG_8723AU_AP_MODE
5635 if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
5636 pwps_ie = rtw_get_wps_ie23a(cur_network->IEs +
5637 _FIXED_IE_LENGTH_,
5638 cur_network->IELength -
5639 _FIXED_IE_LENGTH_, NULL,
5640 &wps_ielen);
5641
5642 /* inerset & update wps_probe_resp_ie */
5643 if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie &&
5644 (wps_ielen > 0)) {
5645 uint wps_offset, remainder_ielen;
5646 u8 *premainder_ie;
5647
5648 wps_offset = (uint)(pwps_ie - cur_network->IEs);
5649
5650 premainder_ie = pwps_ie + wps_ielen;
5651
5652 remainder_ielen = cur_network->IELength - wps_offset -
5653 wps_ielen;
5654
5655 memcpy(pframe, cur_network->IEs, wps_offset);
5656 pframe += wps_offset;
5657 pattrib->pktlen += wps_offset;
5658
5659 /* to get ie data len */
5660 wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];
5661 if ((wps_offset+wps_ielen+2)<= MAX_IE_SZ) {
5662 memcpy(pframe, pmlmepriv->wps_probe_resp_ie,
5663 wps_ielen+2);
5664 pframe += wps_ielen+2;
5665 pattrib->pktlen += wps_ielen+2;
5666 }
5667
5668 if ((wps_offset+wps_ielen+2+remainder_ielen) <=
5669 MAX_IE_SZ) {
5670 memcpy(pframe, premainder_ie, remainder_ielen);
5671 pframe += remainder_ielen;
5672 pattrib->pktlen += remainder_ielen;
5673 }
5674 } else {
5675 memcpy(pframe, cur_network->IEs, cur_network->IELength);
5676 pframe += cur_network->IELength;
5677 pattrib->pktlen += cur_network->IELength;
5678 }
5679
5680 /* retrieve SSID IE from cur_network->Ssid */
5681 ies = pmgntframe->buf_addr + TXDESC_OFFSET +
5682 sizeof(struct ieee80211_hdr_3addr);
5683
5684 ssid_ie = rtw_get_ie23a(ies+_FIXED_IE_LENGTH_, _SSID_IE_,
5685 &ssid_ielen,
5686 (pframe-ies)-_FIXED_IE_LENGTH_);
5687
5688 ssid_ielen_diff = cur_network->Ssid.ssid_len - ssid_ielen;
5689
5690 if (ssid_ie && cur_network->Ssid.ssid_len) {
5691 uint remainder_ielen;
5692 u8 *remainder_ie;
5693 remainder_ie = ssid_ie + 2;
5694 remainder_ielen = (pframe-remainder_ie);
5695
5696 DBG_8723A_LEVEL(_drv_warning_, FUNC_ADPT_FMT
5697 " remainder_ielen > MAX_IE_SZ\n",
5698 FUNC_ADPT_ARG(padapter));
5699 if (remainder_ielen > MAX_IE_SZ) {
5700 remainder_ielen = MAX_IE_SZ;
5701 }
5702
5703 memcpy(buf, remainder_ie, remainder_ielen);
5704 memcpy(remainder_ie+ssid_ielen_diff, buf,
5705 remainder_ielen);
5706 *(ssid_ie+1) = cur_network->Ssid.ssid_len;
5707 memcpy(ssid_ie+2, cur_network->Ssid.ssid,
5708 cur_network->Ssid.ssid_len);
5709
5710 pframe += ssid_ielen_diff;
5711 pattrib->pktlen += ssid_ielen_diff;
5712 }
5713 } else
5714#endif
5715 {
5716
5717 /* timestamp will be inserted by hardware */
5718 pframe += 8;
5719 pattrib->pktlen += 8;
5720
5721 /* beacon interval: 2 bytes */
5722
5723 memcpy(pframe, (unsigned char *)
5724 rtw_get_beacon_interval23a_from_ie(cur_network->IEs), 2);
5725
5726 pframe += 2;
5727 pattrib->pktlen += 2;
5728
5729 /* capability info: 2 bytes */
5730
5731 memcpy(pframe, (unsigned char *)
5732 rtw_get_capability23a_from_ie(cur_network->IEs), 2);
5733
5734 pframe += 2;
5735 pattrib->pktlen += 2;
5736
5737 /* below for ad-hoc mode */
5738
5739 /* SSID */
5740 pframe = rtw_set_ie23a(pframe, _SSID_IE_,
5741 cur_network->Ssid.ssid_len,
5742 cur_network->Ssid.ssid, &pattrib->pktlen);
5743
5744 /* supported rates... */
5745 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
5746 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
5747 ((rate_len > 8)? 8: rate_len),
5748 cur_network->SupportedRates,
5749 &pattrib->pktlen);
5750
5751 /* DS parameter set */
5752 pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)
5753 &cur_network->Configuration.DSConfig,
5754 &pattrib->pktlen);
5755
5756 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
5757 u8 erpinfo = 0;
5758 u32 ATIMWindow;
5759 /* IBSS Parameter Set... */
5760 /* ATIMWindow = cur->Configuration.ATIMWindow; */
5761 ATIMWindow = 0;
5762 pframe = rtw_set_ie23a(pframe, _IBSS_PARA_IE_, 2,
5763 (unsigned char *)&ATIMWindow,
5764 &pattrib->pktlen);
5765
5766 /* ERP IE */
5767 pframe = rtw_set_ie23a(pframe, _ERPINFO_IE_, 1,
5768 &erpinfo, &pattrib->pktlen);
5769 }
5770
5771 /* EXTERNDED SUPPORTED RATE */
5772 if (rate_len > 8)
5773 pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
5774 rate_len - 8,
5775 cur_network->SupportedRates + 8,
5776 &pattrib->pktlen);
5777
5778 /* todo:HT for adhoc */
5779 }
5780
5781#ifdef CONFIG_8723AU_P2P
5782 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && is_valid_p2p_probereq) {
5783 u32 len;
5784 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
5785 /* if pwdinfo->role == P2P_ROLE_DEVICE will call
5786 issue_probersp23a_p2p23a() */
5787 len = pmlmepriv->p2p_go_probe_resp_ie_len;
5788 if (pmlmepriv->p2p_go_probe_resp_ie && len>0)
5789 memcpy(pframe, pmlmepriv->p2p_go_probe_resp_ie,
5790 len);
5791 } else
5792 len = build_probe_resp_p2p_ie23a(pwdinfo, pframe);
5793
5794 pframe += len;
5795 pattrib->pktlen += len;
5796
5797 if (true == pwdinfo->wfd_info->wfd_enable) {
5798 len = build_probe_resp_wfd_ie(pwdinfo, pframe, 0);
5799 } else {
5800 len = 0;
5801 if (pmlmepriv->wfd_probe_resp_ie &&
5802 pmlmepriv->wfd_probe_resp_ie_len > 0) {
5803 len = pmlmepriv->wfd_probe_resp_ie_len;
5804 memcpy(pframe, pmlmepriv->wfd_probe_resp_ie,
5805 len);
5806 }
5807 }
5808 pframe += len;
5809 pattrib->pktlen += len;
5810 }
5811#endif /* CONFIG_8723AU_P2P */
5812
5813 pattrib->last_txcmdsz = pattrib->pktlen;
5814
5815 dump_mgntframe23a(padapter, pmgntframe);
5816
5817 return;
5818}
5819
5820static int _issue_probereq23a(struct rtw_adapter *padapter,
5821 struct cfg80211_ssid *pssid, u8 *da, int wait_ack)
5822{
5823 int ret = _FAIL;
5824 struct xmit_frame *pmgntframe;
5825 struct pkt_attrib *pattrib;
5826 unsigned char *pframe;
5827 struct ieee80211_hdr *pwlanhdr;
5828 unsigned short *fctrl;
5829 unsigned char *mac;
5830 unsigned char bssrate[NumRates];
5831 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5832 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5833 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5834 int bssrate_len = 0;
5835 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
5836
5837 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
5838 ("+issue_probereq23a\n"));
5839
5840 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
5841 goto exit;
5842
5843 /* update attribute */
5844 pattrib = &pmgntframe->attrib;
5845 update_mgntframe_attrib23a(padapter, pattrib);
5846
5847 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5848
5849 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5850 pwlanhdr = (struct ieee80211_hdr *)pframe;
5851
5852 mac = myid(&padapter->eeprompriv);
5853
5854 fctrl = &pwlanhdr->frame_control;
5855 *fctrl = 0;
5856
5857 if (da) {
5858 /* unicast probe request frame */
5859 ether_addr_copy(pwlanhdr->addr1, da);
5860 ether_addr_copy(pwlanhdr->addr3, da);
5861 } else {
5862 /* broadcast probe request frame */
5863 ether_addr_copy(pwlanhdr->addr1, bc_addr);
5864 ether_addr_copy(pwlanhdr->addr3, bc_addr);
5865 }
5866
5867 ether_addr_copy(pwlanhdr->addr2, mac);
5868
5869 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5870 pmlmeext->mgnt_seq++;
5871 SetFrameSubType(pframe, WIFI_PROBEREQ);
5872
5873 pframe += sizeof (struct ieee80211_hdr_3addr);
5874 pattrib->pktlen = sizeof (struct ieee80211_hdr_3addr);
5875
5876 if (pssid)
5877 pframe = rtw_set_ie23a(pframe, _SSID_IE_, pssid->ssid_len,
5878 pssid->ssid, &pattrib->pktlen);
5879 else
5880 pframe = rtw_set_ie23a(pframe, _SSID_IE_, 0, NULL,
5881 &pattrib->pktlen);
5882
5883 get_rate_set23a(padapter, bssrate, &bssrate_len);
5884
5885 if (bssrate_len > 8) {
5886 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
5887 bssrate, &pattrib->pktlen);
5888 pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
5889 (bssrate_len - 8), (bssrate + 8),
5890 &pattrib->pktlen);
5891 } else {
5892 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
5893 bssrate_len, bssrate, &pattrib->pktlen);
5894 }
5895
5896 /* add wps_ie for wps2.0 */
5897 if (pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie) {
5898 memcpy(pframe, pmlmepriv->wps_probe_req_ie,
5899 pmlmepriv->wps_probe_req_ie_len);
5900 pframe += pmlmepriv->wps_probe_req_ie_len;
5901 pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
5902 }
5903
5904 pattrib->last_txcmdsz = pattrib->pktlen;
5905
5906 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
5907 ("issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz));
5908
5909 if (wait_ack) {
5910 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
5911 } else {
5912 dump_mgntframe23a(padapter, pmgntframe);
5913 ret = _SUCCESS;
5914 }
5915
5916exit:
5917 return ret;
5918}
5919
5920inline void issue_probereq23a(struct rtw_adapter *padapter,
5921 struct cfg80211_ssid *pssid, u8 *da)
5922{
5923 _issue_probereq23a(padapter, pssid, da, false);
5924}
5925
5926int issue_probereq23a_ex23a(struct rtw_adapter *padapter,
5927 struct cfg80211_ssid *pssid, u8 *da,
5928 int try_cnt, int wait_ms)
5929{
5930 int ret;
5931 int i = 0;
5932 unsigned long start = jiffies;
5933
5934 do {
5935 ret = _issue_probereq23a(padapter, pssid, da,
5936 wait_ms > 0 ? true : false);
5937
5938 i++;
5939
5940 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
5941 break;
5942
5943 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
5944 msleep(wait_ms);
5945
5946 } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
5947
5948 if (ret != _FAIL) {
5949 ret = _SUCCESS;
5950 goto exit;
5951 }
5952
5953 if (try_cnt && wait_ms) {
5954 if (da)
5955 DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d "
5956 "in %u ms\n", FUNC_ADPT_ARG(padapter),
5957 MAC_ARG(da), rtw_get_oper_ch23a(padapter),
5958 ret == _SUCCESS?", acked":"", i, try_cnt,
5959 jiffies_to_msecs(jiffies - start));
5960 else
5961 DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
5962 FUNC_ADPT_ARG(padapter),
5963 rtw_get_oper_ch23a(padapter),
5964 ret == _SUCCESS?", acked":"", i, try_cnt,
5965 jiffies_to_msecs(jiffies - start));
5966 }
5967exit:
5968 return ret;
5969}
5970
5971/* if psta == NULL, indiate we are station(client) now... */
5972void issue_auth23a(struct rtw_adapter *padapter, struct sta_info *psta,
5973 unsigned short status)
5974{
5975 struct xmit_frame *pmgntframe;
5976 struct pkt_attrib *pattrib;
5977 unsigned char *pframe;
5978 struct ieee80211_hdr *pwlanhdr;
5979 unsigned short *fctrl;
5980 unsigned int val32;
5981 unsigned short val16;
5982 int use_shared_key = 0;
5983 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5984 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5985 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
5986
5987 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
5988 return;
5989
5990 /* update attribute */
5991 pattrib = &pmgntframe->attrib;
5992 update_mgntframe_attrib23a(padapter, pattrib);
5993
5994 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5995
5996 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5997 pwlanhdr = (struct ieee80211_hdr *)pframe;
5998
5999 fctrl = &pwlanhdr->frame_control;
6000 *fctrl = 0;
6001
6002 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6003 pmlmeext->mgnt_seq++;
6004 SetFrameSubType(pframe, WIFI_AUTH);
6005
6006 pframe += sizeof(struct ieee80211_hdr_3addr);
6007 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
6008
6009 if (psta) { /* for AP mode */
6010#ifdef CONFIG_8723AU_AP_MODE
6011
6012 ether_addr_copy(pwlanhdr->addr1, psta->hwaddr);
6013 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
6014 ether_addr_copy(pwlanhdr->addr3, myid(&padapter->eeprompriv));
6015
6016 /* setting auth algo number */
6017 val16 = (u16)psta->authalg;
6018
6019 if (status != WLAN_STATUS_SUCCESS)
6020 val16 = 0;
6021
6022 if (val16) {
6023 val16 = cpu_to_le16(val16);
6024 use_shared_key = 1;
6025 }
6026
6027 pframe = rtw_set_fixed_ie23a(pframe, _AUTH_ALGM_NUM_,
6028 (unsigned char *)&val16,
6029 &pattrib->pktlen);
6030
6031 /* setting auth seq number */
6032 val16 = (u16)psta->auth_seq;
6033 val16 = cpu_to_le16(val16);
6034 pframe = rtw_set_fixed_ie23a(pframe, _AUTH_SEQ_NUM_,
6035 (unsigned char *)&val16,
6036 &pattrib->pktlen);
6037
6038 /* setting status code... */
6039 val16 = status;
6040 val16 = cpu_to_le16(val16);
6041 pframe = rtw_set_fixed_ie23a(pframe, _STATUS_CODE_,
6042 (unsigned char *)&val16,
6043 &pattrib->pktlen);
6044
6045 /* added challenging text... */
6046 if ((psta->auth_seq == 2) &&
6047 (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
6048 pframe = rtw_set_ie23a(pframe, _CHLGETXT_IE_, 128,
6049 psta->chg_txt, &pattrib->pktlen);
6050#endif
6051 } else {
6052 ether_addr_copy(pwlanhdr->addr1,
6053 get_my_bssid23a(&pmlmeinfo->network));
6054 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
6055 ether_addr_copy(pwlanhdr->addr3,
6056 get_my_bssid23a(&pmlmeinfo->network));
6057
6058 /* setting auth algo number */
6059 /* 0:OPEN System, 1:Shared key */
6060 val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)? 1: 0;
6061 if (val16) {
6062 val16 = cpu_to_le16(val16);
6063 use_shared_key = 1;
6064 }
6065 /* DBG_8723A("%s auth_algo = %s auth_seq =%d\n", __func__,
6066 (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED",
6067 pmlmeinfo->auth_seq); */
6068
6069 /* setting IV for auth seq #3 */
6070 if ((pmlmeinfo->auth_seq == 3) &&
6071 (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
6072 (use_shared_key == 1)) {
6073 /* DBG_8723A("==> iv(%d), key_index(%d)\n",
6074 pmlmeinfo->iv, pmlmeinfo->key_index); */
6075 val32 = ((pmlmeinfo->iv++) |
6076 (pmlmeinfo->key_index << 30));
6077 val32 = cpu_to_le32(val32);
6078 pframe = rtw_set_fixed_ie23a(pframe, 4,
6079 (unsigned char *)&val32,
6080 &pattrib->pktlen);
6081
6082 pattrib->iv_len = 4;
6083 }
6084
6085 pframe = rtw_set_fixed_ie23a(pframe, _AUTH_ALGM_NUM_,
6086 (unsigned char *)&val16,
6087 &pattrib->pktlen);
6088
6089 /* setting auth seq number */
6090 val16 = pmlmeinfo->auth_seq;
6091 val16 = cpu_to_le16(val16);
6092 pframe = rtw_set_fixed_ie23a(pframe, _AUTH_SEQ_NUM_,
6093 (unsigned char *)&val16,
6094 &pattrib->pktlen);
6095
6096 /* setting status code... */
6097 val16 = status;
6098 val16 = cpu_to_le16(val16);
6099 pframe = rtw_set_fixed_ie23a(pframe, _STATUS_CODE_,
6100 (unsigned char *)&val16,
6101 &pattrib->pktlen);
6102
6103 /* then checking to see if sending challenging text... */
6104 if ((pmlmeinfo->auth_seq == 3) &&
6105 (pmlmeinfo->state & WIFI_FW_AUTH_STATE) &&
6106 (use_shared_key == 1)) {
6107 pframe = rtw_set_ie23a(pframe, _CHLGETXT_IE_, 128,
6108 pmlmeinfo->chg_txt,
6109 &pattrib->pktlen);
6110
6111 SetPrivacy(fctrl);
6112
6113 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
6114
6115 pattrib->encrypt = _WEP40_;
6116
6117 pattrib->icv_len = 4;
6118
6119 pattrib->pktlen += pattrib->icv_len;
6120 }
6121 }
6122
6123 pattrib->last_txcmdsz = pattrib->pktlen;
6124
6125 rtw_wep_encrypt23a(padapter, pmgntframe);
6126 DBG_8723A("%s\n", __func__);
6127 dump_mgntframe23a(padapter, pmgntframe);
6128
6129 return;
6130}
6131
6132void issue_asocrsp23a(struct rtw_adapter *padapter, unsigned short status,
6133 struct sta_info *pstat, int pkt_type)
6134{
6135#ifdef CONFIG_8723AU_AP_MODE
6136 struct xmit_frame *pmgntframe;
6137 struct ieee80211_hdr *pwlanhdr;
6138 struct pkt_attrib *pattrib;
6139 unsigned char *pbuf, *pframe;
6140 unsigned short val;
6141 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6142 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6143 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6144 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6145 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
6146 u8 *ie = pnetwork->IEs;
6147#ifdef CONFIG_8723AU_P2P
6148 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
6149 u32 wfdielen = 0;
6150#endif /* CONFIG_8723AU_P2P */
6151
6152 DBG_8723A("%s\n", __func__);
6153
6154 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
6155 return;
6156
6157 /* update attribute */
6158 pattrib = &pmgntframe->attrib;
6159 update_mgntframe_attrib23a(padapter, pattrib);
6160
6161 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6162
6163 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6164 pwlanhdr = (struct ieee80211_hdr *)pframe;
6165
6166 pwlanhdr->frame_control = 0;
6167
6168 ether_addr_copy(pwlanhdr->addr1, pstat->hwaddr);
6169 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
6170 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
6171
6172 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6173 pmlmeext->mgnt_seq++;
6174 if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
6175 SetFrameSubType(pwlanhdr, pkt_type);
6176 else
6177 return;
6178
6179 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
6180 pattrib->pktlen += pattrib->hdrlen;
6181 pframe += pattrib->hdrlen;
6182
6183 /* capability */
6184 val = *(unsigned short *)rtw_get_capability23a_from_ie(ie);
6185
6186 pframe = rtw_set_fixed_ie23a(pframe, _CAPABILITY_,
6187 (unsigned char *)&val, &pattrib->pktlen);
6188
6189 status = cpu_to_le16(status);
6190 pframe = rtw_set_fixed_ie23a(pframe, _STATUS_CODE_,
6191 (unsigned char *)&status,
6192 &pattrib->pktlen);
6193
6194 val = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
6195 pframe = rtw_set_fixed_ie23a(pframe, _ASOC_ID_, (unsigned char *)&val,
6196 &pattrib->pktlen);
6197
6198 if (pstat->bssratelen <= 8) {
6199 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
6200 pstat->bssratelen, pstat->bssrateset,
6201 &pattrib->pktlen);
6202 } else {
6203 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
6204 pstat->bssrateset, &pattrib->pktlen);
6205 pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
6206 pstat->bssratelen - 8,
6207 pstat->bssrateset + 8, &pattrib->pktlen);
6208 }
6209
6210 if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
6211 uint ie_len = 0;
6212
6213 /* FILL HT CAP INFO IE */
6214 /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
6215 pbuf = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_,
6216 _HT_CAPABILITY_IE_, &ie_len,
6217 pnetwork->IELength - _BEACON_IE_OFFSET_);
6218 if (pbuf && ie_len>0) {
6219 memcpy(pframe, pbuf, ie_len + 2);
6220 pframe += (ie_len + 2);
6221 pattrib->pktlen += (ie_len + 2);
6222 }
6223
6224 /* FILL HT ADD INFO IE */
6225 /* p = hostapd_eid_ht_operation(hapd, p); */
6226 pbuf = rtw_get_ie23a(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_,
6227 &ie_len,
6228 pnetwork->IELength - _BEACON_IE_OFFSET_);
6229 if (pbuf && ie_len > 0) {
6230 memcpy(pframe, pbuf, ie_len + 2);
6231 pframe += (ie_len + 2);
6232 pattrib->pktlen += (ie_len + 2);
6233 }
6234 }
6235
6236 /* FILL WMM IE */
6237 if ((pstat->flags & WLAN_STA_WME) && pmlmepriv->qospriv.qos_option) {
6238 uint ie_len = 0;
6239 unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02,
6240 0x01, 0x01};
6241
6242 for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) {
6243 pbuf = rtw_get_ie23a(pbuf, _VENDOR_SPECIFIC_IE_,
6244 &ie_len, (pnetwork->IELength -
6245 _BEACON_IE_OFFSET_ -
6246 (ie_len + 2)));
6247 if (pbuf && !memcmp(pbuf + 2, WMM_PARA_IE, 6)) {
6248 memcpy(pframe, pbuf, ie_len + 2);
6249 pframe += (ie_len + 2);
6250 pattrib->pktlen += (ie_len + 2);
6251
6252 break;
6253 }
6254
6255 if ((!pbuf) || (ie_len == 0))
6256 break;
6257 }
6258 }
6259
6260 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
6261 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, 6,
6262 REALTEK_96B_IE23A, &pattrib->pktlen);
6263 }
6264
6265 /* add WPS IE ie for wps 2.0 */
6266 if (pmlmepriv->wps_assoc_resp_ie &&
6267 pmlmepriv->wps_assoc_resp_ie_len > 0) {
6268 memcpy(pframe, pmlmepriv->wps_assoc_resp_ie,
6269 pmlmepriv->wps_assoc_resp_ie_len);
6270
6271 pframe += pmlmepriv->wps_assoc_resp_ie_len;
6272 pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
6273 }
6274
6275#ifdef CONFIG_8723AU_P2P
6276 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) &&
6277 pwdinfo->wfd_info->wfd_enable) {
6278 wfdielen = build_assoc_resp_wfd_ie(pwdinfo, pframe);
6279 pframe += wfdielen;
6280 pattrib->pktlen += wfdielen;
6281 }
6282#endif /* CONFIG_8723AU_P2P */
6283
6284 pattrib->last_txcmdsz = pattrib->pktlen;
6285
6286 dump_mgntframe23a(padapter, pmgntframe);
6287#endif
6288}
6289
6290void issue_assocreq23a(struct rtw_adapter *padapter)
6291{
6292 int ret = _FAIL;
6293 struct xmit_frame *pmgntframe;
6294 struct pkt_attrib *pattrib;
6295 unsigned char *pframe, *p;
6296 struct ieee80211_hdr *pwlanhdr;
6297 unsigned short *fctrl;
6298 unsigned short val16;
6299 unsigned int i, j, ie_len, index = 0;
6300 unsigned char rf_type, bssrate[NumRates], sta_bssrate[NumRates];
6301 struct ndis_802_11_var_ies *pIE;
6302 struct registry_priv *pregpriv = &padapter->registrypriv;
6303 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6304 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6305 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6306 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6307 int bssrate_len = 0, sta_bssrate_len = 0;
6308#ifdef CONFIG_8723AU_P2P
6309 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
6310 u8 p2pie[255] = { 0x00 };
6311 u16 p2pielen = 0;
6312 u32 wfdielen = 0;
6313#endif /* CONFIG_8723AU_P2P */
6314
6315 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
6316 goto exit;
6317
6318 /* update attribute */
6319 pattrib = &pmgntframe->attrib;
6320 update_mgntframe_attrib23a(padapter, pattrib);
6321
6322 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6323
6324 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6325 pwlanhdr = (struct ieee80211_hdr *)pframe;
6326
6327 fctrl = &pwlanhdr->frame_control;
6328 *fctrl = 0;
6329 ether_addr_copy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network));
6330 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
6331 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
6332
6333 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6334 pmlmeext->mgnt_seq++;
6335 SetFrameSubType(pframe, WIFI_ASSOCREQ);
6336
6337 pframe += sizeof(struct ieee80211_hdr_3addr);
6338 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
6339
6340 /* caps */
6341 memcpy(pframe, rtw_get_capability23a_from_ie(pmlmeinfo->network.IEs),
6342 2);
6343
6344 pframe += 2;
6345 pattrib->pktlen += 2;
6346
6347 /* listen interval */
6348 /* todo: listen interval for power saving */
6349 val16 = cpu_to_le16(3);
6350 memcpy(pframe, (unsigned char *)&val16, 2);
6351 pframe += 2;
6352 pattrib->pktlen += 2;
6353
6354 /* SSID */
6355 pframe = rtw_set_ie23a(pframe, _SSID_IE_,
6356 pmlmeinfo->network.Ssid.ssid_len,
6357 pmlmeinfo->network.Ssid.ssid, &pattrib->pktlen);
6358
6359 /* supported rate & extended supported rate */
6360
6361 get_rate_set23a(padapter, sta_bssrate, &sta_bssrate_len);
6362 /* DBG_8723A("sta_bssrate_len =%d\n", sta_bssrate_len); */
6363
6364 /* for JAPAN, channel 14 can only uses B Mode(CCK) */
6365 if (pmlmeext->cur_channel == 14)
6366 sta_bssrate_len = 4;
6367
6368 /* for (i = 0; i < sta_bssrate_len; i++) { */
6369 /* DBG_8723A("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */
6370 /* */
6371
6372 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
6373 if (pmlmeinfo->network.SupportedRates[i] == 0)
6374 break;
6375 DBG_8723A("network.SupportedRates[%d]=%02X\n", i,
6376 pmlmeinfo->network.SupportedRates[i]);
6377 }
6378
6379 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
6380 if (pmlmeinfo->network.SupportedRates[i] == 0)
6381 break;
6382
6383 /* Check if the AP's supported rates are also
6384 supported by STA. */
6385 for (j = 0; j < sta_bssrate_len; j++) {
6386 /* Avoid the proprietary data rate (22Mbps) of
6387 Handlink WSG-4000 AP */
6388 if ((pmlmeinfo->network.SupportedRates[i] |
6389 IEEE80211_BASIC_RATE_MASK) ==
6390 (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)) {
6391 /* DBG_8723A("match i = %d, j =%d\n", i, j); */
6392 break;
6393 }
6394 }
6395
6396 if (j == sta_bssrate_len) {
6397 /* the rate is not supported by STA */
6398 DBG_8723A("%s(): the rate[%d]=%02X is not supported by "
6399 "STA!\n", __func__, i,
6400 pmlmeinfo->network.SupportedRates[i]);
6401 } else {
6402 /* the rate is supported by STA */
6403 bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
6404 }
6405 }
6406
6407 bssrate_len = index;
6408 DBG_8723A("bssrate_len = %d\n", bssrate_len);
6409
6410 if (bssrate_len == 0) {
6411 rtw_free_xmitbuf23a(pxmitpriv, pmgntframe->pxmitbuf);
6412 rtw_free_xmitframe23a(pxmitpriv, pmgntframe);
6413 goto exit; /* don't connect to AP if no joint supported rate */
6414 }
6415
6416 if (bssrate_len > 8) {
6417 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, 8,
6418 bssrate, &pattrib->pktlen);
6419 pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_,
6420 (bssrate_len - 8), (bssrate + 8),
6421 &pattrib->pktlen);
6422 } else
6423 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_,
6424 bssrate_len, bssrate, &pattrib->pktlen);
6425
6426 /* RSN */
6427 p = rtw_get_ie23a((pmlmeinfo->network.IEs +
6428 sizeof(struct ndis_802_11_fixed_ies)), _RSN_IE_2_,
6429 &ie_len, (pmlmeinfo->network.IELength -
6430 sizeof(struct ndis_802_11_fixed_ies)));
6431 if (p)
6432 pframe = rtw_set_ie23a(pframe, _RSN_IE_2_, ie_len, (p + 2),
6433 &pattrib->pktlen);
6434
6435 /* HT caps */
6436 if (padapter->mlmepriv.htpriv.ht_option == true) {
6437 p = rtw_get_ie23a((pmlmeinfo->network.IEs +
6438 sizeof(struct ndis_802_11_fixed_ies)),
6439 _HT_CAPABILITY_IE_, &ie_len,
6440 (pmlmeinfo->network.IELength -
6441 sizeof(struct ndis_802_11_fixed_ies)));
6442 if ((p != NULL) && (!(is_ap_in_tkip23a(padapter)))) {
6443 memcpy(&pmlmeinfo->HT_caps, (p + 2),
6444 sizeof(struct HT_caps_element));
6445
6446 /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
6447 if (pregpriv->cbw40_enable == 0) {
6448 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &= (~(BIT(6) | BIT(1)));
6449 } else {
6450 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= BIT(1);
6451 }
6452
6453 /* todo: disable SM power save mode */
6454 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |=
6455 0x000c;
6456
6457 rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE,
6458 (u8 *)(&rf_type));
6459 /* switch (pregpriv->rf_config) */
6460 switch (rf_type)
6461 {
6462 case RF_1T1R:
6463
6464 if (pregpriv->rx_stbc)
6465 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
6466
6467 memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R23A, 16);
6468 break;
6469
6470 case RF_2T2R:
6471 case RF_1T2R:
6472 default:
6473
6474 /* enable for 2.4/5 GHz */
6475 if ((pregpriv->rx_stbc == 0x3) ||
6476 ((pmlmeext->cur_wireless_mode &
6477 WIRELESS_11_24N) &&
6478 /* enable for 2.4GHz */
6479 (pregpriv->rx_stbc == 0x1)) ||
6480 ((pmlmeext->cur_wireless_mode &
6481 WIRELESS_11_5N) &&
6482 (pregpriv->rx_stbc == 0x2)) ||
6483 /* enable for 5GHz */
6484 (pregpriv->wifi_spec == 1)) {
6485 DBG_8723A("declare supporting RX "
6486 "STBC\n");
6487 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */
6488 }
6489 memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_2R23A, 16);
6490 break;
6491 }
6492 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info =
6493 cpu_to_le16(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);
6494
6495#ifdef CONFIG_8723AU_BT_COEXIST
6496 if (BT_1Ant(padapter) == true) {
6497 /* set to 8K */
6498 pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para &= (u8)~IEEE80211_HT_AMPDU_PARM_FACTOR;
6499/* pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para |= MAX_AMPDU_FACTOR_8K */
6500 }
6501#endif
6502
6503 pframe = rtw_set_ie23a(pframe, _HT_CAPABILITY_IE_,
6504 ie_len,
6505 (u8 *)&pmlmeinfo->HT_caps,
6506 &pattrib->pktlen);
6507 }
6508 }
6509
6510 /* vendor specific IE, such as WPA, WMM, WPS */
6511 for (i = sizeof(struct ndis_802_11_fixed_ies);
6512 i < pmlmeinfo->network.IELength;) {
6513 pIE = (struct ndis_802_11_var_ies *)
6514 (pmlmeinfo->network.IEs + i);
6515
6516 switch (pIE->ElementID)
6517 {
6518 case _VENDOR_SPECIFIC_IE_:
6519 if (!memcmp(pIE->data, RTW_WPA_OUI23A, 4) ||
6520 !memcmp(pIE->data, WMM_OUI23A, 4) ||
6521 !memcmp(pIE->data, WPS_OUI23A, 4)) {
6522 if (!padapter->registrypriv.wifi_spec) {
6523 /* Commented by Kurt 20110629 */
6524 /* In some older APs, WPS handshake */
6525 /* would be fail if we append vender
6526 extensions informations to AP */
6527 if (!memcmp(pIE->data, WPS_OUI23A, 4))
6528 pIE->Length = 14;
6529 }
6530 pframe = rtw_set_ie23a(pframe,
6531 _VENDOR_SPECIFIC_IE_,
6532 pIE->Length, pIE->data,
6533 &pattrib->pktlen);
6534 }
6535 break;
6536
6537 default:
6538 break;
6539 }
6540
6541 i += (pIE->Length + 2);
6542 }
6543
6544 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
6545 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, 6,
6546 REALTEK_96B_IE23A, &pattrib->pktlen);
6547
6548#ifdef CONFIG_8723AU_P2P
6549
6550 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) {
6551 if (pmlmepriv->p2p_assoc_req_ie &&
6552 pmlmepriv->p2p_assoc_req_ie_len>0) {
6553 memcpy(pframe, pmlmepriv->p2p_assoc_req_ie,
6554 pmlmepriv->p2p_assoc_req_ie_len);
6555 pframe += pmlmepriv->p2p_assoc_req_ie_len;
6556 pattrib->pktlen += pmlmepriv->p2p_assoc_req_ie_len;
6557 }
6558 } else {
6559 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
6560 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
6561 /* Should add the P2P IE in the association
6562 request frame. */
6563 /* P2P OUI */
6564
6565 p2pielen = 0;
6566 p2pie[p2pielen++] = 0x50;
6567 p2pie[p2pielen++] = 0x6F;
6568 p2pie[p2pielen++] = 0x9A;
6569 p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
6570
6571 /* Commented by Albert 20101109 */
6572 /* According to the P2P Specification, the
6573 association request frame should contain
6574 3 P2P attributes */
6575 /* 1. P2P Capability */
6576 /* 2. Extended Listen Timing */
6577 /* 3. Device Info */
6578 /* Commented by Albert 20110516 */
6579 /* 4. P2P Interface */
6580
6581 /* P2P Capability */
6582 /* Type: */
6583 p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
6584
6585 /* Length: */
6586 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002);
6587 p2pielen += 2;
6588
6589 /* Value: */
6590 /* Device Capability Bitmap, 1 byte */
6591 p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
6592
6593 /* Group Capability Bitmap, 1 byte */
6594 if (pwdinfo->persistent_supported)
6595 p2pie[p2pielen++] =
6596 P2P_GRPCAP_PERSISTENT_GROUP |
6597 DMP_P2P_GRPCAP_SUPPORT;
6598 else
6599 p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
6600
6601 /* Extended Listen Timing */
6602 /* Type: */
6603 p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
6604
6605 /* Length: */
6606 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004);
6607 p2pielen += 2;
6608
6609 /* Value: */
6610 /* Availability Period */
6611 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
6612 p2pielen += 2;
6613
6614 /* Availability Interval */
6615 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF);
6616 p2pielen += 2;
6617
6618 /* Device Info */
6619 /* Type: */
6620 p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
6621
6622 /* Length: */
6623 /* 21 -> P2P Device Address (6bytes) + Config
6624 Methods (2bytes) + Primary Device
6625 Type (8bytes) */
6626 /* + NumofSecondDevType (1byte) + WPS Device
6627 Name ID field (2bytes) + WPS Device Name
6628 Len field (2bytes) */
6629 *(u16*) (p2pie + p2pielen) =
6630 cpu_to_le16(21 + pwdinfo->device_name_len);
6631 p2pielen += 2;
6632
6633 /* Value: */
6634 /* P2P Device Address */
6635 memcpy(p2pie + p2pielen,
6636 myid(&padapter->eeprompriv), ETH_ALEN);
6637 p2pielen += ETH_ALEN;
6638
6639 /* Config Method */
6640 /* This field should be big endian.
6641 Noted by P2P specification. */
6642 if ((pwdinfo->ui_got_wps_info ==
6643 P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) ||
6644 (pwdinfo->ui_got_wps_info ==
6645 P2P_GOT_WPSINFO_SELF_DISPLAY_PIN))
6646 *(u16*) (p2pie + p2pielen) =
6647 cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
6648 else
6649 *(u16*) (p2pie + p2pielen) =
6650 cpu_to_be16(WPS_CONFIG_METHOD_PBC);
6651
6652 p2pielen += 2;
6653
6654 /* Primary Device Type */
6655 /* Category ID */
6656 *(u16*) (p2pie + p2pielen) =
6657 cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
6658 p2pielen += 2;
6659
6660 /* OUI */
6661 *(u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI);
6662 p2pielen += 4;
6663
6664 /* Sub Category ID */
6665 *(u16*) (p2pie + p2pielen) =
6666 cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
6667 p2pielen += 2;
6668
6669 /* Number of Secondary Device Types */
6670 /* No Secondary Device Type List */
6671 p2pie[p2pielen++] = 0x00;
6672
6673 /* Device Name */
6674 /* Type: */
6675 *(u16*) (p2pie + p2pielen) =
6676 cpu_to_be16(WPS_ATTR_DEVICE_NAME);
6677 p2pielen += 2;
6678
6679 /* Length: */
6680 *(u16*) (p2pie + p2pielen) =
6681 cpu_to_be16(pwdinfo->device_name_len);
6682 p2pielen += 2;
6683
6684 /* Value: */
6685 memcpy(p2pie + p2pielen, pwdinfo->device_name,
6686 pwdinfo->device_name_len);
6687 p2pielen += pwdinfo->device_name_len;
6688
6689 /* P2P Interface */
6690 /* Type: */
6691 p2pie[p2pielen++] = P2P_ATTR_INTERFACE;
6692
6693 /* Length: */
6694 *(u16*) (p2pie + p2pielen) = cpu_to_le16(0x000D);
6695 p2pielen += 2;
6696
6697 /* Value: */
6698 memcpy(p2pie + p2pielen, pwdinfo->device_addr,
6699 ETH_ALEN); /* P2P Device Address */
6700 p2pielen += ETH_ALEN;
6701
6702 /* P2P Interface Address Count */
6703 p2pie[p2pielen++] = 1;
6704
6705 memcpy(p2pie + p2pielen, pwdinfo->device_addr,
6706 ETH_ALEN); /* P2P Interface Address List */
6707 p2pielen += ETH_ALEN;
6708
6709 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_,
6710 p2pielen, (unsigned char *)p2pie,
6711 &pattrib->pktlen);
6712
6713 /* wfdielen = build_assoc_req_wfd_ie(pwdinfo, pframe);*/
6714 /* pframe += wfdielen; */
6715 /* pattrib->pktlen += wfdielen; */
6716 }
6717 }
6718
6719 if (true == pwdinfo->wfd_info->wfd_enable) {
6720 wfdielen = build_assoc_req_wfd_ie(pwdinfo, pframe);
6721 pframe += wfdielen;
6722 pattrib->pktlen += wfdielen;
6723 } else if (pmlmepriv->wfd_assoc_req_ie != NULL &&
6724 pmlmepriv->wfd_assoc_req_ie_len > 0) {
6725 /* WFD IE */
6726 memcpy(pframe, pmlmepriv->wfd_assoc_req_ie,
6727 pmlmepriv->wfd_assoc_req_ie_len);
6728 pattrib->pktlen += pmlmepriv->wfd_assoc_req_ie_len;
6729 pframe += pmlmepriv->wfd_assoc_req_ie_len;
6730 }
6731#endif /* CONFIG_8723AU_P2P */
6732
6733 pattrib->last_txcmdsz = pattrib->pktlen;
6734 dump_mgntframe23a(padapter, pmgntframe);
6735
6736 ret = _SUCCESS;
6737
6738exit:
6739 pmlmepriv->assoc_req_len = 0;
6740 if (ret == _SUCCESS) {
6741 kfree(pmlmepriv->assoc_req);
6742 pmlmepriv->assoc_req = kmalloc(pattrib->pktlen, GFP_ATOMIC);
6743 if (pmlmepriv->assoc_req) {
6744 memcpy(pmlmepriv->assoc_req, pwlanhdr,
6745 pattrib->pktlen);
6746 pmlmepriv->assoc_req_len = pattrib->pktlen;
6747 }
6748 } else
6749 kfree(pmlmepriv->assoc_req);
6750
6751 return;
6752}
6753
6754/* when wait_ack is ture, this function shoule be called at process context */
6755static int _issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
6756 unsigned int power_mode, int wait_ack)
6757{
6758 int ret = _FAIL;
6759 struct xmit_frame *pmgntframe;
6760 struct pkt_attrib *pattrib;
6761 unsigned char *pframe;
6762 struct ieee80211_hdr *pwlanhdr;
6763 unsigned short *fctrl;
6764 struct xmit_priv *pxmitpriv;
6765 struct mlme_ext_priv *pmlmeext;
6766 struct mlme_ext_info *pmlmeinfo;
6767
6768 /* DBG_8723A("%s:%d\n", __func__, power_mode); */
6769
6770 if (!padapter)
6771 goto exit;
6772
6773 pxmitpriv = &padapter->xmitpriv;
6774 pmlmeext = &padapter->mlmeextpriv;
6775 pmlmeinfo = &pmlmeext->mlmext_info;
6776
6777 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
6778 goto exit;
6779
6780 /* update attribute */
6781 pattrib = &pmgntframe->attrib;
6782 update_mgntframe_attrib23a(padapter, pattrib);
6783 pattrib->retry_ctrl = false;
6784
6785 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6786
6787 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6788 pwlanhdr = (struct ieee80211_hdr *)pframe;
6789
6790 fctrl = &pwlanhdr->frame_control;
6791 *fctrl = 0;
6792
6793 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
6794 SetFrDs(fctrl);
6795 else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
6796 SetToDs(fctrl);
6797
6798 if (power_mode)
6799 SetPwrMgt(fctrl);
6800
6801 ether_addr_copy(pwlanhdr->addr1, da);
6802 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
6803 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
6804
6805 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6806 pmlmeext->mgnt_seq++;
6807 SetFrameSubType(pframe, WIFI_DATA_NULL);
6808
6809 pframe += sizeof(struct ieee80211_hdr_3addr);
6810 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
6811
6812 pattrib->last_txcmdsz = pattrib->pktlen;
6813
6814 if (wait_ack)
6815 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
6816 else {
6817 dump_mgntframe23a(padapter, pmgntframe);
6818 ret = _SUCCESS;
6819 }
6820
6821exit:
6822 return ret;
6823}
6824
6825/* when wait_ms >0 , this function shoule be called at process context */
6826/* da == NULL for station mode */
6827int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
6828 unsigned int power_mode, int try_cnt, int wait_ms)
6829{
6830 int ret;
6831 int i = 0;
6832 unsigned long start = jiffies;
6833 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6834 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6835
6836 /* da == NULL, assum it's null data for sta to ap*/
6837 if (da == NULL)
6838 da = get_my_bssid23a(&pmlmeinfo->network);
6839
6840 do {
6841 ret = _issue_nulldata23a(padapter, da, power_mode,
6842 wait_ms > 0 ? true : false);
6843
6844 i++;
6845
6846 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
6847 break;
6848
6849 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
6850 msleep(wait_ms);
6851
6852 } while((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
6853
6854 if (ret != _FAIL) {
6855 ret = _SUCCESS;
6856 goto exit;
6857 }
6858
6859 if (try_cnt && wait_ms) {
6860 if (da)
6861 DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d "
6862 "in %u ms\n", FUNC_ADPT_ARG(padapter),
6863 MAC_ARG(da), rtw_get_oper_ch23a(padapter),
6864 ret == _SUCCESS?", acked":"", i, try_cnt,
6865 jiffies_to_msecs(jiffies - start));
6866 else
6867 DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
6868 FUNC_ADPT_ARG(padapter),
6869 rtw_get_oper_ch23a(padapter),
6870 ret == _SUCCESS?", acked":"", i, try_cnt,
6871 jiffies_to_msecs(jiffies - start));
6872 }
6873exit:
6874 return ret;
6875}
6876
6877/* when wait_ack is ture, this function shoule be called at process context */
6878static int _issue_qos_nulldata23a(struct rtw_adapter *padapter,
6879 unsigned char *da, u16 tid, int wait_ack)
6880{
6881 int ret = _FAIL;
6882 struct xmit_frame *pmgntframe;
6883 struct pkt_attrib *pattrib;
6884 unsigned char *pframe;
6885 struct ieee80211_hdr *pwlanhdr;
6886 unsigned short *fctrl, *qc;
6887 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6888 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6889 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6890
6891 DBG_8723A("%s\n", __func__);
6892
6893 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
6894 goto exit;
6895
6896 /* update attribute */
6897 pattrib = &pmgntframe->attrib;
6898 update_mgntframe_attrib23a(padapter, pattrib);
6899
6900 pattrib->hdrlen += 2;
6901 pattrib->qos_en = true;
6902 pattrib->eosp = 1;
6903 pattrib->ack_policy = 0;
6904 pattrib->mdata = 0;
6905
6906 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6907
6908 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6909 pwlanhdr = (struct ieee80211_hdr *)pframe;
6910
6911 fctrl = &pwlanhdr->frame_control;
6912 *fctrl = 0;
6913
6914 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
6915 SetFrDs(fctrl);
6916 else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
6917 SetToDs(fctrl);
6918
6919 if (pattrib->mdata)
6920 SetMData(fctrl);
6921
6922 qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
6923
6924 SetPriority(qc, tid);
6925
6926 SetEOSP(qc, pattrib->eosp);
6927
6928 SetAckpolicy(qc, pattrib->ack_policy);
6929
6930 ether_addr_copy(pwlanhdr->addr1, da);
6931 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
6932 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
6933
6934 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6935 pmlmeext->mgnt_seq++;
6936 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
6937
6938 pframe += sizeof(struct ieee80211_qos_hdr);
6939 pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
6940
6941 pattrib->last_txcmdsz = pattrib->pktlen;
6942
6943 if (wait_ack)
6944 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
6945 else {
6946 dump_mgntframe23a(padapter, pmgntframe);
6947 ret = _SUCCESS;
6948 }
6949
6950exit:
6951 return ret;
6952}
6953
6954/* when wait_ms >0 , this function shoule be called at process context */
6955/* da == NULL for station mode */
6956int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
6957 u16 tid, int try_cnt, int wait_ms)
6958{
6959 int ret;
6960 int i = 0;
6961 unsigned long start = jiffies;
6962 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6963 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
6964
6965 /* da == NULL, assum it's null data for sta to ap*/
6966 if (da == NULL)
6967 da = get_my_bssid23a(&pmlmeinfo->network);
6968
6969 do {
6970 ret = _issue_qos_nulldata23a(padapter, da, tid,
6971 wait_ms > 0 ? true : false);
6972
6973 i++;
6974
6975 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
6976 break;
6977
6978 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
6979 msleep(wait_ms);
6980 } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
6981
6982 if (ret != _FAIL) {
6983 ret = _SUCCESS;
6984 goto exit;
6985 }
6986
6987 if (try_cnt && wait_ms) {
6988 if (da)
6989 DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d "
6990 "in %u ms\n", FUNC_ADPT_ARG(padapter),
6991 MAC_ARG(da), rtw_get_oper_ch23a(padapter),
6992 ret == _SUCCESS?", acked":"", i, try_cnt,
6993 jiffies_to_msecs(jiffies - start));
6994 else
6995 DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
6996 FUNC_ADPT_ARG(padapter),
6997 rtw_get_oper_ch23a(padapter),
6998 ret == _SUCCESS?", acked":"", i, try_cnt,
6999 jiffies_to_msecs(jiffies - start));
7000 }
7001exit:
7002 return ret;
7003}
7004
7005static int _issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
7006 unsigned short reason, u8 wait_ack)
7007{
7008 struct xmit_frame *pmgntframe;
7009 struct pkt_attrib *pattrib;
7010 unsigned char *pframe;
7011 struct ieee80211_hdr *pwlanhdr;
7012 unsigned short *fctrl;
7013 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
7014 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7015 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7016 int ret = _FAIL;
7017#ifdef CONFIG_8723AU_P2P
7018 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
7019#endif /* CONFIG_8723AU_P2P */
7020
7021 /* DBG_8723A("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); */
7022
7023#ifdef CONFIG_8723AU_P2P
7024 if (!(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) &&
7025 (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
7026 mod_timer(&pwdinfo->reset_ch_sitesurvey,
7027 jiffies + msecs_to_jiffies(10));
7028 }
7029#endif /* CONFIG_8723AU_P2P */
7030
7031 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
7032 goto exit;
7033
7034 /* update attribute */
7035 pattrib = &pmgntframe->attrib;
7036 update_mgntframe_attrib23a(padapter, pattrib);
7037 pattrib->retry_ctrl = false;
7038
7039 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7040
7041 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7042 pwlanhdr = (struct ieee80211_hdr *)pframe;
7043
7044 fctrl = &pwlanhdr->frame_control;
7045 *fctrl = 0;
7046
7047 ether_addr_copy(pwlanhdr->addr1, da);
7048 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
7049 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
7050
7051 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7052 pmlmeext->mgnt_seq++;
7053 SetFrameSubType(pframe, WIFI_DEAUTH);
7054
7055 pframe += sizeof(struct ieee80211_hdr_3addr);
7056 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
7057
7058 reason = cpu_to_le16(reason);
7059 pframe = rtw_set_fixed_ie23a(pframe, WLAN_REASON_PREV_AUTH_NOT_VALID,
7060 (unsigned char *)&reason,
7061 &pattrib->pktlen);
7062
7063 pattrib->last_txcmdsz = pattrib->pktlen;
7064
7065 if (wait_ack)
7066 ret = dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe);
7067 else {
7068 dump_mgntframe23a(padapter, pmgntframe);
7069 ret = _SUCCESS;
7070 }
7071
7072exit:
7073 return ret;
7074}
7075
7076int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
7077 unsigned short reason)
7078{
7079 DBG_8723A("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
7080 return _issue_deauth23a(padapter, da, reason, false);
7081}
7082
7083int issue_deauth23a_ex23a(struct rtw_adapter *padapter, u8 *da,
7084 unsigned short reason, int try_cnt, int wait_ms)
7085{
7086 int ret;
7087 int i = 0;
7088 unsigned long start = jiffies;
7089
7090 do {
7091 ret = _issue_deauth23a(padapter, da, reason,
7092 wait_ms >0 ? true : false);
7093
7094 i++;
7095
7096 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
7097 break;
7098
7099 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
7100 msleep(wait_ms);
7101
7102 } while((i < try_cnt) && ((ret == _FAIL)||(wait_ms == 0)));
7103
7104 if (ret != _FAIL) {
7105 ret = _SUCCESS;
7106 goto exit;
7107 }
7108
7109 if (try_cnt && wait_ms) {
7110 if (da)
7111 DBG_8723A(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d "
7112 "in %u ms\n", FUNC_ADPT_ARG(padapter),
7113 MAC_ARG(da), rtw_get_oper_ch23a(padapter),
7114 ret == _SUCCESS?", acked":"", i, try_cnt,
7115 jiffies_to_msecs(jiffies - start));
7116 else
7117 DBG_8723A(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
7118 FUNC_ADPT_ARG(padapter),
7119 rtw_get_oper_ch23a(padapter),
7120 ret == _SUCCESS?", acked":"", i, try_cnt,
7121 jiffies_to_msecs(jiffies - start));
7122 }
7123exit:
7124 return ret;
7125}
7126
7127void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter,
7128 u8 *ra, u8 new_ch, u8 ch_offset)
7129{
7130 struct xmit_frame *pmgntframe;
7131 struct pkt_attrib *pattrib;
7132 unsigned char *pframe;
7133 struct ieee80211_hdr *pwlanhdr;
7134 unsigned short *fctrl;
7135 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
7136 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7137 u8 category, action;
7138
7139 DBG_8723A(FUNC_NDEV_FMT" ra ="MAC_FMT", ch:%u, offset:%u\n",
7140 FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(ra),
7141 new_ch, ch_offset);
7142
7143 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
7144 return;
7145
7146 /* update attribute */
7147 pattrib = &pmgntframe->attrib;
7148 update_mgntframe_attrib23a(padapter, pattrib);
7149
7150 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7151
7152 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7153 pwlanhdr = (struct ieee80211_hdr *)pframe;
7154
7155 fctrl = &pwlanhdr->frame_control;
7156 *fctrl = 0;
7157
7158 ether_addr_copy(pwlanhdr->addr1, ra); /* RA */
7159 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv)); /* TA */
7160 ether_addr_copy(pwlanhdr->addr3, ra); /* DA = RA */
7161
7162 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7163 pmlmeext->mgnt_seq++;
7164 SetFrameSubType(pframe, WIFI_ACTION);
7165
7166 pframe += sizeof(struct ieee80211_hdr_3addr);
7167 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
7168
7169 /* category, action */
7170 category = WLAN_CATEGORY_SPECTRUM_MGMT;
7171 action = WLAN_ACTION_SPCT_CHL_SWITCH;
7172
7173 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
7174 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
7175
7176 pframe = rtw_set_ie23a_ch_switch (pframe, &pattrib->pktlen, 0,
7177 new_ch, 0);
7178 pframe = rtw_set_ie23a_secondary_ch_offset(pframe, &pattrib->pktlen,
7179 hal_ch_offset_to_secondary_ch_offset23a(ch_offset));
7180
7181 pattrib->last_txcmdsz = pattrib->pktlen;
7182
7183 dump_mgntframe23a(padapter, pmgntframe);
7184}
7185
7186void issue_action_BA23a(struct rtw_adapter *padapter, unsigned char *raddr,
7187 unsigned char action, unsigned short status)
7188{
7189 u8 category = WLAN_CATEGORY_BACK;
7190 u16 start_seq;
7191 u16 BA_para_set;
7192 u16 reason_code;
7193 u16 BA_timeout_value;
7194 u16 BA_starting_seqctrl;
7195 int max_rx_ampdu_factor;
7196 struct xmit_frame *pmgntframe;
7197 struct pkt_attrib *pattrib;
7198 u8 *pframe;
7199 struct ieee80211_hdr *pwlanhdr;
7200 u16 *fctrl;
7201 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
7202 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7203 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7204 struct sta_info *psta;
7205 struct sta_priv *pstapriv = &padapter->stapriv;
7206 struct registry_priv *pregpriv = &padapter->registrypriv;
7207#ifdef CONFIG_8723AU_BT_COEXIST
7208 u8 tendaAPMac[] = {0xC8, 0x3A, 0x35};
7209#endif
7210
7211 DBG_8723A("%s, category =%d, action =%d, status =%d\n",
7212 __func__, category, action, status);
7213
7214 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
7215 return;
7216
7217 /* update attribute */
7218 pattrib = &pmgntframe->attrib;
7219 update_mgntframe_attrib23a(padapter, pattrib);
7220
7221 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7222
7223 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7224 pwlanhdr = (struct ieee80211_hdr *)pframe;
7225
7226 fctrl = &pwlanhdr->frame_control;
7227 *fctrl = 0;
7228
7229 /* memcpy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN); */
7230 ether_addr_copy(pwlanhdr->addr1, raddr);
7231 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
7232 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
7233
7234 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7235 pmlmeext->mgnt_seq++;
7236 SetFrameSubType(pframe, WIFI_ACTION);
7237
7238 pframe += sizeof(struct ieee80211_hdr_3addr);
7239 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
7240
7241 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
7242 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
7243
7244 status = cpu_to_le16(status);
7245
7246 if (category != 3)
7247 goto out;
7248
7249 switch (action)
7250 {
7251 case 0: /* ADDBA req */
7252 do {
7253 pmlmeinfo->dialogToken++;
7254 } while (pmlmeinfo->dialogToken == 0);
7255 pframe = rtw_set_fixed_ie23a(pframe, 1, &pmlmeinfo->dialogToken,
7256 &pattrib->pktlen);
7257
7258#ifdef CONFIG_8723AU_BT_COEXIST
7259 if ((BT_1Ant(padapter) == true) &&
7260 ((pmlmeinfo->assoc_AP_vendor != broadcomAP) ||
7261 memcmp(raddr, tendaAPMac, 3))) {
7262 /* A-MSDU NOT Supported */
7263 BA_para_set = 0;
7264 /* immediate Block Ack */
7265 BA_para_set |= (1 << 1) &
7266 IEEE80211_ADDBA_PARAM_POLICY_MASK;
7267 /* TID */
7268 BA_para_set |= (status << 2) &
7269 IEEE80211_ADDBA_PARAM_TID_MASK;
7270 /* max buffer size is 8 MSDU */
7271 BA_para_set |= (8 << 6) &
7272 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
7273 } else
7274#endif
7275 {
7276 /* immediate ack & 64 buffer size */
7277 BA_para_set = (0x1002 | ((status & 0xf) << 2));
7278 }
7279 BA_para_set = cpu_to_le16(BA_para_set);
7280 pframe = rtw_set_fixed_ie23a(pframe, 2,
7281 (unsigned char *)&BA_para_set,
7282 &pattrib->pktlen);
7283
7284 BA_timeout_value = 5000;/* 5ms */
7285 BA_timeout_value = cpu_to_le16(BA_timeout_value);
7286 pframe = rtw_set_fixed_ie23a(pframe, 2, (unsigned char *)
7287 &BA_timeout_value,
7288 &pattrib->pktlen);
7289
7290 /* if ((psta = rtw_get_stainfo23a(pstapriv,
7291 pmlmeinfo->network.MacAddress)) != NULL) */
7292 if ((psta = rtw_get_stainfo23a(pstapriv, raddr))) {
7293 start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
7294
7295 DBG_8723A("BA_starting_seqctrl = %d for TID =%d\n",
7296 start_seq, status & 0x07);
7297
7298 psta->BA_starting_seqctrl[status & 0x07] = start_seq;
7299
7300 BA_starting_seqctrl = start_seq << 4;
7301 }
7302
7303 BA_starting_seqctrl = cpu_to_le16(BA_starting_seqctrl);
7304 pframe = rtw_set_fixed_ie23a(pframe, 2, (unsigned char *)&BA_starting_seqctrl, &pattrib->pktlen);
7305 break;
7306
7307 case 1: /* ADDBA rsp */
7308 pframe = rtw_set_fixed_ie23a(pframe, 1, &pmlmeinfo->ADDBA_req.dialog_token, &pattrib->pktlen);
7309 pframe = rtw_set_fixed_ie23a(pframe, 2,
7310 (unsigned char *)&status,
7311 &pattrib->pktlen);
7312 rtw_hal_get_def_var23a(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
7313 &max_rx_ampdu_factor);
7314 if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_64K)
7315 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
7316 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_32K)
7317 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */
7318 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_16K)
7319 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */
7320 else if (max_rx_ampdu_factor == IEEE80211_HT_MAX_AMPDU_8K)
7321 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */
7322 else
7323 BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
7324
7325#ifdef CONFIG_8723AU_BT_COEXIST
7326 if ((BT_1Ant(padapter) == true) &&
7327 ((pmlmeinfo->assoc_AP_vendor != broadcomAP) ||
7328 memcmp(raddr, tendaAPMac, 3))) {
7329 /* max buffer size is 8 MSDU */
7330 BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
7331 BA_para_set |= (8 << 6) &
7332 IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
7333 }
7334#endif
7335
7336 if (pregpriv->ampdu_amsdu == 0)/* disabled */
7337 BA_para_set = cpu_to_le16(BA_para_set & ~BIT(0));
7338 else if (pregpriv->ampdu_amsdu == 1)/* enabled */
7339 BA_para_set = cpu_to_le16(BA_para_set | BIT(0));
7340 else /* auto */
7341 BA_para_set = cpu_to_le16(BA_para_set);
7342
7343 pframe = rtw_set_fixed_ie23a(pframe, 2,
7344 (unsigned char *)&BA_para_set,
7345 &pattrib->pktlen);
7346 pframe = rtw_set_fixed_ie23a(pframe, 2, (unsigned char *)&pmlmeinfo->ADDBA_req.BA_timeout_value, &pattrib->pktlen);
7347 break;
7348 case 2:/* DELBA */
7349 BA_para_set = (status & 0x1F) << 3;
7350 BA_para_set = cpu_to_le16(BA_para_set);
7351 pframe = rtw_set_fixed_ie23a(pframe, 2,
7352 (unsigned char *)&BA_para_set,
7353 &pattrib->pktlen);
7354
7355 reason_code = 37;/* Requested from peer STA as it does not
7356 want to use the mechanism */
7357 reason_code = cpu_to_le16(reason_code);
7358 pframe = rtw_set_fixed_ie23a(pframe, 2,
7359 (unsigned char *)&reason_code,
7360 &pattrib->pktlen);
7361 break;
7362 default:
7363 break;
7364 }
7365
7366out:
7367 pattrib->last_txcmdsz = pattrib->pktlen;
7368
7369 dump_mgntframe23a(padapter, pmgntframe);
7370}
7371
7372static void issue_action_BSSCoexistPacket(struct rtw_adapter *padapter)
7373{
7374 struct list_head *plist, *phead, *ptmp;
7375 unsigned char category, action;
7376 struct xmit_frame *pmgntframe;
7377 struct pkt_attrib *pattrib;
7378 unsigned char *pframe;
7379 struct ieee80211_hdr *pwlanhdr;
7380 unsigned short *fctrl;
7381 struct wlan_network *pnetwork = NULL;
7382 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
7383 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
7384 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7385 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7386 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
7387 u8 InfoContent[16] = {0};
7388 u8 ICS[8][15];
7389
7390 if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
7391 return;
7392
7393 if (true == pmlmeinfo->bwmode_updated)
7394 return;
7395
7396 DBG_8723A("%s\n", __func__);
7397
7398 category = WLAN_CATEGORY_PUBLIC;
7399 action = ACT_PUBLIC_BSSCOEXIST;
7400
7401 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
7402 {
7403 return;
7404 }
7405
7406 /* update attribute */
7407 pattrib = &pmgntframe->attrib;
7408 update_mgntframe_attrib23a(padapter, pattrib);
7409
7410 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7411
7412 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7413 pwlanhdr = (struct ieee80211_hdr *)pframe;
7414
7415 fctrl = &pwlanhdr->frame_control;
7416 *fctrl = 0;
7417
7418 ether_addr_copy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network));
7419 ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv));
7420 ether_addr_copy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network));
7421
7422 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7423 pmlmeext->mgnt_seq++;
7424 SetFrameSubType(pframe, WIFI_ACTION);
7425
7426 pframe += sizeof(struct ieee80211_hdr_3addr);
7427 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
7428
7429 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
7430 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
7431
7432 /* */
7433 if (pmlmepriv->num_FortyMHzIntolerant>0)
7434 {
7435 u8 iedata = 0;
7436
7437 iedata |= BIT(2);/* 20 MHz BSS Width Request */
7438
7439 pframe = rtw_set_ie23a(pframe, EID_BSSCoexistence, 1, &iedata, &pattrib->pktlen);
7440
7441 }
7442
7443 /* */
7444 memset(ICS, 0, sizeof(ICS));
7445 if (pmlmepriv->num_sta_no_ht>0)
7446 {
7447 int i;
7448
7449 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
7450
7451 phead = get_list_head(queue);
7452 plist = phead->next;
7453
7454 list_for_each_safe(plist, ptmp, phead) {
7455 int len;
7456 u8 *p;
7457 struct wlan_bssid_ex *pbss_network;
7458
7459 pnetwork = container_of(plist, struct wlan_network,
7460 list);
7461
7462 pbss_network = &pnetwork->network;
7463
7464 p = rtw_get_ie23a(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
7465 if ((p == NULL) || (len == 0))/* non-HT */
7466 {
7467 if ((pbss_network->Configuration.DSConfig<= 0) || (pbss_network->Configuration.DSConfig>14))
7468 continue;
7469
7470 ICS[0][pbss_network->Configuration.DSConfig]= 1;
7471
7472 if (ICS[0][0] == 0)
7473 ICS[0][0] = 1;
7474 }
7475
7476 }
7477
7478 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
7479
7480 for (i = 0;i<8;i++)
7481 {
7482 if (ICS[i][0] == 1)
7483 {
7484 int j, k = 0;
7485
7486 InfoContent[k] = i;
7487 /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
7488 k++;
7489
7490 for (j = 1;j<= 14;j++)
7491 {
7492 if (ICS[i][j]== 1)
7493 {
7494 if (k<16)
7495 {
7496 InfoContent[k] = j; /* channel number */
7497 /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
7498 k++;
7499 }
7500 }
7501 }
7502
7503 pframe = rtw_set_ie23a(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &pattrib->pktlen);
7504
7505 }
7506
7507 }
7508
7509 }
7510
7511 pattrib->last_txcmdsz = pattrib->pktlen;
7512
7513 dump_mgntframe23a(padapter, pmgntframe);
7514}
7515
7516unsigned int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr)
7517{
7518 struct sta_priv *pstapriv = &padapter->stapriv;
7519 struct sta_info *psta = NULL;
7520 /* struct recv_reorder_ctrl *preorder_ctrl; */
7521 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7522 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7523 u16 tid;
7524
7525 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
7526 if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
7527 return _SUCCESS;
7528
7529 psta = rtw_get_stainfo23a(pstapriv, addr);
7530 if (psta == NULL)
7531 return _SUCCESS;
7532
7533 if (initiator == 0) { /* recipient */
7534 for (tid = 0; tid < MAXTID; tid++) {
7535 if (psta->recvreorder_ctrl[tid].enable == true) {
7536 DBG_8723A("rx agg disable tid(%d)\n", tid);
7537 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
7538 psta->recvreorder_ctrl[tid].enable = false;
7539 psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
7540 }
7541 }
7542 } else if (initiator == 1) { /* originator */
7543 for (tid = 0; tid < MAXTID; tid++) {
7544 if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
7545 DBG_8723A("tx agg disable tid(%d)\n", tid);
7546 issue_action_BA23a(padapter, addr, WLAN_ACTION_DELBA, (((tid <<1) |initiator)&0x1F));
7547 psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
7548 psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
7549
7550 }
7551 }
7552 }
7553 return _SUCCESS;
7554}
7555
7556unsigned int send_beacon23a(struct rtw_adapter *padapter)
7557{
7558 u8 bxmitok = false;
7559 int issue = 0;
7560 int poll = 0;
7561 unsigned long start = jiffies;
7562 unsigned int passing_time;
7563
7564 rtw_hal_set_hwreg23a(padapter, HW_VAR_BCN_VALID, NULL);
7565 do {
7566 issue_beacon23a(padapter, 100);
7567 issue++;
7568 do {
7569 yield();
7570 rtw23a_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
7571 poll++;
7572 } while ((poll%10)!= 0 && false == bxmitok &&
7573 !padapter->bSurpriseRemoved &&
7574 !padapter->bDriverStopped);
7575
7576 } while (!bxmitok && issue<100 && !padapter->bSurpriseRemoved &&
7577 !padapter->bDriverStopped);
7578
7579 if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
7580 return _FAIL;
7581
7582 passing_time = jiffies_to_msecs(jiffies - start);
7583
7584 if (!bxmitok) {
7585 DBG_8723A("%s fail! %u ms\n", __func__, passing_time);
7586 return _FAIL;
7587 } else {
7588
7589 if (passing_time > 100 || issue > 3)
7590 DBG_8723A("%s success, issue:%d, poll:%d, %u ms\n",
7591 __func__, issue, poll, passing_time);
7592 return _SUCCESS;
7593 }
7594}
7595
7596/****************************************************************************
7597
7598Following are some utitity fuctions for WiFi MLME
7599
7600*****************************************************************************/
7601
7602bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel)
7603{
7604
7605 int i = 0;
7606 u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
7607 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
7608 124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,
7609 161, 163, 165};
7610 for (i = 0; i < sizeof(Channel_5G); i++)
7611 if (channel == Channel_5G[i])
7612 return true;
7613 return false;
7614}
7615
7616void site_survey23a(struct rtw_adapter *padapter)
7617{
7618 unsigned char survey_channel = 0, val8;
7619 enum rt_scan_type ScanType = SCAN_PASSIVE;
7620 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7621 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7622 u32 initialgain = 0;
7623#ifdef CONFIG_8723AU_P2P
7624 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
7625
7626 if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) ||
7627 (pwdinfo->p2p_info.scan_op_ch_only)) {
7628 if (pwdinfo->rx_invitereq_info.scan_op_ch_only)
7629 survey_channel = pwdinfo->rx_invitereq_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
7630 else
7631 survey_channel = pwdinfo->p2p_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
7632 ScanType = SCAN_ACTIVE;
7633 } else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) {
7634 /* The driver is in the find phase, it should go through the social channel. */
7635 int ch_set_idx;
7636 survey_channel = pwdinfo->social_chan[pmlmeext->sitesurvey_res.channel_idx];
7637 ch_set_idx = rtw_ch_set_search_ch23a(pmlmeext->channel_set, survey_channel);
7638 if (ch_set_idx >= 0)
7639 ScanType = pmlmeext->channel_set[ch_set_idx].ScanType;
7640 else
7641 ScanType = SCAN_ACTIVE;
7642 } else
7643#endif /* CONFIG_8723AU_P2P */
7644 {
7645 struct rtw_ieee80211_channel *ch;
7646 if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
7647 ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
7648 survey_channel = ch->hw_value;
7649 ScanType = (ch->flags & IEEE80211_CHAN_NO_IR) ? SCAN_PASSIVE : SCAN_ACTIVE;
7650}
7651 }
7652
7653 if (survey_channel != 0) {
7654 /* PAUSE 4-AC Queue when site_survey23a */
7655 /* rtw23a_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
7656 /* val8 |= 0x0f; */
7657 /* rtw_hal_set_hwreg23a(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
7658 if (pmlmeext->sitesurvey_res.channel_idx == 0)
7659 set_channel_bwmode23a(padapter, survey_channel,
7660 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
7661 HT_CHANNEL_WIDTH_20);
7662 else
7663 SelectChannel23a(padapter, survey_channel);
7664
7665 if (ScanType == SCAN_ACTIVE) /* obey the channel plan setting... */
7666 {
7667#ifdef CONFIG_8723AU_P2P
7668 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) ||
7669 rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)
7670 )
7671 {
7672 issue23a_probereq_p2p(padapter, NULL);
7673 issue23a_probereq_p2p(padapter, NULL);
7674 issue23a_probereq_p2p(padapter, NULL);
7675 }
7676 else
7677#endif /* CONFIG_8723AU_P2P */
7678 {
7679 int i;
7680 for (i = 0;i<RTW_SSID_SCAN_AMOUNT;i++) {
7681 if (pmlmeext->sitesurvey_res.ssid[i].ssid_len) {
7682 /* todo: to issue two probe req??? */
7683 issue_probereq23a(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
7684 /* msleep(SURVEY_TO>>1); */
7685 issue_probereq23a(padapter, &pmlmeext->sitesurvey_res.ssid[i], NULL);
7686 }
7687 }
7688
7689 if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
7690 /* todo: to issue two probe req??? */
7691 issue_probereq23a(padapter, NULL, NULL);
7692 /* msleep(SURVEY_TO>>1); */
7693 issue_probereq23a(padapter, NULL, NULL);
7694 }
7695 }
7696 }
7697
7698 set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
7699 } else {
7700
7701 /* channel number is 0 or this channel is not valid. */
7702
7703
7704#ifdef CONFIG_8723AU_P2P
7705 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
7706 {
7707 if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only))
7708 {
7709 /* Set the find_phase_state_exchange_cnt to P2P_FINDPHASE_EX_CNT. */
7710 /* This will let the following flow to run the scanning end. */
7711 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
7712 }
7713 }
7714
7715 if (rtw_p2p_findphase_ex_is_needed(pwdinfo))
7716 {
7717 /* Set the P2P State to the listen state of find phase and set the current channel to the listen channel */
7718 set_channel_bwmode23a(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
7719 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
7720 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
7721
7722 initialgain = 0xff; /* restore RX GAIN */
7723 rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
7724 /* turn on dynamic functions */
7725 Restore_DM_Func_Flag23a(padapter);
7726 /* Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DIG|DYNAMIC_FUNC_HP|DYNAMIC_FUNC_SS, true); */
7727
7728 mod_timer(&pwdinfo->find_phase_timer, jiffies +
7729 msecs_to_jiffies(pwdinfo->listen_dwell * 100));
7730 } else
7731#endif /* CONFIG_8723AU_P2P */
7732 {
7733#ifdef CONFIG_8723AU_P2P
7734 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
7735 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
7736 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
7737#endif /* CONFIG_8723AU_P2P */
7738
7739 pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
7740
7741 /* switch back to the original channel */
7742
7743 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
7744
7745 /* flush 4-AC Queue after site_survey23a */
7746 /* val8 = 0; */
7747 /* rtw_hal_set_hwreg23a(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
7748
7749 /* config MSR */
7750 Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
7751
7752 initialgain = 0xff; /* restore RX GAIN */
7753 rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
7754 /* turn on dynamic functions */
7755 Restore_DM_Func_Flag23a(padapter);
7756 /* Switch_DM_Func23a(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
7757
7758 if (is_client_associated_to_ap23a(padapter) == true)
7759 {
7760 issue_nulldata23a(padapter, NULL, 0, 3, 500);
7761
7762 }
7763
7764 val8 = 0; /* survey done */
7765 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
7766
7767 report_surveydone_event23a(padapter);
7768
7769 pmlmeext->chan_scan_time = SURVEY_TO;
7770 pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
7771
7772 issue_action_BSSCoexistPacket(padapter);
7773 issue_action_BSSCoexistPacket(padapter);
7774 issue_action_BSSCoexistPacket(padapter);
7775
7776 }
7777 }
7778
7779 return;
7780}
7781
7782/* collect bss info from Beacon and Probe request/response frames. */
7783u8 collect_bss_info23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
7784{
7785 int i;
7786 u32 len;
7787 u8 *p;
7788 u16 val16;
7789 struct sk_buff *skb = precv_frame->pkt;
7790 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
7791 u8 *pframe = skb->data;
7792 u32 packet_len = skb->len;
7793 u8 ie_offset;
7794 struct registry_priv *pregistrypriv = &padapter->registrypriv;
7795 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7796 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7797
7798 len = packet_len - sizeof(struct ieee80211_hdr_3addr);
7799
7800 if (len > MAX_IE_SZ)
7801 {
7802 /* DBG_8723A("IE too long for survey event\n"); */
7803 return _FAIL;
7804 }
7805
7806 memset(bssid, 0, sizeof(struct wlan_bssid_ex));
7807
7808 if (ieee80211_is_beacon(hdr->frame_control)) {
7809 bssid->reserved = 1;
7810 ie_offset = _BEACON_IE_OFFSET_;
7811 } else {
7812 /* FIXME : more type */
7813 if (ieee80211_is_probe_req(hdr->frame_control)) {
7814 ie_offset = _PROBEREQ_IE_OFFSET_;
7815 bssid->reserved = 2;
7816 } else if (ieee80211_is_probe_resp(hdr->frame_control)) {
7817 ie_offset = _PROBERSP_IE_OFFSET_;
7818 bssid->reserved = 3;
7819 } else {
7820 bssid->reserved = 0;
7821 ie_offset = _FIXED_IE_LENGTH_;
7822 }
7823 }
7824
7825 bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
7826
7827 /* below is to copy the information element */
7828 bssid->IELength = len;
7829 memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
7830
7831 /* get the signal strength */
7832 bssid->Rssi = precv_frame->attrib.phy_info.RecvSignalPower; /* in dBM.raw data */
7833 bssid->PhyInfo.SignalQuality = precv_frame->attrib.phy_info.SignalQuality;/* in percentage */
7834 bssid->PhyInfo.SignalStrength = precv_frame->attrib.phy_info.SignalStrength;/* in percentage */
7835
7836 /* checking SSID */
7837 if ((p = rtw_get_ie23a(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset)) == NULL)
7838 {
7839 DBG_8723A("marc: cannot find SSID for survey event\n");
7840 return _FAIL;
7841 }
7842
7843 if (*(p + 1)) {
7844 if (len > IEEE80211_MAX_SSID_LEN) {
7845 DBG_8723A("%s()-%d: IE too long (%d) for survey "
7846 "event\n", __func__, __LINE__, len);
7847 return _FAIL;
7848 }
7849 memcpy(bssid->Ssid.ssid, (p + 2), *(p + 1));
7850 bssid->Ssid.ssid_len = *(p + 1);
7851 } else {
7852 bssid->Ssid.ssid_len = 0;
7853 }
7854
7855 memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
7856
7857 /* checking rate info... */
7858 i = 0;
7859 p = rtw_get_ie23a(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
7860 if (p != NULL)
7861 {
7862 if (len > NDIS_802_11_LENGTH_RATES_EX)
7863 {
7864 DBG_8723A("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
7865 return _FAIL;
7866 }
7867 memcpy(bssid->SupportedRates, (p + 2), len);
7868 i = len;
7869 }
7870
7871 p = rtw_get_ie23a(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
7872 if (p != NULL)
7873 {
7874 if (len > (NDIS_802_11_LENGTH_RATES_EX-i))
7875 {
7876 DBG_8723A("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
7877 return _FAIL;
7878 }
7879 memcpy(bssid->SupportedRates + i, (p + 2), len);
7880 }
7881
7882 /* todo: */
7883 {
7884 bssid->NetworkTypeInUse = Ndis802_11OFDM24;
7885 }
7886
7887 if (bssid->IELength < 12)
7888 return _FAIL;
7889
7890 /* Checking for DSConfig */
7891 p = rtw_get_ie23a(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
7892
7893 bssid->Configuration.DSConfig = 0;
7894 bssid->Configuration.Length = 0;
7895
7896 if (p)
7897 {
7898 bssid->Configuration.DSConfig = *(p + 2);
7899 }
7900 else
7901 {/* In 5G, some ap do not have DSSET IE */
7902 /* checking HT info for channel */
7903 p = rtw_get_ie23a(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
7904 if (p)
7905 {
7906 struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
7907 bssid->Configuration.DSConfig = HT_info->primary_channel;
7908 }
7909 else
7910 { /* use current channel */
7911 bssid->Configuration.DSConfig = rtw_get_oper_ch23a(padapter);
7912 }
7913 }
7914
7915 if (ieee80211_is_probe_req(hdr->frame_control)) {
7916 /* FIXME */
7917 bssid->InfrastructureMode = Ndis802_11Infrastructure;
7918 ether_addr_copy(bssid->MacAddress, hdr->addr2);
7919 bssid->Privacy = 1;
7920 return _SUCCESS;
7921 }
7922
7923 memcpy(&bssid->Configuration.BeaconPeriod, rtw_get_beacon_interval23a_from_ie(bssid->IEs), 2);
7924 bssid->Configuration.BeaconPeriod = le32_to_cpu(bssid->Configuration.BeaconPeriod);
7925
7926 val16 = rtw_get_capability23a(bssid);
7927
7928 if (val16 & BIT(0)) {
7929 bssid->InfrastructureMode = Ndis802_11Infrastructure;
7930 ether_addr_copy(bssid->MacAddress, hdr->addr2);
7931 } else {
7932 bssid->InfrastructureMode = Ndis802_11IBSS;
7933 ether_addr_copy(bssid->MacAddress, hdr->addr3);
7934 }
7935
7936 if (val16 & BIT(4))
7937 bssid->Privacy = 1;
7938 else
7939 bssid->Privacy = 0;
7940
7941 bssid->Configuration.ATIMWindow = 0;
7942
7943 /* 20/40 BSS Coexistence check */
7944 if ((pregistrypriv->wifi_spec == 1) && (false == pmlmeinfo->bwmode_updated))
7945 {
7946 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
7947
7948 p = rtw_get_ie23a(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
7949 if (p && len > 0) {
7950 struct HT_caps_element *pHT_caps;
7951 pHT_caps = (struct HT_caps_element *)(p + 2);
7952
7953 if (pHT_caps->u.HT_cap_element.HT_caps_info & BIT(14))
7954 pmlmepriv->num_FortyMHzIntolerant++;
7955 } else
7956 {
7957 pmlmepriv->num_sta_no_ht++;
7958 }
7959 }
7960
7961
7962 /* mark bss info receving from nearby channel as SignalQuality 101 */
7963 if (bssid->Configuration.DSConfig != rtw_get_oper_ch23a(padapter))
7964 bssid->PhyInfo.SignalQuality = 101;
7965
7966 return _SUCCESS;
7967}
7968
7969void start_create_ibss23a(struct rtw_adapter* padapter)
7970{
7971 unsigned short caps;
7972 u8 val8;
7973 u8 join_type;
7974 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
7975 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
7976 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
7977 pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
7978 pmlmeinfo->bcn_interval = get_beacon_interval23a(pnetwork);
7979
7980 /* update wireless mode */
7981 update_wireless_mode23a(padapter);
7982
7983 /* udpate capability */
7984 caps = rtw_get_capability23a(pnetwork);
7985 update_capinfo23a(padapter, caps);
7986 if (caps&cap_IBSS)/* adhoc master */
7987 {
7988 val8 = 0xcf;
7989 rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
7990
7991 /* switch channel */
7992 /* SelectChannel23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
7993 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
7994
7995 beacon_timing_control23a(padapter);
7996
7997 /* set msr to WIFI_FW_ADHOC_STATE */
7998 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
7999 Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
8000
8001 /* issue beacon */
8002 if (send_beacon23a(padapter) == _FAIL)
8003 {
8004 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n"));
8005
8006 report_join_res23a(padapter, -1);
8007 pmlmeinfo->state = WIFI_FW_NULL_STATE;
8008 }
8009 else
8010 {
8011 rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
8012 join_type = 0;
8013 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
8014
8015 report_join_res23a(padapter, 1);
8016 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
8017 }
8018 }
8019 else
8020 {
8021 DBG_8723A("start_create_ibss23a, invalid cap:%x\n", caps);
8022 return;
8023 }
8024}
8025
8026void start_clnt_join23a(struct rtw_adapter* padapter)
8027{
8028 unsigned short caps;
8029 u8 val8;
8030 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8031 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8032 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
8033 int beacon_timeout;
8034
8035 pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
8036 pmlmeinfo->bcn_interval = get_beacon_interval23a(pnetwork);
8037
8038 /* update wireless mode */
8039 update_wireless_mode23a(padapter);
8040
8041 /* udpate capability */
8042 caps = rtw_get_capability23a(pnetwork);
8043 update_capinfo23a(padapter, caps);
8044 if (caps&cap_ESS) {
8045 /* switch channel */
8046 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
8047
8048 Set_MSR23a(padapter, WIFI_FW_STATION_STATE);
8049
8050 val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
8051
8052 rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
8053
8054 /* switch channel */
8055 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
8056
8057 /* here wait for receiving the beacon to start auth */
8058 /* and enable a timer */
8059 beacon_timeout = decide_wait_for_beacon_timeout23a(pmlmeinfo->bcn_interval);
8060 set_link_timer(pmlmeext, beacon_timeout);
8061 mod_timer(&padapter->mlmepriv.assoc_timer, jiffies +
8062 msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout));
8063 pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
8064 }
8065 else if (caps&cap_IBSS) /* adhoc client */
8066 {
8067 Set_MSR23a(padapter, WIFI_FW_ADHOC_STATE);
8068
8069 val8 = 0xcf;
8070 rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
8071
8072 /* switch channel */
8073 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
8074
8075 beacon_timing_control23a(padapter);
8076
8077 pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
8078
8079 report_join_res23a(padapter, 1);
8080 }
8081 else
8082 {
8083 /* DBG_8723A("marc: invalid cap:%x\n", caps); */
8084 return;
8085 }
8086}
8087
8088void start_clnt_auth23a(struct rtw_adapter* padapter)
8089{
8090 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8091 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8092
8093 del_timer_sync(&pmlmeext->link_timer);
8094
8095 pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
8096 pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
8097
8098 pmlmeinfo->auth_seq = 1;
8099 pmlmeinfo->reauth_count = 0;
8100 pmlmeinfo->reassoc_count = 0;
8101 pmlmeinfo->link_count = 0;
8102 pmlmeext->retry = 0;
8103
8104 /* Because of AP's not receiving deauth before */
8105 /* AP may: 1)not response auth or 2)deauth us after link is complete */
8106 /* issue deauth before issuing auth to deal with the situation */
8107 /* Commented by Albert 2012/07/21 */
8108 /* For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
8109 issue_deauth23a(padapter, (&pmlmeinfo->network)->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
8110
8111 DBG_8723A_LEVEL(_drv_always_, "start auth\n");
8112 issue_auth23a(padapter, NULL, 0);
8113
8114 set_link_timer(pmlmeext, REAUTH_TO);
8115}
8116
8117void start_clnt_assoc23a(struct rtw_adapter* padapter)
8118{
8119 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8120 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8121
8122 del_timer_sync(&pmlmeext->link_timer);
8123
8124 pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
8125 pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
8126
8127 issue_assocreq23a(padapter);
8128
8129 set_link_timer(pmlmeext, REASSOC_TO);
8130}
8131
8132unsigned int receive_disconnect23a(struct rtw_adapter *padapter, unsigned char *MacAddr, unsigned short reason)
8133{
8134 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8135 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8136
8137 /* check A3 */
8138 if (!ether_addr_equal(MacAddr, get_my_bssid23a(&pmlmeinfo->network)))
8139 return _SUCCESS;
8140
8141 DBG_8723A("%s\n", __func__);
8142
8143 if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
8144 {
8145 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
8146 {
8147 pmlmeinfo->state = WIFI_FW_NULL_STATE;
8148 report_del_sta_event23a(padapter, MacAddr, reason);
8149
8150 }
8151 else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE)
8152 {
8153 pmlmeinfo->state = WIFI_FW_NULL_STATE;
8154 report_join_res23a(padapter, -2);
8155 }
8156 }
8157
8158 return _SUCCESS;
8159}
8160
8161static void process_80211d(struct rtw_adapter *padapter, struct wlan_bssid_ex *bssid)
8162{
8163 struct registry_priv *pregistrypriv;
8164 struct mlme_ext_priv *pmlmeext;
8165 struct rt_channel_info *chplan_new;
8166 u8 channel;
8167 u8 i;
8168
8169 pregistrypriv = &padapter->registrypriv;
8170 pmlmeext = &padapter->mlmeextpriv;
8171
8172 /* Adjust channel plan by AP Country IE */
8173 if (pregistrypriv->enable80211d &&
8174 (!pmlmeext->update_channel_plan_by_ap_done))
8175 {
8176 u8 *ie, *p;
8177 u32 len;
8178 struct rt_channel_plan chplan_ap;
8179 struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
8180 u8 country[4];
8181 u8 fcn; /* first channel number */
8182 u8 noc; /* number of channel */
8183 u8 j, k;
8184
8185 ie = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
8186 if (!ie) return;
8187 if (len < 6) return;
8188
8189 ie += 2;
8190 p = ie;
8191 ie += len;
8192
8193 memset(country, 0, 4);
8194 memcpy(country, p, 3);
8195 p += 3;
8196 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
8197 ("%s: 802.11d country =%s\n", __func__, country));
8198
8199 i = 0;
8200 while ((ie - p) >= 3)
8201 {
8202 fcn = *(p++);
8203 noc = *(p++);
8204 p++;
8205
8206 for (j = 0; j < noc; j++)
8207 {
8208 if (fcn <= 14) channel = fcn + j; /* 2.4 GHz */
8209 else channel = fcn + j*4; /* 5 GHz */
8210
8211 chplan_ap.Channel[i++] = channel;
8212 }
8213 }
8214 chplan_ap.Len = i;
8215
8216 memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
8217 memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
8218 chplan_new = pmlmeext->channel_set;
8219
8220 i = j = k = 0;
8221 if (pregistrypriv->wireless_mode & WIRELESS_11G) {
8222 do {
8223 if ((i == MAX_CHANNEL_NUM) ||
8224 (chplan_sta[i].ChannelNum == 0) ||
8225 (chplan_sta[i].ChannelNum > 14))
8226 break;
8227
8228 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
8229 break;
8230
8231 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
8232 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
8233 chplan_new[k].ScanType = SCAN_ACTIVE;
8234 i++;
8235 j++;
8236 k++;
8237 } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
8238 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
8239 chplan_new[k].ScanType = SCAN_PASSIVE;
8240 i++;
8241 k++;
8242 } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
8243 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
8244 chplan_new[k].ScanType = SCAN_ACTIVE;
8245 j++;
8246 k++;
8247 }
8248 } while (1);
8249
8250 /* change AP not support channel to Passive scan */
8251 while ((i < MAX_CHANNEL_NUM) &&
8252 (chplan_sta[i].ChannelNum != 0) &&
8253 (chplan_sta[i].ChannelNum <= 14)) {
8254 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
8255 chplan_new[k].ScanType = SCAN_PASSIVE;
8256 i++;
8257 k++;
8258 }
8259
8260 /* add channel AP supported */
8261 while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
8262 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
8263 chplan_new[k].ScanType = SCAN_ACTIVE;
8264 j++;
8265 k++;
8266 }
8267 } else {
8268 /* keep original STA 2.4G channel plan */
8269 while ((i < MAX_CHANNEL_NUM) &&
8270 (chplan_sta[i].ChannelNum != 0) &&
8271 (chplan_sta[i].ChannelNum <= 14)) {
8272 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
8273 chplan_new[k].ScanType = chplan_sta[i].ScanType;
8274 i++;
8275 k++;
8276 }
8277
8278 /* skip AP 2.4G channel plan */
8279 while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
8280 j++;
8281 }
8282 }
8283
8284 if (pregistrypriv->wireless_mode & WIRELESS_11A) {
8285 do {
8286 if ((i == MAX_CHANNEL_NUM) ||
8287 (chplan_sta[i].ChannelNum == 0))
8288 break;
8289
8290 if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0))
8291 break;
8292
8293 if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j])
8294 {
8295 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
8296 chplan_new[k].ScanType = SCAN_ACTIVE;
8297 i++;
8298 j++;
8299 k++;
8300 }
8301 else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j])
8302 {
8303 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
8304/* chplan_new[k].ScanType = chplan_sta[i].ScanType; */
8305 chplan_new[k].ScanType = SCAN_PASSIVE;
8306 i++;
8307 k++;
8308 }
8309 else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j])
8310 {
8311 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
8312 chplan_new[k].ScanType = SCAN_ACTIVE;
8313 j++;
8314 k++;
8315 }
8316 } while (1);
8317
8318 /* change AP not support channel to Passive scan */
8319 while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
8320 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
8321 chplan_new[k].ScanType = SCAN_PASSIVE;
8322 i++;
8323 k++;
8324 }
8325
8326 /* add channel AP supported */
8327 while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) {
8328 chplan_new[k].ChannelNum = chplan_ap.Channel[j];
8329 chplan_new[k].ScanType = SCAN_ACTIVE;
8330 j++;
8331 k++;
8332 }
8333 } else {
8334 /* keep original STA 5G channel plan */
8335 while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
8336 chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
8337 chplan_new[k].ScanType = chplan_sta[i].ScanType;
8338 i++;
8339 k++;
8340 }
8341 }
8342 pmlmeext->update_channel_plan_by_ap_done = 1;
8343 }
8344
8345 /* If channel is used by AP, set channel scan type to active */
8346 channel = bssid->Configuration.DSConfig;
8347 chplan_new = pmlmeext->channel_set;
8348 i = 0;
8349 while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
8350 if (chplan_new[i].ChannelNum == channel)
8351 {
8352 if (chplan_new[i].ScanType == SCAN_PASSIVE) {
8353 /* 5G Bnad 2, 3 (DFS) doesn't change to active scan */
8354 if (channel >= 52 && channel <= 144)
8355 break;
8356
8357 chplan_new[i].ScanType = SCAN_ACTIVE;
8358 RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
8359 ("%s: change channel %d scan type from passive to active\n",
8360 __func__, channel));
8361 }
8362 break;
8363 }
8364 i++;
8365 }
8366}
8367
8368/****************************************************************************
8369
8370Following are the functions to report events
8371
8372*****************************************************************************/
8373
8374void report_survey_event23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
8375{
8376 struct cmd_obj *pcmd_obj;
8377 u8 *pevtcmd;
8378 u32 cmdsz;
8379 struct survey_event *psurvey_evt;
8380 struct C2HEvent_Header *pc2h_evt_hdr;
8381 struct mlme_ext_priv *pmlmeext;
8382 struct cmd_priv *pcmdpriv;
8383
8384 if (!padapter)
8385 return;
8386
8387 pmlmeext = &padapter->mlmeextpriv;
8388 pcmdpriv = &padapter->cmdpriv;
8389
8390 pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
8391 GFP_ATOMIC);
8392 if (!pcmd_obj)
8393 return;
8394
8395 cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
8396 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
8397 if (!pevtcmd) {
8398 kfree(pcmd_obj);
8399 return;
8400 }
8401
8402 INIT_LIST_HEAD(&pcmd_obj->list);
8403
8404 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
8405 pcmd_obj->cmdsz = cmdsz;
8406 pcmd_obj->parmbuf = pevtcmd;
8407
8408 pcmd_obj->rsp = NULL;
8409 pcmd_obj->rspsz = 0;
8410
8411 pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
8412 pc2h_evt_hdr->len = sizeof(struct survey_event);
8413 pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
8414 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
8415
8416 psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
8417
8418 if (collect_bss_info23a(padapter, precv_frame, &psurvey_evt->bss) == _FAIL) {
8419 kfree(pcmd_obj);
8420 kfree(pevtcmd);
8421 return;
8422 }
8423
8424 process_80211d(padapter, &psurvey_evt->bss);
8425
8426 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
8427
8428 pmlmeext->sitesurvey_res.bss_cnt++;
8429
8430 return;
8431}
8432
8433void report_surveydone_event23a(struct rtw_adapter *padapter)
8434{
8435 struct cmd_obj *pcmd_obj;
8436 u8 *pevtcmd;
8437 u32 cmdsz;
8438 struct surveydone_event *psurveydone_evt;
8439 struct C2HEvent_Header *pc2h_evt_hdr;
8440 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8441 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
8442
8443 pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
8444 GFP_ATOMIC);
8445 if (!pcmd_obj)
8446 return;
8447
8448 cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
8449 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
8450 if (!pevtcmd) {
8451 kfree(pcmd_obj);
8452 return;
8453 }
8454
8455 INIT_LIST_HEAD(&pcmd_obj->list);
8456
8457 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
8458 pcmd_obj->cmdsz = cmdsz;
8459 pcmd_obj->parmbuf = pevtcmd;
8460
8461 pcmd_obj->rsp = NULL;
8462 pcmd_obj->rspsz = 0;
8463
8464 pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
8465 pc2h_evt_hdr->len = sizeof(struct surveydone_event);
8466 pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
8467 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
8468
8469 psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
8470 psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
8471
8472 DBG_8723A("survey done event(%x)\n", psurveydone_evt->bss_cnt);
8473
8474 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
8475
8476 return;
8477}
8478
8479void report_join_res23a(struct rtw_adapter *padapter, int res)
8480{
8481 struct cmd_obj *pcmd_obj;
8482 u8 *pevtcmd;
8483 u32 cmdsz;
8484 struct joinbss_event *pjoinbss_evt;
8485 struct C2HEvent_Header *pc2h_evt_hdr;
8486 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8487 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8488 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
8489
8490 pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
8491 GFP_ATOMIC);
8492 if (!pcmd_obj)
8493 return;
8494
8495 cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
8496 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
8497 if (!pevtcmd) {
8498 kfree(pcmd_obj);
8499 return;
8500 }
8501
8502 INIT_LIST_HEAD(&pcmd_obj->list);
8503
8504 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
8505 pcmd_obj->cmdsz = cmdsz;
8506 pcmd_obj->parmbuf = pevtcmd;
8507
8508 pcmd_obj->rsp = NULL;
8509 pcmd_obj->rspsz = 0;
8510
8511 pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
8512 pc2h_evt_hdr->len = sizeof(struct joinbss_event);
8513 pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
8514 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
8515
8516 pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
8517 memcpy((unsigned char *)&pjoinbss_evt->network.network,
8518 &pmlmeinfo->network, sizeof(struct wlan_bssid_ex));
8519 pjoinbss_evt->network.join_res = pjoinbss_evt->network.aid = res;
8520
8521 DBG_8723A("report_join_res23a(%d)\n", res);
8522
8523 rtw_joinbss_event_prehandle23a(padapter, (u8 *)&pjoinbss_evt->network);
8524
8525 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
8526
8527 return;
8528}
8529
8530void report_del_sta_event23a(struct rtw_adapter *padapter, unsigned char* MacAddr, unsigned short reason)
8531{
8532 struct cmd_obj *pcmd_obj;
8533 u8 *pevtcmd;
8534 u32 cmdsz;
8535 struct sta_info *psta;
8536 int mac_id;
8537 struct stadel_event *pdel_sta_evt;
8538 struct C2HEvent_Header *pc2h_evt_hdr;
8539 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8540 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
8541
8542 pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
8543 GFP_ATOMIC);
8544 if (!pcmd_obj)
8545 return;
8546
8547 cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
8548 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
8549 if (!pevtcmd) {
8550 kfree(pcmd_obj);
8551 return;
8552 }
8553
8554 INIT_LIST_HEAD(&pcmd_obj->list);
8555
8556 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
8557 pcmd_obj->cmdsz = cmdsz;
8558 pcmd_obj->parmbuf = pevtcmd;
8559
8560 pcmd_obj->rsp = NULL;
8561 pcmd_obj->rspsz = 0;
8562
8563 pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
8564 pc2h_evt_hdr->len = sizeof(struct stadel_event);
8565 pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
8566 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
8567
8568 pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
8569 ether_addr_copy((unsigned char *)&pdel_sta_evt->macaddr, MacAddr);
8570 memcpy((unsigned char *)pdel_sta_evt->rsvd, (unsigned char *)&reason,
8571 2);
8572
8573 psta = rtw_get_stainfo23a(&padapter->stapriv, MacAddr);
8574 if (psta)
8575 mac_id = (int)psta->mac_id;
8576 else
8577 mac_id = (-1);
8578
8579 pdel_sta_evt->mac_id = mac_id;
8580
8581 DBG_8723A("report_del_sta_event23a: delete STA, mac_id =%d\n", mac_id);
8582
8583 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
8584
8585 return;
8586}
8587
8588void report_add_sta_event23a(struct rtw_adapter *padapter, unsigned char* MacAddr, int cam_idx)
8589{
8590 struct cmd_obj *pcmd_obj;
8591 u8 *pevtcmd;
8592 u32 cmdsz;
8593 struct stassoc_event *padd_sta_evt;
8594 struct C2HEvent_Header *pc2h_evt_hdr;
8595 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8596 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
8597
8598 pcmd_obj = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
8599 GFP_ATOMIC);
8600 if (!pcmd_obj)
8601 return;
8602
8603 cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
8604 pevtcmd = kzalloc(cmdsz, GFP_ATOMIC);
8605 if (!pevtcmd) {
8606 kfree(pcmd_obj);
8607 return;
8608 }
8609
8610 INIT_LIST_HEAD(&pcmd_obj->list);
8611
8612 pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
8613 pcmd_obj->cmdsz = cmdsz;
8614 pcmd_obj->parmbuf = pevtcmd;
8615
8616 pcmd_obj->rsp = NULL;
8617 pcmd_obj->rspsz = 0;
8618
8619 pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
8620 pc2h_evt_hdr->len = sizeof(struct stassoc_event);
8621 pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
8622 pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
8623
8624 padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
8625 ether_addr_copy((unsigned char *)&padd_sta_evt->macaddr, MacAddr);
8626 padd_sta_evt->cam_id = cam_idx;
8627
8628 DBG_8723A("report_add_sta_event23a: add STA\n");
8629
8630 rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
8631
8632 return;
8633}
8634
8635/****************************************************************************
8636
8637Following are the event callback functions
8638
8639*****************************************************************************/
8640
8641/* for sta/adhoc mode */
8642void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta)
8643{
8644 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
8645 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8646 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8647
8648 /* ERP */
8649 VCS_update23a(padapter, psta);
8650
8651 /* HT */
8652 if (pmlmepriv->htpriv.ht_option)
8653 {
8654 psta->htpriv.ht_option = true;
8655
8656 psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
8657
8658 if (support_short_GI23a(padapter, &pmlmeinfo->HT_caps))
8659 psta->htpriv.sgi = true;
8660
8661 psta->qos_option = true;
8662
8663 }
8664 else
8665 {
8666 psta->htpriv.ht_option = false;
8667
8668 psta->htpriv.ampdu_enable = false;
8669
8670 psta->htpriv.sgi = false;
8671 psta->qos_option = false;
8672
8673 }
8674 psta->htpriv.bwmode = pmlmeext->cur_bwmode;
8675 psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
8676
8677 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
8678 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
8679
8680 /* QoS */
8681 if (pmlmepriv->qospriv.qos_option)
8682 psta->qos_option = true;
8683
8684 psta->state = _FW_LINKED;
8685}
8686
8687void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter, int join_res)
8688{
8689 struct sta_info *psta, *psta_bmc;
8690 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8691 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8692 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
8693 struct sta_priv *pstapriv = &padapter->stapriv;
8694 u8 join_type;
8695 u16 media_status;
8696
8697 if (join_res < 0)
8698 {
8699 join_type = 1;
8700 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
8701 rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, null_addr);
8702
8703 /* restore to initial setting. */
8704 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
8705
8706 goto exit_mlmeext_joinbss_event_callback23a;
8707 }
8708
8709 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
8710 {
8711 /* for bc/mc */
8712 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
8713 if (psta_bmc)
8714 {
8715 pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
8716 update_bmc_sta_support_rate23a(padapter, psta_bmc->mac_id);
8717 Update_RA_Entry23a(padapter, psta_bmc);
8718 }
8719 }
8720
8721 /* turn on dynamic functions */
8722 Switch_DM_Func23a(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
8723
8724 /* update IOT-releated issue */
8725 update_IOT_info23a(padapter);
8726
8727 rtw_hal_set_hwreg23a(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
8728
8729 /* BCN interval */
8730 rtw_hal_set_hwreg23a(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
8731
8732 /* udpate capability */
8733 update_capinfo23a(padapter, pmlmeinfo->capability);
8734
8735 /* WMM, Update EDCA param */
8736 WMMOnAssocRsp23a(padapter);
8737
8738 /* HT */
8739 HTOnAssocRsp23a(padapter);
8740
8741 /* Set cur_channel&cur_bwmode&cur_ch_offset */
8742 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
8743
8744 psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
8745 if (psta) /* only for infra. mode */
8746 {
8747 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
8748
8749 /* DBG_8723A("set_sta_rate23a\n"); */
8750
8751 psta->wireless_mode = pmlmeext->cur_wireless_mode;
8752
8753 /* set per sta rate after updating HT cap. */
8754 set_sta_rate23a(padapter, psta);
8755
8756 media_status = (psta->mac_id<<8)|1; /* MACID|OPMODE: 1 means connect */
8757 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
8758 }
8759
8760 join_type = 2;
8761 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
8762
8763 if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
8764 {
8765 /* correcting TSF */
8766 correct_TSF23a(padapter, pmlmeext);
8767
8768 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
8769 }
8770
8771 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_CONNECT, 0);
8772
8773exit_mlmeext_joinbss_event_callback23a:
8774 DBG_8723A("=>%s\n", __func__);
8775}
8776
8777void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter, struct sta_info *psta)
8778{
8779 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8780 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8781 u8 join_type;
8782
8783 DBG_8723A("%s\n", __func__);
8784
8785 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
8786 {
8787 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)/* adhoc master or sta_count>1 */
8788 {
8789 /* nothing to do */
8790 }
8791 else/* adhoc client */
8792 {
8793 /* update TSF Value */
8794 /* update_TSF23a(pmlmeext, pframe, len); */
8795
8796 /* correcting TSF */
8797 correct_TSF23a(padapter, pmlmeext);
8798
8799 /* start beacon */
8800 if (send_beacon23a(padapter) == _FAIL)
8801 {
8802 pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
8803
8804 pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
8805
8806 return;
8807 }
8808
8809 pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
8810
8811 }
8812
8813 join_type = 2;
8814 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
8815 }
8816
8817 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
8818
8819 /* rate radaptive */
8820 Update_RA_Entry23a(padapter, psta);
8821
8822 /* update adhoc sta_info */
8823 update_sta_info23a(padapter, psta);
8824}
8825
8826void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter)
8827{
8828 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8829 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8830
8831 if (is_client_associated_to_ap23a(padapter) || is_IBSS_empty23a(padapter))
8832 {
8833 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
8834
8835 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_DISCONNECT, NULL);
8836 rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, null_addr);
8837
8838 /* restore to initial setting. */
8839 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
8840
8841 /* switch to the 20M Hz mode after disconnect */
8842 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
8843 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
8844
8845 /* SelectChannel23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
8846 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
8847
8848 flush_all_cam_entry23a(padapter);
8849
8850 pmlmeinfo->state = WIFI_FW_NULL_STATE;
8851
8852 /* set MSR to no link state -> infra. mode */
8853 Set_MSR23a(padapter, _HW_STATE_STATION_);
8854
8855 del_timer_sync(&pmlmeext->link_timer);
8856 }
8857}
8858
8859/****************************************************************************
8860
8861Following are the functions for the timer handlers
8862
8863*****************************************************************************/
8864void linked23a_rx_sig_stren_disp(struct rtw_adapter *padapter)
8865{
8866 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8867 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8868 u8 mac_id;
8869 int UndecoratedSmoothedPWDB;
8870 if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
8871 mac_id = 0;
8872 else if ((pmlmeinfo->state&0x03) == _HW_STATE_AP_)
8873 mac_id = 2;
8874
8875 rtw_hal_get_def_var23a(padapter, HW_DEF_RA_INFO_DUMP,&mac_id);
8876
8877 rtw_hal_get_def_var23a(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
8878 DBG_8723A("UndecoratedSmoothedPWDB:%d\n", UndecoratedSmoothedPWDB);
8879}
8880
8881static u8 chk_ap_is_alive(struct rtw_adapter *padapter, struct sta_info *psta)
8882{
8883 u8 ret = false;
8884
8885 if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) &&
8886 sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
8887 sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
8888 ret = false;
8889 else
8890 ret = true;
8891
8892 sta_update_last_rx_pkts(psta);
8893 return ret;
8894}
8895
8896void linked_status_chk23a(struct rtw_adapter *padapter)
8897{
8898 u32 i;
8899 struct sta_info *psta;
8900 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
8901 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
8902 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
8903 struct sta_priv *pstapriv = &padapter->stapriv;
8904
8905 if (padapter->bRxRSSIDisplay)
8906 linked23a_rx_sig_stren_disp(padapter);
8907
8908 rtw_hal_sreset_linked_status_check23a(padapter);
8909
8910 if (is_client_associated_to_ap23a(padapter))
8911 {
8912 /* linked infrastructure client mode */
8913
8914 int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
8915 int rx_chk_limit;
8916
8917 rx_chk_limit = 4;
8918
8919 if ((psta = rtw_get_stainfo23a(pstapriv, pmlmeinfo->network.MacAddress)) != NULL)
8920 {
8921 bool is_p2p_enable = false;
8922#ifdef CONFIG_8723AU_P2P
8923 is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);
8924#endif
8925
8926 if (chk_ap_is_alive(padapter, psta) == false)
8927 rx_chk = _FAIL;
8928
8929 if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
8930 tx_chk = _FAIL;
8931
8932 if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
8933 u8 backup_oper_channel = 0;
8934
8935 /* switch to correct channel of current network before issue keep-alive frames */
8936 if (rtw_get_oper_ch23a(padapter) != pmlmeext->cur_channel) {
8937 backup_oper_channel = rtw_get_oper_ch23a(padapter);
8938 SelectChannel23a(padapter, pmlmeext->cur_channel);
8939 }
8940
8941 if (rx_chk != _SUCCESS)
8942 issue_probereq23a_ex23a(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
8943
8944 if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) {
8945 tx_chk = issue_nulldata23a(padapter, psta->hwaddr, 0, 3, 1);
8946 /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
8947 if (tx_chk == _SUCCESS && !is_p2p_enable)
8948 rx_chk = _SUCCESS;
8949 }
8950
8951 /* back to the original operation channel */
8952 if (backup_oper_channel>0)
8953 SelectChannel23a(padapter, backup_oper_channel);
8954
8955 } else {
8956 if (rx_chk != _SUCCESS) {
8957 if (pmlmeext->retry == 0) {
8958 issue_probereq23a(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
8959 issue_probereq23a(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
8960 issue_probereq23a(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
8961 }
8962 }
8963
8964 if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf)
8965 tx_chk = issue_nulldata23a(padapter, NULL, 0, 1, 0);
8966 }
8967
8968 if (rx_chk == _FAIL) {
8969 pmlmeext->retry++;
8970 if (pmlmeext->retry > rx_chk_limit) {
8971 DBG_8723A_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
8972 FUNC_ADPT_ARG(padapter));
8973 receive_disconnect23a(padapter, pmlmeinfo->network.MacAddress,
8974 WLAN_REASON_EXPIRATION_CHK);
8975 return;
8976 }
8977 } else {
8978 pmlmeext->retry = 0;
8979 }
8980
8981 if (tx_chk == _FAIL) {
8982 pmlmeinfo->link_count &= 0xf;
8983 } else {
8984 pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
8985 pmlmeinfo->link_count = 0;
8986 }
8987
8988 } /* end of if ((psta = rtw_get_stainfo23a(pstapriv, passoc_res->network.MacAddress)) != NULL) */
8989 }
8990 else if (is_client_associated_to_ibss23a(padapter))
8991 {
8992 /* linked IBSS mode */
8993 /* for each assoc list entry to check the rx pkt counter */
8994 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++)
8995 {
8996 if (pmlmeinfo->FW_sta_info[i].status == 1)
8997 {
8998 psta = pmlmeinfo->FW_sta_info[i].psta;
8999
9000 if (NULL == psta) continue;
9001
9002 if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta))
9003 {
9004
9005 if (pmlmeinfo->FW_sta_info[i].retry<3)
9006 {
9007 pmlmeinfo->FW_sta_info[i].retry++;
9008 }
9009 else
9010 {
9011 pmlmeinfo->FW_sta_info[i].retry = 0;
9012 pmlmeinfo->FW_sta_info[i].status = 0;
9013 report_del_sta_event23a(padapter, psta->hwaddr,
9014 65535/* indicate disconnect caused by no rx */
9015 );
9016 }
9017 }
9018 else
9019 {
9020 pmlmeinfo->FW_sta_info[i].retry = 0;
9021 pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
9022 }
9023 }
9024 }
9025
9026 /* set_link_timer(pmlmeext, DISCONNECT_TO); */
9027
9028 }
9029}
9030
9031static void survey_timer_hdl(unsigned long data)
9032{
9033 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
9034 struct cmd_obj *ph2c;
9035 struct sitesurvey_parm *psurveyPara;
9036 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
9037 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9038#ifdef CONFIG_8723AU_P2P
9039 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
9040#endif
9041
9042 /* issue rtw_sitesurvey_cmd23a */
9043 if (pmlmeext->sitesurvey_res.state > SCAN_START) {
9044 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
9045 pmlmeext->sitesurvey_res.channel_idx++;
9046
9047 if (pmlmeext->scan_abort == true)
9048 {
9049#ifdef CONFIG_8723AU_P2P
9050 if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE))
9051 {
9052 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
9053 pmlmeext->sitesurvey_res.channel_idx = 3;
9054 DBG_8723A("%s idx:%d, cnt:%u\n", __func__,
9055 pmlmeext->sitesurvey_res.channel_idx,
9056 pwdinfo->find_phase_state_exchange_cnt);
9057 } else
9058 #endif
9059 {
9060 pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
9061 DBG_8723A("%s idx:%d\n", __func__,
9062 pmlmeext->sitesurvey_res.channel_idx);
9063 }
9064
9065 pmlmeext->scan_abort = false;/* reset */
9066 }
9067
9068 ph2c = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
9069 GFP_ATOMIC);
9070 if (!ph2c)
9071 goto exit_survey_timer_hdl;
9072
9073 psurveyPara = (struct sitesurvey_parm*)
9074 kzalloc(sizeof(struct sitesurvey_parm), GFP_ATOMIC);
9075 if (!psurveyPara) {
9076 kfree(ph2c);
9077 goto exit_survey_timer_hdl;
9078 }
9079
9080 init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
9081 rtw_enqueue_cmd23a(pcmdpriv, ph2c);
9082 }
9083
9084exit_survey_timer_hdl:
9085 return;
9086}
9087
9088static void link_timer_hdl(unsigned long data)
9089{
9090 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
9091 /* static unsigned int rx_pkt = 0; */
9092 /* static u64 tx_cnt = 0; */
9093 /* struct xmit_priv *pxmitpriv = &padapter->xmitpriv; */
9094 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9095 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9096 /* struct sta_priv *pstapriv = &padapter->stapriv; */
9097
9098 if (pmlmeinfo->state & WIFI_FW_AUTH_NULL)
9099 {
9100 DBG_8723A("link_timer_hdl:no beacon while connecting\n");
9101 pmlmeinfo->state = WIFI_FW_NULL_STATE;
9102 report_join_res23a(padapter, -3);
9103 }
9104 else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE)
9105 {
9106 /* re-auth timer */
9107 if (++pmlmeinfo->reauth_count > REAUTH_LIMIT)
9108 {
9109 /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
9110 /* */
9111 pmlmeinfo->state = 0;
9112 report_join_res23a(padapter, -1);
9113 return;
9114 /* */
9115 /* else */
9116 /* */
9117 /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
9118 /* pmlmeinfo->reauth_count = 0; */
9119 /* */
9120 }
9121
9122 DBG_8723A("link_timer_hdl: auth timeout and try again\n");
9123 pmlmeinfo->auth_seq = 1;
9124 issue_auth23a(padapter, NULL, 0);
9125 set_link_timer(pmlmeext, REAUTH_TO);
9126 }
9127 else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)
9128 {
9129 /* re-assoc timer */
9130 if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT)
9131 {
9132 pmlmeinfo->state = WIFI_FW_NULL_STATE;
9133 report_join_res23a(padapter, -2);
9134 return;
9135 }
9136
9137 DBG_8723A("link_timer_hdl: assoc timeout and try again\n");
9138 issue_assocreq23a(padapter);
9139 set_link_timer(pmlmeext, REASSOC_TO);
9140 }
9141
9142 return;
9143}
9144
9145static void addba_timer_hdl(unsigned long data)
9146{
9147 struct sta_info *psta = (struct sta_info *)data;
9148 struct ht_priv *phtpriv;
9149
9150 if (!psta)
9151 return;
9152
9153 phtpriv = &psta->htpriv;
9154
9155 if ((phtpriv->ht_option == true) && (phtpriv->ampdu_enable == true))
9156 {
9157 if (phtpriv->candidate_tid_bitmap)
9158 phtpriv->candidate_tid_bitmap = 0x0;
9159
9160 }
9161}
9162
9163void init_addba_retry_timer23a(struct sta_info *psta)
9164{
9165 setup_timer(&psta->addba_retry_timer, addba_timer_hdl,
9166 (unsigned long)psta);
9167}
9168
9169void init_mlme_ext_timer23a(struct rtw_adapter *padapter)
9170{
9171 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9172
9173 setup_timer(&pmlmeext->survey_timer, survey_timer_hdl,
9174 (unsigned long)padapter);
9175
9176 setup_timer(&pmlmeext->link_timer, link_timer_hdl,
9177 (unsigned long)padapter);
9178}
9179
9180u8 NULL_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9181{
9182 return H2C_SUCCESS;
9183}
9184
9185u8 setopmode_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9186{
9187 u8 type;
9188 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9189 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9190 struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
9191
9192 if (psetop->mode == Ndis802_11APMode)
9193 {
9194 pmlmeinfo->state = WIFI_FW_AP_STATE;
9195 type = _HW_STATE_AP_;
9196 }
9197 else if (psetop->mode == Ndis802_11Infrastructure)
9198 {
9199 pmlmeinfo->state &= ~(BIT(0)|BIT(1));/* clear state */
9200 pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */
9201 type = _HW_STATE_STATION_;
9202 }
9203 else if (psetop->mode == Ndis802_11IBSS)
9204 {
9205 type = _HW_STATE_ADHOC_;
9206 }
9207 else
9208 {
9209 type = _HW_STATE_NOLINK_;
9210 }
9211
9212 rtw_hal_set_hwreg23a(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
9213 /* Set_NETYPE0_MSR(padapter, type); */
9214
9215 return H2C_SUCCESS;
9216}
9217
9218u8 createbss_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9219{
9220 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9221 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9222 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
9223 struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
9224 /* u32 initialgain; */
9225
9226 if (pparm->InfrastructureMode == Ndis802_11APMode) {
9227#ifdef CONFIG_8723AU_AP_MODE
9228
9229 if (pmlmeinfo->state == WIFI_FW_AP_STATE)
9230 {
9231 /* todo: */
9232 return H2C_SUCCESS;
9233 }
9234#endif
9235 }
9236
9237 /* below is for ad-hoc master */
9238 if (pparm->InfrastructureMode == Ndis802_11IBSS) {
9239 rtw_joinbss_reset23a(padapter);
9240
9241 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
9242 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
9243 pmlmeinfo->ERP_enable = 0;
9244 pmlmeinfo->WMM_enable = 0;
9245 pmlmeinfo->HT_enable = 0;
9246 pmlmeinfo->HT_caps_enable = 0;
9247 pmlmeinfo->HT_info_enable = 0;
9248 pmlmeinfo->agg_enable_bitmap = 0;
9249 pmlmeinfo->candidate_tid_bitmap = 0;
9250
9251 /* disable dynamic functions, such as high power, DIG */
9252 Save_DM_Func_Flag23a(padapter);
9253 Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DISABLE, false);
9254
9255 /* config the initial gain under linking, need to write the BB registers */
9256 /* initialgain = 0x1E; */
9257 /* rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
9258
9259 /* cancel link timer */
9260 del_timer_sync(&pmlmeext->link_timer);
9261
9262 /* clear CAM */
9263 flush_all_cam_entry23a(padapter);
9264
9265 if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
9266 return H2C_PARAMETERS_ERROR;
9267
9268 memcpy(pnetwork, pparm, sizeof(struct wlan_bssid_ex));
9269
9270 start_create_ibss23a(padapter);
9271 }
9272
9273 return H2C_SUCCESS;
9274}
9275
9276u8 join_cmd_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9277{
9278 u8 join_type;
9279 struct ndis_802_11_var_ies * pIE;
9280 struct registry_priv *pregpriv = &padapter->registrypriv;
9281 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9282 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9283 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
9284 struct wlan_bssid_ex *pparm = (struct wlan_bssid_ex *)pbuf;
9285 struct HT_info_element *pht_info;
9286 u32 i;
9287 /* u32 initialgain; */
9288 /* u32 acparm; */
9289
9290 /* check already connecting to AP or not */
9291 if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
9292 {
9293 if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
9294 issue_deauth23a_ex23a(padapter, pnetwork->MacAddress,
9295 WLAN_REASON_DEAUTH_LEAVING, 5, 100);
9296
9297 pmlmeinfo->state = WIFI_FW_NULL_STATE;
9298
9299 /* clear CAM */
9300 flush_all_cam_entry23a(padapter);
9301
9302 del_timer_sync(&pmlmeext->link_timer);
9303
9304 /* set MSR to nolink -> infra. mode */
9305 /* Set_MSR23a(padapter, _HW_STATE_NOLINK_); */
9306 Set_MSR23a(padapter, _HW_STATE_STATION_);
9307
9308 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_DISCONNECT, NULL);
9309 }
9310
9311 rtw_joinbss_reset23a(padapter);
9312
9313 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
9314 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
9315 pmlmeinfo->ERP_enable = 0;
9316 pmlmeinfo->WMM_enable = 0;
9317 pmlmeinfo->HT_enable = 0;
9318 pmlmeinfo->HT_caps_enable = 0;
9319 pmlmeinfo->HT_info_enable = 0;
9320 pmlmeinfo->agg_enable_bitmap = 0;
9321 pmlmeinfo->candidate_tid_bitmap = 0;
9322 pmlmeinfo->bwmode_updated = false;
9323 /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
9324
9325 if (pparm->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
9326 return H2C_PARAMETERS_ERROR;
9327
9328 memcpy(pnetwork, pbuf, sizeof(struct wlan_bssid_ex));
9329
9330 /* Check AP vendor to move rtw_joinbss_cmd23a() */
9331 /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP23a(pnetwork->IEs,
9332 pnetwork->IELength); */
9333
9334 for (i = sizeof(struct ndis_802_11_fixed_ies); i < pnetwork->IELength;)
9335 {
9336 pIE = (struct ndis_802_11_var_ies *)(pnetwork->IEs + i);
9337
9338 switch (pIE->ElementID)
9339 {
9340 case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
9341 if (!memcmp(pIE->data, WMM_OUI23A, 4))
9342 pmlmeinfo->WMM_enable = 1;
9343 break;
9344
9345 case _HT_CAPABILITY_IE_: /* Get HT Cap IE. */
9346 pmlmeinfo->HT_caps_enable = 1;
9347 break;
9348
9349 case _HT_EXTRA_INFO_IE_: /* Get HT Info IE. */
9350 pmlmeinfo->HT_info_enable = 1;
9351
9352 /* spec case only for cisco's ap because cisco's ap
9353 * issue assoc rsp using mcs rate @40MHz or @20MHz */
9354 pht_info = (struct HT_info_element *)(pIE->data);
9355
9356 if ((pregpriv->cbw40_enable) &&
9357 (pht_info->infos[0] & BIT(2))) {
9358 /* switch to the 40M Hz mode according to AP */
9359 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
9360 switch (pht_info->infos[0] & 0x3)
9361 {
9362 case 1:
9363 pmlmeext->cur_ch_offset =
9364 HAL_PRIME_CHNL_OFFSET_LOWER;
9365 break;
9366
9367 case 3:
9368 pmlmeext->cur_ch_offset =
9369 HAL_PRIME_CHNL_OFFSET_UPPER;
9370 break;
9371
9372 default:
9373 pmlmeext->cur_ch_offset =
9374 HAL_PRIME_CHNL_OFFSET_DONT_CARE;
9375 break;
9376 }
9377
9378 DBG_8723A("set ch/bw before connected\n");
9379 }
9380 break;
9381
9382 default:
9383 break;
9384 }
9385
9386 i += (pIE->Length + 2);
9387 }
9388 /* disable dynamic functions, such as high power, DIG */
9389 /* Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DISABLE, false); */
9390
9391 /* config the initial gain under linking, need to write the BB
9392 registers */
9393 /* initialgain = 0x1E; */
9394 /* rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN,
9395 (u8 *)(&initialgain)); */
9396
9397 rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID,
9398 pmlmeinfo->network.MacAddress);
9399 join_type = 0;
9400 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
9401
9402 /* cancel link timer */
9403 del_timer_sync(&pmlmeext->link_timer);
9404
9405 start_clnt_join23a(padapter);
9406
9407 return H2C_SUCCESS;
9408}
9409
9410u8 disconnect_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9411{
9412 struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
9413 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9414 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9415 struct wlan_bssid_ex *pnetwork = &pmlmeinfo->network;
9416 u8 val8;
9417
9418 if (is_client_associated_to_ap23a(padapter))
9419 {
9420 issue_deauth23a_ex23a(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
9421 }
9422
9423 /* set_opmode_cmd(padapter, infra_client_with_mlme); */
9424
9425 /* pmlmeinfo->state = WIFI_FW_NULL_STATE; */
9426
9427 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_DISCONNECT, NULL);
9428 rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, null_addr);
9429
9430 /* restore to initial setting. */
9431 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
9432
9433 if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
9434 {
9435 /* Stop BCN */
9436 val8 = 0;
9437 rtw_hal_set_hwreg23a(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
9438 }
9439
9440 /* set MSR to no link state -> infra. mode */
9441 Set_MSR23a(padapter, _HW_STATE_STATION_);
9442
9443 pmlmeinfo->state = WIFI_FW_NULL_STATE;
9444
9445 /* switch to the 20M Hz mode after disconnect */
9446 pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
9447 pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
9448
9449 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
9450
9451 flush_all_cam_entry23a(padapter);
9452
9453 del_timer_sync(&pmlmeext->link_timer);
9454
9455 rtw_free_uc_swdec_pending_queue23a(padapter);
9456
9457 return H2C_SUCCESS;
9458}
9459
9460static int rtw_scan_ch_decision(struct rtw_adapter *padapter, struct rtw_ieee80211_channel *out,
9461 u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
9462{
9463 int i, j;
9464 int scan_ch_num = 0;
9465 int set_idx;
9466 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9467
9468 /* clear out first */
9469 memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
9470
9471 /* acquire channels from in */
9472 j = 0;
9473 for (i = 0;i<in_num;i++) {
9474 if (0)
9475 DBG_8723A(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i]));
9476 if (in[i].hw_value && !(in[i].flags & IEEE80211_CHAN_DISABLED)
9477 && (set_idx = rtw_ch_set_search_ch23a(pmlmeext->channel_set, in[i].hw_value)) >= 0
9478 )
9479 {
9480 memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
9481
9482 if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
9483 out[j].flags &= IEEE80211_CHAN_NO_IR;
9484
9485 j++;
9486 }
9487 if (j>= out_num)
9488 break;
9489 }
9490
9491 /* if out is empty, use channel_set as default */
9492 if (j == 0) {
9493 for (i = 0;i<pmlmeext->max_chan_nums;i++) {
9494 out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
9495
9496 if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
9497 out[i].flags &= IEEE80211_CHAN_NO_IR;
9498
9499 j++;
9500 }
9501 }
9502
9503 if (padapter->setband == GHZ_24) { /* 2.4G */
9504 for (i = 0; i < j ; i++) {
9505 if (out[i].hw_value > 35)
9506 memset(&out[i], 0,
9507 sizeof(struct rtw_ieee80211_channel));
9508 else
9509 scan_ch_num++;
9510 }
9511 j = scan_ch_num;
9512 } else if (padapter->setband == GHZ_50) { /* 5G */
9513 for (i = 0; i < j ; i++) {
9514 if (out[i].hw_value > 35) {
9515 memcpy(&out[scan_ch_num++], &out[i], sizeof(struct rtw_ieee80211_channel));
9516 }
9517 }
9518 j = scan_ch_num;
9519 } else
9520 {}
9521
9522 return j;
9523}
9524
9525u8 sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9526{
9527 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9528 struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;
9529 u8 bdelayscan = false;
9530 u8 val8;
9531 u32 initialgain;
9532 u32 i;
9533
9534 if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
9535 /* for first time sitesurvey_cmd */
9536 rtw_hal_set_hwreg23a(padapter, HW_VAR_CHECK_TXBUF, NULL);
9537
9538 pmlmeext->sitesurvey_res.state = SCAN_START;
9539 pmlmeext->sitesurvey_res.bss_cnt = 0;
9540 pmlmeext->sitesurvey_res.channel_idx = 0;
9541
9542 for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
9543 if (pparm->ssid[i].ssid_len) {
9544 memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid,
9545 pparm->ssid[i].ssid, IW_ESSID_MAX_SIZE);
9546 pmlmeext->sitesurvey_res.ssid[i].ssid_len =
9547 pparm->ssid[i].ssid_len;
9548 } else {
9549 pmlmeext->sitesurvey_res.ssid[i].ssid_len = 0;
9550 }
9551 }
9552
9553 pmlmeext->sitesurvey_res.ch_num =
9554 rtw_scan_ch_decision(padapter,
9555 pmlmeext->sitesurvey_res.ch,
9556 RTW_CHANNEL_SCAN_AMOUNT,
9557 pparm->ch, pparm->ch_num);
9558
9559 pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
9560
9561 /* issue null data if associating to the AP */
9562 if (is_client_associated_to_ap23a(padapter)) {
9563 pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
9564
9565 /* switch to correct channel of current network
9566 before issue keep-alive frames */
9567 if (rtw_get_oper_ch23a(padapter) != pmlmeext->cur_channel)
9568 SelectChannel23a(padapter, pmlmeext->cur_channel);
9569
9570 issue_nulldata23a(padapter, NULL, 1, 3, 500);
9571
9572 bdelayscan = true;
9573 }
9574
9575 if (bdelayscan) {
9576 /* delay 50ms to protect nulldata(1). */
9577 set_survey_timer(pmlmeext, 50);
9578 return H2C_SUCCESS;
9579 }
9580 }
9581
9582 if ((pmlmeext->sitesurvey_res.state == SCAN_START) ||
9583 (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
9584 /* disable dynamic functions, such as high power, DIG */
9585 Save_DM_Func_Flag23a(padapter);
9586 Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DISABLE, false);
9587
9588 /* config the initial gain under scaning, need to
9589 write the BB registers */
9590 if ((wdev_to_priv(padapter->rtw_wdev))->p2p_enabled == true) {
9591 initialgain = 0x30;
9592 } else
9593 initialgain = 0x1E;
9594
9595 rtw_hal_set_hwreg23a(padapter, HW_VAR_INITIAL_GAIN,
9596 (u8 *)(&initialgain));
9597
9598 /* set MSR to no link state */
9599 Set_MSR23a(padapter, _HW_STATE_NOLINK_);
9600
9601 val8 = 1; /* under site survey */
9602 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_SITESURVEY,
9603 (u8 *)(&val8));
9604
9605 pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
9606 }
9607
9608 site_survey23a(padapter);
9609
9610 return H2C_SUCCESS;
9611}
9612
9613u8 setauth_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9614{
9615 struct setauth_parm *pparm = (struct setauth_parm *)pbuf;
9616 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9617 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9618
9619 if (pparm->mode < 4)
9620 {
9621 pmlmeinfo->auth_algo = pparm->mode;
9622 }
9623
9624 return H2C_SUCCESS;
9625}
9626
9627u8 setkey_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9628{
9629 unsigned short ctrl;
9630 struct setkey_parm *pparm = (struct setkey_parm *)pbuf;
9631 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9632 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9633 unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
9634
9635 /* main tx key for wep. */
9636 if (pparm->set_tx)
9637 pmlmeinfo->key_index = pparm->keyid;
9638
9639 /* write cam */
9640 ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
9641
9642 DBG_8723A_LEVEL(_drv_always_, "set group key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) "
9643 "keyid:%d\n", pparm->algorithm, pparm->keyid);
9644 write_cam23a(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
9645
9646 /* allow multicast packets to driver */
9647 padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr);
9648
9649 return H2C_SUCCESS;
9650}
9651
9652u8 set_stakey_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9653{
9654 u16 ctrl = 0;
9655 u8 cam_id;/* cam_entry */
9656 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9657 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9658 struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;
9659
9660 /* cam_entry: */
9661 /* 0~3 for default key */
9662
9663 /* for concurrent mode (ap+sta): */
9664 /* default key is disable, using sw encrypt/decrypt */
9665 /* cam_entry = 4 for sta mode (macid = 0) */
9666 /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
9667
9668 /* for concurrent mode (sta+sta): */
9669 /* default key is disable, using sw encrypt/decrypt */
9670 /* cam_entry = 4 mapping to macid = 0 */
9671 /* cam_entry = 5 mapping to macid = 2 */
9672
9673 cam_id = 4;
9674
9675 DBG_8723A_LEVEL(_drv_always_, "set pairwise key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) camid:%d\n",
9676 pparm->algorithm, cam_id);
9677 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
9678 {
9679
9680 struct sta_info *psta;
9681 struct sta_priv *pstapriv = &padapter->stapriv;
9682
9683 if (pparm->algorithm == _NO_PRIVACY_) /* clear cam entry */
9684 {
9685 clear_cam_entry23a(padapter, pparm->id);
9686 return H2C_SUCCESS_RSP;
9687 }
9688
9689 psta = rtw_get_stainfo23a(pstapriv, pparm->addr);
9690 if (psta)
9691 {
9692 ctrl = (BIT(15) | ((pparm->algorithm) << 2));
9693
9694 DBG_8723A("r871x_set_stakey_hdl23a(): enc_algorithm =%d\n", pparm->algorithm);
9695
9696 if ((psta->mac_id<1) || (psta->mac_id>(NUM_STA-4)))
9697 {
9698 DBG_8723A("r871x_set_stakey_hdl23a():set_stakey failed, mac_id(aid) =%d\n", psta->mac_id);
9699 return H2C_REJECTED;
9700 }
9701
9702 cam_id = (psta->mac_id + 3);/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
9703
9704 DBG_8723A("Write CAM, mac_addr =%x:%x:%x:%x:%x:%x, cam_entry =%d\n", pparm->addr[0],
9705 pparm->addr[1], pparm->addr[2], pparm->addr[3], pparm->addr[4],
9706 pparm->addr[5], cam_id);
9707
9708 write_cam23a(padapter, cam_id, ctrl, pparm->addr, pparm->key);
9709
9710 return H2C_SUCCESS_RSP;
9711
9712 }
9713 else
9714 {
9715 DBG_8723A("r871x_set_stakey_hdl23a(): sta has been free\n");
9716 return H2C_REJECTED;
9717 }
9718
9719 }
9720
9721 /* below for sta mode */
9722
9723 if (pparm->algorithm == _NO_PRIVACY_) /* clear cam entry */
9724 {
9725 clear_cam_entry23a(padapter, pparm->id);
9726 return H2C_SUCCESS;
9727 }
9728
9729 ctrl = BIT(15) | ((pparm->algorithm) << 2);
9730
9731 write_cam23a(padapter, cam_id, ctrl, pparm->addr, pparm->key);
9732
9733 pmlmeinfo->enc_algo = pparm->algorithm;
9734
9735 return H2C_SUCCESS;
9736}
9737
9738u8 add_ba_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9739{
9740 struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;
9741 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9742 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9743
9744 struct sta_info *psta = rtw_get_stainfo23a(&padapter->stapriv, pparm->addr);
9745
9746 if (!psta)
9747 return H2C_SUCCESS;
9748
9749 if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
9750 (pmlmeinfo->HT_enable)) ||
9751 ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
9752 issue_action_BA23a(padapter, pparm->addr,
9753 WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
9754 mod_timer(&psta->addba_retry_timer,
9755 jiffies + msecs_to_jiffies(ADDBA_TO));
9756 } else {
9757 psta->htpriv.candidate_tid_bitmap &= ~CHKBIT(pparm->tid);
9758 }
9759 return H2C_SUCCESS;
9760}
9761
9762u8 set_tx_beacon_cmd23a(struct rtw_adapter* padapter)
9763{
9764 struct cmd_obj *ph2c;
9765 struct Tx_Beacon_param *ptxBeacon_parm;
9766 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
9767 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9768 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
9769 u8 res = _SUCCESS;
9770 int len_diff = 0;
9771
9772
9773
9774 ph2c = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj), GFP_ATOMIC);
9775 if (!ph2c) {
9776 res = _FAIL;
9777 goto exit;
9778 }
9779
9780 ptxBeacon_parm = (struct Tx_Beacon_param *)
9781 kzalloc(sizeof(struct Tx_Beacon_param), GFP_ATOMIC);
9782 if (!ptxBeacon_parm) {
9783 kfree(ph2c);
9784 res = _FAIL;
9785 goto exit;
9786 }
9787
9788 memcpy(&ptxBeacon_parm->network, &pmlmeinfo->network,
9789 sizeof(struct wlan_bssid_ex));
9790
9791 len_diff = update_hidden_ssid(
9792 ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_,
9793 ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_,
9794 pmlmeinfo->hidden_ssid_mode);
9795 ptxBeacon_parm->network.IELength += len_diff;
9796
9797 init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
9798
9799 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
9800
9801exit:
9802
9803
9804
9805 return res;
9806}
9807
9808u8 mlme_evt_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9809{
9810 u8 evt_code, evt_seq;
9811 u16 evt_sz;
9812 uint *peventbuf;
9813 void (*event_callback)(struct rtw_adapter *dev, u8 *pbuf);
9814 struct evt_priv *pevt_priv = &padapter->evtpriv;
9815
9816 peventbuf = (uint*)pbuf;
9817 evt_sz = (u16)(*peventbuf&0xffff);
9818 evt_seq = (u8)((*peventbuf>>24)&0x7f);
9819 evt_code = (u8)((*peventbuf>>16)&0xff);
9820
9821 /* checking if event code is valid */
9822 if (evt_code >= MAX_C2HEVT) {
9823 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent Code(%d) mismatch!\n", evt_code));
9824 goto _abort_event_;
9825 }
9826
9827 /* checking if event size match the event parm size */
9828 if ((wlanevents[evt_code].parmsize != 0) &&
9829 (wlanevents[evt_code].parmsize != evt_sz)) {
9830 RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n",
9831 evt_code, wlanevents[evt_code].parmsize, evt_sz));
9832 goto _abort_event_;
9833 }
9834
9835 atomic_inc(&pevt_priv->event_seq);
9836
9837 peventbuf += 2;
9838
9839 if (peventbuf) {
9840 event_callback = wlanevents[evt_code].event_callback;
9841 event_callback(padapter, (u8*)peventbuf);
9842
9843 pevt_priv->evt_done_cnt++;
9844 }
9845
9846_abort_event_:
9847
9848 return H2C_SUCCESS;
9849}
9850
9851u8 h2c_msg_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9852{
9853 if (!pbuf)
9854 return H2C_PARAMETERS_ERROR;
9855
9856 return H2C_SUCCESS;
9857}
9858
9859u8 tx_beacon_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9860{
9861 if (send_beacon23a(padapter) == _FAIL)
9862 {
9863 DBG_8723A("issue_beacon23a, fail!\n");
9864 return H2C_PARAMETERS_ERROR;
9865 }
9866#ifdef CONFIG_8723AU_AP_MODE
9867 else /* tx bc/mc frames after update TIM */
9868 {
9869 struct sta_info *psta_bmc;
9870 struct list_head *plist, *phead, *ptmp;
9871 struct xmit_frame *pxmitframe;
9872 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
9873 struct sta_priv *pstapriv = &padapter->stapriv;
9874
9875 /* for BC/MC Frames */
9876 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
9877 if (!psta_bmc)
9878 return H2C_SUCCESS;
9879
9880 if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len>0))
9881 {
9882 msleep(10);/* 10ms, ATIM(HIQ) Windows */
9883 /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
9884 spin_lock_bh(&pxmitpriv->lock);
9885
9886 phead = get_list_head(&psta_bmc->sleep_q);
9887
9888 list_for_each_safe(plist, ptmp, phead) {
9889 pxmitframe = container_of(plist,
9890 struct xmit_frame,
9891 list);
9892
9893 list_del_init(&pxmitframe->list);
9894
9895 psta_bmc->sleepq_len--;
9896 if (psta_bmc->sleepq_len>0)
9897 pxmitframe->attrib.mdata = 1;
9898 else
9899 pxmitframe->attrib.mdata = 0;
9900
9901 pxmitframe->attrib.triggered = 1;
9902
9903 pxmitframe->attrib.qsel = 0x11;/* HIQ */
9904
9905 rtw_hal_xmit23aframe_enqueue(padapter, pxmitframe);
9906 }
9907
9908 /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
9909 spin_unlock_bh(&pxmitpriv->lock);
9910 }
9911
9912 }
9913#endif
9914
9915 return H2C_SUCCESS;
9916}
9917
9918u8 set_ch_hdl23a(struct rtw_adapter *padapter, u8 *pbuf)
9919{
9920 struct set_ch_parm *set_ch_parm;
9921 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9922
9923 if (!pbuf)
9924 return H2C_PARAMETERS_ERROR;
9925
9926 set_ch_parm = (struct set_ch_parm *)pbuf;
9927
9928 DBG_8723A(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
9929 FUNC_NDEV_ARG(padapter->pnetdev),
9930 set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
9931
9932 pmlmeext->cur_channel = set_ch_parm->ch;
9933 pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
9934 pmlmeext->cur_bwmode = set_ch_parm->bw;
9935
9936 set_channel_bwmode23a(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
9937
9938 return H2C_SUCCESS;
9939}
9940
9941u8 set_chplan_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9942{
9943 struct SetChannelPlan_param *setChannelPlan_param;
9944 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9945
9946 if (!pbuf)
9947 return H2C_PARAMETERS_ERROR;
9948
9949 setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
9950
9951 pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
9952 init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
9953
9954 return H2C_SUCCESS;
9955}
9956
9957u8 led_blink_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9958{
9959 struct LedBlink_param *ledBlink_param;
9960
9961 if (!pbuf)
9962 return H2C_PARAMETERS_ERROR;
9963
9964 ledBlink_param = (struct LedBlink_param *)pbuf;
9965
9966 return H2C_SUCCESS;
9967}
9968
9969u8 set_csa_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9970{
9971 return H2C_REJECTED;
9972}
9973
9974/* TDLS_WRCR : write RCR DATA BIT */
9975/* TDLS_SD_PTI : issue peer traffic indication */
9976/* TDLS_CS_OFF : go back to the channel linked with AP, terminating channel switch procedure */
9977/* TDLS_INIT_CH_SEN : init channel sensing, receive all data and mgnt frame */
9978/* TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
9979/* TDLS_OFF_CH : first time set channel to off channel */
9980/* TDLS_BASE_CH : go back tp the channel linked with AP when set base channel as target channel */
9981/* TDLS_P_OFF_CH : periodically go to off channel */
9982/* TDLS_P_BASE_CH : periodically go back to base channel */
9983/* TDLS_RS_RCR : restore RCR */
9984/* TDLS_CKALV_PH1 : check alive timer phase1 */
9985/* TDLS_CKALV_PH2 : check alive timer phase2 */
9986/* TDLS_FREE_STA : free tdls sta */
9987u8 tdls_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf)
9988{
9989 return H2C_REJECTED;
9990}
diff --git a/drivers/staging/rtl8723au/core/rtw_p2p.c b/drivers/staging/rtl8723au/core/rtw_p2p.c
new file mode 100644
index 000000000000..27a6cc76973d
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_p2p.c
@@ -0,0 +1,4001 @@
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 ******************************************************************************/
15#define _RTW_P2P_C_
16
17#include <drv_types.h>
18#include <rtw_p2p.h>
19#include <wifi.h>
20
21#ifdef CONFIG_8723AU_P2P
22
23static int rtw_p2p_is_channel_list_ok(u8 desired_ch, u8* ch_list, u8 ch_cnt)
24{
25 int found = 0, i = 0;
26
27 for (i = 0; i < ch_cnt; i++)
28 {
29 if (ch_list[ i ] == desired_ch)
30 {
31 found = 1;
32 break;
33 }
34 }
35 return found;
36}
37
38static int is_any_client_associated(struct rtw_adapter *padapter)
39{
40 return padapter->stapriv.asoc_list_cnt ? true : false;
41}
42
43static u32 go_add_group_info_attr(struct wifidirect_info *pwdinfo, u8 *pbuf)
44{
45 struct list_head *phead, *plist;
46 u32 len = 0;
47 u16 attr_len = 0;
48 u8 tmplen, *pdata_attr, *pstart, *pcur;
49 struct sta_info *psta;
50 struct rtw_adapter *padapter = pwdinfo->padapter;
51 struct sta_priv *pstapriv = &padapter->stapriv;
52
53 DBG_8723A("%s\n", __func__);
54
55 pdata_attr = kzalloc(MAX_P2P_IE_LEN, GFP_ATOMIC);
56
57 pstart = pdata_attr;
58 pcur = pdata_attr;
59
60 spin_lock_bh(&pstapriv->asoc_list_lock);
61 phead = &pstapriv->asoc_list;
62
63 list_for_each(plist, phead) {
64 psta = container_of(plist, struct sta_info, asoc_list);
65
66 if (psta->is_p2p_device)
67 {
68 tmplen = 0;
69
70 pcur++;
71
72 /* P2P device address */
73 memcpy(pcur, psta->dev_addr, ETH_ALEN);
74 pcur += ETH_ALEN;
75
76 /* P2P interface address */
77 memcpy(pcur, psta->hwaddr, ETH_ALEN);
78 pcur += ETH_ALEN;
79
80 *pcur = psta->dev_cap;
81 pcur++;
82
83 /* u16*)(pcur) = cpu_to_be16(psta->config_methods); */
84 put_unaligned_be16(psta->config_methods, pcur);
85 pcur += 2;
86
87 memcpy(pcur, psta->primary_dev_type, 8);
88 pcur += 8;
89
90 *pcur = psta->num_of_secdev_type;
91 pcur++;
92
93 memcpy(pcur, psta->secdev_types_list, psta->num_of_secdev_type*8);
94 pcur += psta->num_of_secdev_type*8;
95
96 if (psta->dev_name_len>0)
97 {
98 /* u16*)(pcur) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
99 put_unaligned_be16(WPS_ATTR_DEVICE_NAME, pcur);
100 pcur += 2;
101
102 /* u16*)(pcur) = cpu_to_be16(psta->dev_name_len); */
103 put_unaligned_be16(psta->dev_name_len, pcur);
104 pcur += 2;
105
106 memcpy(pcur, psta->dev_name, psta->dev_name_len);
107 pcur += psta->dev_name_len;
108 }
109
110 tmplen = (u8)(pcur-pstart);
111
112 *pstart = (tmplen-1);
113
114 attr_len += tmplen;
115
116 /* pstart += tmplen; */
117 pstart = pcur;
118
119 }
120
121 }
122 spin_unlock_bh(&pstapriv->asoc_list_lock);
123
124 if (attr_len>0)
125 {
126 len = rtw_set_p2p_attr_content23a(pbuf, P2P_ATTR_GROUP_INFO, attr_len, pdata_attr);
127 }
128
129 kfree(pdata_attr);
130
131 return len;
132}
133
134static void issue_group_disc_req(struct wifidirect_info *pwdinfo, u8 *da)
135{
136 struct xmit_frame *pmgntframe;
137 struct pkt_attrib *pattrib;
138 unsigned char *pframe;
139 struct ieee80211_hdr *pwlanhdr;
140 unsigned short *fctrl;
141 struct rtw_adapter *padapter = pwdinfo->padapter;
142 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
143 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
144 unsigned char category = WLAN_CATEGORY_VENDOR_SPECIFIC;/* P2P action frame */
145 u32 p2poui = cpu_to_be32(P2POUI);
146 u8 oui_subtype = P2P_GO_DISC_REQUEST;
147 u8 dialogToken = 0;
148
149 DBG_8723A("[%s]\n", __func__);
150
151 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
152 {
153 return;
154 }
155
156 /* update attribute */
157 pattrib = &pmgntframe->attrib;
158 update_mgntframe_attrib23a(padapter, pattrib);
159
160 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
161
162 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
163 pwlanhdr = (struct ieee80211_hdr *)pframe;
164
165 fctrl = &pwlanhdr->frame_control;
166 *fctrl = 0;
167
168 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
169 memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
170 memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
171
172 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
173 pmlmeext->mgnt_seq++;
174 SetFrameSubType(pframe, WIFI_ACTION);
175
176 pframe += sizeof(struct ieee80211_hdr_3addr);
177 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
178
179 /* Build P2P action frame header */
180 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
181 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui, &pattrib->pktlen);
182 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
183 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
184
185 /* there is no IE in this P2P action frame */
186
187 pattrib->last_txcmdsz = pattrib->pktlen;
188
189 dump_mgntframe23a(padapter, pmgntframe);
190}
191
192static void issue_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
193{
194 struct xmit_frame *pmgntframe;
195 struct pkt_attrib *pattrib;
196 unsigned char *pframe;
197 struct ieee80211_hdr *pwlanhdr;
198 unsigned short *fctrl;
199 struct rtw_adapter *padapter = pwdinfo->padapter;
200 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
201 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
202 unsigned char category = WLAN_CATEGORY_PUBLIC;
203 u8 action = P2P_PUB_ACTION_ACTION;
204 u32 p2poui = cpu_to_be32(P2POUI);
205 u8 oui_subtype = P2P_DEVDISC_RESP;
206 u8 p2pie[8] = { 0x00 };
207 u32 p2pielen = 0;
208
209 DBG_8723A("[%s]\n", __func__);
210
211 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
212 {
213 return;
214 }
215
216 /* update attribute */
217 pattrib = &pmgntframe->attrib;
218 update_mgntframe_attrib23a(padapter, pattrib);
219
220 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
221
222 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
223 pwlanhdr = (struct ieee80211_hdr *)pframe;
224
225 fctrl = &pwlanhdr->frame_control;
226 *fctrl = 0;
227
228 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
229 memcpy(pwlanhdr->addr2, pwdinfo->device_addr, ETH_ALEN);
230 memcpy(pwlanhdr->addr3, pwdinfo->device_addr, ETH_ALEN);
231
232 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
233 pmlmeext->mgnt_seq++;
234 SetFrameSubType(pframe, WIFI_ACTION);
235
236 pframe += sizeof(struct ieee80211_hdr_3addr);
237 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
238
239 /* Build P2P public action frame header */
240 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
241 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
242 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
243 &pattrib->pktlen);
244 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
245 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
246
247 /* Build P2P IE */
248 /* P2P OUI */
249 p2pielen = 0;
250 p2pie[ p2pielen++ ] = 0x50;
251 p2pie[ p2pielen++ ] = 0x6F;
252 p2pie[ p2pielen++ ] = 0x9A;
253 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
254
255 /* P2P_ATTR_STATUS */
256 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
257
258 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen);
259
260 pattrib->last_txcmdsz = pattrib->pktlen;
261
262 dump_mgntframe23a(padapter, pmgntframe);
263}
264
265static void issue_p2p_provision_resp(struct wifidirect_info *pwdinfo, u8* raddr, u8* frame_body, u16 config_method)
266{
267 struct rtw_adapter *padapter = pwdinfo->padapter;
268 unsigned char category = WLAN_CATEGORY_PUBLIC;
269 u8 action = P2P_PUB_ACTION_ACTION;
270 u8 dialogToken = frame_body[7]; /* The Dialog Token of provisioning discovery request frame. */
271 u32 p2poui = cpu_to_be32(P2POUI);
272 u8 oui_subtype = P2P_PROVISION_DISC_RESP;
273 u8 wpsie[ 100 ] = { 0x00 };
274 u8 wpsielen = 0;
275#ifdef CONFIG_8723AU_P2P
276 u32 wfdielen = 0;
277#endif /* CONFIG_8723AU_P2P */
278
279 struct xmit_frame *pmgntframe;
280 struct pkt_attrib *pattrib;
281 unsigned char *pframe;
282 struct ieee80211_hdr *pwlanhdr;
283 unsigned short *fctrl;
284 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
285 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
286
287 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
288 return;
289
290 /* update attribute */
291 pattrib = &pmgntframe->attrib;
292 update_mgntframe_attrib23a(padapter, pattrib);
293
294 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
295
296 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
297 pwlanhdr = (struct ieee80211_hdr *)pframe;
298
299 fctrl = &pwlanhdr->frame_control;
300 *fctrl = 0;
301
302 memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
303 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
304 memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN);
305
306 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
307 pmlmeext->mgnt_seq++;
308 SetFrameSubType(pframe, WIFI_ACTION);
309
310 pframe += sizeof(struct ieee80211_hdr_3addr);
311 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
312
313 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
314 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
315 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
316 &pattrib->pktlen);
317 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
318 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
319
320 wpsielen = 0;
321 /* WPS OUI */
322 /* u32*) (wpsie) = cpu_to_be32(WPSOUI); */
323 put_unaligned_be32(WPSOUI, wpsie);
324 wpsielen += 4;
325
326 /* Config Method */
327 /* Type: */
328 /* u16*) (wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD); */
329 put_unaligned_be16(WPS_ATTR_CONF_METHOD, wpsie + wpsielen);
330 wpsielen += 2;
331
332 /* Length: */
333 /* u16*) (wpsie + wpsielen) = cpu_to_be16(0x0002); */
334 put_unaligned_be16(0x0002, wpsie + wpsielen);
335 wpsielen += 2;
336
337 /* Value: */
338 /* u16*) (wpsie + wpsielen) = cpu_to_be16(config_method); */
339 put_unaligned_be16(config_method, wpsie + wpsielen);
340 wpsielen += 2;
341
342 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
343
344#ifdef CONFIG_8723AU_P2P
345 wfdielen = build_provdisc_resp_wfd_ie(pwdinfo, pframe);
346 pframe += wfdielen;
347 pattrib->pktlen += wfdielen;
348#endif /* CONFIG_8723AU_P2P */
349
350 pattrib->last_txcmdsz = pattrib->pktlen;
351
352 dump_mgntframe23a(padapter, pmgntframe);
353
354 return;
355}
356
357static void issue_p2p_presence_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
358{
359 struct xmit_frame *pmgntframe;
360 struct pkt_attrib *pattrib;
361 unsigned char *pframe;
362 struct ieee80211_hdr *pwlanhdr;
363 unsigned short *fctrl;
364 struct rtw_adapter *padapter = pwdinfo->padapter;
365 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
366 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
367 unsigned char category = WLAN_CATEGORY_VENDOR_SPECIFIC;/* P2P action frame */
368 u32 p2poui = cpu_to_be32(P2POUI);
369 u8 oui_subtype = P2P_PRESENCE_RESPONSE;
370 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
371 u8 noa_attr_content[32] = { 0x00 };
372 u32 p2pielen = 0;
373
374 DBG_8723A("[%s]\n", __func__);
375
376 if ((pmgntframe = alloc_mgtxmitframe23a(pxmitpriv)) == NULL)
377 {
378 return;
379 }
380
381 /* update attribute */
382 pattrib = &pmgntframe->attrib;
383 update_mgntframe_attrib23a(padapter, pattrib);
384
385 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
386
387 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
388 pwlanhdr = (struct ieee80211_hdr *)pframe;
389
390 fctrl = &pwlanhdr->frame_control;
391 *fctrl = 0;
392
393 memcpy(pwlanhdr->addr1, da, ETH_ALEN);
394 memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
395 memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
396
397 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
398 pmlmeext->mgnt_seq++;
399 SetFrameSubType(pframe, WIFI_ACTION);
400
401 pframe += sizeof(struct ieee80211_hdr_3addr);
402 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
403
404 /* Build P2P action frame header */
405 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
406 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *) &p2poui,
407 &pattrib->pktlen);
408 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
409 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
410
411 /* Add P2P IE header */
412 /* P2P OUI */
413 p2pielen = 0;
414 p2pie[ p2pielen++ ] = 0x50;
415 p2pie[ p2pielen++ ] = 0x6F;
416 p2pie[ p2pielen++ ] = 0x9A;
417 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
418
419 /* Add Status attribute in P2P IE */
420 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
421
422 /* Add NoA attribute in P2P IE */
423 noa_attr_content[0] = 0x1;/* index */
424 noa_attr_content[1] = 0x0;/* CTWindow and OppPS Parameters */
425
426 /* todo: Notice of Absence Descriptor(s) */
427
428 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_NOA, 2, noa_attr_content);
429
430 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie,
431 &pattrib->pktlen);
432
433 pattrib->last_txcmdsz = pattrib->pktlen;
434
435 dump_mgntframe23a(padapter, pmgntframe);
436}
437
438u32 build_beacon_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf)
439{
440 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
441 u16 capability = 0;
442 u32 len = 0, p2pielen = 0;
443
444 /* P2P OUI */
445 p2pielen = 0;
446 p2pie[ p2pielen++ ] = 0x50;
447 p2pie[ p2pielen++ ] = 0x6F;
448 p2pie[ p2pielen++ ] = 0x9A;
449 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
450
451 /* According to the P2P Specification, the beacon frame should contain 3 P2P attributes */
452 /* 1. P2P Capability */
453 /* 2. P2P Device ID */
454 /* 3. Notice of Absence (NOA) */
455
456 /* P2P Capability ATTR */
457 /* Type: */
458 /* Length: */
459 /* Value: */
460 /* Device Capability Bitmap, 1 byte */
461 /* Be able to participate in additional P2P Groups and */
462 /* support the P2P Invitation Procedure */
463 /* Group Capability Bitmap, 1 byte */
464 capability = P2P_DEVCAP_INVITATION_PROC|P2P_DEVCAP_CLIENT_DISCOVERABILITY;
465 capability |= ((P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS) << 8);
466 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
467 capability |= (P2P_GRPCAP_GROUP_FORMATION<<8);
468
469 capability = cpu_to_le16(capability);
470
471 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_CAPABILITY, 2, (u8*)&capability);
472
473 /* P2P Device ID ATTR */
474 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_DEVICE_ID, ETH_ALEN, pwdinfo->device_addr);
475
476 /* Notice of Absence ATTR */
477 /* Type: */
478 /* Length: */
479 /* Value: */
480
481 /* go_add_noa_attr(pwdinfo); */
482
483 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
484
485 return len;
486}
487
488#ifdef CONFIG_8723AU_P2P
489u32 build_beacon_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
490{
491 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
492 u32 len = 0, wfdielen = 0;
493 struct rtw_adapter *padapter = pwdinfo->padapter;
494 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
495 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
496
497 /* WFD OUI */
498 wfdielen = 0;
499 wfdie[ wfdielen++ ] = 0x50;
500 wfdie[ wfdielen++ ] = 0x6F;
501 wfdie[ wfdielen++ ] = 0x9A;
502 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
503
504 /* Commented by Albert 20110812 */
505 /* According to the WFD Specification, the beacon frame should contain 4 WFD attributes */
506 /* 1. WFD Device Information */
507 /* 2. Associated BSSID */
508 /* 3. Coupled Sink Information */
509
510 /* WFD Device Information ATTR */
511 /* Type: */
512 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
513
514 /* Length: */
515 /* Note: In the WFD specification, the size of length field is 2. */
516 put_unaligned_be16(0x0006, wfdie + wfdielen);
517 wfdielen += 2;
518
519 /* Value1: */
520 /* WFD device information */
521
522 if (P2P_ROLE_GO == pwdinfo->role)
523 {
524 if (is_any_client_associated(pwdinfo->padapter))
525 {
526 /* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) */
527 put_unaligned_be16(pwfd_info->wfd_device_type |
528 WFD_DEVINFO_WSD, wfdie + wfdielen);
529 }
530 else
531 {
532 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
533 put_unaligned_be16(pwfd_info->wfd_device_type |
534 WFD_DEVINFO_SESSION_AVAIL |
535 WFD_DEVINFO_WSD, wfdie + wfdielen);
536 }
537
538 }
539 else
540 {
541 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
542 put_unaligned_be16(pwfd_info->wfd_device_type |
543 WFD_DEVINFO_SESSION_AVAIL |
544 WFD_DEVINFO_WSD, wfdie + wfdielen);
545 }
546
547 wfdielen += 2;
548
549 /* Value2: */
550 /* Session Management Control Port */
551 /* Default TCP port for RTSP messages is 554 */
552 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
553 wfdielen += 2;
554
555 /* Value3: */
556 /* WFD Device Maximum Throughput */
557 /* 300Mbps is the maximum throughput */
558 put_unaligned_be16(300, wfdie + wfdielen);
559 wfdielen += 2;
560
561 /* Associated BSSID ATTR */
562 /* Type: */
563 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
564
565 /* Length: */
566 /* Note: In the WFD specification, the size of length field is 2. */
567 put_unaligned_be16(0x0006, wfdie + wfdielen);
568 wfdielen += 2;
569
570 /* Value: */
571 /* Associated BSSID */
572 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
573 {
574 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
575 }
576 else
577 {
578 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
579 }
580
581 wfdielen += ETH_ALEN;
582
583 /* Coupled Sink Information ATTR */
584 /* Type: */
585 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
586
587 /* Length: */
588 /* Note: In the WFD specification, the size of length field is 2. */
589 put_unaligned_be16(0x0007, wfdie + wfdielen);
590 wfdielen += 2;
591
592 /* Value: */
593 /* Coupled Sink Status bitmap */
594 /* Not coupled/available for Coupling */
595 wfdie[ wfdielen++ ] = 0;
596 /* MAC Addr. */
597 wfdie[ wfdielen++ ] = 0;
598 wfdie[ wfdielen++ ] = 0;
599 wfdie[ wfdielen++ ] = 0;
600 wfdie[ wfdielen++ ] = 0;
601 wfdie[ wfdielen++ ] = 0;
602 wfdie[ wfdielen++ ] = 0;
603
604 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
605
606 return len;
607}
608
609u32 build_probe_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
610{
611 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
612 u32 len = 0, wfdielen = 0;
613 struct rtw_adapter *padapter = pwdinfo->padapter;
614 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
615 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
616
617 /* WFD OUI */
618 wfdielen = 0;
619 wfdie[ wfdielen++ ] = 0x50;
620 wfdie[ wfdielen++ ] = 0x6F;
621 wfdie[ wfdielen++ ] = 0x9A;
622 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
623
624 /* Commented by Albert 20110812 */
625 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
626 /* 1. WFD Device Information */
627 /* 2. Associated BSSID */
628 /* 3. Coupled Sink Information */
629
630 /* WFD Device Information ATTR */
631 /* Type: */
632 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
633
634 /* Length: */
635 /* Note: In the WFD specification, the size of length field is 2. */
636 put_unaligned_be16(0x0006, wfdie + wfdielen);
637 wfdielen += 2;
638
639 /* Value1: */
640 /* WFD device information */
641
642 if (1 == pwdinfo->wfd_tdls_enable)
643 {
644 /* WFD primary sink + available for WFD session + WiFi TDLS mode + WSC (WFD Service Discovery) */
645 put_unaligned_be16(pwfd_info->wfd_device_type |
646 WFD_DEVINFO_SESSION_AVAIL |
647 WFD_DEVINFO_WSD |
648 WFD_DEVINFO_PC_TDLS, wfdie + wfdielen);
649 }
650 else
651 {
652 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSC (WFD Service Discovery) */
653 put_unaligned_be16(pwfd_info->wfd_device_type |
654 WFD_DEVINFO_SESSION_AVAIL |
655 WFD_DEVINFO_WSD, wfdie + wfdielen);
656 }
657
658 wfdielen += 2;
659
660 /* Value2: */
661 /* Session Management Control Port */
662 /* Default TCP port for RTSP messages is 554 */
663 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
664 wfdielen += 2;
665
666 /* Value3: */
667 /* WFD Device Maximum Throughput */
668 /* 300Mbps is the maximum throughput */
669 put_unaligned_be16(300, wfdie + wfdielen);
670 wfdielen += 2;
671
672 /* Associated BSSID ATTR */
673 /* Type: */
674 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
675
676 /* Length: */
677 /* Note: In the WFD specification, the size of length field is 2. */
678 put_unaligned_be16(0x0006, wfdie + wfdielen);
679 wfdielen += 2;
680
681 /* Value: */
682 /* Associated BSSID */
683 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
684 {
685 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
686 }
687 else
688 {
689 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
690 }
691
692 wfdielen += ETH_ALEN;
693
694 /* Coupled Sink Information ATTR */
695 /* Type: */
696 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
697
698 /* Length: */
699 /* Note: In the WFD specification, the size of length field is 2. */
700 put_unaligned_be16(0x0007, wfdie + wfdielen);
701 wfdielen += 2;
702
703 /* Value: */
704 /* Coupled Sink Status bitmap */
705 /* Not coupled/available for Coupling */
706 wfdie[ wfdielen++ ] = 0;
707 /* MAC Addr. */
708 wfdie[ wfdielen++ ] = 0;
709 wfdie[ wfdielen++ ] = 0;
710 wfdie[ wfdielen++ ] = 0;
711 wfdie[ wfdielen++ ] = 0;
712 wfdie[ wfdielen++ ] = 0;
713 wfdie[ wfdielen++ ] = 0;
714
715 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
716
717 return len;
718}
719
720u32 build_probe_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 tunneled)
721{
722 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
723 u32 len = 0, wfdielen = 0;
724 struct rtw_adapter *padapter = pwdinfo->padapter;
725 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
726 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
727
728 /* WFD OUI */
729 wfdielen = 0;
730 wfdie[ wfdielen++ ] = 0x50;
731 wfdie[ wfdielen++ ] = 0x6F;
732 wfdie[ wfdielen++ ] = 0x9A;
733 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
734
735 /* Commented by Albert 20110812 */
736 /* According to the WFD Specification, the probe response frame should contain 4 WFD attributes */
737 /* 1. WFD Device Information */
738 /* 2. Associated BSSID */
739 /* 3. Coupled Sink Information */
740 /* 4. WFD Session Information */
741
742 /* WFD Device Information ATTR */
743 /* Type: */
744 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
745
746 /* Length: */
747 /* Note: In the WFD specification, the size of length field is 2. */
748 put_unaligned_be16(0x0006, wfdie + wfdielen);
749 wfdielen += 2;
750
751 /* Value1: */
752 /* WFD device information */
753 /* WFD primary sink + available for WFD session + WiFi Direct mode */
754
755 if (true == pwdinfo->session_available)
756 {
757 if (P2P_ROLE_GO == pwdinfo->role)
758 {
759 if (is_any_client_associated(pwdinfo->padapter))
760 {
761 if (pwdinfo->wfd_tdls_enable)
762 {
763 /* TDLS mode + WSD (WFD Service Discovery) */
764 put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT, wfdie + wfdielen);
765 }
766 else
767 {
768 /* WiFi Direct mode + WSD (WFD Service Discovery) */
769 put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT, wfdie + wfdielen);
770 }
771 }
772 else
773 {
774 if (pwdinfo->wfd_tdls_enable)
775 {
776 /* available for WFD session + TDLS mode + WSD (WFD Service Discovery) */
777 put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT, wfdie + wfdielen);
778 }
779 else
780 {
781 /* available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
782 put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT, wfdie + wfdielen);
783 }
784 }
785 }
786 else
787 {
788 if (pwdinfo->wfd_tdls_enable)
789 {
790 /* available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
791 put_unaligned_be16(pwfd_info->wfd_device_type |
792 WFD_DEVINFO_SESSION_AVAIL |
793 WFD_DEVINFO_WSD |
794 WFD_DEVINFO_PC_TDLS |
795 WFD_DEVINFO_HDCP_SUPPORT,
796 wfdie + wfdielen);
797 }
798 else
799 {
800
801 /* available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
802 put_unaligned_be16(pwfd_info->wfd_device_type |
803 WFD_DEVINFO_SESSION_AVAIL |
804 WFD_DEVINFO_WSD |
805 WFD_DEVINFO_HDCP_SUPPORT,
806 wfdie + wfdielen);
807 }
808 }
809 }
810 else
811 {
812 if (pwdinfo->wfd_tdls_enable)
813 {
814 put_unaligned_be16(pwfd_info->wfd_device_type |
815 WFD_DEVINFO_WSD |
816 WFD_DEVINFO_PC_TDLS |
817 WFD_DEVINFO_HDCP_SUPPORT,
818 wfdie + wfdielen);
819 }
820 else
821 {
822 put_unaligned_be16(pwfd_info->wfd_device_type |
823 WFD_DEVINFO_WSD |
824 WFD_DEVINFO_HDCP_SUPPORT,
825 wfdie + wfdielen);
826 }
827
828 }
829
830 wfdielen += 2;
831
832 /* Value2: */
833 /* Session Management Control Port */
834 /* Default TCP port for RTSP messages is 554 */
835 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
836 wfdielen += 2;
837
838 /* Value3: */
839 /* WFD Device Maximum Throughput */
840 /* 300Mbps is the maximum throughput */
841 put_unaligned_be16(300, wfdie + wfdielen);
842 wfdielen += 2;
843
844 /* Associated BSSID ATTR */
845 /* Type: */
846 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
847
848 /* Length: */
849 /* Note: In the WFD specification, the size of length field is 2. */
850 put_unaligned_be16(0x0006, wfdie + wfdielen);
851 wfdielen += 2;
852
853 /* Value: */
854 /* Associated BSSID */
855 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
856 {
857 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
858 }
859 else
860 {
861 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
862 }
863
864 wfdielen += ETH_ALEN;
865
866 /* Coupled Sink Information ATTR */
867 /* Type: */
868 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
869
870 /* Length: */
871 /* Note: In the WFD specification, the size of length field is 2. */
872 put_unaligned_be16(0x0007, wfdie + wfdielen);
873 wfdielen += 2;
874
875 /* Value: */
876 /* Coupled Sink Status bitmap */
877 /* Not coupled/available for Coupling */
878 wfdie[ wfdielen++ ] = 0;
879 /* MAC Addr. */
880 wfdie[ wfdielen++ ] = 0;
881 wfdie[ wfdielen++ ] = 0;
882 wfdie[ wfdielen++ ] = 0;
883 wfdie[ wfdielen++ ] = 0;
884 wfdie[ wfdielen++ ] = 0;
885 wfdie[ wfdielen++ ] = 0;
886
887 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
888 {
889 /* WFD Session Information ATTR */
890 /* Type: */
891 wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
892
893 /* Length: */
894 /* Note: In the WFD specification, the size of length field is 2. */
895 put_unaligned_be16(0x0000, wfdie + wfdielen);
896 wfdielen += 2;
897
898 /* Todo: to add the list of WFD device info descriptor in WFD group. */
899
900 }
901
902 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
903
904 return len;
905}
906
907u32 build_assoc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
908{
909 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
910 u32 len = 0, wfdielen = 0;
911 struct rtw_adapter *padapter = NULL;
912 struct mlme_priv *pmlmepriv = NULL;
913 struct wifi_display_info *pwfd_info = NULL;
914
915 /* WFD OUI */
916 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
917 {
918 return 0;
919 }
920
921 padapter = pwdinfo->padapter;
922 pmlmepriv = &padapter->mlmepriv;
923 pwfd_info = padapter->wdinfo.wfd_info;
924
925 wfdielen = 0;
926 wfdie[ wfdielen++ ] = 0x50;
927 wfdie[ wfdielen++ ] = 0x6F;
928 wfdie[ wfdielen++ ] = 0x9A;
929 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
930
931 /* Commented by Albert 20110812 */
932 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
933 /* 1. WFD Device Information */
934 /* 2. Associated BSSID */
935 /* 3. Coupled Sink Information */
936
937 /* WFD Device Information ATTR */
938 /* Type: */
939 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
940
941 /* Length: */
942 /* Note: In the WFD specification, the size of length field is 2. */
943 put_unaligned_be16(0x0006, wfdie + wfdielen);
944 wfdielen += 2;
945
946 /* Value1: */
947 /* WFD device information */
948 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
949 put_unaligned_be16(pwfd_info->wfd_device_type |
950 WFD_DEVINFO_SESSION_AVAIL |
951 WFD_DEVINFO_WSD, wfdie + wfdielen);
952 wfdielen += 2;
953
954 /* Value2: */
955 /* Session Management Control Port */
956 /* Default TCP port for RTSP messages is 554 */
957 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
958 wfdielen += 2;
959
960 /* Value3: */
961 /* WFD Device Maximum Throughput */
962 /* 300Mbps is the maximum throughput */
963 put_unaligned_be16(300, wfdie + wfdielen);
964 wfdielen += 2;
965
966 /* Associated BSSID ATTR */
967 /* Type: */
968 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
969
970 /* Length: */
971 /* Note: In the WFD specification, the size of length field is 2. */
972 put_unaligned_be16(0x0006, wfdie + wfdielen);
973 wfdielen += 2;
974
975 /* Value: */
976 /* Associated BSSID */
977 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
978 {
979 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
980 }
981 else
982 {
983 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
984 }
985
986 wfdielen += ETH_ALEN;
987
988 /* Coupled Sink Information ATTR */
989 /* Type: */
990 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
991
992 /* Length: */
993 /* Note: In the WFD specification, the size of length field is 2. */
994 put_unaligned_be16(0x0007, wfdie + wfdielen);
995 wfdielen += 2;
996
997 /* Value: */
998 /* Coupled Sink Status bitmap */
999 /* Not coupled/available for Coupling */
1000 wfdie[ wfdielen++ ] = 0;
1001 /* MAC Addr. */
1002 wfdie[ wfdielen++ ] = 0;
1003 wfdie[ wfdielen++ ] = 0;
1004 wfdie[ wfdielen++ ] = 0;
1005 wfdie[ wfdielen++ ] = 0;
1006 wfdie[ wfdielen++ ] = 0;
1007 wfdie[ wfdielen++ ] = 0;
1008
1009 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1010
1011 return len;
1012}
1013
1014u32 build_assoc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1015{
1016 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1017 u32 len = 0, wfdielen = 0;
1018 struct rtw_adapter *padapter = pwdinfo->padapter;
1019 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1020 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1021
1022 /* WFD OUI */
1023 wfdielen = 0;
1024 wfdie[ wfdielen++ ] = 0x50;
1025 wfdie[ wfdielen++ ] = 0x6F;
1026 wfdie[ wfdielen++ ] = 0x9A;
1027 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1028
1029 /* Commented by Albert 20110812 */
1030 /* According to the WFD Specification, the probe request frame should contain 4 WFD attributes */
1031 /* 1. WFD Device Information */
1032 /* 2. Associated BSSID */
1033 /* 3. Coupled Sink Information */
1034
1035 /* WFD Device Information ATTR */
1036 /* Type: */
1037 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1038
1039 /* Length: */
1040 /* Note: In the WFD specification, the size of length field is 2. */
1041 put_unaligned_be16(0x0006, wfdie + wfdielen);
1042 wfdielen += 2;
1043
1044 /* Value1: */
1045 /* WFD device information */
1046 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1047 put_unaligned_be16(pwfd_info->wfd_device_type |
1048 WFD_DEVINFO_SESSION_AVAIL |
1049 WFD_DEVINFO_WSD, wfdie + wfdielen);
1050 wfdielen += 2;
1051
1052 /* Value2: */
1053 /* Session Management Control Port */
1054 /* Default TCP port for RTSP messages is 554 */
1055 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1056 wfdielen += 2;
1057
1058 /* Value3: */
1059 /* WFD Device Maximum Throughput */
1060 /* 300Mbps is the maximum throughput */
1061 put_unaligned_be16(300, wfdie + wfdielen);
1062 wfdielen += 2;
1063
1064 /* Associated BSSID ATTR */
1065 /* Type: */
1066 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1067
1068 /* Length: */
1069 /* Note: In the WFD specification, the size of length field is 2. */
1070 put_unaligned_be16(0x0006, wfdie + wfdielen);
1071 wfdielen += 2;
1072
1073 /* Value: */
1074 /* Associated BSSID */
1075 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1076 {
1077 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1078 }
1079 else
1080 {
1081 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1082 }
1083
1084 wfdielen += ETH_ALEN;
1085
1086 /* Coupled Sink Information ATTR */
1087 /* Type: */
1088 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1089
1090 /* Length: */
1091 /* Note: In the WFD specification, the size of length field is 2. */
1092 put_unaligned_be16(0x0007, wfdie + wfdielen);
1093 wfdielen += 2;
1094
1095 /* Value: */
1096 /* Coupled Sink Status bitmap */
1097 /* Not coupled/available for Coupling */
1098 wfdie[ wfdielen++ ] = 0;
1099 /* MAC Addr. */
1100 wfdie[ wfdielen++ ] = 0;
1101 wfdie[ wfdielen++ ] = 0;
1102 wfdie[ wfdielen++ ] = 0;
1103 wfdie[ wfdielen++ ] = 0;
1104 wfdie[ wfdielen++ ] = 0;
1105 wfdie[ wfdielen++ ] = 0;
1106
1107 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1108
1109 return len;
1110}
1111
1112u32 build_nego_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1113{
1114 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1115 u32 len = 0, wfdielen = 0;
1116 struct rtw_adapter *padapter = pwdinfo->padapter;
1117 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1118 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1119
1120 /* WFD OUI */
1121 wfdielen = 0;
1122 wfdie[ wfdielen++ ] = 0x50;
1123 wfdie[ wfdielen++ ] = 0x6F;
1124 wfdie[ wfdielen++ ] = 0x9A;
1125 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1126
1127 /* Commented by Albert 20110825 */
1128 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1129 /* 1. WFD Device Information */
1130 /* 2. Associated BSSID (Optional) */
1131 /* 3. Local IP Adress (Optional) */
1132
1133 /* WFD Device Information ATTR */
1134 /* Type: */
1135 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1136
1137 /* Length: */
1138 /* Note: In the WFD specification, the size of length field is 2. */
1139 put_unaligned_be16(0x0006, wfdie + wfdielen);
1140 wfdielen += 2;
1141
1142 /* Value1: */
1143 /* WFD device information */
1144 /* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) + WFD Session Available */
1145 put_unaligned_be16(pwfd_info->wfd_device_type |
1146 WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL,
1147 wfdie + wfdielen);
1148 wfdielen += 2;
1149
1150 /* Value2: */
1151 /* Session Management Control Port */
1152 /* Default TCP port for RTSP messages is 554 */
1153 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1154 wfdielen += 2;
1155
1156 /* Value3: */
1157 /* WFD Device Maximum Throughput */
1158 /* 300Mbps is the maximum throughput */
1159 put_unaligned_be16(300, wfdie + wfdielen);
1160 wfdielen += 2;
1161
1162 /* Associated BSSID ATTR */
1163 /* Type: */
1164 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1165
1166 /* Length: */
1167 /* Note: In the WFD specification, the size of length field is 2. */
1168 put_unaligned_be16(0x0006, wfdie + wfdielen);
1169 wfdielen += 2;
1170
1171 /* Value: */
1172 /* Associated BSSID */
1173 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1174 {
1175 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1176 }
1177 else
1178 {
1179 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1180 }
1181
1182 wfdielen += ETH_ALEN;
1183
1184 /* Coupled Sink Information ATTR */
1185 /* Type: */
1186 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1187
1188 /* Length: */
1189 /* Note: In the WFD specification, the size of length field is 2. */
1190 put_unaligned_be16(0x0007, wfdie + wfdielen);
1191 wfdielen += 2;
1192
1193 /* Value: */
1194 /* Coupled Sink Status bitmap */
1195 /* Not coupled/available for Coupling */
1196 wfdie[ wfdielen++ ] = 0;
1197 /* MAC Addr. */
1198 wfdie[ wfdielen++ ] = 0;
1199 wfdie[ wfdielen++ ] = 0;
1200 wfdie[ wfdielen++ ] = 0;
1201 wfdie[ wfdielen++ ] = 0;
1202 wfdie[ wfdielen++ ] = 0;
1203 wfdie[ wfdielen++ ] = 0;
1204
1205 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1206
1207 return len;
1208}
1209
1210u32 build_nego_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1211{
1212 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1213 u32 len = 0, wfdielen = 0;
1214 struct rtw_adapter *padapter = pwdinfo->padapter;
1215 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1216 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1217
1218 /* WFD OUI */
1219 wfdielen = 0;
1220 wfdie[ wfdielen++ ] = 0x50;
1221 wfdie[ wfdielen++ ] = 0x6F;
1222 wfdie[ wfdielen++ ] = 0x9A;
1223 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1224
1225 /* Commented by Albert 20110825 */
1226 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1227 /* 1. WFD Device Information */
1228 /* 2. Associated BSSID (Optional) */
1229 /* 3. Local IP Adress (Optional) */
1230
1231 /* WFD Device Information ATTR */
1232 /* Type: */
1233 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1234
1235 /* Length: */
1236 /* Note: In the WFD specification, the size of length field is 2. */
1237 put_unaligned_be16(0x0006, wfdie + wfdielen);
1238 wfdielen += 2;
1239
1240 /* Value1: */
1241 /* WFD device information */
1242 /* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) + WFD Session Available */
1243 put_unaligned_be16(pwfd_info->wfd_device_type |
1244 WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL,
1245 wfdie + wfdielen);
1246 wfdielen += 2;
1247
1248 /* Value2: */
1249 /* Session Management Control Port */
1250 /* Default TCP port for RTSP messages is 554 */
1251 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1252 wfdielen += 2;
1253
1254 /* Value3: */
1255 /* WFD Device Maximum Throughput */
1256 /* 300Mbps is the maximum throughput */
1257 put_unaligned_be16(300, wfdie + wfdielen);
1258 wfdielen += 2;
1259
1260 /* Associated BSSID ATTR */
1261 /* Type: */
1262 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1263
1264 /* Length: */
1265 /* Note: In the WFD specification, the size of length field is 2. */
1266 put_unaligned_be16(0x0006, wfdie + wfdielen);
1267 wfdielen += 2;
1268
1269 /* Value: */
1270 /* Associated BSSID */
1271 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1272 {
1273 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1274 }
1275 else
1276 {
1277 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1278 }
1279
1280 wfdielen += ETH_ALEN;
1281
1282 /* Coupled Sink Information ATTR */
1283 /* Type: */
1284 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1285
1286 /* Length: */
1287 /* Note: In the WFD specification, the size of length field is 2. */
1288 put_unaligned_be16(0x0007, wfdie + wfdielen);
1289 wfdielen += 2;
1290
1291 /* Value: */
1292 /* Coupled Sink Status bitmap */
1293 /* Not coupled/available for Coupling */
1294 wfdie[ wfdielen++ ] = 0;
1295 /* MAC Addr. */
1296 wfdie[ wfdielen++ ] = 0;
1297 wfdie[ wfdielen++ ] = 0;
1298 wfdie[ wfdielen++ ] = 0;
1299 wfdie[ wfdielen++ ] = 0;
1300 wfdie[ wfdielen++ ] = 0;
1301 wfdie[ wfdielen++ ] = 0;
1302
1303 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1304
1305 return len;
1306}
1307
1308u32 build_nego_confirm_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1309{
1310 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1311 u32 len = 0, wfdielen = 0;
1312 struct rtw_adapter *padapter = pwdinfo->padapter;
1313 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1314 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1315
1316 /* WFD OUI */
1317 wfdielen = 0;
1318 wfdie[ wfdielen++ ] = 0x50;
1319 wfdie[ wfdielen++ ] = 0x6F;
1320 wfdie[ wfdielen++ ] = 0x9A;
1321 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1322
1323 /* Commented by Albert 20110825 */
1324 /* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes */
1325 /* 1. WFD Device Information */
1326 /* 2. Associated BSSID (Optional) */
1327 /* 3. Local IP Adress (Optional) */
1328
1329 /* WFD Device Information ATTR */
1330 /* Type: */
1331 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1332
1333 /* Length: */
1334 /* Note: In the WFD specification, the size of length field is 2. */
1335 put_unaligned_be16(0x0006, wfdie + wfdielen);
1336 wfdielen += 2;
1337
1338 /* Value1: */
1339 /* WFD device information */
1340 /* WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery) + WFD Session Available */
1341 put_unaligned_be16(pwfd_info->wfd_device_type | WFD_DEVINFO_WSD |
1342 WFD_DEVINFO_SESSION_AVAIL, wfdie + wfdielen);
1343 wfdielen += 2;
1344
1345 /* Value2: */
1346 /* Session Management Control Port */
1347 /* Default TCP port for RTSP messages is 554 */
1348 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1349 wfdielen += 2;
1350
1351 /* Value3: */
1352 /* WFD Device Maximum Throughput */
1353 /* 300Mbps is the maximum throughput */
1354 put_unaligned_be16(300, wfdie + wfdielen);
1355 wfdielen += 2;
1356
1357 /* Associated BSSID ATTR */
1358 /* Type: */
1359 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1360
1361 /* Length: */
1362 /* Note: In the WFD specification, the size of length field is 2. */
1363 put_unaligned_be16(0x0006, wfdie + wfdielen);
1364 wfdielen += 2;
1365
1366 /* Value: */
1367 /* Associated BSSID */
1368 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1369 {
1370 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1371 }
1372 else
1373 {
1374 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1375 }
1376
1377 wfdielen += ETH_ALEN;
1378
1379 /* Coupled Sink Information ATTR */
1380 /* Type: */
1381 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1382
1383 /* Length: */
1384 /* Note: In the WFD specification, the size of length field is 2. */
1385 put_unaligned_be16(0x0007, wfdie + wfdielen);
1386 wfdielen += 2;
1387
1388 /* Value: */
1389 /* Coupled Sink Status bitmap */
1390 /* Not coupled/available for Coupling */
1391 wfdie[ wfdielen++ ] = 0;
1392 /* MAC Addr. */
1393 wfdie[ wfdielen++ ] = 0;
1394 wfdie[ wfdielen++ ] = 0;
1395 wfdie[ wfdielen++ ] = 0;
1396 wfdie[ wfdielen++ ] = 0;
1397 wfdie[ wfdielen++ ] = 0;
1398 wfdie[ wfdielen++ ] = 0;
1399
1400 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1401
1402 return len;
1403}
1404
1405u32 build_invitation_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1406{
1407 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1408 u32 len = 0, wfdielen = 0;
1409 struct rtw_adapter *padapter = pwdinfo->padapter;
1410 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1411 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1412
1413 /* WFD OUI */
1414 wfdielen = 0;
1415 wfdie[ wfdielen++ ] = 0x50;
1416 wfdie[ wfdielen++ ] = 0x6F;
1417 wfdie[ wfdielen++ ] = 0x9A;
1418 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1419
1420 /* Commented by Albert 20110825 */
1421 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1422 /* 1. WFD Device Information */
1423 /* 2. Associated BSSID (Optional) */
1424 /* 3. Local IP Adress (Optional) */
1425
1426 /* WFD Device Information ATTR */
1427 /* Type: */
1428 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1429
1430 /* Length: */
1431 /* Note: In the WFD specification, the size of length field is 2. */
1432 put_unaligned_be16(0x0006, wfdie + wfdielen);
1433 wfdielen += 2;
1434
1435 /* Value1: */
1436 /* WFD device information */
1437 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1438 put_unaligned_be16(pwfd_info->wfd_device_type |
1439 WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD,
1440 wfdie + wfdielen);
1441 wfdielen += 2;
1442
1443 /* Value2: */
1444 /* Session Management Control Port */
1445 /* Default TCP port for RTSP messages is 554 */
1446 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1447 wfdielen += 2;
1448
1449 /* Value3: */
1450 /* WFD Device Maximum Throughput */
1451 /* 300Mbps is the maximum throughput */
1452 put_unaligned_be16(300, wfdie + wfdielen);
1453 wfdielen += 2;
1454
1455 /* Associated BSSID ATTR */
1456 /* Type: */
1457 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1458
1459 /* Length: */
1460 /* Note: In the WFD specification, the size of length field is 2. */
1461 put_unaligned_be16(0x0006, wfdie + wfdielen);
1462 wfdielen += 2;
1463
1464 /* Value: */
1465 /* Associated BSSID */
1466 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1467 {
1468 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1469 }
1470 else
1471 {
1472 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1473 }
1474
1475 wfdielen += ETH_ALEN;
1476
1477 /* Coupled Sink Information ATTR */
1478 /* Type: */
1479 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1480
1481 /* Length: */
1482 /* Note: In the WFD specification, the size of length field is 2. */
1483 put_unaligned_be16(0x0007, wfdie + wfdielen);
1484 wfdielen += 2;
1485
1486 /* Value: */
1487 /* Coupled Sink Status bitmap */
1488 /* Not coupled/available for Coupling */
1489 wfdie[ wfdielen++ ] = 0;
1490 /* MAC Addr. */
1491 wfdie[ wfdielen++ ] = 0;
1492 wfdie[ wfdielen++ ] = 0;
1493 wfdie[ wfdielen++ ] = 0;
1494 wfdie[ wfdielen++ ] = 0;
1495 wfdie[ wfdielen++ ] = 0;
1496 wfdie[ wfdielen++ ] = 0;
1497
1498 if (P2P_ROLE_GO == pwdinfo->role)
1499 {
1500 /* WFD Session Information ATTR */
1501 /* Type: */
1502 wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
1503
1504 /* Length: */
1505 /* Note: In the WFD specification, the size of length field is 2. */
1506 put_unaligned_be16(0x0000, wfdie + wfdielen);
1507 wfdielen += 2;
1508
1509 /* Todo: to add the list of WFD device info descriptor in WFD group. */
1510
1511 }
1512
1513 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1514
1515 return len;
1516}
1517
1518u32 build_invitation_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1519{
1520 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1521 u32 len = 0, wfdielen = 0;
1522 struct rtw_adapter *padapter = pwdinfo->padapter;
1523 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1524 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1525
1526 /* WFD OUI */
1527 wfdielen = 0;
1528 wfdie[ wfdielen++ ] = 0x50;
1529 wfdie[ wfdielen++ ] = 0x6F;
1530 wfdie[ wfdielen++ ] = 0x9A;
1531 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1532
1533 /* Commented by Albert 20110825 */
1534 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1535 /* 1. WFD Device Information */
1536 /* 2. Associated BSSID (Optional) */
1537 /* 3. Local IP Adress (Optional) */
1538
1539 /* WFD Device Information ATTR */
1540 /* Type: */
1541 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1542
1543 /* Length: */
1544 /* Note: In the WFD specification, the size of length field is 2. */
1545 put_unaligned_be16(0x0006, wfdie + wfdielen);
1546 wfdielen += 2;
1547
1548 /* Value1: */
1549 /* WFD device information */
1550 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1551 put_unaligned_be16(pwfd_info->wfd_device_type |
1552 WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD,
1553 wfdie + wfdielen);
1554 wfdielen += 2;
1555
1556 /* Value2: */
1557 /* Session Management Control Port */
1558 /* Default TCP port for RTSP messages is 554 */
1559 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1560 wfdielen += 2;
1561
1562 /* Value3: */
1563 /* WFD Device Maximum Throughput */
1564 /* 300Mbps is the maximum throughput */
1565 put_unaligned_be16(300, wfdie + wfdielen);
1566 wfdielen += 2;
1567
1568 /* Associated BSSID ATTR */
1569 /* Type: */
1570 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1571
1572 /* Length: */
1573 /* Note: In the WFD specification, the size of length field is 2. */
1574 put_unaligned_be16(0x0006, wfdie + wfdielen);
1575 wfdielen += 2;
1576
1577 /* Value: */
1578 /* Associated BSSID */
1579 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1580 {
1581 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1582 }
1583 else
1584 {
1585 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1586 }
1587
1588 wfdielen += ETH_ALEN;
1589
1590 /* Coupled Sink Information ATTR */
1591 /* Type: */
1592 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1593
1594 /* Length: */
1595 /* Note: In the WFD specification, the size of length field is 2. */
1596 put_unaligned_be16(0x0007, wfdie + wfdielen);
1597 wfdielen += 2;
1598
1599 /* Value: */
1600 /* Coupled Sink Status bitmap */
1601 /* Not coupled/available for Coupling */
1602 wfdie[ wfdielen++ ] = 0;
1603 /* MAC Addr. */
1604 wfdie[ wfdielen++ ] = 0;
1605 wfdie[ wfdielen++ ] = 0;
1606 wfdie[ wfdielen++ ] = 0;
1607 wfdie[ wfdielen++ ] = 0;
1608 wfdie[ wfdielen++ ] = 0;
1609 wfdie[ wfdielen++ ] = 0;
1610
1611 if (P2P_ROLE_GO == pwdinfo->role)
1612 {
1613 /* WFD Session Information ATTR */
1614 /* Type: */
1615 wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
1616
1617 /* Length: */
1618 /* Note: In the WFD specification, the size of length field is 2. */
1619 put_unaligned_be16(0x0000, wfdie + wfdielen);
1620 wfdielen += 2;
1621
1622 /* Todo: to add the list of WFD device info descriptor in WFD group. */
1623
1624 }
1625
1626 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1627
1628 return len;
1629}
1630
1631u32 build_provdisc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1632{
1633 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1634 u32 len = 0, wfdielen = 0;
1635 struct rtw_adapter *padapter = pwdinfo->padapter;
1636 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1637 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1638
1639 /* WFD OUI */
1640 wfdielen = 0;
1641 wfdie[ wfdielen++ ] = 0x50;
1642 wfdie[ wfdielen++ ] = 0x6F;
1643 wfdie[ wfdielen++ ] = 0x9A;
1644 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1645
1646 /* Commented by Albert 20110825 */
1647 /* According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes */
1648 /* 1. WFD Device Information */
1649 /* 2. Associated BSSID (Optional) */
1650 /* 3. Local IP Adress (Optional) */
1651
1652 /* WFD Device Information ATTR */
1653 /* Type: */
1654 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1655
1656 /* Length: */
1657 /* Note: In the WFD specification, the size of length field is 2. */
1658 put_unaligned_be16(0x0006, wfdie + wfdielen);
1659 wfdielen += 2;
1660
1661 /* Value1: */
1662 /* WFD device information */
1663 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1664 put_unaligned_be16(pwfd_info->wfd_device_type |
1665 WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD,
1666 wfdie + wfdielen);
1667 wfdielen += 2;
1668
1669 /* Value2: */
1670 /* Session Management Control Port */
1671 /* Default TCP port for RTSP messages is 554 */
1672 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1673 wfdielen += 2;
1674
1675 /* Value3: */
1676 /* WFD Device Maximum Throughput */
1677 /* 300Mbps is the maximum throughput */
1678 put_unaligned_be16(300, wfdie + wfdielen);
1679 wfdielen += 2;
1680
1681 /* Associated BSSID ATTR */
1682 /* Type: */
1683 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1684
1685 /* Length: */
1686 /* Note: In the WFD specification, the size of length field is 2. */
1687 put_unaligned_be16(0x0006, wfdie + wfdielen);
1688 wfdielen += 2;
1689
1690 /* Value: */
1691 /* Associated BSSID */
1692 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1693 {
1694 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1695 }
1696 else
1697 {
1698 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1699 }
1700
1701 wfdielen += ETH_ALEN;
1702
1703 /* Coupled Sink Information ATTR */
1704 /* Type: */
1705 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1706
1707 /* Length: */
1708 /* Note: In the WFD specification, the size of length field is 2. */
1709 put_unaligned_be16(0x0007, wfdie + wfdielen);
1710 wfdielen += 2;
1711
1712 /* Value: */
1713 /* Coupled Sink Status bitmap */
1714 /* Not coupled/available for Coupling */
1715 wfdie[ wfdielen++ ] = 0;
1716 /* MAC Addr. */
1717 wfdie[ wfdielen++ ] = 0;
1718 wfdie[ wfdielen++ ] = 0;
1719 wfdie[ wfdielen++ ] = 0;
1720 wfdie[ wfdielen++ ] = 0;
1721 wfdie[ wfdielen++ ] = 0;
1722 wfdie[ wfdielen++ ] = 0;
1723
1724 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1725
1726 return len;
1727}
1728
1729u32 build_provdisc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
1730{
1731 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
1732 u32 len = 0, wfdielen = 0;
1733 struct rtw_adapter *padapter = pwdinfo->padapter;
1734 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1735 struct wifi_display_info* pwfd_info = padapter->wdinfo.wfd_info;
1736
1737 /* WFD OUI */
1738 wfdielen = 0;
1739 wfdie[ wfdielen++ ] = 0x50;
1740 wfdie[ wfdielen++ ] = 0x6F;
1741 wfdie[ wfdielen++ ] = 0x9A;
1742 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
1743
1744 /* Commented by Albert 20110825 */
1745 /* According to the WFD Specification, the provision discovery response frame should contain 3 WFD attributes */
1746 /* 1. WFD Device Information */
1747 /* 2. Associated BSSID (Optional) */
1748 /* 3. Local IP Adress (Optional) */
1749
1750 /* WFD Device Information ATTR */
1751 /* Type: */
1752 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
1753
1754 /* Length: */
1755 /* Note: In the WFD specification, the size of length field is 2. */
1756 put_unaligned_be16(0x0006, wfdie + wfdielen);
1757 wfdielen += 2;
1758
1759 /* Value1: */
1760 /* WFD device information */
1761 /* WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery) */
1762 put_unaligned_be16(pwfd_info->wfd_device_type |
1763 WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD,
1764 wfdie + wfdielen);
1765 wfdielen += 2;
1766
1767 /* Value2: */
1768 /* Session Management Control Port */
1769 /* Default TCP port for RTSP messages is 554 */
1770 put_unaligned_be16(pwfd_info->rtsp_ctrlport, wfdie + wfdielen);
1771 wfdielen += 2;
1772
1773 /* Value3: */
1774 /* WFD Device Maximum Throughput */
1775 /* 300Mbps is the maximum throughput */
1776 put_unaligned_be16(300, wfdie + wfdielen);
1777 wfdielen += 2;
1778
1779 /* Associated BSSID ATTR */
1780 /* Type: */
1781 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
1782
1783 /* Length: */
1784 /* Note: In the WFD specification, the size of length field is 2. */
1785 put_unaligned_be16(0x0006, wfdie + wfdielen);
1786 wfdielen += 2;
1787
1788 /* Value: */
1789 /* Associated BSSID */
1790 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
1791 {
1792 memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
1793 }
1794 else
1795 {
1796 memset(wfdie + wfdielen, 0x00, ETH_ALEN);
1797 }
1798
1799 wfdielen += ETH_ALEN;
1800
1801 /* Coupled Sink Information ATTR */
1802 /* Type: */
1803 wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
1804
1805 /* Length: */
1806 /* Note: In the WFD specification, the size of length field is 2. */
1807 put_unaligned_be16(0x0007, wfdie + wfdielen);
1808 wfdielen += 2;
1809
1810 /* Value: */
1811 /* Coupled Sink Status bitmap */
1812 /* Not coupled/available for Coupling */
1813 wfdie[ wfdielen++ ] = 0;
1814 /* MAC Addr. */
1815 wfdie[ wfdielen++ ] = 0;
1816 wfdie[ wfdielen++ ] = 0;
1817 wfdie[ wfdielen++ ] = 0;
1818 wfdie[ wfdielen++ ] = 0;
1819 wfdie[ wfdielen++ ] = 0;
1820 wfdie[ wfdielen++ ] = 0;
1821
1822 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
1823
1824 return len;
1825}
1826
1827#endif /* CONFIG_8723AU_P2P */
1828
1829u32 build_probe_resp_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf)
1830{
1831 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
1832 u32 len = 0, p2pielen = 0;
1833
1834 /* P2P OUI */
1835 p2pielen = 0;
1836 p2pie[ p2pielen++ ] = 0x50;
1837 p2pie[ p2pielen++ ] = 0x6F;
1838 p2pie[ p2pielen++ ] = 0x9A;
1839 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
1840
1841 /* Commented by Albert 20100907 */
1842 /* According to the P2P Specification, the probe response frame should contain 5 P2P attributes */
1843 /* 1. P2P Capability */
1844 /* 2. Extended Listen Timing */
1845 /* 3. Notice of Absence (NOA) (Only GO needs this) */
1846 /* 4. Device Info */
1847 /* 5. Group Info (Only GO need this) */
1848
1849 /* P2P Capability ATTR */
1850 /* Type: */
1851 p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
1852
1853 /* Length: */
1854 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */
1855 put_unaligned_le16(0x0002, p2pie + p2pielen);
1856 p2pielen += 2;
1857
1858 /* Value: */
1859 /* Device Capability Bitmap, 1 byte */
1860 p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
1861
1862 /* Group Capability Bitmap, 1 byte */
1863 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
1864 {
1865 p2pie[ p2pielen ] = (P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS);
1866
1867 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
1868 p2pie[ p2pielen ] |= P2P_GRPCAP_GROUP_FORMATION;
1869
1870 p2pielen++;
1871 }
1872 else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE))
1873 {
1874 /* Group Capability Bitmap, 1 byte */
1875 if (pwdinfo->persistent_supported)
1876 p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
1877 else
1878 p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
1879 }
1880
1881 /* Extended Listen Timing ATTR */
1882 /* Type: */
1883 p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
1884
1885 /* Length: */
1886 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0004); */
1887 put_unaligned_le16(0x0004, p2pie + p2pielen);
1888 p2pielen += 2;
1889
1890 /* Value: */
1891 /* Availability Period */
1892 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */
1893 put_unaligned_le16(0xFFFF, p2pie + p2pielen);
1894 p2pielen += 2;
1895
1896 /* Availability Interval */
1897 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0xFFFF); */
1898 put_unaligned_le16(0xFFFF, p2pie + p2pielen);
1899 p2pielen += 2;
1900
1901 /* Notice of Absence ATTR */
1902 /* Type: */
1903 /* Length: */
1904 /* Value: */
1905 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
1906 {
1907 /* go_add_noa_attr(pwdinfo); */
1908 }
1909
1910 /* Device Info ATTR */
1911 /* Type: */
1912 p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
1913
1914 /* Length: */
1915 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
1916 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
1917 /* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */
1918 put_unaligned_le16(21 + pwdinfo->device_name_len, p2pie + p2pielen);
1919 p2pielen += 2;
1920
1921 /* Value: */
1922 /* P2P Device Address */
1923 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
1924 p2pielen += ETH_ALEN;
1925
1926 /* Config Method */
1927 /* This field should be big endian. Noted by P2P specification. */
1928 /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm); */
1929 put_unaligned_be16(pwdinfo->supported_wps_cm, p2pie + p2pielen);
1930 p2pielen += 2;
1931
1932 /* Primary Device Type */
1933 /* Category ID */
1934 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */
1935 put_unaligned_be16(WPS_PDT_CID_MULIT_MEDIA, p2pie + p2pielen);
1936 p2pielen += 2;
1937
1938 /* OUI */
1939 /* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */
1940 put_unaligned_be32(WPSOUI, p2pie + p2pielen);
1941 p2pielen += 4;
1942
1943 /* Sub Category ID */
1944 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */
1945 put_unaligned_be16(WPS_PDT_SCID_MEDIA_SERVER, p2pie + p2pielen);
1946 p2pielen += 2;
1947
1948 /* Number of Secondary Device Types */
1949 p2pie[ p2pielen++ ] = 0x00; /* No Secondary Device Type List */
1950
1951 /* Device Name */
1952 /* Type: */
1953 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
1954 put_unaligned_be16(WPS_ATTR_DEVICE_NAME, p2pie + p2pielen);
1955 p2pielen += 2;
1956
1957 /* Length: */
1958 /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */
1959 put_unaligned_be16(pwdinfo->device_name_len, p2pie + p2pielen);
1960 p2pielen += 2;
1961
1962 /* Value: */
1963 memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
1964 p2pielen += pwdinfo->device_name_len;
1965
1966 /* Group Info ATTR */
1967 /* Type: */
1968 /* Length: */
1969 /* Value: */
1970 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
1971 {
1972 p2pielen += go_add_group_info_attr(pwdinfo, p2pie + p2pielen);
1973 }
1974
1975 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
1976
1977 return len;
1978}
1979
1980u32 build_prov_disc_request_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf, u8* pssid, u8 ussidlen, u8* pdev_raddr)
1981{
1982 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
1983 u32 len = 0, p2pielen = 0;
1984
1985 /* P2P OUI */
1986 p2pielen = 0;
1987 p2pie[ p2pielen++ ] = 0x50;
1988 p2pie[ p2pielen++ ] = 0x6F;
1989 p2pie[ p2pielen++ ] = 0x9A;
1990 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
1991
1992 /* Commented by Albert 20110301 */
1993 /* According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */
1994 /* 1. P2P Capability */
1995 /* 2. Device Info */
1996 /* 3. Group ID (When joining an operating P2P Group) */
1997
1998 /* P2P Capability ATTR */
1999 /* Type: */
2000 p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
2001
2002 /* Length: */
2003 /* u16*) (p2pie + p2pielen) = cpu_to_le16(0x0002); */
2004 put_unaligned_le16(0x0002, p2pie + p2pielen);
2005 p2pielen += 2;
2006
2007 /* Value: */
2008 /* Device Capability Bitmap, 1 byte */
2009 p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
2010
2011 /* Group Capability Bitmap, 1 byte */
2012 if (pwdinfo->persistent_supported)
2013 p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
2014 else
2015 p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
2016
2017 /* Device Info ATTR */
2018 /* Type: */
2019 p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
2020
2021 /* Length: */
2022 /* 21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2023 /* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2024 /* u16*) (p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len); */
2025 put_unaligned_le16(21 + pwdinfo->device_name_len, p2pie + p2pielen);
2026 p2pielen += 2;
2027
2028 /* Value: */
2029 /* P2P Device Address */
2030 memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);
2031 p2pielen += ETH_ALEN;
2032
2033 /* Config Method */
2034 /* This field should be big endian. Noted by P2P specification. */
2035 if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)
2036 {
2037 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC); */
2038 put_unaligned_be16(WPS_CONFIG_METHOD_PBC, p2pie + p2pielen);
2039 }
2040 else
2041 {
2042 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY); */
2043 put_unaligned_be16(WPS_CONFIG_METHOD_DISPLAY, p2pie + p2pielen);
2044 }
2045
2046 p2pielen += 2;
2047
2048 /* Primary Device Type */
2049 /* Category ID */
2050 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); */
2051 put_unaligned_be16(WPS_PDT_CID_MULIT_MEDIA, p2pie + p2pielen);
2052 p2pielen += 2;
2053
2054 /* OUI */
2055 /* u32*) (p2pie + p2pielen) = cpu_to_be32(WPSOUI); */
2056 put_unaligned_be32(WPSOUI, p2pie + p2pielen);
2057 p2pielen += 4;
2058
2059 /* Sub Category ID */
2060 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); */
2061 put_unaligned_be16(WPS_PDT_SCID_MEDIA_SERVER, p2pie + p2pielen);
2062 p2pielen += 2;
2063
2064 /* Number of Secondary Device Types */
2065 p2pie[ p2pielen++ ] = 0x00; /* No Secondary Device Type List */
2066
2067 /* Device Name */
2068 /* Type: */
2069 /* u16*) (p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); */
2070 put_unaligned_be16(WPS_ATTR_DEVICE_NAME, p2pie + p2pielen);
2071 p2pielen += 2;
2072
2073 /* Length: */
2074 /* u16*) (p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); */
2075 put_unaligned_be16(pwdinfo->device_name_len, p2pie + p2pielen);
2076 p2pielen += 2;
2077
2078 /* Value: */
2079 memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
2080 p2pielen += pwdinfo->device_name_len;
2081
2082 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT))
2083 {
2084 /* Added by Albert 2011/05/19 */
2085 /* In this case, the pdev_raddr is the device address of the group owner. */
2086
2087 /* P2P Group ID ATTR */
2088 /* Type: */
2089 p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
2090
2091 /* Length: */
2092 /* u16*) (p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + ussidlen); */
2093 put_unaligned_le16(ETH_ALEN + ussidlen, p2pie + p2pielen);
2094 p2pielen += 2;
2095
2096 /* Value: */
2097 memcpy(p2pie + p2pielen, pdev_raddr, ETH_ALEN);
2098 p2pielen += ETH_ALEN;
2099
2100 memcpy(p2pie + p2pielen, pssid, ussidlen);
2101 p2pielen += ussidlen;
2102
2103 }
2104
2105 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2106
2107 return len;
2108}
2109
2110u32 build_assoc_resp_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 status_code)
2111{
2112 u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
2113 u32 len = 0, p2pielen = 0;
2114
2115 /* P2P OUI */
2116 p2pielen = 0;
2117 p2pie[ p2pielen++ ] = 0x50;
2118 p2pie[ p2pielen++ ] = 0x6F;
2119 p2pie[ p2pielen++ ] = 0x9A;
2120 p2pie[ p2pielen++ ] = 0x09; /* WFA P2P v1.0 */
2121
2122 /* According to the P2P Specification, the Association response frame should contain 2 P2P attributes */
2123 /* 1. Status */
2124 /* 2. Extended Listen Timing (optional) */
2125
2126 /* Status ATTR */
2127 p2pielen += rtw_set_p2p_attr_content23a(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status_code);
2128
2129 /* Extended Listen Timing ATTR */
2130 /* Type: */
2131 /* Length: */
2132 /* Value: */
2133
2134 pbuf = rtw_set_ie23a(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
2135
2136 return len;
2137}
2138
2139u32 build_deauth_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf)
2140{
2141 u32 len = 0;
2142
2143 return len;
2144}
2145
2146u32 process_probe_req_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2147{
2148 u8 *p;
2149 u32 ret = false;
2150 u8 *p2pie;
2151 u32 p2pielen = 0;
2152 int ssid_len = 0, rate_cnt = 0;
2153
2154 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&rate_cnt,
2155 len - sizeof(struct ieee80211_hdr_3addr) - _PROBEREQ_IE_OFFSET_);
2156
2157 if (rate_cnt <= 4)
2158 {
2159 int i, g_rate = 0;
2160
2161 for (i = 0; i < rate_cnt; i++)
2162 {
2163 if (((*(p + 2 + i) & 0xff) != 0x02) &&
2164 ((*(p + 2 + i) & 0xff) != 0x04) &&
2165 ((*(p + 2 + i) & 0xff) != 0x0B) &&
2166 ((*(p + 2 + i) & 0xff) != 0x16))
2167 {
2168 g_rate = 1;
2169 }
2170 }
2171
2172 if (g_rate == 0)
2173 {
2174 /* There is no OFDM rate included in SupportedRates IE of this probe request frame */
2175 /* The driver should response this probe request. */
2176 return ret;
2177 }
2178 }
2179 else
2180 {
2181 /* rate_cnt > 4 means the SupportRates IE contains the OFDM rate because the count of CCK rates are 4. */
2182 /* We should proceed the following check for this probe request. */
2183 }
2184
2185 /* Added comments by Albert 20100906 */
2186 /* There are several items we should check here. */
2187 /* 1. This probe request frame must contain the P2P IE. (Done) */
2188 /* 2. This probe request frame must contain the wildcard SSID. (Done) */
2189 /* 3. Wildcard BSSID. (Todo) */
2190 /* 4. Destination Address. (Done in mgt_dispatcher23a function) */
2191 /* 5. Requested Device Type in WSC IE. (Todo) */
2192 /* 6. Device ID attribute in P2P IE. (Todo) */
2193
2194 p = rtw_get_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ssid_len,
2195 len - sizeof(struct ieee80211_hdr_3addr) - _PROBEREQ_IE_OFFSET_);
2196
2197 ssid_len &= 0xff; /* Just last 1 byte is valid for ssid len of the probe request */
2198 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2199 {
2200 if ((p2pie = rtw_get_p2p_ie23a(pframe + sizeof(struct ieee80211_hdr_3addr) + _PROBEREQ_IE_OFFSET_, len - sizeof(struct ieee80211_hdr_3addr) - _PROBEREQ_IE_OFFSET_, NULL, &p2pielen)))
2201 {
2202 if ((p) && !memcmp((void *)(p+2), (void *)pwdinfo->p2p_wildcard_ssid, 7))
2203 {
2204 /* todo: */
2205 /* Check Requested Device Type attributes in WSC IE. */
2206 /* Check Device ID attribute in P2P IE */
2207
2208 ret = true;
2209 }
2210 else if ((p != NULL) && (ssid_len == 0))
2211 {
2212 ret = true;
2213 }
2214 }
2215 else
2216 {
2217 /* non -p2p device */
2218 }
2219
2220 }
2221
2222 return ret;
2223}
2224
2225u32 process_assoc_req_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len, struct sta_info *psta)
2226{
2227 u8 status_code = P2P_STATUS_SUCCESS;
2228 u8 *pbuf, *pattr_content = NULL;
2229 u32 attr_contentlen = 0;
2230 u16 cap_attr = 0;
2231 unsigned short ie_offset;
2232 u8 * ies;
2233 u32 ies_len;
2234 u8 * p2p_ie;
2235 u32 p2p_ielen = 0;
2236 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe;
2237
2238 if (!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2239 return P2P_STATUS_FAIL_REQUEST_UNABLE;
2240
2241 if (ieee80211_is_assoc_req(hdr->frame_control))
2242 ie_offset = _ASOCREQ_IE_OFFSET_;
2243 else /* WIFI_REASSOCREQ */
2244 ie_offset = _REASOCREQ_IE_OFFSET_;
2245
2246 ies = pframe + sizeof(struct ieee80211_hdr_3addr) + ie_offset;
2247 ies_len = len - sizeof(struct ieee80211_hdr_3addr) - ie_offset;
2248
2249 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
2250
2251 if (!p2p_ie)
2252 {
2253 DBG_8723A("[%s] P2P IE not Found!!\n", __func__);
2254 status_code = P2P_STATUS_FAIL_INVALID_PARAM;
2255 }
2256 else
2257 {
2258 DBG_8723A("[%s] P2P IE Found!!\n", __func__);
2259 }
2260
2261 while (p2p_ie)
2262 {
2263 /* Check P2P Capability ATTR */
2264 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*) &attr_contentlen))
2265 {
2266 DBG_8723A("[%s] Got P2P Capability Attr!!\n", __func__);
2267 cap_attr = le16_to_cpu(cap_attr);
2268 psta->dev_cap = cap_attr&0xff;
2269 }
2270
2271 /* Check Extended Listen Timing ATTR */
2272
2273 /* Check P2P Device Info ATTR */
2274 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint*)&attr_contentlen))
2275 {
2276 DBG_8723A("[%s] Got P2P DEVICE INFO Attr!!\n", __func__);
2277 pattr_content = pbuf = kzalloc(attr_contentlen,
2278 GFP_ATOMIC);
2279 if (pattr_content) {
2280 u8 num_of_secdev_type;
2281 u16 dev_name_len;
2282
2283 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, pattr_content, (uint*)&attr_contentlen);
2284
2285 memcpy(psta->dev_addr, pattr_content, ETH_ALEN);/* P2P Device Address */
2286
2287 pattr_content += ETH_ALEN;
2288
2289 memcpy(&psta->config_methods, pattr_content, 2);/* Config Methods */
2290 psta->config_methods = be16_to_cpu(psta->config_methods);
2291
2292 pattr_content += 2;
2293
2294 memcpy(psta->primary_dev_type, pattr_content, 8);
2295
2296 pattr_content += 8;
2297
2298 num_of_secdev_type = *pattr_content;
2299 pattr_content += 1;
2300
2301 if (num_of_secdev_type == 0)
2302 {
2303 psta->num_of_secdev_type = 0;
2304 }
2305 else
2306 {
2307 u32 len;
2308
2309 psta->num_of_secdev_type = num_of_secdev_type;
2310
2311 len = (sizeof(psta->secdev_types_list)<(num_of_secdev_type*8)) ? (sizeof(psta->secdev_types_list)) : (num_of_secdev_type*8);
2312
2313 memcpy(psta->secdev_types_list, pattr_content, len);
2314
2315 pattr_content += (num_of_secdev_type*8);
2316 }
2317
2318 /* dev_name_len = attr_contentlen - ETH_ALEN - 2 - 8 - 1 - (num_of_secdev_type*8); */
2319 psta->dev_name_len = 0;
2320 if (WPS_ATTR_DEVICE_NAME == be16_to_cpu(*(u16*)pattr_content))
2321 {
2322 dev_name_len = be16_to_cpu(*(u16*)(pattr_content+2));
2323
2324 psta->dev_name_len = (sizeof(psta->dev_name)<dev_name_len) ? sizeof(psta->dev_name):dev_name_len;
2325
2326 memcpy(psta->dev_name, pattr_content+4, psta->dev_name_len);
2327 }
2328
2329 kfree(pbuf);
2330
2331 }
2332
2333 }
2334
2335 /* Get the next P2P IE */
2336 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
2337
2338 }
2339
2340 return status_code;
2341}
2342
2343u32 process_p2p_devdisc_req23a(struct wifidirect_info *pwdinfo, u8 *pframe,
2344 uint len)
2345{
2346 u8 *frame_body;
2347 u8 status, dialogToken;
2348 struct sta_info *psta = NULL;
2349 struct rtw_adapter *padapter = pwdinfo->padapter;
2350 struct sta_priv *pstapriv = &padapter->stapriv;
2351 u8 *p2p_ie;
2352 u32 p2p_ielen = 0;
2353 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) pframe;
2354
2355 frame_body = (unsigned char *)
2356 (pframe + sizeof(struct ieee80211_hdr_3addr));
2357
2358 dialogToken = frame_body[7];
2359 status = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
2360
2361 if ((p2p_ie = rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
2362 len - _PUBLIC_ACTION_IE_OFFSET_, NULL,
2363 &p2p_ielen))) {
2364 u8 groupid[38] = { 0x00 };
2365 u8 dev_addr[ETH_ALEN] = { 0x00 };
2366 u32 attr_contentlen = 0;
2367
2368 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen,
2369 P2P_ATTR_GROUP_ID, groupid,
2370 &attr_contentlen)) {
2371 if (!memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) &&
2372 !memcmp(pwdinfo->p2p_group_ssid, groupid + ETH_ALEN,
2373 pwdinfo->p2p_group_ssid_len)) {
2374 attr_contentlen = 0;
2375
2376 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen,
2377 P2P_ATTR_DEVICE_ID,
2378 dev_addr,
2379 &attr_contentlen)) {
2380 struct list_head *phead, *plist, *ptmp;
2381
2382 spin_lock_bh(&pstapriv->asoc_list_lock);
2383 phead = &pstapriv->asoc_list;
2384
2385 list_for_each_safe(plist, ptmp, phead) {
2386 psta = container_of(plist, struct sta_info, asoc_list);
2387
2388 if (psta->is_p2p_device && (psta->dev_cap&P2P_DEVCAP_CLIENT_DISCOVERABILITY) &&
2389 !memcmp(psta->dev_addr, dev_addr, ETH_ALEN))
2390 {
2391 /* spin_unlock_bh(&pstapriv->asoc_list_lock); */
2392 /* issue GO Discoverability Request */
2393 issue_group_disc_req(pwdinfo, psta->hwaddr);
2394 /* spin_lock_bh(&pstapriv->asoc_list_lock); */
2395 status = P2P_STATUS_SUCCESS;
2396 break;
2397 } else {
2398 status = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
2399 }
2400 }
2401 spin_unlock_bh(&pstapriv->asoc_list_lock);
2402 } else {
2403 status = P2P_STATUS_FAIL_INVALID_PARAM;
2404 }
2405 } else {
2406 status = P2P_STATUS_FAIL_INVALID_PARAM;
2407 }
2408 }
2409 }
2410
2411 /* issue Device Discoverability Response */
2412 issue_p2p_devdisc_resp(pwdinfo, hdr->addr2, status, dialogToken);
2413
2414 return (status == P2P_STATUS_SUCCESS) ? true:false;
2415}
2416
2417u32 process_p2p_devdisc_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2418{
2419 return true;
2420}
2421
2422u8 process_p2p_provdisc_req23a(struct wifidirect_info *pwdinfo,
2423 u8 *pframe, uint len)
2424{
2425 u8 *frame_body;
2426 u8 *wpsie;
2427 u8 *ptr = NULL;
2428 uint wps_ielen = 0, attr_contentlen = 0;
2429 u16 uconfig_method = 0;
2430 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe;
2431
2432 frame_body = (pframe + sizeof(struct ieee80211_hdr_3addr));
2433
2434 wpsie = rtw_get_wps_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
2435 len - _PUBLIC_ACTION_IE_OFFSET_, NULL,
2436 &wps_ielen);
2437 if (!wpsie)
2438 goto out;
2439
2440 if (!rtw_get_wps_attr_content23a(wpsie, wps_ielen, WPS_ATTR_CONF_METHOD,
2441 (u8 *)&uconfig_method, &attr_contentlen))
2442 goto out;
2443
2444 uconfig_method = be16_to_cpu(uconfig_method);
2445 ptr = pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req;
2446
2447 switch (uconfig_method)
2448 {
2449 case WPS_CM_DISPLYA:
2450 memcpy(ptr, "dis", 3);
2451 break;
2452
2453 case WPS_CM_LABEL:
2454 memcpy(ptr, "lab", 3);
2455 break;
2456
2457 case WPS_CM_PUSH_BUTTON:
2458 memcpy(ptr, "pbc", 3);
2459 break;
2460
2461 case WPS_CM_KEYPAD:
2462 memcpy(ptr, "pad", 3);
2463 break;
2464 }
2465 issue_p2p_provision_resp(pwdinfo, hdr->addr2, frame_body,
2466 uconfig_method);
2467
2468out:
2469 DBG_8723A("[%s] config method = %s\n", __func__, ptr);
2470
2471 return true;
2472}
2473
2474u8 process_p2p_provdisc_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe)
2475{
2476
2477 return true;
2478}
2479
2480static u8 rtw_p2p_get_peer_ch_list(struct wifidirect_info *pwdinfo, u8 *ch_content, u8 ch_cnt, u8 *peer_ch_list)
2481{
2482 u8 i = 0, j = 0;
2483 u8 temp = 0;
2484 u8 ch_no = 0;
2485 ch_content += 3;
2486 ch_cnt -= 3;
2487
2488 while(ch_cnt > 0)
2489 {
2490 ch_content += 1;
2491 ch_cnt -= 1;
2492 temp = *ch_content;
2493 for (i = 0 ; i < temp ; i++, j++)
2494 {
2495 peer_ch_list[j] = *(ch_content + 1 + i);
2496 }
2497 ch_content += (temp + 1);
2498 ch_cnt -= (temp + 1);
2499 ch_no += temp ;
2500 }
2501
2502 return ch_no;
2503}
2504
2505static u8 rtw_p2p_ch_inclusion(struct mlme_ext_priv *pmlmeext, u8 *peer_ch_list, u8 peer_ch_num, u8 *ch_list_inclusioned)
2506{
2507 int i = 0, j = 0, temp = 0;
2508 u8 ch_no = 0;
2509
2510 for (i = 0; i < peer_ch_num; i++)
2511 {
2512 for (j = temp; j < pmlmeext->max_chan_nums; j++)
2513 {
2514 if (*(peer_ch_list + i) == pmlmeext->channel_set[ j ].ChannelNum)
2515 {
2516 ch_list_inclusioned[ ch_no++ ] = *(peer_ch_list + i);
2517 temp = j;
2518 break;
2519 }
2520 }
2521 }
2522
2523 return ch_no;
2524}
2525
2526u8 process_p2p_group_negotation_req23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2527{
2528 struct rtw_adapter *padapter = pwdinfo->padapter;
2529 u8 result = P2P_STATUS_SUCCESS;
2530 u32 p2p_ielen = 0, wps_ielen = 0;
2531 u8 * ies;
2532 u32 ies_len;
2533 u8 *p2p_ie;
2534 u8 *wpsie;
2535 u16 wps_devicepassword_id = 0x0000;
2536 uint wps_devicepassword_id_len = 0;
2537#ifdef CONFIG_8723AU_P2P
2538 u8 wfd_ie[ 128 ] = { 0x00 };
2539 u32 wfd_ielen = 0;
2540#endif /* CONFIG_8723AU_P2P */
2541
2542 if ((wpsie = rtw_get_wps_ie23a(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen)))
2543 {
2544 /* Commented by Kurt 20120113 */
2545 /* If some device wants to do p2p handshake without sending prov_disc_req */
2546 /* We have to get peer_req_cm from here. */
2547 if (!memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3))
2548 {
2549 rtw_get_wps_attr_content23a(wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8*) &wps_devicepassword_id, &wps_devicepassword_id_len);
2550 wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
2551
2552 if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
2553 {
2554 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2555 }
2556 else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
2557 {
2558 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2559 }
2560 else
2561 {
2562 memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2563 }
2564 }
2565 }
2566 else
2567 {
2568 DBG_8723A("[%s] WPS IE not Found!!\n", __func__);
2569 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2570 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2571 return result;
2572 }
2573
2574 if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO)
2575 {
2576 result = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
2577 rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INFOR_NOREADY);
2578 return result;
2579 }
2580
2581 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2582 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2583
2584 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
2585
2586 if (!p2p_ie)
2587 {
2588 DBG_8723A("[%s] P2P IE not Found!!\n", __func__);
2589 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2590 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2591 }
2592
2593 while (p2p_ie)
2594 {
2595 u8 attr_content = 0x00;
2596 u32 attr_contentlen = 0;
2597 u8 ch_content[50] = { 0x00 };
2598 uint ch_cnt = 0;
2599 u8 peer_ch_list[50] = { 0x00 };
2600 u8 peer_ch_num = 0;
2601 u8 ch_list_inclusioned[50] = { 0x00 };
2602 u8 ch_num_inclusioned = 0;
2603 u16 cap_attr;
2604
2605 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
2606
2607 /* Check P2P Capability ATTR */
2608 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*)&attr_contentlen))
2609 cap_attr = le16_to_cpu(cap_attr);
2610
2611 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, &attr_content, &attr_contentlen))
2612 {
2613 DBG_8723A("[%s] GO Intent = %d, tie = %d\n", __func__, attr_content >> 1, attr_content & 0x01);
2614 pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */
2615
2616 if (pwdinfo->intent == (pwdinfo->peer_intent >> 1))
2617 {
2618 /* Try to match the tie breaker value */
2619 if (pwdinfo->intent == P2P_MAX_INTENT)
2620 {
2621 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2622 result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
2623 }
2624 else
2625 {
2626 if (attr_content & 0x01)
2627 {
2628 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2629 }
2630 else
2631 {
2632 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2633 }
2634 }
2635 }
2636 else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1))
2637 {
2638 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2639 }
2640 else
2641 {
2642 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2643 }
2644
2645 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2646 {
2647 /* Store the group id information. */
2648 memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
2649 memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2650 }
2651 }
2652
2653 attr_contentlen = 0;
2654 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen))
2655 {
2656 if (attr_contentlen != ETH_ALEN)
2657 {
2658 memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
2659 }
2660 }
2661
2662 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, ch_content, &ch_cnt))
2663 {
2664 peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, ch_content, ch_cnt, peer_ch_list);
2665 ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
2666
2667 if (ch_num_inclusioned == 0)
2668 {
2669 DBG_8723A("[%s] No common channel in channel list!\n", __func__);
2670 result = P2P_STATUS_FAIL_NO_COMMON_CH;
2671 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2672 break;
2673 }
2674
2675 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2676 {
2677 if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
2678 ch_list_inclusioned, ch_num_inclusioned))
2679 {
2680 {
2681 u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
2682 attr_contentlen = 0;
2683
2684 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2685 {
2686 peer_operating_ch = operatingch_info[4];
2687 }
2688
2689 if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
2690 ch_list_inclusioned, ch_num_inclusioned))
2691 {
2692 /**
2693 * Change our operating channel as peer's for compatibility.
2694 */
2695 pwdinfo->operating_channel = peer_operating_ch;
2696 DBG_8723A("[%s] Change op ch to %02x as peer's\n", __func__, pwdinfo->operating_channel);
2697 }
2698 else
2699 {
2700 /* Take first channel of ch_list_inclusioned as operating channel */
2701 pwdinfo->operating_channel = ch_list_inclusioned[0];
2702 DBG_8723A("[%s] Change op ch to %02x\n", __func__, pwdinfo->operating_channel);
2703 }
2704 }
2705
2706 }
2707 }
2708 }
2709
2710 /* Get the next P2P IE */
2711 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
2712 }
2713
2714#ifdef CONFIG_8723AU_P2P
2715 /* Added by Albert 20110823 */
2716 /* Try to get the TCP port information when receiving the negotiation request. */
2717 if (rtw_get_wfd_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wfd_ie, &wfd_ielen))
2718 {
2719 u8 attr_content[ 10 ] = { 0x00 };
2720 u32 attr_contentlen = 0;
2721
2722 DBG_8723A("[%s] WFD IE Found!!\n", __func__);
2723 rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
2724 if (attr_contentlen)
2725 {
2726 pwdinfo->wfd_info->peer_rtsp_ctrlport = get_unaligned_be16(attr_content + 2);
2727 DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
2728 }
2729 }
2730#endif /* CONFIG_8723AU_P2P */
2731
2732 return result;
2733}
2734
2735u8 process_p2p_group_negotation_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2736{
2737 struct rtw_adapter *padapter = pwdinfo->padapter;
2738 u8 result = P2P_STATUS_SUCCESS;
2739 u32 p2p_ielen, wps_ielen;
2740 u8 * ies;
2741 u32 ies_len;
2742 u8 * p2p_ie;
2743#ifdef CONFIG_8723AU_P2P
2744 u8 wfd_ie[ 128 ] = { 0x00 };
2745 u32 wfd_ielen = 0;
2746#endif /* CONFIG_8723AU_P2P */
2747
2748 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2749 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2750
2751 /* Be able to know which one is the P2P GO and which one is P2P client. */
2752
2753 if (rtw_get_wps_ie23a(ies, ies_len, NULL, &wps_ielen))
2754 {
2755
2756 }
2757 else
2758 {
2759 DBG_8723A("[%s] WPS IE not Found!!\n", __func__);
2760 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2761 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2762 }
2763
2764 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
2765 if (!p2p_ie)
2766 {
2767 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2768 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2769 result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
2770 }
2771 else
2772 {
2773
2774 u8 attr_content = 0x00;
2775 u32 attr_contentlen = 0;
2776 u8 operatingch_info[5] = { 0x00 };
2777 u8 groupid[ 38 ];
2778 u16 cap_attr;
2779 u8 peer_ch_list[50] = { 0x00 };
2780 u8 peer_ch_num = 0;
2781 u8 ch_list_inclusioned[50] = { 0x00 };
2782 u8 ch_num_inclusioned = 0;
2783
2784 while (p2p_ie) /* Found the P2P IE. */
2785 {
2786
2787 /* Check P2P Capability ATTR */
2788 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*)&attr_contentlen))
2789 cap_attr = le16_to_cpu(cap_attr);
2790
2791 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
2792 if (attr_contentlen == 1)
2793 {
2794 DBG_8723A("[%s] Status = %d\n", __func__, attr_content);
2795 if (attr_content == P2P_STATUS_SUCCESS)
2796 {
2797 /* Do nothing. */
2798 }
2799 else
2800 {
2801 if (P2P_STATUS_FAIL_INFO_UNAVAILABLE == attr_content) {
2802 rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INFOR_NOREADY);
2803 } else {
2804 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2805 }
2806 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2807 result = attr_content;
2808 break;
2809 }
2810 }
2811
2812 /* Try to get the peer's interface address */
2813 attr_contentlen = 0;
2814 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen))
2815 {
2816 if (attr_contentlen != ETH_ALEN)
2817 {
2818 memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
2819 }
2820 }
2821
2822 /* Try to get the peer's intent and tie breaker value. */
2823 attr_content = 0x00;
2824 attr_contentlen = 0;
2825 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, &attr_content, &attr_contentlen))
2826 {
2827 DBG_8723A("[%s] GO Intent = %d, tie = %d\n", __func__, attr_content >> 1, attr_content & 0x01);
2828 pwdinfo->peer_intent = attr_content; /* include both intent and tie breaker values. */
2829
2830 if (pwdinfo->intent == (pwdinfo->peer_intent >> 1))
2831 {
2832 /* Try to match the tie breaker value */
2833 if (pwdinfo->intent == P2P_MAX_INTENT)
2834 {
2835 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2836 result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
2837 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2838 }
2839 else
2840 {
2841 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2842 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2843 if (attr_content & 0x01)
2844 {
2845 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2846 }
2847 else
2848 {
2849 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2850 }
2851 }
2852 }
2853 else if (pwdinfo->intent > (pwdinfo->peer_intent >> 1))
2854 {
2855 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2856 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2857 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2858 }
2859 else
2860 {
2861 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
2862 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
2863 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
2864 }
2865
2866 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2867 {
2868 /* Store the group id information. */
2869 memcpy(pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN);
2870 memcpy(pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2871
2872 }
2873 }
2874
2875 /* Try to get the operation channel information */
2876
2877 attr_contentlen = 0;
2878 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2879 {
2880 DBG_8723A("[%s] Peer's operating channel = %d\n", __func__, operatingch_info[4]);
2881 pwdinfo->peer_operating_ch = operatingch_info[4];
2882 }
2883
2884 /* Try to get the channel list information */
2885 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, pwdinfo->channel_list_attr, &pwdinfo->channel_list_attr_len))
2886 {
2887 DBG_8723A("[%s] channel list attribute found, len = %d\n", __func__, pwdinfo->channel_list_attr_len);
2888
2889 peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len, peer_ch_list);
2890 ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
2891
2892 if (ch_num_inclusioned == 0)
2893 {
2894 DBG_8723A("[%s] No common channel in channel list!\n", __func__);
2895 result = P2P_STATUS_FAIL_NO_COMMON_CH;
2896 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
2897 break;
2898 }
2899
2900 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
2901 {
2902 if (!rtw_p2p_is_channel_list_ok(pwdinfo->operating_channel,
2903 ch_list_inclusioned, ch_num_inclusioned))
2904 {
2905 {
2906 u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
2907 attr_contentlen = 0;
2908
2909 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
2910 {
2911 peer_operating_ch = operatingch_info[4];
2912 }
2913
2914 if (rtw_p2p_is_channel_list_ok(peer_operating_ch,
2915 ch_list_inclusioned, ch_num_inclusioned))
2916 {
2917 /**
2918 * Change our operating channel as peer's for compatibility.
2919 */
2920 pwdinfo->operating_channel = peer_operating_ch;
2921 DBG_8723A("[%s] Change op ch to %02x as peer's\n", __func__, pwdinfo->operating_channel);
2922 }
2923 else
2924 {
2925 /* Take first channel of ch_list_inclusioned as operating channel */
2926 pwdinfo->operating_channel = ch_list_inclusioned[0];
2927 DBG_8723A("[%s] Change op ch to %02x\n", __func__, pwdinfo->operating_channel);
2928 }
2929 }
2930
2931 }
2932 }
2933
2934 }
2935 else
2936 {
2937 DBG_8723A("[%s] channel list attribute not found!\n", __func__);
2938 }
2939
2940 /* Try to get the group id information if peer is GO */
2941 attr_contentlen = 0;
2942 memset(groupid, 0x00, 38);
2943 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen))
2944 {
2945 memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
2946 memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
2947 }
2948
2949 /* Get the next P2P IE */
2950 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
2951 }
2952
2953 }
2954
2955#ifdef CONFIG_8723AU_P2P
2956 /* Added by Albert 20111122 */
2957 /* Try to get the TCP port information when receiving the negotiation response. */
2958 if (rtw_get_wfd_ie(pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wfd_ie, &wfd_ielen))
2959 {
2960 u8 attr_content[ 10 ] = { 0x00 };
2961 u32 attr_contentlen = 0;
2962
2963 DBG_8723A("[%s] WFD IE Found!!\n", __func__);
2964 rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
2965 if (attr_contentlen)
2966 {
2967 pwdinfo->wfd_info->peer_rtsp_ctrlport = get_unaligned_be16(attr_content + 2);
2968 DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
2969 }
2970 }
2971#endif /* CONFIG_8723AU_P2P */
2972
2973 return result;
2974}
2975
2976u8 process_p2p_group_negotation_confirm23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
2977{
2978 u8 * ies;
2979 u32 ies_len;
2980 u8 * p2p_ie;
2981 u32 p2p_ielen = 0;
2982 u8 result = P2P_STATUS_SUCCESS;
2983 ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
2984 ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
2985
2986 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
2987 while (p2p_ie) /* Found the P2P IE. */
2988 {
2989 u8 attr_content = 0x00, operatingch_info[5] = { 0x00 };
2990 u8 groupid[ 38 ] = { 0x00 };
2991 u32 attr_contentlen = 0;
2992
2993 pwdinfo->negotiation_dialog_token = 1;
2994 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
2995 if (attr_contentlen == 1)
2996 {
2997 DBG_8723A("[%s] Status = %d\n", __func__, attr_content);
2998 result = attr_content;
2999
3000 if (attr_content == P2P_STATUS_SUCCESS)
3001 {
3002 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
3003
3004 /* Commented by Albert 20100911 */
3005 /* Todo: Need to handle the case which both Intents are the same. */
3006 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3007 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
3008 if ((pwdinfo->intent) > (pwdinfo->peer_intent >> 1))
3009 {
3010 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3011 }
3012 else if ((pwdinfo->intent) < (pwdinfo->peer_intent >> 1))
3013 {
3014 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3015 }
3016 else
3017 {
3018 /* Have to compare the Tie Breaker */
3019 if (pwdinfo->peer_intent & 0x01)
3020 {
3021 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3022 }
3023 else
3024 {
3025 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3026 }
3027 }
3028 }
3029 else
3030 {
3031 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3032 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
3033 break;
3034 }
3035 }
3036
3037 /* Try to get the group id information */
3038 attr_contentlen = 0;
3039 memset(groupid, 0x00, 38);
3040 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen))
3041 {
3042 DBG_8723A("[%s] Ssid = %s, ssidlen = %zu\n", __func__, &groupid[ETH_ALEN], strlen(&groupid[ETH_ALEN]));
3043 memcpy(pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN);
3044 memcpy(pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN);
3045 }
3046
3047 attr_contentlen = 0;
3048 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
3049 {
3050 DBG_8723A("[%s] Peer's operating channel = %d\n", __func__, operatingch_info[4]);
3051 pwdinfo->peer_operating_ch = operatingch_info[4];
3052 }
3053
3054 /* Get the next P2P IE */
3055 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
3056
3057 }
3058
3059 return result;
3060}
3061
3062u8 process_p2p_presence_req23a(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
3063{
3064 u8 *frame_body;
3065 u8 dialogToken = 0;
3066 u8 status = P2P_STATUS_SUCCESS;
3067 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) pframe;
3068
3069 frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
3070
3071 dialogToken = frame_body[6];
3072
3073 /* todo: check NoA attribute */
3074
3075 issue_p2p_presence_resp(pwdinfo, hdr->addr2, status, dialogToken);
3076
3077 return true;
3078}
3079
3080static void find_phase_handler(struct rtw_adapter *padapter)
3081{
3082 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3083 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3084 struct cfg80211_ssid ssid;
3085 u8 _status = 0;
3086
3087
3088
3089 memset((unsigned char*)&ssid, 0, sizeof(struct cfg80211_ssid));
3090 memcpy(ssid.ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN);
3091 ssid.ssid_len = P2P_WILDCARD_SSID_LEN;
3092
3093 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
3094
3095 spin_lock_bh(&pmlmepriv->lock);
3096 _status = rtw_sitesurvey_cmd23a(padapter, &ssid, 1, NULL, 0);
3097 spin_unlock_bh(&pmlmepriv->lock);
3098
3099
3100}
3101
3102void p2p_concurrent_handler(struct rtw_adapter* padapter);
3103
3104static void restore_p2p_state_handler(struct rtw_adapter *padapter)
3105{
3106 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3107
3108 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
3109 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3110
3111 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3112
3113 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
3114 /* In the P2P client mode, the driver should not switch back to its listen channel */
3115 /* because this P2P client should stay at the operating channel of P2P GO. */
3116 set_channel_bwmode23a(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3117 }
3118}
3119
3120static void pre_tx_invitereq_handler(struct rtw_adapter *padapter)
3121{
3122 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3123 u8 val8 = 1;
3124
3125 set_channel_bwmode23a(padapter, pwdinfo->invitereq_info.peer_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3126 padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3127 issue23a_probereq_p2p(padapter, NULL);
3128 mod_timer(&pwdinfo->pre_tx_scan_timer,
3129 jiffies + msecs_to_jiffies(P2P_TX_PRESCAN_TIMEOUT));
3130
3131
3132}
3133
3134static void pre_tx_provdisc_handler(struct rtw_adapter *padapter)
3135{
3136 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3137 u8 val8 = 1;
3138
3139
3140 set_channel_bwmode23a(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3141 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3142 issue23a_probereq_p2p(padapter, NULL);
3143 mod_timer(&pwdinfo->pre_tx_scan_timer,
3144 jiffies + msecs_to_jiffies(P2P_TX_PRESCAN_TIMEOUT));
3145
3146
3147}
3148
3149static void pre_tx_negoreq_handler(struct rtw_adapter *padapter)
3150{
3151 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3152 u8 val8 = 1;
3153
3154
3155 set_channel_bwmode23a(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
3156 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3157 issue23a_probereq_p2p(padapter, NULL);
3158 mod_timer(&pwdinfo->pre_tx_scan_timer,
3159 jiffies + msecs_to_jiffies(P2P_TX_PRESCAN_TIMEOUT));
3160
3161
3162}
3163
3164static void ro_ch_handler(struct rtw_adapter *padapter)
3165{
3166 struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
3167 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3168 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3169
3170 if (pcfg80211_wdinfo->restore_channel != pmlmeext->cur_channel) {
3171 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
3172 pmlmeext->cur_channel = pcfg80211_wdinfo->restore_channel;
3173
3174 set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
3175 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
3176 HT_CHANNEL_WIDTH_20);
3177 }
3178
3179 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3180
3181 pcfg80211_wdinfo->is_ro_ch = false;
3182
3183 DBG_8723A("cfg80211_remain_on_channel_expired\n");
3184
3185 rtw_cfg80211_remain_on_channel_expired(padapter,
3186 pcfg80211_wdinfo->remain_on_ch_cookie,
3187 &pcfg80211_wdinfo->remain_on_ch_channel,
3188 pcfg80211_wdinfo->remain_on_ch_type, GFP_KERNEL);
3189}
3190
3191static void ro_ch_timer_process (unsigned long data)
3192{
3193 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3194
3195 p2p_protocol_wk_cmd23a(adapter, P2P_RO_CH_WK);
3196}
3197
3198#ifdef CONFIG_8723AU_P2P
3199void rtw_append_wfd_ie(struct rtw_adapter *padapter, u8 *buf, u32* len)
3200{
3201 unsigned char *frame_body;
3202 u8 category, action, OUI_Subtype, dialogToken = 0;
3203 u32 wfdielen = 0;
3204
3205 frame_body = (unsigned char *)(buf + sizeof(struct ieee80211_hdr_3addr));
3206 category = frame_body[0];
3207
3208 if (category == WLAN_CATEGORY_PUBLIC) {
3209 action = frame_body[1];
3210 if (action == ACT_PUBLIC_VENDOR &&
3211 !memcmp(frame_body+2, P2P_OUI23A, 4)) {
3212 OUI_Subtype = frame_body[6];
3213 dialogToken = frame_body[7];
3214 switch (OUI_Subtype)/* OUI Subtype */ {
3215 case P2P_GO_NEGO_REQ:
3216 wfdielen = build_nego_req_wfd_ie(&padapter->wdinfo, buf + (*len));
3217 (*len) += wfdielen;
3218 break;
3219 case P2P_GO_NEGO_RESP:
3220 wfdielen = build_nego_resp_wfd_ie(&padapter->wdinfo, buf + (*len));
3221 (*len) += wfdielen;
3222 break;
3223 case P2P_GO_NEGO_CONF:
3224 wfdielen = build_nego_confirm_wfd_ie(&padapter->wdinfo, buf + (*len));
3225 (*len) += wfdielen;
3226 break;
3227 case P2P_INVIT_REQ:
3228 wfdielen = build_invitation_req_wfd_ie(&padapter->wdinfo, buf + (*len));
3229 (*len) += wfdielen;
3230 break;
3231 case P2P_INVIT_RESP:
3232 wfdielen = build_invitation_resp_wfd_ie(&padapter->wdinfo, buf + (*len));
3233 (*len) += wfdielen;
3234 break;
3235 case P2P_DEVDISC_REQ:
3236 break;
3237 case P2P_DEVDISC_RESP:
3238 break;
3239 case P2P_PROVISION_DISC_REQ:
3240 wfdielen = build_provdisc_req_wfd_ie(&padapter->wdinfo, buf + (*len));
3241 (*len) += wfdielen;
3242 break;
3243 case P2P_PROVISION_DISC_RESP:
3244 wfdielen = build_provdisc_resp_wfd_ie(&padapter->wdinfo, buf + (*len));
3245 (*len) += wfdielen;
3246 break;
3247 default:
3248 break;
3249 }
3250 }
3251 } else if (category == WLAN_CATEGORY_VENDOR_SPECIFIC) {
3252 OUI_Subtype = frame_body[5];
3253 dialogToken = frame_body[6];
3254 } else {
3255 DBG_8723A("%s, action frame category =%d\n", __func__, category);
3256 }
3257}
3258#endif
3259
3260int rtw_p2p_check_frames(struct rtw_adapter *padapter, const u8 *buf, u32 len, u8 tx)
3261{
3262 int is_p2p_frame = (-1);
3263 unsigned char *frame_body;
3264 u8 category, action, OUI_Subtype, dialogToken = 0;
3265 u8 *p2p_ie = NULL;
3266 uint p2p_ielen = 0;
3267 struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
3268
3269 frame_body = (unsigned char *)(buf + sizeof(struct ieee80211_hdr_3addr));
3270 category = frame_body[0];
3271 /* just for check */
3272 if (category == WLAN_CATEGORY_PUBLIC)
3273 {
3274 action = frame_body[1];
3275 if (action == ACT_PUBLIC_VENDOR &&
3276 !memcmp(frame_body+2, P2P_OUI23A, 4)) {
3277 OUI_Subtype = frame_body[6];
3278 dialogToken = frame_body[7];
3279 is_p2p_frame = OUI_Subtype;
3280 p2p_ie = rtw_get_p2p_ie23a(
3281 (u8 *)buf+sizeof(struct ieee80211_hdr_3addr)+_PUBLIC_ACTION_IE_OFFSET_,
3282 len-sizeof(struct ieee80211_hdr_3addr)-_PUBLIC_ACTION_IE_OFFSET_,
3283 NULL, &p2p_ielen);
3284
3285 switch (OUI_Subtype) {/* OUI Subtype */
3286 u8 *cont;
3287 uint cont_len;
3288 case P2P_GO_NEGO_REQ:
3289 DBG_8723A("RTW_%s:P2P_GO_NEGO_REQ, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
3290 break;
3291 case P2P_GO_NEGO_RESP:
3292 cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3293 DBG_8723A("RTW_%s:P2P_GO_NEGO_RESP, dialogToken =%d, status:%d\n", (tx == true)?"Tx":"Rx", dialogToken, cont?*cont:-1);
3294
3295 if (!tx)
3296 pwdev_priv->provdisc_req_issued = false;
3297 break;
3298 case P2P_GO_NEGO_CONF:
3299 cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3300 DBG_8723A("RTW_%s:P2P_GO_NEGO_CONF, dialogToken =%d, status:%d\n",
3301 (tx == true)?"Tx":"Rx", dialogToken, cont?*cont:-1);
3302 break;
3303 case P2P_INVIT_REQ:
3304 {
3305 struct rtw_wdev_invit_info* invit_info = &pwdev_priv->invit_info;
3306 int flags = -1;
3307 int op_ch = 0;
3308
3309 if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, NULL, &cont_len)))
3310 flags = *cont;
3311 if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
3312 op_ch = *(cont+4);
3313
3314 if (invit_info->token != dialogToken)
3315 rtw_wdev_invit_info_init(invit_info);
3316
3317 invit_info->token = dialogToken;
3318 invit_info->flags = (flags ==-1) ? 0x0 : flags;
3319 invit_info->req_op_ch = op_ch;
3320
3321 DBG_8723A("RTW_%s:P2P_INVIT_REQ, dialogToken =%d, flags:0x%02x, op_ch:%d\n",
3322 (tx) ? "Tx" : "Rx", dialogToken, flags, op_ch);
3323 break;
3324 }
3325 case P2P_INVIT_RESP:
3326 {
3327 struct rtw_wdev_invit_info* invit_info = &pwdev_priv->invit_info;
3328 int status = -1;
3329 int op_ch = 0;
3330
3331 if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len)))
3332 status = *cont;
3333 if ((cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
3334 op_ch = *(cont+4);
3335
3336 if (invit_info->token != dialogToken) {
3337 rtw_wdev_invit_info_init(invit_info);
3338 } else {
3339 invit_info->token = 0;
3340 invit_info->status = (status ==-1) ? 0xff : status;
3341 invit_info->rsp_op_ch = op_ch;
3342 }
3343
3344 DBG_8723A("RTW_%s:P2P_INVIT_RESP, dialogToken =%d, status:%d, op_ch:%d\n",
3345 (tx == true)?"Tx":"Rx", dialogToken, status, op_ch);
3346 break;
3347 }
3348 case P2P_DEVDISC_REQ:
3349 DBG_8723A("RTW_%s:P2P_DEVDISC_REQ, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
3350 break;
3351 case P2P_DEVDISC_RESP:
3352 cont = rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
3353 DBG_8723A("RTW_%s:P2P_DEVDISC_RESP, dialogToken =%d, status:%d\n", (tx == true)?"Tx":"Rx", dialogToken, cont?*cont:-1);
3354 break;
3355 case P2P_PROVISION_DISC_REQ:
3356 {
3357 size_t frame_body_len = len - sizeof(struct ieee80211_hdr_3addr);
3358 u8 *p2p_ie;
3359 uint p2p_ielen = 0;
3360 uint contentlen = 0;
3361
3362 DBG_8723A("RTW_%s:P2P_PROVISION_DISC_REQ, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
3363
3364 pwdev_priv->provdisc_req_issued = false;
3365
3366 p2p_ie = rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
3367 frame_body_len - _PUBLIC_ACTION_IE_OFFSET_,
3368 NULL, &p2p_ielen);
3369 if (p2p_ie) {
3370 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, NULL, &contentlen))
3371 pwdev_priv->provdisc_req_issued = false;/* case: p2p_client join p2p GO */
3372 else
3373 pwdev_priv->provdisc_req_issued = true;/* case: p2p_devices connection before Nego req. */
3374 }
3375 }
3376 break;
3377 case P2P_PROVISION_DISC_RESP:
3378 DBG_8723A("RTW_%s:P2P_PROVISION_DISC_RESP, dialogToken =%d\n", (tx == true)?"Tx":"Rx", dialogToken);
3379 break;
3380 default:
3381 DBG_8723A("RTW_%s:OUI_Subtype =%d, dialogToken =%d\n", (tx == true)?"Tx":"Rx", OUI_Subtype, dialogToken);
3382 break;
3383 }
3384
3385 }
3386
3387 }
3388 else if (category == WLAN_CATEGORY_VENDOR_SPECIFIC)
3389 {
3390 OUI_Subtype = frame_body[5];
3391 dialogToken = frame_body[6];
3392
3393 is_p2p_frame = OUI_Subtype;
3394
3395 switch (OUI_Subtype) {
3396 case P2P_NOTICE_OF_ABSENCE:
3397 DBG_8723A("RTW_%s:P2P_NOTICE_OF_ABSENCE, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
3398 break;
3399 case P2P_PRESENCE_REQUEST:
3400 DBG_8723A("RTW_%s:P2P_PRESENCE_REQUEST, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
3401 break;
3402 case P2P_PRESENCE_RESPONSE:
3403 DBG_8723A("RTW_%s:P2P_PRESENCE_RESPONSE, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
3404 break;
3405 case P2P_GO_DISC_REQUEST:
3406 DBG_8723A("RTW_%s:P2P_GO_DISC_REQUEST, dialogToken =%d\n", (tx == true)?"TX":"RX", dialogToken);
3407 break;
3408 default:
3409 DBG_8723A("RTW_%s:OUI_Subtype =%d, dialogToken =%d\n", (tx == true)?"TX":"RX", OUI_Subtype, dialogToken);
3410 break;
3411 }
3412
3413 } else {
3414 DBG_8723A("RTW_%s:action frame category =%d\n", (tx == true)?"TX":"RX", category);
3415 }
3416 return is_p2p_frame;
3417}
3418
3419void rtw_init_cfg80211_wifidirect_info(struct rtw_adapter *padapter)
3420{
3421 struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
3422
3423 memset(pcfg80211_wdinfo, 0x00, sizeof(struct cfg80211_wifidirect_info));
3424
3425 setup_timer(&pcfg80211_wdinfo->remain_on_ch_timer,
3426 ro_ch_timer_process, (unsigned long)padapter);
3427}
3428
3429void p2p_protocol_wk_hdl23a(struct rtw_adapter *padapter, int intCmdType)
3430{
3431 switch (intCmdType) {
3432 case P2P_FIND_PHASE_WK:
3433 find_phase_handler(padapter);
3434 break;
3435 case P2P_RESTORE_STATE_WK:
3436 restore_p2p_state_handler(padapter);
3437 break;
3438 case P2P_PRE_TX_PROVDISC_PROCESS_WK:
3439 pre_tx_provdisc_handler(padapter);
3440 break;
3441 case P2P_PRE_TX_INVITEREQ_PROCESS_WK:
3442 pre_tx_invitereq_handler(padapter);
3443 break;
3444 case P2P_PRE_TX_NEGOREQ_PROCESS_WK:
3445 pre_tx_negoreq_handler(padapter);
3446 break;
3447 case P2P_RO_CH_WK:
3448 ro_ch_handler(padapter);
3449 break;
3450 }
3451}
3452
3453#ifdef CONFIG_8723AU_P2P
3454void process_p2p_ps_ie23a(struct rtw_adapter *padapter, u8 *IEs, u32 IELength)
3455{
3456 u8 * ies;
3457 u32 ies_len;
3458 u8 * p2p_ie;
3459 u32 p2p_ielen = 0;
3460 u8 noa_attr[MAX_P2P_IE_LEN] = { 0x00 };/* NoA length should be n*(13) + 2 */
3461 u32 attr_contentlen = 0;
3462
3463 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3464 u8 find_p2p = false, find_p2p_ps = false;
3465 u8 noa_offset, noa_num, noa_index;
3466
3467
3468
3469 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3470 {
3471 return;
3472 }
3473 if (IELength <= _BEACON_IE_OFFSET_)
3474 return;
3475
3476 ies = IEs + _BEACON_IE_OFFSET_;
3477 ies_len = IELength - _BEACON_IE_OFFSET_;
3478
3479 p2p_ie = rtw_get_p2p_ie23a(ies, ies_len, NULL, &p2p_ielen);
3480
3481 while(p2p_ie)
3482 {
3483 find_p2p = true;
3484 /* Get Notice of Absence IE. */
3485 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_NOA, noa_attr, &attr_contentlen))
3486 {
3487 find_p2p_ps = true;
3488 noa_index = noa_attr[0];
3489
3490 if ((pwdinfo->p2p_ps_mode == P2P_PS_NONE) ||
3491 (noa_index != pwdinfo->noa_index))/* if index change, driver should reconfigure related setting. */
3492 {
3493 pwdinfo->noa_index = noa_index;
3494 pwdinfo->opp_ps = noa_attr[1] >> 7;
3495 pwdinfo->ctwindow = noa_attr[1] & 0x7F;
3496
3497 noa_offset = 2;
3498 noa_num = 0;
3499 /* NoA length should be n*(13) + 2 */
3500 if (attr_contentlen > 2)
3501 {
3502 while(noa_offset < attr_contentlen)
3503 {
3504 /* memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1); */
3505 pwdinfo->noa_count[noa_num] = noa_attr[noa_offset];
3506 noa_offset += 1;
3507
3508 memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4);
3509 noa_offset += 4;
3510
3511 memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4);
3512 noa_offset += 4;
3513
3514 memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4);
3515 noa_offset += 4;
3516
3517 noa_num++;
3518 }
3519 }
3520 pwdinfo->noa_num = noa_num;
3521
3522 if (pwdinfo->opp_ps == 1)
3523 {
3524 pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
3525 /* driver should wait LPS for entering CTWindow */
3526 if (padapter->pwrctrlpriv.bFwCurrentInPSMode == true)
3527 {
3528 p2p_ps_wk_cmd23a(padapter, P2P_PS_ENABLE, 1);
3529 }
3530 }
3531 else if (pwdinfo->noa_num > 0)
3532 {
3533 pwdinfo->p2p_ps_mode = P2P_PS_NOA;
3534 p2p_ps_wk_cmd23a(padapter, P2P_PS_ENABLE, 1);
3535 }
3536 else if (pwdinfo->p2p_ps_mode > P2P_PS_NONE)
3537 {
3538 p2p_ps_wk_cmd23a(padapter, P2P_PS_DISABLE, 1);
3539 }
3540 }
3541
3542 break; /* find target, just break. */
3543 }
3544
3545 /* Get the next P2P IE */
3546 p2p_ie = rtw_get_p2p_ie23a(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
3547
3548 }
3549
3550 if (find_p2p == true)
3551 {
3552 if ((pwdinfo->p2p_ps_mode > P2P_PS_NONE) && (find_p2p_ps == false))
3553 {
3554 p2p_ps_wk_cmd23a(padapter, P2P_PS_DISABLE, 1);
3555 }
3556 }
3557
3558
3559}
3560
3561void p2p_ps_wk_hdl23a(struct rtw_adapter *padapter, u8 p2p_ps_state)
3562{
3563 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
3564 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3565
3566
3567
3568 /* Pre action for p2p state */
3569 switch (p2p_ps_state)
3570 {
3571 case P2P_PS_DISABLE:
3572 pwdinfo->p2p_ps_state = p2p_ps_state;
3573
3574 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
3575
3576 pwdinfo->noa_index = 0;
3577 pwdinfo->ctwindow = 0;
3578 pwdinfo->opp_ps = 0;
3579 pwdinfo->noa_num = 0;
3580 pwdinfo->p2p_ps_mode = P2P_PS_NONE;
3581 if (padapter->pwrctrlpriv.bFwCurrentInPSMode == true)
3582 {
3583 if (pwrpriv->smart_ps == 0)
3584 {
3585 pwrpriv->smart_ps = 2;
3586 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)&padapter->pwrctrlpriv.pwr_mode);
3587 }
3588 }
3589 break;
3590 case P2P_PS_ENABLE:
3591 if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
3592 pwdinfo->p2p_ps_state = p2p_ps_state;
3593
3594 if (pwdinfo->ctwindow > 0)
3595 {
3596 if (pwrpriv->smart_ps != 0)
3597 {
3598 pwrpriv->smart_ps = 0;
3599 DBG_8723A("%s(): Enter CTW, change SmartPS\n", __func__);
3600 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)&padapter->pwrctrlpriv.pwr_mode);
3601 }
3602 }
3603 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
3604 }
3605 break;
3606 case P2P_PS_SCAN:
3607 case P2P_PS_SCAN_DONE:
3608 case P2P_PS_ALLSTASLEEP:
3609 if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
3610 pwdinfo->p2p_ps_state = p2p_ps_state;
3611 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
3612 }
3613 break;
3614 default:
3615 break;
3616 }
3617
3618
3619}
3620
3621u8 p2p_ps_wk_cmd23a(struct rtw_adapter*padapter, u8 p2p_ps_state, u8 enqueue)
3622{
3623 struct cmd_obj *ph2c;
3624 struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3625 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3626 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
3627 u8 res = _SUCCESS;
3628
3629
3630
3631 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3632 return res;
3633
3634 if (enqueue) {
3635 ph2c = (struct cmd_obj *)kzalloc(sizeof(struct cmd_obj),
3636 GFP_ATOMIC);
3637 if (!ph2c) {
3638 res = _FAIL;
3639 goto exit;
3640 }
3641
3642 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)
3643 kzalloc(sizeof(struct drvextra_cmd_parm), GFP_ATOMIC);
3644 if (pdrvextra_cmd_parm == NULL) {
3645 kfree(ph2c);
3646 res = _FAIL;
3647 goto exit;
3648 }
3649
3650 pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID;
3651 pdrvextra_cmd_parm->type_size = p2p_ps_state;
3652 pdrvextra_cmd_parm->pbuf = NULL;
3653
3654 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
3655
3656 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
3657 }
3658 else
3659 {
3660 p2p_ps_wk_hdl23a(padapter, p2p_ps_state);
3661 }
3662
3663exit:
3664
3665
3666
3667 return res;
3668}
3669#endif /* CONFIG_8723AU_P2P */
3670
3671static void reset_ch_sitesurvey_timer_process(unsigned long data)
3672{
3673 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3674 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3675
3676 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3677 return;
3678
3679 DBG_8723A("[%s] In\n", __func__);
3680 /* Reset the operation channel information */
3681 pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
3682 pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
3683}
3684
3685static void reset_ch_sitesurvey_timer_process2(unsigned long data)
3686{
3687 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3688 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3689
3690 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3691 return;
3692
3693 DBG_8723A("[%s] In\n", __func__);
3694 /* Reset the operation channel information */
3695 pwdinfo->p2p_info.operation_ch[0] = 0;
3696 pwdinfo->p2p_info.scan_op_ch_only = 0;
3697}
3698
3699static void restore_p2p_state_timer_process (unsigned long data)
3700{
3701 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3702 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3703
3704 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3705 return;
3706
3707 p2p_protocol_wk_cmd23a(adapter, P2P_RESTORE_STATE_WK);
3708}
3709
3710static void pre_tx_scan_timer_process (unsigned long data)
3711{
3712 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3713 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3714 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
3715
3716 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3717 return;
3718
3719 spin_lock_bh(&pmlmepriv->lock);
3720
3721 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
3722 {
3723 if (true == pwdinfo->tx_prov_disc_info.benable) /* the provision discovery request frame is trigger to send or not */
3724 {
3725 p2p_protocol_wk_cmd23a(adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK);
3726 /* issue23a_probereq_p2p(adapter, NULL); */
3727 /* _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT); */
3728 }
3729 }
3730 else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
3731 {
3732 if (true == pwdinfo->nego_req_info.benable)
3733 {
3734 p2p_protocol_wk_cmd23a(adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK);
3735 }
3736 }
3737 else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ))
3738 {
3739 if (true == pwdinfo->invitereq_info.benable)
3740 {
3741 p2p_protocol_wk_cmd23a(adapter, P2P_PRE_TX_INVITEREQ_PROCESS_WK);
3742 }
3743 }
3744 else
3745 {
3746 DBG_8723A("[%s] p2p_state is %d, ignore!!\n", __func__, rtw_p2p_state(pwdinfo));
3747 }
3748
3749 spin_unlock_bh(&pmlmepriv->lock);
3750}
3751
3752static void find_phase_timer_process (unsigned long data)
3753{
3754 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
3755 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3756
3757 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3758 return;
3759
3760 adapter->wdinfo.find_phase_state_exchange_cnt++;
3761
3762 p2p_protocol_wk_cmd23a(adapter, P2P_FIND_PHASE_WK);
3763}
3764
3765void reset_global_wifidirect_info23a(struct rtw_adapter *padapter)
3766{
3767 struct wifidirect_info *pwdinfo;
3768
3769 pwdinfo = &padapter->wdinfo;
3770 pwdinfo->persistent_supported = 0;
3771 pwdinfo->session_available = true;
3772 pwdinfo->wfd_tdls_enable = 0;
3773 pwdinfo->wfd_tdls_weaksec = 0;
3774}
3775
3776#ifdef CONFIG_8723AU_P2P
3777int rtw_init_wifi_display_info(struct rtw_adapter* padapter)
3778{
3779 int res = _SUCCESS;
3780 struct wifi_display_info *pwfd_info = &padapter->wfd_info;
3781
3782 /* Used in P2P and TDLS */
3783 pwfd_info->rtsp_ctrlport = 554;
3784 pwfd_info->peer_rtsp_ctrlport = 0; /* Reset to 0 */
3785 pwfd_info->wfd_enable = false;
3786 pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
3787 pwfd_info->scan_result_type = SCAN_RESULT_P2P_ONLY;
3788
3789 /* Used in P2P */
3790 pwfd_info->peer_session_avail = true;
3791 pwfd_info->wfd_pc = false;
3792
3793 /* Used in TDLS */
3794 memset(pwfd_info->ip_address, 0x00, 4);
3795 memset(pwfd_info->peer_ip_address, 0x00, 4);
3796 return res;
3797}
3798#endif /* CONFIG_8723AU_P2P */
3799
3800void rtw_init_wifidirect_timers23a(struct rtw_adapter* padapter)
3801{
3802 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3803
3804 setup_timer(&pwdinfo->find_phase_timer, find_phase_timer_process,
3805 (unsigned long)padapter);
3806 setup_timer(&pwdinfo->restore_p2p_state_timer,
3807 restore_p2p_state_timer_process, (unsigned long)padapter);
3808 setup_timer(&pwdinfo->pre_tx_scan_timer, pre_tx_scan_timer_process,
3809 (unsigned long)padapter);
3810 setup_timer(&pwdinfo->reset_ch_sitesurvey,
3811 reset_ch_sitesurvey_timer_process, (unsigned long)padapter);
3812 setup_timer(&pwdinfo->reset_ch_sitesurvey2,
3813 reset_ch_sitesurvey_timer_process2,
3814 (unsigned long)padapter);
3815}
3816
3817void rtw_init_wifidirect_addrs23a(struct rtw_adapter* padapter, u8 *dev_addr, u8 *iface_addr)
3818{
3819#ifdef CONFIG_8723AU_P2P
3820 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3821
3822 /*init device&interface address */
3823 if (dev_addr) {
3824 memcpy(pwdinfo->device_addr, dev_addr, ETH_ALEN);
3825 }
3826 if (iface_addr) {
3827 memcpy(pwdinfo->interface_addr, iface_addr, ETH_ALEN);
3828 }
3829#endif
3830}
3831
3832void init_wifidirect_info23a(struct rtw_adapter *padapter, enum P2P_ROLE role)
3833{
3834 struct wifidirect_info *pwdinfo;
3835#ifdef CONFIG_8723AU_P2P
3836 struct wifi_display_info *pwfd_info = &padapter->wfd_info;
3837#endif
3838
3839 pwdinfo = &padapter->wdinfo;
3840
3841 pwdinfo->padapter = padapter;
3842
3843 /* 1, 6, 11 are the social channel defined in the WiFi Direct specification. */
3844 pwdinfo->social_chan[0] = 1;
3845 pwdinfo->social_chan[1] = 6;
3846 pwdinfo->social_chan[2] = 11;
3847 pwdinfo->social_chan[3] = 0; /* channel 0 for scanning ending in site survey function. */
3848
3849 /* Use the channel 11 as the listen channel */
3850 pwdinfo->listen_channel = 11;
3851
3852 if (role == P2P_ROLE_DEVICE)
3853 {
3854 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
3855 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
3856 pwdinfo->intent = 1;
3857 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_LISTEN);
3858 }
3859 else if (role == P2P_ROLE_CLIENT)
3860 {
3861 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
3862 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3863 pwdinfo->intent = 1;
3864 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
3865 }
3866 else if (role == P2P_ROLE_GO)
3867 {
3868 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3869 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3870 pwdinfo->intent = 15;
3871 rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
3872 }
3873
3874/* Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
3875 pwdinfo->support_rate[0] = 0x8c; /* 6(B) */
3876 pwdinfo->support_rate[1] = 0x92; /* 9(B) */
3877 pwdinfo->support_rate[2] = 0x18; /* 12 */
3878 pwdinfo->support_rate[3] = 0x24; /* 18 */
3879 pwdinfo->support_rate[4] = 0x30; /* 24 */
3880 pwdinfo->support_rate[5] = 0x48; /* 36 */
3881 pwdinfo->support_rate[6] = 0x60; /* 48 */
3882 pwdinfo->support_rate[7] = 0x6c; /* 54 */
3883
3884 memcpy((void*) pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7);
3885
3886 memset(pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN);
3887 pwdinfo->device_name_len = 0;
3888
3889 memset(&pwdinfo->invitereq_info, 0x00, sizeof(struct tx_invite_req_info));
3890 pwdinfo->invitereq_info.token = 3; /* Token used for P2P invitation request frame. */
3891
3892 memset(&pwdinfo->inviteresp_info, 0x00, sizeof(struct tx_invite_resp_info));
3893 pwdinfo->inviteresp_info.token = 0;
3894
3895 pwdinfo->profileindex = 0;
3896 memset(&pwdinfo->profileinfo[ 0 ], 0x00, sizeof(struct profile_info) * P2P_MAX_PERSISTENT_GROUP_NUM);
3897
3898 rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
3899
3900 pwdinfo->listen_dwell = (u8) ((jiffies % 3) + 1);
3901 /* DBG_8723A("[%s] listen_dwell time is %d00ms\n", __func__, pwdinfo->listen_dwell); */
3902
3903 memset(&pwdinfo->tx_prov_disc_info, 0x00, sizeof(struct tx_provdisc_req_info));
3904 pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE;
3905
3906 memset(&pwdinfo->nego_req_info, 0x00, sizeof(struct tx_nego_req_info));
3907
3908 pwdinfo->device_password_id_for_nego = WPS_DPID_PBC;
3909 pwdinfo->negotiation_dialog_token = 1;
3910
3911 memset(pwdinfo->nego_ssid, 0x00, IEEE80211_MAX_SSID_LEN);
3912 pwdinfo->nego_ssidlen = 0;
3913
3914 pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
3915#ifdef CONFIG_8723AU_P2P
3916 pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC;
3917 pwdinfo->wfd_info = pwfd_info;
3918#else
3919 pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD;
3920#endif /* CONFIG_8723AU_P2P */
3921 pwdinfo->channel_list_attr_len = 0;
3922 memset(pwdinfo->channel_list_attr, 0x00, 100);
3923
3924 memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4);
3925 memset(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3);
3926 memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
3927 pwdinfo->wfd_tdls_enable = 0;
3928 memset(pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN);
3929 memset(pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN);
3930
3931 pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
3932 pwdinfo->rx_invitereq_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */
3933 pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
3934 pwdinfo->p2p_info.operation_ch[0] = 0;
3935 pwdinfo->p2p_info.operation_ch[1] = 0; /* Used to indicate the scan end in site survey function */
3936 pwdinfo->p2p_info.scan_op_ch_only = 0;
3937}
3938
3939int rtw_p2p_enable23a(struct rtw_adapter *padapter, enum P2P_ROLE role)
3940{
3941 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3942 int ret = _SUCCESS;
3943
3944 if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT ||
3945 role == P2P_ROLE_GO) {
3946 /* leave IPS/Autosuspend */
3947 if (_FAIL == rtw_pwr_wakeup(padapter)) {
3948 ret = _FAIL;
3949 goto exit;
3950 }
3951
3952 /* Added by Albert 2011/03/22 */
3953 /* In the P2P mode, the driver should not support the b mode. */
3954 /* So, the Tx packet shouldn't use the CCK rate */
3955 update_tx_basic_rate23a(padapter, WIRELESS_11AGN);
3956
3957 /* Enable P2P function */
3958 init_wifidirect_info23a(padapter, role);
3959
3960 rtw_hal_set_odm_var23a(padapter, HAL_ODM_P2P_STATE, NULL, true);
3961 #ifdef CONFIG_8723AU_P2P
3962 rtw_hal_set_odm_var23a(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, true);
3963 #endif
3964
3965 }
3966 else if (role == P2P_ROLE_DISABLE)
3967 {
3968 if (_FAIL == rtw_pwr_wakeup(padapter)) {
3969 ret = _FAIL;
3970 goto exit;
3971 }
3972
3973 /* Disable P2P function */
3974 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3975 {
3976 del_timer_sync(&pwdinfo->find_phase_timer);
3977 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
3978 del_timer_sync(&pwdinfo->pre_tx_scan_timer);
3979 del_timer_sync(&pwdinfo->reset_ch_sitesurvey);
3980 del_timer_sync(&pwdinfo->reset_ch_sitesurvey2);
3981 reset_ch_sitesurvey_timer_process((unsigned long)padapter);
3982 reset_ch_sitesurvey_timer_process2((unsigned long)padapter);
3983 rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
3984 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE);
3985 memset(&pwdinfo->rx_prov_disc_info, 0x00, sizeof(struct rx_provdisc_req_info));
3986 }
3987
3988 rtw_hal_set_odm_var23a(padapter, HAL_ODM_P2P_STATE, NULL, false);
3989 #ifdef CONFIG_8723AU_P2P
3990 rtw_hal_set_odm_var23a(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, false);
3991 #endif
3992
3993 /* Restore to initial setting. */
3994 update_tx_basic_rate23a(padapter, padapter->registrypriv.wireless_mode);
3995 }
3996
3997exit:
3998 return ret;
3999}
4000
4001#endif /* CONFIG_8723AU_P2P */
diff --git a/drivers/staging/rtl8723au/core/rtw_pwrctrl.c b/drivers/staging/rtl8723au/core/rtw_pwrctrl.c
new file mode 100644
index 000000000000..8ddd67f194ba
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_pwrctrl.c
@@ -0,0 +1,689 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _RTW_PWRCTRL_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <osdep_intf.h>
20
21#ifdef CONFIG_8723AU_BT_COEXIST
22#include <rtl8723a_hal.h>
23#endif
24
25void ips_enter23a(struct rtw_adapter * padapter)
26{
27 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
28
29 down(&pwrpriv->lock);
30
31 pwrpriv->bips_processing = true;
32
33 /* syn ips_mode with request */
34 pwrpriv->ips_mode = pwrpriv->ips_mode_req;
35
36 pwrpriv->ips_enter23a_cnts++;
37 DBG_8723A("==>ips_enter23a cnts:%d\n", pwrpriv->ips_enter23a_cnts);
38#ifdef CONFIG_8723AU_BT_COEXIST
39 BTDM_TurnOffBtCoexistBeforeEnterIPS(padapter);
40#endif
41 if (rf_off == pwrpriv->change_rfpwrstate)
42 {
43 pwrpriv->bpower_saving = true;
44 DBG_8723A_LEVEL(_drv_always_, "nolinked power save enter\n");
45
46 if (pwrpriv->ips_mode == IPS_LEVEL_2)
47 pwrpriv->bkeepfwalive = true;
48
49 rtw_ips_pwr_down23a(padapter);
50 pwrpriv->rf_pwrstate = rf_off;
51 }
52 pwrpriv->bips_processing = false;
53
54 up(&pwrpriv->lock);
55}
56
57int ips_leave23a(struct rtw_adapter * padapter)
58{
59 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
60 struct security_priv *psecuritypriv = &padapter->securitypriv;
61 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
62 int result = _SUCCESS;
63 int keyid;
64
65 down(&pwrpriv->lock);
66
67 if ((pwrpriv->rf_pwrstate == rf_off) &&!pwrpriv->bips_processing)
68 {
69 pwrpriv->bips_processing = true;
70 pwrpriv->change_rfpwrstate = rf_on;
71 pwrpriv->ips_leave23a_cnts++;
72 DBG_8723A("==>ips_leave23a cnts:%d\n", pwrpriv->ips_leave23a_cnts);
73
74 if ((result = rtw_ips_pwr_up23a(padapter)) == _SUCCESS) {
75 pwrpriv->rf_pwrstate = rf_on;
76 }
77 DBG_8723A_LEVEL(_drv_always_, "nolinked power save leave\n");
78
79 if ((_WEP40_ == psecuritypriv->dot11PrivacyAlgrthm) ||(_WEP104_ == psecuritypriv->dot11PrivacyAlgrthm))
80 {
81 DBG_8723A("==>%s, channel(%d), processing(%x)\n", __func__, padapter->mlmeextpriv.cur_channel, pwrpriv->bips_processing);
82 set_channel_bwmode23a(padapter, padapter->mlmeextpriv.cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
83 for (keyid = 0;keyid<4;keyid++) {
84 if (pmlmepriv->key_mask & CHKBIT(keyid)) {
85 if (keyid == psecuritypriv->dot11PrivacyKeyIndex)
86 result = rtw_set_key23a(padapter, psecuritypriv, keyid, 1);
87 else
88 result = rtw_set_key23a(padapter, psecuritypriv, keyid, 0);
89 }
90 }
91 }
92
93 DBG_8723A("==> ips_leave23a.....LED(0x%08x)...\n", rtw_read32(padapter, 0x4c));
94 pwrpriv->bips_processing = false;
95
96 pwrpriv->bkeepfwalive = false;
97 pwrpriv->bpower_saving = false;
98 }
99
100 up(&pwrpriv->lock);
101
102 return result;
103}
104
105
106static bool rtw_pwr_unassociated_idle(struct rtw_adapter *adapter)
107{
108 struct rtw_adapter *buddy = adapter->pbuddy_adapter;
109 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
110 struct xmit_priv *pxmit_priv = &adapter->xmitpriv;
111 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
112
113 bool ret = false;
114
115 if (time_after_eq(adapter->pwrctrlpriv.ips_deny_time, jiffies))
116 goto exit;
117
118 if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
119 || check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
120 || check_fwstate(pmlmepriv, WIFI_AP_STATE)
121 || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
122 || !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
123 ) {
124 goto exit;
125 }
126
127 /* consider buddy, if exist */
128 if (buddy) {
129 struct mlme_priv *b_pmlmepriv = &buddy->mlmepriv;
130 struct wifidirect_info *b_pwdinfo = &buddy->wdinfo;
131
132 if (check_fwstate(b_pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
133 || check_fwstate(b_pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
134 || check_fwstate(b_pmlmepriv, WIFI_AP_STATE)
135 || check_fwstate(b_pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
136 || !rtw_p2p_chk_state(b_pwdinfo, P2P_STATE_NONE)
137 ) {
138 goto exit;
139 }
140 }
141
142 if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF ||
143 pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) {
144 DBG_8723A_LEVEL(_drv_always_, "There are some pkts to transmit\n");
145 DBG_8723A_LEVEL(_drv_info_, "free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n",
146 pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt);
147 goto exit;
148 }
149
150 ret = true;
151
152exit:
153 return ret;
154}
155
156void rtw_ps_processor23a(struct rtw_adapter*padapter)
157{
158 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
159 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
160 enum rt_rf_power_state rfpwrstate;
161
162 pwrpriv->ps_processing = true;
163
164 if (pwrpriv->bips_processing == true)
165 goto exit;
166
167 if (padapter->pwrctrlpriv.bHWPwrPindetect) {
168 rfpwrstate = RfOnOffDetect23a(padapter);
169 DBG_8723A("@@@@- #2 %s ==> rfstate:%s\n", __func__, (rfpwrstate == rf_on)?"rf_on":"rf_off");
170
171 if (rfpwrstate!= pwrpriv->rf_pwrstate) {
172 if (rfpwrstate == rf_off) {
173 pwrpriv->change_rfpwrstate = rf_off;
174 pwrpriv->brfoffbyhw = true;
175 padapter->bCardDisableWOHSM = true;
176 rtw_hw_suspend23a(padapter);
177 } else {
178 pwrpriv->change_rfpwrstate = rf_on;
179 rtw_hw_resume23a(padapter);
180 }
181 DBG_8723A("current rf_pwrstate(%s)\n", (pwrpriv->rf_pwrstate == rf_off)?"rf_off":"rf_on");
182 }
183 pwrpriv->pwr_state_check_cnts ++;
184 }
185
186 if (pwrpriv->ips_mode_req == IPS_NONE)
187 goto exit;
188
189 if (rtw_pwr_unassociated_idle(padapter) == false)
190 goto exit;
191
192 if ((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4) == 0))
193 {
194 DBG_8723A("==>%s .fw_state(%x)\n", __func__, get_fwstate(pmlmepriv));
195 pwrpriv->change_rfpwrstate = rf_off;
196 ips_enter23a(padapter);
197 }
198exit:
199 rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
200 pwrpriv->ps_processing = false;
201 return;
202}
203
204static void pwr_state_check_handler(unsigned long data)
205{
206 struct rtw_adapter *padapter = (struct rtw_adapter *)data;
207 rtw_ps_cmd23a(padapter);
208}
209
210/*
211 *
212 * Parameters
213 * padapter
214 * pslv power state level, only could be PS_STATE_S0 ~ PS_STATE_S4
215 *
216 */
217void rtw_set_rpwm23a(struct rtw_adapter *padapter, u8 pslv)
218{
219 u8 rpwm;
220 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
221
222
223
224 pslv = PS_STATE(pslv);
225
226 if (true == pwrpriv->btcoex_rfon)
227 {
228 if (pslv < PS_STATE_S4)
229 pslv = PS_STATE_S3;
230 }
231
232 if (pwrpriv->rpwm == pslv) {
233 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
234 ("%s: Already set rpwm[0x%02X], new = 0x%02X!\n", __func__, pwrpriv->rpwm, pslv));
235 return;
236 }
237
238 if ((padapter->bSurpriseRemoved == true) ||
239 (padapter->hw_init_completed == false)) {
240 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
241 ("%s: SurpriseRemoved(%d) hw_init_completed(%d)\n",
242 __func__, padapter->bSurpriseRemoved, padapter->hw_init_completed));
243
244 pwrpriv->cpwm = PS_STATE_S4;
245
246 return;
247 }
248
249 if (padapter->bDriverStopped == true) {
250 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
251 ("%s: change power state(0x%02X) when DriverStopped\n", __func__, pslv));
252
253 if (pslv < PS_STATE_S2) {
254 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
255 ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __func__, pslv));
256 return;
257 }
258 }
259
260 rpwm = pslv | pwrpriv->tog;
261 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
262 ("rtw_set_rpwm23a: rpwm = 0x%02x cpwm = 0x%02x\n", rpwm, pwrpriv->cpwm));
263
264 pwrpriv->rpwm = pslv;
265
266 rtw_hal_set_hwreg23a(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
267
268 pwrpriv->tog += 0x80;
269 pwrpriv->cpwm = pslv;
270
271
272}
273
274u8 PS_RDY_CHECK(struct rtw_adapter * padapter)
275{
276 unsigned long delta_time;
277 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
278 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
279
280 delta_time = jiffies - pwrpriv->DelayLPSLastTimeStamp;
281
282 if (delta_time < LPS_DELAY_TIME)
283 {
284 return false;
285 }
286
287 if ((check_fwstate(pmlmepriv, _FW_LINKED) == false) ||
288 (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) ||
289 (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) ||
290 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
291 (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
292 return false;
293 if (true == pwrpriv->bInSuspend)
294 return false;
295 if ((padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == false))
296 {
297 DBG_8723A("Group handshake still in progress !!!\n");
298 return false;
299 }
300 if (!rtw_cfg80211_pwr_mgmt(padapter))
301 return false;
302
303 return true;
304}
305
306void rtw_set_ps_mode23a(struct rtw_adapter *padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode)
307{
308 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
309#ifdef CONFIG_8723AU_P2P
310 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
311#endif /* CONFIG_8723AU_P2P */
312
313
314
315 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
316 ("%s: PowerMode =%d Smart_PS =%d\n",
317 __func__, ps_mode, smart_ps));
318
319 if (ps_mode > PM_Card_Disable) {
320 RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, ("ps_mode:%d error\n", ps_mode));
321 return;
322 }
323
324 if (pwrpriv->pwr_mode == ps_mode)
325 {
326 if (PS_MODE_ACTIVE == ps_mode) return;
327
328 if ((pwrpriv->smart_ps == smart_ps) &&
329 (pwrpriv->bcn_ant_mode == bcn_ant_mode))
330 {
331 return;
332 }
333 }
334
335 if (ps_mode == PS_MODE_ACTIVE) {
336#ifdef CONFIG_8723AU_P2P
337 if (pwdinfo->opp_ps == 0)
338#endif /* CONFIG_8723AU_P2P */
339 {
340 DBG_8723A("rtw_set_ps_mode23a: Leave 802.11 power save\n");
341
342 pwrpriv->pwr_mode = ps_mode;
343 rtw_set_rpwm23a(padapter, PS_STATE_S4);
344 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
345 pwrpriv->bFwCurrentInPSMode = false;
346 }
347 }
348 else
349 {
350 if (PS_RDY_CHECK(padapter)
351#ifdef CONFIG_8723AU_BT_COEXIST
352 || (BT_1Ant(padapter) == true)
353#endif
354 )
355 {
356 DBG_8723A("%s: Enter 802.11 power save\n", __func__);
357
358 pwrpriv->bFwCurrentInPSMode = true;
359 pwrpriv->pwr_mode = ps_mode;
360 pwrpriv->smart_ps = smart_ps;
361 pwrpriv->bcn_ant_mode = bcn_ant_mode;
362 rtw_hal_set_hwreg23a(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
363
364#ifdef CONFIG_8723AU_P2P
365 /* Set CTWindow after LPS */
366 if (pwdinfo->opp_ps == 1)
367 p2p_ps_wk_cmd23a(padapter, P2P_PS_ENABLE, 0);
368#endif /* CONFIG_8723AU_P2P */
369
370 rtw_set_rpwm23a(padapter, PS_STATE_S2);
371 }
372 }
373
374
375}
376
377/*
378 * Return:
379 * 0: Leave OK
380 * -1: Timeout
381 * -2: Other error
382 */
383s32 LPS_RF_ON_check23a(struct rtw_adapter *padapter, u32 delay_ms)
384{
385 unsigned long start_time, end_time;
386 u8 bAwake = false;
387 s32 err = 0;
388
389 start_time = jiffies;
390 end_time = start_time + msecs_to_jiffies(delay_ms);
391
392 while (1)
393 {
394 rtw23a_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake);
395 if (true == bAwake)
396 break;
397
398 if (true == padapter->bSurpriseRemoved)
399 {
400 err = -2;
401 DBG_8723A("%s: device surprise removed!!\n", __func__);
402 break;
403 }
404
405 if (time_after(jiffies, end_time)) {
406 err = -1;
407 DBG_8723A("%s: Wait for FW LPS leave more than %u ms!!!\n", __func__, delay_ms);
408 break;
409 }
410 udelay(100);
411 }
412
413 return err;
414}
415
416/* Description: */
417/* Enter the leisure power save mode. */
418void LPS_Enter23a(struct rtw_adapter *padapter)
419{
420 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
421
422 if (!PS_RDY_CHECK(padapter))
423 return;
424
425 if (pwrpriv->bLeisurePs) {
426 /* Idle for a while if we connect to AP a while ago. */
427 if (pwrpriv->LpsIdleCount >= 2) { /* 4 Sec */
428 if (pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
429 pwrpriv->bpower_saving = true;
430 DBG_8723A("%s smart_ps:%d\n", __func__, pwrpriv->smart_ps);
431 /* For Tenda W311R IOT issue */
432 rtw_set_ps_mode23a(padapter, pwrpriv->power_mgnt, pwrpriv->smart_ps, 0);
433 }
434 } else {
435 pwrpriv->LpsIdleCount++;
436 }
437 }
438}
439
440/* Description: */
441/* Leave the leisure power save mode. */
442void LPS_Leave23a(struct rtw_adapter *padapter)
443{
444#define LPS_LEAVE_TIMEOUT_MS 100
445
446 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
447
448 if (pwrpriv->bLeisurePs) {
449 if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
450 rtw_set_ps_mode23a(padapter, PS_MODE_ACTIVE, 0, 0);
451
452 if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
453 LPS_RF_ON_check23a(padapter, LPS_LEAVE_TIMEOUT_MS);
454 }
455 }
456
457 pwrpriv->bpower_saving = false;
458}
459
460/* Description: Leave all power save mode: LPS, FwLPS, IPS if needed. */
461/* Move code to function by tynli. 2010.03.26. */
462void LeaveAllPowerSaveMode23a(struct rtw_adapter *Adapter)
463{
464 struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
465 u8 enqueue = 0;
466
467
468
469 /* DBG_8723A("%s.....\n", __func__); */
470 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
471 { /* connect */
472#ifdef CONFIG_8723AU_P2P
473 p2p_ps_wk_cmd23a(Adapter, P2P_PS_DISABLE, enqueue);
474#endif /* CONFIG_8723AU_P2P */
475
476 rtw_lps_ctrl_wk_cmd23a(Adapter, LPS_CTRL_LEAVE, enqueue);
477 }
478
479
480}
481
482void rtw_init_pwrctrl_priv23a(struct rtw_adapter *padapter)
483{
484 struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
485
486 sema_init(&pwrctrlpriv->lock, 1);
487 pwrctrlpriv->rf_pwrstate = rf_on;
488 pwrctrlpriv->ips_enter23a_cnts = 0;
489 pwrctrlpriv->ips_leave23a_cnts = 0;
490 pwrctrlpriv->bips_processing = false;
491
492 pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode;
493 pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode;
494
495 pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
496 pwrctrlpriv->pwr_state_check_cnts = 0;
497 pwrctrlpriv->bInternalAutoSuspend = false;
498 pwrctrlpriv->bInSuspend = false;
499 pwrctrlpriv->bkeepfwalive = false;
500
501 pwrctrlpriv->LpsIdleCount = 0;
502 pwrctrlpriv->power_mgnt = padapter->registrypriv.power_mgnt;/* PS_MODE_MIN; */
503 pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?true:false;
504
505 pwrctrlpriv->bFwCurrentInPSMode = false;
506
507 pwrctrlpriv->rpwm = 0;
508 pwrctrlpriv->cpwm = PS_STATE_S4;
509
510 pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
511 pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps;
512 pwrctrlpriv->bcn_ant_mode = 0;
513
514 pwrctrlpriv->tog = 0x80;
515
516 pwrctrlpriv->btcoex_rfon = false;
517
518 setup_timer(&pwrctrlpriv->pwr_state_check_timer,
519 pwr_state_check_handler, (unsigned long)padapter);
520
521
522}
523
524void rtw_free_pwrctrl_priv(struct rtw_adapter *adapter)
525{
526}
527
528u8 rtw_interface_ps_func23a(struct rtw_adapter *padapter, enum hal_intf_ps_func efunc_id, u8* val)
529{
530 u8 bResult = true;
531 rtw_hal_intf_ps_func23a(padapter, efunc_id, val);
532
533 return bResult;
534}
535
536inline void rtw_set_ips_deny23a(struct rtw_adapter *padapter, u32 ms)
537{
538 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
539 pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ms);
540}
541
542/*
543* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
544* @adapter: pointer to _adapter structure
545* @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
546* Return _SUCCESS or _FAIL
547*/
548
549int _rtw_pwr_wakeup23a(struct rtw_adapter *padapter, u32 ips_deffer_ms, const char *caller)
550{
551 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
552 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
553 int ret = _SUCCESS;
554 unsigned long start = jiffies;
555 unsigned long new_deny_time;
556
557 new_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
558
559 if (time_before(pwrpriv->ips_deny_time, new_deny_time))
560 pwrpriv->ips_deny_time = new_deny_time;
561
562 if (pwrpriv->ps_processing) {
563 DBG_8723A("%s wait ps_processing...\n", __func__);
564 while (pwrpriv->ps_processing &&
565 jiffies_to_msecs(jiffies - start) <= 3000)
566 msleep(10);
567 if (pwrpriv->ps_processing)
568 DBG_8723A("%s wait ps_processing timeout\n", __func__);
569 else
570 DBG_8723A("%s wait ps_processing done\n", __func__);
571 }
572
573 if (rtw_hal_sreset_inprogress(padapter)) {
574 DBG_8723A("%s wait sreset_inprogress...\n", __func__);
575 while (rtw_hal_sreset_inprogress(padapter) &&
576 jiffies_to_msecs(jiffies - start) <= 4000)
577 msleep(10);
578 if (rtw_hal_sreset_inprogress(padapter))
579 DBG_8723A("%s wait sreset_inprogress timeout\n", __func__);
580 else
581 DBG_8723A("%s wait sreset_inprogress done\n", __func__);
582 }
583
584 if (pwrpriv->bInternalAutoSuspend == false && pwrpriv->bInSuspend) {
585 DBG_8723A("%s wait bInSuspend...\n", __func__);
586 while (pwrpriv->bInSuspend &&
587 (jiffies_to_msecs(jiffies - start) <= 3000)) {
588 msleep(10);
589 }
590 if (pwrpriv->bInSuspend)
591 DBG_8723A("%s wait bInSuspend timeout\n", __func__);
592 else
593 DBG_8723A("%s wait bInSuspend done\n", __func__);
594 }
595
596 /* System suspend is not allowed to wakeup */
597 if ((pwrpriv->bInternalAutoSuspend == false) && (true == pwrpriv->bInSuspend)) {
598 ret = _FAIL;
599 goto exit;
600 }
601
602 /* block??? */
603 if ((pwrpriv->bInternalAutoSuspend == true) && (padapter->net_closed == true)) {
604 ret = _FAIL;
605 goto exit;
606 }
607
608 /* I think this should be check in IPS, LPS, autosuspend functions... */
609 if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
610 {
611 ret = _SUCCESS;
612 goto exit;
613 }
614
615 if (rf_off == pwrpriv->rf_pwrstate) {
616 DBG_8723A("%s call ips_leave23a....\n", __func__);
617 if (_FAIL == ips_leave23a(padapter)) {
618 DBG_8723A("======> ips_leave23a fail.............\n");
619 ret = _FAIL;
620 goto exit;
621 }
622 }
623
624 /* TODO: the following checking need to be merged... */
625 if (padapter->bDriverStopped || !padapter->bup ||
626 !padapter->hw_init_completed) {
627 DBG_8723A("%s: bDriverStopped =%d, bup =%d, hw_init_completed "
628 "=%u\n", caller, padapter->bDriverStopped,
629 padapter->bup, padapter->hw_init_completed);
630 ret = false;
631 goto exit;
632 }
633
634exit:
635 new_deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms);
636 if (time_before(pwrpriv->ips_deny_time, new_deny_time))
637 pwrpriv->ips_deny_time = new_deny_time;
638 return ret;
639}
640
641int rtw_pm_set_lps23a(struct rtw_adapter *padapter, u8 mode)
642{
643 int ret = 0;
644 struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
645
646 if (mode < PS_MODE_NUM)
647 {
648 if (pwrctrlpriv->power_mgnt != mode)
649 {
650 if (PS_MODE_ACTIVE == mode)
651 {
652 LeaveAllPowerSaveMode23a(padapter);
653 }
654 else
655 {
656 pwrctrlpriv->LpsIdleCount = 2;
657 }
658 pwrctrlpriv->power_mgnt = mode;
659 pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?true:false;
660 }
661 }
662 else
663 {
664 ret = -EINVAL;
665 }
666
667 return ret;
668}
669
670int rtw_pm_set_ips23a(struct rtw_adapter *padapter, u8 mode)
671{
672 struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
673
674 if (mode == IPS_NORMAL || mode == IPS_LEVEL_2) {
675 rtw_ips_mode_req(pwrctrlpriv, mode);
676 DBG_8723A("%s %s\n", __func__, mode == IPS_NORMAL?"IPS_NORMAL":"IPS_LEVEL_2");
677 return 0;
678 }
679 else if (mode == IPS_NONE) {
680 rtw_ips_mode_req(pwrctrlpriv, mode);
681 DBG_8723A("%s %s\n", __func__, "IPS_NONE");
682 if ((padapter->bSurpriseRemoved == 0)&&_FAIL == rtw_pwr_wakeup(padapter))
683 return -EFAULT;
684 }
685 else {
686 return -EINVAL;
687 }
688 return 0;
689}
diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c b/drivers/staging/rtl8723au/core/rtw_recv.c
new file mode 100644
index 000000000000..0b2455e4f5b6
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_recv.c
@@ -0,0 +1,2471 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _RTW_RECV_C_
16#include <osdep_service.h>
17#include <drv_types.h>
18#include <recv_osdep.h>
19#include <mlme_osdep.h>
20#include <linux/ip.h>
21#include <linux/if_ether.h>
22#include <ethernet.h>
23#include <usb_ops.h>
24#include <linux/ieee80211.h>
25#include <wifi.h>
26
27void rtw_signal_stat_timer_hdl23a(unsigned long data);
28
29void _rtw_init_sta_recv_priv23a(struct sta_recv_priv *psta_recvpriv)
30{
31
32
33
34 spin_lock_init(&psta_recvpriv->lock);
35
36 /* for (i = 0; i<MAX_RX_NUMBLKS; i++) */
37 /* _rtw_init_queue23a(&psta_recvpriv->blk_strms[i]); */
38
39 _rtw_init_queue23a(&psta_recvpriv->defrag_q);
40
41
42}
43
44int _rtw_init_recv_priv23a(struct recv_priv *precvpriv,
45 struct rtw_adapter *padapter)
46{
47 struct recv_frame *precvframe;
48 int i;
49 int res = _SUCCESS;
50
51
52
53 /* We don't need to memset padapter->XXX to zero, because
54 adapter is allocated by rtw_zvmalloc(). */
55 /* memset((unsigned char *)precvpriv, 0, sizeof (struct recv_priv)); */
56
57 spin_lock_init(&precvpriv->lock);
58
59 _rtw_init_queue23a(&precvpriv->free_recv_queue);
60 _rtw_init_queue23a(&precvpriv->recv_pending_queue);
61 _rtw_init_queue23a(&precvpriv->uc_swdec_pending_queue);
62
63 precvpriv->adapter = padapter;
64
65 precvpriv->free_recvframe_cnt = NR_RECVFRAME;
66
67 precvpriv->pallocated_frame_buf =
68 rtw_zvmalloc(NR_RECVFRAME * sizeof(struct recv_frame));
69
70 if (precvpriv->pallocated_frame_buf == NULL) {
71 res = _FAIL;
72 goto exit;
73 }
74
75 precvframe = precvpriv->pallocated_frame_buf;
76
77 for (i = 0; i < NR_RECVFRAME ; i++) {
78 INIT_LIST_HEAD(&precvframe->list);
79
80 list_add_tail(&precvframe->list,
81 &precvpriv->free_recv_queue.queue);
82
83 res = rtw_os_recv_resource_alloc23a(padapter, precvframe);
84
85 precvframe->adapter = padapter;
86 precvframe++;
87 }
88
89 precvpriv->rx_pending_cnt = 1;
90
91 sema_init(&precvpriv->allrxreturnevt, 0);
92
93 res = rtw_hal_init23a_recv_priv(padapter);
94
95 setup_timer(&precvpriv->signal_stat_timer, rtw_signal_stat_timer_hdl23a,
96 (unsigned long)padapter);
97
98 precvpriv->signal_stat_sampling_interval = 1000; /* ms */
99
100 rtw_set_signal_stat_timer(precvpriv);
101
102exit:
103
104
105
106 return res;
107}
108
109void _rtw_free_recv_priv23a (struct recv_priv *precvpriv)
110{
111 struct rtw_adapter *padapter = precvpriv->adapter;
112
113
114
115 rtw_free_uc_swdec_pending_queue23a(padapter);
116
117 if (precvpriv->pallocated_frame_buf) {
118 rtw_vmfree(precvpriv->pallocated_frame_buf,
119 NR_RECVFRAME * sizeof(struct recv_frame));
120 }
121
122 rtw_hal_free_recv_priv23a(padapter);
123
124
125}
126
127struct recv_frame *rtw_alloc_recvframe23a(struct rtw_queue *pfree_recv_queue)
128{
129 struct recv_frame *pframe;
130 struct list_head *plist, *phead;
131 struct rtw_adapter *padapter;
132 struct recv_priv *precvpriv;
133
134 spin_lock_bh(&pfree_recv_queue->lock);
135
136 if (_rtw_queue_empty23a(pfree_recv_queue) == true)
137 pframe = NULL;
138 else {
139 phead = get_list_head(pfree_recv_queue);
140
141 plist = phead->next;
142
143 pframe = container_of(plist, struct recv_frame, list);
144
145 list_del_init(&pframe->list);
146 padapter = pframe->adapter;
147 if (padapter) {
148 precvpriv = &padapter->recvpriv;
149 if (pfree_recv_queue == &precvpriv->free_recv_queue)
150 precvpriv->free_recvframe_cnt--;
151 }
152 }
153
154 spin_unlock_bh(&pfree_recv_queue->lock);
155
156 return pframe;
157}
158
159int rtw_free_recvframe23a(struct recv_frame *precvframe, struct rtw_queue *pfree_recv_queue)
160{
161 struct rtw_adapter *padapter = precvframe->adapter;
162 struct recv_priv *precvpriv = &padapter->recvpriv;
163
164
165
166 if (precvframe->pkt) {
167 dev_kfree_skb_any(precvframe->pkt);/* free skb by driver */
168 precvframe->pkt = NULL;
169 }
170
171 spin_lock_bh(&pfree_recv_queue->lock);
172
173 list_del_init(&precvframe->list);
174
175 list_add_tail(&precvframe->list, get_list_head(pfree_recv_queue));
176
177 if (padapter) {
178 if (pfree_recv_queue == &precvpriv->free_recv_queue)
179 precvpriv->free_recvframe_cnt++;
180 }
181
182 spin_unlock_bh(&pfree_recv_queue->lock);
183
184
185
186 return _SUCCESS;
187}
188
189int rtw_enqueue_recvframe23a(struct recv_frame *precvframe, struct rtw_queue *queue)
190{
191 struct rtw_adapter *padapter = precvframe->adapter;
192 struct recv_priv *precvpriv = &padapter->recvpriv;
193
194 spin_lock_bh(&queue->lock);
195
196 list_del_init(&precvframe->list);
197
198 list_add_tail(&precvframe->list, get_list_head(queue));
199
200 if (padapter) {
201 if (queue == &precvpriv->free_recv_queue)
202 precvpriv->free_recvframe_cnt++;
203 }
204
205 spin_unlock_bh(&queue->lock);
206
207 return _SUCCESS;
208}
209
210/*
211caller : defrag ; recvframe_chk_defrag23a in recv_thread (passive)
212pframequeue: defrag_queue : will be accessed in recv_thread (passive)
213
214using spinlock to protect
215
216*/
217
218void rtw_free_recvframe23a_queue(struct rtw_queue *pframequeue, struct rtw_queue *pfree_recv_queue)
219{
220 struct recv_frame *hdr;
221 struct list_head *plist, *phead, *ptmp;
222
223
224 spin_lock(&pframequeue->lock);
225
226 phead = get_list_head(pframequeue);
227 plist = phead->next;
228
229 list_for_each_safe(plist, ptmp, phead) {
230 hdr = container_of(plist, struct recv_frame, list);
231 rtw_free_recvframe23a(hdr, pfree_recv_queue);
232 }
233
234 spin_unlock(&pframequeue->lock);
235
236
237}
238
239u32 rtw_free_uc_swdec_pending_queue23a(struct rtw_adapter *adapter)
240{
241 u32 cnt = 0;
242 struct recv_frame *pending_frame;
243 while ((pending_frame = rtw_alloc_recvframe23a(&adapter->recvpriv.uc_swdec_pending_queue))) {
244 rtw_free_recvframe23a(pending_frame,
245 &adapter->recvpriv.free_recv_queue);
246 DBG_8723A("%s: dequeue uc_swdec_pending_queue\n", __func__);
247 cnt++;
248 }
249
250 return cnt;
251}
252
253int rtw_enqueue_recvbuf23a_to_head(struct recv_buf *precvbuf, struct rtw_queue *queue)
254{
255 spin_lock_bh(&queue->lock);
256
257 list_del_init(&precvbuf->list);
258 list_add(&precvbuf->list, get_list_head(queue));
259
260 spin_unlock_bh(&queue->lock);
261
262 return _SUCCESS;
263}
264
265int rtw_enqueue_recvbuf23a(struct recv_buf *precvbuf, struct rtw_queue *queue)
266{
267 unsigned long irqL;
268 spin_lock_irqsave(&queue->lock, irqL);
269
270 list_del_init(&precvbuf->list);
271
272 list_add_tail(&precvbuf->list, get_list_head(queue));
273 spin_unlock_irqrestore(&queue->lock, irqL);
274 return _SUCCESS;
275}
276
277struct recv_buf *rtw_dequeue_recvbuf23a (struct rtw_queue *queue)
278{
279 unsigned long irqL;
280 struct recv_buf *precvbuf;
281 struct list_head *plist, *phead;
282
283 spin_lock_irqsave(&queue->lock, irqL);
284
285 if (_rtw_queue_empty23a(queue) == true) {
286 precvbuf = NULL;
287 } else {
288 phead = get_list_head(queue);
289
290 plist = phead->next;
291
292 precvbuf = container_of(plist, struct recv_buf, list);
293
294 list_del_init(&precvbuf->list);
295 }
296
297 spin_unlock_irqrestore(&queue->lock, irqL);
298
299 return precvbuf;
300}
301
302int recvframe_chkmic(struct rtw_adapter *adapter,
303 struct recv_frame *precvframe);
304int recvframe_chkmic(struct rtw_adapter *adapter,
305 struct recv_frame *precvframe) {
306
307 int i, res = _SUCCESS;
308 u32 datalen;
309 u8 miccode[8];
310 u8 bmic_err = false, brpt_micerror = true;
311 u8 *pframe, *payload,*pframemic;
312 u8 *mickey;
313 /* u8 *iv, rxdata_key_idx = 0; */
314 struct sta_info *stainfo;
315 struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
316 struct security_priv *psecuritypriv = &adapter->securitypriv;
317
318 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
319 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
320
321
322 stainfo = rtw_get_stainfo23a(&adapter->stapriv, &prxattrib->ta[0]);
323
324 if (prxattrib->encrypt == _TKIP_) {
325 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
326 ("\n recvframe_chkmic:prxattrib->encrypt == _TKIP_\n"));
327 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
328 ("\n recvframe_chkmic:da = 0x%02x:0x%02x:0x%02x:0x%02x:"
329 "0x%02x:0x%02x\n", prxattrib->ra[0],
330 prxattrib->ra[1], prxattrib->ra[2], prxattrib->ra[3],
331 prxattrib->ra[4], prxattrib->ra[5]));
332
333 /* calculate mic code */
334 if (stainfo != NULL) {
335 if (is_multicast_ether_addr(prxattrib->ra)) {
336 mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0];
337
338 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
339 ("\n recvframe_chkmic: bcmc key\n"));
340
341 if (psecuritypriv->binstallGrpkey == false) {
342 res = _FAIL;
343 RT_TRACE(_module_rtl871x_recv_c_,
344 _drv_err_,
345 ("\n recvframe_chkmic:didn't "
346 "install group key!!!!!!\n"));
347 DBG_8723A("\n recvframe_chkmic:didn't "
348 "install group key!!!!!!\n");
349 goto exit;
350 }
351 } else {
352 mickey = &stainfo->dot11tkiprxmickey.skey[0];
353 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
354 ("\n recvframe_chkmic: unicast "
355 "key\n"));
356 }
357
358 /* icv_len included the mic code */
359 datalen = precvframe->pkt->len-prxattrib->
360 hdrlen-prxattrib->iv_len-prxattrib->icv_len - 8;
361 pframe = precvframe->pkt->data;
362 payload = pframe + prxattrib->hdrlen +
363 prxattrib->iv_len;
364
365 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
366 ("\n prxattrib->iv_len =%d prxattrib->icv_len ="
367 "%d\n", prxattrib->iv_len,
368 prxattrib->icv_len));
369
370 /* care the length of the data */
371 rtw_seccalctkipmic23a(mickey, pframe, payload,
372 datalen, &miccode[0],
373 (unsigned char)prxattrib->priority);
374
375 pframemic = payload + datalen;
376
377 bmic_err = false;
378
379 for (i = 0; i < 8; i++) {
380 if (miccode[i] != *(pframemic + i)) {
381 RT_TRACE(_module_rtl871x_recv_c_,
382 _drv_err_,
383 ("recvframe_chkmic:miccode"
384 "[%d](%02x) != *(pframemic+"
385 "%d)(%02x) ", i, miccode[i],
386 i, *(pframemic + i)));
387 bmic_err = true;
388 }
389 }
390
391 if (bmic_err == true) {
392 int i;
393 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
394 ("\n *(pframemic-8)-*(pframemic-1) ="
395 "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:"
396 "0x%02x:0x%02x:0x%02x\n",
397 *(pframemic - 8), *(pframemic - 7),
398 *(pframemic - 6), *(pframemic - 5),
399 *(pframemic - 4), *(pframemic - 3),
400 *(pframemic - 2), *(pframemic - 1)));
401 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
402 ("\n *(pframemic-16)-*(pframemic-9) ="
403 "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:"
404 "0x%02x:0x%02x:0x%02x\n",
405 *(pframemic - 16), *(pframemic - 15),
406 *(pframemic - 14), *(pframemic - 13),
407 *(pframemic - 12), *(pframemic - 11),
408 *(pframemic - 10), *(pframemic - 9)));
409
410 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
411 ("\n ====== demp packet (len =%d) ======"
412 "\n", precvframe->pkt->len));
413 for (i = 0; i < precvframe->pkt->len; i = i + 8) {
414 RT_TRACE(_module_rtl871x_recv_c_,
415 _drv_err_, ("0x%02x:0x%02x:0x"
416 "%02x:0x%02x:0x%0"
417 "2x:0x%02x:0x%02x"
418 ":0x%02x",
419 *(precvframe->pkt->data+i),*(precvframe->pkt->data+i+1),
420 *(precvframe->pkt->data+i+2),*(precvframe->pkt->data+i+3),
421 *(precvframe->pkt->data+i+4),*(precvframe->pkt->data+i+5),
422 *(precvframe->pkt->data+i+6),*(precvframe->pkt->data+i+7)));
423 }
424 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
425 ("\n ====== demp packet end [len =%d]"
426 "======\n", precvframe->pkt->len));
427 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
428 ("\n hrdlen =%d,\n",
429 prxattrib->hdrlen));
430
431 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
432 ("ra = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%."
433 "2x 0x%.2x psecuritypriv->"
434 "binstallGrpkey =%d ",
435 prxattrib->ra[0], prxattrib->ra[1],
436 prxattrib->ra[2], prxattrib->ra[3],
437 prxattrib->ra[4], prxattrib->ra[5],
438 psecuritypriv->binstallGrpkey));
439
440 /* double check key_index for some timing
441 issue, cannot compare with
442 psecuritypriv->dot118021XGrpKeyid also
443 cause timing issue */
444 if ((is_multicast_ether_addr(prxattrib->ra)) &&
445 (prxattrib->key_index !=
446 pmlmeinfo->key_index))
447 brpt_micerror = false;
448
449 if ((prxattrib->bdecrypted == true) &&
450 (brpt_micerror == true)) {
451 rtw_handle_tkip_mic_err23a(adapter, (u8)is_multicast_ether_addr(prxattrib->ra));
452 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted =%d ", prxattrib->bdecrypted));
453 DBG_8723A(" mic error :prxattrib->"
454 "bdecrypted =%d\n",
455 prxattrib->bdecrypted);
456 } else {
457 RT_TRACE(_module_rtl871x_recv_c_,
458 _drv_err_,
459 (" mic error :prxattrib->"
460 "bdecrypted =%d ",
461 prxattrib->bdecrypted));
462 DBG_8723A(" mic error :prxattrib->"
463 "bdecrypted =%d\n",
464 prxattrib->bdecrypted);
465 }
466
467 res = _FAIL;
468 } else {
469 /* mic checked ok */
470 if ((psecuritypriv->bcheck_grpkey == false) &&
471 (is_multicast_ether_addr(prxattrib->ra))) {
472 psecuritypriv->bcheck_grpkey = true;
473 RT_TRACE(_module_rtl871x_recv_c_,
474 _drv_err_,
475 ("psecuritypriv->bcheck_grp"
476 "key = true"));
477 }
478 }
479 } else {
480 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
481 ("recvframe_chkmic: rtw_get_stainfo23a =="
482 "NULL!!!\n"));
483 }
484
485 skb_trim(precvframe->pkt, precvframe->pkt->len - 8);
486 }
487
488exit:
489
490
491
492 return res;
493}
494
495/* decrypt and set the ivlen, icvlen of the recv_frame */
496struct recv_frame *decryptor(struct rtw_adapter *padapter,
497 struct recv_frame *precv_frame);
498struct recv_frame *decryptor(struct rtw_adapter *padapter,
499 struct recv_frame *precv_frame)
500{
501 struct rx_pkt_attrib *prxattrib = &precv_frame->attrib;
502 struct security_priv *psecuritypriv = &padapter->securitypriv;
503 struct recv_frame *return_packet = precv_frame;
504 u32 res = _SUCCESS;
505
506
507 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
508 ("prxstat->decrypted =%x prxattrib->encrypt = 0x%03x\n",
509 prxattrib->bdecrypted, prxattrib->encrypt));
510
511 if (prxattrib->encrypt > 0) {
512 u8 *iv = precv_frame->pkt->data + prxattrib->hdrlen;
513 prxattrib->key_index = (((iv[3]) >> 6) & 0x3);
514
515 if (prxattrib->key_index > WEP_KEYS) {
516 DBG_8723A("prxattrib->key_index(%d) > WEP_KEYS\n",
517 prxattrib->key_index);
518
519 switch (prxattrib->encrypt) {
520 case _WEP40_:
521 case _WEP104_:
522 prxattrib->key_index =
523 psecuritypriv->dot11PrivacyKeyIndex;
524 break;
525 case _TKIP_:
526 case _AES_:
527 default:
528 prxattrib->key_index =
529 psecuritypriv->dot118021XGrpKeyid;
530 break;
531 }
532 }
533 }
534
535 if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0))) {
536 psecuritypriv->hw_decrypted = false;
537 switch (prxattrib->encrypt) {
538 case _WEP40_:
539 case _WEP104_:
540 rtw_wep_decrypt23a(padapter, precv_frame);
541 break;
542 case _TKIP_:
543 res = rtw_tkip_decrypt23a(padapter, precv_frame);
544 break;
545 case _AES_:
546 res = rtw_aes_decrypt23a(padapter, precv_frame);
547 break;
548 default:
549 break;
550 }
551 } else if (prxattrib->bdecrypted == 1 && prxattrib->encrypt > 0 &&
552 (psecuritypriv->busetkipkey == 1 ||
553 prxattrib->encrypt != _TKIP_)) {
554 psecuritypriv->hw_decrypted = true;
555 }
556
557 if (res == _FAIL) {
558 rtw_free_recvframe23a(return_packet,
559 &padapter->recvpriv.free_recv_queue);
560 return_packet = NULL;
561 }
562
563
564
565 return return_packet;
566}
567
568/* set the security information in the recv_frame */
569static struct recv_frame *portctrl(struct rtw_adapter *adapter,
570 struct recv_frame *precv_frame)
571{
572 u8 *psta_addr = NULL, *ptr;
573 uint auth_alg;
574 struct recv_frame *pfhdr;
575 struct sta_info *psta;
576 struct sta_priv *pstapriv ;
577 struct recv_frame *prtnframe;
578 u16 ether_type = 0;
579 u16 eapol_type = 0x888e;/* for Funia BD's WPA issue */
580 struct rx_pkt_attrib *pattrib;
581
582 pstapriv = &adapter->stapriv;
583 psta = rtw_get_stainfo23a(pstapriv, psta_addr);
584
585 auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
586
587 ptr = precv_frame->pkt->data;
588 pfhdr = precv_frame;
589 pattrib = &pfhdr->attrib;
590 psta_addr = pattrib->ta;
591
592 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
593 ("########portctrl:adapter->securitypriv.dot11AuthAlgrthm ="
594 "%d\n", adapter->securitypriv.dot11AuthAlgrthm));
595
596 if (auth_alg == 2) {
597 if ((psta != NULL) && (psta->ieee8021x_blocked)) {
598 /* blocked */
599 /* only accept EAPOL frame */
600 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
601 ("########portctrl:psta->ieee8021x_blocked =="
602 "1\n"));
603
604 prtnframe = precv_frame;
605
606 /* get ether_type */
607 ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
608 memcpy(&ether_type, ptr, 2);
609 ether_type = ntohs((unsigned short)ether_type);
610
611 if (ether_type == eapol_type) {
612 prtnframe = precv_frame;
613 } else {
614 /* free this frame */
615 rtw_free_recvframe23a(precv_frame,
616 &adapter->recvpriv.free_recv_queue);
617 prtnframe = NULL;
618 }
619 } else {
620 /* allowed */
621 /* check decryption status, and decrypt the frame if needed */
622 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
623 ("########portctrl:psta->ieee8021x_blocked =="
624 "0\n"));
625 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
626 ("portctrl:precv_frame->hdr.attrib.privacy ="
627 "%x\n", precv_frame->attrib.privacy));
628
629 if (pattrib->bdecrypted == 0) {
630 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
631 ("portctrl:prxstat->decrypted =%x\n",
632 pattrib->bdecrypted));
633 }
634
635 prtnframe = precv_frame;
636 /* check is the EAPOL frame or not (Rekey) */
637 if (ether_type == eapol_type) {
638 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
639 ("########portctrl:ether_type == "
640 "0x888e\n"));
641 /* check Rekey */
642
643 prtnframe = precv_frame;
644 } else {
645 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
646 ("########portctrl:ether_type = 0x%04x"
647 "\n", ether_type));
648 }
649 }
650 } else {
651 prtnframe = precv_frame;
652 }
653
654
655
656 return prtnframe;
657}
658
659int recv_decache(struct recv_frame *precv_frame, u8 bretry,
660 struct stainfo_rxcache *prxcache);
661int recv_decache(struct recv_frame *precv_frame, u8 bretry,
662 struct stainfo_rxcache *prxcache)
663{
664 int tid = precv_frame->attrib.priority;
665
666 u16 seq_ctrl = ((precv_frame->attrib.seq_num & 0xffff) << 4) |
667 (precv_frame->attrib.frag_num & 0xf);
668
669
670
671 if (tid > 15) {
672 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
673 ("recv_decache, (tid>15)! seq_ctrl = 0x%x, tid = 0x%x\n",
674 seq_ctrl, tid));
675
676 return _FAIL;
677 }
678
679 if (1) { /* if (bretry) */
680 if (seq_ctrl == prxcache->tid_rxseq[tid]) {
681 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
682 ("recv_decache, seq_ctrl = 0x%x, tid = 0x%x, "
683 "tid_rxseq = 0x%x\n",
684 seq_ctrl, tid, prxcache->tid_rxseq[tid]));
685
686 return _FAIL;
687 }
688 }
689
690 prxcache->tid_rxseq[tid] = seq_ctrl;
691
692
693
694 return _SUCCESS;
695}
696
697void process23a_pwrbit_data(struct rtw_adapter *padapter,
698 struct recv_frame *precv_frame);
699void process23a_pwrbit_data(struct rtw_adapter *padapter,
700 struct recv_frame *precv_frame)
701{
702#ifdef CONFIG_8723AU_AP_MODE
703 unsigned char pwrbit;
704 struct sk_buff *skb = precv_frame->pkt;
705 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
706 struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
707 struct sta_priv *pstapriv = &padapter->stapriv;
708 struct sta_info *psta = NULL;
709
710 psta = rtw_get_stainfo23a(pstapriv, pattrib->src);
711
712 if (psta) {
713 pwrbit = ieee80211_has_pm(hdr->frame_control);
714
715 if (pwrbit) {
716 if (!(psta->state & WIFI_SLEEP_STATE))
717 stop_sta_xmit23a(padapter, psta);
718 } else {
719 if (psta->state & WIFI_SLEEP_STATE)
720 wakeup_sta_to_xmit23a(padapter, psta);
721 }
722 }
723
724#endif
725}
726
727void process_wmmps_data(struct rtw_adapter *padapter,
728 struct recv_frame *precv_frame);
729void process_wmmps_data(struct rtw_adapter *padapter,
730 struct recv_frame *precv_frame)
731{
732#ifdef CONFIG_8723AU_AP_MODE
733 struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
734 struct sta_priv *pstapriv = &padapter->stapriv;
735 struct sta_info *psta = NULL;
736
737 psta = rtw_get_stainfo23a(pstapriv, pattrib->src);
738
739 if (!psta)
740 return;
741
742
743 if (!psta->qos_option)
744 return;
745
746 if (!(psta->qos_info & 0xf))
747 return;
748
749 if (psta->state & WIFI_SLEEP_STATE) {
750 u8 wmmps_ac = 0;
751
752 switch (pattrib->priority) {
753 case 1:
754 case 2:
755 wmmps_ac = psta->uapsd_bk & BIT(1);
756 break;
757 case 4:
758 case 5:
759 wmmps_ac = psta->uapsd_vi & BIT(1);
760 break;
761 case 6:
762 case 7:
763 wmmps_ac = psta->uapsd_vo & BIT(1);
764 break;
765 case 0:
766 case 3:
767 default:
768 wmmps_ac = psta->uapsd_be & BIT(1);
769 break;
770 }
771
772 if (wmmps_ac) {
773 if (psta->sleepq_ac_len > 0) {
774 /* process received triggered frame */
775 xmit_delivery_enabled_frames23a(padapter, psta);
776 } else {
777 /* issue one qos null frame with More data bit = 0 and the EOSP bit set (= 1) */
778 issue_qos_nulldata23a(padapter, psta->hwaddr,
779 (u16)pattrib->priority,
780 0, 0);
781 }
782 }
783 }
784
785#endif
786}
787
788static void count_rx_stats(struct rtw_adapter *padapter,
789 struct recv_frame *prframe, struct sta_info *sta)
790{
791 int sz;
792 struct sta_info *psta = NULL;
793 struct stainfo_stats *pstats = NULL;
794 struct rx_pkt_attrib *pattrib = & prframe->attrib;
795 struct recv_priv *precvpriv = &padapter->recvpriv;
796
797 sz = prframe->pkt->len;
798 precvpriv->rx_bytes += sz;
799
800 padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++;
801
802 if ((!is_broadcast_ether_addr(pattrib->dst)) &&
803 (!is_multicast_ether_addr(pattrib->dst)))
804 padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++;
805
806 if (sta)
807 psta = sta;
808 else
809 psta = prframe->psta;
810
811 if (psta) {
812 pstats = &psta->sta_stats;
813
814 pstats->rx_data_pkts++;
815 pstats->rx_bytes += sz;
816 }
817}
818
819static int sta2sta_data_frame(struct rtw_adapter *adapter,
820 struct recv_frame *precv_frame,
821 struct sta_info**psta)
822{
823 struct sk_buff *skb = precv_frame->pkt;
824 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
825 int ret = _SUCCESS;
826 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
827 struct sta_priv *pstapriv = &adapter->stapriv;
828 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
829 u8 *mybssid = get_bssid(pmlmepriv);
830 u8 *myhwaddr = myid(&adapter->eeprompriv);
831 u8 *sta_addr = NULL;
832 int bmcast = is_multicast_ether_addr(pattrib->dst);
833
834
835
836 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
837 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
838
839 /* filter packets that SA is myself or multicast or broadcast */
840 if (ether_addr_equal(myhwaddr, pattrib->src)) {
841 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
842 (" SA == myself\n"));
843 ret = _FAIL;
844 goto exit;
845 }
846
847 if (!ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) {
848 ret = _FAIL;
849 goto exit;
850 }
851
852 if (ether_addr_equal(pattrib->bssid, "\x0\x0\x0\x0\x0\x0") ||
853 ether_addr_equal(mybssid, "\x0\x0\x0\x0\x0\x0") ||
854 !ether_addr_equal(pattrib->bssid, mybssid)) {
855 ret = _FAIL;
856 goto exit;
857 }
858
859 sta_addr = pattrib->src;
860 } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
861 /* For Station mode, sa and bssid should always be BSSID,
862 and DA is my mac-address */
863 if (!ether_addr_equal(pattrib->bssid, pattrib->src)) {
864 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
865 ("bssid != TA under STATION_MODE; drop "
866 "pkt\n"));
867 ret = _FAIL;
868 goto exit;
869 }
870
871 sta_addr = pattrib->bssid;
872
873 } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
874 if (bmcast) {
875 /* For AP mode, if DA == MCAST, then BSSID should be also MCAST */
876 if (!is_multicast_ether_addr(pattrib->bssid)) {
877 ret = _FAIL;
878 goto exit;
879 }
880 } else { /* not mc-frame */
881 /* For AP mode, if DA is non-MCAST, then it must
882 be BSSID, and bssid == BSSID */
883 if (!ether_addr_equal(pattrib->bssid, pattrib->dst)) {
884 ret = _FAIL;
885 goto exit;
886 }
887
888 sta_addr = pattrib->src;
889 }
890 } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
891 ether_addr_copy(pattrib->dst, hdr->addr1);
892 ether_addr_copy(pattrib->src, hdr->addr2);
893 ether_addr_copy(pattrib->bssid, hdr->addr3);
894 ether_addr_copy(pattrib->ra, pattrib->dst);
895 ether_addr_copy(pattrib->ta, pattrib->src);
896
897 sta_addr = mybssid;
898 } else {
899 ret = _FAIL;
900 }
901
902 if (bmcast)
903 *psta = rtw_get_bcmc_stainfo23a(adapter);
904 else
905 *psta = rtw_get_stainfo23a(pstapriv, sta_addr); /* get ap_info */
906
907 if (*psta == NULL) {
908 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under sta2sta_data_frame ; drop pkt\n"));
909 ret = _FAIL;
910 goto exit;
911 }
912
913exit:
914
915 return ret;
916}
917
918int ap2sta_data_frame(struct rtw_adapter *adapter,
919 struct recv_frame *precv_frame,
920 struct sta_info **psta);
921int ap2sta_data_frame(struct rtw_adapter *adapter,
922 struct recv_frame *precv_frame,
923 struct sta_info **psta)
924{
925 struct sk_buff *skb = precv_frame->pkt;
926 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
927 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
928 int ret = _SUCCESS;
929 struct sta_priv *pstapriv = &adapter->stapriv;
930 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
931 u8 *mybssid = get_bssid(pmlmepriv);
932 u8 *myhwaddr = myid(&adapter->eeprompriv);
933 int bmcast = is_multicast_ether_addr(pattrib->dst);
934
935
936
937 if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) &&
938 (check_fwstate(pmlmepriv, _FW_LINKED) == true ||
939 check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)) {
940
941 /* filter packets that SA is myself or multicast or broadcast */
942 if (ether_addr_equal(myhwaddr, pattrib->src)) {
943 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
944 (" SA == myself\n"));
945 ret = _FAIL;
946 goto exit;
947 }
948
949 /* da should be for me */
950 if (!ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) {
951 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
952 (" ap2sta_data_frame: compare DA fail; DA ="
953 MAC_FMT"\n", MAC_ARG(pattrib->dst)));
954 ret = _FAIL;
955 goto exit;
956 }
957
958 /* check BSSID */
959 if (ether_addr_equal(pattrib->bssid, "\x0\x0\x0\x0\x0\x0") ||
960 ether_addr_equal(mybssid, "\x0\x0\x0\x0\x0\x0") ||
961 !ether_addr_equal(pattrib->bssid, mybssid)) {
962 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
963 (" ap2sta_data_frame: compare BSSID fail ; "
964 "BSSID ="MAC_FMT"\n", MAC_ARG(pattrib->bssid)));
965 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
966 ("mybssid ="MAC_FMT"\n", MAC_ARG(mybssid)));
967
968 if (!bmcast) {
969 DBG_8723A("issue_deauth23a to the nonassociated "
970 "ap =" MAC_FMT " for the reason(7)\n",
971 MAC_ARG(pattrib->bssid));
972 issue_deauth23a(adapter, pattrib->bssid,
973 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
974 }
975
976 ret = _FAIL;
977 goto exit;
978 }
979
980 if (bmcast)
981 *psta = rtw_get_bcmc_stainfo23a(adapter);
982 else
983 /* get ap_info */
984 *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid);
985
986 if (*psta == NULL) {
987 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
988 ("ap2sta: can't get psta under STATION_MODE ;"
989 " drop pkt\n"));
990 ret = _FAIL;
991 goto exit;
992 }
993
994 if (ieee80211_is_nullfunc(hdr->frame_control)) {
995 /* No data, will not indicate to upper layer,
996 temporily count it here */
997 count_rx_stats(adapter, precv_frame, *psta);
998 ret = RTW_RX_HANDLED;
999 goto exit;
1000 }
1001
1002 } else if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) &&
1003 (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
1004 ether_addr_copy(pattrib->dst, hdr->addr1);
1005 ether_addr_copy(pattrib->src, hdr->addr2);
1006 ether_addr_copy(pattrib->bssid, hdr->addr3);
1007 ether_addr_copy(pattrib->ra, pattrib->dst);
1008 ether_addr_copy(pattrib->ta, pattrib->src);
1009
1010 /* */
1011 ether_addr_copy(pattrib->bssid, mybssid);
1012
1013 /* get sta_info */
1014 *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid);
1015 if (*psta == NULL) {
1016 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1017 ("can't get psta under MP_MODE ; drop pkt\n"));
1018 ret = _FAIL;
1019 goto exit;
1020 }
1021 } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
1022 /* Special case */
1023 ret = RTW_RX_HANDLED;
1024 goto exit;
1025 } else {
1026 if (ether_addr_equal(myhwaddr, pattrib->dst) && !bmcast) {
1027 *psta = rtw_get_stainfo23a(pstapriv, pattrib->bssid);
1028 if (*psta == NULL) {
1029 DBG_8723A("issue_deauth23a to the ap =" MAC_FMT
1030 " for the reason(7)\n",
1031 MAC_ARG(pattrib->bssid));
1032
1033 issue_deauth23a(adapter, pattrib->bssid,
1034 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1035 }
1036 }
1037
1038 ret = _FAIL;
1039 }
1040
1041exit:
1042
1043
1044
1045 return ret;
1046}
1047
1048int sta2ap_data_frame(struct rtw_adapter *adapter,
1049 struct recv_frame *precv_frame,
1050 struct sta_info **psta);
1051int sta2ap_data_frame(struct rtw_adapter *adapter,
1052 struct recv_frame *precv_frame,
1053 struct sta_info **psta)
1054{
1055 struct sk_buff *skb = precv_frame->pkt;
1056 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1057 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
1058 struct sta_priv *pstapriv = &adapter->stapriv;
1059 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1060 unsigned char *mybssid = get_bssid(pmlmepriv);
1061 int ret = _SUCCESS;
1062
1063
1064
1065 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
1066 /* For AP mode, RA = BSSID, TX = STA(SRC_ADDR), A3 = DST_ADDR */
1067 if (!ether_addr_equal(pattrib->bssid, mybssid)) {
1068 ret = _FAIL;
1069 goto exit;
1070 }
1071
1072 *psta = rtw_get_stainfo23a(pstapriv, pattrib->src);
1073 if (*psta == NULL) {
1074 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1075 ("can't get psta under AP_MODE; drop pkt\n"));
1076 DBG_8723A("issue_deauth23a to sta =" MAC_FMT
1077 " for the reason(7)\n",
1078 MAC_ARG(pattrib->src));
1079
1080 issue_deauth23a(adapter, pattrib->src,
1081 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1082
1083 ret = RTW_RX_HANDLED;
1084 goto exit;
1085 }
1086
1087 process23a_pwrbit_data(adapter, precv_frame);
1088
1089 /* We only get here if it's a data frame, so no need to
1090 * confirm data frame type first */
1091 if (ieee80211_is_data_qos(hdr->frame_control))
1092 process_wmmps_data(adapter, precv_frame);
1093
1094 if (ieee80211_is_nullfunc(hdr->frame_control)) {
1095 /* No data, will not indicate to upper layer,
1096 temporily count it here */
1097 count_rx_stats(adapter, precv_frame, *psta);
1098 ret = RTW_RX_HANDLED;
1099 goto exit;
1100 }
1101 } else {
1102 u8 *myhwaddr = myid(&adapter->eeprompriv);
1103 if (!ether_addr_equal(pattrib->ra, myhwaddr)) {
1104 ret = RTW_RX_HANDLED;
1105 goto exit;
1106 }
1107 DBG_8723A("issue_deauth23a to sta =" MAC_FMT " for the reason(7)\n",
1108 MAC_ARG(pattrib->src));
1109 issue_deauth23a(adapter, pattrib->src,
1110 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1111 ret = RTW_RX_HANDLED;
1112 goto exit;
1113 }
1114
1115exit:
1116
1117
1118
1119 return ret;
1120}
1121
1122int validate_recv_ctrl_frame(struct rtw_adapter *padapter,
1123 struct recv_frame *precv_frame);
1124int validate_recv_ctrl_frame(struct rtw_adapter *padapter,
1125 struct recv_frame *precv_frame)
1126{
1127#ifdef CONFIG_8723AU_AP_MODE
1128 struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
1129 struct sta_priv *pstapriv = &padapter->stapriv;
1130 struct sk_buff *skb = precv_frame->pkt;
1131 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1132 u8 *pframe = skb->data;
1133
1134 if (!ieee80211_is_ctl(hdr->frame_control))
1135 return _FAIL;
1136
1137 /* receive the frames that ra(a1) is my address */
1138 if (!ether_addr_equal(hdr->addr1, myid(&padapter->eeprompriv)))
1139 return _FAIL;
1140
1141 /* only handle ps-poll */
1142 if (ieee80211_is_pspoll(hdr->frame_control)) {
1143 u16 aid;
1144 u8 wmmps_ac = 0;
1145 struct sta_info *psta = NULL;
1146
1147 aid = GetAid(pframe);
1148 psta = rtw_get_stainfo23a(pstapriv, hdr->addr2);
1149
1150 if ((!psta) || (psta->aid != aid))
1151 return _FAIL;
1152
1153 /* for rx pkt statistics */
1154 psta->sta_stats.rx_ctrl_pkts++;
1155
1156 switch (pattrib->priority) {
1157 case 1:
1158 case 2:
1159 wmmps_ac = psta->uapsd_bk & BIT(0);
1160 break;
1161 case 4:
1162 case 5:
1163 wmmps_ac = psta->uapsd_vi & BIT(0);
1164 break;
1165 case 6:
1166 case 7:
1167 wmmps_ac = psta->uapsd_vo & BIT(0);
1168 break;
1169 case 0:
1170 case 3:
1171 default:
1172 wmmps_ac = psta->uapsd_be & BIT(0);
1173 break;
1174 }
1175
1176 if (wmmps_ac)
1177 return _FAIL;
1178
1179 if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
1180 DBG_8723A("%s alive check-rx ps-poll\n", __func__);
1181 psta->expire_to = pstapriv->expire_to;
1182 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
1183 }
1184
1185 if ((psta->state & WIFI_SLEEP_STATE) &&
1186 (pstapriv->sta_dz_bitmap & CHKBIT(psta->aid))) {
1187 struct list_head *xmitframe_plist, *xmitframe_phead;
1188 struct xmit_frame *pxmitframe;
1189 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1190
1191 spin_lock_bh(&pxmitpriv->lock);
1192
1193 xmitframe_phead = get_list_head(&psta->sleep_q);
1194 xmitframe_plist = xmitframe_phead->next;
1195
1196 if (!list_empty(xmitframe_phead)) {
1197 pxmitframe = container_of(xmitframe_plist,
1198 struct xmit_frame,
1199 list);
1200
1201 xmitframe_plist = xmitframe_plist->next;
1202
1203 list_del_init(&pxmitframe->list);
1204
1205 psta->sleepq_len--;
1206
1207 if (psta->sleepq_len>0)
1208 pxmitframe->attrib.mdata = 1;
1209 else
1210 pxmitframe->attrib.mdata = 0;
1211
1212 pxmitframe->attrib.triggered = 1;
1213
1214 /* DBG_8723A("handling ps-poll, q_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */
1215
1216 rtw_hal_xmit23aframe_enqueue(padapter, pxmitframe);
1217
1218 if (psta->sleepq_len == 0) {
1219 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
1220
1221 /* DBG_8723A("after handling ps-poll, tim =%x\n", pstapriv->tim_bitmap); */
1222
1223 /* upate BCN for TIM IE */
1224 /* update_BCNTIM(padapter); */
1225 update_beacon23a(padapter, _TIM_IE_,
1226 NULL, false);
1227 }
1228
1229 /* spin_unlock_bh(&psta->sleep_q.lock); */
1230 spin_unlock_bh(&pxmitpriv->lock);
1231
1232 } else {
1233 /* spin_unlock_bh(&psta->sleep_q.lock); */
1234 spin_unlock_bh(&pxmitpriv->lock);
1235
1236 /* DBG_8723A("no buffered packets to xmit\n"); */
1237 if (pstapriv->tim_bitmap & CHKBIT(psta->aid)) {
1238 if (psta->sleepq_len == 0) {
1239 DBG_8723A("no buffered packets "
1240 "to xmit\n");
1241
1242 /* issue nulldata with More data bit = 0 to indicate we have no buffered packets */
1243 issue_nulldata23a(padapter,
1244 psta->hwaddr,
1245 0, 0, 0);
1246 } else {
1247 DBG_8723A("error!psta->sleepq"
1248 "_len =%d\n",
1249 psta->sleepq_len);
1250 psta->sleepq_len = 0;
1251 }
1252
1253 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
1254
1255 /* upate BCN for TIM IE */
1256 /* update_BCNTIM(padapter); */
1257 update_beacon23a(padapter, _TIM_IE_,
1258 NULL, false);
1259 }
1260 }
1261 }
1262 }
1263
1264#endif
1265 return _FAIL;
1266}
1267
1268struct recv_frame* recvframe_chk_defrag23a(struct rtw_adapter *padapter,
1269 struct recv_frame *precv_frame);
1270int validate_recv_mgnt_frame(struct rtw_adapter *padapter,
1271 struct recv_frame *precv_frame);
1272int validate_recv_mgnt_frame(struct rtw_adapter *padapter,
1273 struct recv_frame *precv_frame)
1274{
1275 struct sta_info *psta;
1276 struct sk_buff *skb;
1277 struct ieee80211_hdr *hdr;
1278 /* struct mlme_priv *pmlmepriv = &adapter->mlmepriv; */
1279
1280 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1281 ("+validate_recv_mgnt_frame\n"));
1282
1283 precv_frame = recvframe_chk_defrag23a(padapter, precv_frame);
1284 if (precv_frame == NULL) {
1285 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
1286 ("%s: fragment packet\n", __func__));
1287 return _SUCCESS;
1288 }
1289
1290 skb = precv_frame->pkt;
1291 hdr = (struct ieee80211_hdr *) skb->data;
1292
1293 /* for rx pkt statistics */
1294 psta = rtw_get_stainfo23a(&padapter->stapriv, hdr->addr2);
1295 if (psta) {
1296 psta->sta_stats.rx_mgnt_pkts++;
1297
1298 if (ieee80211_is_beacon(hdr->frame_control))
1299 psta->sta_stats.rx_beacon_pkts++;
1300 else if (ieee80211_is_probe_req(hdr->frame_control))
1301 psta->sta_stats.rx_probereq_pkts++;
1302 else if (ieee80211_is_probe_resp(hdr->frame_control)) {
1303 if (ether_addr_equal(padapter->eeprompriv.mac_addr,
1304 hdr->addr1))
1305 psta->sta_stats.rx_probersp_pkts++;
1306 else if (is_broadcast_ether_addr(hdr->addr1) ||
1307 is_multicast_ether_addr(hdr->addr1))
1308 psta->sta_stats.rx_probersp_bm_pkts++;
1309 else
1310 psta->sta_stats.rx_probersp_uo_pkts++;
1311 }
1312 }
1313
1314 mgt_dispatcher23a(padapter, precv_frame);
1315
1316 return _SUCCESS;
1317}
1318
1319int validate_recv_data_frame(struct rtw_adapter *adapter,
1320 struct recv_frame *precv_frame);
1321int validate_recv_data_frame(struct rtw_adapter *adapter,
1322 struct recv_frame *precv_frame)
1323{
1324 u8 bretry;
1325 u8 *psa, *pda, *pbssid;
1326 struct sta_info *psta = NULL;
1327 u8 *ptr = precv_frame->pkt->data;
1328 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
1329 struct security_priv *psecuritypriv = &adapter->securitypriv;
1330 int ret = _SUCCESS;
1331 struct sk_buff *skb = precv_frame->pkt;
1332 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1333
1334
1335
1336 bretry = ieee80211_has_retry(hdr->frame_control);
1337 pda = ieee80211_get_DA(hdr);
1338 psa = ieee80211_get_SA(hdr);
1339 pbssid = get_hdr_bssid(ptr);
1340
1341 if (pbssid == NULL) {
1342 ret = _FAIL;
1343 goto exit;
1344 }
1345
1346 ether_addr_copy(pattrib->dst, pda);
1347 ether_addr_copy(pattrib->src, psa);
1348
1349 ether_addr_copy(pattrib->bssid, pbssid);
1350
1351 switch (pattrib->to_fr_ds)
1352 {
1353 case 0:
1354 ether_addr_copy(pattrib->ra, pda);
1355 ether_addr_copy(pattrib->ta, psa);
1356 ret = sta2sta_data_frame(adapter, precv_frame, &psta);
1357 break;
1358
1359 case 1:
1360 ether_addr_copy(pattrib->ra, pda);
1361 ether_addr_copy(pattrib->ta, pbssid);
1362 ret = ap2sta_data_frame(adapter, precv_frame, &psta);
1363 break;
1364
1365 case 2:
1366 ether_addr_copy(pattrib->ra, pbssid);
1367 ether_addr_copy(pattrib->ta, psa);
1368 ret = sta2ap_data_frame(adapter, precv_frame, &psta);
1369 break;
1370
1371 case 3:
1372 ether_addr_copy(pattrib->ra, hdr->addr1);
1373 ether_addr_copy(pattrib->ta, hdr->addr2);
1374 ret = _FAIL;
1375 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" case 3\n"));
1376 break;
1377
1378 default:
1379 ret = _FAIL;
1380 break;
1381 }
1382
1383 if ((ret == _FAIL) || (ret == RTW_RX_HANDLED))
1384 goto exit;
1385
1386 if (!psta) {
1387 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1388 (" after to_fr_ds_chk; psta == NULL\n"));
1389 ret = _FAIL;
1390 goto exit;
1391 }
1392
1393 /* psta->rssi = prxcmd->rssi; */
1394 /* psta->signal_quality = prxcmd->sq; */
1395 precv_frame->psta = psta;
1396
1397 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
1398 if (ieee80211_has_a4(hdr->frame_control))
1399 pattrib->hdrlen += ETH_ALEN;
1400
1401 /* parsing QC field */
1402 if (pattrib->qos == 1) {
1403 __le16 *qptr = (__le16 *)ieee80211_get_qos_ctl(hdr);
1404 u16 qos_ctrl = le16_to_cpu(*qptr);
1405
1406 pattrib->priority = qos_ctrl & IEEE80211_QOS_CTL_TID_MASK;
1407 pattrib->ack_policy = (qos_ctrl >> 5) & 3;
1408 pattrib->amsdu =
1409 (qos_ctrl & IEEE80211_QOS_CTL_A_MSDU_PRESENT) >> 7;
1410 pattrib->hdrlen += IEEE80211_QOS_CTL_LEN;
1411
1412 if (pattrib->priority != 0 && pattrib->priority != 3) {
1413 adapter->recvpriv.bIsAnyNonBEPkts = true;
1414 }
1415 } else {
1416 pattrib->priority = 0;
1417 pattrib->ack_policy = 0;
1418 pattrib->amsdu = 0;
1419 }
1420
1421 if (pattrib->order) { /* HT-CTRL 11n */
1422 pattrib->hdrlen += 4;
1423 }
1424
1425 precv_frame->preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority];
1426
1427 /* decache, drop duplicate recv packets */
1428 if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) ==
1429 _FAIL) {
1430 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1431 ("decache : drop pkt\n"));
1432 ret = _FAIL;
1433 goto exit;
1434 }
1435
1436 if (pattrib->privacy) {
1437 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1438 ("validate_recv_data_frame:pattrib->privacy =%x\n",
1439 pattrib->privacy));
1440 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1441 ("\n ^^^^^^^^^^^is_multicast_ether_addr"
1442 "(pattrib->ra(0x%02x)) =%d^^^^^^^^^^^^^^^6\n",
1443 pattrib->ra[0],
1444 is_multicast_ether_addr(pattrib->ra)));
1445
1446 GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt,
1447 is_multicast_ether_addr(pattrib->ra));
1448
1449 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1450 ("\n pattrib->encrypt =%d\n", pattrib->encrypt));
1451
1452 switch (pattrib->encrypt)
1453 {
1454 case _WEP40_:
1455 case _WEP104_:
1456 pattrib->iv_len = 4;
1457 pattrib->icv_len = 4;
1458 break;
1459 case _TKIP_:
1460 pattrib->iv_len = 8;
1461 pattrib->icv_len = 4;
1462 break;
1463 case _AES_:
1464 pattrib->iv_len = 8;
1465 pattrib->icv_len = 8;
1466 break;
1467 case _SMS4_:
1468 pattrib->iv_len = 18;
1469 pattrib->icv_len = 16;
1470 break;
1471 default:
1472 pattrib->iv_len = 0;
1473 pattrib->icv_len = 0;
1474 break;
1475 }
1476 } else {
1477 pattrib->encrypt = 0;
1478 pattrib->iv_len = 0;
1479 pattrib->icv_len = 0;
1480 }
1481
1482exit:
1483
1484
1485
1486 return ret;
1487}
1488
1489static void dump_rx_pkt(struct sk_buff *skb, u16 type, int level)
1490{
1491 int i;
1492 u8 *ptr;
1493
1494 if ((level == 1) ||
1495 ((level == 2) && (type == IEEE80211_FTYPE_MGMT)) ||
1496 ((level == 3) && (type == IEEE80211_FTYPE_DATA))) {
1497
1498 ptr = skb->data;
1499
1500 DBG_8723A("#############################\n");
1501
1502 for (i = 0; i < 64; i = i + 8)
1503 DBG_8723A("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n",
1504 *(ptr + i), *(ptr + i + 1), *(ptr + i + 2),
1505 *(ptr + i + 3), *(ptr + i + 4),
1506 *(ptr + i + 5), *(ptr + i + 6),
1507 *(ptr + i + 7));
1508 DBG_8723A("#############################\n");
1509 }
1510}
1511
1512static int validate_recv_frame(struct rtw_adapter *adapter,
1513 struct recv_frame *precv_frame)
1514{
1515 /* shall check frame subtype, to / from ds, da, bssid */
1516
1517 /* then call check if rx seq/frag. duplicated. */
1518 u8 type;
1519 u8 subtype;
1520 int retval = _SUCCESS;
1521 struct rx_pkt_attrib *pattrib = & precv_frame->attrib;
1522 struct sk_buff *skb = precv_frame->pkt;
1523 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1524 u8 ver;
1525 u8 bDumpRxPkt;
1526 u16 seq_ctrl, fctl;
1527
1528 fctl = le16_to_cpu(hdr->frame_control);
1529 ver = fctl & IEEE80211_FCTL_VERS;
1530 type = fctl & IEEE80211_FCTL_FTYPE;
1531 subtype = fctl & IEEE80211_FCTL_STYPE;
1532
1533 /* add version chk */
1534 if (ver != 0) {
1535 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1536 ("validate_recv_data_frame fail! (ver!= 0)\n"));
1537 retval = _FAIL;
1538 goto exit;
1539 }
1540
1541 pattrib->to_fr_ds = get_tofr_ds(hdr->frame_control);
1542
1543 seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
1544 pattrib->frag_num = seq_ctrl & IEEE80211_SCTL_FRAG;
1545 pattrib->seq_num = seq_ctrl >> 4;
1546
1547 pattrib->pw_save = ieee80211_has_pm(hdr->frame_control);
1548 pattrib->mfrag = ieee80211_has_morefrags(hdr->frame_control);
1549 pattrib->mdata = ieee80211_has_moredata(hdr->frame_control);
1550 pattrib->privacy = ieee80211_has_protected(hdr->frame_control);
1551 pattrib->order = ieee80211_has_order(hdr->frame_control);
1552
1553 rtw_hal_get_def_var23a(adapter, HAL_DEF_DBG_DUMP_RXPKT, &bDumpRxPkt);
1554
1555 if (unlikely(bDumpRxPkt == 1))
1556 dump_rx_pkt(skb, type, bDumpRxPkt);
1557
1558 switch (type)
1559 {
1560 case IEEE80211_FTYPE_MGMT:
1561 retval = validate_recv_mgnt_frame(adapter, precv_frame);
1562 if (retval == _FAIL) {
1563 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1564 ("validate_recv_mgnt_frame fail\n"));
1565 }
1566 retval = _FAIL; /* only data frame return _SUCCESS */
1567 break;
1568 case IEEE80211_FTYPE_CTL:
1569 retval = validate_recv_ctrl_frame(adapter, precv_frame);
1570 if (retval == _FAIL) {
1571 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1572 ("validate_recv_ctrl_frame fail\n"));
1573 }
1574 retval = _FAIL; /* only data frame return _SUCCESS */
1575 break;
1576 case IEEE80211_FTYPE_DATA:
1577 rtw_led_control(adapter, LED_CTL_RX);
1578 pattrib->qos = (subtype & IEEE80211_STYPE_QOS_DATA) ? 1 : 0;
1579 retval = validate_recv_data_frame(adapter, precv_frame);
1580 if (retval == _FAIL) {
1581 struct recv_priv *precvpriv = &adapter->recvpriv;
1582 /* RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_data_frame fail\n")); */
1583 precvpriv->rx_drop++;
1584 }
1585 break;
1586 default:
1587 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1588 ("validate_recv_data_frame fail! type = 0x%x\n", type));
1589 retval = _FAIL;
1590 break;
1591 }
1592
1593exit:
1594 return retval;
1595}
1596
1597/* remove the wlanhdr and add the eth_hdr */
1598
1599static int wlanhdr_to_ethhdr (struct recv_frame *precvframe)
1600{
1601 u16 eth_type, len, hdrlen;
1602 u8 bsnaphdr;
1603 u8 *psnap;
1604
1605 int ret = _SUCCESS;
1606 struct rtw_adapter *adapter = precvframe->adapter;
1607 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1608
1609 struct sk_buff *skb = precvframe->pkt;
1610 u8 *ptr;
1611 struct rx_pkt_attrib *pattrib = &precvframe->attrib;
1612
1613
1614
1615 ptr = skb->data;
1616 hdrlen = pattrib->hdrlen;
1617 psnap = ptr + hdrlen;
1618 eth_type = (psnap[6] << 8) | psnap[7];
1619 /* convert hdr + possible LLC headers into Ethernet header */
1620 /* eth_type = (psnap_type[0] << 8) | psnap_type[1]; */
1621 if ((ether_addr_equal(psnap, rfc1042_header) &&
1622 eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
1623 ether_addr_equal(psnap, bridge_tunnel_header)) {
1624 /* remove RFC1042 or Bridge-Tunnel encapsulation
1625 and replace EtherType */
1626 bsnaphdr = true;
1627 hdrlen += SNAP_SIZE;
1628 } else {
1629 /* Leave Ethernet header part of hdr and full payload */
1630 bsnaphdr = false;
1631 eth_type = (psnap[0] << 8) | psnap[1];
1632 }
1633
1634 len = skb->len - hdrlen;
1635
1636 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1637 ("\n === pattrib->hdrlen: %x, pattrib->iv_len:%x ===\n\n",
1638 pattrib->hdrlen, pattrib->iv_len));
1639
1640 pattrib->eth_type = eth_type;
1641 if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)) {
1642 ptr += hdrlen;
1643 *ptr = 0x87;
1644 *(ptr + 1) = 0x12;
1645
1646 eth_type = 0x8712;
1647 /* append rx status for mp test packets */
1648
1649 ptr = skb_pull(skb, (hdrlen - sizeof(struct ethhdr) + 2) - 24);
1650 memcpy(ptr, skb->head, 24);
1651 ptr += 24;
1652 } else {
1653 ptr = skb_pull(skb, (hdrlen - sizeof(struct ethhdr) +
1654 (bsnaphdr ? 2:0)));
1655 }
1656
1657 ether_addr_copy(ptr, pattrib->dst);
1658 ether_addr_copy(ptr + ETH_ALEN, pattrib->src);
1659
1660 if (!bsnaphdr) {
1661 len = htons(len);
1662 memcpy(ptr + 12, &len, 2);
1663 }
1664
1665
1666 return ret;
1667}
1668
1669/* perform defrag */
1670struct recv_frame *recvframe_defrag(struct rtw_adapter *adapter,
1671 struct rtw_queue *defrag_q);
1672struct recv_frame *recvframe_defrag(struct rtw_adapter *adapter,
1673 struct rtw_queue *defrag_q)
1674{
1675 struct list_head *plist, *phead, *ptmp;
1676 u8 *data, wlanhdr_offset;
1677 u8 curfragnum;
1678 struct recv_frame *pnfhdr;
1679 struct recv_frame *prframe, *pnextrframe;
1680 struct rtw_queue *pfree_recv_queue;
1681 struct sk_buff *skb;
1682
1683
1684
1685 curfragnum = 0;
1686 pfree_recv_queue = &adapter->recvpriv.free_recv_queue;
1687
1688 phead = get_list_head(defrag_q);
1689 plist = phead->next;
1690 prframe = container_of(plist, struct recv_frame, list);
1691 list_del_init(&prframe->list);
1692 skb = prframe->pkt;
1693
1694 if (curfragnum != prframe->attrib.frag_num) {
1695 /* the first fragment number must be 0 */
1696 /* free the whole queue */
1697 rtw_free_recvframe23a(prframe, pfree_recv_queue);
1698 rtw_free_recvframe23a_queue(defrag_q, pfree_recv_queue);
1699
1700 return NULL;
1701 }
1702
1703 curfragnum++;
1704
1705 phead = get_list_head(defrag_q);
1706
1707 data = prframe->pkt->data;
1708
1709 list_for_each_safe(plist, ptmp, phead) {
1710 pnfhdr = container_of(plist, struct recv_frame, list);
1711 pnextrframe = (struct recv_frame *)pnfhdr;
1712 /* check the fragment sequence (2nd ~n fragment frame) */
1713
1714 if (curfragnum != pnfhdr->attrib.frag_num) {
1715 /* the fragment number must be increasing
1716 (after decache) */
1717 /* release the defrag_q & prframe */
1718 rtw_free_recvframe23a(prframe, pfree_recv_queue);
1719 rtw_free_recvframe23a_queue(defrag_q, pfree_recv_queue);
1720 return NULL;
1721 }
1722
1723 curfragnum++;
1724
1725 /* copy the 2nd~n fragment frame's payload to the
1726 first fragment */
1727 /* get the 2nd~last fragment frame's payload */
1728
1729 wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
1730
1731 skb_pull(pnfhdr->pkt, wlanhdr_offset);
1732
1733 /* append to first fragment frame's tail
1734 (if privacy frame, pull the ICV) */
1735
1736 skb_trim(skb, skb->len - prframe->attrib.icv_len);
1737
1738 memcpy(skb_tail_pointer(skb), pnfhdr->pkt->data,
1739 pnfhdr->pkt->len);
1740
1741 skb_put(skb, pnfhdr->pkt->len);
1742
1743 prframe->attrib.icv_len = pnfhdr->attrib.icv_len;
1744 };
1745
1746 /* free the defrag_q queue and return the prframe */
1747 rtw_free_recvframe23a_queue(defrag_q, pfree_recv_queue);
1748
1749 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1750 ("Performance defrag!!!!!\n"));
1751
1752
1753
1754 return prframe;
1755}
1756
1757/* check if need to defrag, if needed queue the frame to defrag_q */
1758struct recv_frame* recvframe_chk_defrag23a(struct rtw_adapter *padapter,
1759 struct recv_frame *precv_frame)
1760{
1761 u8 ismfrag;
1762 u8 fragnum;
1763 u8 *psta_addr;
1764 struct recv_frame *pfhdr;
1765 struct sta_info *psta;
1766 struct sta_priv *pstapriv;
1767 struct list_head *phead;
1768 struct recv_frame *prtnframe = NULL;
1769 struct rtw_queue *pfree_recv_queue, *pdefrag_q;
1770
1771
1772
1773 pstapriv = &padapter->stapriv;
1774
1775 pfhdr = precv_frame;
1776
1777 pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
1778
1779 /* need to define struct of wlan header frame ctrl */
1780 ismfrag = pfhdr->attrib.mfrag;
1781 fragnum = pfhdr->attrib.frag_num;
1782
1783 psta_addr = pfhdr->attrib.ta;
1784 psta = rtw_get_stainfo23a(pstapriv, psta_addr);
1785 if (!psta) {
1786 struct ieee80211_hdr *hdr =
1787 (struct ieee80211_hdr *) pfhdr->pkt->data;
1788 if (!ieee80211_is_data(hdr->frame_control)) {
1789 psta = rtw_get_bcmc_stainfo23a(padapter);
1790 pdefrag_q = &psta->sta_recvpriv.defrag_q;
1791 } else
1792 pdefrag_q = NULL;
1793 } else
1794 pdefrag_q = &psta->sta_recvpriv.defrag_q;
1795
1796 if ((ismfrag == 0) && (fragnum == 0)) {
1797 prtnframe = precv_frame;/* isn't a fragment frame */
1798 }
1799
1800 if (ismfrag == 1) {
1801 /* 0~(n-1) fragment frame */
1802 /* enqueue to defraf_g */
1803 if (pdefrag_q != NULL) {
1804 if (fragnum == 0) {
1805 /* the first fragment */
1806 if (_rtw_queue_empty23a(pdefrag_q) == false) {
1807 /* free current defrag_q */
1808 rtw_free_recvframe23a_queue(pdefrag_q, pfree_recv_queue);
1809 }
1810 }
1811
1812 /* Then enqueue the 0~(n-1) fragment into the
1813 defrag_q */
1814
1815 /* spin_lock(&pdefrag_q->lock); */
1816 phead = get_list_head(pdefrag_q);
1817 list_add_tail(&pfhdr->list, phead);
1818 /* spin_unlock(&pdefrag_q->lock); */
1819
1820 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1821 ("Enqueuq: ismfrag = %d, fragnum = %d\n",
1822 ismfrag, fragnum));
1823
1824 prtnframe = NULL;
1825
1826 } else {
1827 /* can't find this ta's defrag_queue,
1828 so free this recv_frame */
1829 rtw_free_recvframe23a(precv_frame, pfree_recv_queue);
1830 prtnframe = NULL;
1831 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1832 ("Free because pdefrag_q == NULL: ismfrag = "
1833 "%d, fragnum = %d\n", ismfrag, fragnum));
1834 }
1835 }
1836
1837 if ((ismfrag == 0) && (fragnum != 0)) {
1838 /* the last fragment frame */
1839 /* enqueue the last fragment */
1840 if (pdefrag_q != NULL) {
1841 /* spin_lock(&pdefrag_q->lock); */
1842 phead = get_list_head(pdefrag_q);
1843 list_add_tail(&pfhdr->list, phead);
1844 /* spin_unlock(&pdefrag_q->lock); */
1845
1846 /* call recvframe_defrag to defrag */
1847 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
1848 ("defrag: ismfrag = %d, fragnum = %d\n",
1849 ismfrag, fragnum));
1850 precv_frame = recvframe_defrag(padapter, pdefrag_q);
1851 prtnframe = precv_frame;
1852 } else {
1853 /* can't find this ta's defrag_queue,
1854 so free this recv_frame */
1855 rtw_free_recvframe23a(precv_frame, pfree_recv_queue);
1856 prtnframe = NULL;
1857 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1858 ("Free because pdefrag_q == NULL: ismfrag = "
1859 "%d, fragnum = %d\n", ismfrag, fragnum));
1860 }
1861
1862 }
1863
1864 if ((prtnframe != NULL) && (prtnframe->attrib.privacy)) {
1865 /* after defrag we must check tkip mic code */
1866 if (recvframe_chkmic(padapter, prtnframe) == _FAIL) {
1867 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
1868 ("recvframe_chkmic(padapter, prtnframe) =="
1869 "_FAIL\n"));
1870 rtw_free_recvframe23a(prtnframe, pfree_recv_queue);
1871 prtnframe = NULL;
1872 }
1873 }
1874
1875
1876
1877 return prtnframe;
1878}
1879
1880int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe);
1881int amsdu_to_msdu(struct rtw_adapter *padapter, struct recv_frame *prframe)
1882{
1883 struct rx_pkt_attrib *pattrib;
1884 struct sk_buff *skb, *sub_skb;
1885 struct sk_buff_head skb_list;
1886 struct recv_priv *precvpriv = &padapter->recvpriv;
1887 struct rtw_queue *pfree_recv_queue = &precvpriv->free_recv_queue;
1888
1889 pattrib = &prframe->attrib;
1890
1891 skb = prframe->pkt;
1892 skb_pull(skb, prframe->attrib.hdrlen);
1893 __skb_queue_head_init(&skb_list);
1894
1895 ieee80211_amsdu_to_8023s(skb, &skb_list, NULL, 0, 0, false);
1896
1897 while (!skb_queue_empty(&skb_list)) {
1898 sub_skb = __skb_dequeue(&skb_list);
1899
1900 sub_skb->protocol = eth_type_trans(sub_skb, padapter->pnetdev);
1901 sub_skb->dev = padapter->pnetdev;
1902
1903 sub_skb->ip_summed = CHECKSUM_NONE;
1904
1905 netif_rx(sub_skb);
1906 }
1907
1908 prframe->pkt = NULL;
1909 rtw_free_recvframe23a(prframe, pfree_recv_queue);
1910 return _SUCCESS;
1911}
1912
1913int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num);
1914int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num)
1915{
1916 u8 wsize = preorder_ctrl->wsize_b;
1917 u16 wend = (preorder_ctrl->indicate_seq + wsize -1) & 0xFFF;
1918
1919 /* Rx Reorder initialize condition. */
1920 if (preorder_ctrl->indicate_seq == 0xFFFF)
1921 preorder_ctrl->indicate_seq = seq_num;
1922
1923 /* Drop out the packet which SeqNum is smaller than WinStart */
1924 if (SN_LESS(seq_num, preorder_ctrl->indicate_seq))
1925 return false;
1926
1927 /* */
1928 /* Sliding window manipulation. Conditions includes: */
1929 /* 1. Incoming SeqNum is equal to WinStart =>Window shift 1 */
1930 /* 2. Incoming SeqNum is larger than the WinEnd => Window shift N */
1931 /* */
1932 if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq)) {
1933 preorder_ctrl->indicate_seq =
1934 (preorder_ctrl->indicate_seq + 1) & 0xFFF;
1935 } else if (SN_LESS(wend, seq_num)) {
1936 /* boundary situation, when seq_num cross 0xFFF */
1937 if (seq_num >= (wsize - 1))
1938 preorder_ctrl->indicate_seq = seq_num + 1 -wsize;
1939 else
1940 preorder_ctrl->indicate_seq = 0xFFF - (wsize - (seq_num + 1)) + 1;
1941 }
1942 return true;
1943}
1944
1945int enqueue_reorder_recvframe23a(struct recv_reorder_ctrl *preorder_ctrl,
1946 struct recv_frame *prframe)
1947{
1948 struct rx_pkt_attrib *pattrib = &prframe->attrib;
1949 struct rtw_queue *ppending_recvframe_queue;
1950 struct list_head *phead, *plist, *ptmp;
1951 struct recv_frame *hdr;
1952 struct rx_pkt_attrib *pnextattrib;
1953
1954 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
1955 /* DbgPrint("+enqueue_reorder_recvframe23a()\n"); */
1956
1957 /* spin_lock_irqsave(&ppending_recvframe_queue->lock); */
1958 /* spin_lock_ex(&ppending_recvframe_queue->lock); */
1959
1960 phead = get_list_head(ppending_recvframe_queue);
1961
1962 list_for_each_safe(plist, ptmp, phead) {
1963 hdr = container_of(plist, struct recv_frame, list);
1964 pnextattrib = &hdr->attrib;
1965
1966 if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num)) {
1967 continue;
1968 } else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) {
1969 /* Duplicate entry is found!! Do not insert current entry. */
1970 /* RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum)); */
1971
1972 /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock); */
1973 return false;
1974 } else {
1975 break;
1976 }
1977
1978 /* DbgPrint("enqueue_reorder_recvframe23a():while\n"); */
1979 }
1980
1981 /* spin_lock_irqsave(&ppending_recvframe_queue->lock); */
1982 /* spin_lock_ex(&ppending_recvframe_queue->lock); */
1983
1984 list_del_init(&prframe->list);
1985
1986 list_add_tail(&prframe->list, plist);
1987
1988 /* spin_unlock_ex(&ppending_recvframe_queue->lock); */
1989 /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock); */
1990
1991 /* RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum)); */
1992 return true;
1993}
1994
1995int recv_indicatepkts_in_order(struct rtw_adapter *padapter,
1996 struct recv_reorder_ctrl *preorder_ctrl,
1997 int bforced);
1998int recv_indicatepkts_in_order(struct rtw_adapter *padapter,
1999 struct recv_reorder_ctrl *preorder_ctrl,
2000 int bforced)
2001{
2002 /* u8 bcancelled; */
2003 struct list_head *phead, *plist;
2004 struct recv_frame *prframe;
2005 struct rx_pkt_attrib *pattrib;
2006 /* u8 index = 0; */
2007 int bPktInBuf = false;
2008 struct recv_priv *precvpriv;
2009 struct rtw_queue *ppending_recvframe_queue;
2010
2011 precvpriv = &padapter->recvpriv;
2012 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
2013 /* DbgPrint("+recv_indicatepkts_in_order\n"); */
2014
2015 /* spin_lock_irqsave(&ppending_recvframe_queue->lock); */
2016 /* spin_lock_ex(&ppending_recvframe_queue->lock); */
2017
2018 phead = get_list_head(ppending_recvframe_queue);
2019 plist = phead->next;
2020
2021 /* Handling some condition for forced indicate case. */
2022 if (bforced) {
2023 if (list_empty(phead)) {
2024 /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock); */
2025 /* spin_unlock_ex(&ppending_recvframe_queue->lock); */
2026 return true;
2027 }
2028
2029 prframe = container_of(plist, struct recv_frame, list);
2030 pattrib = &prframe->attrib;
2031 preorder_ctrl->indicate_seq = pattrib->seq_num;
2032 }
2033
2034 /* Prepare indication list and indication. */
2035 /* Check if there is any packet need indicate. */
2036 while (!list_empty(phead)) {
2037
2038 prframe = container_of(plist, struct recv_frame, list);
2039 pattrib = &prframe->attrib;
2040
2041 if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
2042 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2043 ("recv_indicatepkts_in_order: indicate =%d "
2044 "seq =%d amsdu =%d\n",
2045 preorder_ctrl->indicate_seq,
2046 pattrib->seq_num, pattrib->amsdu));
2047
2048 plist = plist->next;
2049 list_del_init(&prframe->list);
2050
2051 if (SN_EQUAL(preorder_ctrl->indicate_seq,
2052 pattrib->seq_num)) {
2053 preorder_ctrl->indicate_seq =
2054 (preorder_ctrl->indicate_seq + 1)&0xFFF;
2055 }
2056
2057 if (!pattrib->amsdu) {
2058 if ((padapter->bDriverStopped == false) &&
2059 (padapter->bSurpriseRemoved == false)) {
2060 rtw_recv_indicatepkt23a(padapter, prframe);
2061 }
2062 } else {
2063 if (amsdu_to_msdu(padapter, prframe) !=
2064 _SUCCESS) {
2065 rtw_free_recvframe23a(prframe,
2066 &precvpriv->free_recv_queue);
2067 }
2068 }
2069
2070 /* Update local variables. */
2071 bPktInBuf = false;
2072
2073 } else {
2074 bPktInBuf = true;
2075 break;
2076 }
2077
2078 /* DbgPrint("recv_indicatepkts_in_order():while\n"); */
2079 }
2080
2081 /* spin_unlock_ex(&ppending_recvframe_queue->lock); */
2082 /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock); */
2083
2084 return bPktInBuf;
2085}
2086
2087int recv_indicatepkt_reorder(struct rtw_adapter *padapter,
2088 struct recv_frame *prframe);
2089int recv_indicatepkt_reorder(struct rtw_adapter *padapter,
2090 struct recv_frame *prframe)
2091{
2092 int retval = _SUCCESS;
2093 struct rx_pkt_attrib *pattrib;
2094 struct recv_reorder_ctrl *preorder_ctrl;
2095 struct rtw_queue *ppending_recvframe_queue;
2096
2097 pattrib = &prframe->attrib;
2098 preorder_ctrl = prframe->preorder_ctrl;
2099 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
2100
2101 if (!pattrib->amsdu) {
2102 /* s1. */
2103 wlanhdr_to_ethhdr(prframe);
2104
2105 if ((pattrib->qos!= 1) || (pattrib->eth_type == 0x0806) ||
2106 (pattrib->ack_policy != 0)) {
2107 if ((padapter->bDriverStopped == false) &&
2108 (padapter->bSurpriseRemoved == false)) {
2109 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2110 ("@@@@ recv_indicatepkt_reorder -"
2111 "recv_func recv_indicatepkt\n"));
2112
2113 rtw_recv_indicatepkt23a(padapter, prframe);
2114 return _SUCCESS;
2115 }
2116
2117 return _FAIL;
2118 }
2119
2120 if (preorder_ctrl->enable == false) {
2121 /* indicate this recv_frame */
2122 preorder_ctrl->indicate_seq = pattrib->seq_num;
2123 rtw_recv_indicatepkt23a(padapter, prframe);
2124
2125 preorder_ctrl->indicate_seq =
2126 (preorder_ctrl->indicate_seq + 1) % 4096;
2127 return _SUCCESS;
2128 }
2129 } else {
2130 /* temp filter -> means didn't support A-MSDUs in a A-MPDU */
2131 if (preorder_ctrl->enable == false) {
2132 preorder_ctrl->indicate_seq = pattrib->seq_num;
2133 retval = amsdu_to_msdu(padapter, prframe);
2134
2135 preorder_ctrl->indicate_seq =
2136 (preorder_ctrl->indicate_seq + 1) % 4096;
2137 return retval;
2138 }
2139 }
2140
2141 spin_lock_bh(&ppending_recvframe_queue->lock);
2142
2143 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2144 ("recv_indicatepkt_reorder: indicate =%d seq =%d\n",
2145 preorder_ctrl->indicate_seq, pattrib->seq_num));
2146
2147 /* s2. check if winstart_b(indicate_seq) needs to been updated */
2148 if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) {
2149 goto _err_exit;
2150 }
2151
2152 /* s3. Insert all packet into Reorder Queue to maintain its ordering. */
2153 if (!enqueue_reorder_recvframe23a(preorder_ctrl, prframe)) {
2154 goto _err_exit;
2155 }
2156
2157 /* s4. */
2158 /* Indication process. */
2159 /* After Packet dropping and Sliding Window shifting as above,
2160 we can now just indicate the packets */
2161 /* with the SeqNum smaller than latest WinStart and buffer
2162 other packets. */
2163 /* */
2164 /* For Rx Reorder condition: */
2165 /* 1. All packets with SeqNum smaller than WinStart => Indicate */
2166 /* 2. All packets with SeqNum larger than or equal to WinStart =>
2167 Buffer it. */
2168 /* */
2169
2170 if (recv_indicatepkts_in_order(padapter, preorder_ctrl, false) == true) {
2171 mod_timer(&preorder_ctrl->reordering_ctrl_timer,
2172 jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
2173 spin_unlock_bh(&ppending_recvframe_queue->lock);
2174 } else {
2175 spin_unlock_bh(&ppending_recvframe_queue->lock);
2176 del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
2177 }
2178 return _SUCCESS;
2179
2180_err_exit:
2181
2182 spin_unlock_bh(&ppending_recvframe_queue->lock);
2183 return _FAIL;
2184}
2185
2186void rtw_reordering_ctrl_timeout_handler23a(unsigned long pcontext)
2187{
2188 struct recv_reorder_ctrl *preorder_ctrl;
2189 struct rtw_adapter *padapter;
2190 struct rtw_queue *ppending_recvframe_queue;
2191
2192 preorder_ctrl = (struct recv_reorder_ctrl *)pcontext;
2193 padapter = preorder_ctrl->padapter;
2194 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
2195
2196 if (padapter->bDriverStopped || padapter->bSurpriseRemoved) {
2197 return;
2198 }
2199
2200 /* DBG_8723A("+rtw_reordering_ctrl_timeout_handler23a() =>\n"); */
2201
2202 spin_lock_bh(&ppending_recvframe_queue->lock);
2203
2204 if (recv_indicatepkts_in_order(padapter, preorder_ctrl, true) == true) {
2205 mod_timer(&preorder_ctrl->reordering_ctrl_timer,
2206 jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
2207 }
2208
2209 spin_unlock_bh(&ppending_recvframe_queue->lock);
2210}
2211
2212int process_recv_indicatepkts(struct rtw_adapter *padapter,
2213 struct recv_frame *prframe);
2214int process_recv_indicatepkts(struct rtw_adapter *padapter,
2215 struct recv_frame *prframe)
2216{
2217 int retval = _SUCCESS;
2218 /* struct recv_priv *precvpriv = &padapter->recvpriv; */
2219 /* struct rx_pkt_attrib *pattrib = &prframe->attrib; */
2220 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2221 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2222
2223 if (phtpriv->ht_option == true) { /* B/G/N Mode */
2224 /* prframe->preorder_ctrl = &precvpriv->recvreorder_ctrl[pattrib->priority]; */
2225
2226 /* including perform A-MPDU Rx Ordering Buffer Control */
2227 if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) {
2228 if ((padapter->bDriverStopped == false) &&
2229 (padapter->bSurpriseRemoved == false)) {
2230 retval = _FAIL;
2231 return retval;
2232 }
2233 }
2234 } else /* B/G mode */
2235 {
2236 retval = wlanhdr_to_ethhdr(prframe);
2237 if (retval != _SUCCESS) {
2238 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2239 ("wlanhdr_to_ethhdr: drop pkt\n"));
2240 return retval;
2241 }
2242
2243 if ((padapter->bDriverStopped == false) &&
2244 (padapter->bSurpriseRemoved == false)) {
2245 /* indicate this recv_frame */
2246 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2247 ("@@@@ process_recv_indicatepkts- "
2248 "recv_func recv_indicatepkt\n"));
2249 rtw_recv_indicatepkt23a(padapter, prframe);
2250 } else {
2251 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2252 ("@@@@ process_recv_indicatepkts- "
2253 "recv_func free_indicatepkt\n"));
2254
2255 RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2256 ("recv_func:bDriverStopped(%d) OR "
2257 "bSurpriseRemoved(%d)",
2258 padapter->bDriverStopped,
2259 padapter->bSurpriseRemoved));
2260 retval = _FAIL;
2261 return retval;
2262 }
2263
2264 }
2265
2266 return retval;
2267}
2268
2269static int recv_func_prehandle(struct rtw_adapter *padapter,
2270 struct recv_frame *rframe)
2271{
2272 struct rtw_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
2273 int ret = _SUCCESS;
2274
2275 /* check the frame crtl field and decache */
2276 ret = validate_recv_frame(padapter, rframe);
2277 if (ret != _SUCCESS) {
2278 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
2279 ("recv_func: validate_recv_frame fail! drop pkt\n"));
2280 rtw_free_recvframe23a(rframe, pfree_recv_queue);
2281 goto exit;
2282 }
2283
2284exit:
2285 return ret;
2286}
2287
2288static int recv_func_posthandle(struct rtw_adapter *padapter,
2289 struct recv_frame *prframe)
2290{
2291 int ret = _SUCCESS;
2292 struct recv_frame *orig_prframe = prframe;
2293 struct recv_priv *precvpriv = &padapter->recvpriv;
2294 struct rtw_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
2295
2296 /* DATA FRAME */
2297 rtw_led_control(padapter, LED_CTL_RX);
2298
2299 prframe = decryptor(padapter, prframe);
2300 if (prframe == NULL) {
2301 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2302 ("decryptor: drop pkt\n"));
2303 ret = _FAIL;
2304 goto _recv_data_drop;
2305 }
2306
2307 prframe = recvframe_chk_defrag23a(padapter, prframe);
2308 if (!prframe) {
2309 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2310 ("recvframe_chk_defrag23a: drop pkt\n"));
2311 goto _recv_data_drop;
2312 }
2313
2314 /*
2315 * Pull off crypto headers
2316 */
2317 if (prframe->attrib.iv_len > 0) {
2318 skb_pull(prframe->pkt, prframe->attrib.iv_len);
2319 }
2320
2321 if (prframe->attrib.icv_len > 0) {
2322 skb_trim(prframe->pkt,
2323 prframe->pkt->len - prframe->attrib.icv_len);
2324 }
2325
2326 prframe = portctrl(padapter, prframe);
2327 if (!prframe) {
2328 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2329 ("portctrl: drop pkt\n"));
2330 ret = _FAIL;
2331 goto _recv_data_drop;
2332 }
2333
2334 count_rx_stats(padapter, prframe, NULL);
2335
2336 ret = process_recv_indicatepkts(padapter, prframe);
2337 if (ret != _SUCCESS) {
2338 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
2339 ("recv_func: process_recv_indicatepkts fail!\n"));
2340 rtw_free_recvframe23a(orig_prframe, pfree_recv_queue);/* free this recv_frame */
2341 goto _recv_data_drop;
2342 }
2343 return ret;
2344
2345_recv_data_drop:
2346 precvpriv->rx_drop++;
2347 return ret;
2348}
2349
2350int rtw_recv_entry23a(struct recv_frame *rframe)
2351{
2352 int ret, r;
2353 struct rtw_adapter *padapter = rframe->adapter;
2354 struct rx_pkt_attrib *prxattrib = &rframe->attrib;
2355 struct recv_priv *recvpriv = &padapter->recvpriv;
2356 struct security_priv *psecuritypriv = &padapter->securitypriv;
2357 struct mlme_priv *mlmepriv = &padapter->mlmepriv;
2358
2359 /* check if need to handle uc_swdec_pending_queue*/
2360 if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
2361 psecuritypriv->busetkipkey) {
2362 struct recv_frame *pending_frame;
2363
2364 while ((pending_frame = rtw_alloc_recvframe23a(&padapter->recvpriv.uc_swdec_pending_queue))) {
2365 r = recv_func_posthandle(padapter, pending_frame);
2366 if (r == _SUCCESS)
2367 DBG_8723A("%s: dequeue uc_swdec_pending_queue\n", __func__);
2368 }
2369 }
2370
2371 ret = recv_func_prehandle(padapter, rframe);
2372
2373 if (ret == _SUCCESS) {
2374 /* check if need to enqueue into uc_swdec_pending_queue*/
2375 if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
2376 !is_multicast_ether_addr(prxattrib->ra) &&
2377 prxattrib->encrypt > 0 &&
2378 (prxattrib->bdecrypted == 0) &&
2379 !is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm) &&
2380 !psecuritypriv->busetkipkey) {
2381 rtw_enqueue_recvframe23a(rframe, &padapter->recvpriv.uc_swdec_pending_queue);
2382 DBG_8723A("%s: no key, enqueue uc_swdec_pending_queue\n", __func__);
2383 goto exit;
2384 }
2385
2386 ret = recv_func_posthandle(padapter, rframe);
2387
2388 recvpriv->rx_pkts++;
2389 }
2390
2391exit:
2392 return ret;
2393}
2394
2395void rtw_signal_stat_timer_hdl23a(unsigned long data)
2396{
2397 struct rtw_adapter *adapter = (struct rtw_adapter *)data;
2398 struct recv_priv *recvpriv = &adapter->recvpriv;
2399
2400 u32 tmp_s, tmp_q;
2401 u8 avg_signal_strength = 0;
2402 u8 avg_signal_qual = 0;
2403 u32 num_signal_strength = 0;
2404 u32 num_signal_qual = 0;
2405 u8 _alpha = 3; /* this value is based on converging_constant = 5000 */
2406 /* and sampling_interval = 1000 */
2407
2408 if (adapter->recvpriv.is_signal_dbg) {
2409 /* update the user specific value, signal_strength_dbg, */
2410 /* to signal_strength, rssi */
2411 adapter->recvpriv.signal_strength =
2412 adapter->recvpriv.signal_strength_dbg;
2413 adapter->recvpriv.rssi =
2414 (s8)translate_percentage_to_dbm((u8)adapter->recvpriv.signal_strength_dbg);
2415 } else {
2416 if (recvpriv->signal_strength_data.update_req == 0) {
2417 /* update_req is clear, means we got rx */
2418 avg_signal_strength =
2419 recvpriv->signal_strength_data.avg_val;
2420 num_signal_strength =
2421 recvpriv->signal_strength_data.total_num;
2422 /* after avg_vals are accquired, we can re-stat */
2423 /* the signal values */
2424 recvpriv->signal_strength_data.update_req = 1;
2425 }
2426
2427 if (recvpriv->signal_qual_data.update_req == 0) {
2428 /* update_req is clear, means we got rx */
2429 avg_signal_qual = recvpriv->signal_qual_data.avg_val;
2430 num_signal_qual = recvpriv->signal_qual_data.total_num;
2431 /* after avg_vals are accquired, we can re-stat */
2432 /*the signal values */
2433 recvpriv->signal_qual_data.update_req = 1;
2434 }
2435
2436 /* update value of signal_strength, rssi, signal_qual */
2437 if (check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY) ==
2438 false) {
2439 tmp_s = (avg_signal_strength + (_alpha - 1) *
2440 recvpriv->signal_strength);
2441 if (tmp_s %_alpha)
2442 tmp_s = tmp_s / _alpha + 1;
2443 else
2444 tmp_s = tmp_s / _alpha;
2445 if (tmp_s > 100)
2446 tmp_s = 100;
2447
2448 tmp_q = (avg_signal_qual + (_alpha - 1) *
2449 recvpriv->signal_qual);
2450 if (tmp_q %_alpha)
2451 tmp_q = tmp_q / _alpha + 1;
2452 else
2453 tmp_q = tmp_q / _alpha;
2454 if (tmp_q > 100)
2455 tmp_q = 100;
2456
2457 recvpriv->signal_strength = tmp_s;
2458 recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s);
2459 recvpriv->signal_qual = tmp_q;
2460
2461 DBG_8723A("%s signal_strength:%3u, rssi:%3d, "
2462 "signal_qual:%3u, num_signal_strength:%u, "
2463 "num_signal_qual:%u\n",
2464 __func__, recvpriv->signal_strength,
2465 recvpriv->rssi, recvpriv->signal_qual,
2466 num_signal_strength, num_signal_qual
2467 );
2468 }
2469 }
2470 rtw_set_signal_stat_timer(recvpriv);
2471}
diff --git a/drivers/staging/rtl8723au/core/rtw_security.c b/drivers/staging/rtl8723au/core/rtw_security.c
new file mode 100644
index 000000000000..fd43e71bf6d6
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_security.c
@@ -0,0 +1,1652 @@
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 ******************************************************************************/
15#define _RTW_SECURITY_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <wifi.h>
20#include <osdep_intf.h>
21
22/* WEP related ===== */
23
24#define CRC32_POLY 0x04c11db7
25
26struct arc4context
27{
28 u32 x;
29 u32 y;
30 u8 state[256];
31};
32
33static void arcfour_init(struct arc4context *parc4ctx, u8 * key, u32 key_len)
34{
35 u32 t, u;
36 u32 keyindex;
37 u32 stateindex;
38 u8 * state;
39 u32 counter;
40
41 state = parc4ctx->state;
42 parc4ctx->x = 0;
43 parc4ctx->y = 0;
44 for (counter = 0; counter < 256; counter++)
45 state[counter] = (u8)counter;
46 keyindex = 0;
47 stateindex = 0;
48 for (counter = 0; counter < 256; counter++)
49 {
50 t = state[counter];
51 stateindex = (stateindex + key[keyindex] + t) & 0xff;
52 u = state[stateindex];
53 state[stateindex] = (u8)t;
54 state[counter] = (u8)u;
55 if (++keyindex >= key_len)
56 keyindex = 0;
57 }
58
59}
60static u32 arcfour_byte( struct arc4context *parc4ctx)
61{
62 u32 x;
63 u32 y;
64 u32 sx, sy;
65 u8 * state;
66
67 state = parc4ctx->state;
68 x = (parc4ctx->x + 1) & 0xff;
69 sx = state[x];
70 y = (sx + parc4ctx->y) & 0xff;
71 sy = state[y];
72 parc4ctx->x = x;
73 parc4ctx->y = y;
74 state[y] = (u8)sx;
75 state[x] = (u8)sy;
76
77 return state[(sx + sy) & 0xff];
78}
79
80static void arcfour_encrypt( struct arc4context *parc4ctx,
81 u8 * dest,
82 u8 * src,
83 u32 len)
84{
85 u32 i;
86
87 for (i = 0; i < len; i++)
88 dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx);
89
90}
91
92static int bcrc32initialized = 0;
93static u32 crc32_table[256];
94
95static u8 crc32_reverseBit(u8 data)
96{
97 u8 retval = ((data << 7) & 0x80) | ((data << 5) & 0x40) |
98 ((data << 3) & 0x20) | ((data << 1) & 0x10) |
99 ((data >> 1) & 0x08) | ((data >> 3) & 0x04) |
100 ((data >> 5) & 0x02) | ((data >> 7) & 0x01);
101 return retval;
102}
103
104static void crc32_init(void)
105{
106
107 if (bcrc32initialized == 1)
108 return;
109 else{
110 int i, j;
111 u32 c;
112 u8 *p = (u8 *)&c, *p1;
113 u8 k;
114
115 c = 0x12340000;
116
117 for (i = 0; i < 256; ++i)
118 {
119 k = crc32_reverseBit((u8)i);
120 for (c = ((u32)k) << 24, j = 8; j > 0; --j) {
121 c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1);
122 }
123 p1 = (u8 *)&crc32_table[i];
124
125 p1[0] = crc32_reverseBit(p[3]);
126 p1[1] = crc32_reverseBit(p[2]);
127 p1[2] = crc32_reverseBit(p[1]);
128 p1[3] = crc32_reverseBit(p[0]);
129 }
130 bcrc32initialized = 1;
131 }
132}
133
134static u32 getcrc32(u8 *buf, int len)
135{
136 u8 *p;
137 u32 crc;
138
139 if (bcrc32initialized == 0) crc32_init();
140
141 crc = 0xffffffff; /* preload shift register, per CRC-32 spec */
142
143 for (p = buf; len > 0; ++p, --len)
144 crc = crc32_table[ (crc ^ *p) & 0xff] ^ (crc >> 8);
145
146 return ~crc; /* transmit complement, per CRC-32 spec */
147}
148
149/* Need to consider the fragment situation */
150void rtw_wep_encrypt23a(struct rtw_adapter *padapter,
151 struct xmit_frame *pxmitframe)
152{
153 /* exclude ICV */
154 unsigned char crc[4];
155 struct arc4context mycontext;
156 int curfragnum, length, index;
157 u32 keylength;
158 u8 *pframe, *payload, *iv; /* wepkey */
159 u8 wepkey[16];
160 u8 hw_hdr_offset = 0;
161 struct pkt_attrib *pattrib = &pxmitframe->attrib;
162 struct security_priv *psecuritypriv = &padapter->securitypriv;
163 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
164
165 if (!pxmitframe->buf_addr)
166 return;
167
168 hw_hdr_offset = TXDESC_OFFSET;
169
170 pframe = pxmitframe->buf_addr + hw_hdr_offset;
171
172 /* start to encrypt each fragment */
173 if ((pattrib->encrypt != _WEP40_) && (pattrib->encrypt != _WEP104_))
174 return;
175
176 index = psecuritypriv->dot11PrivacyKeyIndex;
177 keylength = psecuritypriv->dot11DefKeylen[index];
178
179 for (curfragnum = 0; curfragnum < pattrib->nr_frags ; curfragnum++) {
180 iv = pframe + pattrib->hdrlen;
181 memcpy(&wepkey[0], iv, 3);
182 memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[index].skey[0],
183 keylength);
184 payload = pframe + pattrib->iv_len + pattrib->hdrlen;
185
186 if ((curfragnum + 1) == pattrib->nr_frags) {
187 /* the last fragment */
188 length = pattrib->last_txcmdsz - pattrib->hdrlen -
189 pattrib->iv_len- pattrib->icv_len;
190
191 *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));
192
193 arcfour_init(&mycontext, wepkey, 3 + keylength);
194 arcfour_encrypt(&mycontext, payload, payload, length);
195 arcfour_encrypt(&mycontext, payload + length, crc, 4);
196 } else {
197 length = pxmitpriv->frag_len - pattrib->hdrlen -
198 pattrib->iv_len - pattrib->icv_len;
199 *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));
200 arcfour_init(&mycontext, wepkey, 3 + keylength);
201 arcfour_encrypt(&mycontext, payload, payload, length);
202 arcfour_encrypt(&mycontext, payload + length, crc, 4);
203
204 pframe += pxmitpriv->frag_len;
205 pframe = PTR_ALIGN(pframe, 4);
206 }
207 }
208
209}
210
211void rtw_wep_decrypt23a(struct rtw_adapter *padapter,
212 struct recv_frame *precvframe)
213{
214 /* exclude ICV */
215 u8 crc[4];
216 struct arc4context mycontext;
217 int length;
218 u32 keylength;
219 u8 *pframe, *payload, *iv, wepkey[16];
220 u8 keyindex;
221 struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
222 struct security_priv *psecuritypriv = &padapter->securitypriv;
223 struct sk_buff * skb = precvframe->pkt;
224
225 pframe = skb->data;
226
227 /* start to decrypt recvframe */
228 if ((prxattrib->encrypt != _WEP40_) && (prxattrib->encrypt != _WEP104_))
229 return;
230
231 iv = pframe + prxattrib->hdrlen;
232 /* keyindex = (iv[3]&0x3); */
233 keyindex = prxattrib->key_index;
234 keylength = psecuritypriv->dot11DefKeylen[keyindex];
235 memcpy(&wepkey[0], iv, 3);
236 /* memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength); */
237 memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[keyindex].skey[0],
238 keylength);
239 length = skb->len - prxattrib->hdrlen - prxattrib->iv_len;
240
241 payload = pframe + prxattrib->iv_len + prxattrib->hdrlen;
242
243 /* decrypt payload include icv */
244 arcfour_init(&mycontext, wepkey, 3 + keylength);
245 arcfour_encrypt(&mycontext, payload, payload, length);
246
247 /* calculate icv and compare the icv */
248 *((u32 *)crc) = le32_to_cpu(getcrc32(payload, length - 4));
249
250 if (crc[3] != payload[length - 1] || crc[2] != payload[length - 2] ||
251 crc[1] != payload[length - 3] || crc[0] != payload[length - 4]) {
252 RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
253 ("rtw_wep_decrypt23a:icv error crc[3](%x)!= payload"
254 "[length-1](%x) || crc[2](%x)!= payload[length-2](%x)"
255 " || crc[1](%x)!= payload[length-3](%x) || crc[0](%x)"
256 "!= payload[length-4](%x)\n",
257 crc[3], payload[length - 1],
258 crc[2], payload[length - 2],
259 crc[1], payload[length - 3],
260 crc[0], payload[length - 4]));
261 }
262
263 return;
264}
265
266/* 3 ===== TKIP related ===== */
267
268static u32 secmicgetuint32(u8 * p)
269/* Convert from Byte[] to u32 in a portable way */
270{
271 s32 i;
272 u32 res = 0;
273
274 for (i = 0; i<4; i++)
275 {
276 res |= ((u32)(*p++)) << (8*i);
277 }
278
279 return res;
280}
281
282static void secmicputuint32(u8 * p, u32 val)
283/* Convert from long to Byte[] in a portable way */
284{
285 long i;
286
287 for (i = 0; i<4; i++)
288 {
289 *p++ = (u8) (val & 0xff);
290 val >>= 8;
291 }
292
293}
294
295static void secmicclear(struct mic_data *pmicdata)
296{
297/* Reset the state to the empty message. */
298
299 pmicdata->L = pmicdata->K0;
300 pmicdata->R = pmicdata->K1;
301 pmicdata->nBytesInM = 0;
302 pmicdata->M = 0;
303
304}
305
306void rtw_secmicsetkey23a(struct mic_data *pmicdata, u8 * key)
307{
308 /* Set the key */
309
310 pmicdata->K0 = secmicgetuint32(key);
311 pmicdata->K1 = secmicgetuint32(key + 4);
312 /* and reset the message */
313 secmicclear(pmicdata);
314
315}
316
317void rtw_secmicappend23abyte23a(struct mic_data *pmicdata, u8 b)
318{
319
320 /* Append the byte to our word-sized buffer */
321 pmicdata->M |= ((unsigned long)b) << (8*pmicdata->nBytesInM);
322 pmicdata->nBytesInM++;
323 /* Process the word if it is full. */
324 if (pmicdata->nBytesInM >= 4)
325 {
326 pmicdata->L ^= pmicdata->M;
327 pmicdata->R ^= ROL32(pmicdata->L, 17);
328 pmicdata->L += pmicdata->R;
329 pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | ((pmicdata->L & 0x00ff00ff) << 8);
330 pmicdata->L += pmicdata->R;
331 pmicdata->R ^= ROL32(pmicdata->L, 3);
332 pmicdata->L += pmicdata->R;
333 pmicdata->R ^= ROR32(pmicdata->L, 2);
334 pmicdata->L += pmicdata->R;
335 /* Clear the buffer */
336 pmicdata->M = 0;
337 pmicdata->nBytesInM = 0;
338 }
339
340}
341
342void rtw_secmicappend23a(struct mic_data *pmicdata, u8 * src, u32 nbytes)
343{
344
345 /* This is simple */
346 while(nbytes > 0)
347 {
348 rtw_secmicappend23abyte23a(pmicdata, *src++);
349 nbytes--;
350 }
351
352}
353
354void rtw_secgetmic23a(struct mic_data *pmicdata, u8 * dst)
355{
356
357 /* Append the minimum padding */
358 rtw_secmicappend23abyte23a(pmicdata, 0x5a);
359 rtw_secmicappend23abyte23a(pmicdata, 0);
360 rtw_secmicappend23abyte23a(pmicdata, 0);
361 rtw_secmicappend23abyte23a(pmicdata, 0);
362 rtw_secmicappend23abyte23a(pmicdata, 0);
363 /* and then zeroes until the length is a multiple of 4 */
364 while(pmicdata->nBytesInM != 0)
365 {
366 rtw_secmicappend23abyte23a(pmicdata, 0);
367 }
368 /* The appendByte function has already computed the result. */
369 secmicputuint32(dst, pmicdata->L);
370 secmicputuint32(dst+4, pmicdata->R);
371 /* Reset to the empty message. */
372 secmicclear(pmicdata);
373
374}
375
376void rtw_seccalctkipmic23a(u8 * key, u8 *header, u8 *data, u32 data_len, u8 *mic_code, u8 pri)
377{
378
379 struct mic_data micdata;
380 u8 priority[4]={0x0, 0x0, 0x0, 0x0};
381
382 rtw_secmicsetkey23a(&micdata, key);
383 priority[0]= pri;
384
385 /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
386 if (header[1]&1) { /* ToDS == 1 */
387 rtw_secmicappend23a(&micdata, &header[16], 6); /* DA */
388 if (header[1]&2) /* From Ds == 1 */
389 rtw_secmicappend23a(&micdata, &header[24], 6);
390 else
391 rtw_secmicappend23a(&micdata, &header[10], 6);
392 }
393 else{ /* ToDS == 0 */
394 rtw_secmicappend23a(&micdata, &header[4], 6); /* DA */
395 if (header[1]&2) /* From Ds == 1 */
396 rtw_secmicappend23a(&micdata, &header[16], 6);
397 else
398 rtw_secmicappend23a(&micdata, &header[10], 6);
399
400 }
401 rtw_secmicappend23a(&micdata, &priority[0], 4);
402
403 rtw_secmicappend23a(&micdata, data, data_len);
404
405 rtw_secgetmic23a(&micdata, mic_code);
406
407}
408
409/* macros for extraction/creation of unsigned char/unsigned short values */
410#define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15))
411#define Lo8(v16) ((u8)((v16) & 0x00FF))
412#define Hi8(v16) ((u8)(((v16) >> 8) & 0x00FF))
413#define Lo16(v32) ((u16)((v32) & 0xFFFF))
414#define Hi16(v32) ((u16)(((v32) >>16) & 0xFFFF))
415#define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8))
416
417/* select the Nth 16-bit word of the temporal key unsigned char array TK[] */
418#define TK16(N) Mk16(tk[2*(N)+1], tk[2*(N)])
419
420/* S-box lookup: 16 bits --> 16 bits */
421#define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)])
422
423/* fixed algorithm "parameters" */
424#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */
425#define TA_SIZE 6 /* 48-bit transmitter address */
426#define TK_SIZE 16 /* 128-bit temporal key */
427#define P1K_SIZE 10 /* 80-bit Phase1 key */
428#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */
429
430/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */
431static const unsigned short Sbox1[2][256]= /* Sbox for hash (can be in ROM) */
432{ {
433 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
434 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
435 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
436 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
437 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
438 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
439 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
440 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
441 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
442 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
443 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
444 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
445 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
446 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
447 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
448 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
449 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
450 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
451 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
452 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
453 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
454 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
455 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
456 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
457 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
458 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
459 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
460 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
461 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
462 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
463 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
464 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
465 },
466
467 { /* second half of table is unsigned char-reversed version of first! */
468 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,
469 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,
470 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,
471 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,
472 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,
473 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,
474 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,
475 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,
476 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,
477 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,
478 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,
479 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,
480 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,
481 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,
482 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,
483 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,
484 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,
485 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,
486 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,
487 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,
488 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,
489 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,
490 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,
491 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,
492 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,
493 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,
494 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,
495 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,
496 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,
497 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,
498 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,
499 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C,
500 }
501};
502
503 /*
504**********************************************************************
505* Routine: Phase 1 -- generate P1K, given TA, TK, IV32
506*
507* Inputs:
508* tk[] = temporal key [128 bits]
509* ta[] = transmitter's MAC address [ 48 bits]
510* iv32 = upper 32 bits of IV [ 32 bits]
511* Output:
512* p1k[] = Phase 1 key [ 80 bits]
513*
514* Note:
515* This function only needs to be called every 2**16 packets,
516* although in theory it could be called every packet.
517*
518**********************************************************************
519*/
520static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
521{
522 int i;
523
524 /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */
525 p1k[0] = Lo16(iv32);
526 p1k[1] = Hi16(iv32);
527 p1k[2] = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */
528 p1k[3] = Mk16(ta[3], ta[2]);
529 p1k[4] = Mk16(ta[5], ta[4]);
530
531 /* Now compute an unbalanced Feistel cipher with 80-bit block */
532 /* size on the 80-bit block P1K[], using the 128-bit key TK[] */
533 for (i = 0; i < PHASE1_LOOP_CNT ;i++)
534 { /* Each add operation here is mod 2**16 */
535 p1k[0] += _S_(p1k[4] ^ TK16((i&1)+0));
536 p1k[1] += _S_(p1k[0] ^ TK16((i&1)+2));
537 p1k[2] += _S_(p1k[1] ^ TK16((i&1)+4));
538 p1k[3] += _S_(p1k[2] ^ TK16((i&1)+6));
539 p1k[4] += _S_(p1k[3] ^ TK16((i&1)+0));
540 p1k[4] += (unsigned short)i; /* avoid "slide attacks" */
541 }
542
543}
544
545/*
546**********************************************************************
547* Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16
548*
549* Inputs:
550* tk[] = Temporal key [128 bits]
551* p1k[] = Phase 1 output key [ 80 bits]
552* iv16 = low 16 bits of IV counter [ 16 bits]
553* Output:
554* rc4key[] = the key used to encrypt the packet [128 bits]
555*
556* Note:
557* The value {TA, IV32, IV16} for Phase1/Phase2 must be unique
558* across all packets using the same key TK value. Then, for a
559* given value of TK[], this TKIP48 construction guarantees that
560* the final RC4KEY value is unique across all packets.
561*
562* Suggested implementation optimization: if PPK[] is "overlaid"
563* appropriately on RC4KEY[], there is no need for the final
564* for loop below that copies the PPK[] result into RC4KEY[].
565*
566**********************************************************************
567*/
568static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16)
569{
570 int i;
571 u16 PPK[6]; /* temporary key for mixing */
572
573 /* Note: all adds in the PPK[] equations below are mod 2**16 */
574 for (i = 0;i<5;i++) PPK[i]= p1k[i]; /* first, copy P1K to PPK */
575 PPK[5] = p1k[4] +iv16; /* next, add in IV16 */
576
577 /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */
578 PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */
579 PPK[1] += _S_(PPK[0] ^ TK16(1));
580 PPK[2] += _S_(PPK[1] ^ TK16(2));
581 PPK[3] += _S_(PPK[2] ^ TK16(3));
582 PPK[4] += _S_(PPK[3] ^ TK16(4));
583 PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */
584
585 /* Final sweep: bijective, "linear". Rotates kill LSB correlations */
586 PPK[0] += RotR1(PPK[5] ^ TK16(6));
587 PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */
588 PPK[2] += RotR1(PPK[1]);
589 PPK[3] += RotR1(PPK[2]);
590 PPK[4] += RotR1(PPK[3]);
591 PPK[5] += RotR1(PPK[4]);
592 /* Note: At this point, for a given key TK[0..15], the 96-bit output */
593 /* value PPK[0..5] is guaranteed to be unique, as a function */
594 /* of the 96-bit "input" value {TA, IV32, IV16}. That is, P1K */
595 /* is now a keyed permutation of {TA, IV32, IV16}. */
596
597 /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */
598 rc4key[0] = Hi8(iv16); /* RC4KEY[0..2] is the WEP IV */
599 rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */
600 rc4key[2] = Lo8(iv16);
601 rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1);
602
603 /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */
604 for (i = 0;i<6;i++)
605 {
606 rc4key[4+2*i] = Lo8(PPK[i]);
607 rc4key[5+2*i] = Hi8(PPK[i]);
608 }
609
610}
611
612/* The hlen isn't include the IV */
613u32 rtw_tkip_encrypt23a(struct rtw_adapter *padapter,
614 struct xmit_frame *pxmitframe)
615{ /* exclude ICV */
616 u16 pnl;
617 u32 pnh;
618 u8 rc4key[16];
619 u8 ttkey[16];
620 u8 crc[4];
621 u8 hw_hdr_offset = 0;
622 struct arc4context mycontext;
623 int curfragnum, length;
624 u32 prwskeylen;
625
626 u8 *pframe, *payload,*iv,*prwskey;
627 union pn48 dot11txpn;
628 struct sta_info *stainfo;
629 struct pkt_attrib *pattrib = &pxmitframe->attrib;
630 struct security_priv *psecuritypriv = &padapter->securitypriv;
631 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
632 u32 res = _SUCCESS;
633
634 if (!pxmitframe->buf_addr)
635 return _FAIL;
636
637 hw_hdr_offset = TXDESC_OFFSET;
638
639 pframe = pxmitframe->buf_addr + hw_hdr_offset;
640 /* 4 start to encrypt each fragment */
641 if (pattrib->encrypt == _TKIP_) {
642
643 if (pattrib->psta)
644 {
645 stainfo = pattrib->psta;
646 }
647 else
648 {
649 DBG_8723A("%s, call rtw_get_stainfo()\n", __func__);
650 stainfo = rtw_get_stainfo23a(&padapter->stapriv,
651 &pattrib->ra[0]);
652 }
653
654 if (stainfo!= NULL) {
655
656 if (!(stainfo->state &_FW_LINKED))
657 {
658 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state);
659 return _FAIL;
660 }
661
662 RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_encrypt23a: stainfo!= NULL!!!\n"));
663
664 if (is_multicast_ether_addr(pattrib->ra))
665 prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
666 else
667 prwskey = &stainfo->dot118021x_UncstKey.skey[0];
668
669 prwskeylen = 16;
670
671 for (curfragnum = 0;curfragnum<pattrib->nr_frags;curfragnum++) {
672 iv = pframe+pattrib->hdrlen;
673 payload = pframe+pattrib->iv_len+pattrib->hdrlen;
674
675 GET_TKIP_PN(iv, dot11txpn);
676
677 pnl = (u16)(dot11txpn.val);
678 pnh = (u32)(dot11txpn.val>>16);
679
680 phase1((u16 *)&ttkey[0], prwskey,&pattrib->ta[0], pnh);
681
682 phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl);
683
684 if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */
685 length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len- pattrib->icv_len;
686 RT_TRACE(_module_rtl871x_security_c_, _drv_info_, ("pattrib->iv_len =%x, pattrib->icv_len =%x\n", pattrib->iv_len, pattrib->icv_len));
687 *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));/* modified by Amy*/
688
689 arcfour_init(&mycontext, rc4key, 16);
690 arcfour_encrypt(&mycontext, payload, payload, length);
691 arcfour_encrypt(&mycontext, payload+length, crc, 4);
692
693 }
694 else{
695 length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len ;
696 *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));/* modified by Amy*/
697 arcfour_init(&mycontext, rc4key, 16);
698 arcfour_encrypt(&mycontext, payload, payload, length);
699 arcfour_encrypt(&mycontext, payload+length, crc, 4);
700
701 pframe+= pxmitpriv->frag_len;
702 pframe = PTR_ALIGN(pframe, 4);
703 }
704 }
705
706 }
707 else{
708 RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_encrypt23a: stainfo == NULL!!!\n"));
709 DBG_8723A("%s, psta == NUL\n", __func__);
710 res = _FAIL;
711 }
712
713 }
714
715 return res;
716}
717
718/* The hlen isn't include the IV */
719u32 rtw_tkip_decrypt23a(struct rtw_adapter *padapter,
720 struct recv_frame *precvframe)
721{
722 /* exclude ICV */
723 u16 pnl;
724 u32 pnh;
725 u8 rc4key[16];
726 u8 ttkey[16];
727 u8 crc[4];
728 struct arc4context mycontext;
729 int length;
730 u32 prwskeylen;
731 u8 *pframe, *payload,*iv,*prwskey;
732 union pn48 dot11txpn;
733 struct sta_info *stainfo;
734 struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
735 struct security_priv *psecuritypriv = &padapter->securitypriv;
736 struct sk_buff * skb = precvframe->pkt;
737 u32 res = _SUCCESS;
738
739 pframe = skb->data;
740
741 /* 4 start to decrypt recvframe */
742 if (prxattrib->encrypt == _TKIP_) {
743
744 stainfo = rtw_get_stainfo23a(&padapter->stapriv,
745 &prxattrib->ta[0]);
746 if (stainfo!= NULL) {
747
748 if (is_multicast_ether_addr(prxattrib->ra)) {
749 if (psecuritypriv->binstallGrpkey == false) {
750 res = _FAIL;
751 DBG_8723A("%s:rx bc/mc packets, but didn't install group key!!!!!!!!!!\n", __func__);
752 goto exit;
753 }
754 prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
755 prwskeylen = 16;
756 } else {
757 RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_decrypt23a: stainfo!= NULL!!!\n"));
758 prwskey = &stainfo->dot118021x_UncstKey.skey[0];
759 prwskeylen = 16;
760 }
761
762 iv = pframe+prxattrib->hdrlen;
763 payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
764 length = skb->len - prxattrib->hdrlen-prxattrib->iv_len;
765
766 GET_TKIP_PN(iv, dot11txpn);
767
768 pnl = (u16)(dot11txpn.val);
769 pnh = (u32)(dot11txpn.val>>16);
770
771 phase1((u16 *)&ttkey[0], prwskey,&prxattrib->ta[0], pnh);
772 phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl);
773
774 /* 4 decrypt payload include icv */
775 arcfour_init(&mycontext, rc4key, 16);
776 arcfour_encrypt(&mycontext, payload, payload, length);
777
778 *((u32 *)crc) = le32_to_cpu(getcrc32(payload, length-4));
779
780 if (crc[3]!= payload[length-1] || crc[2]!= payload[length-2] || crc[1]!= payload[length-3] || crc[0]!= payload[length-4])
781 {
782 RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_wep_decrypt23a:icv error crc[3](%x)!= payload[length-1](%x) || crc[2](%x)!= payload[length-2](%x) || crc[1](%x)!= payload[length-3](%x) || crc[0](%x)!= payload[length-4](%x)\n",
783 crc[3], payload[length-1], crc[2], payload[length-2], crc[1], payload[length-3], crc[0], payload[length-4]));
784 res = _FAIL;
785 }
786 } else {
787 RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_decrypt23a: stainfo == NULL!!!\n"));
788 res = _FAIL;
789 }
790 }
791exit:
792 return res;
793}
794
795/* 3 ===== AES related ===== */
796
797#define MAX_MSG_SIZE 2048
798/*****************************/
799/******** SBOX Table *********/
800/*****************************/
801
802static u8 sbox_table[256] = {
803 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
804 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
805 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
806 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
807 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
808 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
809 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
810 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
811 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
812 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
813 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
814 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
815 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
816 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
817 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
818 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
819 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
820 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
821 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
822 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
823 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
824 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
825 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
826 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
827 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
828 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
829 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
830 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
831 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
832 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
833 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
834 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
835};
836
837/*****************************/
838/**** Function Prototypes ****/
839/*****************************/
840
841static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, int a4_exists,
842 int qc_exists);
843
844static void xor_128(u8 *a, u8 *b, u8 *out)
845{
846 int i;
847
848 for (i = 0;i<16; i++)
849 out[i] = a[i] ^ b[i];
850}
851
852static void xor_32(u8 *a, u8 *b, u8 *out)
853{
854 int i;
855
856 for (i = 0; i < 4; i++)
857 out[i] = a[i] ^ b[i];
858}
859
860static u8 sbox(u8 a)
861{
862 return sbox_table[(int)a];
863}
864
865static void next_key(u8 *key, int round)
866{
867 u8 rcon;
868 u8 sbox_key[4];
869 u8 rcon_table[12] =
870 {
871 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
872 0x1b, 0x36, 0x36, 0x36
873 };
874
875 sbox_key[0] = sbox(key[13]);
876 sbox_key[1] = sbox(key[14]);
877 sbox_key[2] = sbox(key[15]);
878 sbox_key[3] = sbox(key[12]);
879
880 rcon = rcon_table[round];
881
882 xor_32(&key[0], sbox_key, &key[0]);
883 key[0] = key[0] ^ rcon;
884
885 xor_32(&key[4], &key[0], &key[4]);
886 xor_32(&key[8], &key[4], &key[8]);
887 xor_32(&key[12], &key[8], &key[12]);
888
889}
890
891static void byte_sub(u8 *in, u8 *out)
892{
893 int i;
894
895 for (i = 0; i< 16; i++)
896 {
897 out[i] = sbox(in[i]);
898 }
899
900}
901
902static void shift_row(u8 *in, u8 *out)
903{
904
905 out[0] = in[0];
906 out[1] = in[5];
907 out[2] = in[10];
908 out[3] = in[15];
909 out[4] = in[4];
910 out[5] = in[9];
911 out[6] = in[14];
912 out[7] = in[3];
913 out[8] = in[8];
914 out[9] = in[13];
915 out[10] = in[2];
916 out[11] = in[7];
917 out[12] = in[12];
918 out[13] = in[1];
919 out[14] = in[6];
920 out[15] = in[11];
921
922}
923
924static void mix_column(u8 *in, u8 *out)
925{
926 int i;
927 u8 add1b[4];
928 u8 add1bf7[4];
929 u8 rotl[4];
930 u8 swap_halfs[4];
931 u8 andf7[4];
932 u8 rotr[4];
933 u8 temp[4];
934 u8 tempb[4];
935
936 for (i = 0 ; i<4; i++)
937 {
938 if ((in[i] & 0x80) == 0x80)
939 add1b[i] = 0x1b;
940 else
941 add1b[i] = 0x00;
942 }
943
944 swap_halfs[0] = in[2]; /* Swap halfs */
945 swap_halfs[1] = in[3];
946 swap_halfs[2] = in[0];
947 swap_halfs[3] = in[1];
948
949 rotl[0] = in[3]; /* Rotate left 8 bits */
950 rotl[1] = in[0];
951 rotl[2] = in[1];
952 rotl[3] = in[2];
953
954 andf7[0] = in[0] & 0x7f;
955 andf7[1] = in[1] & 0x7f;
956 andf7[2] = in[2] & 0x7f;
957 andf7[3] = in[3] & 0x7f;
958
959 for (i = 3; i>0; i--) /* logical shift left 1 bit */
960 {
961 andf7[i] = andf7[i] << 1;
962 if ((andf7[i-1] & 0x80) == 0x80)
963 {
964 andf7[i] = (andf7[i] | 0x01);
965 }
966 }
967 andf7[0] = andf7[0] << 1;
968 andf7[0] = andf7[0] & 0xfe;
969
970 xor_32(add1b, andf7, add1bf7);
971
972 xor_32(in, add1bf7, rotr);
973
974 temp[0] = rotr[0]; /* Rotate right 8 bits */
975 rotr[0] = rotr[1];
976 rotr[1] = rotr[2];
977 rotr[2] = rotr[3];
978 rotr[3] = temp[0];
979
980 xor_32(add1bf7, rotr, temp);
981 xor_32(swap_halfs, rotl, tempb);
982 xor_32(temp, tempb, out);
983
984}
985
986static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext)
987{
988 int round;
989 int i;
990 u8 intermediatea[16];
991 u8 intermediateb[16];
992 u8 round_key[16];
993
994 for (i = 0; i<16; i++) round_key[i] = key[i];
995
996 for (round = 0; round < 11; round++)
997 {
998 if (round == 0)
999 {
1000 xor_128(round_key, data, ciphertext);
1001 next_key(round_key, round);
1002 }
1003 else if (round == 10)
1004 {
1005 byte_sub(ciphertext, intermediatea);
1006 shift_row(intermediatea, intermediateb);
1007 xor_128(intermediateb, round_key, ciphertext);
1008 }
1009 else /* 1 - 9 */
1010 {
1011 byte_sub(ciphertext, intermediatea);
1012 shift_row(intermediatea, intermediateb);
1013 mix_column(&intermediateb[0], &intermediatea[0]);
1014 mix_column(&intermediateb[4], &intermediatea[4]);
1015 mix_column(&intermediateb[8], &intermediatea[8]);
1016 mix_column(&intermediateb[12], &intermediatea[12]);
1017 xor_128(intermediatea, round_key, ciphertext);
1018 next_key(round_key, round);
1019 }
1020 }
1021
1022}
1023
1024/************************************************/
1025/* construct_mic_iv() */
1026/* Builds the MIC IV from header fields and PN */
1027/************************************************/
1028static void construct_mic_iv(u8 *mic_iv, int qc_exists, int a4_exists, u8 *mpdu,
1029 uint payload_length, u8 *pn_vector)
1030{
1031 int i;
1032
1033 mic_iv[0] = 0x59;
1034 if (qc_exists && a4_exists)
1035 mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */
1036 if (qc_exists && !a4_exists)
1037 mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */
1038 if (!qc_exists)
1039 mic_iv[1] = 0x00;
1040 for (i = 2; i < 8; i++)
1041 mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */
1042 for (i = 8; i < 14; i++)
1043 mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */
1044 mic_iv[14] = (unsigned char)(payload_length / 256);
1045 mic_iv[15] = (unsigned char)(payload_length % 256);
1046}
1047
1048/************************************************/
1049/* construct_mic_header1() */
1050/* Builds the first MIC header block from */
1051/* header fields. */
1052/************************************************/
1053static void construct_mic_header1(u8 *mic_header1, int header_length, u8 *mpdu)
1054{
1055 mic_header1[0] = (u8)((header_length - 2) / 256);
1056 mic_header1[1] = (u8)((header_length - 2) % 256);
1057 mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */
1058 mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */
1059 mic_header1[4] = mpdu[4]; /* A1 */
1060 mic_header1[5] = mpdu[5];
1061 mic_header1[6] = mpdu[6];
1062 mic_header1[7] = mpdu[7];
1063 mic_header1[8] = mpdu[8];
1064 mic_header1[9] = mpdu[9];
1065 mic_header1[10] = mpdu[10]; /* A2 */
1066 mic_header1[11] = mpdu[11];
1067 mic_header1[12] = mpdu[12];
1068 mic_header1[13] = mpdu[13];
1069 mic_header1[14] = mpdu[14];
1070 mic_header1[15] = mpdu[15];
1071
1072}
1073
1074/************************************************/
1075 /* construct_mic_header2() */
1076/* Builds the last MIC header block from */
1077/* header fields. */
1078/************************************************/
1079static void construct_mic_header2(
1080 u8 *mic_header2,
1081 u8 *mpdu,
1082 int a4_exists,
1083 int qc_exists
1084 )
1085{
1086 int i;
1087
1088 for (i = 0; i<16; i++) mic_header2[i]= 0x00;
1089
1090 mic_header2[0] = mpdu[16]; /* A3 */
1091 mic_header2[1] = mpdu[17];
1092 mic_header2[2] = mpdu[18];
1093 mic_header2[3] = mpdu[19];
1094 mic_header2[4] = mpdu[20];
1095 mic_header2[5] = mpdu[21];
1096
1097 mic_header2[6] = 0x00;
1098 mic_header2[7] = 0x00; /* mpdu[23]; */
1099
1100 if (!qc_exists && a4_exists)
1101 {
1102 for (i = 0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */
1103
1104 }
1105
1106 if (qc_exists && !a4_exists)
1107 {
1108 mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */
1109 mic_header2[9] = mpdu[25] & 0x00;
1110 }
1111
1112 if (qc_exists && a4_exists)
1113 {
1114 for (i = 0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */
1115
1116 mic_header2[14] = mpdu[30] & 0x0f;
1117 mic_header2[15] = mpdu[31] & 0x00;
1118 }
1119
1120}
1121
1122/************************************************/
1123/* construct_mic_header2() */
1124/* Builds the last MIC header block from */
1125/* header fields. */
1126/************************************************/
1127static void construct_ctr_preload(u8 *ctr_preload, int a4_exists, int qc_exists,
1128 u8 *mpdu, u8 *pn_vector, int c)
1129{
1130 int i = 0;
1131
1132 for (i = 0; i<16; i++) ctr_preload[i] = 0x00;
1133 i = 0;
1134
1135 ctr_preload[0] = 0x01; /* flag */
1136 if (qc_exists && a4_exists)
1137 ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */
1138 if (qc_exists && !a4_exists)
1139 ctr_preload[1] = mpdu[24] & 0x0f;
1140
1141 for (i = 2; i < 8; i++)
1142 ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */
1143 for (i = 8; i < 14; i++)
1144 ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */
1145 ctr_preload[14] = (unsigned char) (c / 256); /* Ctr */
1146 ctr_preload[15] = (unsigned char) (c % 256);
1147
1148}
1149
1150/************************************/
1151/* bitwise_xor() */
1152/* A 128 bit, bitwise exclusive or */
1153/************************************/
1154static void bitwise_xor(u8 *ina, u8 *inb, u8 *out)
1155{
1156 int i;
1157
1158 for (i = 0; i < 16; i++)
1159 out[i] = ina[i] ^ inb[i];
1160}
1161
1162static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen)
1163{
1164 uint qc_exists, a4_exists, i, j, payload_remainder,
1165 num_blocks, payload_index;
1166 u8 pn_vector[6];
1167 u8 mic_iv[16];
1168 u8 mic_header1[16];
1169 u8 mic_header2[16];
1170 u8 ctr_preload[16];
1171 /* Intermediate Buffers */
1172 u8 chain_buffer[16];
1173 u8 aes_out[16];
1174 u8 padded_buffer[16];
1175 u8 mic[8];
1176 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe;
1177 u16 frsubtype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE;
1178
1179 memset((void *)mic_iv, 0, 16);
1180 memset((void *)mic_header1, 0, 16);
1181 memset((void *)mic_header2, 0, 16);
1182 memset((void *)ctr_preload, 0, 16);
1183 memset((void *)chain_buffer, 0, 16);
1184 memset((void *)aes_out, 0, 16);
1185 memset((void *)padded_buffer, 0, 16);
1186
1187 if ((hdrlen == sizeof(struct ieee80211_hdr_3addr) ||
1188 (hdrlen == sizeof(struct ieee80211_qos_hdr))))
1189 a4_exists = 0;
1190 else
1191 a4_exists = 1;
1192
1193 if (ieee80211_is_data(hdr->frame_control)) {
1194 if ((frsubtype == IEEE80211_STYPE_DATA_CFACK) ||
1195 (frsubtype == IEEE80211_STYPE_DATA_CFPOLL) ||
1196 (frsubtype == IEEE80211_STYPE_DATA_CFACKPOLL)) {
1197 qc_exists = 1;
1198 if (hdrlen != sizeof(struct ieee80211_qos_hdr))
1199 hdrlen += 2;
1200 } else if ((frsubtype == IEEE80211_STYPE_QOS_DATA) ||
1201 (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACK) ||
1202 (frsubtype == IEEE80211_STYPE_QOS_DATA_CFPOLL) ||
1203 (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACKPOLL)) {
1204 if (hdrlen != sizeof(struct ieee80211_qos_hdr))
1205 hdrlen += 2;
1206 qc_exists = 1;
1207 } else {
1208 qc_exists = 0;
1209 }
1210 } else {
1211 qc_exists = 0;
1212 }
1213 pn_vector[0]= pframe[hdrlen];
1214 pn_vector[1]= pframe[hdrlen+1];
1215 pn_vector[2]= pframe[hdrlen+4];
1216 pn_vector[3]= pframe[hdrlen+5];
1217 pn_vector[4]= pframe[hdrlen+6];
1218 pn_vector[5]= pframe[hdrlen+7];
1219
1220 construct_mic_iv(mic_iv, qc_exists, a4_exists, pframe, plen, pn_vector);
1221
1222 construct_mic_header1(mic_header1, hdrlen, pframe);
1223 construct_mic_header2(mic_header2, pframe, a4_exists, qc_exists);
1224
1225 payload_remainder = plen % 16;
1226 num_blocks = plen / 16;
1227
1228 /* Find start of payload */
1229 payload_index = (hdrlen + 8);
1230
1231 /* Calculate MIC */
1232 aes128k128d(key, mic_iv, aes_out);
1233 bitwise_xor(aes_out, mic_header1, chain_buffer);
1234 aes128k128d(key, chain_buffer, aes_out);
1235 bitwise_xor(aes_out, mic_header2, chain_buffer);
1236 aes128k128d(key, chain_buffer, aes_out);
1237
1238 for (i = 0; i < num_blocks; i++) {
1239 bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
1240
1241 payload_index += 16;
1242 aes128k128d(key, chain_buffer, aes_out);
1243 }
1244
1245 /* Add on the final payload block if it needs padding */
1246 if (payload_remainder > 0) {
1247 for (j = 0; j < 16; j++)
1248 padded_buffer[j] = 0x00;
1249 for (j = 0; j < payload_remainder; j++)
1250 padded_buffer[j] = pframe[payload_index++];
1251 bitwise_xor(aes_out, padded_buffer, chain_buffer);
1252 aes128k128d(key, chain_buffer, aes_out);
1253 }
1254
1255 for (j = 0; j < 8; j++)
1256 mic[j] = aes_out[j];
1257
1258 /* Insert MIC into payload */
1259 for (j = 0; j < 8; j++)
1260 pframe[payload_index+j] = mic[j];
1261
1262 payload_index = hdrlen + 8;
1263 for (i = 0; i < num_blocks; i++) {
1264 construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
1265 pframe, pn_vector, i+1);
1266 aes128k128d(key, ctr_preload, aes_out);
1267 bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
1268 for (j = 0; j < 16; j++)
1269 pframe[payload_index++] = chain_buffer[j];
1270 }
1271
1272 if (payload_remainder > 0) {
1273 /* If there is a short final block, then pad it,
1274 * encrypt it and copy the unpadded part back
1275 */
1276 construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe,
1277 pn_vector, num_blocks+1);
1278
1279 for (j = 0; j < 16; j++)
1280 padded_buffer[j] = 0x00;
1281 for (j = 0; j < payload_remainder; j++)
1282 padded_buffer[j] = pframe[payload_index+j];
1283 aes128k128d(key, ctr_preload, aes_out);
1284 bitwise_xor(aes_out, padded_buffer, chain_buffer);
1285 for (j = 0; j < payload_remainder;j++)
1286 pframe[payload_index++] = chain_buffer[j];
1287 }
1288
1289 /* Encrypt the MIC */
1290 construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe,
1291 pn_vector, 0);
1292
1293 for (j = 0; j < 16; j++)
1294 padded_buffer[j] = 0x00;
1295 for (j = 0; j < 8; j++)
1296 padded_buffer[j] = pframe[j+hdrlen+8+plen];
1297
1298 aes128k128d(key, ctr_preload, aes_out);
1299 bitwise_xor(aes_out, padded_buffer, chain_buffer);
1300 for (j = 0; j < 8;j++)
1301 pframe[payload_index++] = chain_buffer[j];
1302
1303 return _SUCCESS;
1304}
1305
1306u32 rtw_aes_encrypt23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
1307{ /* exclude ICV */
1308 /* Intermediate Buffers */
1309 int curfragnum, length;
1310 u32 prwskeylen;
1311 u8 *pframe, *prwskey; /* *payload,*iv */
1312 u8 hw_hdr_offset = 0;
1313 struct sta_info *stainfo;
1314 struct pkt_attrib *pattrib = &pxmitframe->attrib;
1315 struct security_priv *psecuritypriv = &padapter->securitypriv;
1316 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1317 u32 res = _SUCCESS;
1318
1319 if (!pxmitframe->buf_addr)
1320 return _FAIL;
1321
1322 hw_hdr_offset = TXDESC_OFFSET;
1323
1324 pframe = pxmitframe->buf_addr + hw_hdr_offset;
1325
1326 /* 4 start to encrypt each fragment */
1327 if (pattrib->encrypt != _AES_)
1328 return _FAIL;
1329
1330 if (pattrib->psta) {
1331 stainfo = pattrib->psta;
1332 } else {
1333 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
1334 stainfo = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]);
1335 }
1336
1337 if (!stainfo) {
1338 RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
1339 ("rtw_aes_encrypt23a: stainfo == NULL!!!\n"));
1340 DBG_8723A("%s, psta == NUL\n", __func__);
1341 res = _FAIL;
1342 goto out;
1343 }
1344 if (!(stainfo->state &_FW_LINKED)) {
1345 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n",
1346 __func__, stainfo->state);
1347 return _FAIL;
1348 }
1349 RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
1350 ("rtw_aes_encrypt23a: stainfo!= NULL!!!\n"));
1351
1352 if (is_multicast_ether_addr(pattrib->ra))
1353 prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
1354 else
1355 prwskey = &stainfo->dot118021x_UncstKey.skey[0];
1356
1357 prwskeylen = 16;
1358
1359 for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
1360 /* 4 the last fragment */
1361 if ((curfragnum + 1) == pattrib->nr_frags) {
1362 length = pattrib->last_txcmdsz -
1363 pattrib->hdrlen-pattrib->iv_len -
1364 pattrib->icv_len;
1365
1366 aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
1367 } else {
1368 length = pxmitpriv->frag_len-pattrib->hdrlen -
1369 pattrib->iv_len - pattrib->icv_len;
1370
1371 aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
1372 pframe += pxmitpriv->frag_len;
1373 pframe = PTR_ALIGN(pframe, 4);
1374 }
1375 }
1376out:
1377 return res;
1378}
1379
1380static int aes_decipher(u8 *key, uint hdrlen,
1381 u8 *pframe, uint plen)
1382{
1383 static u8 message[MAX_MSG_SIZE];
1384 uint qc_exists, a4_exists, i, j, payload_remainder,
1385 num_blocks, payload_index;
1386 int res = _SUCCESS;
1387 u8 pn_vector[6];
1388 u8 mic_iv[16];
1389 u8 mic_header1[16];
1390 u8 mic_header2[16];
1391 u8 ctr_preload[16];
1392 /* Intermediate Buffers */
1393 u8 chain_buffer[16];
1394 u8 aes_out[16];
1395 u8 padded_buffer[16];
1396 u8 mic[8];
1397 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)pframe;
1398 u16 frsubtype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE;
1399
1400 memset((void *)mic_iv, 0, 16);
1401 memset((void *)mic_header1, 0, 16);
1402 memset((void *)mic_header2, 0, 16);
1403 memset((void *)ctr_preload, 0, 16);
1404 memset((void *)chain_buffer, 0, 16);
1405 memset((void *)aes_out, 0, 16);
1406 memset((void *)padded_buffer, 0, 16);
1407
1408 /* start to decrypt the payload */
1409
1410 num_blocks = (plen-8) / 16; /* plen including llc, payload_length and mic) */
1411
1412 payload_remainder = (plen-8) % 16;
1413
1414 pn_vector[0] = pframe[hdrlen];
1415 pn_vector[1] = pframe[hdrlen+1];
1416 pn_vector[2] = pframe[hdrlen+4];
1417 pn_vector[3] = pframe[hdrlen+5];
1418 pn_vector[4] = pframe[hdrlen+6];
1419 pn_vector[5] = pframe[hdrlen+7];
1420
1421 if ((hdrlen == sizeof(struct ieee80211_hdr_3addr) ||
1422 (hdrlen == sizeof(struct ieee80211_qos_hdr))))
1423 a4_exists = 0;
1424 else
1425 a4_exists = 1;
1426
1427 if (ieee80211_is_data(hdr->frame_control)) {
1428 if ((frsubtype == IEEE80211_STYPE_DATA_CFACK) ||
1429 (frsubtype == IEEE80211_STYPE_DATA_CFPOLL) ||
1430 (frsubtype == IEEE80211_STYPE_DATA_CFACKPOLL)) {
1431 qc_exists = 1;
1432 if (hdrlen != sizeof(struct ieee80211_hdr_3addr))
1433 hdrlen += 2;
1434 } else if ((frsubtype == IEEE80211_STYPE_QOS_DATA) ||
1435 (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACK) ||
1436 (frsubtype == IEEE80211_STYPE_QOS_DATA_CFPOLL) ||
1437 (frsubtype == IEEE80211_STYPE_QOS_DATA_CFACKPOLL)) {
1438 if (hdrlen != sizeof(struct ieee80211_hdr_3addr))
1439 hdrlen += 2;
1440 qc_exists = 1;
1441 } else {
1442 qc_exists = 0;
1443 }
1444 } else {
1445 qc_exists = 0;
1446 }
1447
1448 /* now, decrypt pframe with hdrlen offset and plen long */
1449
1450 payload_index = hdrlen + 8; /* 8 is for extiv */
1451
1452 for (i = 0; i < num_blocks; i++) {
1453 construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
1454 pframe, pn_vector, i+1);
1455
1456 aes128k128d(key, ctr_preload, aes_out);
1457 bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
1458
1459 for (j = 0; j < 16; j++)
1460 pframe[payload_index++] = chain_buffer[j];
1461 }
1462
1463 if (payload_remainder > 0) {
1464 /* If there is a short final block, then pad it,
1465 * encrypt it and copy the unpadded part back
1466 */
1467 construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe,
1468 pn_vector, num_blocks+1);
1469
1470 for (j = 0; j < 16; j++)
1471 padded_buffer[j] = 0x00;
1472 for (j = 0; j < payload_remainder; j++)
1473 padded_buffer[j] = pframe[payload_index+j];
1474 aes128k128d(key, ctr_preload, aes_out);
1475 bitwise_xor(aes_out, padded_buffer, chain_buffer);
1476 for (j = 0; j < payload_remainder; j++)
1477 pframe[payload_index++] = chain_buffer[j];
1478 }
1479
1480 /* start to calculate the mic */
1481 if ((hdrlen +plen+8) <= MAX_MSG_SIZE)
1482 memcpy(message, pframe, (hdrlen+plen+8)); /* 8 is for ext iv len */
1483
1484 pn_vector[0] = pframe[hdrlen];
1485 pn_vector[1] = pframe[hdrlen+1];
1486 pn_vector[2] = pframe[hdrlen+4];
1487 pn_vector[3] = pframe[hdrlen+5];
1488 pn_vector[4] = pframe[hdrlen+6];
1489 pn_vector[5] = pframe[hdrlen+7];
1490
1491 construct_mic_iv(mic_iv, qc_exists, a4_exists, message,
1492 plen-8, pn_vector);
1493
1494 construct_mic_header1(mic_header1, hdrlen, message);
1495 construct_mic_header2(mic_header2, message, a4_exists, qc_exists);
1496
1497 payload_remainder = (plen-8) % 16;
1498 num_blocks = (plen-8) / 16;
1499
1500 /* Find start of payload */
1501 payload_index = (hdrlen + 8);
1502
1503 /* Calculate MIC */
1504 aes128k128d(key, mic_iv, aes_out);
1505 bitwise_xor(aes_out, mic_header1, chain_buffer);
1506 aes128k128d(key, chain_buffer, aes_out);
1507 bitwise_xor(aes_out, mic_header2, chain_buffer);
1508 aes128k128d(key, chain_buffer, aes_out);
1509
1510 for (i = 0; i < num_blocks; i++) {
1511 bitwise_xor(aes_out, &message[payload_index], chain_buffer);
1512
1513 payload_index += 16;
1514 aes128k128d(key, chain_buffer, aes_out);
1515 }
1516
1517 /* Add on the final payload block if it needs padding */
1518 if (payload_remainder > 0) {
1519 for (j = 0; j < 16; j++)
1520 padded_buffer[j] = 0x00;
1521 for (j = 0; j < payload_remainder; j++)
1522 padded_buffer[j] = message[payload_index++];
1523 bitwise_xor(aes_out, padded_buffer, chain_buffer);
1524 aes128k128d(key, chain_buffer, aes_out);
1525 }
1526
1527 for (j = 0 ; j < 8; j++)
1528 mic[j] = aes_out[j];
1529
1530 /* Insert MIC into payload */
1531 for (j = 0; j < 8; j++)
1532 message[payload_index+j] = mic[j];
1533
1534 payload_index = hdrlen + 8;
1535 for (i = 0; i< num_blocks; i++) {
1536 construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
1537 message, pn_vector, i+1);
1538 aes128k128d(key, ctr_preload, aes_out);
1539 bitwise_xor(aes_out, &message[payload_index], chain_buffer);
1540 for (j = 0; j < 16; j++)
1541 message[payload_index++] = chain_buffer[j];
1542 }
1543
1544 if (payload_remainder > 0) {
1545 /* If there is a short final block, then pad it,
1546 * encrypt it and copy the unpadded part back
1547 */
1548 construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
1549 message, pn_vector, num_blocks+1);
1550
1551 for (j = 0; j < 16; j++)
1552 padded_buffer[j] = 0x00;
1553 for (j = 0; j < payload_remainder; j++)
1554 padded_buffer[j] = message[payload_index+j];
1555 aes128k128d(key, ctr_preload, aes_out);
1556 bitwise_xor(aes_out, padded_buffer, chain_buffer);
1557 for (j = 0; j < payload_remainder; j++)
1558 message[payload_index++] = chain_buffer[j];
1559 }
1560
1561 /* Encrypt the MIC */
1562 construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message,
1563 pn_vector, 0);
1564
1565 for (j = 0; j < 16; j++)
1566 padded_buffer[j] = 0x00;
1567 for (j = 0; j < 8; j++)
1568 padded_buffer[j] = message[j+hdrlen+8+plen-8];
1569
1570 aes128k128d(key, ctr_preload, aes_out);
1571 bitwise_xor(aes_out, padded_buffer, chain_buffer);
1572 for (j = 0; j < 8; j++)
1573 message[payload_index++] = chain_buffer[j];
1574
1575 /* compare the mic */
1576 for (i = 0; i < 8; i++) {
1577 if (pframe[hdrlen+8+plen-8+i] != message[hdrlen+8+plen-8+i]) {
1578 RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
1579 ("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x)\n",
1580 i, pframe[hdrlen+8+plen-8+i], message[hdrlen+8+plen-8+i]));
1581 DBG_8723A("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x)\n",
1582 i, pframe[hdrlen+8+plen-8+i], message[hdrlen+8+plen-8+i]);
1583 res = _FAIL;
1584 }
1585 }
1586 return res;
1587}
1588
1589u32 rtw_aes_decrypt23a(struct rtw_adapter *padapter, struct recv_frame *precvframe)
1590{ /* exclude ICV */
1591 struct sta_info *stainfo;
1592 struct rx_pkt_attrib *prxattrib = &precvframe->attrib;
1593 struct security_priv *psecuritypriv = &padapter->securitypriv;
1594 struct sk_buff *skb = precvframe->pkt;
1595 int length;
1596 u8 *pframe, *prwskey; /* *payload,*iv */
1597 u32 res = _SUCCESS;
1598
1599 pframe = skb->data;
1600 /* 4 start to encrypt each fragment */
1601 if (prxattrib->encrypt != _AES_)
1602 return _FAIL;
1603
1604 stainfo = rtw_get_stainfo23a(&padapter->stapriv, &prxattrib->ta[0]);
1605 if (!stainfo) {
1606 RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
1607 ("rtw_aes_encrypt23a: stainfo == NULL!!!\n"));
1608 res = _FAIL;
1609 goto exit;
1610 }
1611
1612 RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
1613 ("rtw_aes_decrypt23a: stainfo!= NULL!!!\n"));
1614
1615 if (is_multicast_ether_addr(prxattrib->ra)) {
1616 /* in concurrent we should use sw decrypt in group key,
1617 so we remove this message */
1618 if (!psecuritypriv->binstallGrpkey) {
1619 res = _FAIL;
1620 DBG_8723A("%s:rx bc/mc packets, but didn't install "
1621 "group key!!!!!!!!!!\n", __func__);
1622 goto exit;
1623 }
1624 prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
1625 if (psecuritypriv->dot118021XGrpKeyid != prxattrib->key_index) {
1626 DBG_8723A("not match packet_index =%d, install_index ="
1627 "%d\n", prxattrib->key_index,
1628 psecuritypriv->dot118021XGrpKeyid);
1629 res = _FAIL;
1630 goto exit;
1631 }
1632 } else {
1633 prwskey = &stainfo->dot118021x_UncstKey.skey[0];
1634 }
1635
1636 length = skb->len - prxattrib->hdrlen - prxattrib->iv_len;
1637
1638 res = aes_decipher(prwskey, prxattrib->hdrlen, pframe, length);
1639exit:
1640 return res;
1641}
1642
1643void rtw_use_tkipkey_handler23a(void *FunctionContext)
1644{
1645 struct rtw_adapter *padapter = (struct rtw_adapter *)FunctionContext;
1646
1647 RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("^^^rtw_use_tkipkey_handler23a ^^^\n"));
1648 padapter->securitypriv.busetkipkey = true;
1649 RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
1650 ("^^^rtw_use_tkipkey_handler23a padapter->securitypriv.busetkipkey =%d^^^\n",
1651 padapter->securitypriv.busetkipkey));
1652}
diff --git a/drivers/staging/rtl8723au/core/rtw_sreset.c b/drivers/staging/rtl8723au/core/rtw_sreset.c
new file mode 100644
index 000000000000..4f7459203390
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_sreset.c
@@ -0,0 +1,255 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15
16#include<rtw_sreset.h>
17
18void sreset_init_value23a(struct rtw_adapter *padapter)
19{
20 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
21 struct sreset_priv *psrtpriv = &pHalData->srestpriv;
22
23 mutex_init(&psrtpriv->silentreset_mutex);
24 psrtpriv->silent_reset_inprogress = false;
25 psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
26 psrtpriv->last_tx_time = 0;
27 psrtpriv->last_tx_complete_time = 0;
28}
29void sreset_reset_value23a(struct rtw_adapter *padapter)
30{
31 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
32 struct sreset_priv *psrtpriv = &pHalData->srestpriv;
33
34 psrtpriv->silent_reset_inprogress = false;
35 psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
36 psrtpriv->last_tx_time = 0;
37 psrtpriv->last_tx_complete_time = 0;
38}
39
40u8 sreset_get_wifi_status23a(struct rtw_adapter *padapter)
41{
42 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
43 struct sreset_priv *psrtpriv = &pHalData->srestpriv;
44 u8 status = WIFI_STATUS_SUCCESS;
45 u32 val32 = 0;
46
47 if (psrtpriv->silent_reset_inprogress)
48 return status;
49 val32 = rtw_read32(padapter, REG_TXDMA_STATUS);
50 if (val32 == 0xeaeaeaea) {
51 psrtpriv->Wifi_Error_Status = WIFI_IF_NOT_EXIST;
52 } else if (val32 != 0) {
53 DBG_8723A("txdmastatu(%x)\n", val32);
54 psrtpriv->Wifi_Error_Status = WIFI_MAC_TXDMA_ERROR;
55 }
56
57 if (WIFI_STATUS_SUCCESS != psrtpriv->Wifi_Error_Status) {
58 DBG_8723A("==>%s error_status(0x%x)\n", __func__, psrtpriv->Wifi_Error_Status);
59 status = (psrtpriv->Wifi_Error_Status &~(USB_READ_PORT_FAIL|USB_WRITE_PORT_FAIL));
60 }
61 DBG_8723A("==> %s wifi_status(0x%x)\n", __func__, status);
62
63 /* status restore */
64 psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
65
66 return status;
67}
68
69void sreset_set_wifi_error_status23a(struct rtw_adapter *padapter, u32 status)
70{
71 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
72
73 pHalData->srestpriv.Wifi_Error_Status = status;
74}
75
76void sreset_set_trigger_point(struct rtw_adapter *padapter, s32 tgp)
77{
78 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
79
80 pHalData->srestpriv.dbg_trigger_point = tgp;
81}
82
83bool sreset_inprogress(struct rtw_adapter *padapter)
84{
85 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
86
87 return pHalData->srestpriv.silent_reset_inprogress;
88}
89
90static void sreset_restore_security_station(struct rtw_adapter *padapter)
91{
92 struct mlme_priv *mlmepriv = &padapter->mlmepriv;
93 struct sta_priv *pstapriv = &padapter->stapriv;
94 struct sta_info *psta;
95 struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info;
96 u8 val8;
97
98 if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X)
99 val8 = 0xcc;
100 else
101 val8 = 0xcf;
102 rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
103
104 if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
105 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {
106 psta = rtw_get_stainfo23a(pstapriv, get_bssid(mlmepriv));
107 if (psta == NULL) {
108 /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
109 } else {
110 /* pairwise key */
111 rtw_setstakey_cmd23a(padapter, (unsigned char *)psta, true);
112 /* group key */
113 rtw_set_key23a(padapter,&padapter->securitypriv, padapter->securitypriv.dot118021XGrpKeyid, 0);
114 }
115 }
116}
117
118static void sreset_restore_network_station(struct rtw_adapter *padapter)
119{
120 struct mlme_priv *mlmepriv = &padapter->mlmepriv;
121 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
122 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
123 u8 threshold;
124
125 rtw_setopmode_cmd23a(padapter, Ndis802_11Infrastructure);
126
127 /* TH = 1 => means that invalidate usb rx aggregation */
128 /* TH = 0 => means that validate usb rx aggregation, use init value. */
129 if (mlmepriv->htpriv.ht_option) {
130 if (padapter->registrypriv.wifi_spec == 1)
131 threshold = 1;
132 else
133 threshold = 0;
134 rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
135 } else {
136 threshold = 1;
137 rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
138 }
139
140 set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
141
142 /* disable dynamic functions, such as high power, DIG */
143 /* Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DISABLE, false); */
144
145 rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
146
147 {
148 u8 join_type = 0;
149 rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
150 }
151
152 Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
153
154 mlmeext_joinbss_event_callback23a(padapter, 1);
155 /* restore Sequence No. */
156 rtw_write8(padapter, 0x4dc, padapter->xmitpriv.nqos_ssn);
157
158 sreset_restore_security_station(padapter);
159}
160
161static void sreset_restore_network_status(struct rtw_adapter *padapter)
162{
163 struct mlme_priv *mlmepriv = &padapter->mlmepriv;
164
165 if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) {
166 DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_STATION_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
167 sreset_restore_network_station(padapter);
168#ifdef CONFIG_8723AU_AP_MODE
169 } else if (check_fwstate(mlmepriv, WIFI_AP_STATE)) {
170 DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_AP_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
171 rtw_ap_restore_network(padapter);
172#endif
173 } else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE)) {
174 DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_ADHOC_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
175 } else {
176 DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - ???\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
177 }
178}
179
180static void sreset_stop_adapter(struct rtw_adapter *padapter)
181{
182 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
183 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
184
185 if (padapter == NULL)
186 return;
187
188 DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
189
190 if (!rtw_netif_queue_stopped(padapter->pnetdev))
191 netif_tx_stop_all_queues(padapter->pnetdev);
192
193 rtw_cancel_all_timer23a(padapter);
194
195 /* TODO: OS and HCI independent */
196 tasklet_kill(&pxmitpriv->xmit_tasklet);
197
198 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
199 rtw_scan_abort23a(padapter);
200
201 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
202 rtw23a_join_to_handler((unsigned long)padapter);
203}
204
205static void sreset_start_adapter(struct rtw_adapter *padapter)
206{
207 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
208 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
209
210 if (padapter == NULL)
211 return;
212
213 DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
214
215 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
216 sreset_restore_network_status(padapter);
217 }
218
219 /* TODO: OS and HCI independent */
220 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
221
222 mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
223 jiffies + msecs_to_jiffies(2000));
224
225 if (rtw_netif_queue_stopped(padapter->pnetdev))
226 netif_tx_wake_all_queues(padapter->pnetdev);
227}
228
229void sreset_reset(struct rtw_adapter *padapter)
230{
231 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
232 struct sreset_priv *psrtpriv = &pHalData->srestpriv;
233 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
234 unsigned long start = jiffies;
235
236 DBG_8723A("%s\n", __func__);
237
238 psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
239
240 mutex_lock(&psrtpriv->silentreset_mutex);
241 psrtpriv->silent_reset_inprogress = true;
242 pwrpriv->change_rfpwrstate = rf_off;
243
244 sreset_stop_adapter(padapter);
245
246 ips_enter23a(padapter);
247 ips_leave23a(padapter);
248
249 sreset_start_adapter(padapter);
250 psrtpriv->silent_reset_inprogress = false;
251 mutex_unlock(&psrtpriv->silentreset_mutex);
252
253 DBG_8723A("%s done in %d ms\n", __func__,
254 jiffies_to_msecs(jiffies - start));
255}
diff --git a/drivers/staging/rtl8723au/core/rtw_sta_mgt.c b/drivers/staging/rtl8723au/core/rtw_sta_mgt.c
new file mode 100644
index 000000000000..451b58f47287
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_sta_mgt.c
@@ -0,0 +1,509 @@
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 ******************************************************************************/
15#define _RTW_STA_MGT_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <recv_osdep.h>
20#include <xmit_osdep.h>
21#include <mlme_osdep.h>
22#include <sta_info.h>
23
24void _rtw_init_stainfo(struct sta_info *psta)
25{
26 memset((u8 *)psta, 0, sizeof (struct sta_info));
27 spin_lock_init(&psta->lock);
28 INIT_LIST_HEAD(&psta->list);
29 INIT_LIST_HEAD(&psta->hash_list);
30 _rtw_init_queue23a(&psta->sleep_q);
31 psta->sleepq_len = 0;
32 _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv);
33 _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv);
34#ifdef CONFIG_8723AU_AP_MODE
35 INIT_LIST_HEAD(&psta->asoc_list);
36 INIT_LIST_HEAD(&psta->auth_list);
37 psta->expire_to = 0;
38 psta->flags = 0;
39 psta->capability = 0;
40 psta->bpairwise_key_installed = false;
41 psta->nonerp_set = 0;
42 psta->no_short_slot_time_set = 0;
43 psta->no_short_preamble_set = 0;
44 psta->no_ht_gf_set = 0;
45 psta->no_ht_set = 0;
46 psta->ht_20mhz_set = 0;
47 psta->keep_alive_trycnt = 0;
48#endif /* CONFIG_8723AU_AP_MODE */
49}
50
51u32 _rtw_init_sta_priv23a(struct sta_priv *pstapriv)
52{
53 struct sta_info *psta;
54 s32 i;
55
56 pstapriv->pallocated_stainfo_buf = rtw_zvmalloc(sizeof(struct sta_info) * NUM_STA+ 4);
57
58 if (!pstapriv->pallocated_stainfo_buf)
59 return _FAIL;
60
61 pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
62 ((unsigned long)(pstapriv->pallocated_stainfo_buf) & 3);
63 _rtw_init_queue23a(&pstapriv->free_sta_queue);
64 spin_lock_init(&pstapriv->sta_hash_lock);
65 pstapriv->asoc_sta_count = 0;
66 _rtw_init_queue23a(&pstapriv->sleep_q);
67 _rtw_init_queue23a(&pstapriv->wakeup_q);
68 psta = (struct sta_info *)(pstapriv->pstainfo_buf);
69
70 for (i = 0; i < NUM_STA; i++) {
71 _rtw_init_stainfo(psta);
72 INIT_LIST_HEAD(&pstapriv->sta_hash[i]);
73 list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
74 psta++;
75 }
76#ifdef CONFIG_8723AU_AP_MODE
77 pstapriv->sta_dz_bitmap = 0;
78 pstapriv->tim_bitmap = 0;
79 INIT_LIST_HEAD(&pstapriv->asoc_list);
80 INIT_LIST_HEAD(&pstapriv->auth_list);
81 spin_lock_init(&pstapriv->asoc_list_lock);
82 spin_lock_init(&pstapriv->auth_list_lock);
83 pstapriv->asoc_list_cnt = 0;
84 pstapriv->auth_list_cnt = 0;
85 pstapriv->auth_to = 3; /* 3*2 = 6 sec */
86 pstapriv->assoc_to = 3;
87 /* pstapriv->expire_to = 900; 900*2 = 1800 sec = 30 min, expire after no any traffic. */
88 /* pstapriv->expire_to = 30; 30*2 = 60 sec = 1 min, expire after no any traffic. */
89 pstapriv->expire_to = 3; /* 3*2 = 6 sec */
90 pstapriv->max_num_sta = NUM_STA;
91#endif
92 return _SUCCESS;
93}
94
95inline int rtw_stainfo_offset23a(struct sta_priv *stapriv, struct sta_info *sta)
96{
97 int offset = (((u8 *)sta) - stapriv->pstainfo_buf)/sizeof(struct sta_info);
98
99 if (!stainfo_offset_valid(offset))
100 DBG_8723A("%s invalid offset(%d), out of range!!!", __func__, offset);
101 return offset;
102}
103
104inline struct sta_info *rtw_get_stainfo23a_by_offset23a(struct sta_priv *stapriv, int offset)
105{
106 if (!stainfo_offset_valid(offset))
107 DBG_8723A("%s invalid offset(%d), out of range!!!", __func__, offset);
108 return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info));
109}
110
111/* this function is used to free the memory of lock || sema for all stainfos */
112void rtw_mfree_all_stainfo(struct sta_priv *pstapriv)
113{
114 struct list_head *plist, *phead;
115 struct sta_info *psta;
116
117 spin_lock_bh(&pstapriv->sta_hash_lock);
118
119 phead = get_list_head(&pstapriv->free_sta_queue);
120
121 /* we really achieve a lot in this loop .... */
122 list_for_each(plist, phead)
123 psta = container_of(plist, struct sta_info, list);
124 spin_unlock_bh(&pstapriv->sta_hash_lock);
125}
126
127void rtw_mfree_sta_priv_lock(struct sta_priv *pstapriv)
128{
129 rtw_mfree_all_stainfo(pstapriv); /* be done before free sta_hash_lock */
130}
131
132u32 _rtw_free_sta_priv23a(struct sta_priv *pstapriv)
133{
134 struct list_head *phead, *plist, *ptmp;
135 struct sta_info *psta;
136 struct recv_reorder_ctrl *preorder_ctrl;
137 int index;
138
139 if (pstapriv) {
140 /* delete all reordering_ctrl_timer */
141 spin_lock_bh(&pstapriv->sta_hash_lock);
142 for (index = 0; index < NUM_STA; index++) {
143 phead = &pstapriv->sta_hash[index];
144
145 list_for_each_safe(plist, ptmp, phead) {
146 int i;
147 psta = container_of(plist, struct sta_info,
148 hash_list);
149 for (i = 0; i < 16 ; i++) {
150 preorder_ctrl = &psta->recvreorder_ctrl[i];
151 del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
152 }
153 }
154 }
155 spin_unlock_bh(&pstapriv->sta_hash_lock);
156 /*===============================*/
157
158 rtw_mfree_sta_priv_lock(pstapriv);
159
160 if (pstapriv->pallocated_stainfo_buf)
161 rtw_vmfree(pstapriv->pallocated_stainfo_buf, sizeof(struct sta_info)*NUM_STA+4);
162 }
163 return _SUCCESS;
164}
165
166struct sta_info *rtw_alloc_stainfo23a(struct sta_priv *pstapriv, u8 *hwaddr)
167{
168 struct list_head *phash_list;
169 struct sta_info *psta;
170 struct rtw_queue *pfree_sta_queue;
171 struct recv_reorder_ctrl *preorder_ctrl;
172 uint tmp_aid;
173 s32 index;
174 int i = 0;
175 u16 wRxSeqInitialValue = 0xffff;
176
177 pfree_sta_queue = &pstapriv->free_sta_queue;
178
179 spin_lock_bh(&pstapriv->sta_hash_lock);
180
181 if (_rtw_queue_empty23a(pfree_sta_queue)) {
182 spin_unlock_bh(&pstapriv->sta_hash_lock);
183 return NULL;
184 }
185 psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list);
186
187 list_del_init(&psta->list);
188
189 tmp_aid = psta->aid;
190
191 _rtw_init_stainfo(psta);
192
193 psta->padapter = pstapriv->padapter;
194
195 memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
196
197 index = wifi_mac_hash(hwaddr);
198
199 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
200 ("rtw_alloc_stainfo23a: index = %x", index));
201 if (index >= NUM_STA) {
202 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
203 ("ERROR => rtw_alloc_stainfo23a: index >= NUM_STA"));
204 psta = NULL;
205 goto exit;
206 }
207 phash_list = &pstapriv->sta_hash[index];
208
209 list_add_tail(&psta->hash_list, phash_list);
210
211 pstapriv->asoc_sta_count ++ ;
212
213/* For the SMC router, the sequence number of first packet of WPS handshake will be 0. */
214/* In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable. */
215/* So, we initialize the tid_rxseq variable as the 0xffff. */
216
217 for (i = 0; i < 16; i++)
218 memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2);
219
220 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
221 ("alloc number_%d stainfo with hwaddr = %pM\n",
222 pstapriv->asoc_sta_count, hwaddr));
223
224 init_addba_retry_timer23a(psta);
225
226 /* for A-MPDU Rx reordering buffer control */
227 for (i = 0; i < 16; i++) {
228 preorder_ctrl = &psta->recvreorder_ctrl[i];
229
230 preorder_ctrl->padapter = pstapriv->padapter;
231
232 preorder_ctrl->enable = false;
233
234 preorder_ctrl->indicate_seq = 0xffff;
235 preorder_ctrl->wend_b = 0xffff;
236 /* preorder_ctrl->wsize_b = (NR_RECVBUFF-2); */
237 preorder_ctrl->wsize_b = 64;/* 64; */
238
239 _rtw_init_queue23a(&preorder_ctrl->pending_recvframe_queue);
240
241 rtw_init_recv_timer23a(preorder_ctrl);
242 }
243 /* init for DM */
244 psta->rssi_stat.UndecoratedSmoothedPWDB = (-1);
245 psta->rssi_stat.UndecoratedSmoothedCCK = (-1);
246
247 /* init for the sequence number of received management frame */
248 psta->RxMgmtFrameSeqNum = 0xffff;
249exit:
250 spin_unlock_bh(&pstapriv->sta_hash_lock);
251 return psta;
252}
253
254/* using pstapriv->sta_hash_lock to protect */
255u32 rtw_free_stainfo23a(struct rtw_adapter *padapter, struct sta_info *psta)
256{
257 struct rtw_queue *pfree_sta_queue;
258 struct recv_reorder_ctrl *preorder_ctrl;
259 struct sta_xmit_priv *pstaxmitpriv;
260 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
261 struct sta_priv *pstapriv = &padapter->stapriv;
262 struct hw_xmit *phwxmit;
263 int i;
264
265 if (psta == NULL)
266 goto exit;
267
268 spin_lock_bh(&psta->lock);
269 psta->state &= ~_FW_LINKED;
270 spin_unlock_bh(&psta->lock);
271
272 pfree_sta_queue = &pstapriv->free_sta_queue;
273
274 pstaxmitpriv = &psta->sta_xmitpriv;
275
276 spin_lock_bh(&pxmitpriv->lock);
277
278 rtw_free_xmitframe_queue23a(pxmitpriv, &psta->sleep_q);
279 psta->sleepq_len = 0;
280
281 /* vo */
282 rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
283 list_del_init(&pstaxmitpriv->vo_q.tx_pending);
284 phwxmit = pxmitpriv->hwxmits;
285 phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt;
286 pstaxmitpriv->vo_q.qcnt = 0;
287
288 /* vi */
289 rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
290 list_del_init(&pstaxmitpriv->vi_q.tx_pending);
291 phwxmit = pxmitpriv->hwxmits+1;
292 phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt;
293 pstaxmitpriv->vi_q.qcnt = 0;
294
295 /* be */
296 rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
297 list_del_init(&pstaxmitpriv->be_q.tx_pending);
298 phwxmit = pxmitpriv->hwxmits+2;
299 phwxmit->accnt -= pstaxmitpriv->be_q.qcnt;
300 pstaxmitpriv->be_q.qcnt = 0;
301
302 /* bk */
303 rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
304 list_del_init(&pstaxmitpriv->bk_q.tx_pending);
305 phwxmit = pxmitpriv->hwxmits+3;
306 phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt;
307 pstaxmitpriv->bk_q.qcnt = 0;
308
309 spin_unlock_bh(&pxmitpriv->lock);
310
311 list_del_init(&psta->hash_list);
312 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("\n free number_%d stainfo with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n", pstapriv->asoc_sta_count, psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2], psta->hwaddr[3], psta->hwaddr[4], psta->hwaddr[5]));
313 pstapriv->asoc_sta_count --;
314
315 /* re-init sta_info; 20061114 will be init in alloc_stainfo */
316 /* _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv); */
317 /* _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv); */
318
319 del_timer_sync(&psta->addba_retry_timer);
320
321 /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */
322 for (i = 0; i < 16; i++) {
323 struct list_head *phead, *plist;
324 struct recv_frame *prframe;
325 struct rtw_queue *ppending_recvframe_queue;
326 struct rtw_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
327
328 preorder_ctrl = &psta->recvreorder_ctrl[i];
329
330 del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
331
332 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
333
334 spin_lock_bh(&ppending_recvframe_queue->lock);
335 phead = get_list_head(ppending_recvframe_queue);
336 plist = phead->next;
337
338 while (!list_empty(phead)) {
339 prframe = container_of(plist, struct recv_frame, list);
340 plist = plist->next;
341 list_del_init(&prframe->list);
342 rtw_free_recvframe23a(prframe, pfree_recv_queue);
343 }
344 spin_unlock_bh(&ppending_recvframe_queue->lock);
345 }
346 if (!(psta->state & WIFI_AP_STATE))
347 rtw_hal_set_odm_var23a(padapter, HAL_ODM_STA_INFO, psta, false);
348#ifdef CONFIG_8723AU_AP_MODE
349 spin_lock_bh(&pstapriv->auth_list_lock);
350 if (!list_empty(&psta->auth_list)) {
351 list_del_init(&psta->auth_list);
352 pstapriv->auth_list_cnt--;
353 }
354 spin_unlock_bh(&pstapriv->auth_list_lock);
355
356 psta->expire_to = 0;
357
358 psta->sleepq_ac_len = 0;
359 psta->qos_info = 0;
360
361 psta->max_sp_len = 0;
362 psta->uapsd_bk = 0;
363 psta->uapsd_be = 0;
364 psta->uapsd_vi = 0;
365 psta->uapsd_vo = 0;
366
367 psta->has_legacy_ac = 0;
368
369 pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid);
370 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
371
372 if ((psta->aid >0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
373 pstapriv->sta_aid[psta->aid - 1] = NULL;
374 psta->aid = 0;
375 }
376#endif /* CONFIG_8723AU_AP_MODE */
377 list_add_tail(&psta->list, get_list_head(pfree_sta_queue));
378exit:
379 return _SUCCESS;
380}
381
382/* free all stainfo which in sta_hash[all] */
383void rtw_free_all_stainfo23a(struct rtw_adapter *padapter)
384{
385 struct list_head *plist, *phead, *ptmp;
386 struct sta_info *psta;
387 struct sta_priv *pstapriv = &padapter->stapriv;
388 struct sta_info* pbcmc_stainfo = rtw_get_bcmc_stainfo23a(padapter);
389 s32 index; if (pstapriv->asoc_sta_count == 1)
390 return;
391
392 spin_lock_bh(&pstapriv->sta_hash_lock);
393
394 for (index = 0; index < NUM_STA; index++) {
395 phead = &pstapriv->sta_hash[index];
396
397 list_for_each_safe(plist, ptmp, phead) {
398 psta = container_of(plist, struct sta_info, hash_list);
399
400 if (pbcmc_stainfo!= psta)
401 rtw_free_stainfo23a(padapter, psta);
402 }
403 }
404 spin_unlock_bh(&pstapriv->sta_hash_lock);
405}
406
407/* any station allocated can be searched by hash list */
408struct sta_info *rtw_get_stainfo23a(struct sta_priv *pstapriv, u8 *hwaddr)
409{
410 struct list_head *plist, *phead;
411 struct sta_info *psta = NULL;
412 u32 index;
413 u8 *addr;
414 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
415
416 if (hwaddr == NULL)
417 return NULL;
418
419 if (is_multicast_ether_addr(hwaddr))
420 addr = bc_addr;
421 else
422 addr = hwaddr;
423
424 index = wifi_mac_hash(addr);
425
426 spin_lock_bh(&pstapriv->sta_hash_lock);
427
428 phead = &pstapriv->sta_hash[index];
429
430 list_for_each(plist, phead) {
431 psta = container_of(plist, struct sta_info, hash_list);
432
433 if (!memcmp(psta->hwaddr, addr, ETH_ALEN)) {
434 /* if found the matched address */
435 break;
436 }
437 psta = NULL;
438 }
439 spin_unlock_bh(&pstapriv->sta_hash_lock);
440 return psta;
441}
442
443u32 rtw_init_bcmc_stainfo23a(struct rtw_adapter* padapter)
444{
445 struct sta_priv *pstapriv = &padapter->stapriv;
446 struct sta_info *psta;
447 struct tx_servq *ptxservq;
448 u32 res = _SUCCESS;
449 unsigned char bcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
450
451 psta = rtw_alloc_stainfo23a(pstapriv, bcast_addr);
452 if (psta == NULL) {
453 res = _FAIL;
454 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
455 ("rtw_alloc_stainfo23a fail"));
456 return res;
457 }
458 /* default broadcast & multicast use macid 1 */
459 psta->mac_id = 1;
460
461 ptxservq = &psta->sta_xmitpriv.be_q;
462 return _SUCCESS;
463}
464
465struct sta_info *rtw_get_bcmc_stainfo23a(struct rtw_adapter *padapter)
466{
467 struct sta_info *psta;
468 struct sta_priv *pstapriv = &padapter->stapriv;
469 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
470
471 psta = rtw_get_stainfo23a(pstapriv, bc_addr);
472 return psta;
473}
474
475u8 rtw_access_ctrl23a(struct rtw_adapter *padapter, u8 *mac_addr)
476{
477 u8 res = true;
478#ifdef CONFIG_8723AU_AP_MODE
479 struct list_head *plist, *phead;
480 struct rtw_wlan_acl_node *paclnode;
481 u8 match = false;
482 struct sta_priv *pstapriv = &padapter->stapriv;
483 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
484 struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q;
485
486 spin_lock_bh(&pacl_node_q->lock);
487 phead = get_list_head(pacl_node_q);
488
489 list_for_each(plist, phead) {
490 paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
491
492 if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) {
493 if (paclnode->valid) {
494 match = true;
495 break;
496 }
497 }
498 }
499 spin_unlock_bh(&pacl_node_q->lock);
500
501 if (pacl_list->mode == 1)/* accept unless in deny list */
502 res = (match) ? false : true;
503 else if (pacl_list->mode == 2)/* deny unless in accept list */
504 res = (match) ? true : false;
505 else
506 res = true;
507#endif
508 return res;
509}
diff --git a/drivers/staging/rtl8723au/core/rtw_wlan_util.c b/drivers/staging/rtl8723au/core/rtw_wlan_util.c
new file mode 100644
index 000000000000..0dfcfbce3b52
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_wlan_util.c
@@ -0,0 +1,1760 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _RTW_WLAN_UTIL_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <linux/ieee80211.h>
20#include <wifi.h>
21
22static unsigned char ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f};
23static unsigned char ARTHEROS_OUI2[] = {0x00, 0x13, 0x74};
24
25static unsigned char BROADCOM_OUI1[] = {0x00, 0x10, 0x18};
26static unsigned char BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7};
27
28static unsigned char CISCO_OUI[] = {0x00, 0x40, 0x96};
29static unsigned char MARVELL_OUI[] = {0x00, 0x50, 0x43};
30static unsigned char RALINK_OUI[] = {0x00, 0x0c, 0x43};
31static unsigned char REALTEK_OUI[] = {0x00, 0xe0, 0x4c};
32static unsigned char AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5};
33static unsigned char EPIGRAM_OUI[] = {0x00, 0x90, 0x4c};
34
35unsigned char REALTEK_96B_IE23A[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
36
37#define R2T_PHY_DELAY (0)
38
39/* define WAIT_FOR_BCN_TO_MIN (3000) */
40#define WAIT_FOR_BCN_TO_MIN (6000)
41#define WAIT_FOR_BCN_TO_MAX (20000)
42
43static u8 rtw_basic_rate_cck[4] = {
44 IEEE80211_CCK_RATE_1MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_2MB|IEEE80211_BASIC_RATE_MASK,
45 IEEE80211_CCK_RATE_5MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_11MB|IEEE80211_BASIC_RATE_MASK
46};
47
48static u8 rtw_basic_rate_ofdm[3] = {
49 IEEE80211_OFDM_RATE_6MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_OFDM_RATE_12MB|IEEE80211_BASIC_RATE_MASK,
50 IEEE80211_OFDM_RATE_24MB|IEEE80211_BASIC_RATE_MASK
51};
52
53static u8 rtw_basic_rate_mix[7] = {
54 IEEE80211_CCK_RATE_1MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_2MB|IEEE80211_BASIC_RATE_MASK,
55 IEEE80211_CCK_RATE_5MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_11MB|IEEE80211_BASIC_RATE_MASK,
56 IEEE80211_OFDM_RATE_6MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_OFDM_RATE_12MB|IEEE80211_BASIC_RATE_MASK,
57 IEEE80211_OFDM_RATE_24MB|IEEE80211_BASIC_RATE_MASK
58};
59
60int cckrates_included23a(unsigned char *rate, int ratelen)
61{
62 int i;
63
64 for (i = 0; i < ratelen; i++) {
65 if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) ||
66 (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22))
67 return true;
68 }
69
70 return false;
71}
72
73int cckratesonly_included23a(unsigned char *rate, int ratelen)
74{
75 int i;
76
77 for (i = 0; i < ratelen; i++) {
78 if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
79 (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22))
80 return false;
81 }
82
83 return true;
84}
85
86unsigned char networktype_to_raid23a(unsigned char network_type)
87{
88 unsigned char raid;
89
90 switch (network_type) {
91 case WIRELESS_11B:
92 raid = RATR_INX_WIRELESS_B;
93 break;
94 case WIRELESS_11A:
95 case WIRELESS_11G:
96 raid = RATR_INX_WIRELESS_G;
97 break;
98 case WIRELESS_11BG:
99 raid = RATR_INX_WIRELESS_GB;
100 break;
101 case WIRELESS_11_24N:
102 case WIRELESS_11_5N:
103 raid = RATR_INX_WIRELESS_N;
104 break;
105 case WIRELESS_11A_5N:
106 case WIRELESS_11G_24N:
107 raid = RATR_INX_WIRELESS_NG;
108 break;
109 case WIRELESS_11BG_24N:
110 raid = RATR_INX_WIRELESS_NGB;
111 break;
112 default:
113 raid = RATR_INX_WIRELESS_GB;
114 break;
115 }
116 return raid;
117}
118
119u8 judge_network_type23a(struct rtw_adapter *padapter, unsigned char *rate, int ratelen)
120{
121 u8 network_type = 0;
122 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
123 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
124
125 if (pmlmeext->cur_channel > 14) {
126 if (pmlmeinfo->HT_enable)
127 network_type = WIRELESS_11_5N;
128 network_type |= WIRELESS_11A;
129 } else {
130 if (pmlmeinfo->HT_enable)
131 network_type = WIRELESS_11_24N;
132
133 if ((cckratesonly_included23a(rate, ratelen)) == true)
134 network_type |= WIRELESS_11B;
135 else if ((cckrates_included23a(rate, ratelen)) == true)
136 network_type |= WIRELESS_11BG;
137 else
138 network_type |= WIRELESS_11G;
139 }
140 return network_type;
141}
142
143unsigned char ratetbl_val_2wifirate(unsigned char rate)
144{
145 unsigned char val = 0;
146
147 switch (rate & 0x7f) {
148 case 0:
149 val = IEEE80211_CCK_RATE_1MB;
150 break;
151 case 1:
152 val = IEEE80211_CCK_RATE_2MB;
153 break;
154 case 2:
155 val = IEEE80211_CCK_RATE_5MB;
156 break;
157 case 3:
158 val = IEEE80211_CCK_RATE_11MB;
159 break;
160 case 4:
161 val = IEEE80211_OFDM_RATE_6MB;
162 break;
163 case 5:
164 val = IEEE80211_OFDM_RATE_9MB;
165 break;
166 case 6:
167 val = IEEE80211_OFDM_RATE_12MB;
168 break;
169 case 7:
170 val = IEEE80211_OFDM_RATE_18MB;
171 break;
172 case 8:
173 val = IEEE80211_OFDM_RATE_24MB;
174 break;
175 case 9:
176 val = IEEE80211_OFDM_RATE_36MB;
177 break;
178 case 10:
179 val = IEEE80211_OFDM_RATE_48MB;
180 break;
181 case 11:
182 val = IEEE80211_OFDM_RATE_54MB;
183 break;
184 }
185 return val;
186}
187
188int is_basicrate(struct rtw_adapter *padapter, unsigned char rate)
189{
190 int i;
191 unsigned char val;
192 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
193
194 for (i = 0; i < NumRates; i++) {
195 val = pmlmeext->basicrate[i];
196
197 if ((val != 0xff) && (val != 0xfe)) {
198 if (rate == ratetbl_val_2wifirate(val))
199 return true;
200 }
201 }
202
203 return false;
204}
205
206unsigned int ratetbl2rateset(struct rtw_adapter *padapter, unsigned char *rateset)
207{
208 int i;
209 unsigned char rate;
210 unsigned int len = 0;
211 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
212
213 for (i = 0; i < NumRates; i++) {
214 rate = pmlmeext->datarate[i];
215
216 switch (rate) {
217 case 0xff:
218 return len;
219 case 0xfe:
220 continue;
221 default:
222 rate = ratetbl_val_2wifirate(rate);
223
224 if (is_basicrate(padapter, rate) == true)
225 rate |= IEEE80211_BASIC_RATE_MASK;
226
227 rateset[len] = rate;
228 len++;
229 break;
230 }
231 }
232 return len;
233}
234
235void get_rate_set23a(struct rtw_adapter *padapter, unsigned char *pbssrate, int *bssrate_len)
236{
237 unsigned char supportedrates[NumRates];
238
239 memset(supportedrates, 0, NumRates);
240 *bssrate_len = ratetbl2rateset(padapter, supportedrates);
241 memcpy(pbssrate, supportedrates, *bssrate_len);
242}
243
244void UpdateBrateTbl23a(struct rtw_adapter *Adapter, u8 *mBratesOS)
245{
246 u8 i;
247 u8 rate;
248
249 /* 1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory. */
250 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
251 rate = mBratesOS[i] & 0x7f;
252 switch (rate) {
253 case IEEE80211_CCK_RATE_1MB:
254 case IEEE80211_CCK_RATE_2MB:
255 case IEEE80211_CCK_RATE_5MB:
256 case IEEE80211_CCK_RATE_11MB:
257 case IEEE80211_OFDM_RATE_6MB:
258 case IEEE80211_OFDM_RATE_12MB:
259 case IEEE80211_OFDM_RATE_24MB:
260 mBratesOS[i] |= IEEE80211_BASIC_RATE_MASK;
261 break;
262 default:
263 break;
264 }
265 }
266}
267
268void Update23aTblForSoftAP(u8 *bssrateset, u32 bssratelen)
269{
270 u8 i;
271 u8 rate;
272
273 for (i = 0; i < bssratelen; i++) {
274 rate = bssrateset[i] & 0x7f;
275 switch (rate) {
276 case IEEE80211_CCK_RATE_1MB:
277 case IEEE80211_CCK_RATE_2MB:
278 case IEEE80211_CCK_RATE_5MB:
279 case IEEE80211_CCK_RATE_11MB:
280 bssrateset[i] |= IEEE80211_BASIC_RATE_MASK;
281 break;
282 }
283 }
284}
285
286void Save_DM_Func_Flag23a(struct rtw_adapter *padapter)
287{
288 u8 bSaveFlag = true;
289
290 rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag));
291}
292
293void Restore_DM_Func_Flag23a(struct rtw_adapter *padapter)
294{
295 u8 bSaveFlag = false;
296 rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag));
297}
298
299void Switch_DM_Func23a(struct rtw_adapter *padapter, unsigned long mode, u8 enable)
300{
301 if (enable == true)
302 rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_SET, (u8 *)(&mode));
303 else
304 rtw_hal_set_hwreg23a(padapter, HW_VAR_DM_FUNC_CLR, (u8 *)(&mode));
305}
306
307static void Set_NETYPE0_MSR(struct rtw_adapter *padapter, u8 type)
308{
309 rtw_hal_set_hwreg23a(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type));
310}
311
312void Set_MSR23a(struct rtw_adapter *padapter, u8 type)
313{
314 Set_NETYPE0_MSR(padapter, type);
315}
316
317inline u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter)
318{
319 return adapter_to_dvobj(adapter)->oper_channel;
320}
321
322inline void rtw_set_oper_ch23a(struct rtw_adapter *adapter, u8 ch)
323{
324 adapter_to_dvobj(adapter)->oper_channel = ch;
325}
326
327inline u8 rtw_get_oper_bw23a(struct rtw_adapter *adapter)
328{
329 return adapter_to_dvobj(adapter)->oper_bwmode;
330}
331
332inline void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw)
333{
334 adapter_to_dvobj(adapter)->oper_bwmode = bw;
335}
336
337inline u8 rtw_get_oper_ch23aoffset(struct rtw_adapter *adapter)
338{
339 return adapter_to_dvobj(adapter)->oper_ch_offset;
340}
341
342inline void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 offset)
343{
344 adapter_to_dvobj(adapter)->oper_ch_offset = offset;
345}
346
347void SelectChannel23a(struct rtw_adapter *padapter, unsigned char channel)
348{
349 mutex_lock(&adapter_to_dvobj(padapter)->setch_mutex);
350
351 /* saved channel info */
352 rtw_set_oper_ch23a(padapter, channel);
353
354 rtw_hal_set_chan23a(padapter, channel);
355
356 mutex_unlock(&adapter_to_dvobj(padapter)->setch_mutex);
357}
358
359void SetBWMode23a(struct rtw_adapter *padapter, unsigned short bwmode, unsigned char channel_offset)
360{
361 mutex_lock(&adapter_to_dvobj(padapter)->setbw_mutex);
362
363 /* saved bw info */
364 rtw_set_oper_bw23a(padapter, bwmode);
365 rtw_set_oper_ch23aoffset23a(padapter, channel_offset);
366
367 rtw_hal_set_bwmode23a(padapter, (enum ht_channel_width)bwmode,
368 channel_offset);
369
370 mutex_unlock(&adapter_to_dvobj(padapter)->setbw_mutex);
371}
372
373void set_channel_bwmode23a(struct rtw_adapter *padapter, unsigned char channel,
374 unsigned char channel_offset, unsigned short bwmode)
375{
376 u8 center_ch;
377
378 if (padapter->bNotifyChannelChange)
379 DBG_8723A("[%s] ch = %d, offset = %d, bwmode = %d\n", __func__, channel, channel_offset, bwmode);
380
381 if ((bwmode == HT_CHANNEL_WIDTH_20) ||
382 (channel_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)) {
383 /* SelectChannel23a(padapter, channel); */
384 center_ch = channel;
385 } else {
386 /* switch to the proper channel */
387 if (channel_offset == HAL_PRIME_CHNL_OFFSET_LOWER) {
388 /* SelectChannel23a(padapter, channel + 2); */
389 center_ch = channel + 2;
390 } else {
391 /* SelectChannel23a(padapter, channel - 2); */
392 center_ch = channel - 2;
393 }
394 }
395
396 /* set Channel */
397 mutex_lock(&adapter_to_dvobj(padapter)->setch_mutex);
398
399 /* saved channel/bw info */
400 rtw_set_oper_ch23a(padapter, channel);
401 rtw_set_oper_bw23a(padapter, bwmode);
402 rtw_set_oper_ch23aoffset23a(padapter, channel_offset);
403
404 rtw_hal_set_chan23a(padapter, center_ch); /* set center channel */
405
406 mutex_unlock(&adapter_to_dvobj(padapter)->setch_mutex);
407
408 SetBWMode23a(padapter, bwmode, channel_offset);
409}
410
411int get_bsstype23a(unsigned short capability)
412{
413 if (capability & BIT(0))
414 return WIFI_FW_AP_STATE;
415 else if (capability & BIT(1))
416 return WIFI_FW_ADHOC_STATE;
417 return 0;
418}
419
420inline u8 *get_my_bssid23a(struct wlan_bssid_ex *pnetwork)
421{
422 return pnetwork->MacAddress;
423}
424
425u16 get_beacon_interval23a(struct wlan_bssid_ex *bss)
426{
427 unsigned short val;
428 memcpy((unsigned char *)&val, rtw_get_beacon_interval23a_from_ie(bss->IEs), 2);
429
430 return le16_to_cpu(val);
431}
432
433int is_client_associated_to_ap23a(struct rtw_adapter *padapter)
434{
435 struct mlme_ext_priv *pmlmeext;
436 struct mlme_ext_info *pmlmeinfo;
437
438 if (!padapter)
439 return _FAIL;
440
441 pmlmeext = &padapter->mlmeextpriv;
442 pmlmeinfo = &pmlmeext->mlmext_info;
443
444 if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE))
445 return true;
446 else
447 return _FAIL;
448}
449
450int is_client_associated_to_ibss23a(struct rtw_adapter *padapter)
451{
452 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
453 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
454
455 if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) &&
456 ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE))
457 return true;
458 else
459 return _FAIL;
460}
461
462int is_IBSS_empty23a(struct rtw_adapter *padapter)
463{
464 unsigned int i;
465 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
466 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
467
468 for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
469 if (pmlmeinfo->FW_sta_info[i].status == 1)
470 return _FAIL;
471 }
472
473 return true;
474}
475
476unsigned int decide_wait_for_beacon_timeout23a(unsigned int bcn_interval)
477{
478 if ((bcn_interval << 2) < WAIT_FOR_BCN_TO_MIN)
479 return WAIT_FOR_BCN_TO_MIN;
480 else if ((bcn_interval << 2) > WAIT_FOR_BCN_TO_MAX)
481 return WAIT_FOR_BCN_TO_MAX;
482 else
483 return bcn_interval << 2;
484}
485
486void CAM_empty_entry23a(struct rtw_adapter *Adapter, u8 ucIndex)
487{
488 rtw_hal_set_hwreg23a(Adapter, HW_VAR_CAM_EMPTY_ENTRY, (u8 *)(&ucIndex));
489}
490
491void invalidate_cam_all23a(struct rtw_adapter *padapter)
492{
493 rtw_hal_set_hwreg23a(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
494}
495
496void write_cam23a(struct rtw_adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key)
497{
498 unsigned int i, val, addr;
499 int j;
500 u32 cam_val[2];
501
502 addr = entry << 3;
503
504 for (j = 5; j >= 0; j--) {
505 switch (j) {
506 case 0:
507 val = (ctrl | (mac[0] << 16) | (mac[1] << 24));
508 break;
509 case 1:
510 val = (mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24));
511 break;
512 default:
513 i = (j - 2) << 2;
514 val = (key[i] | (key[i+1] << 8) | (key[i+2] << 16) | (key[i+3] << 24));
515 break;
516 }
517
518 cam_val[0] = val;
519 cam_val[1] = addr + (unsigned int)j;
520
521 rtw_hal_set_hwreg23a(padapter, HW_VAR_CAM_WRITE, (u8 *)cam_val);
522
523 /* rtw_write32(padapter, WCAMI, val); */
524
525 /* cmd = CAM_POLLINIG | CAM_WRITE | (addr + j); */
526 /* rtw_write32(padapter, RWCAM, cmd); */
527
528 /* DBG_8723A("%s => cam write: %x, %x\n", __func__, cmd, val); */
529
530 }
531}
532
533void clear_cam_entry23a(struct rtw_adapter *padapter, u8 entry)
534{
535 unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
536
537 unsigned char null_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
538
539 write_cam23a(padapter, entry, 0, null_sta, null_key);
540}
541
542int allocate_fw_sta_entry23a(struct rtw_adapter *padapter)
543{
544 unsigned int mac_id;
545 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
546 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
547
548 for (mac_id = IBSS_START_MAC_ID; mac_id < NUM_STA; mac_id++) {
549 if (pmlmeinfo->FW_sta_info[mac_id].status == 0) {
550 pmlmeinfo->FW_sta_info[mac_id].status = 1;
551 pmlmeinfo->FW_sta_info[mac_id].retry = 0;
552 break;
553 }
554 }
555
556 return mac_id;
557}
558
559void flush_all_cam_entry23a(struct rtw_adapter *padapter)
560{
561 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
562 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
563
564 rtw_hal_set_hwreg23a(padapter, HW_VAR_CAM_INVALID_ALL, NULL);
565
566 memset((u8 *)(pmlmeinfo->FW_sta_info), 0, sizeof(pmlmeinfo->FW_sta_info));
567}
568
569#if defined(CONFIG_8723AU_P2P) && defined(CONFIG_8723AU_P2P)
570int WFD_info_handler(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
571{
572 struct wifidirect_info *pwdinfo;
573 u8 wfd_ie[128] = {0x00};
574 u32 wfd_ielen = 0;
575
576 pwdinfo = &padapter->wdinfo;
577 if (rtw_get_wfd_ie((u8 *) pIE, pIE->Length, wfd_ie, &wfd_ielen)) {
578 u8 attr_content[ 10 ] = { 0x00 };
579 u32 attr_contentlen = 0;
580
581 DBG_8723A("[%s] Found WFD IE\n", __func__);
582 rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
583 if (attr_contentlen) {
584 pwdinfo->wfd_info->peer_rtsp_ctrlport = get_unaligned_be16(attr_content + 2);
585 DBG_8723A("[%s] Peer PORT NUM = %d\n", __func__, pwdinfo->wfd_info->peer_rtsp_ctrlport);
586 return true;
587 }
588 } else {
589 DBG_8723A("[%s] NO WFD IE\n", __func__);
590 }
591 return _FAIL;
592}
593#endif
594
595int WMM_param_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
596{
597 /* struct registry_priv *pregpriv = &padapter->registrypriv; */
598 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
599 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
600 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
601
602 if (pmlmepriv->qospriv.qos_option == 0) {
603 pmlmeinfo->WMM_enable = 0;
604 return _FAIL;
605 }
606
607 pmlmeinfo->WMM_enable = 1;
608 memcpy(&pmlmeinfo->WMM_param, (pIE->data + 6),
609 sizeof(struct WMM_para_element));
610 return true;
611}
612
613void WMMOnAssocRsp23a(struct rtw_adapter *padapter)
614{
615 u8 ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime;
616 u8 acm_mask;
617 u16 TXOP;
618 u32 acParm, i;
619 u32 edca[4], inx[4];
620 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
621 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
622 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
623 struct registry_priv *pregpriv = &padapter->registrypriv;
624
625 if (pmlmeinfo->WMM_enable == 0) {
626 padapter->mlmepriv.acm_mask = 0;
627 return;
628 }
629
630 acm_mask = 0;
631
632 if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
633 aSifsTime = 10;
634 else
635 aSifsTime = 16;
636
637 for (i = 0; i < 4; i++) {
638 ACI = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 5) & 0x03;
639 ACM = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 4) & 0x01;
640
641 /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */
642 AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) * pmlmeinfo->slotTime + aSifsTime;
643
644 ECWMin = (pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f);
645 ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4;
646 TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit);
647
648 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
649
650 switch (ACI) {
651 case 0x0:
652 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
653 acm_mask |= (ACM? BIT(1):0);
654 edca[XMIT_BE_QUEUE] = acParm;
655 break;
656 case 0x1:
657 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
658 /* acm_mask |= (ACM? BIT(0):0); */
659 edca[XMIT_BK_QUEUE] = acParm;
660 break;
661 case 0x2:
662 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
663 acm_mask |= (ACM? BIT(2):0);
664 edca[XMIT_VI_QUEUE] = acParm;
665 break;
666 case 0x3:
667 rtw_hal_set_hwreg23a(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
668 acm_mask |= (ACM? BIT(3):0);
669 edca[XMIT_VO_QUEUE] = acParm;
670 break;
671 }
672
673 DBG_8723A("WMM(%x): %x, %x\n", ACI, ACM, acParm);
674 }
675
676 if (padapter->registrypriv.acm_method == 1)
677 rtw_hal_set_hwreg23a(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask));
678 else
679 padapter->mlmepriv.acm_mask = acm_mask;
680
681 inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
682
683 if (pregpriv->wifi_spec == 1) {
684 u32 j, tmp, change_inx;
685
686 /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
687 for (i = 0; i < 4; i++) {
688 for (j = i+1; j < 4; j++) {
689 /* compare CW and AIFS */
690 if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) {
691 change_inx = true;
692 } else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) {
693 /* compare TXOP */
694 if ((edca[j] >> 16) > (edca[i] >> 16))
695 change_inx = true;
696 }
697
698 if (change_inx) {
699 tmp = edca[i];
700 edca[i] = edca[j];
701 edca[j] = tmp;
702
703 tmp = inx[i];
704 inx[i] = inx[j];
705 inx[j] = tmp;
706
707 change_inx = false;
708 }
709 }
710 }
711 }
712
713 for (i = 0; i<4; i++) {
714 pxmitpriv->wmm_para_seq[i] = inx[i];
715 DBG_8723A("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]);
716 }
717
718 return;
719}
720
721static void bwmode_update_check(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
722{
723 struct HT_info_element *pHT_info;
724 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
725 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
726 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
727 struct registry_priv *pregistrypriv = &padapter->registrypriv;
728 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
729 unsigned char new_bwmode;
730 unsigned char new_ch_offset;
731
732 if (!pIE)
733 return;
734 if (!phtpriv->ht_option)
735 return;
736 if (pIE->Length > sizeof(struct HT_info_element))
737 return;
738
739 pHT_info = (struct HT_info_element *)pIE->data;
740
741 if ((pHT_info->infos[0] & BIT(2)) && pregistrypriv->cbw40_enable) {
742 new_bwmode = HT_CHANNEL_WIDTH_40;
743
744 switch (pHT_info->infos[0] & 0x3) {
745 case 1:
746 new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
747 break;
748 case 3:
749 new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
750 break;
751 default:
752 new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
753 break;
754 }
755 } else {
756 new_bwmode = HT_CHANNEL_WIDTH_20;
757 new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
758 }
759
760 if ((new_bwmode!= pmlmeext->cur_bwmode) ||
761 (new_ch_offset!= pmlmeext->cur_ch_offset)) {
762 pmlmeinfo->bwmode_updated = true;
763
764 pmlmeext->cur_bwmode = new_bwmode;
765 pmlmeext->cur_ch_offset = new_ch_offset;
766
767 /* update HT info also */
768 HT_info_handler23a(padapter, pIE);
769 } else {
770 pmlmeinfo->bwmode_updated = false;
771 }
772
773 if (pmlmeinfo->bwmode_updated) {
774 struct sta_info *psta;
775 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
776 struct sta_priv *pstapriv = &padapter->stapriv;
777
778 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
779
780 /* update ap's stainfo */
781 psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
782 if (psta) {
783 struct ht_priv *phtpriv_sta = &psta->htpriv;
784
785 if (phtpriv_sta->ht_option) {
786 /* bwmode */
787 phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
788 phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
789 } else {
790 phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20;
791 phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
792 }
793
794 }
795 }
796}
797
798void HT_caps_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
799{
800 unsigned int i;
801 u8 rf_type;
802 u8 max_AMPDU_len, min_MPDU_spacing;
803 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
804 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
805 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
806 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
807
808 if (pIE == NULL) return;
809
810 if (phtpriv->ht_option == false) return;
811
812 pmlmeinfo->HT_caps_enable = 1;
813
814 for (i = 0; i < (pIE->Length); i++) {
815 if (i != 2) {
816 /* Commented by Albert 2010/07/12 */
817 /* Got the endian issue here. */
818 pmlmeinfo->HT_caps.u.HT_cap[i] &= (pIE->data[i]);
819 } else {
820 /* modify from fw by Thomas 2010/11/17 */
821 if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (pIE->data[i] & 0x3))
822 max_AMPDU_len = (pIE->data[i] & 0x3);
823 else
824 max_AMPDU_len = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3);
825
826 if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) > (pIE->data[i] & 0x1c))
827 min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c);
828 else
829 min_MPDU_spacing = (pIE->data[i] & 0x1c);
830
831 pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para = max_AMPDU_len | min_MPDU_spacing;
832 }
833 }
834
835 /* Commented by Albert 2010/07/12 */
836 /* Have to handle the endian issue after copying. */
837 /* HT_ext_caps didn't be used yet. */
838 pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info = le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);
839 pmlmeinfo->HT_caps.u.HT_cap_element.HT_ext_caps = le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_ext_caps);
840
841 rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
842
843 /* update the MCS rates */
844 for (i = 0; i < 16; i++) {
845 if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R))
846 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R23A[i];
847 else
848 pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R23A[i];
849 }
850 return;
851}
852
853void HT_info_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
854{
855 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
856 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
857 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
858 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
859
860 if (pIE == NULL) return;
861
862 if (phtpriv->ht_option == false) return;
863
864 if (pIE->Length > sizeof(struct HT_info_element))
865 return;
866
867 pmlmeinfo->HT_info_enable = 1;
868 memcpy(&pmlmeinfo->HT_info, pIE->data, pIE->Length);
869 return;
870}
871
872void HTOnAssocRsp23a(struct rtw_adapter *padapter)
873{
874 unsigned char max_AMPDU_len;
875 unsigned char min_MPDU_spacing;
876 /* struct registry_priv *pregpriv = &padapter->registrypriv; */
877 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
878 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
879
880 DBG_8723A("%s\n", __func__);
881
882 if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable)) {
883 pmlmeinfo->HT_enable = 1;
884 } else {
885 pmlmeinfo->HT_enable = 0;
886 /* set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
887 return;
888 }
889
890 /* handle A-MPDU parameter field */
891 /*
892 AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
893 AMPDU_para [4:2]:Min MPDU Start Spacing
894 */
895 max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
896
897 min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
898
899 rtw_hal_set_hwreg23a(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
900
901 rtw_hal_set_hwreg23a(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
902}
903
904void ERP_IE_handler23a(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE)
905{
906 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
907 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
908
909 if (pIE->Length>1)
910 return;
911
912 pmlmeinfo->ERP_enable = 1;
913 memcpy(&pmlmeinfo->ERP_IE, pIE->data, pIE->Length);
914}
915
916void VCS_update23a(struct rtw_adapter *padapter, struct sta_info *psta)
917{
918 struct registry_priv *pregpriv = &padapter->registrypriv;
919 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
920 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
921
922 switch (pregpriv->vrtl_carrier_sense) { /* 0:off 1:on 2:auto */
923 case 0: /* off */
924 psta->rtsen = 0;
925 psta->cts2self = 0;
926 break;
927 case 1: /* on */
928 if (pregpriv->vcs_type == 1) { /* 1:RTS/CTS 2:CTS to self */
929 psta->rtsen = 1;
930 psta->cts2self = 0;
931 } else {
932 psta->rtsen = 0;
933 psta->cts2self = 1;
934 }
935 break;
936 case 2: /* auto */
937 default:
938 if ((pmlmeinfo->ERP_enable) && (pmlmeinfo->ERP_IE & BIT(1))) {
939 if (pregpriv->vcs_type == 1) {
940 psta->rtsen = 1;
941 psta->cts2self = 0;
942 } else {
943 psta->rtsen = 0;
944 psta->cts2self = 1;
945 }
946 } else {
947 psta->rtsen = 0;
948 psta->cts2self = 0;
949 }
950 break;
951 }
952}
953
954int rtw_check_bcn_info23a(struct rtw_adapter *Adapter, u8 *pframe, u32 packet_len)
955{
956 unsigned int len;
957 unsigned char *p;
958 unsigned short val16;
959 struct wlan_network *cur_network = &Adapter->mlmepriv.cur_network;
960 u16 wpa_len = 0, rsn_len = 0;
961 u8 encryp_protocol = 0;
962 struct wlan_bssid_ex *bssid;
963 int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0;
964 unsigned char *pbuf;
965 u32 wpa_ielen = 0;
966 u32 hidden_ssid = 0;
967 struct HT_info_element *pht_info = NULL;
968 struct ieee80211_ht_cap *pht_cap = NULL;
969 u32 bcn_channel;
970 unsigned short ht_cap_info;
971 unsigned char ht_info_infos_0;
972 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) pframe;
973 u8 *pbssid = hdr->addr3;
974
975 if (is_client_associated_to_ap23a(Adapter) == false)
976 return true;
977
978 len = packet_len - sizeof(struct ieee80211_hdr_3addr);
979
980 if (len > MAX_IE_SZ) {
981 DBG_8723A("%s IE too long for survey event\n", __func__);
982 return _FAIL;
983 }
984
985 if (memcmp(cur_network->network.MacAddress, pbssid, 6)) {
986 DBG_8723A("Oops: rtw_check_network_encrypt linked but recv other bssid bcn\n" MAC_FMT MAC_FMT,
987 MAC_ARG(pbssid), MAC_ARG(cur_network->network.MacAddress));
988 return true;
989 }
990
991 bssid = (struct wlan_bssid_ex *)kzalloc(sizeof(struct wlan_bssid_ex),
992 GFP_ATOMIC);
993
994 if (ieee80211_is_beacon(hdr->frame_control))
995 bssid->reserved = 1;
996
997 bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
998
999 /* below is to copy the information element */
1000 bssid->IELength = len;
1001 memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
1002
1003 /* check bw and channel offset */
1004 /* parsing HT_CAP_IE */
1005 p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
1006 if (p && len>0) {
1007 pht_cap = (struct ieee80211_ht_cap *)(p + 2);
1008 ht_cap_info = pht_cap->cap_info;
1009 } else {
1010 ht_cap_info = 0;
1011 }
1012 /* parsing HT_INFO_IE */
1013 p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
1014 if (p && len>0) {
1015 pht_info = (struct HT_info_element *)(p + 2);
1016 ht_info_infos_0 = pht_info->infos[0];
1017 } else {
1018 ht_info_infos_0 = 0;
1019 }
1020 if (ht_cap_info != cur_network->BcnInfo.ht_cap_info ||
1021 ((ht_info_infos_0&0x03) != (cur_network->BcnInfo.ht_info_infos_0&0x03))) {
1022 DBG_8723A("%s bcn now: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
1023 ht_cap_info, ht_info_infos_0);
1024 DBG_8723A("%s bcn link: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
1025 cur_network->BcnInfo.ht_cap_info, cur_network->BcnInfo.ht_info_infos_0);
1026 DBG_8723A("%s bw mode change, disconnect\n", __func__);
1027 /* bcn_info_update */
1028 cur_network->BcnInfo.ht_cap_info = ht_cap_info;
1029 cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0;
1030 /* to do : need to check that whether modify related register of BB or not */
1031 }
1032
1033 /* Checking for channel */
1034 p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _DSSET_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
1035 if (p) {
1036 bcn_channel = *(p + 2);
1037 } else {/* In 5G, some ap do not have DSSET IE checking HT info for channel */
1038 p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
1039 if (pht_info) {
1040 bcn_channel = pht_info->primary_channel;
1041 } else { /* we don't find channel IE, so don't check it */
1042 DBG_8723A("Oops: %s we don't find channel IE, so don't check it\n", __func__);
1043 bcn_channel = Adapter->mlmeextpriv.cur_channel;
1044 }
1045 }
1046 if (bcn_channel != Adapter->mlmeextpriv.cur_channel) {
1047 DBG_8723A("%s beacon channel:%d cur channel:%d disconnect\n", __func__,
1048 bcn_channel, Adapter->mlmeextpriv.cur_channel);
1049 goto _mismatch;
1050 }
1051
1052 /* checking SSID */
1053 if ((p = rtw_get_ie23a(bssid->IEs + _FIXED_IE_LENGTH_, _SSID_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_)) == NULL) {
1054 DBG_8723A("%s marc: cannot find SSID for survey event\n", __func__);
1055 hidden_ssid = true;
1056 } else {
1057 hidden_ssid = false;
1058 }
1059
1060 if ((NULL != p) && (false == hidden_ssid && (*(p + 1)))) {
1061 memcpy(bssid->Ssid.ssid, (p + 2), *(p + 1));
1062 bssid->Ssid.ssid_len = *(p + 1);
1063 } else {
1064 bssid->Ssid.ssid_len = 0;
1065 bssid->Ssid.ssid[0] = '\0';
1066 }
1067
1068 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1069 ("%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d "
1070 "cur_network->network.Ssid.Ssid:%s len:%d\n", __func__,
1071 bssid->Ssid.ssid, bssid->Ssid.ssid_len,
1072 cur_network->network.Ssid.ssid,
1073 cur_network->network.Ssid.ssid_len));
1074
1075 if (memcmp(bssid->Ssid.ssid, cur_network->network.Ssid.ssid, 32) ||
1076 bssid->Ssid.ssid_len != cur_network->network.Ssid.ssid_len) {
1077 if (bssid->Ssid.ssid[0] != '\0' &&
1078 bssid->Ssid.ssid_len != 0) { /* not hidden ssid */
1079 DBG_8723A("%s(), SSID is not match return FAIL\n",
1080 __func__);
1081 goto _mismatch;
1082 }
1083 }
1084
1085 /* check encryption info */
1086 val16 = rtw_get_capability23a((struct wlan_bssid_ex *)bssid);
1087
1088 if (val16 & BIT(4))
1089 bssid->Privacy = 1;
1090 else
1091 bssid->Privacy = 0;
1092
1093 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1094 ("%s(): cur_network->network.Privacy is %d, bssid.Privacy is %d\n",
1095 __func__, cur_network->network.Privacy, bssid->Privacy));
1096 if (cur_network->network.Privacy != bssid->Privacy) {
1097 DBG_8723A("%s(), privacy is not match return FAIL\n", __func__);
1098 goto _mismatch;
1099 }
1100
1101 rtw_get_sec_ie23a(bssid->IEs, bssid->IELength, NULL,&rsn_len, NULL,&wpa_len);
1102
1103 if (rsn_len > 0) {
1104 encryp_protocol = ENCRYP_PROTOCOL_WPA2;
1105 } else if (wpa_len > 0) {
1106 encryp_protocol = ENCRYP_PROTOCOL_WPA;
1107 } else {
1108 if (bssid->Privacy)
1109 encryp_protocol = ENCRYP_PROTOCOL_WEP;
1110 }
1111
1112 if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) {
1113 DBG_8723A("%s(): enctyp is not match , return FAIL\n", __func__);
1114 goto _mismatch;
1115 }
1116
1117 if (encryp_protocol == ENCRYP_PROTOCOL_WPA || encryp_protocol == ENCRYP_PROTOCOL_WPA2) {
1118 pbuf = rtw_get_wpa_ie23a(&bssid->IEs[12], &wpa_ielen, bssid->IELength-12);
1119 if (pbuf && (wpa_ielen>0)) {
1120 if (_SUCCESS == rtw_parse_wpa_ie23a(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is_8021x)) {
1121 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1122 ("%s pnetwork->pairwise_cipher: %d, group_cipher is %d, is_8021x is %d\n", __func__,
1123 pairwise_cipher, group_cipher, is_8021x));
1124 }
1125 } else {
1126 pbuf = rtw_get_wpa2_ie23a(&bssid->IEs[12], &wpa_ielen, bssid->IELength-12);
1127
1128 if (pbuf && (wpa_ielen>0)) {
1129 if (_SUCCESS == rtw_parse_wpa2_ie23a(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is_8021x)) {
1130 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1131 ("%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher is %d, is_802x is %d\n",
1132 __func__, pairwise_cipher, group_cipher, is_8021x));
1133 }
1134 }
1135 }
1136
1137 RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1138 ("%s cur_network->group_cipher is %d: %d\n", __func__, cur_network->BcnInfo.group_cipher, group_cipher));
1139 if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || group_cipher != cur_network->BcnInfo.group_cipher) {
1140 DBG_8723A("%s pairwise_cipher(%x:%x) or group_cipher(%x:%x) is not match , return FAIL\n", __func__,
1141 pairwise_cipher, cur_network->BcnInfo.pairwise_cipher,
1142 group_cipher, cur_network->BcnInfo.group_cipher);
1143 goto _mismatch;
1144 }
1145
1146 if (is_8021x != cur_network->BcnInfo.is_8021x) {
1147 DBG_8723A("%s authentication is not match , return FAIL\n", __func__);
1148 goto _mismatch;
1149 }
1150 }
1151
1152 kfree(bssid);
1153 return _SUCCESS;
1154
1155_mismatch:
1156 kfree(bssid);
1157
1158 return _FAIL;
1159}
1160
1161void update_beacon23a_info(struct rtw_adapter *padapter, u8 *pframe, uint pkt_len, struct sta_info *psta)
1162{
1163 unsigned int i;
1164 unsigned int len;
1165 struct ndis_802_11_var_ies * pIE;
1166
1167 len = pkt_len -
1168 (_BEACON_IE_OFFSET_ + sizeof(struct ieee80211_hdr_3addr));
1169
1170 for (i = 0; i < len;) {
1171 pIE = (struct ndis_802_11_var_ies *)(pframe + (_BEACON_IE_OFFSET_ + sizeof(struct ieee80211_hdr_3addr)) + i);
1172
1173 switch (pIE->ElementID) {
1174 case _HT_EXTRA_INFO_IE_: /* HT info */
1175 /* HT_info_handler23a(padapter, pIE); */
1176 bwmode_update_check(padapter, pIE);
1177 break;
1178 case _ERPINFO_IE_:
1179 ERP_IE_handler23a(padapter, pIE);
1180 VCS_update23a(padapter, psta);
1181 break;
1182 default:
1183 break;
1184 }
1185 i += (pIE->Length + 2);
1186 }
1187}
1188
1189unsigned int is_ap_in_tkip23a(struct rtw_adapter *padapter)
1190{
1191 u32 i;
1192 struct ndis_802_11_var_ies * pIE;
1193 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1194 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1195 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1196
1197 if (rtw_get_capability23a((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
1198 for (i = sizeof(struct ndis_802_11_fixed_ies); i < pmlmeinfo->network.IELength;) {
1199 pIE = (struct ndis_802_11_var_ies *)(pmlmeinfo->network.IEs + i);
1200
1201 switch (pIE->ElementID) {
1202 case _VENDOR_SPECIFIC_IE_:
1203 if ((!memcmp(pIE->data, RTW_WPA_OUI23A, 4)) && (!memcmp((pIE->data + 12), WPA_TKIP_CIPHER23A, 4)))
1204 return true;
1205 break;
1206 case _RSN_IE_2_:
1207 if (!memcmp((pIE->data + 8), RSN_TKIP_CIPHER23A, 4))
1208 return true;
1209 break;
1210 default:
1211 break;
1212 }
1213 i += (pIE->Length + 2);
1214 }
1215 return false;
1216 } else {
1217 return false;
1218 }
1219}
1220
1221unsigned int should_forbid_n_rate23a(struct rtw_adapter * padapter)
1222{
1223 u32 i;
1224 struct ndis_802_11_var_ies * pIE;
1225 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1226 struct wlan_bssid_ex *cur_network = &pmlmepriv->cur_network.network;
1227
1228 if (rtw_get_capability23a((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
1229 for (i = sizeof(struct ndis_802_11_fixed_ies); i < cur_network->IELength;) {
1230 pIE = (struct ndis_802_11_var_ies *)(cur_network->IEs + i);
1231
1232 switch (pIE->ElementID) {
1233 case _VENDOR_SPECIFIC_IE_:
1234 if (!memcmp(pIE->data, RTW_WPA_OUI23A, 4) &&
1235 ((!memcmp((pIE->data + 12), WPA_CIPHER_SUITE_CCMP23A, 4)) ||
1236 (!memcmp((pIE->data + 16), WPA_CIPHER_SUITE_CCMP23A, 4))))
1237 return false;
1238 break;
1239 case _RSN_IE_2_:
1240 if ((!memcmp((pIE->data + 8), RSN_CIPHER_SUITE_CCMP23A, 4)) ||
1241 (!memcmp((pIE->data + 12), RSN_CIPHER_SUITE_CCMP23A, 4)))
1242 return false;
1243 default:
1244 break;
1245 }
1246
1247 i += (pIE->Length + 2);
1248 }
1249 return true;
1250 } else {
1251 return false;
1252 }
1253}
1254
1255unsigned int is_ap_in_wep23a(struct rtw_adapter *padapter)
1256{
1257 u32 i;
1258 struct ndis_802_11_var_ies * pIE;
1259 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1260 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1261 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1262
1263 if (rtw_get_capability23a((struct wlan_bssid_ex *)cur_network) & WLAN_CAPABILITY_PRIVACY) {
1264 for (i = sizeof(struct ndis_802_11_fixed_ies); i < pmlmeinfo->network.IELength;) {
1265 pIE = (struct ndis_802_11_var_ies *)(pmlmeinfo->network.IEs + i);
1266
1267 switch (pIE->ElementID) {
1268 case _VENDOR_SPECIFIC_IE_:
1269 if (!memcmp(pIE->data, RTW_WPA_OUI23A, 4))
1270 return false;
1271 break;
1272 case _RSN_IE_2_:
1273 return false;
1274
1275 default:
1276 break;
1277 }
1278
1279 i += (pIE->Length + 2);
1280 }
1281
1282 return true;
1283 } else {
1284 return false;
1285 }
1286}
1287
1288int wifirate2_ratetbl_inx23a(unsigned char rate)
1289{
1290 int inx = 0;
1291 rate = rate & 0x7f;
1292
1293 switch (rate) {
1294 case 54*2:
1295 inx = 11;
1296 break;
1297 case 48*2:
1298 inx = 10;
1299 break;
1300 case 36*2:
1301 inx = 9;
1302 break;
1303 case 24*2:
1304 inx = 8;
1305 break;
1306 case 18*2:
1307 inx = 7;
1308 break;
1309 case 12*2:
1310 inx = 6;
1311 break;
1312 case 9*2:
1313 inx = 5;
1314 break;
1315 case 6*2:
1316 inx = 4;
1317 break;
1318 case 11*2:
1319 inx = 3;
1320 break;
1321 case 11:
1322 inx = 2;
1323 break;
1324 case 2*2:
1325 inx = 1;
1326 break;
1327 case 1*2:
1328 inx = 0;
1329 break;
1330 }
1331 return inx;
1332}
1333
1334unsigned int update_basic_rate23a(unsigned char *ptn, unsigned int ptn_sz)
1335{
1336 unsigned int i, num_of_rate;
1337 unsigned int mask = 0;
1338
1339 num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz;
1340
1341 for (i = 0; i < num_of_rate; i++) {
1342 if ((*(ptn + i)) & 0x80)
1343 mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i));
1344 }
1345 return mask;
1346}
1347
1348unsigned int update_supported_rate23a(unsigned char *ptn, unsigned int ptn_sz)
1349{
1350 unsigned int i, num_of_rate;
1351 unsigned int mask = 0;
1352
1353 num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz;
1354
1355 for (i = 0; i < num_of_rate; i++)
1356 mask |= 0x1 << wifirate2_ratetbl_inx23a(*(ptn + i));
1357 return mask;
1358}
1359
1360unsigned int update_MSC_rate23a(struct HT_caps_element *pHT_caps)
1361{
1362 unsigned int mask = 0;
1363
1364 mask = ((pHT_caps->u.HT_cap_element.MCS_rate[0] << 12) | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 20));
1365
1366 return mask;
1367}
1368
1369int support_short_GI23a(struct rtw_adapter *padapter,
1370 struct HT_caps_element *pHT_caps)
1371{
1372 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1373 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1374 unsigned char bit_offset;
1375
1376 if (!(pmlmeinfo->HT_enable))
1377 return _FAIL;
1378 if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK))
1379 return _FAIL;
1380 bit_offset = (pmlmeext->cur_bwmode & HT_CHANNEL_WIDTH_40)? 6: 5;
1381
1382 if (pHT_caps->u.HT_cap_element.HT_caps_info & (0x1 << bit_offset))
1383 return _SUCCESS;
1384 else
1385 return _FAIL;
1386}
1387
1388unsigned char get_highest_rate_idx23a(u32 mask)
1389{
1390 int i;
1391 unsigned char rate_idx = 0;
1392
1393 for (i = 27; i >= 0; i--) {
1394 if (mask & BIT(i)) {
1395 rate_idx = i;
1396 break;
1397 }
1398 }
1399 return rate_idx;
1400}
1401
1402unsigned char get_highest_mcs_rate(struct HT_caps_element *pHT_caps)
1403{
1404 int i, mcs_rate;
1405
1406 mcs_rate = (pHT_caps->u.HT_cap_element.MCS_rate[0] | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 8));
1407
1408 for (i = 15; i >= 0; i--) {
1409 if (mcs_rate & (0x1 << i))
1410 break;
1411 }
1412 return i;
1413}
1414
1415void Update_RA_Entry23a(struct rtw_adapter *padapter, struct sta_info *psta)
1416{
1417 rtw_hal_update_ra_mask23a(psta, 0);
1418}
1419
1420void enable_rate_adaptive(struct rtw_adapter *padapter, struct sta_info *psta)
1421{
1422 Update_RA_Entry23a(padapter, psta);
1423}
1424
1425void set_sta_rate23a(struct rtw_adapter *padapter, struct sta_info *psta)
1426{
1427 /* rate adaptive */
1428 enable_rate_adaptive(padapter, psta);
1429}
1430
1431/* Update RRSR and Rate for USERATE */
1432void update_tx_basic_rate23a(struct rtw_adapter *padapter, u8 wirelessmode)
1433{
1434 unsigned char supported_rates[NDIS_802_11_LENGTH_RATES_EX];
1435#ifdef CONFIG_8723AU_P2P
1436 struct wifidirect_info* pwdinfo = &padapter->wdinfo;
1437
1438 /* Added by Albert 2011/03/22 */
1439 /* In the P2P mode, the driver should not support the b mode. */
1440 /* So, the Tx packet shouldn't use the CCK rate */
1441 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1442 return;
1443#endif /* CONFIG_8723AU_P2P */
1444
1445 memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
1446
1447 if ((wirelessmode & WIRELESS_11B) && (wirelessmode == WIRELESS_11B)) {
1448 memcpy(supported_rates, rtw_basic_rate_cck, 4);
1449 } else if (wirelessmode & WIRELESS_11B) {
1450 memcpy(supported_rates, rtw_basic_rate_mix, 7);
1451 } else {
1452 memcpy(supported_rates, rtw_basic_rate_ofdm, 3);
1453 }
1454
1455 if (wirelessmode & WIRELESS_11B)
1456 update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB);
1457 else
1458 update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB);
1459
1460 rtw_hal_set_hwreg23a(padapter, HW_VAR_BASIC_RATE, supported_rates);
1461}
1462
1463unsigned char check_assoc_AP23a(u8 *pframe, uint len)
1464{
1465 unsigned int i;
1466 struct ndis_802_11_var_ies * pIE;
1467 u8 epigram_vendor_flag;
1468 u8 ralink_vendor_flag;
1469 epigram_vendor_flag = 0;
1470 ralink_vendor_flag = 0;
1471
1472 for (i = sizeof(struct ndis_802_11_fixed_ies); i < len;) {
1473 pIE = (struct ndis_802_11_var_ies *)(pframe + i);
1474
1475 switch (pIE->ElementID) {
1476 case _VENDOR_SPECIFIC_IE_:
1477 if ((!memcmp(pIE->data, ARTHEROS_OUI1, 3)) ||
1478 (!memcmp(pIE->data, ARTHEROS_OUI2, 3))) {
1479 DBG_8723A("link to Artheros AP\n");
1480 return HT_IOT_PEER_ATHEROS;
1481 } else if ((!memcmp(pIE->data, BROADCOM_OUI1, 3)) ||
1482 !memcmp(pIE->data, BROADCOM_OUI2, 3) ||
1483 !memcmp(pIE->data, BROADCOM_OUI2, 3)) {
1484 DBG_8723A("link to Broadcom AP\n");
1485 return HT_IOT_PEER_BROADCOM;
1486 } else if (!memcmp(pIE->data, MARVELL_OUI, 3)) {
1487 DBG_8723A("link to Marvell AP\n");
1488 return HT_IOT_PEER_MARVELL;
1489 } else if (!memcmp(pIE->data, RALINK_OUI, 3)) {
1490 if (!ralink_vendor_flag) {
1491 ralink_vendor_flag = 1;
1492 } else {
1493 DBG_8723A("link to Ralink AP\n");
1494 return HT_IOT_PEER_RALINK;
1495 }
1496 } else if (!memcmp(pIE->data, CISCO_OUI, 3)) {
1497 DBG_8723A("link to Cisco AP\n");
1498 return HT_IOT_PEER_CISCO;
1499 } else if (!memcmp(pIE->data, REALTEK_OUI, 3)) {
1500 DBG_8723A("link to Realtek 96B\n");
1501 return HT_IOT_PEER_REALTEK;
1502 } else if (!memcmp(pIE->data, AIRGOCAP_OUI, 3)) {
1503 DBG_8723A("link to Airgo Cap\n");
1504 return HT_IOT_PEER_AIRGO;
1505 } else if (!memcmp(pIE->data, EPIGRAM_OUI, 3)) {
1506 epigram_vendor_flag = 1;
1507 if (ralink_vendor_flag) {
1508 DBG_8723A("link to Tenda W311R AP\n");
1509 return HT_IOT_PEER_TENDA;
1510 } else {
1511 DBG_8723A("Capture EPIGRAM_OUI\n");
1512 }
1513 } else {
1514 break;
1515 }
1516 default:
1517 break;
1518 }
1519
1520 i += (pIE->Length + 2);
1521 }
1522
1523 if (ralink_vendor_flag && !epigram_vendor_flag) {
1524 DBG_8723A("link to Ralink AP\n");
1525 return HT_IOT_PEER_RALINK;
1526 } else if (ralink_vendor_flag && epigram_vendor_flag) {
1527 DBG_8723A("link to Tenda W311R AP\n");
1528 return HT_IOT_PEER_TENDA;
1529 } else {
1530 DBG_8723A("link to new AP\n");
1531 return HT_IOT_PEER_UNKNOWN;
1532 }
1533}
1534
1535void update_IOT_info23a(struct rtw_adapter *padapter)
1536{
1537 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1538 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1539
1540 switch (pmlmeinfo->assoc_AP_vendor) {
1541 case HT_IOT_PEER_MARVELL:
1542 pmlmeinfo->turboMode_cts2self = 1;
1543 pmlmeinfo->turboMode_rtsen = 0;
1544 break;
1545 case HT_IOT_PEER_RALINK:
1546 pmlmeinfo->turboMode_cts2self = 0;
1547 pmlmeinfo->turboMode_rtsen = 1;
1548 /* disable high power */
1549 Switch_DM_Func23a(padapter, ~DYNAMIC_BB_DYNAMIC_TXPWR,
1550 false);
1551 break;
1552 case HT_IOT_PEER_REALTEK:
1553 /* rtw_write16(padapter, 0x4cc, 0xffff); */
1554 /* rtw_write16(padapter, 0x546, 0x01c0); */
1555 /* disable high power */
1556 Switch_DM_Func23a(padapter, ~DYNAMIC_BB_DYNAMIC_TXPWR,
1557 false);
1558 break;
1559 default:
1560 pmlmeinfo->turboMode_cts2self = 0;
1561 pmlmeinfo->turboMode_rtsen = 1;
1562 break;
1563 }
1564}
1565
1566void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap)
1567{
1568 struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
1569 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1570 bool ShortPreamble;
1571
1572 if (updateCap & cShortPreamble) {
1573 /* Short Preamble */
1574 if (pmlmeinfo->preamble_mode != PREAMBLE_SHORT) {
1575 /* PREAMBLE_LONG or PREAMBLE_AUTO */
1576 ShortPreamble = true;
1577 pmlmeinfo->preamble_mode = PREAMBLE_SHORT;
1578 rtw_hal_set_hwreg23a(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
1579 }
1580 } else { /* Long Preamble */
1581 if (pmlmeinfo->preamble_mode != PREAMBLE_LONG) {
1582 /* PREAMBLE_SHORT or PREAMBLE_AUTO */
1583 ShortPreamble = false;
1584 pmlmeinfo->preamble_mode = PREAMBLE_LONG;
1585 rtw_hal_set_hwreg23a(Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble);
1586 }
1587 }
1588 if (updateCap & cIBSS) {
1589 /* Filen: See 802.11-2007 p.91 */
1590 pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1591 } else {
1592 /* Filen: See 802.11-2007 p.90 */
1593 if (pmlmeext->cur_wireless_mode & (WIRELESS_11G | WIRELESS_11_24N)) {
1594 if (updateCap & cShortSlotTime) { /* Short Slot Time */
1595 if (pmlmeinfo->slotTime != SHORT_SLOT_TIME)
1596 pmlmeinfo->slotTime = SHORT_SLOT_TIME;
1597 } else { /* Long Slot Time */
1598 if (pmlmeinfo->slotTime != NON_SHORT_SLOT_TIME)
1599 pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1600 }
1601 } else if (pmlmeext->cur_wireless_mode & (WIRELESS_11A | WIRELESS_11_5N)) {
1602 pmlmeinfo->slotTime = SHORT_SLOT_TIME;
1603 } else {
1604 /* B Mode */
1605 pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
1606 }
1607 }
1608 rtw_hal_set_hwreg23a(Adapter, HW_VAR_SLOT_TIME, &pmlmeinfo->slotTime);
1609}
1610
1611void update_wireless_mode23a(struct rtw_adapter *padapter)
1612{
1613 int ratelen, network_type = 0;
1614 u32 SIFS_Timer;
1615 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1616 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1617 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1618 unsigned char *rate = cur_network->SupportedRates;
1619
1620 ratelen = rtw_get_rateset_len23a(cur_network->SupportedRates);
1621
1622 if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable))
1623 pmlmeinfo->HT_enable = 1;
1624
1625 if (pmlmeext->cur_channel > 14) {
1626 if (pmlmeinfo->HT_enable)
1627 network_type = WIRELESS_11_5N;
1628 network_type |= WIRELESS_11A;
1629 } else {
1630 if (pmlmeinfo->HT_enable)
1631 network_type = WIRELESS_11_24N;
1632
1633 if ((cckratesonly_included23a(rate, ratelen)) == true)
1634 network_type |= WIRELESS_11B;
1635 else if ((cckrates_included23a(rate, ratelen)) == true)
1636 network_type |= WIRELESS_11BG;
1637 else
1638 network_type |= WIRELESS_11G;
1639 }
1640
1641 pmlmeext->cur_wireless_mode = network_type & padapter->registrypriv.wireless_mode;
1642
1643 SIFS_Timer = 0x0a0a0808; /* 0x0808 -> for CCK, 0x0a0a -> for OFDM */
1644 /* change this value if having IOT issues. */
1645
1646 padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer);
1647
1648 if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
1649 update_mgnt_tx_rate23a(padapter, IEEE80211_CCK_RATE_1MB);
1650 else
1651 update_mgnt_tx_rate23a(padapter, IEEE80211_OFDM_RATE_6MB);
1652}
1653
1654void update_bmc_sta_support_rate23a(struct rtw_adapter *padapter, u32 mac_id)
1655{
1656 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1657 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1658
1659 if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {
1660 /* Only B, B/G, and B/G/N AP could use CCK rate */
1661 memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), rtw_basic_rate_cck, 4);
1662 } else {
1663 memcpy((pmlmeinfo->FW_sta_info[mac_id].SupportedRates), rtw_basic_rate_ofdm, 4);
1664 }
1665}
1666
1667int update_sta_support_rate23a(struct rtw_adapter *padapter, u8 *pvar_ie, uint var_ie_len, int cam_idx)
1668{
1669 unsigned int ie_len;
1670 struct ndis_802_11_var_ies *pIE;
1671 int supportRateNum = 0;
1672 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1673 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1674
1675 pIE = (struct ndis_802_11_var_ies *)rtw_get_ie23a(pvar_ie, _SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
1676 if (pIE == NULL)
1677 return _FAIL;
1678
1679 memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, pIE->data, ie_len);
1680 supportRateNum = ie_len;
1681
1682 pIE = (struct ndis_802_11_var_ies *)rtw_get_ie23a(pvar_ie, _EXT_SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
1683 if (pIE)
1684 memcpy((pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + supportRateNum), pIE->data, ie_len);
1685 return _SUCCESS;
1686}
1687
1688void process_addba_req23a(struct rtw_adapter *padapter, u8 *paddba_req, u8 *addr)
1689{
1690 struct sta_info *psta;
1691 u16 tid, start_seq, param;
1692 struct recv_reorder_ctrl *preorder_ctrl;
1693 struct sta_priv *pstapriv = &padapter->stapriv;
1694 struct ADDBA_request *preq = (struct ADDBA_request*)paddba_req;
1695 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1696 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1697
1698 psta = rtw_get_stainfo23a(pstapriv, addr);
1699
1700 if (psta) {
1701 start_seq = le16_to_cpu(preq->BA_starting_seqctrl) >> 4;
1702
1703 param = le16_to_cpu(preq->BA_para_set);
1704 tid = (param>>2)&0x0f;
1705
1706 preorder_ctrl = &psta->recvreorder_ctrl[tid];
1707
1708 preorder_ctrl->indicate_seq = 0xffff;
1709
1710 preorder_ctrl->enable = (pmlmeinfo->bAcceptAddbaReq == true)? true :false;
1711 }
1712}
1713
1714void update_TSF23a(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len)
1715{
1716 u8 *pIE;
1717 u32 *pbuf;
1718
1719 pIE = pframe + sizeof(struct ieee80211_hdr_3addr);
1720 pbuf = (u32 *)pIE;
1721
1722 pmlmeext->TSFValue = le32_to_cpu(*(pbuf+1));
1723
1724 pmlmeext->TSFValue = pmlmeext->TSFValue << 32;
1725
1726 pmlmeext->TSFValue |= le32_to_cpu(*pbuf);
1727}
1728
1729void correct_TSF23a(struct rtw_adapter *padapter, struct mlme_ext_priv *pmlmeext)
1730{
1731 rtw_hal_set_hwreg23a(padapter, HW_VAR_CORRECT_TSF, NULL);
1732}
1733
1734void beacon_timing_control23a(struct rtw_adapter *padapter)
1735{
1736 rtw_hal_bcn_related_reg_setting23a(padapter);
1737}
1738
1739static struct rtw_adapter *pbuddy_padapter;
1740
1741int rtw_handle_dualmac23a(struct rtw_adapter *adapter, bool init)
1742{
1743 int status = _SUCCESS;
1744
1745 if (init) {
1746 if (pbuddy_padapter == NULL) {
1747 pbuddy_padapter = adapter;
1748 DBG_8723A("%s(): pbuddy_padapter == NULL, Set pbuddy_padapter\n", __func__);
1749 } else {
1750 adapter->pbuddy_adapter = pbuddy_padapter;
1751 pbuddy_padapter->pbuddy_adapter = adapter;
1752 /* clear global value */
1753 pbuddy_padapter = NULL;
1754 DBG_8723A("%s(): pbuddy_padapter exist, Exchange Information\n", __func__);
1755 }
1756 } else {
1757 pbuddy_padapter = NULL;
1758 }
1759 return status;
1760}
diff --git a/drivers/staging/rtl8723au/core/rtw_xmit.c b/drivers/staging/rtl8723au/core/rtw_xmit.c
new file mode 100644
index 000000000000..0f10cfa10d39
--- /dev/null
+++ b/drivers/staging/rtl8723au/core/rtw_xmit.c
@@ -0,0 +1,2460 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _RTW_XMIT_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <wifi.h>
20#include <osdep_intf.h>
21#include <linux/ip.h>
22#include <usb_ops.h>
23
24static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
25static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
26
27static void _init_txservq(struct tx_servq *ptxservq)
28{
29
30 INIT_LIST_HEAD(&ptxservq->tx_pending);
31 _rtw_init_queue23a(&ptxservq->sta_pending);
32 ptxservq->qcnt = 0;
33
34}
35
36void _rtw_init_sta_xmit_priv23a(struct sta_xmit_priv *psta_xmitpriv)
37{
38
39 spin_lock_init(&psta_xmitpriv->lock);
40
41 /* for (i = 0 ; i < MAX_NUMBLKS; i++) */
42 /* _init_txservq(&psta_xmitpriv->blk_q[i]); */
43
44 _init_txservq(&psta_xmitpriv->be_q);
45 _init_txservq(&psta_xmitpriv->bk_q);
46 _init_txservq(&psta_xmitpriv->vi_q);
47 _init_txservq(&psta_xmitpriv->vo_q);
48 INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz);
49 INIT_LIST_HEAD(&psta_xmitpriv->apsd);
50
51}
52
53s32 _rtw_init_xmit_priv23a(struct xmit_priv *pxmitpriv, struct rtw_adapter *padapter)
54{
55 int i;
56 struct xmit_buf *pxmitbuf;
57 struct xmit_frame *pxframe;
58 int res = _SUCCESS;
59 u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
60 u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
61
62 /* We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc(). */
63 /* memset((unsigned char *)pxmitpriv, 0, sizeof(struct xmit_priv)); */
64
65 spin_lock_init(&pxmitpriv->lock);
66 spin_lock_init(&pxmitpriv->lock_sctx);
67 sema_init(&pxmitpriv->xmit_sema, 0);
68 sema_init(&pxmitpriv->terminate_xmitthread_sema, 0);
69
70 /*
71 Please insert all the queue initializaiton using _rtw_init_queue23a below
72 */
73
74 pxmitpriv->adapter = padapter;
75
76 _rtw_init_queue23a(&pxmitpriv->be_pending);
77 _rtw_init_queue23a(&pxmitpriv->bk_pending);
78 _rtw_init_queue23a(&pxmitpriv->vi_pending);
79 _rtw_init_queue23a(&pxmitpriv->vo_pending);
80 _rtw_init_queue23a(&pxmitpriv->bm_pending);
81
82 _rtw_init_queue23a(&pxmitpriv->free_xmit_queue);
83
84 /*
85 Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME,
86 and initialize free_xmit_frame below.
87 Please also apply free_txobj to link_up all the xmit_frames...
88 */
89
90 pxmitpriv->pallocated_frame_buf = rtw_zvmalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
91
92 if (pxmitpriv->pallocated_frame_buf == NULL) {
93 pxmitpriv->pxmit_frame_buf = NULL;
94 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xmit_frame fail!\n"));
95 res = _FAIL;
96 goto exit;
97 }
98 pxmitpriv->pxmit_frame_buf = PTR_ALIGN(pxmitpriv->pallocated_frame_buf, 4);
99
100 pxframe = (struct xmit_frame*) pxmitpriv->pxmit_frame_buf;
101
102 for (i = 0; i < NR_XMITFRAME; i++) {
103 INIT_LIST_HEAD(&pxframe->list);
104
105 pxframe->padapter = padapter;
106 pxframe->frame_tag = NULL_FRAMETAG;
107
108 pxframe->pkt = NULL;
109
110 pxframe->buf_addr = NULL;
111 pxframe->pxmitbuf = NULL;
112
113 list_add_tail(&pxframe->list,
114 &pxmitpriv->free_xmit_queue.queue);
115
116 pxframe++;
117 }
118
119 pxmitpriv->free_xmitframe_cnt = NR_XMITFRAME;
120
121 pxmitpriv->frag_len = MAX_FRAG_THRESHOLD;
122
123 /* init xmit_buf */
124 _rtw_init_queue23a(&pxmitpriv->free_xmitbuf_queue);
125 INIT_LIST_HEAD(&pxmitpriv->xmitbuf_list);
126 _rtw_init_queue23a(&pxmitpriv->pending_xmitbuf_queue);
127
128 for (i = 0; i < NR_XMITBUFF; i++) {
129 pxmitbuf = kzalloc(sizeof(struct xmit_buf), GFP_KERNEL);
130 if (!pxmitbuf)
131 goto fail;
132 INIT_LIST_HEAD(&pxmitbuf->list);
133 INIT_LIST_HEAD(&pxmitbuf->list2);
134
135 pxmitbuf->padapter = padapter;
136
137 /* Tx buf allocation may fail sometimes, so sleep and retry. */
138 res = rtw_os_xmit_resource_alloc23a(padapter, pxmitbuf,
139 (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ));
140 if (res == _FAIL) {
141 goto fail;
142 }
143
144 list_add_tail(&pxmitbuf->list,
145 &pxmitpriv->free_xmitbuf_queue.queue);
146 list_add_tail(&pxmitbuf->list2,
147 &pxmitpriv->xmitbuf_list);
148 }
149
150 pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF;
151
152 /* init xframe_ext queue, the same count as extbuf */
153 _rtw_init_queue23a(&pxmitpriv->free_xframe_ext_queue);
154
155 pxmitpriv->xframe_ext_alloc_addr = rtw_zvmalloc(num_xmit_extbuf * sizeof(struct xmit_frame) + 4);
156
157 if (pxmitpriv->xframe_ext_alloc_addr == NULL) {
158 pxmitpriv->xframe_ext = NULL;
159 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("alloc xframe_ext fail!\n"));
160 res = _FAIL;
161 goto exit;
162 }
163 pxmitpriv->xframe_ext = PTR_ALIGN(pxmitpriv->xframe_ext_alloc_addr, 4);
164 pxframe = (struct xmit_frame*)pxmitpriv->xframe_ext;
165
166 for (i = 0; i < num_xmit_extbuf; i++) {
167 INIT_LIST_HEAD(&pxframe->list);
168
169 pxframe->padapter = padapter;
170 pxframe->frame_tag = NULL_FRAMETAG;
171
172 pxframe->pkt = NULL;
173
174 pxframe->buf_addr = NULL;
175 pxframe->pxmitbuf = NULL;
176
177 pxframe->ext_tag = 1;
178
179 list_add_tail(&pxframe->list,
180 &pxmitpriv->free_xframe_ext_queue.queue);
181
182 pxframe++;
183 }
184 pxmitpriv->free_xframe_ext_cnt = num_xmit_extbuf;
185
186 /* Init xmit extension buff */
187 _rtw_init_queue23a(&pxmitpriv->free_xmit_extbuf_queue);
188 INIT_LIST_HEAD(&pxmitpriv->xmitextbuf_list);
189
190 for (i = 0; i < num_xmit_extbuf; i++) {
191 pxmitbuf = kzalloc(sizeof(struct xmit_buf), GFP_KERNEL);
192 if (!pxmitbuf)
193 goto fail;
194 INIT_LIST_HEAD(&pxmitbuf->list);
195 INIT_LIST_HEAD(&pxmitbuf->list2);
196
197 pxmitbuf->padapter = padapter;
198
199 /* Tx buf allocation may fail sometimes, so sleep and retry. */
200 res = rtw_os_xmit_resource_alloc23a(padapter, pxmitbuf,
201 max_xmit_extbuf_size + XMITBUF_ALIGN_SZ);
202 if (res == _FAIL) {
203 goto exit;
204 }
205
206 list_add_tail(&pxmitbuf->list,
207 &pxmitpriv->free_xmit_extbuf_queue.queue);
208 list_add_tail(&pxmitbuf->list2,
209 &pxmitpriv->xmitextbuf_list);
210 }
211
212 pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf;
213
214 rtw_alloc_hwxmits23a(padapter);
215 rtw_init_hwxmits23a(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
216
217 for (i = 0; i < 4; i ++)
218 pxmitpriv->wmm_para_seq[i] = i;
219
220 pxmitpriv->txirp_cnt = 1;
221
222 sema_init(&pxmitpriv->tx_retevt, 0);
223
224 /* per AC pending irp */
225 pxmitpriv->beq_cnt = 0;
226 pxmitpriv->bkq_cnt = 0;
227 pxmitpriv->viq_cnt = 0;
228 pxmitpriv->voq_cnt = 0;
229
230 pxmitpriv->ack_tx = false;
231 mutex_init(&pxmitpriv->ack_tx_mutex);
232 rtw_sctx_init23a(&pxmitpriv->ack_tx_ops, 0);
233 rtw_hal_init23a_xmit_priv(padapter);
234
235exit:
236
237 return res;
238fail:
239 goto exit;
240}
241
242void _rtw_free_xmit_priv23a (struct xmit_priv *pxmitpriv)
243{
244 struct rtw_adapter *padapter = pxmitpriv->adapter;
245 struct xmit_frame *pxmitframe = (struct xmit_frame*) pxmitpriv->pxmit_frame_buf;
246 struct xmit_buf *pxmitbuf;
247 struct list_head *plist, *ptmp;
248 u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
249 int i;
250
251 rtw_hal_free_xmit_priv23a(padapter);
252
253 if (pxmitpriv->pxmit_frame_buf == NULL)
254 return;
255 for (i = 0; i < NR_XMITFRAME; i++) {
256 rtw_os_xmit_complete23a(padapter, pxmitframe);
257 pxmitframe++;
258 }
259
260 list_for_each_safe(plist, ptmp, &pxmitpriv->xmitbuf_list) {
261 pxmitbuf = container_of(plist, struct xmit_buf, list2);
262 list_del_init(&pxmitbuf->list2);
263 rtw_os_xmit_resource_free23a(padapter, pxmitbuf);
264 kfree(pxmitbuf);
265 }
266
267 if (pxmitpriv->pallocated_frame_buf) {
268 rtw_vmfree(pxmitpriv->pallocated_frame_buf, NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
269 }
270
271 /* free xframe_ext queue, the same count as extbuf */
272 if ((pxmitframe = (struct xmit_frame*)pxmitpriv->xframe_ext)) {
273 for (i = 0; i<num_xmit_extbuf; i++) {
274 rtw_os_xmit_complete23a(padapter, pxmitframe);
275 pxmitframe++;
276 }
277 }
278 if (pxmitpriv->xframe_ext_alloc_addr)
279 rtw_vmfree(pxmitpriv->xframe_ext_alloc_addr, num_xmit_extbuf * sizeof(struct xmit_frame) + 4);
280
281 /* free xmit extension buff */
282 list_for_each_safe(plist, ptmp, &pxmitpriv->xmitextbuf_list) {
283 pxmitbuf = container_of(plist, struct xmit_buf, list2);
284 list_del_init(&pxmitbuf->list2);
285 rtw_os_xmit_resource_free23a(padapter, pxmitbuf);
286 kfree(pxmitbuf);
287 }
288
289 rtw_free_hwxmits23a(padapter);
290 mutex_destroy(&pxmitpriv->ack_tx_mutex);
291}
292
293static void update_attrib_vcs_info(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
294{
295 u32 sz;
296 struct pkt_attrib *pattrib = &pxmitframe->attrib;
297 struct sta_info *psta = pattrib->psta;
298 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
299 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
300
301 if (pattrib->psta) {
302 psta = pattrib->psta;
303 } else {
304 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
305 psta = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]);
306 }
307
308 if (psta == NULL) {
309 DBG_8723A("%s, psta == NUL\n", __func__);
310 return;
311 }
312
313 if (!(psta->state &_FW_LINKED)) {
314 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
315 return;
316 }
317
318 if (pattrib->nr_frags != 1)
319 sz = padapter->xmitpriv.frag_len;
320 else /* no frag */
321 sz = pattrib->last_txcmdsz;
322
323 /* (1) RTS_Threshold is compared to the MPDU, not MSDU. */
324 /* (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. */
325 /* Other fragments are protected by previous fragment. */
326 /* So we only need to check the length of first fragment. */
327 if (pmlmeext->cur_wireless_mode < WIRELESS_11_24N || padapter->registrypriv.wifi_spec) {
328 if (sz > padapter->registrypriv.rts_thresh) {
329 pattrib->vcs_mode = RTS_CTS;
330 } else {
331 if (psta->rtsen)
332 pattrib->vcs_mode = RTS_CTS;
333 else if (psta->cts2self)
334 pattrib->vcs_mode = CTS_TO_SELF;
335 else
336 pattrib->vcs_mode = NONE_VCS;
337 }
338 } else {
339 while (true) {
340 /* IOT action */
341 if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS) &&
342 (pattrib->ampdu_en) &&
343 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {
344 pattrib->vcs_mode = CTS_TO_SELF;
345 break;
346 }
347
348 /* check ERP protection */
349 if (psta->rtsen || psta->cts2self) {
350 if (psta->rtsen)
351 pattrib->vcs_mode = RTS_CTS;
352 else if (psta->cts2self)
353 pattrib->vcs_mode = CTS_TO_SELF;
354
355 break;
356 }
357
358 /* check HT op mode */
359 if (pattrib->ht_en) {
360 u8 HTOpMode = pmlmeinfo->HT_protection;
361 if ((pmlmeext->cur_bwmode && (HTOpMode == 2 || HTOpMode == 3)) ||
362 (!pmlmeext->cur_bwmode && HTOpMode == 3)) {
363 pattrib->vcs_mode = RTS_CTS;
364 break;
365 }
366 }
367
368 /* check rts */
369 if (sz > padapter->registrypriv.rts_thresh) {
370 pattrib->vcs_mode = RTS_CTS;
371 break;
372 }
373
374 /* to do list: check MIMO power save condition. */
375
376 /* check AMPDU aggregation for TXOP */
377 if (pattrib->ampdu_en) {
378 pattrib->vcs_mode = RTS_CTS;
379 break;
380 }
381
382 pattrib->vcs_mode = NONE_VCS;
383 break;
384 }
385 }
386}
387
388static void update_attrib_phy_info(struct pkt_attrib *pattrib, struct sta_info *psta)
389{
390 /*if (psta->rtsen)
391 pattrib->vcs_mode = RTS_CTS;
392 else if (psta->cts2self)
393 pattrib->vcs_mode = CTS_TO_SELF;
394 else
395 pattrib->vcs_mode = NONE_VCS;*/
396
397 pattrib->mdata = 0;
398 pattrib->eosp = 0;
399 pattrib->triggered = 0;
400
401 /* qos_en, ht_en, init rate, , bw, ch_offset, sgi */
402 pattrib->qos_en = psta->qos_option;
403
404 pattrib->raid = psta->raid;
405 pattrib->ht_en = psta->htpriv.ht_option;
406 pattrib->bwmode = psta->htpriv.bwmode;
407 pattrib->ch_offset = psta->htpriv.ch_offset;
408 pattrib->sgi = psta->htpriv.sgi;
409 pattrib->ampdu_en = false;
410
411 pattrib->retry_ctrl = false;
412}
413
414u8 qos_acm23a(u8 acm_mask, u8 priority)
415{
416 u8 change_priority = priority;
417
418 switch (priority) {
419 case 0:
420 case 3:
421 if (acm_mask & BIT(1))
422 change_priority = 1;
423 break;
424 case 1:
425 case 2:
426 break;
427 case 4:
428 case 5:
429 if (acm_mask & BIT(2))
430 change_priority = 0;
431 break;
432 case 6:
433 case 7:
434 if (acm_mask & BIT(3))
435 change_priority = 5;
436 break;
437 default:
438 DBG_8723A("qos_acm23a(): invalid pattrib->priority: %d!!!\n",
439 priority);
440 break;
441 }
442
443 return change_priority;
444}
445
446static void set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib)
447{
448 struct ethhdr etherhdr;
449 struct iphdr ip_hdr;
450 s32 UserPriority = 0;
451
452 _rtw_open_pktfile23a(ppktfile->pkt, ppktfile);
453 _rtw_pktfile_read23a(ppktfile, (unsigned char*)&etherhdr, ETH_HLEN);
454
455 /* get UserPriority from IP hdr */
456 if (pattrib->ether_type == 0x0800) {
457 _rtw_pktfile_read23a(ppktfile, (u8*)&ip_hdr, sizeof(ip_hdr));
458/* UserPriority = (ntohs(ip_hdr.tos) >> 5) & 0x3; */
459 UserPriority = ip_hdr.tos >> 5;
460 } else if (pattrib->ether_type == 0x888e) {
461 /* "When priority processing of data frames is supported, */
462 /* a STA's SME should send EAPOL-Key frames at the highest
463 priority." */
464 UserPriority = 7;
465 }
466
467 pattrib->priority = UserPriority;
468 pattrib->hdrlen = sizeof(struct ieee80211_qos_hdr);
469 pattrib->subtype = WIFI_QOS_DATA_TYPE;
470}
471
472static s32 update_attrib(struct rtw_adapter *padapter,
473 struct sk_buff *pkt, struct pkt_attrib *pattrib)
474{
475 uint i;
476 struct pkt_file pktfile;
477 struct sta_info *psta = NULL;
478 struct ethhdr etherhdr;
479
480 int bmcast;
481 struct sta_priv *pstapriv = &padapter->stapriv;
482 struct security_priv *psecuritypriv = &padapter->securitypriv;
483 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
484 struct qos_priv *pqospriv = &pmlmepriv->qospriv;
485 int res = _SUCCESS;
486
487 _rtw_open_pktfile23a(pkt, &pktfile);
488 i = _rtw_pktfile_read23a(&pktfile, (u8*)&etherhdr, ETH_HLEN);
489
490 pattrib->ether_type = ntohs(etherhdr.h_proto);
491
492 memcpy(pattrib->dst, &etherhdr.h_dest, ETH_ALEN);
493 memcpy(pattrib->src, &etherhdr.h_source, ETH_ALEN);
494
495 pattrib->pctrl = 0;
496
497 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
498 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
499 memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
500 memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
501 }
502 else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
503 memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
504 memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
505 }
506 else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
507 memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
508 memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN);
509 }
510
511 pattrib->pktlen = pktfile.pkt_len;
512
513 if (pattrib->ether_type == ETH_P_IP) {
514 /* The following is for DHCP and ARP packet, we use cck1M
515 to tx these packets and let LPS awake some time */
516 /* to prevent DHCP protocol fail */
517 u8 tmp[24];
518 _rtw_pktfile_read23a(&pktfile, &tmp[0], 24);
519 pattrib->dhcp_pkt = 0;
520 if (pktfile.pkt_len > 282) {/* MINIMUM_DHCP_PACKET_SIZE) { */
521 if (ETH_P_IP == pattrib->ether_type) {/* IP header */
522 if (((tmp[21] == 68) && (tmp[23] == 67)) ||
523 ((tmp[21] == 67) && (tmp[23] == 68))) {
524 /* 68 : UDP BOOTP client */
525 /* 67 : UDP BOOTP server */
526 RT_TRACE(_module_rtl871x_xmit_c_,
527 _drv_err_,
528 ("======================"
529 "update_attrib: get DHCP "
530 "Packet\n"));
531 pattrib->dhcp_pkt = 1;
532 }
533 }
534 }
535 } else if (0x888e == pattrib->ether_type) {
536 DBG_8723A_LEVEL(_drv_always_, "send eapol packet\n");
537 }
538
539 if ((pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1)) {
540 rtw_set_scan_deny(padapter, 3000);
541 }
542
543 /* If EAPOL , ARP , OR DHCP packet, driver must be in active mode. */
544 if ((pattrib->ether_type == 0x0806) ||
545 (pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1)) {
546 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SPECIAL_PACKET, 1);
547 }
548
549 bmcast = is_multicast_ether_addr(pattrib->ra);
550
551 /* get sta_info */
552 if (bmcast) {
553 psta = rtw_get_bcmc_stainfo23a(padapter);
554 } else {
555 psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
556 if (psta == NULL) { /* if we cannot get psta => drrp the pkt */
557 RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_,
558 ("\nupdate_attrib => get sta_info fail, ra:"
559 MAC_FMT"\n", MAC_ARG(pattrib->ra)));
560 res = _FAIL;
561 goto exit;
562 } else if ((check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) &&
563 (!(psta->state & _FW_LINKED))) {
564 res = _FAIL;
565 goto exit;
566 }
567 }
568
569 if (psta) {
570 pattrib->mac_id = psta->mac_id;
571 /* DBG_8723A("%s ==> mac_id(%d)\n", __func__, pattrib->mac_id); */
572 pattrib->psta = psta;
573 } else {
574 /* if we cannot get psta => drop the pkt */
575 RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_,
576 ("\nupdate_attrib => get sta_info fail, ra:" MAC_FMT
577 "\n", MAC_ARG(pattrib->ra)));
578 res = _FAIL;
579 goto exit;
580 }
581
582 pattrib->ack_policy = 0;
583 /* get ether_hdr_len */
584
585 /* pattrib->ether_type == 0x8100) ? (14 + 4): 14; vlan tag */
586 pattrib->pkt_hdrlen = ETH_HLEN;
587
588 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
589 pattrib->subtype = WIFI_DATA_TYPE;
590 pattrib->priority = 0;
591
592 if (check_fwstate(pmlmepriv, WIFI_AP_STATE | WIFI_ADHOC_STATE |
593 WIFI_ADHOC_MASTER_STATE)) {
594 if (psta->qos_option)
595 set_qos(&pktfile, pattrib);
596 } else {
597 if (pqospriv->qos_option) {
598 set_qos(&pktfile, pattrib);
599
600 if (pmlmepriv->acm_mask != 0) {
601 pattrib->priority = qos_acm23a(pmlmepriv->acm_mask,
602 pattrib->priority);
603 }
604 }
605 }
606
607 if (psta->ieee8021x_blocked == true) {
608 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
609 ("\n psta->ieee8021x_blocked == true\n"));
610
611 pattrib->encrypt = 0;
612
613 if ((pattrib->ether_type != 0x888e) &&
614 (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false)) {
615 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
616 ("\npsta->ieee8021x_blocked == true, "
617 "pattrib->ether_type(%.4x) != 0x888e\n",
618 pattrib->ether_type));
619 res = _FAIL;
620 goto exit;
621 }
622 } else {
623 GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast);
624
625 switch (psecuritypriv->dot11AuthAlgrthm) {
626 case dot11AuthAlgrthm_Open:
627 case dot11AuthAlgrthm_Shared:
628 case dot11AuthAlgrthm_Auto:
629 pattrib->key_idx =
630 (u8)psecuritypriv->dot11PrivacyKeyIndex;
631 break;
632 case dot11AuthAlgrthm_8021X:
633 if (bmcast)
634 pattrib->key_idx =
635 (u8)psecuritypriv->dot118021XGrpKeyid;
636 else
637 pattrib->key_idx = 0;
638 break;
639 default:
640 pattrib->key_idx = 0;
641 break;
642 }
643
644 }
645
646 switch (pattrib->encrypt) {
647 case _WEP40_:
648 case _WEP104_:
649 pattrib->iv_len = 4;
650 pattrib->icv_len = 4;
651 break;
652
653 case _TKIP_:
654 pattrib->iv_len = 8;
655 pattrib->icv_len = 4;
656
657 if (padapter->securitypriv.busetkipkey == _FAIL) {
658 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
659 ("\npadapter->securitypriv.busetkip"
660 "key(%d) == _FAIL drop packet\n",
661 padapter->securitypriv.busetkipkey));
662 res = _FAIL;
663 goto exit;
664 }
665
666 break;
667 case _AES_:
668 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
669 ("pattrib->encrypt =%d (_AES_)\n", pattrib->encrypt));
670 pattrib->iv_len = 8;
671 pattrib->icv_len = 8;
672 break;
673
674 default:
675 pattrib->iv_len = 0;
676 pattrib->icv_len = 0;
677 break;
678 }
679
680 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
681 ("update_attrib: encrypt =%d\n", pattrib->encrypt));
682
683 if (pattrib->encrypt && psecuritypriv->hw_decrypted == false) {
684 pattrib->bswenc = true;
685 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
686 ("update_attrib: encrypt =%d bswenc = true\n",
687 pattrib->encrypt));
688 } else {
689 pattrib->bswenc = false;
690 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
691 ("update_attrib: bswenc = false\n"));
692 }
693 update_attrib_phy_info(pattrib, psta);
694
695exit:
696
697 return res;
698}
699
700static s32 xmitframe_addmic(struct rtw_adapter *padapter,
701 struct xmit_frame *pxmitframe) {
702 struct mic_data micdata;
703 struct sta_info *stainfo;
704 struct pkt_attrib *pattrib = &pxmitframe->attrib;
705 struct security_priv *psecuritypriv = &padapter->securitypriv;
706 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
707 int curfragnum, length;
708 u8 *pframe, *payload, mic[8];
709 u8 priority[4]= {0x0, 0x0, 0x0, 0x0};
710 u8 hw_hdr_offset = 0;
711 int bmcst = is_multicast_ether_addr(pattrib->ra);
712
713 if (pattrib->psta) {
714 stainfo = pattrib->psta;
715 } else {
716 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
717 stainfo = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]);
718 }
719
720 if (!stainfo) {
721 DBG_8723A("%s, psta == NUL\n", __func__);
722 return _FAIL;
723 }
724
725 if (!(stainfo->state &_FW_LINKED)) {
726 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n",
727 __func__, stainfo->state);
728 return _FAIL;
729 }
730
731 hw_hdr_offset = TXDESC_OFFSET;
732
733 if (pattrib->encrypt == _TKIP_) {
734 /* encode mic code */
735 if (stainfo) {
736 u8 null_key[16]={0x0, 0x0, 0x0, 0x0,
737 0x0, 0x0, 0x0, 0x0,
738 0x0, 0x0, 0x0, 0x0,
739 0x0, 0x0, 0x0, 0x0};
740
741 pframe = pxmitframe->buf_addr + hw_hdr_offset;
742
743 if (bmcst) {
744 if (!memcmp(psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey, null_key, 16)) {
745 return _FAIL;
746 }
747 /* start to calculate the mic code */
748 rtw_secmicsetkey23a(&micdata, psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey);
749 } else {
750 if (!memcmp(&stainfo->dot11tkiptxmickey.skey[0],
751 null_key, 16)) {
752 return _FAIL;
753 }
754 /* start to calculate the mic code */
755 rtw_secmicsetkey23a(&micdata, &stainfo->dot11tkiptxmickey.skey[0]);
756 }
757
758 if (pframe[1] & 1) { /* ToDS == 1 */
759 /* DA */
760 rtw_secmicappend23a(&micdata, &pframe[16], 6);
761 if (pframe[1] & 2) /* From Ds == 1 */
762 rtw_secmicappend23a(&micdata,
763 &pframe[24], 6);
764 else
765 rtw_secmicappend23a(&micdata,
766 &pframe[10], 6);
767 } else { /* ToDS == 0 */
768 /* DA */
769 rtw_secmicappend23a(&micdata, &pframe[4], 6);
770 if (pframe[1] & 2) /* From Ds == 1 */
771 rtw_secmicappend23a(&micdata,
772 &pframe[16], 6);
773 else
774 rtw_secmicappend23a(&micdata,
775 &pframe[10], 6);
776 }
777
778 /* if (pqospriv->qos_option == 1) */
779 if (pattrib->qos_en)
780 priority[0] = (u8)pxmitframe->attrib.priority;
781
782 rtw_secmicappend23a(&micdata, &priority[0], 4);
783
784 payload = pframe;
785
786 for (curfragnum = 0; curfragnum < pattrib->nr_frags;
787 curfragnum++) {
788 payload = PTR_ALIGN(payload, 4);
789 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
790 ("=== curfragnum =%d, pframe = 0x%.2x, "
791 "0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x"
792 "%.2x, 0x%.2x, 0x%.2x,!!!\n",
793 curfragnum, *payload, *(payload + 1),
794 *(payload + 2), *(payload + 3),
795 *(payload + 4), *(payload + 5),
796 *(payload + 6), *(payload + 7)));
797
798 payload = payload + pattrib->hdrlen +
799 pattrib->iv_len;
800 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
801 ("curfragnum =%d pattrib->hdrlen =%d "
802 "pattrib->iv_len =%d", curfragnum,
803 pattrib->hdrlen, pattrib->iv_len));
804 if ((curfragnum + 1) == pattrib->nr_frags) {
805 length = pattrib->last_txcmdsz -
806 pattrib->hdrlen -
807 pattrib->iv_len -
808 ((pattrib->bswenc) ?
809 pattrib->icv_len : 0);
810 rtw_secmicappend23a(&micdata, payload,
811 length);
812 payload = payload + length;
813 } else {
814 length = pxmitpriv->frag_len -
815 pattrib->hdrlen -
816 pattrib->iv_len -
817 ((pattrib->bswenc) ?
818 pattrib->icv_len : 0);
819 rtw_secmicappend23a(&micdata, payload,
820 length);
821 payload = payload + length +
822 pattrib->icv_len;
823 RT_TRACE(_module_rtl871x_xmit_c_,
824 _drv_err_,
825 ("curfragnum =%d length =%d "
826 "pattrib->icv_len =%d",
827 curfragnum, length,
828 pattrib->icv_len));
829 }
830 }
831 rtw_secgetmic23a(&micdata, &mic[0]);
832 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
833 ("xmitframe_addmic: before add mic code!!\n"));
834 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
835 ("xmitframe_addmic: pattrib->last_txcmdsz ="
836 "%d!!!\n", pattrib->last_txcmdsz));
837 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
838 ("xmitframe_addmic: mic[0]= 0x%.2x , mic[1]="
839 "0x%.2x , mic[2]= 0x%.2x , mic[3]= 0x%.2x\n"
840 "mic[4]= 0x%.2x , mic[5]= 0x%.2x , mic[6]= 0x%.2x "
841 ", mic[7]= 0x%.2x !!!!\n", mic[0], mic[1],
842 mic[2], mic[3], mic[4], mic[5], mic[6],
843 mic[7]));
844 /* add mic code and add the mic code length
845 in last_txcmdsz */
846
847 memcpy(payload, &mic[0], 8);
848 pattrib->last_txcmdsz += 8;
849
850 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
851 ("\n ======== last pkt ========\n"));
852 payload = payload - pattrib->last_txcmdsz + 8;
853 for (curfragnum = 0; curfragnum < pattrib->last_txcmdsz;
854 curfragnum = curfragnum + 8)
855 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
856 (" %.2x, %.2x, %.2x, %.2x, %.2x, "
857 " %.2x, %.2x, %.2x ",
858 *(payload + curfragnum),
859 *(payload + curfragnum + 1),
860 *(payload + curfragnum + 2),
861 *(payload + curfragnum + 3),
862 *(payload + curfragnum + 4),
863 *(payload + curfragnum + 5),
864 *(payload + curfragnum + 6),
865 *(payload + curfragnum + 7)));
866 } else {
867 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
868 ("xmitframe_addmic: rtw_get_stainfo23a =="
869 "NULL!!!\n"));
870 }
871 }
872
873 return _SUCCESS;
874}
875
876static s32 xmitframe_swencrypt(struct rtw_adapter *padapter,
877 struct xmit_frame *pxmitframe)
878{
879 struct pkt_attrib *pattrib = &pxmitframe->attrib;
880
881 /* if ((psecuritypriv->sw_encrypt)||(pattrib->bswenc)) */
882 if (pattrib->bswenc) {
883 /* DBG_8723A("start xmitframe_swencrypt\n"); */
884 RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_,
885 ("### xmitframe_swencrypt\n"));
886 switch (pattrib->encrypt) {
887 case _WEP40_:
888 case _WEP104_:
889 rtw_wep_encrypt23a(padapter, pxmitframe);
890 break;
891 case _TKIP_:
892 rtw_tkip_encrypt23a(padapter, pxmitframe);
893 break;
894 case _AES_:
895 rtw_aes_encrypt23a(padapter, pxmitframe);
896 break;
897 default:
898 break;
899 }
900
901 } else {
902 RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_,
903 ("### xmitframe_hwencrypt\n"));
904 }
905
906 return _SUCCESS;
907}
908
909s32 rtw_make_wlanhdr23a(struct rtw_adapter *padapter, u8 *hdr,
910 struct pkt_attrib *pattrib)
911{
912 u16 *qc;
913
914 struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr;
915 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
916 struct qos_priv *pqospriv = &pmlmepriv->qospriv;
917 u8 qos_option = false;
918 int res = _SUCCESS;
919 u16 *fctrl = &pwlanhdr->frame_control;
920
921 struct sta_info *psta;
922
923 int bmcst = is_multicast_ether_addr(pattrib->ra);
924
925 if (pattrib->psta) {
926 psta = pattrib->psta;
927 } else {
928 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
929 if (bmcst) {
930 psta = rtw_get_bcmc_stainfo23a(padapter);
931 } else {
932 psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
933 }
934 }
935
936 if (psta == NULL) {
937 DBG_8723A("%s, psta == NUL\n", __func__);
938 return _FAIL;
939 }
940
941 if (!(psta->state &_FW_LINKED)) {
942 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
943 return _FAIL;
944 }
945
946 memset(hdr, 0, WLANHDR_OFFSET);
947
948 SetFrameSubType(fctrl, pattrib->subtype);
949
950 if (pattrib->subtype & WIFI_DATA_TYPE) {
951 if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)) {
952 /* to_ds = 1, fr_ds = 0; */
953 /* Data transfer to AP */
954 SetToDs(fctrl);
955 memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv), ETH_ALEN);
956 memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
957 memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN);
958
959 if (pqospriv->qos_option)
960 qos_option = true;
961
962 }
963 else if ((check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)) {
964 /* to_ds = 0, fr_ds = 1; */
965 SetFrDs(fctrl);
966 memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
967 memcpy(pwlanhdr->addr2, get_bssid(pmlmepriv), ETH_ALEN);
968 memcpy(pwlanhdr->addr3, pattrib->src, ETH_ALEN);
969
970 if (psta->qos_option)
971 qos_option = true;
972 }
973 else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
974 (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
975 memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
976 memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
977 memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN);
978
979 if (psta->qos_option)
980 qos_option = true;
981 }
982 else {
983 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("fw_state:%x is not allowed to xmit frame\n", get_fwstate(pmlmepriv)));
984 res = _FAIL;
985 goto exit;
986 }
987 if (pattrib->mdata)
988 SetMData(fctrl);
989 if (pattrib->encrypt)
990 SetPrivacy(fctrl);
991 if (qos_option) {
992 qc = (unsigned short *)(hdr + pattrib->hdrlen - 2);
993 if (pattrib->priority)
994 SetPriority(qc, pattrib->priority);
995 SetEOSP(qc, pattrib->eosp);
996 SetAckpolicy(qc, pattrib->ack_policy);
997 }
998 /* TODO: fill HT Control Field */
999
1000 /* Update Seq Num will be handled by f/w */
1001 if (psta) {
1002 psta->sta_xmitpriv.txseq_tid[pattrib->priority]++;
1003 psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF;
1004 pattrib->seqnum = psta->sta_xmitpriv.txseq_tid[pattrib->priority];
1005 SetSeqNum(hdr, pattrib->seqnum);
1006 /* check if enable ampdu */
1007 if (pattrib->ht_en && psta->htpriv.ampdu_enable) {
1008 if (psta->htpriv.agg_enable_bitmap & CHKBIT(pattrib->priority))
1009 pattrib->ampdu_en = true;
1010 }
1011 /* re-check if enable ampdu by BA_starting_seqctrl */
1012 if (pattrib->ampdu_en) {
1013 u16 tx_seq;
1014
1015 tx_seq = psta->BA_starting_seqctrl[pattrib->priority & 0x0f];
1016
1017 /* check BA_starting_seqctrl */
1018 if (SN_LESS(pattrib->seqnum, tx_seq)) {
1019 /* DBG_8723A("tx ampdu seqnum(%d) < tx_seq(%d)\n", pattrib->seqnum, tx_seq); */
1020 pattrib->ampdu_en = false;/* AGG BK */
1021 } else if (SN_EQUAL(pattrib->seqnum, tx_seq)) {
1022 psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (tx_seq+1)&0xfff;
1023 pattrib->ampdu_en = true;/* AGG EN */
1024 } else {
1025 /* DBG_8723A("tx ampdu over run\n"); */
1026 psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (pattrib->seqnum+1)&0xfff;
1027 pattrib->ampdu_en = true;/* AGG EN */
1028 }
1029 }
1030 }
1031 }
1032exit:
1033 return res;
1034}
1035
1036s32 rtw_txframes_pending23a(struct rtw_adapter *padapter)
1037{
1038 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1039
1040 return (!_rtw_queue_empty23a(&pxmitpriv->be_pending)) ||
1041 (!_rtw_queue_empty23a(&pxmitpriv->bk_pending)) ||
1042 (!_rtw_queue_empty23a(&pxmitpriv->vi_pending)) ||
1043 (!_rtw_queue_empty23a(&pxmitpriv->vo_pending));
1044}
1045
1046s32 rtw_txframes_sta_ac_pending23a(struct rtw_adapter *padapter,
1047 struct pkt_attrib *pattrib)
1048{
1049 struct sta_info *psta;
1050 struct tx_servq *ptxservq;
1051 int priority = pattrib->priority;
1052
1053 if (pattrib->psta) {
1054 psta = pattrib->psta;
1055 } else {
1056 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
1057 psta = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]);
1058 }
1059 if (psta == NULL) {
1060 DBG_8723A("%s, psta == NUL\n", __func__);
1061 return 0;
1062 }
1063 if (!(psta->state &_FW_LINKED)) {
1064 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__,
1065 psta->state);
1066 return 0;
1067 }
1068 switch (priority) {
1069 case 1:
1070 case 2:
1071 ptxservq = &psta->sta_xmitpriv.bk_q;
1072 break;
1073 case 4:
1074 case 5:
1075 ptxservq = &psta->sta_xmitpriv.vi_q;
1076 break;
1077 case 6:
1078 case 7:
1079 ptxservq = &psta->sta_xmitpriv.vo_q;
1080 break;
1081 case 0:
1082 case 3:
1083 default:
1084 ptxservq = &psta->sta_xmitpriv.be_q;
1085 break;
1086 }
1087 return ptxservq->qcnt;
1088}
1089
1090/*
1091 * Calculate wlan 802.11 packet MAX size from pkt_attrib
1092 * This function doesn't consider fragment case
1093 */
1094u32 rtw_calculate_wlan_pkt_size_by_attribue23a(struct pkt_attrib *pattrib)
1095{
1096 u32 len = 0;
1097
1098 len = pattrib->hdrlen + pattrib->iv_len; /* WLAN Header and IV */
1099 len += SNAP_SIZE + sizeof(u16); /* LLC */
1100 len += pattrib->pktlen;
1101 if (pattrib->encrypt == _TKIP_) len += 8; /* MIC */
1102 len += ((pattrib->bswenc) ? pattrib->icv_len : 0); /* ICV */
1103
1104 return len;
1105}
1106
1107/*
1108
1109This sub-routine will perform all the following:
1110
11111. remove 802.3 header.
11122. create wlan_header, based on the info in pxmitframe
11133. append sta's iv/ext-iv
11144. append LLC
11155. move frag chunk from pframe to pxmitframe->mem
11166. apply sw-encrypt, if necessary.
1117
1118*/
1119s32 rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *pkt,
1120 struct xmit_frame *pxmitframe)
1121{
1122 struct pkt_file pktfile;
1123 struct sta_info *psta;
1124 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1125 struct pkt_attrib *pattrib = &pxmitframe->attrib;
1126 s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz;
1127 u8 *pframe, *mem_start;
1128 u8 hw_hdr_offset;
1129 u8 *pbuf_start;
1130
1131 s32 bmcst = is_multicast_ether_addr(pattrib->ra);
1132 s32 res = _SUCCESS;
1133
1134 if (pattrib->psta) {
1135 psta = pattrib->psta;
1136 } else {
1137 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
1138 psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
1139 }
1140
1141 if (psta == NULL) {
1142 DBG_8723A("%s, psta == NUL\n", __func__);
1143 return _FAIL;
1144 }
1145
1146 if (!(psta->state &_FW_LINKED)) {
1147 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
1148 return _FAIL;
1149 }
1150
1151 if (pxmitframe->buf_addr == NULL) {
1152 DBG_8723A("==> %s buf_addr == NULL\n", __func__);
1153 return _FAIL;
1154 }
1155
1156 pbuf_start = pxmitframe->buf_addr;
1157
1158 hw_hdr_offset = TXDESC_OFFSET;
1159
1160 mem_start = pbuf_start + hw_hdr_offset;
1161
1162 if (rtw_make_wlanhdr23a(padapter, mem_start, pattrib) == _FAIL) {
1163 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
1164 ("rtw_xmitframe_coalesce23a: rtw_make_wlanhdr23a "
1165 "fail; drop pkt\n"));
1166 res = _FAIL;
1167 goto exit;
1168 }
1169
1170 _rtw_open_pktfile23a(pkt, &pktfile);
1171 _rtw_pktfile_read23a(&pktfile, NULL, pattrib->pkt_hdrlen);
1172
1173 frg_inx = 0;
1174 frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */
1175
1176 while (1) {
1177 llc_sz = 0;
1178
1179 mpdu_len = frg_len;
1180
1181 pframe = mem_start;
1182
1183 SetMFrag(mem_start);
1184
1185 pframe += pattrib->hdrlen;
1186 mpdu_len -= pattrib->hdrlen;
1187
1188 /* adding icv, if necessary... */
1189 if (pattrib->iv_len) {
1190 if (psta != NULL) {
1191 switch (pattrib->encrypt) {
1192 case _WEP40_:
1193 case _WEP104_:
1194 WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
1195 break;
1196 case _TKIP_:
1197 if (bmcst)
1198 TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
1199 else
1200 TKIP_IV(pattrib->iv, psta->dot11txpn, 0);
1201 break;
1202 case _AES_:
1203 if (bmcst)
1204 AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
1205 else
1206 AES_IV(pattrib->iv, psta->dot11txpn, 0);
1207 break;
1208 }
1209 }
1210
1211 memcpy(pframe, pattrib->iv, pattrib->iv_len);
1212
1213 RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_,
1214 ("rtw_xmiaframe_coalesce23a: keyid =%d pattrib"
1215 "->iv[3]=%.2x pframe =%.2x %.2x %.2x %.2x\n",
1216 padapter->securitypriv.dot11PrivacyKeyIndex,
1217 pattrib->iv[3], *pframe, *(pframe+1),
1218 *(pframe+2), *(pframe+3)));
1219 pframe += pattrib->iv_len;
1220 mpdu_len -= pattrib->iv_len;
1221 }
1222 if (frg_inx == 0) {
1223 llc_sz = rtw_put_snap23a(pframe, pattrib->ether_type);
1224 pframe += llc_sz;
1225 mpdu_len -= llc_sz;
1226 }
1227
1228 if ((pattrib->icv_len >0) && (pattrib->bswenc))
1229 mpdu_len -= pattrib->icv_len;
1230
1231 if (bmcst) {
1232 /* don't do fragment to broadcat/multicast packets */
1233 mem_sz = _rtw_pktfile_read23a(&pktfile, pframe, pattrib->pktlen);
1234 } else {
1235 mem_sz = _rtw_pktfile_read23a(&pktfile, pframe, mpdu_len);
1236 }
1237 pframe += mem_sz;
1238
1239 if ((pattrib->icv_len >0) && (pattrib->bswenc)) {
1240 memcpy(pframe, pattrib->icv, pattrib->icv_len);
1241 pframe += pattrib->icv_len;
1242 }
1243
1244 frg_inx++;
1245
1246 if (bmcst || (rtw_endofpktfile23a(&pktfile))) {
1247 pattrib->nr_frags = frg_inx;
1248
1249 pattrib->last_txcmdsz = pattrib->hdrlen +
1250 pattrib->iv_len +
1251 ((pattrib->nr_frags == 1) ?
1252 llc_sz : 0) +
1253 ((pattrib->bswenc) ?
1254 pattrib->icv_len : 0) + mem_sz;
1255
1256 ClearMFrag(mem_start);
1257
1258 break;
1259 } else {
1260 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: There're still something in packet!\n", __func__));
1261 }
1262
1263 mem_start = PTR_ALIGN(pframe, 4) + hw_hdr_offset;
1264 memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen);
1265
1266 }
1267
1268 if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) {
1269 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"));
1270 DBG_8723A("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n");
1271 res = _FAIL;
1272 goto exit;
1273 }
1274
1275 xmitframe_swencrypt(padapter, pxmitframe);
1276
1277 if (bmcst == false)
1278 update_attrib_vcs_info(padapter, pxmitframe);
1279 else
1280 pattrib->vcs_mode = NONE_VCS;
1281
1282exit:
1283 return res;
1284}
1285
1286/* Logical Link Control(LLC) SubNetwork Attachment Point(SNAP) header
1287 * IEEE LLC/SNAP header contains 8 octets
1288 * First 3 octets comprise the LLC portion
1289 * SNAP portion, 5 octets, is divided into two fields:
1290 * Organizationally Unique Identifier(OUI), 3 octets,
1291 * type, defined by that organization, 2 octets.
1292 */
1293s32 rtw_put_snap23a(u8 *data, u16 h_proto)
1294{
1295 struct ieee80211_snap_hdr *snap;
1296 u8 *oui;
1297
1298 snap = (struct ieee80211_snap_hdr *)data;
1299 snap->dsap = 0xaa;
1300 snap->ssap = 0xaa;
1301 snap->ctrl = 0x03;
1302
1303 if (h_proto == 0x8137 || h_proto == 0x80f3)
1304 oui = P802_1H_OUI;
1305 else
1306 oui = RFC1042_OUI;
1307 snap->oui[0] = oui[0];
1308 snap->oui[1] = oui[1];
1309 snap->oui[2] = oui[2];
1310 *(u16 *)(data + SNAP_SIZE) = htons(h_proto);
1311 return SNAP_SIZE + sizeof(u16);
1312}
1313
1314void rtw_update_protection23a(struct rtw_adapter *padapter, u8 *ie, uint ie_len)
1315{
1316 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1317 struct registry_priv *pregistrypriv = &padapter->registrypriv;
1318 uint protection;
1319 u8 *perp;
1320 int erp_len;
1321
1322 switch (pxmitpriv->vcs_setting) {
1323 case DISABLE_VCS:
1324 pxmitpriv->vcs = NONE_VCS;
1325 break;
1326 case ENABLE_VCS:
1327 break;
1328 case AUTO_VCS:
1329 default:
1330 perp = rtw_get_ie23a(ie, _ERPINFO_IE_, &erp_len, ie_len);
1331 if (perp == NULL) {
1332 pxmitpriv->vcs = NONE_VCS;
1333 } else {
1334 protection = (*(perp + 2)) & BIT(1);
1335 if (protection) {
1336 if (pregistrypriv->vcs_type == RTS_CTS)
1337 pxmitpriv->vcs = RTS_CTS;
1338 else
1339 pxmitpriv->vcs = CTS_TO_SELF;
1340 } else {
1341 pxmitpriv->vcs = NONE_VCS;
1342 }
1343 }
1344 break;
1345 }
1346}
1347
1348void rtw_count_tx_stats23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe, int sz)
1349{
1350 struct sta_info *psta = NULL;
1351 struct stainfo_stats *pstats = NULL;
1352 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1353 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1354
1355 if ((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) {
1356 pxmitpriv->tx_bytes += sz;
1357 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod++;
1358
1359 psta = pxmitframe->attrib.psta;
1360 if (psta) {
1361 pstats = &psta->sta_stats;
1362 pstats->tx_pkts++;
1363 pstats->tx_bytes += sz;
1364 }
1365 }
1366}
1367
1368struct xmit_buf *rtw_alloc_xmitbuf23a_ext(struct xmit_priv *pxmitpriv)
1369{
1370 unsigned long irqL;
1371 struct xmit_buf *pxmitbuf = NULL;
1372 struct list_head *phead;
1373 struct rtw_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
1374
1375 spin_lock_irqsave(&pfree_queue->lock, irqL);
1376
1377 phead = get_list_head(pfree_queue);
1378
1379 if (!list_empty(phead)) {
1380 pxmitbuf = list_first_entry(phead, struct xmit_buf, list);
1381
1382 list_del_init(&pxmitbuf->list);
1383
1384 pxmitpriv->free_xmit_extbuf_cnt--;
1385 pxmitbuf->priv_data = NULL;
1386 pxmitbuf->ext_tag = true;
1387
1388 if (pxmitbuf->sctx) {
1389 DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__);
1390 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
1391 }
1392 }
1393
1394 spin_unlock_irqrestore(&pfree_queue->lock, irqL);
1395
1396 return pxmitbuf;
1397}
1398
1399s32 rtw_free_xmitbuf_ext23a(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
1400{
1401 unsigned long irqL;
1402 struct rtw_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
1403
1404 if (pxmitbuf == NULL)
1405 return _FAIL;
1406
1407 spin_lock_irqsave(&pfree_queue->lock, irqL);
1408
1409 list_del_init(&pxmitbuf->list);
1410
1411 list_add_tail(&pxmitbuf->list, get_list_head(pfree_queue));
1412 pxmitpriv->free_xmit_extbuf_cnt++;
1413
1414 spin_unlock_irqrestore(&pfree_queue->lock, irqL);
1415
1416 return _SUCCESS;
1417}
1418
1419struct xmit_buf *rtw_alloc_xmitbuf23a(struct xmit_priv *pxmitpriv)
1420{
1421 unsigned long irqL;
1422 struct xmit_buf *pxmitbuf = NULL;
1423 struct list_head *phead;
1424 struct rtw_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
1425
1426 /* DBG_8723A("+rtw_alloc_xmitbuf23a\n"); */
1427
1428 spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
1429
1430 phead = get_list_head(pfree_xmitbuf_queue);
1431
1432 if (!list_empty(phead)) {
1433 pxmitbuf = list_first_entry(phead, struct xmit_buf, list);
1434
1435 list_del_init(&pxmitbuf->list);
1436
1437 pxmitpriv->free_xmitbuf_cnt--;
1438 pxmitbuf->priv_data = NULL;
1439 pxmitbuf->ext_tag = false;
1440 pxmitbuf->flags = XMIT_VO_QUEUE;
1441
1442 if (pxmitbuf->sctx) {
1443 DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__);
1444 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
1445 }
1446 }
1447
1448 spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
1449
1450 return pxmitbuf;
1451}
1452
1453s32 rtw_free_xmitbuf23a(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
1454{
1455 unsigned long irqL;
1456 struct rtw_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
1457
1458 /* DBG_8723A("+rtw_free_xmitbuf23a\n"); */
1459
1460 if (pxmitbuf == NULL)
1461 return _FAIL;
1462
1463 if (pxmitbuf->sctx) {
1464 DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__);
1465 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE);
1466 }
1467
1468 if (pxmitbuf->ext_tag) {
1469 rtw_free_xmitbuf_ext23a(pxmitpriv, pxmitbuf);
1470 } else {
1471 spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
1472
1473 list_del_init(&pxmitbuf->list);
1474
1475 list_add_tail(&pxmitbuf->list,
1476 get_list_head(pfree_xmitbuf_queue));
1477
1478 pxmitpriv->free_xmitbuf_cnt++;
1479 spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
1480 }
1481
1482 return _SUCCESS;
1483}
1484
1485static void rtw_init_xmitframe(struct xmit_frame *pxframe)
1486{
1487 if (pxframe != NULL) {
1488 /* default value setting */
1489 pxframe->buf_addr = NULL;
1490 pxframe->pxmitbuf = NULL;
1491
1492 memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib));
1493 /* pxframe->attrib.psta = NULL; */
1494
1495 pxframe->frame_tag = DATA_FRAMETAG;
1496
1497 pxframe->pkt = NULL;
1498 pxframe->pkt_offset = 1;/* default use pkt_offset to fill tx desc */
1499
1500 pxframe->ack_report = 0;
1501 }
1502}
1503
1504/*
1505Calling context:
15061. OS_TXENTRY
15072. RXENTRY (rx_thread or RX_ISR/RX_CallBack)
1508
1509If we turn on USE_RXTHREAD, then, no need for critical section.
1510Otherwise, we must use _enter/_exit critical to protect free_xmit_queue...
1511
1512Must be very very cautious...
1513
1514*/
1515struct xmit_frame *rtw_alloc_xmitframe23a(struct xmit_priv *pxmitpriv)/* _queue *pfree_xmit_queue) */
1516{
1517 /*
1518 Please remember to use all the osdep_service api,
1519 and lock/unlock or _enter/_exit critical to protect
1520 pfree_xmit_queue
1521 */
1522
1523 struct xmit_frame *pxframe = NULL;
1524 struct list_head *plist, *phead;
1525 struct rtw_queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
1526
1527 spin_lock_bh(&pfree_xmit_queue->lock);
1528
1529 if (_rtw_queue_empty23a(pfree_xmit_queue) == true) {
1530 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe23a:%d\n", pxmitpriv->free_xmitframe_cnt));
1531 pxframe = NULL;
1532 } else {
1533 phead = get_list_head(pfree_xmit_queue);
1534
1535 plist = phead->next;
1536
1537 pxframe = container_of(plist, struct xmit_frame, list);
1538
1539 list_del_init(&pxframe->list);
1540 pxmitpriv->free_xmitframe_cnt--;
1541 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe23a():free_xmitframe_cnt =%d\n", pxmitpriv->free_xmitframe_cnt));
1542 }
1543
1544 spin_unlock_bh(&pfree_xmit_queue->lock);
1545
1546 rtw_init_xmitframe(pxframe);
1547
1548 return pxframe;
1549}
1550
1551struct xmit_frame *rtw_alloc_xmitframe23a_ext(struct xmit_priv *pxmitpriv)
1552{
1553 struct xmit_frame *pxframe = NULL;
1554 struct list_head *plist, *phead;
1555 struct rtw_queue *queue = &pxmitpriv->free_xframe_ext_queue;
1556
1557 spin_lock_bh(&queue->lock);
1558
1559 if (_rtw_queue_empty23a(queue) == true) {
1560 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe23a_ext:%d\n", pxmitpriv->free_xframe_ext_cnt));
1561 pxframe = NULL;
1562 } else {
1563 phead = get_list_head(queue);
1564 plist = phead->next;
1565 pxframe = container_of(plist, struct xmit_frame, list);
1566
1567 list_del_init(&pxframe->list);
1568 pxmitpriv->free_xframe_ext_cnt--;
1569 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe23a_ext():free_xmitframe_cnt =%d\n", pxmitpriv->free_xframe_ext_cnt));
1570 }
1571
1572 spin_unlock_bh(&queue->lock);
1573
1574 rtw_init_xmitframe(pxframe);
1575
1576 return pxframe;
1577}
1578
1579s32 rtw_free_xmitframe23a(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe)
1580{
1581 struct rtw_queue *queue = NULL;
1582 struct rtw_adapter *padapter = pxmitpriv->adapter;
1583 struct sk_buff *pndis_pkt = NULL;
1584
1585 if (pxmitframe == NULL) {
1586 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("====== rtw_free_xmitframe23a():pxmitframe == NULL!!!!!!!!!!\n"));
1587 goto exit;
1588 }
1589
1590 if (pxmitframe->pkt) {
1591 pndis_pkt = pxmitframe->pkt;
1592 pxmitframe->pkt = NULL;
1593 }
1594
1595 if (pxmitframe->ext_tag == 0)
1596 queue = &pxmitpriv->free_xmit_queue;
1597 else if (pxmitframe->ext_tag == 1)
1598 queue = &pxmitpriv->free_xframe_ext_queue;
1599
1600 if (!queue)
1601 goto check_pkt_complete;
1602 spin_lock_bh(&queue->lock);
1603
1604 list_del_init(&pxmitframe->list);
1605 list_add_tail(&pxmitframe->list, get_list_head(queue));
1606 if (pxmitframe->ext_tag == 0) {
1607 pxmitpriv->free_xmitframe_cnt++;
1608 RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("rtw_free_xmitframe23a():free_xmitframe_cnt =%d\n", pxmitpriv->free_xmitframe_cnt));
1609 } else if (pxmitframe->ext_tag == 1) {
1610 pxmitpriv->free_xframe_ext_cnt++;
1611 RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("rtw_free_xmitframe23a():free_xframe_ext_cnt =%d\n", pxmitpriv->free_xframe_ext_cnt));
1612 }
1613
1614 spin_unlock_bh(&queue->lock);
1615
1616check_pkt_complete:
1617
1618 if (pndis_pkt)
1619 rtw_os_pkt_complete23a(padapter, pndis_pkt);
1620
1621exit:
1622
1623 return _SUCCESS;
1624}
1625
1626void rtw_free_xmitframe_queue23a(struct xmit_priv *pxmitpriv,
1627 struct rtw_queue *pframequeue)
1628{
1629 struct list_head *plist, *phead, *ptmp;
1630 struct xmit_frame *pxmitframe;
1631
1632 spin_lock_bh(&pframequeue->lock);
1633
1634 phead = get_list_head(pframequeue);
1635
1636 list_for_each_safe(plist, ptmp, phead) {
1637 pxmitframe = container_of(plist, struct xmit_frame, list);
1638
1639 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
1640 }
1641 spin_unlock_bh(&pframequeue->lock);
1642
1643}
1644
1645s32 rtw_xmitframe_enqueue23a(struct rtw_adapter *padapter,
1646 struct xmit_frame *pxmitframe)
1647{
1648 if (rtw_xmit23a_classifier(padapter, pxmitframe) == _FAIL) {
1649 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
1650 ("rtw_xmitframe_enqueue23a: drop xmit pkt for "
1651 "classifier fail\n"));
1652 return _FAIL;
1653 }
1654
1655 return _SUCCESS;
1656}
1657
1658static struct xmit_frame *
1659dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit,
1660 struct tx_servq *ptxservq, struct rtw_queue *pframe_queue)
1661{
1662 struct list_head *phead;
1663 struct xmit_frame *pxmitframe = NULL;
1664
1665 phead = get_list_head(pframe_queue);
1666
1667 if (!list_empty(phead)) {
1668 pxmitframe = list_first_entry(phead, struct xmit_frame, list);
1669 list_del_init(&pxmitframe->list);
1670 ptxservq->qcnt--;
1671 }
1672 return pxmitframe;
1673}
1674
1675struct xmit_frame *
1676rtw_dequeue_xframe23a(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit_i,
1677 int entry)
1678{
1679 struct list_head *sta_plist, *sta_phead, *ptmp;
1680 struct hw_xmit *phwxmit;
1681 struct tx_servq *ptxservq = NULL;
1682 struct rtw_queue *pframe_queue = NULL;
1683 struct xmit_frame *pxmitframe = NULL;
1684 struct rtw_adapter *padapter = pxmitpriv->adapter;
1685 struct registry_priv *pregpriv = &padapter->registrypriv;
1686 int i, inx[4];
1687
1688 inx[0] = 0;
1689 inx[1] = 1;
1690 inx[2] = 2;
1691 inx[3] = 3;
1692 if (pregpriv->wifi_spec == 1) {
1693 int j;
1694
1695 for (j = 0; j < 4; j++)
1696 inx[j] = pxmitpriv->wmm_para_seq[j];
1697 }
1698
1699 spin_lock_bh(&pxmitpriv->lock);
1700
1701 for (i = 0; i < entry; i++) {
1702 phwxmit = phwxmit_i + inx[i];
1703
1704 sta_phead = get_list_head(phwxmit->sta_queue);
1705
1706 list_for_each_safe(sta_plist, ptmp, sta_phead) {
1707 ptxservq = container_of(sta_plist, struct tx_servq,
1708 tx_pending);
1709
1710 pframe_queue = &ptxservq->sta_pending;
1711
1712 pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, ptxservq, pframe_queue);
1713
1714 if (pxmitframe) {
1715 phwxmit->accnt--;
1716
1717 /* Remove sta node when there is no pending packets. */
1718 if (_rtw_queue_empty23a(pframe_queue)) /* must be done after get_next and before break */
1719 list_del_init(&ptxservq->tx_pending);
1720 goto exit;
1721 }
1722 }
1723 }
1724exit:
1725 spin_unlock_bh(&pxmitpriv->lock);
1726 return pxmitframe;
1727}
1728
1729struct tx_servq *rtw_get_sta_pending23a(struct rtw_adapter *padapter, struct sta_info *psta, int up, u8 *ac)
1730{
1731 struct tx_servq *ptxservq = NULL;
1732
1733 switch (up) {
1734 case 1:
1735 case 2:
1736 ptxservq = &psta->sta_xmitpriv.bk_q;
1737 *(ac) = 3;
1738 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : BK\n"));
1739 break;
1740 case 4:
1741 case 5:
1742 ptxservq = &psta->sta_xmitpriv.vi_q;
1743 *(ac) = 1;
1744 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : VI\n"));
1745 break;
1746 case 6:
1747 case 7:
1748 ptxservq = &psta->sta_xmitpriv.vo_q;
1749 *(ac) = 0;
1750 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : VO\n"));
1751 break;
1752 case 0:
1753 case 3:
1754 default:
1755 ptxservq = &psta->sta_xmitpriv.be_q;
1756 *(ac) = 2;
1757 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : BE\n"));
1758 break;
1759 }
1760 return ptxservq;
1761}
1762
1763/*
1764 * Will enqueue pxmitframe to the proper queue,
1765 * and indicate it to xx_pending list.....
1766 */
1767s32 rtw_xmit23a_classifier(struct rtw_adapter *padapter,
1768 struct xmit_frame *pxmitframe)
1769{
1770 struct sta_info *psta;
1771 struct tx_servq *ptxservq;
1772 struct pkt_attrib *pattrib = &pxmitframe->attrib;
1773 struct sta_priv *pstapriv = &padapter->stapriv;
1774 struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
1775 u8 ac_index;
1776 int res = _SUCCESS;
1777
1778 if (pattrib->psta) {
1779 psta = pattrib->psta;
1780 } else {
1781 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
1782 psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
1783 }
1784 if (psta == NULL) {
1785 res = _FAIL;
1786 DBG_8723A("rtw_xmit23a_classifier: psta == NULL\n");
1787 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
1788 ("rtw_xmit23a_classifier: psta == NULL\n"));
1789 goto exit;
1790 }
1791 if (!(psta->state & _FW_LINKED)) {
1792 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__,
1793 psta->state);
1794 return _FAIL;
1795 }
1796 ptxservq = rtw_get_sta_pending23a(padapter, psta, pattrib->priority,
1797 (u8 *)(&ac_index));
1798
1799 if (list_empty(&ptxservq->tx_pending)) {
1800 list_add_tail(&ptxservq->tx_pending,
1801 get_list_head(phwxmits[ac_index].sta_queue));
1802 }
1803
1804 list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending));
1805 ptxservq->qcnt++;
1806 phwxmits[ac_index].accnt++;
1807exit:
1808 return res;
1809}
1810
1811void rtw_alloc_hwxmits23a(struct rtw_adapter *padapter)
1812{
1813 struct hw_xmit *hwxmits;
1814 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1815 int size;
1816
1817 pxmitpriv->hwxmit_entry = HWXMIT_ENTRY;
1818
1819 size = sizeof(struct hw_xmit) * (pxmitpriv->hwxmit_entry + 1);
1820 pxmitpriv->hwxmits = kzalloc(size, GFP_KERNEL);
1821
1822 hwxmits = pxmitpriv->hwxmits;
1823
1824 if (pxmitpriv->hwxmit_entry == 5) {
1825 /* pxmitpriv->bmc_txqueue.head = 0; */
1826 /* hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue; */
1827 hwxmits[0] .sta_queue = &pxmitpriv->bm_pending;
1828
1829 /* pxmitpriv->vo_txqueue.head = 0; */
1830 /* hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue; */
1831 hwxmits[1] .sta_queue = &pxmitpriv->vo_pending;
1832
1833 /* pxmitpriv->vi_txqueue.head = 0; */
1834 /* hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue; */
1835 hwxmits[2] .sta_queue = &pxmitpriv->vi_pending;
1836
1837 /* pxmitpriv->bk_txqueue.head = 0; */
1838 /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */
1839 hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
1840
1841 /* pxmitpriv->be_txqueue.head = 0; */
1842 /* hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue; */
1843 hwxmits[4] .sta_queue = &pxmitpriv->be_pending;
1844
1845 } else if (pxmitpriv->hwxmit_entry == 4) {
1846
1847 /* pxmitpriv->vo_txqueue.head = 0; */
1848 /* hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue; */
1849 hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
1850
1851 /* pxmitpriv->vi_txqueue.head = 0; */
1852 /* hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue; */
1853 hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
1854
1855 /* pxmitpriv->be_txqueue.head = 0; */
1856 /* hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue; */
1857 hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
1858
1859 /* pxmitpriv->bk_txqueue.head = 0; */
1860 /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */
1861 hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
1862 } else {
1863
1864 }
1865}
1866
1867void rtw_free_hwxmits23a(struct rtw_adapter *padapter)
1868{
1869 struct hw_xmit *hwxmits;
1870 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1871
1872 hwxmits = pxmitpriv->hwxmits;
1873 kfree(hwxmits);
1874}
1875
1876void rtw_init_hwxmits23a(struct hw_xmit *phwxmit, int entry)
1877{
1878 int i;
1879
1880 for (i = 0; i < entry; i++, phwxmit++)
1881 phwxmit->accnt = 0;
1882}
1883
1884u32 rtw_get_ff_hwaddr23a(struct xmit_frame *pxmitframe)
1885{
1886 u32 addr;
1887 struct pkt_attrib *pattrib = &pxmitframe->attrib;
1888
1889 switch (pattrib->qsel) {
1890 case 0:
1891 case 3:
1892 addr = BE_QUEUE_INX;
1893 break;
1894 case 1:
1895 case 2:
1896 addr = BK_QUEUE_INX;
1897 break;
1898 case 4:
1899 case 5:
1900 addr = VI_QUEUE_INX;
1901 break;
1902 case 6:
1903 case 7:
1904 addr = VO_QUEUE_INX;
1905 break;
1906 case 0x10:
1907 addr = BCN_QUEUE_INX;
1908 break;
1909 case 0x11:/* BC/MC in PS (HIQ) */
1910 addr = HIGH_QUEUE_INX;
1911 break;
1912 case 0x12:
1913 default:
1914 addr = MGT_QUEUE_INX;
1915 break;
1916 }
1917
1918 return addr;
1919}
1920
1921static void do_queue_select(struct rtw_adapter *padapter, struct pkt_attrib *pattrib)
1922{
1923 u8 qsel;
1924
1925 qsel = pattrib->priority;
1926 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
1927 ("### do_queue_select priority =%d , qsel = %d\n",
1928 pattrib->priority, qsel));
1929
1930 pattrib->qsel = qsel;
1931}
1932
1933/*
1934 * The main transmit(tx) entry
1935 *
1936 * Return
1937 * 1 enqueue
1938 * 0 success, hardware will handle this xmit frame(packet)
1939 * <0 fail
1940 */
1941int rtw_xmit23a(struct rtw_adapter *padapter, struct sk_buff *skb)
1942{
1943 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1944 struct xmit_frame *pxmitframe = NULL;
1945 s32 res;
1946
1947 pxmitframe = rtw_alloc_xmitframe23a(pxmitpriv);
1948
1949 if (pxmitframe == NULL) {
1950 RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
1951 ("rtw_xmit23a: no more pxmitframe\n"));
1952 return -1;
1953 }
1954
1955 res = update_attrib(padapter, skb, &pxmitframe->attrib);
1956
1957 if (res == _FAIL) {
1958 RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit23a: update attrib fail\n"));
1959 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
1960 return -1;
1961 }
1962 pxmitframe->pkt = skb;
1963
1964 rtw_led_control(padapter, LED_CTL_TX);
1965
1966 do_queue_select(padapter, &pxmitframe->attrib);
1967
1968#ifdef CONFIG_8723AU_AP_MODE
1969 spin_lock_bh(&pxmitpriv->lock);
1970 if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) {
1971 spin_unlock_bh(&pxmitpriv->lock);
1972 return 1;
1973 }
1974 spin_unlock_bh(&pxmitpriv->lock);
1975#endif
1976
1977 if (rtw_hal_xmit23a(padapter, pxmitframe) == false)
1978 return 1;
1979
1980 return 0;
1981}
1982
1983#if defined(CONFIG_8723AU_AP_MODE)
1984
1985int xmitframe_enqueue_for_sleeping_sta23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
1986{
1987 int ret = false;
1988 struct sta_info *psta = NULL;
1989 struct sta_priv *pstapriv = &padapter->stapriv;
1990 struct pkt_attrib *pattrib = &pxmitframe->attrib;
1991 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1992 int bmcst = is_multicast_ether_addr(pattrib->ra);
1993
1994 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == false)
1995 return ret;
1996
1997 if (pattrib->psta) {
1998 psta = pattrib->psta;
1999 } else {
2000 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
2001 psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
2002 }
2003
2004 if (psta == NULL) {
2005 DBG_8723A("%s, psta == NUL\n", __func__);
2006 return false;
2007 }
2008
2009 if (!(psta->state & _FW_LINKED)) {
2010 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__,
2011 psta->state);
2012 return false;
2013 }
2014
2015 if (pattrib->triggered == 1) {
2016 if (bmcst)
2017 pattrib->qsel = 0x11;/* HIQ */
2018 return ret;
2019 }
2020
2021 if (bmcst) {
2022 spin_lock_bh(&psta->sleep_q.lock);
2023
2024 if (pstapriv->sta_dz_bitmap) {
2025 /* if anyone sta is in ps mode */
2026 list_del_init(&pxmitframe->list);
2027
2028 /* spin_lock_bh(&psta->sleep_q.lock); */
2029
2030 list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
2031
2032 psta->sleepq_len++;
2033
2034 pstapriv->tim_bitmap |= BIT(0);/* */
2035 pstapriv->sta_dz_bitmap |= BIT(0);
2036
2037 /* DBG_8723A("enqueue, sq_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */
2038
2039 update_beacon23a(padapter, _TIM_IE_, NULL, false);/* tx bc/mc packets after upate bcn */
2040
2041 /* spin_unlock_bh(&psta->sleep_q.lock); */
2042
2043 ret = true;
2044
2045 }
2046
2047 spin_unlock_bh(&psta->sleep_q.lock);
2048
2049 return ret;
2050
2051 }
2052
2053 spin_lock_bh(&psta->sleep_q.lock);
2054
2055 if (psta->state&WIFI_SLEEP_STATE) {
2056 u8 wmmps_ac = 0;
2057
2058 if (pstapriv->sta_dz_bitmap & CHKBIT(psta->aid)) {
2059 list_del_init(&pxmitframe->list);
2060
2061 /* spin_lock_bh(&psta->sleep_q.lock); */
2062
2063 list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
2064
2065 psta->sleepq_len++;
2066
2067 switch (pattrib->priority) {
2068 case 1:
2069 case 2:
2070 wmmps_ac = psta->uapsd_bk & BIT(0);
2071 break;
2072 case 4:
2073 case 5:
2074 wmmps_ac = psta->uapsd_vi & BIT(0);
2075 break;
2076 case 6:
2077 case 7:
2078 wmmps_ac = psta->uapsd_vo & BIT(0);
2079 break;
2080 case 0:
2081 case 3:
2082 default:
2083 wmmps_ac = psta->uapsd_be & BIT(0);
2084 break;
2085 }
2086
2087 if (wmmps_ac)
2088 psta->sleepq_ac_len++;
2089
2090 if (((psta->has_legacy_ac) && (!wmmps_ac)) ||
2091 ((!psta->has_legacy_ac) && (wmmps_ac))) {
2092 pstapriv->tim_bitmap |= CHKBIT(psta->aid);
2093
2094 if (psta->sleepq_len == 1) {
2095 /* upate BCN for TIM IE */
2096 update_beacon23a(padapter, _TIM_IE_, NULL, false);
2097 }
2098 }
2099
2100 /* spin_unlock_bh(&psta->sleep_q.lock); */
2101
2102 /* if (psta->sleepq_len > (NR_XMITFRAME>>3)) */
2103 /* */
2104 /* wakeup_sta_to_xmit23a(padapter, psta); */
2105 /* */
2106
2107 ret = true;
2108
2109 }
2110
2111 }
2112
2113 spin_unlock_bh(&psta->sleep_q.lock);
2114
2115 return ret;
2116}
2117
2118static void
2119dequeue_xmitframes_to_sleeping_queue(struct rtw_adapter *padapter,
2120 struct sta_info *psta,
2121 struct rtw_queue *pframequeue)
2122{
2123 int ret;
2124 struct list_head *plist, *phead, *ptmp;
2125 u8 ac_index;
2126 struct tx_servq *ptxservq;
2127 struct pkt_attrib *pattrib;
2128 struct xmit_frame *pxmitframe;
2129 struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
2130
2131 phead = get_list_head(pframequeue);
2132
2133 list_for_each_safe(plist, ptmp, phead) {
2134 pxmitframe = container_of(plist, struct xmit_frame, list);
2135
2136 ret = xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe);
2137
2138 if (ret == true) {
2139 pattrib = &pxmitframe->attrib;
2140
2141 ptxservq = rtw_get_sta_pending23a(padapter, psta, pattrib->priority, (u8 *)(&ac_index));
2142
2143 ptxservq->qcnt--;
2144 phwxmits[ac_index].accnt--;
2145 } else {
2146 /* DBG_8723A("xmitframe_enqueue_for_sleeping_sta23a return false\n"); */
2147 }
2148 }
2149}
2150
2151void stop_sta_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta)
2152{
2153 struct sta_info *psta_bmc;
2154 struct sta_xmit_priv *pstaxmitpriv;
2155 struct sta_priv *pstapriv = &padapter->stapriv;
2156 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2157
2158 pstaxmitpriv = &psta->sta_xmitpriv;
2159
2160 /* for BC/MC Frames */
2161 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
2162
2163 spin_lock_bh(&pxmitpriv->lock);
2164
2165 psta->state |= WIFI_SLEEP_STATE;
2166
2167 pstapriv->sta_dz_bitmap |= CHKBIT(psta->aid);
2168
2169 dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending);
2170 list_del_init(&pstaxmitpriv->vo_q.tx_pending);
2171
2172 dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vi_q.sta_pending);
2173 list_del_init(&pstaxmitpriv->vi_q.tx_pending);
2174
2175 dequeue_xmitframes_to_sleeping_queue(padapter, psta,
2176 &pstaxmitpriv->be_q.sta_pending);
2177 list_del_init(&pstaxmitpriv->be_q.tx_pending);
2178
2179 dequeue_xmitframes_to_sleeping_queue(padapter, psta,
2180 &pstaxmitpriv->bk_q.sta_pending);
2181 list_del_init(&pstaxmitpriv->bk_q.tx_pending);
2182
2183 /* for BC/MC Frames */
2184 pstaxmitpriv = &psta_bmc->sta_xmitpriv;
2185 dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc,
2186 &pstaxmitpriv->be_q.sta_pending);
2187 list_del_init(&pstaxmitpriv->be_q.tx_pending);
2188
2189 spin_unlock_bh(&pxmitpriv->lock);
2190}
2191
2192void wakeup_sta_to_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta)
2193{
2194 u8 update_mask = 0, wmmps_ac = 0;
2195 struct sta_info *psta_bmc;
2196 struct list_head *plist, *phead, *ptmp;
2197 struct xmit_frame *pxmitframe = NULL;
2198 struct sta_priv *pstapriv = &padapter->stapriv;
2199 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2200
2201 spin_lock_bh(&pxmitpriv->lock);
2202
2203 phead = get_list_head(&psta->sleep_q);
2204
2205 list_for_each_safe(plist, ptmp, phead) {
2206 pxmitframe = container_of(plist, struct xmit_frame, list);
2207 list_del_init(&pxmitframe->list);
2208
2209 switch (pxmitframe->attrib.priority) {
2210 case 1:
2211 case 2:
2212 wmmps_ac = psta->uapsd_bk & BIT(1);
2213 break;
2214 case 4:
2215 case 5:
2216 wmmps_ac = psta->uapsd_vi & BIT(1);
2217 break;
2218 case 6:
2219 case 7:
2220 wmmps_ac = psta->uapsd_vo & BIT(1);
2221 break;
2222 case 0:
2223 case 3:
2224 default:
2225 wmmps_ac = psta->uapsd_be & BIT(1);
2226 break;
2227 }
2228
2229 psta->sleepq_len--;
2230 if (psta->sleepq_len > 0)
2231 pxmitframe->attrib.mdata = 1;
2232 else
2233 pxmitframe->attrib.mdata = 0;
2234
2235 if (wmmps_ac) {
2236 psta->sleepq_ac_len--;
2237 if (psta->sleepq_ac_len > 0) {
2238 pxmitframe->attrib.mdata = 1;
2239 pxmitframe->attrib.eosp = 0;
2240 } else {
2241 pxmitframe->attrib.mdata = 0;
2242 pxmitframe->attrib.eosp = 1;
2243 }
2244 }
2245
2246 pxmitframe->attrib.triggered = 1;
2247 rtw_hal_xmit23aframe_enqueue(padapter, pxmitframe);
2248 }
2249
2250 if (psta->sleepq_len == 0) {
2251 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
2252
2253 /* upate BCN for TIM IE */
2254 update_mask = BIT(0);
2255
2256 if (psta->state&WIFI_SLEEP_STATE)
2257 psta->state ^= WIFI_SLEEP_STATE;
2258
2259 if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
2260 psta->expire_to = pstapriv->expire_to;
2261 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
2262 }
2263
2264 pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid);
2265 }
2266
2267 /* spin_unlock_bh(&psta->sleep_q.lock); */
2268 spin_unlock_bh(&pxmitpriv->lock);
2269
2270 /* for BC/MC Frames */
2271 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
2272 if (!psta_bmc)
2273 return;
2274
2275 if ((pstapriv->sta_dz_bitmap&0xfffe) == 0x0) {
2276 /* no any sta in ps mode */
2277 spin_lock_bh(&pxmitpriv->lock);
2278
2279 phead = get_list_head(&psta_bmc->sleep_q);
2280
2281 list_for_each_safe(plist, ptmp, phead) {
2282 pxmitframe = container_of(plist, struct xmit_frame,
2283 list);
2284
2285 list_del_init(&pxmitframe->list);
2286
2287 psta_bmc->sleepq_len--;
2288 if (psta_bmc->sleepq_len > 0)
2289 pxmitframe->attrib.mdata = 1;
2290 else
2291 pxmitframe->attrib.mdata = 0;
2292
2293 pxmitframe->attrib.triggered = 1;
2294 rtw_hal_xmit23aframe_enqueue(padapter, pxmitframe);
2295 }
2296 if (psta_bmc->sleepq_len == 0) {
2297 pstapriv->tim_bitmap &= ~BIT(0);
2298 pstapriv->sta_dz_bitmap &= ~BIT(0);
2299
2300 /* upate BCN for TIM IE */
2301 /* update_BCNTIM(padapter); */
2302 update_mask |= BIT(1);
2303 }
2304
2305 /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
2306 spin_unlock_bh(&pxmitpriv->lock);
2307 }
2308
2309 if (update_mask)
2310 update_beacon23a(padapter, _TIM_IE_, NULL, false);
2311}
2312
2313void xmit_delivery_enabled_frames23a(struct rtw_adapter *padapter,
2314 struct sta_info *psta)
2315{
2316 u8 wmmps_ac = 0;
2317 struct list_head *plist, *phead, *ptmp;
2318 struct xmit_frame *pxmitframe;
2319 struct sta_priv *pstapriv = &padapter->stapriv;
2320 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2321
2322 /* spin_lock_bh(&psta->sleep_q.lock); */
2323 spin_lock_bh(&pxmitpriv->lock);
2324
2325 phead = get_list_head(&psta->sleep_q);
2326
2327 list_for_each_safe(plist, ptmp, phead) {
2328 pxmitframe = container_of(plist, struct xmit_frame, list);
2329
2330 switch (pxmitframe->attrib.priority) {
2331 case 1:
2332 case 2:
2333 wmmps_ac = psta->uapsd_bk & BIT(1);
2334 break;
2335 case 4:
2336 case 5:
2337 wmmps_ac = psta->uapsd_vi & BIT(1);
2338 break;
2339 case 6:
2340 case 7:
2341 wmmps_ac = psta->uapsd_vo & BIT(1);
2342 break;
2343 case 0:
2344 case 3:
2345 default:
2346 wmmps_ac = psta->uapsd_be & BIT(1);
2347 break;
2348 }
2349
2350 if (!wmmps_ac)
2351 continue;
2352
2353 list_del_init(&pxmitframe->list);
2354
2355 psta->sleepq_len--;
2356 psta->sleepq_ac_len--;
2357
2358 if (psta->sleepq_ac_len > 0) {
2359 pxmitframe->attrib.mdata = 1;
2360 pxmitframe->attrib.eosp = 0;
2361 } else {
2362 pxmitframe->attrib.mdata = 0;
2363 pxmitframe->attrib.eosp = 1;
2364 }
2365
2366 pxmitframe->attrib.triggered = 1;
2367
2368 rtw_hal_xmit23aframe_enqueue(padapter, pxmitframe);
2369
2370 if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) &&
2371 (wmmps_ac)) {
2372 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
2373
2374 /* upate BCN for TIM IE */
2375 update_beacon23a(padapter, _TIM_IE_, NULL, false);
2376 }
2377 }
2378 spin_unlock_bh(&pxmitpriv->lock);
2379}
2380
2381#endif
2382
2383void rtw_sctx_init23a(struct submit_ctx *sctx, int timeout_ms)
2384{
2385 sctx->timeout_ms = timeout_ms;
2386 init_completion(&sctx->done);
2387 sctx->status = RTW_SCTX_SUBMITTED;
2388}
2389
2390int rtw_sctx_wait23a(struct submit_ctx *sctx)
2391{
2392 int ret = _FAIL;
2393 unsigned long expire;
2394 int status = 0;
2395
2396 expire = sctx->timeout_ms ? msecs_to_jiffies(sctx->timeout_ms) :
2397 MAX_SCHEDULE_TIMEOUT;
2398 if (!wait_for_completion_timeout(&sctx->done, expire)) {
2399 /* timeout, do something?? */
2400 status = RTW_SCTX_DONE_TIMEOUT;
2401 DBG_8723A("%s timeout\n", __func__);
2402 } else {
2403 status = sctx->status;
2404 }
2405
2406 if (status == RTW_SCTX_DONE_SUCCESS)
2407 ret = _SUCCESS;
2408
2409 return ret;
2410}
2411
2412static bool rtw_sctx_chk_waring_status(int status)
2413{
2414 switch (status) {
2415 case RTW_SCTX_DONE_UNKNOWN:
2416 case RTW_SCTX_DONE_BUF_ALLOC:
2417 case RTW_SCTX_DONE_BUF_FREE:
2418 case RTW_SCTX_DONE_DRV_STOP:
2419 case RTW_SCTX_DONE_DEV_REMOVE:
2420 return true;
2421 default:
2422 return false;
2423 }
2424}
2425
2426void rtw23a_sctx_done_err(struct submit_ctx **sctx, int status)
2427{
2428 if (*sctx) {
2429 if (rtw_sctx_chk_waring_status(status))
2430 DBG_8723A("%s status:%d\n", __func__, status);
2431 (*sctx)->status = status;
2432 complete(&(*sctx)->done);
2433 *sctx = NULL;
2434 }
2435}
2436
2437void rtw_sctx_done23a(struct submit_ctx **sctx)
2438{
2439 rtw23a_sctx_done_err(sctx, RTW_SCTX_DONE_SUCCESS);
2440}
2441
2442int rtw_ack_tx_wait23a(struct xmit_priv *pxmitpriv, u32 timeout_ms)
2443{
2444 struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
2445
2446 pack_tx_ops->timeout_ms = timeout_ms;
2447 pack_tx_ops->status = RTW_SCTX_SUBMITTED;
2448
2449 return rtw_sctx_wait23a(pack_tx_ops);
2450}
2451
2452void rtw_ack_tx_done23a(struct xmit_priv *pxmitpriv, int status)
2453{
2454 struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
2455
2456 if (pxmitpriv->ack_tx)
2457 rtw23a_sctx_done_err(&pack_tx_ops, status);
2458 else
2459 DBG_8723A("%s ack_tx not set\n", __func__);
2460}
diff --git a/drivers/staging/rtl8723au/hal/Hal8723PwrSeq.c b/drivers/staging/rtl8723au/hal/Hal8723PwrSeq.c
new file mode 100644
index 000000000000..747f86cddeb9
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/Hal8723PwrSeq.c
@@ -0,0 +1,80 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15
16#include "Hal8723PwrSeq.h"
17
18/*
19 drivers should parse below arrays and do the corresponding actions
20*/
21/* 3 Power on Array */
22struct wlan_pwr_cfg rtl8723AU_power_on_flow[RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS] = {
23 RTL8723A_TRANS_CARDEMU_TO_ACT
24 RTL8723A_TRANS_END
25};
26
27/* 3 Radio off GPIO Array */
28struct wlan_pwr_cfg rtl8723AU_radio_off_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_END_STEPS] = {
29 RTL8723A_TRANS_ACT_TO_CARDEMU
30 RTL8723A_TRANS_END
31};
32
33/* 3 Card Disable Array */
34struct wlan_pwr_cfg rtl8723AU_card_disable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = {
35 RTL8723A_TRANS_ACT_TO_CARDEMU
36 RTL8723A_TRANS_CARDEMU_TO_CARDDIS
37 RTL8723A_TRANS_END
38};
39
40/* 3 Card Enable Array */
41struct wlan_pwr_cfg rtl8723AU_card_enable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = {
42 RTL8723A_TRANS_CARDDIS_TO_CARDEMU
43 RTL8723A_TRANS_CARDEMU_TO_ACT
44 RTL8723A_TRANS_END
45};
46
47/* 3 Suspend Array */
48struct wlan_pwr_cfg rtl8723AU_suspend_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS] = {
49 RTL8723A_TRANS_ACT_TO_CARDEMU
50 RTL8723A_TRANS_CARDEMU_TO_SUS
51 RTL8723A_TRANS_END
52};
53
54/* 3 Resume Array */
55struct wlan_pwr_cfg rtl8723AU_resume_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS] = {
56 RTL8723A_TRANS_SUS_TO_CARDEMU
57 RTL8723A_TRANS_CARDEMU_TO_ACT
58 RTL8723A_TRANS_END
59};
60
61/* 3 HWPDN Array */
62struct wlan_pwr_cfg rtl8723AU_hwpdn_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS] = {
63 RTL8723A_TRANS_ACT_TO_CARDEMU
64 RTL8723A_TRANS_CARDEMU_TO_PDN
65 RTL8723A_TRANS_END
66};
67
68/* 3 Enter LPS */
69struct wlan_pwr_cfg rtl8723AU_enter_lps_flow[RTL8723A_TRANS_ACT_TO_LPS_STEPS+RTL8723A_TRANS_END_STEPS] = {
70 /* FW behavior */
71 RTL8723A_TRANS_ACT_TO_LPS
72 RTL8723A_TRANS_END
73};
74
75/* 3 Leave LPS */
76struct wlan_pwr_cfg rtl8723AU_leave_lps_flow[RTL8723A_TRANS_LPS_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS] = {
77 /* FW behavior */
78 RTL8723A_TRANS_LPS_TO_ACT
79 RTL8723A_TRANS_END
80};
diff --git a/drivers/staging/rtl8723au/hal/Hal8723UHWImg_CE.c b/drivers/staging/rtl8723au/hal/Hal8723UHWImg_CE.c
new file mode 100644
index 000000000000..56833da63ced
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/Hal8723UHWImg_CE.c
@@ -0,0 +1,136 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15
16/*Created on 2013/01/14, 15:51*/
17#include "odm_precomp.h"
18
19u32 Rtl8723UPHY_REG_Array_PG[Rtl8723UPHY_REG_Array_PGLength] = {
20 0xe00, 0xffffffff, 0x0a0c0c0c,
21 0xe04, 0xffffffff, 0x02040608,
22 0xe08, 0x0000ff00, 0x00000000,
23 0x86c, 0xffffff00, 0x00000000,
24 0xe10, 0xffffffff, 0x0a0c0d0e,
25 0xe14, 0xffffffff, 0x02040608,
26 0xe18, 0xffffffff, 0x0a0c0d0e,
27 0xe1c, 0xffffffff, 0x02040608,
28 0x830, 0xffffffff, 0x0a0c0c0c,
29 0x834, 0xffffffff, 0x02040608,
30 0x838, 0xffffff00, 0x00000000,
31 0x86c, 0x000000ff, 0x00000000,
32 0x83c, 0xffffffff, 0x0a0c0d0e,
33 0x848, 0xffffffff, 0x02040608,
34 0x84c, 0xffffffff, 0x0a0c0d0e,
35 0x868, 0xffffffff, 0x02040608,
36 0xe00, 0xffffffff, 0x00000000,
37 0xe04, 0xffffffff, 0x00000000,
38 0xe08, 0x0000ff00, 0x00000000,
39 0x86c, 0xffffff00, 0x00000000,
40 0xe10, 0xffffffff, 0x00000000,
41 0xe14, 0xffffffff, 0x00000000,
42 0xe18, 0xffffffff, 0x00000000,
43 0xe1c, 0xffffffff, 0x00000000,
44 0x830, 0xffffffff, 0x00000000,
45 0x834, 0xffffffff, 0x00000000,
46 0x838, 0xffffff00, 0x00000000,
47 0x86c, 0x000000ff, 0x00000000,
48 0x83c, 0xffffffff, 0x00000000,
49 0x848, 0xffffffff, 0x00000000,
50 0x84c, 0xffffffff, 0x00000000,
51 0x868, 0xffffffff, 0x00000000,
52 0xe00, 0xffffffff, 0x04040404,
53 0xe04, 0xffffffff, 0x00020204,
54 0xe08, 0x0000ff00, 0x00000000,
55 0x86c, 0xffffff00, 0x00000000,
56 0xe10, 0xffffffff, 0x06060606,
57 0xe14, 0xffffffff, 0x00020406,
58 0xe18, 0xffffffff, 0x00000000,
59 0xe1c, 0xffffffff, 0x00000000,
60 0x830, 0xffffffff, 0x04040404,
61 0x834, 0xffffffff, 0x00020204,
62 0x838, 0xffffff00, 0x00000000,
63 0x86c, 0x000000ff, 0x00000000,
64 0x83c, 0xffffffff, 0x06060606,
65 0x848, 0xffffffff, 0x00020406,
66 0x84c, 0xffffffff, 0x00000000,
67 0x868, 0xffffffff, 0x00000000,
68 0xe00, 0xffffffff, 0x00000000,
69 0xe04, 0xffffffff, 0x00000000,
70 0xe08, 0x0000ff00, 0x00000000,
71 0x86c, 0xffffff00, 0x00000000,
72 0xe10, 0xffffffff, 0x00000000,
73 0xe14, 0xffffffff, 0x00000000,
74 0xe18, 0xffffffff, 0x00000000,
75 0xe1c, 0xffffffff, 0x00000000,
76 0x830, 0xffffffff, 0x00000000,
77 0x834, 0xffffffff, 0x00000000,
78 0x838, 0xffffff00, 0x00000000,
79 0x86c, 0x000000ff, 0x00000000,
80 0x83c, 0xffffffff, 0x00000000,
81 0x848, 0xffffffff, 0x00000000,
82 0x84c, 0xffffffff, 0x00000000,
83 0x868, 0xffffffff, 0x00000000,
84 0xe00, 0xffffffff, 0x00000000,
85 0xe04, 0xffffffff, 0x00000000,
86 0xe08, 0x0000ff00, 0x00000000,
87 0x86c, 0xffffff00, 0x00000000,
88 0xe10, 0xffffffff, 0x00000000,
89 0xe14, 0xffffffff, 0x00000000,
90 0xe18, 0xffffffff, 0x00000000,
91 0xe1c, 0xffffffff, 0x00000000,
92 0x830, 0xffffffff, 0x00000000,
93 0x834, 0xffffffff, 0x00000000,
94 0x838, 0xffffff00, 0x00000000,
95 0x86c, 0x000000ff, 0x00000000,
96 0x83c, 0xffffffff, 0x00000000,
97 0x848, 0xffffffff, 0x00000000,
98 0x84c, 0xffffffff, 0x00000000,
99 0x868, 0xffffffff, 0x00000000,
100 0xe00, 0xffffffff, 0x04040404,
101 0xe04, 0xffffffff, 0x00020204,
102 0xe08, 0x0000ff00, 0x00000000,
103 0x86c, 0xffffff00, 0x00000000,
104 0xe10, 0xffffffff, 0x00000000,
105 0xe14, 0xffffffff, 0x00000000,
106 0xe18, 0xffffffff, 0x00000000,
107 0xe1c, 0xffffffff, 0x00000000,
108 0x830, 0xffffffff, 0x04040404,
109 0x834, 0xffffffff, 0x00020204,
110 0x838, 0xffffff00, 0x00000000,
111 0x86c, 0x000000ff, 0x00000000,
112 0x83c, 0xffffffff, 0x00000000,
113 0x848, 0xffffffff, 0x00000000,
114 0x84c, 0xffffffff, 0x00000000,
115 0x868, 0xffffffff, 0x00000000,
116 0xe00, 0xffffffff, 0x00000000,
117 0xe04, 0xffffffff, 0x00000000,
118 0xe08, 0x0000ff00, 0x00000000,
119 0x86c, 0xffffff00, 0x00000000,
120 0xe10, 0xffffffff, 0x00000000,
121 0xe14, 0xffffffff, 0x00000000,
122 0xe18, 0xffffffff, 0x00000000,
123 0xe1c, 0xffffffff, 0x00000000,
124 0x830, 0xffffffff, 0x00000000,
125 0x834, 0xffffffff, 0x00000000,
126 0x838, 0xffffff00, 0x00000000,
127 0x86c, 0x000000ff, 0x00000000,
128 0x83c, 0xffffffff, 0x00000000,
129 0x848, 0xffffffff, 0x00000000,
130 0x84c, 0xffffffff, 0x00000000,
131 0x868, 0xffffffff, 0x00000000,
132 };
133
134u32 Rtl8723UMACPHY_Array_PG[Rtl8723UMACPHY_Array_PGLength] = {
135 0x0,
136};
diff --git a/drivers/staging/rtl8723au/hal/HalDMOutSrc8723A_CE.c b/drivers/staging/rtl8723au/hal/HalDMOutSrc8723A_CE.c
new file mode 100644
index 000000000000..9796f2e5c68f
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/HalDMOutSrc8723A_CE.c
@@ -0,0 +1,1063 @@
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 ******************************************************************************/
15/* Description: */
16/* This file is for 92CE/92CU dynamic mechanism only */
17
18/* include files */
19
20#include "odm_precomp.h"
21
22#define DPK_DELTA_MAPPING_NUM 13
23#define index_mapping_HP_NUM 15
24/* 091212 chiyokolin */
25static void
26odm_TXPowerTrackingCallback_ThermalMeter_92C(
27 struct rtw_adapter *Adapter)
28{
29 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
30 struct dm_priv *pdmpriv = &pHalData->dmpriv;
31 u8 ThermalValue = 0, delta, delta_LCK, delta_IQK, delta_HP;
32 int ele_A, ele_D, TempCCk, X, value32;
33 int Y, ele_C;
34 s8 OFDM_index[2], CCK_index = 0, OFDM_index_old[2] = {0};
35 s8 CCK_index_old = 0;
36 int i = 0;
37 bool is2T = IS_92C_SERIAL(pHalData->VersionID);
38 u8 OFDM_min_index = 6, rf; /* OFDM BB Swing should be less than +3.0dB*/
39 u8 ThermalValue_HP_count = 0;
40 u32 ThermalValue_HP = 0;
41 s32 index_mapping_HP[index_mapping_HP_NUM] = {
42 0, 1, 3, 4, 6,
43 7, 9, 10, 12, 13,
44 15, 16, 18, 19, 21
45 };
46 s8 index_HP;
47
48 pdmpriv->TXPowerTrackingCallbackCnt++; /* cosa add for debug */
49 pdmpriv->bTXPowerTrackingInit = true;
50
51 if (pHalData->CurrentChannel == 14 && !pdmpriv->bCCKinCH14)
52 pdmpriv->bCCKinCH14 = true;
53 else if (pHalData->CurrentChannel != 14 && pdmpriv->bCCKinCH14)
54 pdmpriv->bCCKinCH14 = false;
55
56 ThermalValue = (u8)PHY_QueryRFReg(Adapter, RF_PATH_A, RF_T_METER,
57 0x1f);/* 0x24: RF Reg[4:0] */
58
59 rtl8723a_phy_ap_calibrate(Adapter, (ThermalValue -
60 pHalData->EEPROMThermalMeter));
61
62 if (is2T)
63 rf = 2;
64 else
65 rf = 1;
66
67 if (ThermalValue) {
68 /* Query OFDM path A default setting */
69 ele_D = PHY_QueryBBReg(Adapter, rOFDM0_XATxIQImbalance,
70 bMaskDWord)&bMaskOFDM_D;
71 for (i = 0; i < OFDM_TABLE_SIZE_92C; i++) {
72 /* find the index */
73 if (ele_D == (OFDMSwingTable23A[i]&bMaskOFDM_D)) {
74 OFDM_index_old[0] = (u8)i;
75 break;
76 }
77 }
78
79 /* Query OFDM path B default setting */
80 if (is2T) {
81 ele_D = PHY_QueryBBReg(Adapter, rOFDM0_XBTxIQImbalance,
82 bMaskDWord)&bMaskOFDM_D;
83 for (i = 0; i < OFDM_TABLE_SIZE_92C; i++) { /* find the index */
84 if (ele_D == (OFDMSwingTable23A[i]&bMaskOFDM_D)) {
85 OFDM_index_old[1] = (u8)i;
86 break;
87 }
88 }
89 }
90
91 /* Query CCK default setting From 0xa24 */
92 TempCCk = PHY_QueryBBReg(Adapter, rCCK0_TxFilter2,
93 bMaskDWord)&bMaskCCK;
94 for (i = 0 ; i < CCK_TABLE_SIZE ; i++) {
95 if (pdmpriv->bCCKinCH14) {
96 if (!memcmp(&TempCCk,
97 &CCKSwingTable_Ch1423A[i][2], 4)) {
98 CCK_index_old = (u8)i;
99 break;
100 }
101 } else {
102 if (!memcmp(&TempCCk,
103 &CCKSwingTable_Ch1_Ch1323A[i][2], 4)) {
104 CCK_index_old = (u8)i;
105 break;
106 }
107 }
108 }
109
110 if (!pdmpriv->ThermalValue) {
111 pdmpriv->ThermalValue = pHalData->EEPROMThermalMeter;
112 pdmpriv->ThermalValue_LCK = ThermalValue;
113 pdmpriv->ThermalValue_IQK = ThermalValue;
114 pdmpriv->ThermalValue_DPK = pHalData->EEPROMThermalMeter;
115
116 for (i = 0; i < rf; i++) {
117 pdmpriv->OFDM_index_HP[i] = OFDM_index_old[i];
118 pdmpriv->OFDM_index[i] = OFDM_index_old[i];
119 }
120 pdmpriv->CCK_index_HP = CCK_index_old;
121 pdmpriv->CCK_index = CCK_index_old;
122 }
123
124 if (pHalData->BoardType == BOARD_USB_High_PA) {
125 pdmpriv->ThermalValue_HP[pdmpriv->ThermalValue_HP_index] = ThermalValue;
126 pdmpriv->ThermalValue_HP_index++;
127 if (pdmpriv->ThermalValue_HP_index == HP_THERMAL_NUM)
128 pdmpriv->ThermalValue_HP_index = 0;
129
130 for (i = 0; i < HP_THERMAL_NUM; i++) {
131 if (pdmpriv->ThermalValue_HP[i]) {
132 ThermalValue_HP += pdmpriv->ThermalValue_HP[i];
133 ThermalValue_HP_count++;
134 }
135 }
136
137 if (ThermalValue_HP_count)
138 ThermalValue = (u8)(ThermalValue_HP / ThermalValue_HP_count);
139 }
140
141 delta = (ThermalValue > pdmpriv->ThermalValue) ?
142 (ThermalValue - pdmpriv->ThermalValue) :
143 (pdmpriv->ThermalValue - ThermalValue);
144 if (pHalData->BoardType == BOARD_USB_High_PA) {
145 if (pdmpriv->bDoneTxpower)
146 delta_HP = (ThermalValue > pdmpriv->ThermalValue) ?
147 (ThermalValue - pdmpriv->ThermalValue) :
148 (pdmpriv->ThermalValue - ThermalValue);
149 else
150 delta_HP = ThermalValue > pHalData->EEPROMThermalMeter ?
151 (ThermalValue - pHalData->EEPROMThermalMeter) :
152 (pHalData->EEPROMThermalMeter - ThermalValue);
153 } else {
154 delta_HP = 0;
155 }
156 delta_LCK = (ThermalValue > pdmpriv->ThermalValue_LCK) ?
157 (ThermalValue - pdmpriv->ThermalValue_LCK) :
158 (pdmpriv->ThermalValue_LCK - ThermalValue);
159 delta_IQK = (ThermalValue > pdmpriv->ThermalValue_IQK) ?
160 (ThermalValue - pdmpriv->ThermalValue_IQK) :
161 (pdmpriv->ThermalValue_IQK - ThermalValue);
162
163 if (delta_LCK > 1) {
164 pdmpriv->ThermalValue_LCK = ThermalValue;
165 rtl8723a_phy_lc_calibrate(Adapter);
166 }
167
168 if ((delta > 0 || delta_HP > 0) && pdmpriv->TxPowerTrackControl) {
169 if (pHalData->BoardType == BOARD_USB_High_PA) {
170 pdmpriv->bDoneTxpower = true;
171 delta_HP = ThermalValue > pHalData->EEPROMThermalMeter ?
172 (ThermalValue - pHalData->EEPROMThermalMeter) :
173 (pHalData->EEPROMThermalMeter - ThermalValue);
174
175 if (delta_HP > index_mapping_HP_NUM-1)
176 index_HP = index_mapping_HP[index_mapping_HP_NUM-1];
177 else
178 index_HP = index_mapping_HP[delta_HP];
179
180 if (ThermalValue > pHalData->EEPROMThermalMeter) {
181 /* set larger Tx power */
182 for (i = 0; i < rf; i++)
183 OFDM_index[i] = pdmpriv->OFDM_index_HP[i] - index_HP;
184 CCK_index = pdmpriv->CCK_index_HP - index_HP;
185 } else {
186 for (i = 0; i < rf; i++)
187 OFDM_index[i] = pdmpriv->OFDM_index_HP[i] + index_HP;
188 CCK_index = pdmpriv->CCK_index_HP + index_HP;
189 }
190
191 delta_HP = (ThermalValue > pdmpriv->ThermalValue) ?
192 (ThermalValue - pdmpriv->ThermalValue) :
193 (pdmpriv->ThermalValue - ThermalValue);
194 } else {
195 if (ThermalValue > pdmpriv->ThermalValue) {
196 for (i = 0; i < rf; i++)
197 pdmpriv->OFDM_index[i] -= delta;
198 pdmpriv->CCK_index -= delta;
199 } else {
200 for (i = 0; i < rf; i++)
201 pdmpriv->OFDM_index[i] += delta;
202 pdmpriv->CCK_index += delta;
203 }
204 }
205
206 /* no adjust */
207 if (pHalData->BoardType != BOARD_USB_High_PA) {
208 if (ThermalValue > pHalData->EEPROMThermalMeter) {
209 for (i = 0; i < rf; i++)
210 OFDM_index[i] = pdmpriv->OFDM_index[i]+1;
211 CCK_index = pdmpriv->CCK_index+1;
212 } else {
213 for (i = 0; i < rf; i++)
214 OFDM_index[i] = pdmpriv->OFDM_index[i];
215 CCK_index = pdmpriv->CCK_index;
216 }
217 }
218 for (i = 0; i < rf; i++) {
219 if (OFDM_index[i] > (OFDM_TABLE_SIZE_92C-1))
220 OFDM_index[i] = (OFDM_TABLE_SIZE_92C-1);
221 else if (OFDM_index[i] < OFDM_min_index)
222 OFDM_index[i] = OFDM_min_index;
223 }
224
225 if (CCK_index > (CCK_TABLE_SIZE-1))
226 CCK_index = (CCK_TABLE_SIZE-1);
227 else if (CCK_index < 0)
228 CCK_index = 0;
229 }
230
231 if (pdmpriv->TxPowerTrackControl && (delta != 0 || delta_HP != 0)) {
232 /* Adujst OFDM Ant_A according to IQK result */
233 ele_D = (OFDMSwingTable23A[OFDM_index[0]] & 0xFFC00000)>>22;
234 X = pdmpriv->RegE94;
235 Y = pdmpriv->RegE9C;
236
237 if (X != 0) {
238 if ((X & 0x00000200) != 0)
239 X = X | 0xFFFFFC00;
240 ele_A = ((X * ele_D)>>8)&0x000003FF;
241
242 /* new element C = element D x Y */
243 if ((Y & 0x00000200) != 0)
244 Y = Y | 0xFFFFFC00;
245 ele_C = ((Y * ele_D)>>8)&0x000003FF;
246
247 /* write new elements A, C, D to regC80 and regC94, element B is always 0 */
248 value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A;
249 PHY_SetBBReg(Adapter, rOFDM0_XATxIQImbalance, bMaskDWord, value32);
250
251 value32 = (ele_C&0x000003C0)>>6;
252 PHY_SetBBReg(Adapter, rOFDM0_XCTxAFE, bMaskH4Bits, value32);
253
254 value32 = ((X * ele_D)>>7)&0x01;
255 PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, BIT31, value32);
256
257 value32 = ((Y * ele_D)>>7)&0x01;
258 PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, BIT29, value32);
259 } else {
260 PHY_SetBBReg(Adapter, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable23A[OFDM_index[0]]);
261 PHY_SetBBReg(Adapter, rOFDM0_XCTxAFE, bMaskH4Bits, 0x00);
262 PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, BIT31|BIT29, 0x00);
263 }
264
265 /* Adjust CCK according to IQK result */
266 if (!pdmpriv->bCCKinCH14) {
267 rtw_write8(Adapter, 0xa22, CCKSwingTable_Ch1_Ch1323A[CCK_index][0]);
268 rtw_write8(Adapter, 0xa23, CCKSwingTable_Ch1_Ch1323A[CCK_index][1]);
269 rtw_write8(Adapter, 0xa24, CCKSwingTable_Ch1_Ch1323A[CCK_index][2]);
270 rtw_write8(Adapter, 0xa25, CCKSwingTable_Ch1_Ch1323A[CCK_index][3]);
271 rtw_write8(Adapter, 0xa26, CCKSwingTable_Ch1_Ch1323A[CCK_index][4]);
272 rtw_write8(Adapter, 0xa27, CCKSwingTable_Ch1_Ch1323A[CCK_index][5]);
273 rtw_write8(Adapter, 0xa28, CCKSwingTable_Ch1_Ch1323A[CCK_index][6]);
274 rtw_write8(Adapter, 0xa29, CCKSwingTable_Ch1_Ch1323A[CCK_index][7]);
275 } else {
276 rtw_write8(Adapter, 0xa22, CCKSwingTable_Ch1423A[CCK_index][0]);
277 rtw_write8(Adapter, 0xa23, CCKSwingTable_Ch1423A[CCK_index][1]);
278 rtw_write8(Adapter, 0xa24, CCKSwingTable_Ch1423A[CCK_index][2]);
279 rtw_write8(Adapter, 0xa25, CCKSwingTable_Ch1423A[CCK_index][3]);
280 rtw_write8(Adapter, 0xa26, CCKSwingTable_Ch1423A[CCK_index][4]);
281 rtw_write8(Adapter, 0xa27, CCKSwingTable_Ch1423A[CCK_index][5]);
282 rtw_write8(Adapter, 0xa28, CCKSwingTable_Ch1423A[CCK_index][6]);
283 rtw_write8(Adapter, 0xa29, CCKSwingTable_Ch1423A[CCK_index][7]);
284 }
285
286 if (is2T) {
287 ele_D = (OFDMSwingTable23A[(u8)OFDM_index[1]] & 0xFFC00000)>>22;
288
289 /* new element A = element D x X */
290 X = pdmpriv->RegEB4;
291 Y = pdmpriv->RegEBC;
292
293 if (X != 0) {
294 if ((X & 0x00000200) != 0) /* consider minus */
295 X = X | 0xFFFFFC00;
296 ele_A = ((X * ele_D)>>8)&0x000003FF;
297
298 /* new element C = element D x Y */
299 if ((Y & 0x00000200) != 0)
300 Y = Y | 0xFFFFFC00;
301 ele_C = ((Y * ele_D)>>8)&0x00003FF;
302
303 /* write new elements A, C, D to regC88 and regC9C, element B is always 0 */
304 value32 = (ele_D<<22)|((ele_C&0x3F)<<16) | ele_A;
305 PHY_SetBBReg(Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord, value32);
306
307 value32 = (ele_C&0x000003C0)>>6;
308 PHY_SetBBReg(Adapter, rOFDM0_XDTxAFE, bMaskH4Bits, value32);
309
310 value32 = ((X * ele_D)>>7)&0x01;
311 PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, BIT27, value32);
312
313 value32 = ((Y * ele_D)>>7)&0x01;
314 PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, BIT25, value32);
315 } else {
316 PHY_SetBBReg(Adapter, rOFDM0_XBTxIQImbalance, bMaskDWord, OFDMSwingTable23A[OFDM_index[1]]);
317 PHY_SetBBReg(Adapter, rOFDM0_XDTxAFE, bMaskH4Bits, 0x00);
318 PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold, BIT27|BIT25, 0x00);
319 }
320 }
321
322 }
323 if (delta_IQK > 3) {
324 pdmpriv->ThermalValue_IQK = ThermalValue;
325 rtl8723a_phy_iq_calibrate(Adapter, false);
326 }
327
328 /* update thermal meter value */
329 if (pdmpriv->TxPowerTrackControl)
330 pdmpriv->ThermalValue = ThermalValue;
331 }
332 pdmpriv->TXPowercount = 0;
333}
334
335/* Description: */
336/* - Dispatch TxPower Tracking direct call ONLY for 92s. */
337/* - We shall NOT schedule Workitem within PASSIVE LEVEL, which will cause system resource */
338/* leakage under some platform. */
339/* Assumption: */
340/* PASSIVE_LEVEL when this routine is called. */
341static void ODM_TXPowerTracking92CDirectCall(struct rtw_adapter *Adapter)
342{
343 odm_TXPowerTrackingCallback_ThermalMeter_92C(Adapter);
344}
345
346static void odm_CheckTXPowerTracking_ThermalMeter(struct rtw_adapter *Adapter)
347{
348 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
349 struct dm_priv *pdmpriv = &pHalData->dmpriv;
350 struct dm_odm_t *podmpriv = &pHalData->odmpriv;
351
352 if (!(podmpriv->SupportAbility & ODM_RF_TX_PWR_TRACK))
353 return;
354
355 if (!pdmpriv->TM_Trigger) { /* at least delay 1 sec */
356 PHY_SetRFReg(Adapter, RF_PATH_A, RF_T_METER, bRFRegOffsetMask, 0x60);
357
358 pdmpriv->TM_Trigger = 1;
359 return;
360 } else {
361 ODM_TXPowerTracking92CDirectCall(Adapter);
362 pdmpriv->TM_Trigger = 0;
363 }
364}
365
366void rtl8723a_odm_check_tx_power_tracking(struct rtw_adapter *Adapter)
367{
368 odm_CheckTXPowerTracking_ThermalMeter(Adapter);
369}
370
371/* IQK */
372#define MAX_TOLERANCE 5
373#define IQK_DELAY_TIME 1 /* ms */
374
375static u8 _PHY_PathA_IQK(struct rtw_adapter *pAdapter, bool configPathB)
376{
377 u32 regEAC, regE94, regE9C, regEA4;
378 u8 result = 0x00;
379 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
380
381 /* path-A IQK setting */
382 PHY_SetBBReg(pAdapter, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1f);
383 PHY_SetBBReg(pAdapter, rRx_IQK_Tone_A, bMaskDWord, 0x10008c1f);
384 PHY_SetBBReg(pAdapter, rTx_IQK_PI_A, bMaskDWord, 0x82140102);
385
386 PHY_SetBBReg(pAdapter, rRx_IQK_PI_A, bMaskDWord, configPathB ? 0x28160202 :
387 IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID)?0x28160202:0x28160502);
388
389 /* path-B IQK setting */
390 if (configPathB) {
391 PHY_SetBBReg(pAdapter, rTx_IQK_Tone_B, bMaskDWord, 0x10008c22);
392 PHY_SetBBReg(pAdapter, rRx_IQK_Tone_B, bMaskDWord, 0x10008c22);
393 PHY_SetBBReg(pAdapter, rTx_IQK_PI_B, bMaskDWord, 0x82140102);
394 PHY_SetBBReg(pAdapter, rRx_IQK_PI_B, bMaskDWord, 0x28160202);
395 }
396
397 /* LO calibration setting */
398 PHY_SetBBReg(pAdapter, rIQK_AGC_Rsp, bMaskDWord, 0x001028d1);
399
400 /* One shot, path A LOK & IQK */
401 PHY_SetBBReg(pAdapter, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
402 PHY_SetBBReg(pAdapter, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
403
404 /* delay x ms */
405 udelay(IQK_DELAY_TIME*1000);/* PlatformStallExecution(IQK_DELAY_TIME*1000); */
406
407 /* Check failed */
408 regEAC = PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_A_2, bMaskDWord);
409 regE94 = PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_A, bMaskDWord);
410 regE9C = PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_A, bMaskDWord);
411 regEA4 = PHY_QueryBBReg(pAdapter, rRx_Power_Before_IQK_A_2, bMaskDWord);
412
413 if (!(regEAC & BIT28) &&
414 (((regE94 & 0x03FF0000)>>16) != 0x142) &&
415 (((regE9C & 0x03FF0000)>>16) != 0x42))
416 result |= 0x01;
417 else /* if Tx not OK, ignore Rx */
418 return result;
419
420 if (!(regEAC & BIT27) && /* if Tx is OK, check whether Rx is OK */
421 (((regEA4 & 0x03FF0000)>>16) != 0x132) &&
422 (((regEAC & 0x03FF0000)>>16) != 0x36))
423 result |= 0x02;
424 else
425 DBG_8723A("Path A Rx IQK fail!!\n");
426 return result;
427}
428
429static u8 _PHY_PathB_IQK(struct rtw_adapter *pAdapter)
430{
431 u32 regEAC, regEB4, regEBC, regEC4, regECC;
432 u8 result = 0x00;
433
434 /* One shot, path B LOK & IQK */
435 PHY_SetBBReg(pAdapter, rIQK_AGC_Cont, bMaskDWord, 0x00000002);
436 PHY_SetBBReg(pAdapter, rIQK_AGC_Cont, bMaskDWord, 0x00000000);
437
438 /* delay x ms */
439 udelay(IQK_DELAY_TIME*1000);
440
441 /* Check failed */
442 regEAC = PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_A_2, bMaskDWord);
443 regEB4 = PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_B, bMaskDWord);
444 regEBC = PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_B, bMaskDWord);
445 regEC4 = PHY_QueryBBReg(pAdapter, rRx_Power_Before_IQK_B_2, bMaskDWord);
446 regECC = PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_B_2, bMaskDWord);
447
448 if (!(regEAC & BIT31) &&
449 (((regEB4 & 0x03FF0000)>>16) != 0x142) &&
450 (((regEBC & 0x03FF0000)>>16) != 0x42))
451 result |= 0x01;
452 else
453 return result;
454
455 if (!(regEAC & BIT30) &&
456 (((regEC4 & 0x03FF0000)>>16) != 0x132) &&
457 (((regECC & 0x03FF0000)>>16) != 0x36))
458 result |= 0x02;
459 else
460 DBG_8723A("Path B Rx IQK fail!!\n");
461 return result;
462}
463
464static void _PHY_PathAFillIQKMatrix(struct rtw_adapter *pAdapter,
465 bool bIQKOK,
466 int result[][8],
467 u8 final_candidate,
468 bool bTxOnly
469 )
470{
471 u32 Oldval_0, X, TX0_A, reg;
472 s32 Y, TX0_C;
473
474 DBG_8723A("Path A IQ Calibration %s !\n", (bIQKOK)?"Success":"Failed");
475
476 if (final_candidate == 0xFF) {
477 return;
478 } else if (bIQKOK) {
479 Oldval_0 = (PHY_QueryBBReg(pAdapter, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
480
481 X = result[final_candidate][0];
482 if ((X & 0x00000200) != 0)
483 X = X | 0xFFFFFC00;
484 TX0_A = (X * Oldval_0) >> 8;
485 PHY_SetBBReg(pAdapter, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A);
486 PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(31), ((X * Oldval_0>>7) & 0x1));
487
488 Y = result[final_candidate][1];
489 if ((Y & 0x00000200) != 0)
490 Y = Y | 0xFFFFFC00;
491 TX0_C = (Y * Oldval_0) >> 8;
492 PHY_SetBBReg(pAdapter, rOFDM0_XCTxAFE, 0xF0000000, ((TX0_C&0x3C0)>>6));
493 PHY_SetBBReg(pAdapter, rOFDM0_XATxIQImbalance, 0x003F0000, (TX0_C&0x3F));
494 PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(29), ((Y * Oldval_0>>7) & 0x1));
495
496 if (bTxOnly) {
497 DBG_8723A("_PHY_PathAFillIQKMatrix only Tx OK\n");
498 return;
499 }
500
501 reg = result[final_candidate][2];
502 PHY_SetBBReg(pAdapter, rOFDM0_XARxIQImbalance, 0x3FF, reg);
503
504 reg = result[final_candidate][3] & 0x3F;
505 PHY_SetBBReg(pAdapter, rOFDM0_XARxIQImbalance, 0xFC00, reg);
506
507 reg = (result[final_candidate][3] >> 6) & 0xF;
508 PHY_SetBBReg(pAdapter, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
509 }
510}
511
512static void _PHY_PathBFillIQKMatrix(struct rtw_adapter *pAdapter, bool bIQKOK, int result[][8], u8 final_candidate, bool bTxOnly)
513{
514 u32 Oldval_1, X, TX1_A, reg;
515 s32 Y, TX1_C;
516
517 DBG_8723A("Path B IQ Calibration %s !\n", (bIQKOK)?"Success":"Failed");
518
519 if (final_candidate == 0xFF) {
520 return;
521 } else if (bIQKOK) {
522 Oldval_1 = (PHY_QueryBBReg(pAdapter, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
523
524 X = result[final_candidate][4];
525 if ((X & 0x00000200) != 0)
526 X = X | 0xFFFFFC00;
527 TX1_A = (X * Oldval_1) >> 8;
528 PHY_SetBBReg(pAdapter, rOFDM0_XBTxIQImbalance, 0x3FF, TX1_A);
529 PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(27), ((X * Oldval_1>>7) & 0x1));
530
531 Y = result[final_candidate][5];
532 if ((Y & 0x00000200) != 0)
533 Y = Y | 0xFFFFFC00;
534 TX1_C = (Y * Oldval_1) >> 8;
535 PHY_SetBBReg(pAdapter, rOFDM0_XDTxAFE, 0xF0000000, ((TX1_C&0x3C0)>>6));
536 PHY_SetBBReg(pAdapter, rOFDM0_XBTxIQImbalance, 0x003F0000, (TX1_C&0x3F));
537 PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(25), ((Y * Oldval_1>>7) & 0x1));
538
539 if (bTxOnly)
540 return;
541
542 reg = result[final_candidate][6];
543 PHY_SetBBReg(pAdapter, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
544
545 reg = result[final_candidate][7] & 0x3F;
546 PHY_SetBBReg(pAdapter, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
547
548 reg = (result[final_candidate][7] >> 6) & 0xF;
549 PHY_SetBBReg(pAdapter, rOFDM0_AGCRSSITable, 0x0000F000, reg);
550 }
551}
552
553static void _PHY_SaveADDARegisters(struct rtw_adapter *pAdapter, u32 *ADDAReg, u32 *ADDABackup, u32 RegisterNum)
554{
555 u32 i;
556
557 for (i = 0 ; i < RegisterNum ; i++) {
558 ADDABackup[i] = PHY_QueryBBReg(pAdapter, ADDAReg[i], bMaskDWord);
559 }
560}
561
562static void _PHY_SaveMACRegisters(struct rtw_adapter *pAdapter, u32 *MACReg, u32 *MACBackup)
563{
564 u32 i;
565
566 for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++) {
567 MACBackup[i] = rtw_read8(pAdapter, MACReg[i]);
568 }
569 MACBackup[i] = rtw_read32(pAdapter, MACReg[i]);
570}
571
572static void _PHY_ReloadADDARegisters(struct rtw_adapter *pAdapter, u32 *ADDAReg, u32 *ADDABackup, u32 RegiesterNum)
573{
574 u32 i;
575
576 for (i = 0 ; i < RegiesterNum ; i++) {
577 PHY_SetBBReg(pAdapter, ADDAReg[i], bMaskDWord, ADDABackup[i]);
578 }
579}
580
581static void _PHY_ReloadMACRegisters(struct rtw_adapter *pAdapter, u32 *MACReg, u32 *MACBackup)
582{
583 u32 i;
584
585 for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++) {
586 rtw_write8(pAdapter, MACReg[i], (u8)MACBackup[i]);
587 }
588 rtw_write32(pAdapter, MACReg[i], MACBackup[i]);
589}
590
591static void _PHY_PathADDAOn(struct rtw_adapter *pAdapter, u32 *ADDAReg, bool isPathAOn, bool is2T)
592{
593 u32 pathOn;
594 u32 i;
595
596 pathOn = isPathAOn ? 0x04db25a4 : 0x0b1b25a4;
597 if (false == is2T) {
598 pathOn = 0x0bdb25a0;
599 PHY_SetBBReg(pAdapter, ADDAReg[0], bMaskDWord, 0x0b1b25a0);
600 } else {
601 PHY_SetBBReg(pAdapter, ADDAReg[0], bMaskDWord, pathOn);
602 }
603
604 for (i = 1 ; i < IQK_ADDA_REG_NUM ; i++)
605 PHY_SetBBReg(pAdapter, ADDAReg[i], bMaskDWord, pathOn);
606}
607
608static void _PHY_MACSettingCalibration(struct rtw_adapter *pAdapter, u32 *MACReg, u32 *MACBackup)
609{
610 u32 i = 0;
611
612 rtw_write8(pAdapter, MACReg[i], 0x3F);
613
614 for (i = 1 ; i < (IQK_MAC_REG_NUM - 1); i++) {
615 rtw_write8(pAdapter, MACReg[i], (u8)(MACBackup[i]&(~BIT3)));
616 }
617 rtw_write8(pAdapter, MACReg[i], (u8)(MACBackup[i]&(~BIT5)));
618}
619
620static void _PHY_PathAStandBy(struct rtw_adapter *pAdapter)
621{
622 PHY_SetBBReg(pAdapter, rFPGA0_IQK, bMaskDWord, 0x0);
623 PHY_SetBBReg(pAdapter, 0x840, bMaskDWord, 0x00010000);
624 PHY_SetBBReg(pAdapter, rFPGA0_IQK, bMaskDWord, 0x80800000);
625}
626
627static void _PHY_PIModeSwitch(struct rtw_adapter *pAdapter, bool PIMode)
628{
629 u32 mode;
630
631 mode = PIMode ? 0x01000100 : 0x01000000;
632 PHY_SetBBReg(pAdapter, 0x820, bMaskDWord, mode);
633 PHY_SetBBReg(pAdapter, 0x828, bMaskDWord, mode);
634}
635
636/*
637return false => do IQK again
638*/
639static bool _PHY_SimularityCompare(struct rtw_adapter *pAdapter, int result[][8], u8 c1, u8 c2)
640{
641 u32 i, j, diff, SimularityBitMap, bound = 0;
642 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
643 u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */
644 bool bResult = true, is2T = IS_92C_SERIAL(pHalData->VersionID);
645
646 if (is2T)
647 bound = 8;
648 else
649 bound = 4;
650
651 SimularityBitMap = 0;
652
653 for (i = 0; i < bound; i++) {
654 diff = (result[c1][i] > result[c2][i]) ? (result[c1][i] - result[c2][i]) : (result[c2][i] - result[c1][i]);
655 if (diff > MAX_TOLERANCE) {
656 if ((i == 2 || i == 6) && !SimularityBitMap) {
657 if (result[c1][i]+result[c1][i+1] == 0)
658 final_candidate[(i/4)] = c2;
659 else if (result[c2][i]+result[c2][i+1] == 0)
660 final_candidate[(i/4)] = c1;
661 else
662 SimularityBitMap = SimularityBitMap|(1<<i);
663 } else {
664 SimularityBitMap = SimularityBitMap|(1<<i);
665 }
666 }
667 }
668
669 if (SimularityBitMap == 0) {
670 for (i = 0; i < (bound/4); i++) {
671 if (final_candidate[i] != 0xFF) {
672 for (j = i*4; j < (i+1)*4-2; j++)
673 result[3][j] = result[final_candidate[i]][j];
674 bResult = false;
675 }
676 }
677 return bResult;
678 } else if (!(SimularityBitMap & 0x0F)) {
679 /* path A OK */
680 for (i = 0; i < 4; i++)
681 result[3][i] = result[c1][i];
682 return false;
683 } else if (!(SimularityBitMap & 0xF0) && is2T) {
684 /* path B OK */
685 for (i = 4; i < 8; i++)
686 result[3][i] = result[c1][i];
687 return false;
688 } else {
689 return false;
690 }
691}
692
693static void _PHY_IQCalibrate(struct rtw_adapter *pAdapter, int result[][8], u8 t, bool is2T)
694{
695 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
696 struct dm_priv *pdmpriv = &pHalData->dmpriv;
697 u32 i;
698 u8 PathAOK, PathBOK;
699 u32 ADDA_REG[IQK_ADDA_REG_NUM] = {
700 rFPGA0_XCD_SwitchControl, rBlue_Tooth,
701 rRx_Wait_CCA, rTx_CCK_RFON,
702 rTx_CCK_BBON, rTx_OFDM_RFON,
703 rTx_OFDM_BBON, rTx_To_Rx,
704 rTx_To_Tx, rRx_CCK,
705 rRx_OFDM, rRx_Wait_RIFS,
706 rRx_TO_Rx, rStandby,
707 rSleep, rPMPD_ANAEN
708 };
709
710 u32 IQK_MAC_REG[IQK_MAC_REG_NUM] = {
711 REG_TXPAUSE, REG_BCN_CTRL,
712 REG_BCN_CTRL_1, REG_GPIO_MUXCFG
713 };
714
715 u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = {
716 rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar,
717 rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB,
718 rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE,
719 rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD
720 };
721
722 const u32 retryCount = 2;
723
724 /* Note: IQ calibration must be performed after loading */
725 /* PHY_REG.txt , and radio_a, radio_b.txt */
726
727 u32 bbvalue;
728
729 if (t == 0) {
730 bbvalue = PHY_QueryBBReg(pAdapter, rFPGA0_RFMOD, bMaskDWord);
731
732 /* Save ADDA parameters, turn Path A ADDA on */
733 _PHY_SaveADDARegisters(pAdapter, ADDA_REG, pdmpriv->ADDA_backup, IQK_ADDA_REG_NUM);
734 _PHY_SaveMACRegisters(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup);
735 _PHY_SaveADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup, IQK_BB_REG_NUM);
736 }
737 _PHY_PathADDAOn(pAdapter, ADDA_REG, true, is2T);
738
739 if (t == 0)
740 pdmpriv->bRfPiEnable = (u8)PHY_QueryBBReg(pAdapter, rFPGA0_XA_HSSIParameter1, BIT(8));
741
742 if (!pdmpriv->bRfPiEnable) {
743 /* Switch BB to PI mode to do IQ Calibration. */
744 _PHY_PIModeSwitch(pAdapter, true);
745 }
746
747 PHY_SetBBReg(pAdapter, rFPGA0_RFMOD, BIT24, 0x00);
748 PHY_SetBBReg(pAdapter, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
749 PHY_SetBBReg(pAdapter, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
750 PHY_SetBBReg(pAdapter, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
751 PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT10, 0x01);
752 PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT26, 0x01);
753 PHY_SetBBReg(pAdapter, rFPGA0_XA_RFInterfaceOE, BIT10, 0x00);
754 PHY_SetBBReg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT10, 0x00);
755
756 if (is2T) {
757 PHY_SetBBReg(pAdapter, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00010000);
758 PHY_SetBBReg(pAdapter, rFPGA0_XB_LSSIParameter, bMaskDWord, 0x00010000);
759 }
760
761 /* MAC settings */
762 _PHY_MACSettingCalibration(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup);
763
764 /* Page B init */
765 PHY_SetBBReg(pAdapter, rConfig_AntA, bMaskDWord, 0x00080000);
766
767 if (is2T)
768 PHY_SetBBReg(pAdapter, rConfig_AntB, bMaskDWord, 0x00080000);
769
770 /* IQ calibration setting */
771 PHY_SetBBReg(pAdapter, rFPGA0_IQK, bMaskDWord, 0x80800000);
772 PHY_SetBBReg(pAdapter, rTx_IQK, bMaskDWord, 0x01007c00);
773 PHY_SetBBReg(pAdapter, rRx_IQK, bMaskDWord, 0x01004800);
774
775 for (i = 0 ; i < retryCount ; i++) {
776 PathAOK = _PHY_PathA_IQK(pAdapter, is2T);
777 if (PathAOK == 0x03) {
778 DBG_8723A("Path A IQK Success!!\n");
779 result[t][0] = (PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
780 result[t][1] = (PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
781 result[t][2] = (PHY_QueryBBReg(pAdapter, rRx_Power_Before_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
782 result[t][3] = (PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_A_2, bMaskDWord)&0x3FF0000)>>16;
783 break;
784 } else if (i == (retryCount-1) && PathAOK == 0x01) {
785 /* Tx IQK OK */
786 DBG_8723A("Path A IQK Only Tx Success!!\n");
787
788 result[t][0] = (PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_A, bMaskDWord)&0x3FF0000)>>16;
789 result[t][1] = (PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_A, bMaskDWord)&0x3FF0000)>>16;
790 }
791 }
792
793 if (0x00 == PathAOK) {
794 DBG_8723A("Path A IQK failed!!\n");
795 }
796
797 if (is2T) {
798 _PHY_PathAStandBy(pAdapter);
799
800 /* Turn Path B ADDA on */
801 _PHY_PathADDAOn(pAdapter, ADDA_REG, false, is2T);
802
803 for (i = 0 ; i < retryCount ; i++) {
804 PathBOK = _PHY_PathB_IQK(pAdapter);
805 if (PathBOK == 0x03) {
806 DBG_8723A("Path B IQK Success!!\n");
807 result[t][4] = (PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_B, bMaskDWord)&0x3FF0000)>>16;
808 result[t][5] = (PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_B, bMaskDWord)&0x3FF0000)>>16;
809 result[t][6] = (PHY_QueryBBReg(pAdapter, rRx_Power_Before_IQK_B_2, bMaskDWord)&0x3FF0000)>>16;
810 result[t][7] = (PHY_QueryBBReg(pAdapter, rRx_Power_After_IQK_B_2, bMaskDWord)&0x3FF0000)>>16;
811 break;
812 } else if (i == (retryCount - 1) && PathBOK == 0x01) {
813 /* Tx IQK OK */
814 DBG_8723A("Path B Only Tx IQK Success!!\n");
815 result[t][4] = (PHY_QueryBBReg(pAdapter, rTx_Power_Before_IQK_B, bMaskDWord)&0x3FF0000)>>16;
816 result[t][5] = (PHY_QueryBBReg(pAdapter, rTx_Power_After_IQK_B, bMaskDWord)&0x3FF0000)>>16;
817 }
818 }
819
820 if (0x00 == PathBOK) {
821 DBG_8723A("Path B IQK failed!!\n");
822 }
823 }
824
825 /* Back to BB mode, load original value */
826 PHY_SetBBReg(pAdapter, rFPGA0_IQK, bMaskDWord, 0);
827
828 if (t != 0) {
829 if (!pdmpriv->bRfPiEnable) {
830 /* Switch back BB to SI mode after finish IQ Calibration. */
831 _PHY_PIModeSwitch(pAdapter, false);
832 }
833
834 /* Reload ADDA power saving parameters */
835 _PHY_ReloadADDARegisters(pAdapter, ADDA_REG, pdmpriv->ADDA_backup, IQK_ADDA_REG_NUM);
836
837 /* Reload MAC parameters */
838 _PHY_ReloadMACRegisters(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup);
839
840 /* Reload BB parameters */
841 _PHY_ReloadADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup, IQK_BB_REG_NUM);
842
843 /* Restore RX initial gain */
844 PHY_SetBBReg(pAdapter, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00032ed3);
845 if (is2T) {
846 PHY_SetBBReg(pAdapter, rFPGA0_XB_LSSIParameter, bMaskDWord, 0x00032ed3);
847 }
848
849 /* load 0xe30 IQC default value */
850 PHY_SetBBReg(pAdapter, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
851 PHY_SetBBReg(pAdapter, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
852
853 }
854}
855
856static void _PHY_LCCalibrate(struct rtw_adapter *pAdapter, bool is2T)
857{
858 u8 tmpReg;
859 u32 RF_Amode = 0, RF_Bmode = 0, LC_Cal;
860
861 /* Check continuous TX and Packet TX */
862 tmpReg = rtw_read8(pAdapter, 0xd03);
863
864 if ((tmpReg&0x70) != 0) /* Deal with contisuous TX case */
865 rtw_write8(pAdapter, 0xd03, tmpReg&0x8F); /* disable all continuous TX */
866 else /* Deal with Packet TX case */
867 rtw_write8(pAdapter, REG_TXPAUSE, 0xFF); /* block all queues */
868
869 if ((tmpReg&0x70) != 0) {
870 /* 1. Read original RF mode */
871 /* Path-A */
872 RF_Amode = PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits);
873
874 /* Path-B */
875 if (is2T)
876 RF_Bmode = PHY_QueryRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits);
877
878 /* 2. Set RF mode = standby mode */
879 /* Path-A */
880 PHY_SetRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits, (RF_Amode&0x8FFFF)|0x10000);
881
882 /* Path-B */
883 if (is2T)
884 PHY_SetRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits, (RF_Bmode&0x8FFFF)|0x10000);
885 }
886
887 /* 3. Read RF reg18 */
888 LC_Cal = PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_CHNLBW, bMask12Bits);
889
890 /* 4. Set LC calibration begin */
891 PHY_SetRFReg(pAdapter, RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal|0x08000);
892
893 msleep(100);
894
895 /* Restore original situation */
896 if ((tmpReg&0x70) != 0) { /* Deal with contuous TX case */
897 /* Path-A */
898 rtw_write8(pAdapter, 0xd03, tmpReg);
899 PHY_SetRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits, RF_Amode);
900
901 /* Path-B */
902 if (is2T)
903 PHY_SetRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits, RF_Bmode);
904 } else { /* Deal with Packet TX case */
905 rtw_write8(pAdapter, REG_TXPAUSE, 0x00);
906 }
907}
908
909/* Analog Pre-distortion calibration */
910#define APK_BB_REG_NUM 8
911#define APK_CURVE_REG_NUM 4
912#define PATH_NUM 2
913
914void rtl8723a_phy_iq_calibrate(struct rtw_adapter *pAdapter, bool bReCovery)
915{
916 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
917 struct dm_priv *pdmpriv = &pHalData->dmpriv;
918 s32 result[4][8]; /* last is final result */
919 u8 i, final_candidate;
920 bool bPathAOK, bPathBOK;
921 s32 RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4;
922 s32 RegECC, RegTmp = 0;
923 bool is12simular, is13simular, is23simular;
924 bool bStartContTx = false, bSingleTone = false;
925 bool bCarrierSuppression = false;
926 u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = {
927 rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance,
928 rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable,
929 rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance,
930 rOFDM0_XCTxAFE, rOFDM0_XDTxAFE,
931 rOFDM0_RxIQExtAnta
932 };
933
934 /* ignore IQK when continuous Tx */
935 if (bStartContTx || bSingleTone || bCarrierSuppression)
936 return;
937
938 if (bReCovery) {
939 _PHY_ReloadADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup_recover, 9);
940 return;
941 }
942 DBG_8723A("IQK:Start!!!\n");
943
944 for (i = 0; i < 8; i++) {
945 result[0][i] = 0;
946 result[1][i] = 0;
947 result[2][i] = 0;
948 result[3][i] = 0;
949 }
950 final_candidate = 0xff;
951 bPathAOK = false;
952 bPathBOK = false;
953 is12simular = false;
954 is23simular = false;
955 is13simular = false;
956
957 for (i = 0; i < 3; i++) {
958 if (IS_92C_SERIAL(pHalData->VersionID)) {
959 _PHY_IQCalibrate(pAdapter, result, i, true);
960 } else {
961 /* For 88C 1T1R */
962 _PHY_IQCalibrate(pAdapter, result, i, false);
963 }
964
965 if (i == 1) {
966 is12simular = _PHY_SimularityCompare(pAdapter, result, 0, 1);
967 if (is12simular) {
968 final_candidate = 0;
969 break;
970 }
971 }
972
973 if (i == 2) {
974 is13simular = _PHY_SimularityCompare(pAdapter, result, 0, 2);
975 if (is13simular) {
976 final_candidate = 0;
977 break;
978 }
979
980 is23simular = _PHY_SimularityCompare(pAdapter, result, 1, 2);
981 if (is23simular) {
982 final_candidate = 1;
983 } else {
984 for (i = 0; i < 8; i++)
985 RegTmp += result[3][i];
986
987 if (RegTmp != 0)
988 final_candidate = 3;
989 else
990 final_candidate = 0xFF;
991 }
992 }
993 }
994
995 for (i = 0; i < 4; i++) {
996 RegE94 = result[i][0];
997 RegE9C = result[i][1];
998 RegEA4 = result[i][2];
999 RegEAC = result[i][3];
1000 RegEB4 = result[i][4];
1001 RegEBC = result[i][5];
1002 RegEC4 = result[i][6];
1003 RegECC = result[i][7];
1004 }
1005
1006 if (final_candidate != 0xff) {
1007 RegE94 = result[final_candidate][0];
1008 pdmpriv->RegE94 = RegE94;
1009 RegE9C = result[final_candidate][1];
1010 pdmpriv->RegE9C = RegE9C;
1011 RegEA4 = result[final_candidate][2];
1012 RegEAC = result[final_candidate][3];
1013 RegEB4 = result[final_candidate][4];
1014 pdmpriv->RegEB4 = RegEB4;
1015 RegEBC = result[final_candidate][5];
1016 pdmpriv->RegEBC = RegEBC;
1017 RegEC4 = result[final_candidate][6];
1018 RegECC = result[final_candidate][7];
1019 DBG_8723A("IQK: final_candidate is %x\n", final_candidate);
1020 DBG_8723A("IQK: RegE94 =%x RegE9C =%x RegEA4 =%x RegEAC =%x RegEB4 =%x RegEBC =%x RegEC4 =%x RegECC =%x\n ",
1021 RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC);
1022 bPathAOK = bPathBOK = true;
1023 } else {
1024 RegE94 = RegEB4 = pdmpriv->RegE94 = pdmpriv->RegEB4 = 0x100; /* X default value */
1025 RegE9C = RegEBC = pdmpriv->RegE9C = pdmpriv->RegEBC = 0x0; /* Y default value */
1026 }
1027
1028 if ((RegE94 != 0)/*&&(RegEA4 != 0)*/)
1029 _PHY_PathAFillIQKMatrix(pAdapter, bPathAOK, result, final_candidate, (RegEA4 == 0));
1030
1031 if (IS_92C_SERIAL(pHalData->VersionID)) {
1032 if ((RegEB4 != 0)/*&&(RegEC4 != 0)*/)
1033 _PHY_PathBFillIQKMatrix(pAdapter, bPathBOK, result, final_candidate, (RegEC4 == 0));
1034 }
1035
1036 _PHY_SaveADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup_recover, 9);
1037}
1038
1039void rtl8723a_phy_lc_calibrate(struct rtw_adapter *pAdapter)
1040{
1041 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
1042 struct mlme_ext_priv *pmlmeext = &pAdapter->mlmeextpriv;
1043 bool bStartContTx = false, bSingleTone = false, bCarrierSuppression = false;
1044
1045 /* ignore IQK when continuous Tx */
1046 if (bStartContTx || bSingleTone || bCarrierSuppression)
1047 return;
1048
1049 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
1050 return;
1051
1052 if (IS_92C_SERIAL(pHalData->VersionID)) {
1053 _PHY_LCCalibrate(pAdapter, true);
1054 } else {
1055 /* For 88C 1T1R */
1056 _PHY_LCCalibrate(pAdapter, false);
1057 }
1058}
1059
1060void
1061rtl8723a_phy_ap_calibrate(struct rtw_adapter *pAdapter, char delta)
1062{
1063}
diff --git a/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c b/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c
new file mode 100644
index 000000000000..294e6a6c60db
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c
@@ -0,0 +1,726 @@
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******************************************************************************/
15
16#include "odm_precomp.h"
17
18static bool CheckCondition(const u32 Condition, const u32 Hex)
19{
20 u32 _board = (Hex & 0x000000FF);
21 u32 _interface = (Hex & 0x0000FF00) >> 8;
22 u32 _platform = (Hex & 0x00FF0000) >> 16;
23 u32 cond = Condition;
24
25 if (Condition == 0xCDCDCDCD)
26 return true;
27
28 cond = Condition & 0x000000FF;
29 if ((_board == cond) && cond != 0x00)
30 return false;
31
32 cond = Condition & 0x0000FF00;
33 cond = cond >> 8;
34 if ((_interface & cond) == 0 && cond != 0x07)
35 return false;
36
37 cond = Condition & 0x00FF0000;
38 cond = cond >> 16;
39 if ((_platform & cond) == 0 && cond != 0x0F)
40 return false;
41 return true;
42}
43
44/******************************************************************************
45* AGC_TAB_1T.TXT
46******************************************************************************/
47
48static u32 Array_AGC_TAB_1T_8723A[] = {
49 0xC78, 0x7B000001,
50 0xC78, 0x7B010001,
51 0xC78, 0x7B020001,
52 0xC78, 0x7B030001,
53 0xC78, 0x7B040001,
54 0xC78, 0x7B050001,
55 0xC78, 0x7A060001,
56 0xC78, 0x79070001,
57 0xC78, 0x78080001,
58 0xC78, 0x77090001,
59 0xC78, 0x760A0001,
60 0xC78, 0x750B0001,
61 0xC78, 0x740C0001,
62 0xC78, 0x730D0001,
63 0xC78, 0x720E0001,
64 0xC78, 0x710F0001,
65 0xC78, 0x70100001,
66 0xC78, 0x6F110001,
67 0xC78, 0x6E120001,
68 0xC78, 0x6D130001,
69 0xC78, 0x6C140001,
70 0xC78, 0x6B150001,
71 0xC78, 0x6A160001,
72 0xC78, 0x69170001,
73 0xC78, 0x68180001,
74 0xC78, 0x67190001,
75 0xC78, 0x661A0001,
76 0xC78, 0x651B0001,
77 0xC78, 0x641C0001,
78 0xC78, 0x631D0001,
79 0xC78, 0x621E0001,
80 0xC78, 0x611F0001,
81 0xC78, 0x60200001,
82 0xC78, 0x49210001,
83 0xC78, 0x48220001,
84 0xC78, 0x47230001,
85 0xC78, 0x46240001,
86 0xC78, 0x45250001,
87 0xC78, 0x44260001,
88 0xC78, 0x43270001,
89 0xC78, 0x42280001,
90 0xC78, 0x41290001,
91 0xC78, 0x402A0001,
92 0xC78, 0x262B0001,
93 0xC78, 0x252C0001,
94 0xC78, 0x242D0001,
95 0xC78, 0x232E0001,
96 0xC78, 0x222F0001,
97 0xC78, 0x21300001,
98 0xC78, 0x20310001,
99 0xC78, 0x06320001,
100 0xC78, 0x05330001,
101 0xC78, 0x04340001,
102 0xC78, 0x03350001,
103 0xC78, 0x02360001,
104 0xC78, 0x01370001,
105 0xC78, 0x00380001,
106 0xC78, 0x00390001,
107 0xC78, 0x003A0001,
108 0xC78, 0x003B0001,
109 0xC78, 0x003C0001,
110 0xC78, 0x003D0001,
111 0xC78, 0x003E0001,
112 0xC78, 0x003F0001,
113 0xC78, 0x7B400001,
114 0xC78, 0x7B410001,
115 0xC78, 0x7B420001,
116 0xC78, 0x7B430001,
117 0xC78, 0x7B440001,
118 0xC78, 0x7B450001,
119 0xC78, 0x7A460001,
120 0xC78, 0x79470001,
121 0xC78, 0x78480001,
122 0xC78, 0x77490001,
123 0xC78, 0x764A0001,
124 0xC78, 0x754B0001,
125 0xC78, 0x744C0001,
126 0xC78, 0x734D0001,
127 0xC78, 0x724E0001,
128 0xC78, 0x714F0001,
129 0xC78, 0x70500001,
130 0xC78, 0x6F510001,
131 0xC78, 0x6E520001,
132 0xC78, 0x6D530001,
133 0xC78, 0x6C540001,
134 0xC78, 0x6B550001,
135 0xC78, 0x6A560001,
136 0xC78, 0x69570001,
137 0xC78, 0x68580001,
138 0xC78, 0x67590001,
139 0xC78, 0x665A0001,
140 0xC78, 0x655B0001,
141 0xC78, 0x645C0001,
142 0xC78, 0x635D0001,
143 0xC78, 0x625E0001,
144 0xC78, 0x615F0001,
145 0xC78, 0x60600001,
146 0xC78, 0x49610001,
147 0xC78, 0x48620001,
148 0xC78, 0x47630001,
149 0xC78, 0x46640001,
150 0xC78, 0x45650001,
151 0xC78, 0x44660001,
152 0xC78, 0x43670001,
153 0xC78, 0x42680001,
154 0xC78, 0x41690001,
155 0xC78, 0x406A0001,
156 0xC78, 0x266B0001,
157 0xC78, 0x256C0001,
158 0xC78, 0x246D0001,
159 0xC78, 0x236E0001,
160 0xC78, 0x226F0001,
161 0xC78, 0x21700001,
162 0xC78, 0x20710001,
163 0xC78, 0x06720001,
164 0xC78, 0x05730001,
165 0xC78, 0x04740001,
166 0xC78, 0x03750001,
167 0xC78, 0x02760001,
168 0xC78, 0x01770001,
169 0xC78, 0x00780001,
170 0xC78, 0x00790001,
171 0xC78, 0x007A0001,
172 0xC78, 0x007B0001,
173 0xC78, 0x007C0001,
174 0xC78, 0x007D0001,
175 0xC78, 0x007E0001,
176 0xC78, 0x007F0001,
177 0xC78, 0x3800001E,
178 0xC78, 0x3801001E,
179 0xC78, 0x3802001E,
180 0xC78, 0x3803001E,
181 0xC78, 0x3804001E,
182 0xC78, 0x3805001E,
183 0xC78, 0x3806001E,
184 0xC78, 0x3807001E,
185 0xC78, 0x3808001E,
186 0xC78, 0x3C09001E,
187 0xC78, 0x3E0A001E,
188 0xC78, 0x400B001E,
189 0xC78, 0x440C001E,
190 0xC78, 0x480D001E,
191 0xC78, 0x4C0E001E,
192 0xC78, 0x500F001E,
193 0xC78, 0x5210001E,
194 0xC78, 0x5611001E,
195 0xC78, 0x5A12001E,
196 0xC78, 0x5E13001E,
197 0xC78, 0x6014001E,
198 0xC78, 0x6015001E,
199 0xC78, 0x6016001E,
200 0xC78, 0x6217001E,
201 0xC78, 0x6218001E,
202 0xC78, 0x6219001E,
203 0xC78, 0x621A001E,
204 0xC78, 0x621B001E,
205 0xC78, 0x621C001E,
206 0xC78, 0x621D001E,
207 0xC78, 0x621E001E,
208 0xC78, 0x621F001E,
209};
210
211#define READ_NEXT_PAIR(v1, v2, i) \
212 do { \
213 i += 2; v1 = Array[i]; v2 = Array[i+1]; \
214 } while (0)
215
216void ODM_ReadAndConfig_AGC_TAB_1T_8723A(struct dm_odm_t *pDM_Odm)
217{
218
219 u32 hex;
220 u32 i;
221 u8 platform = 0x04;
222 u8 interfaceValue = pDM_Odm->SupportInterface;
223 u8 board = pDM_Odm->BoardType;
224 u32 ArrayLen = sizeof(Array_AGC_TAB_1T_8723A)/sizeof(u32);
225 u32 *Array = Array_AGC_TAB_1T_8723A;
226
227 hex = board;
228 hex += interfaceValue << 8;
229 hex += platform << 16;
230 hex += 0xFF000000;
231 for (i = 0; i < ArrayLen; i += 2) {
232 u32 v1 = Array[i];
233 u32 v2 = Array[i+1];
234
235 /* This (offset, data) pair meets the condition. */
236 if (v1 < 0xCDCDCDCD) {
237 odm_ConfigBB_AGC_8723A(pDM_Odm, v1, bMaskDWord, v2);
238 continue;
239 } else {
240 if (!CheckCondition(Array[i], hex)) {
241 /* Discard the following (offset, data) pairs. */
242 READ_NEXT_PAIR(v1, v2, i);
243 while (v2 != 0xDEAD &&
244 v2 != 0xCDEF &&
245 v2 != 0xCDCD && i < ArrayLen - 2)
246 READ_NEXT_PAIR(v1, v2, i);
247 i -= 2; /* prevent from for-loop += 2 */
248 } else {
249 /* Configure matched pairs and skip to end of if-else. */
250 READ_NEXT_PAIR(v1, v2, i);
251 while (v2 != 0xDEAD &&
252 v2 != 0xCDEF &&
253 v2 != 0xCDCD && i < ArrayLen - 2) {
254 odm_ConfigBB_AGC_8723A(pDM_Odm, v1, bMaskDWord, v2);
255 READ_NEXT_PAIR(v1, v2, i);
256 }
257 while (v2 != 0xDEAD && i < ArrayLen - 2)
258 READ_NEXT_PAIR(v1, v2, i);
259 }
260 }
261 }
262}
263
264/******************************************************************************
265* PHY_REG_1T.TXT
266******************************************************************************/
267
268static u32 Array_PHY_REG_1T_8723A[] = {
269 0x800, 0x80040000,
270 0x804, 0x00000003,
271 0x808, 0x0000FC00,
272 0x80C, 0x0000000A,
273 0x810, 0x10001331,
274 0x814, 0x020C3D10,
275 0x818, 0x02200385,
276 0x81C, 0x00000000,
277 0x820, 0x01000100,
278 0x824, 0x00390004,
279 0x828, 0x00000000,
280 0x82C, 0x00000000,
281 0x830, 0x00000000,
282 0x834, 0x00000000,
283 0x838, 0x00000000,
284 0x83C, 0x00000000,
285 0x840, 0x00010000,
286 0x844, 0x00000000,
287 0x848, 0x00000000,
288 0x84C, 0x00000000,
289 0x850, 0x00000000,
290 0x854, 0x00000000,
291 0x858, 0x569A569A,
292 0x85C, 0x001B25A4,
293 0x860, 0x66F60110,
294 0x864, 0x061F0130,
295 0x868, 0x00000000,
296 0x86C, 0x32323200,
297 0x870, 0x07000760,
298 0x874, 0x22004000,
299 0x878, 0x00000808,
300 0x87C, 0x00000000,
301 0x880, 0xC0083070,
302 0x884, 0x000004D5,
303 0x888, 0x00000000,
304 0x88C, 0xCCC000C0,
305 0x890, 0x00000800,
306 0x894, 0xFFFFFFFE,
307 0x898, 0x40302010,
308 0x89C, 0x00706050,
309 0x900, 0x00000000,
310 0x904, 0x00000023,
311 0x908, 0x00000000,
312 0x90C, 0x81121111,
313 0xA00, 0x00D047C8,
314 0xA04, 0x80FF000C,
315 0xA08, 0x8C838300,
316 0xA0C, 0x2E68120F,
317 0xA10, 0x9500BB78,
318 0xA14, 0x11144028,
319 0xA18, 0x00881117,
320 0xA1C, 0x89140F00,
321 0xA20, 0x1A1B0000,
322 0xA24, 0x090E1317,
323 0xA28, 0x00000204,
324 0xA2C, 0x00D30000,
325 0xA70, 0x101FBF00,
326 0xA74, 0x00000007,
327 0xA78, 0x00000900,
328 0xC00, 0x48071D40,
329 0xC04, 0x03A05611,
330 0xC08, 0x000000E4,
331 0xC0C, 0x6C6C6C6C,
332 0xC10, 0x08800000,
333 0xC14, 0x40000100,
334 0xC18, 0x08800000,
335 0xC1C, 0x40000100,
336 0xC20, 0x00000000,
337 0xC24, 0x00000000,
338 0xC28, 0x00000000,
339 0xC2C, 0x00000000,
340 0xC30, 0x69E9AC44,
341 0xFF0F011F, 0xABCD,
342 0xC34, 0x469652CF,
343 0xCDCDCDCD, 0xCDCD,
344 0xC34, 0x469652AF,
345 0xFF0F011F, 0xDEAD,
346 0xC38, 0x49795994,
347 0xC3C, 0x0A97971C,
348 0xC40, 0x1F7C403F,
349 0xC44, 0x000100B7,
350 0xC48, 0xEC020107,
351 0xC4C, 0x007F037F,
352 0xC50, 0x69543420,
353 0xC54, 0x43BC0094,
354 0xC58, 0x69543420,
355 0xC5C, 0x433C0094,
356 0xC60, 0x00000000,
357 0xFF0F011F, 0xABCD,
358 0xC64, 0x7116848B,
359 0xCDCDCDCD, 0xCDCD,
360 0xC64, 0x7112848B,
361 0xFF0F011F, 0xDEAD,
362 0xC68, 0x47C00BFF,
363 0xC6C, 0x00000036,
364 0xC70, 0x2C7F000D,
365 0xC74, 0x018610DB,
366 0xC78, 0x0000001F,
367 0xC7C, 0x00B91612,
368 0xC80, 0x40000100,
369 0xC84, 0x20F60000,
370 0xC88, 0x40000100,
371 0xC8C, 0x20200000,
372 0xC90, 0x00121820,
373 0xC94, 0x00000000,
374 0xC98, 0x00121820,
375 0xC9C, 0x00007F7F,
376 0xCA0, 0x00000000,
377 0xCA4, 0x00000080,
378 0xCA8, 0x00000000,
379 0xCAC, 0x00000000,
380 0xCB0, 0x00000000,
381 0xCB4, 0x00000000,
382 0xCB8, 0x00000000,
383 0xCBC, 0x28000000,
384 0xCC0, 0x00000000,
385 0xCC4, 0x00000000,
386 0xCC8, 0x00000000,
387 0xCCC, 0x00000000,
388 0xCD0, 0x00000000,
389 0xCD4, 0x00000000,
390 0xCD8, 0x64B22427,
391 0xCDC, 0x00766932,
392 0xCE0, 0x00222222,
393 0xCE4, 0x00000000,
394 0xCE8, 0x37644302,
395 0xCEC, 0x2F97D40C,
396 0xD00, 0x00080740,
397 0xD04, 0x00020401,
398 0xD08, 0x0000907F,
399 0xD0C, 0x20010201,
400 0xD10, 0xA0633333,
401 0xD14, 0x3333BC43,
402 0xD18, 0x7A8F5B6B,
403 0xD2C, 0xCC979975,
404 0xD30, 0x00000000,
405 0xD34, 0x80608000,
406 0xD38, 0x00000000,
407 0xD3C, 0x00027293,
408 0xD40, 0x00000000,
409 0xD44, 0x00000000,
410 0xD48, 0x00000000,
411 0xD4C, 0x00000000,
412 0xD50, 0x6437140A,
413 0xD54, 0x00000000,
414 0xD58, 0x00000000,
415 0xD5C, 0x30032064,
416 0xD60, 0x4653DE68,
417 0xD64, 0x04518A3C,
418 0xD68, 0x00002101,
419 0xD6C, 0x2A201C16,
420 0xD70, 0x1812362E,
421 0xD74, 0x322C2220,
422 0xD78, 0x000E3C24,
423 0xE00, 0x2A2A2A2A,
424 0xE04, 0x2A2A2A2A,
425 0xE08, 0x03902A2A,
426 0xE10, 0x2A2A2A2A,
427 0xE14, 0x2A2A2A2A,
428 0xE18, 0x2A2A2A2A,
429 0xE1C, 0x2A2A2A2A,
430 0xE28, 0x00000000,
431 0xE30, 0x1000DC1F,
432 0xE34, 0x10008C1F,
433 0xE38, 0x02140102,
434 0xE3C, 0x681604C2,
435 0xE40, 0x01007C00,
436 0xE44, 0x01004800,
437 0xE48, 0xFB000000,
438 0xE4C, 0x000028D1,
439 0xE50, 0x1000DC1F,
440 0xE54, 0x10008C1F,
441 0xE58, 0x02140102,
442 0xE5C, 0x28160D05,
443 0xE60, 0x00000008,
444 0xE68, 0x001B25A4,
445 0xE6C, 0x631B25A0,
446 0xE70, 0x631B25A0,
447 0xE74, 0x081B25A0,
448 0xE78, 0x081B25A0,
449 0xE7C, 0x081B25A0,
450 0xE80, 0x081B25A0,
451 0xE84, 0x631B25A0,
452 0xE88, 0x081B25A0,
453 0xE8C, 0x631B25A0,
454 0xED0, 0x631B25A0,
455 0xED4, 0x631B25A0,
456 0xED8, 0x631B25A0,
457 0xEDC, 0x001B25A0,
458 0xEE0, 0x001B25A0,
459 0xEEC, 0x6B1B25A0,
460 0xF14, 0x00000003,
461 0xF4C, 0x00000000,
462 0xF00, 0x00000300,
463};
464
465void ODM_ReadAndConfig_PHY_REG_1T_8723A(struct dm_odm_t *pDM_Odm)
466{
467 u32 hex = 0;
468 u32 i = 0;
469 u8 platform = 0x04;
470 u8 interfaceValue = pDM_Odm->SupportInterface;
471 u8 board = pDM_Odm->BoardType;
472 u32 ArrayLen = sizeof(Array_PHY_REG_1T_8723A)/sizeof(u32);
473 u32 *Array = Array_PHY_REG_1T_8723A;
474
475 hex += board;
476 hex += interfaceValue << 8;
477 hex += platform << 16;
478 hex += 0xFF000000;
479 for (i = 0; i < ArrayLen; i += 2) {
480 u32 v1 = Array[i];
481 u32 v2 = Array[i+1];
482
483 /* This (offset, data) pair meets the condition. */
484 if (v1 < 0xCDCDCDCD) {
485 odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
486 continue;
487 } else {
488 if (!CheckCondition(Array[i], hex)) {
489 /* Discard the following (offset, data) pairs. */
490 READ_NEXT_PAIR(v1, v2, i);
491 while (v2 != 0xDEAD &&
492 v2 != 0xCDEF &&
493 v2 != 0xCDCD && i < ArrayLen - 2)
494 READ_NEXT_PAIR(v1, v2, i);
495 i -= 2; /* prevent from for-loop += 2 */
496 } else {
497 /* Configure matched pairs and skip to end of if-else. */
498 READ_NEXT_PAIR(v1, v2, i);
499 while (v2 != 0xDEAD &&
500 v2 != 0xCDEF &&
501 v2 != 0xCDCD && i < ArrayLen - 2) {
502 odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
503 READ_NEXT_PAIR(v1, v2, i);
504 }
505 while (v2 != 0xDEAD && i < ArrayLen - 2)
506 READ_NEXT_PAIR(v1, v2, i);
507 }
508 }
509 }
510}
511
512/******************************************************************************
513* PHY_REG_MP.TXT
514******************************************************************************/
515
516static u32 Array_PHY_REG_MP_8723A[] = {
517 0xC30, 0x69E9AC4A,
518 0xC3C, 0x0A979718,
519};
520
521void ODM_ReadAndConfig_PHY_REG_MP_8723A(struct dm_odm_t *pDM_Odm)
522{
523 u32 hex = 0;
524 u32 i = 0;
525 u8 platform = 0x04;
526 u8 interfaceValue = pDM_Odm->SupportInterface;
527 u8 board = pDM_Odm->BoardType;
528 u32 ArrayLen = sizeof(Array_PHY_REG_MP_8723A)/sizeof(u32);
529 u32 *Array = Array_PHY_REG_MP_8723A;
530
531 hex += board;
532 hex += interfaceValue << 8;
533 hex += platform << 16;
534 hex += 0xFF000000;
535 for (i = 0; i < ArrayLen; i += 2) {
536 u32 v1 = Array[i];
537 u32 v2 = Array[i+1];
538
539 /* This (offset, data) pair meets the condition. */
540 if (v1 < 0xCDCDCDCD) {
541 odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
542 continue;
543 } else {
544 if (!CheckCondition(Array[i], hex)) {
545 /* Discard the following (offset, data) pairs. */
546 READ_NEXT_PAIR(v1, v2, i);
547 while (v2 != 0xDEAD &&
548 v2 != 0xCDEF &&
549 v2 != 0xCDCD && i < ArrayLen - 2)
550 READ_NEXT_PAIR(v1, v2, i);
551 i -= 2; /* prevent from for-loop += 2 */
552 } else {
553 /* Configure matched pairs and skip to end of if-else. */
554 READ_NEXT_PAIR(v1, v2, i);
555 while (v2 != 0xDEAD &&
556 v2 != 0xCDEF &&
557 v2 != 0xCDCD && i < ArrayLen - 2) {
558 odm_ConfigBB_PHY_8723A(pDM_Odm, v1, bMaskDWord, v2);
559 READ_NEXT_PAIR(v1, v2, i);
560 }
561 while (v2 != 0xDEAD && i < ArrayLen - 2)
562 READ_NEXT_PAIR(v1, v2, i);
563 }
564 }
565 }
566}
567
568/******************************************************************************
569* PHY_REG_PG.TXT
570******************************************************************************/
571
572static u32 Array_PHY_REG_PG_8723A[] = {
573 0xE00, 0xFFFFFFFF, 0x0A0C0C0C,
574 0xE04, 0xFFFFFFFF, 0x02040608,
575 0xE08, 0x0000FF00, 0x00000000,
576 0x86C, 0xFFFFFF00, 0x00000000,
577 0xE10, 0xFFFFFFFF, 0x0A0C0D0E,
578 0xE14, 0xFFFFFFFF, 0x02040608,
579 0xE18, 0xFFFFFFFF, 0x0A0C0D0E,
580 0xE1C, 0xFFFFFFFF, 0x02040608,
581 0x830, 0xFFFFFFFF, 0x0A0C0C0C,
582 0x834, 0xFFFFFFFF, 0x02040608,
583 0x838, 0xFFFFFF00, 0x00000000,
584 0x86C, 0x000000FF, 0x00000000,
585 0x83C, 0xFFFFFFFF, 0x0A0C0D0E,
586 0x848, 0xFFFFFFFF, 0x02040608,
587 0x84C, 0xFFFFFFFF, 0x0A0C0D0E,
588 0x868, 0xFFFFFFFF, 0x02040608,
589 0xE00, 0xFFFFFFFF, 0x00000000,
590 0xE04, 0xFFFFFFFF, 0x00000000,
591 0xE08, 0x0000FF00, 0x00000000,
592 0x86C, 0xFFFFFF00, 0x00000000,
593 0xE10, 0xFFFFFFFF, 0x00000000,
594 0xE14, 0xFFFFFFFF, 0x00000000,
595 0xE18, 0xFFFFFFFF, 0x00000000,
596 0xE1C, 0xFFFFFFFF, 0x00000000,
597 0x830, 0xFFFFFFFF, 0x00000000,
598 0x834, 0xFFFFFFFF, 0x00000000,
599 0x838, 0xFFFFFF00, 0x00000000,
600 0x86C, 0x000000FF, 0x00000000,
601 0x83C, 0xFFFFFFFF, 0x00000000,
602 0x848, 0xFFFFFFFF, 0x00000000,
603 0x84C, 0xFFFFFFFF, 0x00000000,
604 0x868, 0xFFFFFFFF, 0x00000000,
605 0xE00, 0xFFFFFFFF, 0x04040404,
606 0xE04, 0xFFFFFFFF, 0x00020204,
607 0xE08, 0x0000FF00, 0x00000000,
608 0x86C, 0xFFFFFF00, 0x00000000,
609 0xE10, 0xFFFFFFFF, 0x06060606,
610 0xE14, 0xFFFFFFFF, 0x00020406,
611 0xE18, 0xFFFFFFFF, 0x00000000,
612 0xE1C, 0xFFFFFFFF, 0x00000000,
613 0x830, 0xFFFFFFFF, 0x04040404,
614 0x834, 0xFFFFFFFF, 0x00020204,
615 0x838, 0xFFFFFF00, 0x00000000,
616 0x86C, 0x000000FF, 0x00000000,
617 0x83C, 0xFFFFFFFF, 0x06060606,
618 0x848, 0xFFFFFFFF, 0x00020406,
619 0x84C, 0xFFFFFFFF, 0x00000000,
620 0x868, 0xFFFFFFFF, 0x00000000,
621 0xE00, 0xFFFFFFFF, 0x00000000,
622 0xE04, 0xFFFFFFFF, 0x00000000,
623 0xE08, 0x0000FF00, 0x00000000,
624 0x86C, 0xFFFFFF00, 0x00000000,
625 0xE10, 0xFFFFFFFF, 0x00000000,
626 0xE14, 0xFFFFFFFF, 0x00000000,
627 0xE18, 0xFFFFFFFF, 0x00000000,
628 0xE1C, 0xFFFFFFFF, 0x00000000,
629 0x830, 0xFFFFFFFF, 0x00000000,
630 0x834, 0xFFFFFFFF, 0x00000000,
631 0x838, 0xFFFFFF00, 0x00000000,
632 0x86C, 0x000000FF, 0x00000000,
633 0x83C, 0xFFFFFFFF, 0x00000000,
634 0x848, 0xFFFFFFFF, 0x00000000,
635 0x84C, 0xFFFFFFFF, 0x00000000,
636 0x868, 0xFFFFFFFF, 0x00000000,
637 0xE00, 0xFFFFFFFF, 0x00000000,
638 0xE04, 0xFFFFFFFF, 0x00000000,
639 0xE08, 0x0000FF00, 0x00000000,
640 0x86C, 0xFFFFFF00, 0x00000000,
641 0xE10, 0xFFFFFFFF, 0x00000000,
642 0xE14, 0xFFFFFFFF, 0x00000000,
643 0xE18, 0xFFFFFFFF, 0x00000000,
644 0xE1C, 0xFFFFFFFF, 0x00000000,
645 0x830, 0xFFFFFFFF, 0x00000000,
646 0x834, 0xFFFFFFFF, 0x00000000,
647 0x838, 0xFFFFFF00, 0x00000000,
648 0x86C, 0x000000FF, 0x00000000,
649 0x83C, 0xFFFFFFFF, 0x00000000,
650 0x848, 0xFFFFFFFF, 0x00000000,
651 0x84C, 0xFFFFFFFF, 0x00000000,
652 0x868, 0xFFFFFFFF, 0x00000000,
653 0xE00, 0xFFFFFFFF, 0x04040404,
654 0xE04, 0xFFFFFFFF, 0x00020204,
655 0xE08, 0x0000FF00, 0x00000000,
656 0x86C, 0xFFFFFF00, 0x00000000,
657 0xE10, 0xFFFFFFFF, 0x00000000,
658 0xE14, 0xFFFFFFFF, 0x00000000,
659 0xE18, 0xFFFFFFFF, 0x00000000,
660 0xE1C, 0xFFFFFFFF, 0x00000000,
661 0x830, 0xFFFFFFFF, 0x04040404,
662 0x834, 0xFFFFFFFF, 0x00020204,
663 0x838, 0xFFFFFF00, 0x00000000,
664 0x86C, 0x000000FF, 0x00000000,
665 0x83C, 0xFFFFFFFF, 0x00000000,
666 0x848, 0xFFFFFFFF, 0x00000000,
667 0x84C, 0xFFFFFFFF, 0x00000000,
668 0x868, 0xFFFFFFFF, 0x00000000,
669 0xE00, 0xFFFFFFFF, 0x00000000,
670 0xE04, 0xFFFFFFFF, 0x00000000,
671 0xE08, 0x0000FF00, 0x00000000,
672 0x86C, 0xFFFFFF00, 0x00000000,
673 0xE10, 0xFFFFFFFF, 0x00000000,
674 0xE14, 0xFFFFFFFF, 0x00000000,
675 0xE18, 0xFFFFFFFF, 0x00000000,
676 0xE1C, 0xFFFFFFFF, 0x00000000,
677 0x830, 0xFFFFFFFF, 0x00000000,
678 0x834, 0xFFFFFFFF, 0x00000000,
679 0x838, 0xFFFFFF00, 0x00000000,
680 0x86C, 0x000000FF, 0x00000000,
681 0x83C, 0xFFFFFFFF, 0x00000000,
682 0x848, 0xFFFFFFFF, 0x00000000,
683 0x84C, 0xFFFFFFFF, 0x00000000,
684 0x868, 0xFFFFFFFF, 0x00000000,
685};
686
687void ODM_ReadAndConfig_PHY_REG_PG_8723A(struct dm_odm_t *pDM_Odm)
688{
689 u32 hex = 0;
690 u32 i = 0;
691 u8 platform = 0x04;
692 u8 interfaceValue = pDM_Odm->SupportInterface;
693 u8 board = pDM_Odm->BoardType;
694 u32 ArrayLen = sizeof(Array_PHY_REG_PG_8723A)/sizeof(u32);
695 u32 *Array = Array_PHY_REG_PG_8723A;
696
697 hex += board;
698 hex += interfaceValue << 8;
699 hex += platform << 16;
700 hex += 0xFF000000;
701 for (i = 0; i < ArrayLen; i += 3) {
702 u32 v1 = Array[i];
703 u32 v2 = Array[i+1];
704 u32 v3 = Array[i+2];
705
706 /* this line is a line of pure_body */
707 if (v1 < 0xCDCDCDCD) {
708 odm_ConfigBB_PHY_REG_PG_8723A(pDM_Odm, v1, v2, v3);
709 continue;
710 } else { /* this line is the start of branch */
711 if (!CheckCondition(Array[i], hex)) {
712 /* don't need the hw_body */
713 i += 2; /* skip the pair of expression */
714 v1 = Array[i];
715 v2 = Array[i+1];
716 v3 = Array[i+2];
717 while (v2 != 0xDEAD) {
718 i += 3;
719 v1 = Array[i];
720 v2 = Array[i+1];
721 v3 = Array[i+1];
722 }
723 }
724 }
725 }
726}
diff --git a/drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c b/drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c
new file mode 100644
index 000000000000..12071453be97
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c
@@ -0,0 +1,188 @@
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******************************************************************************/
15
16#include "odm_precomp.h"
17
18static bool CheckCondition(const u32 Condition, const u32 Hex)
19{
20 u32 _board = (Hex & 0x000000FF);
21 u32 _interface = (Hex & 0x0000FF00) >> 8;
22 u32 _platform = (Hex & 0x00FF0000) >> 16;
23 u32 cond = Condition;
24
25 if (Condition == 0xCDCDCDCD)
26 return true;
27
28 cond = Condition & 0x000000FF;
29 if ((_board == cond) && cond != 0x00)
30 return false;
31
32 cond = Condition & 0x0000FF00;
33 cond = cond >> 8;
34 if ((_interface & cond) == 0 && cond != 0x07)
35 return false;
36
37 cond = Condition & 0x00FF0000;
38 cond = cond >> 16;
39 if ((_platform & cond) == 0 && cond != 0x0F)
40 return false;
41 return true;
42}
43
44/******************************************************************************
45* MAC_REG.TXT
46******************************************************************************/
47
48static u32 Array_MAC_REG_8723A[] = {
49 0x420, 0x00000080,
50 0x423, 0x00000000,
51 0x430, 0x00000000,
52 0x431, 0x00000000,
53 0x432, 0x00000000,
54 0x433, 0x00000001,
55 0x434, 0x00000004,
56 0x435, 0x00000005,
57 0x436, 0x00000006,
58 0x437, 0x00000007,
59 0x438, 0x00000000,
60 0x439, 0x00000000,
61 0x43A, 0x00000000,
62 0x43B, 0x00000001,
63 0x43C, 0x00000004,
64 0x43D, 0x00000005,
65 0x43E, 0x00000006,
66 0x43F, 0x00000007,
67 0x440, 0x0000005D,
68 0x441, 0x00000001,
69 0x442, 0x00000000,
70 0x444, 0x00000015,
71 0x445, 0x000000F0,
72 0x446, 0x0000000F,
73 0x447, 0x00000000,
74 0x458, 0x00000041,
75 0x459, 0x000000A8,
76 0x45A, 0x00000072,
77 0x45B, 0x000000B9,
78 0x460, 0x00000066,
79 0x461, 0x00000066,
80 0x462, 0x00000008,
81 0x463, 0x00000003,
82 0x4C8, 0x000000FF,
83 0x4C9, 0x00000008,
84 0x4CC, 0x000000FF,
85 0x4CD, 0x000000FF,
86 0x4CE, 0x00000001,
87 0x500, 0x00000026,
88 0x501, 0x000000A2,
89 0x502, 0x0000002F,
90 0x503, 0x00000000,
91 0x504, 0x00000028,
92 0x505, 0x000000A3,
93 0x506, 0x0000005E,
94 0x507, 0x00000000,
95 0x508, 0x0000002B,
96 0x509, 0x000000A4,
97 0x50A, 0x0000005E,
98 0x50B, 0x00000000,
99 0x50C, 0x0000004F,
100 0x50D, 0x000000A4,
101 0x50E, 0x00000000,
102 0x50F, 0x00000000,
103 0x512, 0x0000001C,
104 0x514, 0x0000000A,
105 0x515, 0x00000010,
106 0x516, 0x0000000A,
107 0x517, 0x00000010,
108 0x51A, 0x00000016,
109 0x524, 0x0000000F,
110 0x525, 0x0000004F,
111 0x546, 0x00000040,
112 0x547, 0x00000000,
113 0x550, 0x00000010,
114 0x551, 0x00000010,
115 0x559, 0x00000002,
116 0x55A, 0x00000002,
117 0x55D, 0x000000FF,
118 0x605, 0x00000030,
119 0x608, 0x0000000E,
120 0x609, 0x0000002A,
121 0x652, 0x00000020,
122 0x63C, 0x0000000A,
123 0x63D, 0x0000000A,
124 0x63E, 0x0000000E,
125 0x63F, 0x0000000E,
126 0x66E, 0x00000005,
127 0x700, 0x00000021,
128 0x701, 0x00000043,
129 0x702, 0x00000065,
130 0x703, 0x00000087,
131 0x708, 0x00000021,
132 0x709, 0x00000043,
133 0x70A, 0x00000065,
134 0x70B, 0x00000087,
135};
136
137void ODM_ReadAndConfig_MAC_REG_8723A(struct dm_odm_t *pDM_Odm)
138{
139 #define READ_NEXT_PAIR(v1, v2, i) \
140 do { \
141 i += 2; v1 = Array[i]; v2 = Array[i+1]; \
142 } while (0)
143
144 u32 hex = 0;
145 u32 i = 0;
146 u8 platform = 0x04;
147 u8 interfaceValue = pDM_Odm->SupportInterface;
148 u8 board = pDM_Odm->BoardType;
149 u32 ArrayLen = sizeof(Array_MAC_REG_8723A)/sizeof(u32);
150 u32 *Array = Array_MAC_REG_8723A;
151
152 hex += board;
153 hex += interfaceValue << 8;
154 hex += platform << 16;
155 hex += 0xFF000000;
156 for (i = 0; i < ArrayLen; i += 2) {
157 u32 v1 = Array[i];
158 u32 v2 = Array[i+1];
159
160 /* This (offset, data) pair meets the condition. */
161 if (v1 < 0xCDCDCDCD) {
162 odm_ConfigMAC_8723A(pDM_Odm, v1, (u8)v2);
163 continue;
164 } else {
165 if (!CheckCondition(Array[i], hex)) {
166 /* Discard the following (offset, data) pairs. */
167 READ_NEXT_PAIR(v1, v2, i);
168 while (v2 != 0xDEAD &&
169 v2 != 0xCDEF &&
170 v2 != 0xCDCD && i < ArrayLen - 2)
171 READ_NEXT_PAIR(v1, v2, i);
172 i -= 2; /* prevent from for-loop += 2 */
173 } else {
174 /* Configure matched pairs and skip to end of if-else. */
175 READ_NEXT_PAIR(v1, v2, i);
176 while (v2 != 0xDEAD &&
177 v2 != 0xCDEF &&
178 v2 != 0xCDCD && i < ArrayLen - 2) {
179 odm_ConfigMAC_8723A(pDM_Odm, v1, (u8)v2);
180 READ_NEXT_PAIR(v1, v2, i);
181 }
182
183 while (v2 != 0xDEAD && i < ArrayLen - 2)
184 READ_NEXT_PAIR(v1, v2, i);
185 }
186 }
187 }
188}
diff --git a/drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c b/drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c
new file mode 100644
index 000000000000..0f2ae05c8eae
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/HalHWImg8723A_RF.c
@@ -0,0 +1,259 @@
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******************************************************************************/
15
16#include "odm_precomp.h"
17
18static bool CheckCondition(const u32 Condition, const u32 Hex)
19{
20 u32 _board = (Hex & 0x000000FF);
21 u32 _interface = (Hex & 0x0000FF00) >> 8;
22 u32 _platform = (Hex & 0x00FF0000) >> 16;
23 u32 cond = Condition;
24
25 if (Condition == 0xCDCDCDCD)
26 return true;
27
28 cond = Condition & 0x000000FF;
29 if ((_board == cond) && cond != 0x00)
30 return false;
31
32 cond = Condition & 0x0000FF00;
33 cond = cond >> 8;
34 if ((_interface & cond) == 0 && cond != 0x07)
35 return false;
36
37 cond = Condition & 0x00FF0000;
38 cond = cond >> 16;
39 if ((_platform & cond) == 0 && cond != 0x0F)
40 return false;
41 return true;
42}
43
44/******************************************************************************
45* RadioA_1T.TXT
46******************************************************************************/
47
48static u32 Array_RadioA_1T_8723A[] = {
49 0x000, 0x00030159,
50 0x001, 0x00031284,
51 0x002, 0x00098000,
52 0xFF0F011F, 0xABCD,
53 0x003, 0x00018C63,
54 0xCDCDCDCD, 0xCDCD,
55 0x003, 0x00039C63,
56 0xFF0F011F, 0xDEAD,
57 0x004, 0x000210E7,
58 0x009, 0x0002044F,
59 0x00A, 0x0001A3F1,
60 0x00B, 0x00014787,
61 0x00C, 0x000896FE,
62 0x00D, 0x0000E02C,
63 0x00E, 0x00039CE7,
64 0x00F, 0x00000451,
65 0x019, 0x00000000,
66 0x01A, 0x00030355,
67 0x01B, 0x00060A00,
68 0x01C, 0x000FC378,
69 0x01D, 0x000A1250,
70 0x01E, 0x0000024F,
71 0x01F, 0x00000000,
72 0x020, 0x0000B614,
73 0x021, 0x0006C000,
74 0x022, 0x00000000,
75 0x023, 0x00001558,
76 0x024, 0x00000060,
77 0x025, 0x00000483,
78 0x026, 0x0004F000,
79 0x027, 0x000EC7D9,
80 0x028, 0x00057730,
81 0x029, 0x00004783,
82 0x02A, 0x00000001,
83 0x02B, 0x00021334,
84 0x02A, 0x00000000,
85 0x02B, 0x00000054,
86 0x02A, 0x00000001,
87 0x02B, 0x00000808,
88 0x02B, 0x00053333,
89 0x02C, 0x0000000C,
90 0x02A, 0x00000002,
91 0x02B, 0x00000808,
92 0x02B, 0x0005B333,
93 0x02C, 0x0000000D,
94 0x02A, 0x00000003,
95 0x02B, 0x00000808,
96 0x02B, 0x00063333,
97 0x02C, 0x0000000D,
98 0x02A, 0x00000004,
99 0x02B, 0x00000808,
100 0x02B, 0x0006B333,
101 0x02C, 0x0000000D,
102 0x02A, 0x00000005,
103 0x02B, 0x00000808,
104 0x02B, 0x00073333,
105 0x02C, 0x0000000D,
106 0x02A, 0x00000006,
107 0x02B, 0x00000709,
108 0x02B, 0x0005B333,
109 0x02C, 0x0000000D,
110 0x02A, 0x00000007,
111 0x02B, 0x00000709,
112 0x02B, 0x00063333,
113 0x02C, 0x0000000D,
114 0x02A, 0x00000008,
115 0x02B, 0x0000060A,
116 0x02B, 0x0004B333,
117 0x02C, 0x0000000D,
118 0x02A, 0x00000009,
119 0x02B, 0x0000060A,
120 0x02B, 0x00053333,
121 0x02C, 0x0000000D,
122 0x02A, 0x0000000A,
123 0x02B, 0x0000060A,
124 0x02B, 0x0005B333,
125 0x02C, 0x0000000D,
126 0x02A, 0x0000000B,
127 0x02B, 0x0000060A,
128 0x02B, 0x00063333,
129 0x02C, 0x0000000D,
130 0x02A, 0x0000000C,
131 0x02B, 0x0000060A,
132 0x02B, 0x0006B333,
133 0x02C, 0x0000000D,
134 0x02A, 0x0000000D,
135 0x02B, 0x0000060A,
136 0x02B, 0x00073333,
137 0x02C, 0x0000000D,
138 0x02A, 0x0000000E,
139 0x02B, 0x0000050B,
140 0x02B, 0x00066666,
141 0x02C, 0x0000001A,
142 0x02A, 0x000E0000,
143 0x010, 0x0004000F,
144 0x011, 0x000E31FC,
145 0x010, 0x0006000F,
146 0x011, 0x000FF9F8,
147 0x010, 0x0002000F,
148 0x011, 0x000203F9,
149 0x010, 0x0003000F,
150 0x011, 0x000FF500,
151 0x010, 0x00000000,
152 0x011, 0x00000000,
153 0x010, 0x0008000F,
154 0x011, 0x0003F100,
155 0x010, 0x0009000F,
156 0x011, 0x00023100,
157 0x012, 0x00032000,
158 0x012, 0x00071000,
159 0x012, 0x000B0000,
160 0x012, 0x000FC000,
161 0x013, 0x000287B3,
162 0x013, 0x000244B7,
163 0x013, 0x000204AB,
164 0x013, 0x0001C49F,
165 0x013, 0x00018493,
166 0x013, 0x0001429B,
167 0x013, 0x00010299,
168 0x013, 0x0000C29C,
169 0x013, 0x000081A0,
170 0x013, 0x000040AC,
171 0x013, 0x00000020,
172 0x014, 0x0001944C,
173 0x014, 0x00059444,
174 0x014, 0x0009944C,
175 0x014, 0x000D9444,
176 0xFF0F011F, 0xABCD,
177 0x015, 0x0000F424,
178 0x015, 0x0004F424,
179 0x015, 0x0008F424,
180 0x015, 0x000CF424,
181 0xCDCDCDCD, 0xCDCD,
182 0x015, 0x0000F474,
183 0x015, 0x0004F477,
184 0x015, 0x0008F455,
185 0x015, 0x000CF455,
186 0xFF0F011F, 0xDEAD,
187 0x016, 0x00000339,
188 0x016, 0x00040339,
189 0x016, 0x00080339,
190 0xFF0F011F, 0xABCD,
191 0x016, 0x000C0356,
192 0xCDCDCDCD, 0xCDCD,
193 0x016, 0x000C0366,
194 0xFF0F011F, 0xDEAD,
195 0x000, 0x00010159,
196 0x018, 0x0000F401,
197 0x0FE, 0x00000000,
198 0x0FE, 0x00000000,
199 0x01F, 0x00000003,
200 0x0FE, 0x00000000,
201 0x0FE, 0x00000000,
202 0x01E, 0x00000247,
203 0x01F, 0x00000000,
204 0x000, 0x00030159,
205};
206
207void ODM_ReadAndConfig_RadioA_1T_8723A(struct dm_odm_t *pDM_Odm)
208{
209 #define READ_NEXT_PAIR(v1, v2, i) \
210 do { \
211 i += 2; v1 = Array[i]; v2 = Array[i+1];\
212 } while (0)
213
214 u32 hex = 0;
215 u32 i = 0;
216 u8 platform = 0x04;
217 u8 interfaceValue = pDM_Odm->SupportInterface;
218 u8 board = pDM_Odm->BoardType;
219 u32 ArrayLen = sizeof(Array_RadioA_1T_8723A)/sizeof(u32);
220 u32 *Array = Array_RadioA_1T_8723A;
221
222 hex += board;
223 hex += interfaceValue << 8;
224 hex += platform << 16;
225 hex += 0xFF000000;
226
227 for (i = 0; i < ArrayLen; i += 2) {
228 u32 v1 = Array[i];
229 u32 v2 = Array[i+1];
230
231 /* This (offset, data) pair meets the condition. */
232 if (v1 < 0xCDCDCDCD) {
233 odm_ConfigRF_RadioA_8723A(pDM_Odm, v1, v2);
234 continue;
235 } else {
236 if (!CheckCondition(Array[i], hex)) {
237 /* Discard the following (offset, data) pairs. */
238 READ_NEXT_PAIR(v1, v2, i);
239 while (v2 != 0xDEAD &&
240 v2 != 0xCDEF &&
241 v2 != 0xCDCD && i < ArrayLen - 2)
242 READ_NEXT_PAIR(v1, v2, i);
243 i -= 2; /* prevent from for-loop += 2 */
244 } else {
245 /* Configure matched pairs and skip to end of if-else. */
246 READ_NEXT_PAIR(v1, v2, i);
247 while (v2 != 0xDEAD &&
248 v2 != 0xCDEF &&
249 v2 != 0xCDCD && i < ArrayLen - 2) {
250 odm_ConfigRF_RadioA_8723A(pDM_Odm, v1, v2);
251 READ_NEXT_PAIR(v1, v2, i);
252 }
253
254 while (v2 != 0xDEAD && i < ArrayLen - 2)
255 READ_NEXT_PAIR(v1, v2, i);
256 }
257 }
258 }
259}
diff --git a/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c b/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c
new file mode 100644
index 000000000000..4f6b4b72f922
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c
@@ -0,0 +1,163 @@
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 ******************************************************************************/
15/*++
16Copyright (c) Realtek Semiconductor Corp. All rights reserved.
17
18Module Name:
19 HalPwrSeqCmd.c
20
21Abstract:
22 Implement HW Power sequence configuration CMD handling routine for
23 Realtek devices.
24
25Major Change History:
26 When Who What
27 ---------- --------------- -------------------------------
28 2011-10-26 Lucas Modify to be compatible with SD4-CE driver.
29 2011-07-07 Roger Create.
30
31--*/
32#include <HalPwrSeqCmd.h>
33
34/* */
35/* Description: */
36/* This routine deal with the Power Configuration CMDs parsing
37 for RTL8723/RTL8188E Series IC. */
38/* */
39/* Assumption: */
40/* We should follow specific format which was released from
41 HW SD. */
42/* */
43/* 2011.07.07, added by Roger. */
44/* */
45u8 HalPwrSeqCmdParsing23a(struct rtw_adapter *padapter, u8 CutVersion,
46 u8 FabVersion, u8 InterfaceType,
47 struct wlan_pwr_cfg PwrSeqCmd[])
48{
49 struct wlan_pwr_cfg PwrCfgCmd = { 0 };
50 u8 bPollingBit = false;
51 u32 AryIdx = 0;
52 u8 value = 0;
53 u32 offset = 0;
54 u32 pollingCount = 0; /* polling autoload done. */
55 u32 maxPollingCnt = 5000;
56
57 do {
58 PwrCfgCmd = PwrSeqCmd[AryIdx];
59
60 RT_TRACE(_module_hal_init_c_, _drv_info_,
61 ("HalPwrSeqCmdParsing23a: offset(%#x) cut_msk(%#x) "
62 "fab_msk(%#x) interface_msk(%#x) base(%#x) cmd(%#x) "
63 "msk(%#x) value(%#x)\n",
64 GET_PWR_CFG_OFFSET(PwrCfgCmd),
65 GET_PWR_CFG_CUT_MASK(PwrCfgCmd),
66 GET_PWR_CFG_FAB_MASK(PwrCfgCmd),
67 GET_PWR_CFG_INTF_MASK(PwrCfgCmd),
68 GET_PWR_CFG_BASE(PwrCfgCmd),
69 GET_PWR_CFG_CMD(PwrCfgCmd),
70 GET_PWR_CFG_MASK(PwrCfgCmd),
71 GET_PWR_CFG_VALUE(PwrCfgCmd)));
72
73 /* 2 Only Handle the command whose FAB, CUT, and Interface are
74 matched */
75 if ((GET_PWR_CFG_FAB_MASK(PwrCfgCmd) & FabVersion) &&
76 (GET_PWR_CFG_CUT_MASK(PwrCfgCmd) & CutVersion) &&
77 (GET_PWR_CFG_INTF_MASK(PwrCfgCmd) & InterfaceType)) {
78 switch (GET_PWR_CFG_CMD(PwrCfgCmd)) {
79 case PWR_CMD_READ:
80 RT_TRACE(_module_hal_init_c_, _drv_info_,
81 ("HalPwrSeqCmdParsing23a: "
82 "PWR_CMD_READ\n"));
83 break;
84
85 case PWR_CMD_WRITE:
86 RT_TRACE(_module_hal_init_c_, _drv_info_,
87 ("HalPwrSeqCmdParsing23a: "
88 "PWR_CMD_WRITE\n"));
89 offset = GET_PWR_CFG_OFFSET(PwrCfgCmd);
90
91 /* Read the value from system register */
92 value = rtw_read8(padapter, offset);
93
94 value &= ~(GET_PWR_CFG_MASK(PwrCfgCmd));
95 value |= (GET_PWR_CFG_VALUE(PwrCfgCmd) &
96 GET_PWR_CFG_MASK(PwrCfgCmd));
97
98 /* Write the value back to sytem register */
99 rtw_write8(padapter, offset, value);
100 break;
101
102 case PWR_CMD_POLLING:
103 RT_TRACE(_module_hal_init_c_, _drv_info_,
104 ("HalPwrSeqCmdParsing23a: "
105 "PWR_CMD_POLLING\n"));
106
107 bPollingBit = false;
108 offset = GET_PWR_CFG_OFFSET(PwrCfgCmd);
109 do {
110 value = rtw_read8(padapter, offset);
111
112 value &= GET_PWR_CFG_MASK(PwrCfgCmd);
113 if (value ==
114 (GET_PWR_CFG_VALUE(PwrCfgCmd) &
115 GET_PWR_CFG_MASK(PwrCfgCmd)))
116 bPollingBit = true;
117 else
118 udelay(10);
119
120 if (pollingCount++ > maxPollingCnt) {
121 DBG_8723A("Fail to polling "
122 "Offset[%#x]\n",
123 offset);
124 return false;
125 }
126 } while (!bPollingBit);
127
128 break;
129
130 case PWR_CMD_DELAY:
131 RT_TRACE(_module_hal_init_c_, _drv_info_,
132 ("HalPwrSeqCmdParsing23a: "
133 "PWR_CMD_DELAY\n"));
134 if (GET_PWR_CFG_VALUE(PwrCfgCmd) ==
135 PWRSEQ_DELAY_US)
136 udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd));
137 else
138 udelay(GET_PWR_CFG_OFFSET(PwrCfgCmd) *
139 1000);
140 break;
141
142 case PWR_CMD_END:
143 /* When this command is parsed, end
144 the process */
145 RT_TRACE(_module_hal_init_c_, _drv_info_,
146 ("HalPwrSeqCmdParsing23a: "
147 "PWR_CMD_END\n"));
148 return true;
149 break;
150
151 default:
152 RT_TRACE(_module_hal_init_c_, _drv_err_,
153 ("HalPwrSeqCmdParsing23a: "
154 "Unknown CMD!!\n"));
155 break;
156 }
157 }
158
159 AryIdx++; /* Add Array Index */
160 } while (1);
161
162 return true;
163}
diff --git a/drivers/staging/rtl8723au/hal/hal_com.c b/drivers/staging/rtl8723au/hal/hal_com.c
new file mode 100644
index 000000000000..0640f3522136
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/hal_com.c
@@ -0,0 +1,881 @@
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 ******************************************************************************/
15#include <osdep_service.h>
16#include <drv_types.h>
17
18#include <hal_intf.h>
19#include <hal_com.h>
20#include <rtl8723a_hal.h>
21
22#define _HAL_INIT_C_
23
24void dump_chip_info23a(struct hal_version ChipVersion)
25{
26 int cnt = 0;
27 u8 buf[128];
28
29 cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8723A_");
30
31 cnt += sprintf((buf + cnt), "%s_", IS_NORMAL_CHIP(ChipVersion) ?
32 "Normal_Chip" : "Test_Chip");
33 cnt += sprintf((buf + cnt), "%s_",
34 IS_CHIP_VENDOR_TSMC(ChipVersion) ? "TSMC" : "UMC");
35 if (IS_A_CUT(ChipVersion))
36 cnt += sprintf((buf + cnt), "A_CUT_");
37 else if (IS_B_CUT(ChipVersion))
38 cnt += sprintf((buf + cnt), "B_CUT_");
39 else if (IS_C_CUT(ChipVersion))
40 cnt += sprintf((buf + cnt), "C_CUT_");
41 else if (IS_D_CUT(ChipVersion))
42 cnt += sprintf((buf + cnt), "D_CUT_");
43 else if (IS_E_CUT(ChipVersion))
44 cnt += sprintf((buf + cnt), "E_CUT_");
45 else
46 cnt += sprintf((buf + cnt), "UNKNOWN_CUT(%d)_",
47 ChipVersion.CUTVersion);
48
49 if (IS_1T1R(ChipVersion))
50 cnt += sprintf((buf + cnt), "1T1R_");
51 else if (IS_1T2R(ChipVersion))
52 cnt += sprintf((buf + cnt), "1T2R_");
53 else if (IS_2T2R(ChipVersion))
54 cnt += sprintf((buf + cnt), "2T2R_");
55 else
56 cnt += sprintf((buf + cnt), "UNKNOWN_RFTYPE(%d)_",
57 ChipVersion.RFType);
58
59 cnt += sprintf((buf + cnt), "RomVer(%d)\n", ChipVersion.ROMVer);
60
61 DBG_8723A("%s", buf);
62}
63
64#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80
65
66/* return the final channel plan decision */
67/* hw_channel_plan: channel plan from HW (efuse/eeprom) */
68/* sw_channel_plan: channel plan from SW (registry/module param) */
69/* def_channel_plan: channel plan used when the former two is invalid */
70u8 hal_com_get_channel_plan23a(struct rtw_adapter *padapter, u8 hw_channel_plan,
71 u8 sw_channel_plan, u8 def_channel_plan,
72 bool AutoLoadFail)
73{
74 u8 swConfig;
75 u8 chnlPlan;
76
77 swConfig = true;
78 if (!AutoLoadFail) {
79 if (!rtw_is_channel_plan_valid(sw_channel_plan))
80 swConfig = false;
81 if (hw_channel_plan & EEPROM_CHANNEL_PLAN_BY_HW_MASK)
82 swConfig = false;
83 }
84
85 if (swConfig == true)
86 chnlPlan = sw_channel_plan;
87 else
88 chnlPlan = hw_channel_plan & (~EEPROM_CHANNEL_PLAN_BY_HW_MASK);
89
90 if (!rtw_is_channel_plan_valid(chnlPlan))
91 chnlPlan = def_channel_plan;
92
93 return chnlPlan;
94}
95
96u8 MRateToHwRate23a(u8 rate)
97{
98 u8 ret = DESC_RATE1M;
99
100 switch (rate) {
101 /* CCK and OFDM non-HT rates */
102 case IEEE80211_CCK_RATE_1MB:
103 ret = DESC_RATE1M;
104 break;
105 case IEEE80211_CCK_RATE_2MB:
106 ret = DESC_RATE2M;
107 break;
108 case IEEE80211_CCK_RATE_5MB:
109 ret = DESC_RATE5_5M;
110 break;
111 case IEEE80211_CCK_RATE_11MB:
112 ret = DESC_RATE11M;
113 break;
114 case IEEE80211_OFDM_RATE_6MB:
115 ret = DESC_RATE6M;
116 break;
117 case IEEE80211_OFDM_RATE_9MB:
118 ret = DESC_RATE9M;
119 break;
120 case IEEE80211_OFDM_RATE_12MB:
121 ret = DESC_RATE12M;
122 break;
123 case IEEE80211_OFDM_RATE_18MB:
124 ret = DESC_RATE18M;
125 break;
126 case IEEE80211_OFDM_RATE_24MB:
127 ret = DESC_RATE24M;
128 break;
129 case IEEE80211_OFDM_RATE_36MB:
130 ret = DESC_RATE36M;
131 break;
132 case IEEE80211_OFDM_RATE_48MB:
133 ret = DESC_RATE48M;
134 break;
135 case IEEE80211_OFDM_RATE_54MB:
136 ret = DESC_RATE54M;
137 break;
138
139 /* HT rates since here */
140 /* case MGN_MCS0: ret = DESC_RATEMCS0; break; */
141 /* case MGN_MCS1: ret = DESC_RATEMCS1; break; */
142 /* case MGN_MCS2: ret = DESC_RATEMCS2; break; */
143 /* case MGN_MCS3: ret = DESC_RATEMCS3; break; */
144 /* case MGN_MCS4: ret = DESC_RATEMCS4; break; */
145 /* case MGN_MCS5: ret = DESC_RATEMCS5; break; */
146 /* case MGN_MCS6: ret = DESC_RATEMCS6; break; */
147 /* case MGN_MCS7: ret = DESC_RATEMCS7; break; */
148
149 default:
150 break;
151 }
152 return ret;
153}
154
155void HalSetBrateCfg23a(struct rtw_adapter *padapter, u8 *mBratesOS)
156{
157 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
158 u8 i, is_brate, brate;
159 u16 brate_cfg = 0;
160 u8 rate_index;
161
162 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
163 is_brate = mBratesOS[i] & IEEE80211_BASIC_RATE_MASK;
164 brate = mBratesOS[i] & 0x7f;
165
166 if (is_brate) {
167 switch (brate) {
168 case IEEE80211_CCK_RATE_1MB:
169 brate_cfg |= RATE_1M;
170 break;
171 case IEEE80211_CCK_RATE_2MB:
172 brate_cfg |= RATE_2M;
173 break;
174 case IEEE80211_CCK_RATE_5MB:
175 brate_cfg |= RATE_5_5M;
176 break;
177 case IEEE80211_CCK_RATE_11MB:
178 brate_cfg |= RATE_11M;
179 break;
180 case IEEE80211_OFDM_RATE_6MB:
181 brate_cfg |= RATE_6M;
182 break;
183 case IEEE80211_OFDM_RATE_9MB:
184 brate_cfg |= RATE_9M;
185 break;
186 case IEEE80211_OFDM_RATE_12MB:
187 brate_cfg |= RATE_12M;
188 break;
189 case IEEE80211_OFDM_RATE_18MB:
190 brate_cfg |= RATE_18M;
191 break;
192 case IEEE80211_OFDM_RATE_24MB:
193 brate_cfg |= RATE_24M;
194 break;
195 case IEEE80211_OFDM_RATE_36MB:
196 brate_cfg |= RATE_36M;
197 break;
198 case IEEE80211_OFDM_RATE_48MB:
199 brate_cfg |= RATE_48M;
200 break;
201 case IEEE80211_OFDM_RATE_54MB:
202 brate_cfg |= RATE_54M;
203 break;
204 }
205 }
206 }
207
208 /* 2007.01.16, by Emily */
209 /* Select RRSR (in Legacy-OFDM and CCK) */
210 /* For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M,
211 and 1M from the Basic rate. */
212 /* We do not use other rates. */
213 /* 2011.03.30 add by Luke Lee */
214 /* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */
215 /* because CCK 2M has poor TXEVM */
216 /* CCK 5.5M & 11M ACK should be enabled for better
217 performance */
218
219 brate_cfg = (brate_cfg | 0xd) & 0x15d;
220 pHalData->BasicRateSet = brate_cfg;
221 brate_cfg |= 0x01; /* default enable 1M ACK rate */
222 DBG_8723A("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", brate_cfg);
223
224 /* Set RRSR rate table. */
225 rtw_write8(padapter, REG_RRSR, brate_cfg & 0xff);
226 rtw_write8(padapter, REG_RRSR + 1, (brate_cfg >> 8) & 0xff);
227 rtw_write8(padapter, REG_RRSR + 2,
228 rtw_read8(padapter, REG_RRSR + 2) & 0xf0);
229
230 rate_index = 0;
231 /* Set RTS initial rate */
232 while (brate_cfg > 0x1) {
233 brate_cfg = (brate_cfg >> 1);
234 rate_index++;
235 }
236 /* Ziv - Check */
237 rtw_write8(padapter, REG_INIRTS_RATE_SEL, rate_index);
238
239 return;
240}
241
242static void _OneOutPipeMapping(struct rtw_adapter *pAdapter)
243{
244 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
245
246 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
247 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */
248 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0]; /* BE */
249 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0]; /* BK */
250
251 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
252 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
253 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
254 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD */
255}
256
257static void _TwoOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg)
258{
259 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
260
261 if (bWIFICfg) { /* WMM */
262 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
263 /* 0, 1, 0, 1, 0, 0, 0, 0, 0 }; */
264 /* 0:H, 1:L */
265 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1]; /* VO */
266 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */
267 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */
268 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0]; /* BK */
269
270 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
271 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
272 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
273 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
274 } else { /* typical setting */
275 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
276 /* 1, 1, 0, 0, 0, 0, 0, 0, 0 }; */
277 /* 0:H, 1:L */
278 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
279 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */
280 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */
281 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */
282
283 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
284 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
285 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
286 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
287 }
288}
289
290static void _ThreeOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg)
291{
292 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
293
294 if (bWIFICfg) { /* for WMM */
295 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
296 /* 1, 2, 1, 0, 0, 0, 0, 0, 0 }; */
297 /* 0:H, 1:N, 2:L */
298 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
299 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */
300 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */
301 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */
302
303 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
304 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
305 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
306 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
307 } else { /* typical setting */
308 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
309 /* 2, 2, 1, 0, 0, 0, 0, 0, 0 }; */
310 /* 0:H, 1:N, 2:L */
311 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
312 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */
313 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */
314 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2]; /* BK */
315
316 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
317 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
318 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
319 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
320 }
321}
322
323bool Hal_MappingOutPipe23a(struct rtw_adapter *pAdapter, u8 NumOutPipe)
324{
325 struct registry_priv *pregistrypriv = &pAdapter->registrypriv;
326 bool bWIFICfg = (pregistrypriv->wifi_spec) ? true : false;
327 bool result = true;
328
329 switch (NumOutPipe) {
330 case 2:
331 _TwoOutPipeMapping(pAdapter, bWIFICfg);
332 break;
333 case 3:
334 _ThreeOutPipeMapping(pAdapter, bWIFICfg);
335 break;
336 case 1:
337 _OneOutPipeMapping(pAdapter);
338 break;
339 default:
340 result = false;
341 break;
342 }
343
344 return result;
345}
346
347void hal_init_macaddr23a(struct rtw_adapter *adapter)
348{
349 rtw_hal_set_hwreg23a(adapter, HW_VAR_MAC_ADDR,
350 adapter->eeprompriv.mac_addr);
351}
352
353/*
354* C2H event format:
355* Field TRIGGER CONTENT CMD_SEQ CMD_LEN CMD_ID
356* BITS [127:120] [119:16] [15:8] [7:4] [3:0]
357*/
358
359void c2h_evt_clear23a(struct rtw_adapter *adapter)
360{
361 rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
362}
363
364s32 c2h_evt_read23a(struct rtw_adapter *adapter, u8 *buf)
365{
366 s32 ret = _FAIL;
367 struct c2h_evt_hdr *c2h_evt;
368 int i;
369 u8 trigger;
370
371 if (buf == NULL)
372 goto exit;
373
374 trigger = rtw_read8(adapter, REG_C2HEVT_CLEAR);
375
376 if (trigger == C2H_EVT_HOST_CLOSE)
377 goto exit; /* Not ready */
378 else if (trigger != C2H_EVT_FW_CLOSE)
379 goto clear_evt; /* Not a valid value */
380
381 c2h_evt = (struct c2h_evt_hdr *)buf;
382
383 memset(c2h_evt, 0, 16);
384
385 *buf = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL);
386 *(buf + 1) = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1);
387
388 RT_PRINT_DATA(_module_hal_init_c_, _drv_info_, "c2h_evt_read23a(): ",
389 &c2h_evt, sizeof(c2h_evt));
390
391 if (0) {
392 DBG_8723A("%s id:%u, len:%u, seq:%u, trigger:0x%02x\n",
393 __func__, c2h_evt->id, c2h_evt->plen, c2h_evt->seq,
394 trigger);
395 }
396
397 /* Read the content */
398 for (i = 0; i < c2h_evt->plen; i++)
399 c2h_evt->payload[i] = rtw_read8(adapter,
400 REG_C2HEVT_MSG_NORMAL +
401 sizeof(*c2h_evt) + i);
402
403 RT_PRINT_DATA(_module_hal_init_c_, _drv_info_,
404 "c2h_evt_read23a(): Command Content:\n", c2h_evt->payload,
405 c2h_evt->plen);
406
407 ret = _SUCCESS;
408
409clear_evt:
410 /*
411 * Clear event to notify FW we have read the command.
412 * If this field isn't clear, the FW won't update the
413 * next command message.
414 */
415 c2h_evt_clear23a(adapter);
416exit:
417 return ret;
418}
419
420void
421rtl8723a_set_ampdu_min_space(struct rtw_adapter *padapter, u8 MinSpacingToSet)
422{
423 u8 SecMinSpace;
424
425 if (MinSpacingToSet <= 7) {
426 switch (padapter->securitypriv.dot11PrivacyAlgrthm) {
427 case _NO_PRIVACY_:
428 case _AES_:
429 SecMinSpace = 0;
430 break;
431
432 case _WEP40_:
433 case _WEP104_:
434 case _TKIP_:
435 case _TKIP_WTMIC_:
436 SecMinSpace = 6;
437 break;
438 default:
439 SecMinSpace = 7;
440 break;
441 }
442
443 if (MinSpacingToSet < SecMinSpace)
444 MinSpacingToSet = SecMinSpace;
445
446 /* RT_TRACE(COMP_MLME, DBG_LOUD,
447 ("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
448 padapter->MgntInfo.MinSpaceCfg)); */
449 MinSpacingToSet |=
450 rtw_read8(padapter, REG_AMPDU_MIN_SPACE) & 0xf8;
451 rtw_write8(padapter, REG_AMPDU_MIN_SPACE,
452 MinSpacingToSet);
453 }
454}
455
456void rtl8723a_set_ampdu_factor(struct rtw_adapter *padapter, u8 FactorToSet)
457{
458 u8 RegToSet_Normal[4] = { 0x41, 0xa8, 0x72, 0xb9 };
459 u8 MaxAggNum;
460 u8 *pRegToSet;
461 u8 index = 0;
462
463 pRegToSet = RegToSet_Normal; /* 0xb972a841; */
464#ifdef CONFIG_8723AU_BT_COEXIST
465 if ((BT_IsBtDisabled(padapter) == false) &&
466 (BT_1Ant(padapter) == true)) {
467 MaxAggNum = 0x8;
468 } else
469#endif /* CONFIG_8723AU_BT_COEXIST */
470 {
471 MaxAggNum = 0xF;
472 }
473
474 if (FactorToSet <= 3) {
475 FactorToSet = (1 << (FactorToSet + 2));
476 if (FactorToSet > MaxAggNum)
477 FactorToSet = MaxAggNum;
478
479 for (index = 0; index < 4; index++) {
480 if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4))
481 pRegToSet[index] = (pRegToSet[index] & 0x0f) |
482 (FactorToSet << 4);
483
484 if ((pRegToSet[index] & 0x0f) > FactorToSet)
485 pRegToSet[index] = (pRegToSet[index] & 0xf0) |
486 FactorToSet;
487
488 rtw_write8(padapter, REG_AGGLEN_LMT + index,
489 pRegToSet[index]);
490 }
491
492 /* RT_TRACE(COMP_MLME, DBG_LOUD,
493 ("Set HW_VAR_AMPDU_FACTOR: %#x\n", FactorToSet)); */
494 }
495}
496
497void rtl8723a_set_acm_ctrl(struct rtw_adapter *padapter, u8 ctrl)
498{
499 u8 hwctrl = 0;
500
501 if (ctrl != 0) {
502 hwctrl |= AcmHw_HwEn;
503
504 if (ctrl & BIT(1)) /* BE */
505 hwctrl |= AcmHw_BeqEn;
506
507 if (ctrl & BIT(2)) /* VI */
508 hwctrl |= AcmHw_ViqEn;
509
510 if (ctrl & BIT(3)) /* VO */
511 hwctrl |= AcmHw_VoqEn;
512 }
513
514 DBG_8723A("[HW_VAR_ACM_CTRL] Write 0x%02X\n", hwctrl);
515 rtw_write8(padapter, REG_ACMHWCTRL, hwctrl);
516}
517
518void rtl8723a_set_media_status(struct rtw_adapter *padapter, u8 status)
519{
520 u8 val8;
521
522 val8 = rtw_read8(padapter, MSR) & 0x0c;
523 val8 |= status;
524 rtw_write8(padapter, MSR, val8);
525}
526
527void rtl8723a_set_media_status1(struct rtw_adapter *padapter, u8 status)
528{
529 u8 val8;
530
531 val8 = rtw_read8(padapter, MSR) & 0x03;
532 val8 |= status << 2;
533 rtw_write8(padapter, MSR, val8);
534}
535
536void rtl8723a_set_bcn_func(struct rtw_adapter *padapter, u8 val)
537{
538 if (val)
539 SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION | EN_TXBCN_RPT, 0);
540 else
541 SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION | EN_TXBCN_RPT);
542}
543
544void rtl8723a_check_bssid(struct rtw_adapter *padapter, u8 val)
545{
546 u32 val32;
547 val32 = rtw_read32(padapter, REG_RCR);
548 if (val)
549 val32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;
550 else
551 val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
552 rtw_write32(padapter, REG_RCR, val32);
553}
554
555void rtl8723a_mlme_sitesurvey(struct rtw_adapter *padapter, u8 flag)
556{
557 if (flag) { /* under sitesurvey */
558 u32 v32;
559
560 /* config RCR to receive different BSSID & not
561 to receive data frame */
562 v32 = rtw_read32(padapter, REG_RCR);
563 v32 &= ~(RCR_CBSSID_BCN);
564 rtw_write32(padapter, REG_RCR, v32);
565 /* reject all data frame */
566 rtw_write16(padapter, REG_RXFLTMAP2, 0);
567
568 /* disable update TSF */
569 SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0);
570 } else { /* sitesurvey done */
571
572 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
573 struct mlme_ext_info *pmlmeinfo;
574 u32 v32;
575
576 pmlmeinfo = &pmlmeext->mlmext_info;
577
578 if ((is_client_associated_to_ap23a(padapter) == true) ||
579 ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
580 ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
581 /* enable to rx data frame */
582 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
583
584 /* enable update TSF */
585 SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT);
586 }
587
588 v32 = rtw_read32(padapter, REG_RCR);
589 v32 |= RCR_CBSSID_BCN;
590 rtw_write32(padapter, REG_RCR, v32);
591 }
592
593#ifdef CONFIG_8723AU_BT_COEXIST
594 BT_WifiScanNotify(padapter, flag ? true : false);
595#endif
596}
597
598void rtl8723a_on_rcr_am(struct rtw_adapter *padapter)
599{
600 rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR) | RCR_AM);
601 DBG_8723A("%s, %d, RCR = %x \n", __FUNCTION__, __LINE__,
602 rtw_read32(padapter, REG_RCR));
603}
604
605void rtl8723a_off_rcr_am(struct rtw_adapter *padapter)
606{
607 rtw_write32(padapter, REG_RCR,
608 rtw_read32(padapter, REG_RCR) & (~RCR_AM));
609 DBG_8723A("%s, %d, RCR = %x \n", __FUNCTION__, __LINE__,
610 rtw_read32(padapter, REG_RCR));
611}
612
613void rtl8723a_set_slot_time(struct rtw_adapter *padapter, u8 slottime)
614{
615 u8 u1bAIFS, aSifsTime;
616 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
617 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
618
619 rtw_write8(padapter, REG_SLOT, slottime);
620
621 if (pmlmeinfo->WMM_enable == 0) {
622 if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
623 aSifsTime = 10;
624 else
625 aSifsTime = 16;
626
627 u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
628
629 /* <Roger_EXP> Temporary removed, 2008.06.20. */
630 rtw_write8(padapter, REG_EDCA_VO_PARAM, u1bAIFS);
631 rtw_write8(padapter, REG_EDCA_VI_PARAM, u1bAIFS);
632 rtw_write8(padapter, REG_EDCA_BE_PARAM, u1bAIFS);
633 rtw_write8(padapter, REG_EDCA_BK_PARAM, u1bAIFS);
634 }
635}
636
637void rtl8723a_ack_preamble(struct rtw_adapter *padapter, u8 bShortPreamble)
638{
639 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
640 u8 regTmp;
641
642 /* Joseph marked out for Netgear 3500 TKIP
643 channel 7 issue.(Temporarily) */
644 regTmp = (pHalData->nCur40MhzPrimeSC) << 5;
645 /* regTmp = 0; */
646 if (bShortPreamble)
647 regTmp |= 0x80;
648 rtw_write8(padapter, REG_RRSR + 2, regTmp);
649}
650
651void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec)
652{
653 rtw_write8(padapter, REG_SECCFG, sec);
654}
655
656void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex)
657{
658 u8 i;
659 u32 ulCommand = 0;
660 u32 ulContent = 0;
661 u32 ulEncAlgo = CAM_AES;
662
663 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
664 /* filled id in CAM config 2 byte */
665 if (i == 0) {
666 ulContent |= (ucIndex & 0x03) |
667 ((u16) (ulEncAlgo) << 2);
668 /* ulContent |= CAM_VALID; */
669 } else {
670 ulContent = 0;
671 }
672 /* polling bit, and No Write enable, and address */
673 ulCommand = CAM_CONTENT_COUNT * ucIndex + i;
674 ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE;
675 /* write content 0 is equall to mark invalid */
676 /* delay_ms(40); */
677 rtw_write32(padapter, WCAMI, ulContent);
678 /* RT_TRACE(COMP_SEC, DBG_LOUD,
679 ("CAM_empty_entry23a(): WRITE A4: %lx \n", ulContent));*/
680 /* delay_ms(40); */
681 rtw_write32(padapter, RWCAM, ulCommand);
682 /* RT_TRACE(COMP_SEC, DBG_LOUD,
683 ("CAM_empty_entry23a(): WRITE A0: %lx \n", ulCommand));*/
684 }
685}
686
687void rtl8723a_cam_invalid_all(struct rtw_adapter *padapter)
688{
689 rtw_write32(padapter, RWCAM, BIT(31) | BIT(30));
690}
691
692void rtl8723a_cam_write(struct rtw_adapter *padapter, u32 val1, u32 val2)
693{
694 u32 cmd;
695
696 rtw_write32(padapter, WCAMI, val1);
697
698 cmd = CAM_POLLINIG | CAM_WRITE | val2;
699 rtw_write32(padapter, RWCAM, cmd);
700}
701
702void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter)
703{
704#define RW_RELEASE_EN BIT(18)
705#define RXDMA_IDLE BIT(17)
706
707 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
708 u8 trycnt = 100;
709
710 /* pause tx */
711 rtw_write8(padapter, REG_TXPAUSE, 0xff);
712
713 /* keep sn */
714 padapter->xmitpriv.nqos_ssn = rtw_read16(padapter, REG_NQOS_SEQ);
715
716 if (pwrpriv->bkeepfwalive != true) {
717 u32 v32;
718
719 /* RX DMA stop */
720 v32 = rtw_read32(padapter, REG_RXPKT_NUM);
721 v32 |= RW_RELEASE_EN;
722 rtw_write32(padapter, REG_RXPKT_NUM, v32);
723 do {
724 v32 = rtw_read32(padapter, REG_RXPKT_NUM) & RXDMA_IDLE;
725 if (!v32)
726 break;
727 } while (trycnt--);
728 if (trycnt == 0) {
729 DBG_8723A("Stop RX DMA failed......\n");
730 }
731
732 /* RQPN Load 0 */
733 rtw_write16(padapter, REG_RQPN_NPQ, 0);
734 rtw_write32(padapter, REG_RQPN, 0x80000000);
735 mdelay(10);
736 }
737}
738
739void rtl8723a_set_apfm_on_mac(struct rtw_adapter *padapter, u8 val)
740{
741 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
742
743 pHalData->bMacPwrCtrlOn = val;
744 DBG_8723A("%s: bMacPwrCtrlOn =%d\n", __func__, pHalData->bMacPwrCtrlOn);
745}
746
747void rtl8723a_bcn_valid(struct rtw_adapter *padapter)
748{
749 /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2,
750 write 1 to clear, Clear by sw */
751 rtw_write8(padapter, REG_TDECTRL + 2,
752 rtw_read8(padapter, REG_TDECTRL + 2) | BIT0);
753}
754
755void rtl8723a_set_tx_pause(struct rtw_adapter *padapter, u8 pause)
756{
757 rtw_write8(padapter, REG_TXPAUSE, pause);
758}
759
760void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval)
761{
762 rtw_write16(padapter, REG_BCN_INTERVAL, interval);
763}
764
765void rtl8723a_set_resp_sifs(struct rtw_adapter *padapter,
766 u8 r2t1, u8 r2t2, u8 t2t1, u8 t2t2)
767{
768 /* SIFS_Timer = 0x0a0a0808; */
769 /* RESP_SIFS for CCK */
770 /* SIFS_T2T_CCK (0x08) */
771 rtw_write8(padapter, REG_R2T_SIFS, r2t1);
772 /* SIFS_R2T_CCK(0x08) */
773 rtw_write8(padapter, REG_R2T_SIFS + 1, r2t2);
774 /* RESP_SIFS for OFDM */
775 /* SIFS_T2T_OFDM (0x0a) */
776 rtw_write8(padapter, REG_T2T_SIFS, t2t1);
777 /* SIFS_R2T_OFDM(0x0a) */
778 rtw_write8(padapter, REG_T2T_SIFS + 1, t2t2);
779}
780
781void rtl8723a_set_ac_param_vo(struct rtw_adapter *padapter, u32 vo)
782{
783 rtw_write32(padapter, REG_EDCA_VO_PARAM, vo);
784}
785
786void rtl8723a_set_ac_param_vi(struct rtw_adapter *padapter, u32 vi)
787{
788 rtw_write32(padapter, REG_EDCA_VI_PARAM, vi);
789}
790
791void rtl8723a_set_ac_param_be(struct rtw_adapter *padapter, u32 be)
792{
793 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
794
795 pHalData->AcParam_BE = be;
796 rtw_write32(padapter, REG_EDCA_BE_PARAM, be);
797}
798
799void rtl8723a_set_ac_param_bk(struct rtw_adapter *padapter, u32 bk)
800{
801 rtw_write32(padapter, REG_EDCA_BK_PARAM, bk);
802}
803
804void rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter *padapter, u8 val)
805{
806 rtw_write8(padapter, REG_RXDMA_AGG_PG_TH, val);
807}
808
809void rtl8723a_set_nav_upper(struct rtw_adapter *padapter, u32 usNavUpper)
810{
811 if (usNavUpper > HAL_8723A_NAV_UPPER_UNIT * 0xFF) {
812 RT_TRACE(_module_hal_init_c_, _drv_notice_,
813 ("The setting value (0x%08X us) of NAV_UPPER "
814 "is larger than (%d * 0xFF)!!!\n",
815 usNavUpper, HAL_8723A_NAV_UPPER_UNIT));
816 return;
817 }
818
819 /* The value of ((usNavUpper + HAL_8723A_NAV_UPPER_UNIT - 1) /
820 HAL_8723A_NAV_UPPER_UNIT) */
821 /* is getting the upper integer. */
822 usNavUpper = (usNavUpper + HAL_8723A_NAV_UPPER_UNIT - 1) /
823 HAL_8723A_NAV_UPPER_UNIT;
824 rtw_write8(padapter, REG_NAV_UPPER, (u8) usNavUpper);
825}
826
827void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain)
828{
829 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
830 struct dig_t *pDigTable = &pHalData->odmpriv.DM_DigTable;
831
832 if (rx_gain == 0xff) /* restore rx gain */
833 ODM_Write_DIG23a(&pHalData->odmpriv, pDigTable->BackupIGValue);
834 else {
835 pDigTable->BackupIGValue = pDigTable->CurIGValue;
836 ODM_Write_DIG23a(&pHalData->odmpriv, rx_gain);
837 }
838}
839
840void rtl8723a_odm_support_ability_write(struct rtw_adapter *padapter, u32 val)
841{
842 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
843
844 pHalData->odmpriv.SupportAbility = val;
845}
846
847void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter, u8 val)
848{
849 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
850
851 if (val) /* save dm flag */
852 pHalData->odmpriv.BK_SupportAbility =
853 pHalData->odmpriv.SupportAbility;
854 else /* restore dm flag */
855 pHalData->odmpriv.SupportAbility =
856 pHalData->odmpriv.BK_SupportAbility;
857}
858
859void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val)
860{
861 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
862
863 if (val == DYNAMIC_ALL_FUNC_ENABLE) {
864 pHalData->dmpriv.DMFlag = pHalData->dmpriv.InitDMFlag;
865 pHalData->odmpriv.SupportAbility = pHalData->dmpriv.InitODMFlag;
866 } else {
867 pHalData->odmpriv.SupportAbility |= val;
868 }
869}
870
871void rtl8723a_odm_support_ability_clr(struct rtw_adapter *padapter, u32 val)
872{
873 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
874
875 pHalData->odmpriv.SupportAbility &= val;
876}
877
878void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val)
879{
880 rtw_write8(padapter, REG_USB_HRPWM, val);
881}
diff --git a/drivers/staging/rtl8723au/hal/hal_intf.c b/drivers/staging/rtl8723au/hal/hal_intf.c
new file mode 100644
index 000000000000..de3608b4010a
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/hal_intf.c
@@ -0,0 +1,420 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15
16#define _HAL_INTF_C_
17#include <osdep_service.h>
18#include <drv_types.h>
19
20#include <hal_intf.h>
21
22#include <usb_hal.h>
23
24void rtw_hal_chip_configure23a(struct rtw_adapter *padapter)
25{
26 if (padapter->HalFunc.intf_chip_configure)
27 padapter->HalFunc.intf_chip_configure(padapter);
28}
29
30void rtw_hal_read_chip_info23a(struct rtw_adapter *padapter)
31{
32 if (padapter->HalFunc.read_adapter_info)
33 padapter->HalFunc.read_adapter_info(padapter);
34}
35
36void rtw_hal_read_chip_version23a(struct rtw_adapter *padapter)
37{
38 if (padapter->HalFunc.read_chip_version)
39 padapter->HalFunc.read_chip_version(padapter);
40}
41
42void rtw_hal_def_value_init23a(struct rtw_adapter *padapter)
43{
44 if (padapter->HalFunc.init_default_value)
45 padapter->HalFunc.init_default_value(padapter);
46}
47void rtw_hal_free_data23a(struct rtw_adapter *padapter)
48{
49 if (padapter->HalFunc.free_hal_data)
50 padapter->HalFunc.free_hal_data(padapter);
51}
52void rtw_hal_dm_init23a(struct rtw_adapter *padapter)
53{
54 if (padapter->HalFunc.dm_init)
55 padapter->HalFunc.dm_init(padapter);
56}
57void rtw_hal_dm_deinit23a(struct rtw_adapter *padapter)
58{
59 /* cancel dm timer */
60 if (padapter->HalFunc.dm_deinit)
61 padapter->HalFunc.dm_deinit(padapter);
62}
63void rtw_hal_sw_led_init23a(struct rtw_adapter *padapter)
64{
65 if (padapter->HalFunc.InitSwLeds)
66 padapter->HalFunc.InitSwLeds(padapter);
67}
68
69void rtw_hal_sw_led_deinit23a(struct rtw_adapter *padapter)
70{
71 if (padapter->HalFunc.DeInitSwLeds)
72 padapter->HalFunc.DeInitSwLeds(padapter);
73}
74
75u32 rtw_hal_power_on23a(struct rtw_adapter *padapter)
76{
77 if (padapter->HalFunc.hal_power_on)
78 return padapter->HalFunc.hal_power_on(padapter);
79 return _FAIL;
80}
81
82uint rtw_hal_init23a(struct rtw_adapter *padapter)
83{
84 uint status = _SUCCESS;
85
86 padapter->hw_init_completed = false;
87
88 status = padapter->HalFunc.hal_init(padapter);
89
90 if (status == _SUCCESS) {
91 padapter->hw_init_completed = true;
92
93 if (padapter->registrypriv.notch_filter == 1)
94 rtw_hal_notch_filter23a(padapter, 1);
95
96 rtw_hal_reset_security_engine23a(padapter);
97 } else {
98 padapter->hw_init_completed = false;
99 DBG_8723A("rtw_hal_init23a: hal__init fail\n");
100 }
101
102 RT_TRACE(_module_hal_init_c_, _drv_err_, ("-rtl871x_hal_init:status = 0x%x\n", status));
103
104 return status;
105}
106
107uint rtw_hal_deinit23a(struct rtw_adapter *padapter)
108{
109 uint status = _SUCCESS;
110
111 status = padapter->HalFunc.hal_deinit(padapter);
112
113 if (status == _SUCCESS)
114 padapter->hw_init_completed = false;
115 else
116 DBG_8723A("\n rtw_hal_deinit23a: hal_init fail\n");
117 return status;
118}
119
120void rtw_hal_set_hwreg23a(struct rtw_adapter *padapter, u8 variable, u8 *val)
121{
122 if (padapter->HalFunc.SetHwRegHandler)
123 padapter->HalFunc.SetHwRegHandler(padapter, variable, val);
124}
125
126void rtw23a_hal_get_hwreg(struct rtw_adapter *padapter, u8 variable, u8 *val)
127{
128 if (padapter->HalFunc.GetHwRegHandler)
129 padapter->HalFunc.GetHwRegHandler(padapter, variable, val);
130}
131
132u8 rtw_hal_set_def_var23a(struct rtw_adapter *padapter, enum hal_def_variable eVariable, void *pValue)
133{
134 if (padapter->HalFunc.SetHalDefVarHandler)
135 return padapter->HalFunc.SetHalDefVarHandler(padapter, eVariable, pValue);
136 return _FAIL;
137}
138u8 rtw_hal_get_def_var23a(struct rtw_adapter *padapter, enum hal_def_variable eVariable, void *pValue)
139{
140 if (padapter->HalFunc.GetHalDefVarHandler)
141 return padapter->HalFunc.GetHalDefVarHandler(padapter, eVariable, pValue);
142 return _FAIL;
143}
144
145void rtw_hal_set_odm_var23a(struct rtw_adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
146{
147 if (padapter->HalFunc.SetHalODMVarHandler)
148 padapter->HalFunc.SetHalODMVarHandler(padapter, eVariable, pValue1, bSet);
149}
150void rtw_hal_get_odm_var23a(struct rtw_adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
151{
152 if (padapter->HalFunc.GetHalODMVarHandler)
153 padapter->HalFunc.GetHalODMVarHandler(padapter, eVariable, pValue1, bSet);
154}
155
156void rtw_hal_enable_interrupt23a(struct rtw_adapter *padapter)
157{
158 if (padapter->HalFunc.enable_interrupt)
159 padapter->HalFunc.enable_interrupt(padapter);
160 else
161 DBG_8723A("%s: HalFunc.enable_interrupt is NULL!\n", __FUNCTION__);
162
163}
164void rtw_hal_disable_interrupt23a(struct rtw_adapter *padapter)
165{
166 if (padapter->HalFunc.disable_interrupt)
167 padapter->HalFunc.disable_interrupt(padapter);
168 else
169 DBG_8723A("%s: HalFunc.disable_interrupt is NULL!\n", __FUNCTION__);
170
171}
172
173u32 rtw_hal_inirp_init23a(struct rtw_adapter *padapter)
174{
175 u32 rst = _FAIL;
176 if (padapter->HalFunc.inirp_init)
177 rst = padapter->HalFunc.inirp_init(padapter);
178 else
179 DBG_8723A(" %s HalFunc.inirp_init is NULL!!!\n", __FUNCTION__);
180 return rst;
181}
182
183u32 rtw_hal_inirp_deinit23a(struct rtw_adapter *padapter)
184{
185
186 if (padapter->HalFunc.inirp_deinit)
187 return padapter->HalFunc.inirp_deinit(padapter);
188
189 return _FAIL;
190
191}
192
193u8 rtw_hal_intf_ps_func23a(struct rtw_adapter *padapter, enum hal_intf_ps_func efunc_id, u8 *val)
194{
195 if (padapter->HalFunc.interface_ps_func)
196 return padapter->HalFunc.interface_ps_func(padapter, efunc_id, val);
197 return _FAIL;
198}
199
200s32 rtw_hal_xmit23aframe_enqueue(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
201{
202 if (padapter->HalFunc.hal_xmitframe_enqueue)
203 return padapter->HalFunc.hal_xmitframe_enqueue(padapter, pxmitframe);
204
205 return false;
206}
207
208s32 rtw_hal_xmit23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
209{
210 if (padapter->HalFunc.hal_xmit)
211 return padapter->HalFunc.hal_xmit(padapter, pxmitframe);
212
213 return false;
214}
215
216s32 rtw_hal_mgnt_xmit23a(struct rtw_adapter *padapter, struct xmit_frame *pmgntframe)
217{
218 s32 ret = _FAIL;
219 if (padapter->HalFunc.mgnt_xmit)
220 ret = padapter->HalFunc.mgnt_xmit(padapter, pmgntframe);
221 return ret;
222}
223
224s32 rtw_hal_init23a_xmit_priv(struct rtw_adapter *padapter)
225{
226 if (padapter->HalFunc.init_xmit_priv != NULL)
227 return padapter->HalFunc.init_xmit_priv(padapter);
228 return _FAIL;
229}
230void rtw_hal_free_xmit_priv23a(struct rtw_adapter *padapter)
231{
232 if (padapter->HalFunc.free_xmit_priv != NULL)
233 padapter->HalFunc.free_xmit_priv(padapter);
234}
235
236s32 rtw_hal_init23a_recv_priv(struct rtw_adapter *padapter)
237{
238 if (padapter->HalFunc.init_recv_priv)
239 return padapter->HalFunc.init_recv_priv(padapter);
240
241 return _FAIL;
242}
243void rtw_hal_free_recv_priv23a(struct rtw_adapter *padapter)
244{
245 if (padapter->HalFunc.free_recv_priv)
246 padapter->HalFunc.free_recv_priv(padapter);
247}
248
249void rtw_hal_update_ra_mask23a(struct sta_info *psta, u8 rssi_level)
250{
251 struct rtw_adapter *padapter;
252 struct mlme_priv *pmlmepriv;
253
254 if (!psta)
255 return;
256
257 padapter = psta->padapter;
258
259 pmlmepriv = &padapter->mlmepriv;
260
261 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
262#ifdef CONFIG_8723AU_AP_MODE
263 add_RATid23a(padapter, psta, rssi_level);
264#endif
265 } else {
266 if (padapter->HalFunc.UpdateRAMaskHandler)
267 padapter->HalFunc.UpdateRAMaskHandler(padapter, psta->mac_id, rssi_level);
268 }
269}
270
271void rtw_hal_add_ra_tid23a(struct rtw_adapter *padapter, u32 bitmap, u8 arg, u8 rssi_level)
272{
273 if (padapter->HalFunc.Add_RateATid)
274 padapter->HalFunc.Add_RateATid(padapter, bitmap, arg, rssi_level);
275}
276
277/* Start specifical interface thread */
278void rtw_hal_start_thread23a(struct rtw_adapter *padapter)
279{
280 if (padapter->HalFunc.run_thread)
281 padapter->HalFunc.run_thread(padapter);
282}
283/* Start specifical interface thread */
284void rtw_hal_stop_thread23a(struct rtw_adapter *padapter)
285{
286 if (padapter->HalFunc.cancel_thread)
287 padapter->HalFunc.cancel_thread(padapter);
288}
289
290u32 rtw_hal_read_bbreg23a(struct rtw_adapter *padapter, u32 RegAddr, u32 BitMask)
291{
292 u32 data = 0;
293 if (padapter->HalFunc.read_bbreg)
294 data = padapter->HalFunc.read_bbreg(padapter, RegAddr, BitMask);
295 return data;
296}
297void rtw_hal_write_bbreg23a(struct rtw_adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data)
298{
299 if (padapter->HalFunc.write_bbreg)
300 padapter->HalFunc.write_bbreg(padapter, RegAddr, BitMask, Data);
301}
302
303u32 rtw_hal_read_rfreg23a(struct rtw_adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask)
304{
305 u32 data = 0;
306 if (padapter->HalFunc.read_rfreg)
307 data = padapter->HalFunc.read_rfreg(padapter, eRFPath, RegAddr, BitMask);
308 return data;
309}
310void rtw_hal_write_rfreg23a(struct rtw_adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask, u32 Data)
311{
312 if (padapter->HalFunc.write_rfreg)
313 padapter->HalFunc.write_rfreg(padapter, eRFPath, RegAddr, BitMask, Data);
314}
315
316s32 rtw_hal_interrupt_handler23a(struct rtw_adapter *padapter)
317{
318 if (padapter->HalFunc.interrupt_handler)
319 return padapter->HalFunc.interrupt_handler(padapter);
320 return _FAIL;
321}
322
323void rtw_hal_set_bwmode23a(struct rtw_adapter *padapter,
324 enum ht_channel_width Bandwidth, u8 offset)
325{
326 if (padapter->HalFunc.set_bwmode_handler)
327 padapter->HalFunc.set_bwmode_handler(padapter, Bandwidth,
328 offset);
329}
330
331void rtw_hal_set_chan23a(struct rtw_adapter *padapter, u8 channel)
332{
333 if (padapter->HalFunc.set_channel_handler)
334 padapter->HalFunc.set_channel_handler(padapter, channel);
335}
336
337void rtw_hal_dm_watchdog23a(struct rtw_adapter *padapter)
338{
339 if (padapter->HalFunc.hal_dm_watchdog)
340 padapter->HalFunc.hal_dm_watchdog(padapter);
341}
342
343void rtw_hal_bcn_related_reg_setting23a(struct rtw_adapter *padapter)
344{
345 if (padapter->HalFunc.SetBeaconRelatedRegistersHandler)
346 padapter->HalFunc.SetBeaconRelatedRegistersHandler(padapter);
347}
348
349void rtw_hal_sreset_init23a(struct rtw_adapter *padapter)
350{
351 if (padapter->HalFunc.sreset_init_value23a)
352 padapter->HalFunc.sreset_init_value23a(padapter);
353}
354void rtw_hal_sreset_reset23a(struct rtw_adapter *padapter)
355{
356 padapter = GET_PRIMARY_ADAPTER(padapter);
357
358 if (padapter->HalFunc.silentreset)
359 padapter->HalFunc.silentreset(padapter);
360}
361
362void rtw_hal_sreset_reset23a_value23a(struct rtw_adapter *padapter)
363{
364 if (padapter->HalFunc.sreset_reset_value23a)
365 padapter->HalFunc.sreset_reset_value23a(padapter);
366}
367
368void rtw_hal_sreset_xmit_status_check23a(struct rtw_adapter *padapter)
369{
370 if (padapter->HalFunc.sreset_xmit_status_check)
371 padapter->HalFunc.sreset_xmit_status_check(padapter);
372}
373void rtw_hal_sreset_linked_status_check23a(struct rtw_adapter *padapter)
374{
375 if (padapter->HalFunc.sreset_linked_status_check)
376 padapter->HalFunc.sreset_linked_status_check(padapter);
377}
378u8 rtw_hal_sreset_get_wifi_status23a(struct rtw_adapter *padapter)
379{
380 u8 status = 0;
381 if (padapter->HalFunc.sreset_get_wifi_status23a)
382 status = padapter->HalFunc.sreset_get_wifi_status23a(padapter);
383 return status;
384}
385
386bool rtw_hal_sreset_inprogress(struct rtw_adapter *padapter)
387{
388 bool inprogress = false;
389
390 padapter = GET_PRIMARY_ADAPTER(padapter);
391
392 if (padapter->HalFunc.sreset_inprogress)
393 inprogress = padapter->HalFunc.sreset_inprogress(padapter);
394 return inprogress;
395}
396
397void rtw_hal_notch_filter23a(struct rtw_adapter *adapter, bool enable)
398{
399 if (adapter->HalFunc.hal_notch_filter)
400 adapter->HalFunc.hal_notch_filter(adapter, enable);
401}
402
403void rtw_hal_reset_security_engine23a(struct rtw_adapter *adapter)
404{
405 if (adapter->HalFunc.hal_reset_security_engine)
406 adapter->HalFunc.hal_reset_security_engine(adapter);
407}
408
409s32 rtw_hal_c2h_handler23a(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt)
410{
411 s32 ret = _FAIL;
412 if (adapter->HalFunc.c2h_handler)
413 ret = adapter->HalFunc.c2h_handler(adapter, c2h_evt);
414 return ret;
415}
416
417c2h_id_filter rtw_hal_c2h_id_filter_ccx23a(struct rtw_adapter *adapter)
418{
419 return adapter->HalFunc.c2h_id_filter_ccx;
420}
diff --git a/drivers/staging/rtl8723au/hal/odm.c b/drivers/staging/rtl8723au/hal/odm.c
new file mode 100644
index 000000000000..584a74ed2943
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/odm.c
@@ -0,0 +1,2090 @@
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 ******************************************************************************/
15
16#include "odm_precomp.h"
17
18static const u16 dB_Invert_Table[8][12] = {
19 {1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4},
20 {4, 5, 6, 6, 7, 8, 9, 10, 11, 13, 14, 16},
21 {18, 20, 22, 25, 28, 32, 35, 40, 45, 50, 56, 63},
22 {71, 79, 89, 100, 112, 126, 141, 158, 178, 200, 224, 251},
23 {282, 316, 355, 398, 447, 501, 562, 631, 708, 794, 891, 1000},
24 {1122, 1259, 1413, 1585, 1778, 1995, 2239, 2512, 2818, 3162, 3548, 3981},
25 {4467, 5012, 5623, 6310, 7079, 7943, 8913, 10000, 11220, 12589, 14125, 15849},
26 {17783, 19953, 22387, 25119, 28184, 31623, 35481, 39811, 44668, 50119, 56234, 65535}
27};
28
29static u32 EDCAParam[HT_IOT_PEER_MAX][3] = { /* UL DL */
30 {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 0:unknown AP */
31 {0xa44f, 0x5ea44f, 0x5e431c}, /* 1:realtek AP */
32 {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 2:unknown AP => realtek_92SE */
33 {0x5ea32b, 0x5ea42b, 0x5e4322}, /* 3:broadcom AP */
34 {0x5ea422, 0x00a44f, 0x00a44f}, /* 4:ralink AP */
35 {0x5ea322, 0x00a630, 0x00a44f}, /* 5:atheros AP */
36 {0x5e4322, 0x5e4322, 0x5e4322},/* 6:cisco AP */
37 {0x5ea44f, 0x00a44f, 0x5ea42b}, /* 8:marvell AP */
38 {0x5ea42b, 0x5ea42b, 0x5ea42b}, /* 10:unknown AP => 92U AP */
39 {0x5ea42b, 0xa630, 0x5e431c}, /* 11:airgocap AP */
40};
41
42/* EDCA Paramter for AP/ADSL by Mingzhi 2011-11-22 */
43
44/* Global var */
45u32 OFDMSwingTable23A[OFDM_TABLE_SIZE_92D] = {
46 0x7f8001fe, /* 0, +6.0dB */
47 0x788001e2, /* 1, +5.5dB */
48 0x71c001c7, /* 2, +5.0dB */
49 0x6b8001ae, /* 3, +4.5dB */
50 0x65400195, /* 4, +4.0dB */
51 0x5fc0017f, /* 5, +3.5dB */
52 0x5a400169, /* 6, +3.0dB */
53 0x55400155, /* 7, +2.5dB */
54 0x50800142, /* 8, +2.0dB */
55 0x4c000130, /* 9, +1.5dB */
56 0x47c0011f, /* 10, +1.0dB */
57 0x43c0010f, /* 11, +0.5dB */
58 0x40000100, /* 12, +0dB */
59 0x3c8000f2, /* 13, -0.5dB */
60 0x390000e4, /* 14, -1.0dB */
61 0x35c000d7, /* 15, -1.5dB */
62 0x32c000cb, /* 16, -2.0dB */
63 0x300000c0, /* 17, -2.5dB */
64 0x2d4000b5, /* 18, -3.0dB */
65 0x2ac000ab, /* 19, -3.5dB */
66 0x288000a2, /* 20, -4.0dB */
67 0x26000098, /* 21, -4.5dB */
68 0x24000090, /* 22, -5.0dB */
69 0x22000088, /* 23, -5.5dB */
70 0x20000080, /* 24, -6.0dB */
71 0x1e400079, /* 25, -6.5dB */
72 0x1c800072, /* 26, -7.0dB */
73 0x1b00006c, /* 27. -7.5dB */
74 0x19800066, /* 28, -8.0dB */
75 0x18000060, /* 29, -8.5dB */
76 0x16c0005b, /* 30, -9.0dB */
77 0x15800056, /* 31, -9.5dB */
78 0x14400051, /* 32, -10.0dB */
79 0x1300004c, /* 33, -10.5dB */
80 0x12000048, /* 34, -11.0dB */
81 0x11000044, /* 35, -11.5dB */
82 0x10000040, /* 36, -12.0dB */
83 0x0f00003c,/* 37, -12.5dB */
84 0x0e400039,/* 38, -13.0dB */
85 0x0d800036,/* 39, -13.5dB */
86 0x0cc00033,/* 40, -14.0dB */
87 0x0c000030,/* 41, -14.5dB */
88 0x0b40002d,/* 42, -15.0dB */
89};
90
91u8 CCKSwingTable_Ch1_Ch1323A[CCK_TABLE_SIZE][8] = {
92 {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */
93 {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */
94 {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */
95 {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */
96 {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */
97 {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */
98 {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */
99 {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */
100 {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */
101 {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */
102 {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */
103 {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */
104 {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */
105 {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */
106 {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */
107 {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */
108 {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
109 {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */
110 {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */
111 {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */
112 {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */
113 {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */
114 {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */
115 {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */
116 {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */
117 {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */
118 {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */
119 {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */
120 {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */
121 {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */
122 {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */
123 {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */
124 {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */
125};
126
127u8 CCKSwingTable_Ch1423A[CCK_TABLE_SIZE][8] = {
128 {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */
129 {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */
130 {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */
131 {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */
132 {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */
133 {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */
134 {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */
135 {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */
136 {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */
137 {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */
138 {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */
139 {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */
140 {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */
141 {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */
142 {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */
143 {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */
144 {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
145 {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */
146 {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */
147 {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */
148 {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */
149 {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */
150 {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */
151 {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */
152 {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */
153 {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */
154 {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */
155 {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */
156 {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */
157 {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */
158 {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */
159 {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */
160 {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB */
161};
162
163/* Local Function predefine. */
164
165/* START------------COMMON INFO RELATED--------------- */
166void odm_CommonInfoSelfInit23a(struct dm_odm_t *pDM_Odm);
167
168void odm_CommonInfoSelfUpdate23a(struct dm_odm_t *pDM_Odm);
169
170void odm_CmnInfoInit_Debug23a(struct dm_odm_t *pDM_Odm);
171
172void odm_CmnInfoHook_Debug23a(struct dm_odm_t *pDM_Odm);
173
174void odm_CmnInfoUpdate_Debug23a(struct dm_odm_t *pDM_Odm);
175
176/* START---------------DIG--------------------------- */
177void odm_FalseAlarmCounterStatistics23a(struct dm_odm_t *pDM_Odm);
178
179void odm_DIG23aInit(struct dm_odm_t *pDM_Odm);
180
181void odm_DIG23a(struct dm_odm_t *pDM_Odm);
182
183void odm_CCKPacketDetectionThresh23a(struct dm_odm_t *pDM_Odm);
184/* END---------------DIG--------------------------- */
185
186/* START-------BB POWER SAVE----------------------- */
187void odm23a_DynBBPSInit(struct dm_odm_t *pDM_Odm);
188
189void odm_DynamicBBPowerSaving23a(struct dm_odm_t *pDM_Odm);
190
191void odm_1R_CCA23a(struct dm_odm_t *pDM_Odm);
192/* END---------BB POWER SAVE----------------------- */
193
194void odm_RefreshRateAdaptiveMask23aMP23a(struct dm_odm_t *pDM_Odm);
195
196void odm_RefreshRateAdaptiveMask23aCE23a(struct dm_odm_t *pDM_Odm);
197
198void odm_RefreshRateAdaptiveMask23aAPADSL23a(struct dm_odm_t *pDM_Odm);
199
200void odm_DynamicTxPower23aInit(struct dm_odm_t *pDM_Odm);
201
202void odm_DynamicTxPower23aRestorePowerIndex(struct dm_odm_t *pDM_Odm);
203
204void odm_DynamicTxPower23aSavePowerIndex(struct dm_odm_t *pDM_Odm);
205
206void odm_DynamicTxPower23aWritePowerIndex(struct dm_odm_t *pDM_Odm,
207 u8 Value);
208
209void odm_DynamicTxPower23a_92C(struct dm_odm_t *pDM_Odm);
210
211void odm_DynamicTxPower23a_92D(struct dm_odm_t *pDM_Odm);
212
213void odm_RSSIMonitorInit(struct dm_odm_t *pDM_Odm);
214
215void odm_RSSIMonitorCheck23aMP(struct dm_odm_t *pDM_Odm);
216
217void odm_RSSIMonitorCheck23aCE(struct dm_odm_t *pDM_Odm);
218void odm_RSSIMonitorCheck23aAP(struct dm_odm_t *pDM_Odm);
219
220void odm_RSSIMonitorCheck23a(struct dm_odm_t *pDM_Odm);
221void odm_DynamicTxPower23a(struct dm_odm_t *pDM_Odm);
222
223void odm_SwAntDivInit(struct dm_odm_t *pDM_Odm);
224
225void odm_SwAntDivInit_NIC(struct dm_odm_t *pDM_Odm);
226
227void odm_SwAntDivChkAntSwitch(struct dm_odm_t *pDM_Odm, u8 Step);
228
229void odm_SwAntDivChkAntSwitchNIC(struct dm_odm_t *pDM_Odm,
230 u8 Step
231 );
232
233void odm_SwAntDivChkAntSwitchCallback23a(unsigned long data);
234
235void odm_GlobalAdapterCheck(void);
236
237void odm_RefreshRateAdaptiveMask23a(struct dm_odm_t *pDM_Odm);
238
239void ODM_TXPowerTrackingCheck23a(struct dm_odm_t *pDM_Odm);
240
241void odm_TXPowerTrackingCheckAP(struct dm_odm_t *pDM_Odm);
242
243void odm_RateAdaptiveMaskInit23a(struct dm_odm_t *pDM_Odm);
244
245void odm_TXPowerTrackingThermalMeterInit23a(struct dm_odm_t *pDM_Odm);
246
247void odm_TXPowerTrackingInit23a(struct dm_odm_t *pDM_Odm);
248
249void odm_TXPowerTrackingCheckMP(struct dm_odm_t *pDM_Odm);
250
251void odm_TXPowerTrackingCheckCE23a(struct dm_odm_t *pDM_Odm);
252
253void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm);
254void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm);
255
256void odm_EdcaTurboCheck23aCE23a(struct dm_odm_t *pDM_Odm);
257
258#define RxDefaultAnt1 0x65a9
259#define RxDefaultAnt2 0x569a
260
261void odm_InitHybridAntDiv23a(struct dm_odm_t *pDM_Odm);
262
263bool odm_StaDefAntSel(struct dm_odm_t *pDM_Odm,
264 u32 OFDM_Ant1_Cnt,
265 u32 OFDM_Ant2_Cnt,
266 u32 CCK_Ant1_Cnt,
267 u32 CCK_Ant2_Cnt,
268 u8 *pDefAnt
269 );
270
271void odm_SetRxIdleAnt(struct dm_odm_t *pDM_Odm,
272 u8 Ant,
273 bool bDualPath
274);
275
276void odm_HwAntDiv23a(struct dm_odm_t *pDM_Odm);
277
278/* 3 Export Interface */
279
280/* 2011/09/21 MH Add to describe different team necessary resource allocate?? */
281void ODM23a_DMInit(struct dm_odm_t *pDM_Odm)
282{
283 /* For all IC series */
284 odm_CommonInfoSelfInit23a(pDM_Odm);
285 odm_CmnInfoInit_Debug23a(pDM_Odm);
286 odm_DIG23aInit(pDM_Odm);
287 odm_RateAdaptiveMaskInit23a(pDM_Odm);
288
289 if (pDM_Odm->SupportICType & ODM_IC_11N_SERIES) {
290 odm23a_DynBBPSInit(pDM_Odm);
291 odm_DynamicTxPower23aInit(pDM_Odm);
292 odm_TXPowerTrackingInit23a(pDM_Odm);
293 ODM_EdcaTurboInit23a(pDM_Odm);
294 if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) ||
295 (pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV) ||
296 (pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV))
297 odm_InitHybridAntDiv23a(pDM_Odm);
298 else if (pDM_Odm->AntDivType == CGCS_RX_SW_ANTDIV)
299 odm_SwAntDivInit(pDM_Odm);
300 }
301}
302
303/* 2011/09/20 MH This is the entry pointer for all team to execute HW out source DM. */
304/* You can not add any dummy function here, be care, you can only use DM structure */
305/* to perform any new ODM_DM. */
306void ODM_DMWatchdog23a(struct dm_odm_t *pDM_Odm)
307{
308 /* 2012.05.03 Luke: For all IC series */
309 odm_GlobalAdapterCheck();
310 odm_CmnInfoHook_Debug23a(pDM_Odm);
311 odm_CmnInfoUpdate_Debug23a(pDM_Odm);
312 odm_CommonInfoSelfUpdate23a(pDM_Odm);
313 odm_FalseAlarmCounterStatistics23a(pDM_Odm);
314 odm_RSSIMonitorCheck23a(pDM_Odm);
315
316 /* 8723A or 8189ES platform */
317 /* NeilChen--2012--08--24-- */
318 /* Fix Leave LPS issue */
319 if ((pDM_Odm->Adapter->pwrctrlpriv.pwr_mode != PS_MODE_ACTIVE) &&/* in LPS mode */
320 (pDM_Odm->SupportICType & (ODM_RTL8723A))) {
321 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("----Step1: odm_DIG23a is in LPS mode\n"));
322 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("---Step2: 8723AS is in LPS mode\n"));
323 odm_DIG23abyRSSI_LPS(pDM_Odm);
324 } else {
325 odm_DIG23a(pDM_Odm);
326 }
327
328 odm_CCKPacketDetectionThresh23a(pDM_Odm);
329
330 if (*(pDM_Odm->pbPowerSaving))
331 return;
332
333 odm_RefreshRateAdaptiveMask23a(pDM_Odm);
334
335 odm_DynamicBBPowerSaving23a(pDM_Odm);
336 if ((pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV) ||
337 (pDM_Odm->AntDivType == CGCS_RX_HW_ANTDIV) ||
338 (pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV))
339 odm_HwAntDiv23a(pDM_Odm);
340 else if (pDM_Odm->AntDivType == CGCS_RX_SW_ANTDIV)
341 odm_SwAntDivChkAntSwitch(pDM_Odm, SWAW_STEP_PEAK);
342
343 if (pDM_Odm->SupportICType & ODM_IC_11N_SERIES) {
344 ODM_TXPowerTrackingCheck23a(pDM_Odm);
345 odm_EdcaTurboCheck23a(pDM_Odm);
346 odm_DynamicTxPower23a(pDM_Odm);
347 }
348
349 odm_dtc(pDM_Odm);
350}
351
352/* */
353/* Init /.. Fixed HW value. Only init time. */
354/* */
355void ODM_CmnInfoInit23a(struct dm_odm_t *pDM_Odm,
356 enum odm_cmninfo CmnInfo,
357 u32 Value
358 )
359{
360 /* ODM_RT_TRACE(pDM_Odm,); */
361
362 /* */
363 /* This section is used for init value */
364 /* */
365 switch (CmnInfo) {
366 /* Fixed ODM value. */
367 case ODM_CMNINFO_ABILITY:
368 pDM_Odm->SupportAbility = (u32)Value;
369 break;
370 case ODM_CMNINFO_PLATFORM:
371 break;
372 case ODM_CMNINFO_INTERFACE:
373 pDM_Odm->SupportInterface = (u8)Value;
374 break;
375 case ODM_CMNINFO_MP_TEST_CHIP:
376 pDM_Odm->bIsMPChip = (u8)Value;
377 break;
378 case ODM_CMNINFO_IC_TYPE:
379 pDM_Odm->SupportICType = Value;
380 break;
381 case ODM_CMNINFO_CUT_VER:
382 pDM_Odm->CutVersion = (u8)Value;
383 break;
384 case ODM_CMNINFO_FAB_VER:
385 pDM_Odm->FabVersion = (u8)Value;
386 break;
387 case ODM_CMNINFO_RF_TYPE:
388 pDM_Odm->RFType = (u8)Value;
389 break;
390 case ODM_CMNINFO_RF_ANTENNA_TYPE:
391 pDM_Odm->AntDivType = (u8)Value;
392 break;
393 case ODM_CMNINFO_BOARD_TYPE:
394 pDM_Odm->BoardType = (u8)Value;
395 break;
396 case ODM_CMNINFO_EXT_LNA:
397 pDM_Odm->ExtLNA = (u8)Value;
398 break;
399 case ODM_CMNINFO_EXT_PA:
400 pDM_Odm->ExtPA = (u8)Value;
401 break;
402 case ODM_CMNINFO_EXT_TRSW:
403 pDM_Odm->ExtTRSW = (u8)Value;
404 break;
405 case ODM_CMNINFO_PATCH_ID:
406 pDM_Odm->PatchID = (u8)Value;
407 break;
408 case ODM_CMNINFO_BINHCT_TEST:
409 pDM_Odm->bInHctTest = (bool)Value;
410 break;
411 case ODM_CMNINFO_BWIFI_TEST:
412 pDM_Odm->bWIFITest = (bool)Value;
413 break;
414 case ODM_CMNINFO_SMART_CONCURRENT:
415 pDM_Odm->bDualMacSmartConcurrent = (bool)Value;
416 break;
417 /* To remove the compiler warning, must add an empty default statement to handle the other values. */
418 default:
419 /* do nothing */
420 break;
421 }
422
423 /* */
424 /* Tx power tracking BB swing table. */
425 /* The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */
426 /* */
427 pDM_Odm->BbSwingIdxOfdm = 12; /* Set defalut value as index 12. */
428 pDM_Odm->BbSwingIdxOfdmCurrent = 12;
429 pDM_Odm->BbSwingFlagOfdm = false;
430
431}
432
433void ODM23a_CmnInfoHook(struct dm_odm_t *pDM_Odm,
434 enum odm_cmninfo CmnInfo,
435 void *pValue
436 )
437{
438 /* Hook call by reference pointer. */
439 switch (CmnInfo) {
440 /* Dynamic call by reference pointer. */
441 case ODM_CMNINFO_MAC_PHY_MODE:
442 pDM_Odm->pMacPhyMode = (u8 *)pValue;
443 break;
444 case ODM_CMNINFO_TX_UNI:
445 pDM_Odm->pNumTxBytesUnicast = (u64 *)pValue;
446 break;
447 case ODM_CMNINFO_RX_UNI:
448 pDM_Odm->pNumRxBytesUnicast = (u64 *)pValue;
449 break;
450 case ODM_CMNINFO_WM_MODE:
451 pDM_Odm->pWirelessMode = (u8 *)pValue;
452 break;
453 case ODM_CMNINFO_BAND:
454 pDM_Odm->pBandType = (u8 *)pValue;
455 break;
456 case ODM_CMNINFO_SEC_CHNL_OFFSET:
457 pDM_Odm->pSecChOffset = (u8 *)pValue;
458 break;
459 case ODM_CMNINFO_SEC_MODE:
460 pDM_Odm->pSecurity = (u8 *)pValue;
461 break;
462 case ODM_CMNINFO_BW:
463 pDM_Odm->pBandWidth = (u8 *)pValue;
464 break;
465 case ODM_CMNINFO_CHNL:
466 pDM_Odm->pChannel = (u8 *)pValue;
467 break;
468 case ODM_CMNINFO_DMSP_GET_VALUE:
469 pDM_Odm->pbGetValueFromOtherMac = (bool *)pValue;
470 break;
471 case ODM_CMNINFO_BUDDY_ADAPTOR:
472 pDM_Odm->pBuddyAdapter = (struct rtw_adapter **)pValue;
473 break;
474 case ODM_CMNINFO_DMSP_IS_MASTER:
475 pDM_Odm->pbMasterOfDMSP = (bool *)pValue;
476 break;
477 case ODM_CMNINFO_SCAN:
478 pDM_Odm->pbScanInProcess = (bool *)pValue;
479 break;
480 case ODM_CMNINFO_POWER_SAVING:
481 pDM_Odm->pbPowerSaving = (bool *)pValue;
482 break;
483 case ODM_CMNINFO_ONE_PATH_CCA:
484 pDM_Odm->pOnePathCCA = (u8 *)pValue;
485 break;
486 case ODM_CMNINFO_DRV_STOP:
487 pDM_Odm->pbDriverStopped = (bool *)pValue;
488 break;
489 case ODM_CMNINFO_PNP_IN:
490 pDM_Odm->pbDriverIsGoingToPnpSetPowerSleep = (bool *)pValue;
491 break;
492 case ODM_CMNINFO_INIT_ON:
493 pDM_Odm->pinit_adpt_in_progress = (bool *)pValue;
494 break;
495 case ODM_CMNINFO_ANT_TEST:
496 pDM_Odm->pAntennaTest = (u8 *)pValue;
497 break;
498 case ODM_CMNINFO_NET_CLOSED:
499 pDM_Odm->pbNet_closed = (bool *)pValue;
500 break;
501 /* To remove the compiler warning, must add an empty default statement to handle the other values. */
502 default:
503 /* do nothing */
504 break;
505 }
506}
507
508void ODM_CmnInfoPtrArrayHook23a(struct dm_odm_t *pDM_Odm, enum odm_cmninfo CmnInfo,
509 u16 Index, void *pValue)
510{
511 /* Hook call by reference pointer. */
512 switch (CmnInfo) {
513 /* Dynamic call by reference pointer. */
514 case ODM_CMNINFO_STA_STATUS:
515 pDM_Odm->pODM_StaInfo[Index] = (struct sta_info *)pValue;
516 break;
517 /* To remove the compiler warning, must add an empty default statement to handle the other values. */
518 default:
519 /* do nothing */
520 break;
521 }
522}
523
524/* Update Band/CHannel/.. The values are dynamic but non-per-packet. */
525void ODM_CmnInfoUpdate23a(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value)
526{
527 /* This init variable may be changed in run time. */
528 switch (CmnInfo) {
529 case ODM_CMNINFO_ABILITY:
530 pDM_Odm->SupportAbility = (u32)Value;
531 break;
532 case ODM_CMNINFO_RF_TYPE:
533 pDM_Odm->RFType = (u8)Value;
534 break;
535 case ODM_CMNINFO_WIFI_DIRECT:
536 pDM_Odm->bWIFI_Direct = (bool)Value;
537 break;
538 case ODM_CMNINFO_WIFI_DISPLAY:
539 pDM_Odm->bWIFI_Display = (bool)Value;
540 break;
541 case ODM_CMNINFO_LINK:
542 pDM_Odm->bLinked = (bool)Value;
543 break;
544 case ODM_CMNINFO_RSSI_MIN:
545 pDM_Odm->RSSI_Min = (u8)Value;
546 break;
547 case ODM_CMNINFO_DBG_COMP:
548 pDM_Odm->DebugComponents = Value;
549 break;
550 case ODM_CMNINFO_DBG_LEVEL:
551 pDM_Odm->DebugLevel = (u32)Value;
552 break;
553 case ODM_CMNINFO_RA_THRESHOLD_HIGH:
554 pDM_Odm->RateAdaptive.HighRSSIThresh = (u8)Value;
555 break;
556 case ODM_CMNINFO_RA_THRESHOLD_LOW:
557 pDM_Odm->RateAdaptive.LowRSSIThresh = (u8)Value;
558 break;
559 }
560
561}
562
563void odm_CommonInfoSelfInit23a(struct dm_odm_t *pDM_Odm
564 )
565{
566 pDM_Odm->bCckHighPower = (bool) ODM_GetBBReg(pDM_Odm, 0x824, BIT9);
567 pDM_Odm->RFPathRxEnable = (u8) ODM_GetBBReg(pDM_Odm, 0xc04, 0x0F);
568 if (pDM_Odm->SupportICType & (ODM_RTL8723A))
569 pDM_Odm->AntDivType = CGCS_RX_SW_ANTDIV;
570
571 ODM_InitDebugSetting23a(pDM_Odm);
572}
573
574void odm_CommonInfoSelfUpdate23a(struct dm_odm_t *pDM_Odm)
575{
576 u8 EntryCnt = 0;
577 u8 i;
578 struct sta_info *pEntry;
579
580 if (*(pDM_Odm->pBandWidth) == ODM_BW40M) {
581 if (*(pDM_Odm->pSecChOffset) == 1)
582 pDM_Odm->ControlChannel = *(pDM_Odm->pChannel) - 2;
583 else if (*(pDM_Odm->pSecChOffset) == 2)
584 pDM_Odm->ControlChannel = *(pDM_Odm->pChannel) + 2;
585 } else {
586 pDM_Odm->ControlChannel = *(pDM_Odm->pChannel);
587 }
588
589 for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
590 pEntry = pDM_Odm->pODM_StaInfo[i];
591 if (IS_STA_VALID(pEntry))
592 EntryCnt++;
593 }
594 if (EntryCnt == 1)
595 pDM_Odm->bOneEntryOnly = true;
596 else
597 pDM_Odm->bOneEntryOnly = false;
598}
599
600void odm_CmnInfoInit_Debug23a(struct dm_odm_t *pDM_Odm)
601{
602 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoInit_Debug23a ==>\n"));
603 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportAbility = 0x%x\n", pDM_Odm->SupportAbility));
604 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportInterface =%d\n", pDM_Odm->SupportInterface));
605 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("SupportICType = 0x%x\n", pDM_Odm->SupportICType));
606 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("CutVersion =%d\n", pDM_Odm->CutVersion));
607 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("FabVersion =%d\n", pDM_Odm->FabVersion));
608 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RFType =%d\n", pDM_Odm->RFType));
609 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("BoardType =%d\n", pDM_Odm->BoardType));
610 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtLNA =%d\n", pDM_Odm->ExtLNA));
611 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtPA =%d\n", pDM_Odm->ExtPA));
612 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("ExtTRSW =%d\n", pDM_Odm->ExtTRSW));
613 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("PatchID =%d\n", pDM_Odm->PatchID));
614 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bInHctTest =%d\n", pDM_Odm->bInHctTest));
615 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFITest =%d\n", pDM_Odm->bWIFITest));
616 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bDualMacSmartConcurrent =%d\n", pDM_Odm->bDualMacSmartConcurrent));
617
618}
619
620void odm_CmnInfoHook_Debug23a(struct dm_odm_t *pDM_Odm)
621{
622 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoHook_Debug23a ==>\n"));
623 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pNumTxBytesUnicast =%llu\n", *(pDM_Odm->pNumTxBytesUnicast)));
624 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pNumRxBytesUnicast =%llu\n", *(pDM_Odm->pNumRxBytesUnicast)));
625 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pWirelessMode = 0x%x\n", *(pDM_Odm->pWirelessMode)));
626 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pSecChOffset =%d\n", *(pDM_Odm->pSecChOffset)));
627 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pSecurity =%d\n", *(pDM_Odm->pSecurity)));
628 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pBandWidth =%d\n", *(pDM_Odm->pBandWidth)));
629 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pChannel =%d\n", *(pDM_Odm->pChannel)));
630
631 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pbScanInProcess =%d\n", *(pDM_Odm->pbScanInProcess)));
632 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("pbPowerSaving =%d\n", *(pDM_Odm->pbPowerSaving)));
633}
634
635void odm_CmnInfoUpdate_Debug23a(struct dm_odm_t *pDM_Odm)
636{
637 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("odm_CmnInfoUpdate_Debug23a ==>\n"));
638 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFI_Direct =%d\n", pDM_Odm->bWIFI_Direct));
639 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bWIFI_Display =%d\n", pDM_Odm->bWIFI_Display));
640 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("bLinked =%d\n", pDM_Odm->bLinked));
641 ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD, ("RSSI_Min =%d\n", pDM_Odm->RSSI_Min));
642}
643
644void ODM_Write_DIG23a(struct dm_odm_t *pDM_Odm,
645 u8 CurrentIGI
646 )
647{
648 struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
649
650 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("ODM_REG(IGI_A, pDM_Odm) = 0x%x, ODM_BIT(IGI, pDM_Odm) = 0x%x \n",
651 ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm)));
652
653 if (pDM_DigTable->CurIGValue != CurrentIGI) {
654 ODM_SetBBReg(pDM_Odm, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
655 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("CurrentIGI(0x%02x). \n", CurrentIGI));
656 pDM_DigTable->CurIGValue = CurrentIGI;
657 }
658 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
659 ("ODM_Write_DIG23a():CurrentIGI = 0x%x \n", CurrentIGI));
660}
661
662/* Need LPS mode for CE platform --2012--08--24--- */
663/* 8723AS/8189ES */
664void odm_DIG23abyRSSI_LPS(struct dm_odm_t *pDM_Odm)
665{
666 struct rtw_adapter *pAdapter = pDM_Odm->Adapter;
667 struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
668 u8 RSSI_Lower = DM_DIG_MIN_NIC; /* 0x1E or 0x1C */
669 u8 bFwCurrentInPSMode = false;
670 u8 CurrentIGI = pDM_Odm->RSSI_Min;
671
672 if (!(pDM_Odm->SupportICType & (ODM_RTL8723A)))
673 return;
674
675 CurrentIGI = CurrentIGI+RSSI_OFFSET_DIG;
676 bFwCurrentInPSMode = pAdapter->pwrctrlpriv.bFwCurrentInPSMode;
677
678 /* ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG_LPS, ODM_DBG_LOUD, ("odm_DIG23a() ==>\n")); */
679
680 /* Using FW PS mode to make IGI */
681 if (bFwCurrentInPSMode) {
682 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("---Neil---odm_DIG23a is in LPS mode\n"));
683 /* Adjust by FA in LPS MODE */
684 if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_LPS)
685 CurrentIGI = CurrentIGI+2;
686 else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1_LPS)
687 CurrentIGI = CurrentIGI+1;
688 else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0_LPS)
689 CurrentIGI = CurrentIGI-1;
690 } else {
691 CurrentIGI = RSSI_Lower;
692 }
693
694 /* Lower bound checking */
695
696 /* RSSI Lower bound check */
697 if ((pDM_Odm->RSSI_Min-10) > DM_DIG_MIN_NIC)
698 RSSI_Lower = (pDM_Odm->RSSI_Min-10);
699 else
700 RSSI_Lower = DM_DIG_MIN_NIC;
701
702 /* Upper and Lower Bound checking */
703 if (CurrentIGI > DM_DIG_MAX_NIC)
704 CurrentIGI = DM_DIG_MAX_NIC;
705 else if (CurrentIGI < RSSI_Lower)
706 CurrentIGI = RSSI_Lower;
707
708 ODM_Write_DIG23a(pDM_Odm, CurrentIGI);/* ODM_Write_DIG23a(pDM_Odm, pDM_DigTable->CurIGValue); */
709
710}
711
712void odm_DIG23aInit(struct dm_odm_t *pDM_Odm)
713{
714 struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
715
716 pDM_DigTable->CurIGValue = (u8) ODM_GetBBReg(pDM_Odm, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm));
717 pDM_DigTable->RssiLowThresh = DM_DIG_THRESH_LOW;
718 pDM_DigTable->RssiHighThresh = DM_DIG_THRESH_HIGH;
719 pDM_DigTable->FALowThresh = DM_FALSEALARM_THRESH_LOW;
720 pDM_DigTable->FAHighThresh = DM_FALSEALARM_THRESH_HIGH;
721 if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) {
722 pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
723 pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
724 } else {
725 pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
726 pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
727 }
728 pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT;
729 pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX;
730 pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN;
731 pDM_DigTable->PreCCK_CCAThres = 0xFF;
732 pDM_DigTable->CurCCK_CCAThres = 0x83;
733 pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC;
734 pDM_DigTable->LargeFAHit = 0;
735 pDM_DigTable->Recover_cnt = 0;
736 pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC;
737 pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC;
738 pDM_DigTable->bMediaConnect_0 = false;
739 pDM_DigTable->bMediaConnect_1 = false;
740
741 /* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */
742 pDM_Odm->bDMInitialGainEnable = true;
743
744}
745
746void odm_DIG23a(struct dm_odm_t *pDM_Odm)
747{
748
749 struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
750 struct false_alarm_stats *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
751 u8 DIG_Dynamic_MIN;
752 u8 DIG_MaxOfMin;
753 bool FirstConnect, FirstDisConnect;
754 u8 dm_dig_max, dm_dig_min;
755 u8 CurrentIGI = pDM_DigTable->CurIGValue;
756
757 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a() ==>\n"));
758 /* if (!(pDM_Odm->SupportAbility & (ODM_BB_DIG|ODM_BB_FA_CNT))) */
759 if ((!(pDM_Odm->SupportAbility&ODM_BB_DIG)) || (!(pDM_Odm->SupportAbility&ODM_BB_FA_CNT))) {
760 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
761 ("odm_DIG23a() Return: SupportAbility ODM_BB_DIG or ODM_BB_FA_CNT is disabled\n"));
762 return;
763 }
764
765 if (*(pDM_Odm->pbScanInProcess)) {
766 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a() Return: In Scan Progress \n"));
767 return;
768 }
769
770 /* add by Neil Chen to avoid PSD is processing */
771 if (!pDM_Odm->bDMInitialGainEnable) {
772 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a() Return: PSD is Processing \n"));
773 return;
774 }
775
776 DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0;
777 FirstConnect = (pDM_Odm->bLinked) && (!pDM_DigTable->bMediaConnect_0);
778 FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0);
779
780 /* 1 Boundary Decision */
781 if ((pDM_Odm->SupportICType & (ODM_RTL8723A)) &&
782 ((pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) || pDM_Odm->ExtLNA)) {
783 dm_dig_max = DM_DIG_MAX_NIC_HP;
784 dm_dig_min = DM_DIG_MIN_NIC_HP;
785 DIG_MaxOfMin = DM_DIG_MAX_AP_HP;
786 } else {
787 dm_dig_max = DM_DIG_MAX_NIC;
788 dm_dig_min = DM_DIG_MIN_NIC;
789 DIG_MaxOfMin = DM_DIG_MAX_AP;
790 }
791
792 if (pDM_Odm->bLinked) {
793 /* 2 8723A Series, offset need to be 10 */
794 if (pDM_Odm->SupportICType == (ODM_RTL8723A)) {
795 /* 2 Upper Bound */
796 if ((pDM_Odm->RSSI_Min + 10) > DM_DIG_MAX_NIC)
797 pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
798 else if ((pDM_Odm->RSSI_Min + 10) < DM_DIG_MIN_NIC)
799 pDM_DigTable->rx_gain_range_max = DM_DIG_MIN_NIC;
800 else
801 pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + 10;
802
803 /* 2 If BT is Concurrent, need to set Lower Bound */
804 DIG_Dynamic_MIN = DM_DIG_MIN_NIC;
805 } else {
806 /* 2 Modify DIG upper bound */
807 if ((pDM_Odm->RSSI_Min + 20) > dm_dig_max)
808 pDM_DigTable->rx_gain_range_max = dm_dig_max;
809 else if ((pDM_Odm->RSSI_Min + 20) < dm_dig_min)
810 pDM_DigTable->rx_gain_range_max = dm_dig_min;
811 else
812 pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + 20;
813
814 /* 2 Modify DIG lower bound */
815 if (pDM_Odm->bOneEntryOnly) {
816 if (pDM_Odm->RSSI_Min < dm_dig_min)
817 DIG_Dynamic_MIN = dm_dig_min;
818 else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin)
819 DIG_Dynamic_MIN = DIG_MaxOfMin;
820 else
821 DIG_Dynamic_MIN = pDM_Odm->RSSI_Min;
822 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
823 ("odm_DIG23a() : bOneEntryOnly = true, DIG_Dynamic_MIN = 0x%x\n",
824 DIG_Dynamic_MIN));
825 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
826 ("odm_DIG23a() : pDM_Odm->RSSI_Min =%d\n",
827 pDM_Odm->RSSI_Min));
828 } else {
829 DIG_Dynamic_MIN = dm_dig_min;
830 }
831 }
832 } else {
833 pDM_DigTable->rx_gain_range_max = dm_dig_max;
834 DIG_Dynamic_MIN = dm_dig_min;
835 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a() : No Link\n"));
836 }
837
838 /* 1 Modify DIG lower bound, deal with abnormally large false alarm */
839 if (pFalseAlmCnt->Cnt_all > 10000) {
840 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
841 ("dm_DIG(): Abnornally false alarm case. \n"));
842
843 if (pDM_DigTable->LargeFAHit != 3)
844 pDM_DigTable->LargeFAHit++;
845 if (pDM_DigTable->ForbiddenIGI < CurrentIGI) {
846 pDM_DigTable->ForbiddenIGI = CurrentIGI;
847 pDM_DigTable->LargeFAHit = 1;
848 }
849
850 if (pDM_DigTable->LargeFAHit >= 3) {
851 if ((pDM_DigTable->ForbiddenIGI+1) > pDM_DigTable->rx_gain_range_max)
852 pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
853 else
854 pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1);
855 pDM_DigTable->Recover_cnt = 3600; /* 3600 = 2hr */
856 }
857 } else {
858 /* Recovery mechanism for IGI lower bound */
859 if (pDM_DigTable->Recover_cnt != 0) {
860 pDM_DigTable->Recover_cnt--;
861 } else {
862 if (pDM_DigTable->LargeFAHit < 3) {
863 if ((pDM_DigTable->ForbiddenIGI - 1) < DIG_Dynamic_MIN) {
864 pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
865 pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
866 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
867 ("odm_DIG23a(): Normal Case: At Lower Bound\n"));
868 } else {
869 pDM_DigTable->ForbiddenIGI--;
870 pDM_DigTable->rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 1);
871 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD,
872 ("odm_DIG23a(): Normal Case: Approach Lower Bound\n"));
873 }
874 } else {
875 pDM_DigTable->LargeFAHit = 0;
876 }
877 }
878 }
879 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): pDM_DigTable->LargeFAHit =%d\n", pDM_DigTable->LargeFAHit));
880
881 /* 1 Adjust initial gain by false alarm */
882 if (pDM_Odm->bLinked) {
883 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): DIG AfterLink\n"));
884 if (FirstConnect) {
885 CurrentIGI = pDM_Odm->RSSI_Min;
886 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("DIG: First Connect\n"));
887 } else {
888 if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2)
889 CurrentIGI = CurrentIGI + 4;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */
890 else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1)
891 CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */
892 else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0)
893 CurrentIGI = CurrentIGI - 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue-1; */
894 }
895 } else {
896 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): DIG BeforeLink\n"));
897 if (FirstDisConnect) {
898 CurrentIGI = pDM_DigTable->rx_gain_range_min;
899 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): First DisConnect \n"));
900 } else {
901 /* 2012.03.30 LukeLee: enable DIG before link but with very high thresholds */
902 if (pFalseAlmCnt->Cnt_all > 10000)
903 CurrentIGI = CurrentIGI + 2;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+2; */
904 else if (pFalseAlmCnt->Cnt_all > 8000)
905 CurrentIGI = CurrentIGI + 1;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue+1; */
906 else if (pFalseAlmCnt->Cnt_all < 500)
907 CurrentIGI = CurrentIGI - 1;/* pDM_DigTable->CurIGValue = pDM_DigTable->PreIGValue-1; */
908 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): England DIG \n"));
909 }
910 }
911 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): DIG End Adjust IGI\n"));
912 /* 1 Check initial gain by upper/lower bound */
913 if (CurrentIGI > pDM_DigTable->rx_gain_range_max)
914 CurrentIGI = pDM_DigTable->rx_gain_range_max;
915 if (CurrentIGI < pDM_DigTable->rx_gain_range_min)
916 CurrentIGI = pDM_DigTable->rx_gain_range_min;
917
918 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): rx_gain_range_max = 0x%x, rx_gain_range_min = 0x%x\n",
919 pDM_DigTable->rx_gain_range_max, pDM_DigTable->rx_gain_range_min));
920 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): TotalFA =%d\n", pFalseAlmCnt->Cnt_all));
921 ODM_RT_TRACE(pDM_Odm, ODM_COMP_DIG, ODM_DBG_LOUD, ("odm_DIG23a(): CurIGValue = 0x%x\n", CurrentIGI));
922
923 /* 2 High power RSSI threshold */
924
925 ODM_Write_DIG23a(pDM_Odm, CurrentIGI);/* ODM_Write_DIG23a(pDM_Odm, pDM_DigTable->CurIGValue); */
926 pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
927 pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
928}
929
930/* 3 ============================================================ */
931/* 3 FASLE ALARM CHECK */
932/* 3 ============================================================ */
933
934void odm_FalseAlarmCounterStatistics23a(struct dm_odm_t *pDM_Odm)
935{
936 u32 ret_value;
937 struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
938
939 if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
940 return;
941
942 if (pDM_Odm->SupportICType & ODM_IC_11N_SERIES) {
943 /* hold ofdm counter */
944 ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 1); /* hold page C counter */
945 ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 1); /* hold page D counter */
946
947 ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord);
948 FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
949 FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value&0xffff0000)>>16);
950 ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord);
951 FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff);
952 FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16);
953 ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord);
954 FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff);
955 FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16);
956 ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord);
957 FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff);
958
959 FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail +
960 FalseAlmCnt->Cnt_Rate_Illegal +
961 FalseAlmCnt->Cnt_Crc8_fail +
962 FalseAlmCnt->Cnt_Mcs_fail +
963 FalseAlmCnt->Cnt_Fast_Fsync +
964 FalseAlmCnt->Cnt_SB_Search_fail;
965 /* hold cck counter */
966 ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT12, 1);
967 ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT14, 1);
968
969 ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_LSB_11N, bMaskByte0);
970 FalseAlmCnt->Cnt_Cck_fail = ret_value;
971 ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_MSB_11N, bMaskByte3);
972 FalseAlmCnt->Cnt_Cck_fail += (ret_value & 0xff) << 8;
973
974 ret_value = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord);
975 FalseAlmCnt->Cnt_CCK_CCA = ((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8);
976
977 FalseAlmCnt->Cnt_all = (FalseAlmCnt->Cnt_Fast_Fsync +
978 FalseAlmCnt->Cnt_SB_Search_fail +
979 FalseAlmCnt->Cnt_Parity_Fail +
980 FalseAlmCnt->Cnt_Rate_Illegal +
981 FalseAlmCnt->Cnt_Crc8_fail +
982 FalseAlmCnt->Cnt_Mcs_fail +
983 FalseAlmCnt->Cnt_Cck_fail);
984
985 FalseAlmCnt->Cnt_CCA_all = FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA;
986
987 if (pDM_Odm->SupportICType >= ODM_RTL8723A) {
988 /* reset false alarm counter registers */
989 ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTC_11N, BIT31, 1);
990 ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTC_11N, BIT31, 0);
991 ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT27, 1);
992 ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT27, 0);
993 /* update ofdm counter */
994 ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 0); /* update page C counter */
995 ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 0); /* update page D counter */
996
997 /* reset CCK CCA counter */
998 ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT13|BIT12, 0);
999 ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT13|BIT12, 2);
1000 /* reset CCK FA counter */
1001 ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT15|BIT14, 0);
1002 ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11N, BIT15|BIT14, 2);
1003 }
1004
1005 ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Enter odm_FalseAlarmCounterStatistics23a\n"));
1006 ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Fast_Fsync =%d, Cnt_SB_Search_fail =%d\n",
1007 FalseAlmCnt->Cnt_Fast_Fsync, FalseAlmCnt->Cnt_SB_Search_fail));
1008 ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Parity_Fail =%d, Cnt_Rate_Illegal =%d\n",
1009 FalseAlmCnt->Cnt_Parity_Fail, FalseAlmCnt->Cnt_Rate_Illegal));
1010 ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Crc8_fail =%d, Cnt_Mcs_fail =%d\n",
1011 FalseAlmCnt->Cnt_Crc8_fail, FalseAlmCnt->Cnt_Mcs_fail));
1012 } else { /* FOR ODM_IC_11AC_SERIES */
1013 /* read OFDM FA counter */
1014 FalseAlmCnt->Cnt_Ofdm_fail = ODM_GetBBReg(pDM_Odm, ODM_REG_OFDM_FA_11AC, bMaskLWord);
1015 FalseAlmCnt->Cnt_Cck_fail = ODM_GetBBReg(pDM_Odm, ODM_REG_CCK_FA_11AC, bMaskLWord);
1016 FalseAlmCnt->Cnt_all = FalseAlmCnt->Cnt_Ofdm_fail + FalseAlmCnt->Cnt_Cck_fail;
1017
1018 /* reset OFDM FA coutner */
1019 ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RST_11AC, BIT17, 1);
1020 ODM_SetBBReg(pDM_Odm, ODM_REG_OFDM_FA_RST_11AC, BIT17, 0);
1021 /* reset CCK FA counter */
1022 ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11AC, BIT15, 0);
1023 ODM_SetBBReg(pDM_Odm, ODM_REG_CCK_FA_RST_11AC, BIT15, 1);
1024 }
1025 ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Cck_fail =%d\n", FalseAlmCnt->Cnt_Cck_fail));
1026 ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Cnt_Ofdm_fail =%d\n", FalseAlmCnt->Cnt_Ofdm_fail));
1027 ODM_RT_TRACE(pDM_Odm, ODM_COMP_FA_CNT, ODM_DBG_LOUD, ("Total False Alarm =%d\n", FalseAlmCnt->Cnt_all));
1028}
1029
1030/* 3 ============================================================ */
1031/* 3 CCK Packet Detect Threshold */
1032/* 3 ============================================================ */
1033
1034void odm_CCKPacketDetectionThresh23a(struct dm_odm_t *pDM_Odm)
1035{
1036 struct false_alarm_stats *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
1037 u8 CurCCK_CCAThres;
1038
1039 if (!(pDM_Odm->SupportAbility & (ODM_BB_CCK_PD|ODM_BB_FA_CNT)))
1040 return;
1041
1042 if (pDM_Odm->ExtLNA)
1043 return;
1044
1045 if (pDM_Odm->bLinked) {
1046 if (pDM_Odm->RSSI_Min > 25) {
1047 CurCCK_CCAThres = 0xcd;
1048 } else if ((pDM_Odm->RSSI_Min <= 25) && (pDM_Odm->RSSI_Min > 10)) {
1049 CurCCK_CCAThres = 0x83;
1050 } else {
1051 if (FalseAlmCnt->Cnt_Cck_fail > 1000)
1052 CurCCK_CCAThres = 0x83;
1053 else
1054 CurCCK_CCAThres = 0x40;
1055 }
1056 } else {
1057 if (FalseAlmCnt->Cnt_Cck_fail > 1000)
1058 CurCCK_CCAThres = 0x83;
1059 else
1060 CurCCK_CCAThres = 0x40;
1061 }
1062
1063 ODM_Write_CCK_CCA_Thres23a(pDM_Odm, CurCCK_CCAThres);
1064}
1065
1066void ODM_Write_CCK_CCA_Thres23a(struct dm_odm_t *pDM_Odm, u8 CurCCK_CCAThres)
1067{
1068 struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
1069
1070 if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres)
1071 ODM_Write1Byte(pDM_Odm, ODM_REG(CCK_CCA, pDM_Odm), CurCCK_CCAThres);
1072 pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres;
1073 pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres;
1074
1075}
1076
1077/* 3 ============================================================ */
1078/* 3 BB Power Save */
1079/* 3 ============================================================ */
1080void odm23a_DynBBPSInit(struct dm_odm_t *pDM_Odm)
1081{
1082 struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable;
1083
1084 pDM_PSTable->PreCCAState = CCA_MAX;
1085 pDM_PSTable->CurCCAState = CCA_MAX;
1086 pDM_PSTable->PreRFState = RF_MAX;
1087 pDM_PSTable->CurRFState = RF_MAX;
1088 pDM_PSTable->Rssi_val_min = 0;
1089 pDM_PSTable->initialize = 0;
1090}
1091
1092void odm_DynamicBBPowerSaving23a(struct dm_odm_t *pDM_Odm)
1093{
1094 return;
1095}
1096
1097void odm_1R_CCA23a(struct dm_odm_t *pDM_Odm)
1098{
1099 struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable;
1100
1101 if (pDM_Odm->RSSI_Min != 0xFF) {
1102 if (pDM_PSTable->PreCCAState == CCA_2R) {
1103 if (pDM_Odm->RSSI_Min >= 35)
1104 pDM_PSTable->CurCCAState = CCA_1R;
1105 else
1106 pDM_PSTable->CurCCAState = CCA_2R;
1107 } else {
1108 if (pDM_Odm->RSSI_Min <= 30)
1109 pDM_PSTable->CurCCAState = CCA_2R;
1110 else
1111 pDM_PSTable->CurCCAState = CCA_1R;
1112 }
1113 } else {
1114 pDM_PSTable->CurCCAState = CCA_MAX;
1115 }
1116
1117 if (pDM_PSTable->PreCCAState != pDM_PSTable->CurCCAState) {
1118 if (pDM_PSTable->CurCCAState == CCA_1R) {
1119 if (pDM_Odm->RFType == ODM_2T2R)
1120 ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x13);
1121 else
1122 ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x23);
1123 } else {
1124 ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x33);
1125 /* PHY_SetBBReg(pAdapter, 0xe70, bMaskByte3, 0x63); */
1126 }
1127 pDM_PSTable->PreCCAState = pDM_PSTable->CurCCAState;
1128 }
1129}
1130
1131void ODM_RF_Saving23a(struct dm_odm_t *pDM_Odm, u8 bForceInNormal)
1132{
1133 struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable;
1134 u8 Rssi_Up_bound = 30 ;
1135 u8 Rssi_Low_bound = 25;
1136 if (pDM_Odm->PatchID == 40) { /* RT_CID_819x_FUNAI_TV */
1137 Rssi_Up_bound = 50 ;
1138 Rssi_Low_bound = 45;
1139 }
1140 if (pDM_PSTable->initialize == 0) {
1141
1142 pDM_PSTable->Reg874 = (ODM_GetBBReg(pDM_Odm, 0x874, bMaskDWord)&0x1CC000)>>14;
1143 pDM_PSTable->RegC70 = (ODM_GetBBReg(pDM_Odm, 0xc70, bMaskDWord)&BIT3)>>3;
1144 pDM_PSTable->Reg85C = (ODM_GetBBReg(pDM_Odm, 0x85c, bMaskDWord)&0xFF000000)>>24;
1145 pDM_PSTable->RegA74 = (ODM_GetBBReg(pDM_Odm, 0xa74, bMaskDWord)&0xF000)>>12;
1146 /* Reg818 = PHY_QueryBBReg(pAdapter, 0x818, bMaskDWord); */
1147 pDM_PSTable->initialize = 1;
1148 }
1149
1150 if (!bForceInNormal) {
1151 if (pDM_Odm->RSSI_Min != 0xFF) {
1152 if (pDM_PSTable->PreRFState == RF_Normal) {
1153 if (pDM_Odm->RSSI_Min >= Rssi_Up_bound)
1154 pDM_PSTable->CurRFState = RF_Save;
1155 else
1156 pDM_PSTable->CurRFState = RF_Normal;
1157 } else {
1158 if (pDM_Odm->RSSI_Min <= Rssi_Low_bound)
1159 pDM_PSTable->CurRFState = RF_Normal;
1160 else
1161 pDM_PSTable->CurRFState = RF_Save;
1162 }
1163 } else {
1164 pDM_PSTable->CurRFState = RF_MAX;
1165 }
1166 } else {
1167 pDM_PSTable->CurRFState = RF_Normal;
1168 }
1169
1170 if (pDM_PSTable->PreRFState != pDM_PSTable->CurRFState) {
1171 if (pDM_PSTable->CurRFState == RF_Save) {
1172 /* <tynli_note> 8723 RSSI report will be wrong. Set 0x874[5]= 1 when enter BB power saving mode. */
1173 /* Suggested by SD3 Yu-Nan. 2011.01.20. */
1174 if (pDM_Odm->SupportICType == ODM_RTL8723A)
1175 ODM_SetBBReg(pDM_Odm, 0x874, BIT5, 0x1); /* Reg874[5]= 1b'1 */
1176 ODM_SetBBReg(pDM_Odm, 0x874, 0x1C0000, 0x2); /* Reg874[20:18]= 3'b010 */
1177 ODM_SetBBReg(pDM_Odm, 0xc70, BIT3, 0); /* RegC70[3]= 1'b0 */
1178 ODM_SetBBReg(pDM_Odm, 0x85c, 0xFF000000, 0x63); /* Reg85C[31:24]= 0x63 */
1179 ODM_SetBBReg(pDM_Odm, 0x874, 0xC000, 0x2); /* Reg874[15:14]= 2'b10 */
1180 ODM_SetBBReg(pDM_Odm, 0xa74, 0xF000, 0x3); /* RegA75[7:4]= 0x3 */
1181 ODM_SetBBReg(pDM_Odm, 0x818, BIT28, 0x0); /* Reg818[28]= 1'b0 */
1182 ODM_SetBBReg(pDM_Odm, 0x818, BIT28, 0x1); /* Reg818[28]= 1'b1 */
1183 } else {
1184 ODM_SetBBReg(pDM_Odm, 0x874, 0x1CC000, pDM_PSTable->Reg874);
1185 ODM_SetBBReg(pDM_Odm, 0xc70, BIT3, pDM_PSTable->RegC70);
1186 ODM_SetBBReg(pDM_Odm, 0x85c, 0xFF000000, pDM_PSTable->Reg85C);
1187 ODM_SetBBReg(pDM_Odm, 0xa74, 0xF000, pDM_PSTable->RegA74);
1188 ODM_SetBBReg(pDM_Odm, 0x818, BIT28, 0x0);
1189
1190 if (pDM_Odm->SupportICType == ODM_RTL8723A)
1191 ODM_SetBBReg(pDM_Odm, 0x874, BIT5, 0x0); /* Reg874[5]= 1b'0 */
1192 }
1193 pDM_PSTable->PreRFState = pDM_PSTable->CurRFState;
1194 }
1195}
1196
1197/* 3 ============================================================ */
1198/* 3 RATR MASK */
1199/* 3 ============================================================ */
1200/* 3 ============================================================ */
1201/* 3 Rate Adaptive */
1202/* 3 ============================================================ */
1203
1204void odm_RateAdaptiveMaskInit23a(struct dm_odm_t *pDM_Odm)
1205{
1206 struct odm_rate_adapt *pOdmRA = &pDM_Odm->RateAdaptive;
1207
1208 pOdmRA->Type = DM_Type_ByDriver;
1209 if (pOdmRA->Type == DM_Type_ByDriver)
1210 pDM_Odm->bUseRAMask = true;
1211 else
1212 pDM_Odm->bUseRAMask = false;
1213
1214 pOdmRA->RATRState = DM_RATR_STA_INIT;
1215 pOdmRA->HighRSSIThresh = 50;
1216 pOdmRA->LowRSSIThresh = 20;
1217}
1218
1219u32 ODM_Get_Rate_Bitmap23a(struct dm_odm_t *pDM_Odm,
1220 u32 macid,
1221 u32 ra_mask,
1222 u8 rssi_level)
1223{
1224 struct sta_info *pEntry;
1225 u32 rate_bitmap = 0x0fffffff;
1226 u8 WirelessMode;
1227 /* u8 WirelessMode =*(pDM_Odm->pWirelessMode); */
1228
1229 pEntry = pDM_Odm->pODM_StaInfo[macid];
1230 if (!IS_STA_VALID(pEntry))
1231 return ra_mask;
1232
1233 WirelessMode = pEntry->wireless_mode;
1234
1235 switch (WirelessMode) {
1236 case ODM_WM_B:
1237 if (ra_mask & 0x0000000c) /* 11M or 5.5M enable */
1238 rate_bitmap = 0x0000000d;
1239 else
1240 rate_bitmap = 0x0000000f;
1241 break;
1242 case (ODM_WM_A|ODM_WM_G):
1243 if (rssi_level == DM_RATR_STA_HIGH)
1244 rate_bitmap = 0x00000f00;
1245 else
1246 rate_bitmap = 0x00000ff0;
1247 break;
1248 case (ODM_WM_B|ODM_WM_G):
1249 if (rssi_level == DM_RATR_STA_HIGH)
1250 rate_bitmap = 0x00000f00;
1251 else if (rssi_level == DM_RATR_STA_MIDDLE)
1252 rate_bitmap = 0x00000ff0;
1253 else
1254 rate_bitmap = 0x00000ff5;
1255 break;
1256 case (ODM_WM_B|ODM_WM_G|ODM_WM_N24G):
1257 case (ODM_WM_A|ODM_WM_B|ODM_WM_G|ODM_WM_N24G):
1258 if (pDM_Odm->RFType == ODM_1T2R || pDM_Odm->RFType == ODM_1T1R) {
1259 if (rssi_level == DM_RATR_STA_HIGH) {
1260 rate_bitmap = 0x000f0000;
1261 } else if (rssi_level == DM_RATR_STA_MIDDLE) {
1262 rate_bitmap = 0x000ff000;
1263 } else {
1264 if (*(pDM_Odm->pBandWidth) == ODM_BW40M)
1265 rate_bitmap = 0x000ff015;
1266 else
1267 rate_bitmap = 0x000ff005;
1268 }
1269 } else {
1270 if (rssi_level == DM_RATR_STA_HIGH) {
1271 rate_bitmap = 0x0f8f0000;
1272 } else if (rssi_level == DM_RATR_STA_MIDDLE) {
1273 rate_bitmap = 0x0f8ff000;
1274 } else {
1275 if (*(pDM_Odm->pBandWidth) == ODM_BW40M)
1276 rate_bitmap = 0x0f8ff015;
1277 else
1278 rate_bitmap = 0x0f8ff005;
1279 }
1280 }
1281 break;
1282 default:
1283 /* case WIRELESS_11_24N: */
1284 /* case WIRELESS_11_5N: */
1285 if (pDM_Odm->RFType == RF_1T2R)
1286 rate_bitmap = 0x000fffff;
1287 else
1288 rate_bitmap = 0x0fffffff;
1289 break;
1290 }
1291
1292 /* printk("%s ==> rssi_level:0x%02x, WirelessMode:0x%02x, rate_bitmap:0x%08x \n", __FUNCTION__, rssi_level, WirelessMode, rate_bitmap); */
1293 ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD, (" ==> rssi_level:0x%02x, WirelessMode:0x%02x, rate_bitmap:0x%08x \n", rssi_level, WirelessMode, rate_bitmap));
1294
1295 return rate_bitmap;
1296
1297}
1298
1299/*-----------------------------------------------------------------------------
1300 * Function: odm_RefreshRateAdaptiveMask23a()
1301 *
1302 * Overview: Update rate table mask according to rssi
1303 *
1304 * Input: NONE
1305 *
1306 * Output: NONE
1307 *
1308 * Return: NONE
1309 *
1310 * Revised History:
1311 *When Who Remark
1312 *05/27/2009 hpfan Create Version 0.
1313 *
1314 *---------------------------------------------------------------------------*/
1315void odm_RefreshRateAdaptiveMask23a(struct dm_odm_t *pDM_Odm)
1316{
1317 if (!(pDM_Odm->SupportAbility & ODM_BB_RA_MASK))
1318 return;
1319 /* */
1320 /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
1321 /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
1322 /* HW dynamic mechanism. */
1323 /* */
1324 odm_RefreshRateAdaptiveMask23aCE23a(pDM_Odm);
1325}
1326
1327void odm_RefreshRateAdaptiveMask23aMP23a(struct dm_odm_t *pDM_Odm)
1328{
1329}
1330
1331void odm_RefreshRateAdaptiveMask23aCE23a(struct dm_odm_t *pDM_Odm)
1332{
1333 u8 i;
1334 struct rtw_adapter *pAdapter = pDM_Odm->Adapter;
1335
1336 if (pAdapter->bDriverStopped) {
1337 ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_TRACE,
1338 ("<---- odm_RefreshRateAdaptiveMask23a(): driver is going to unload\n"));
1339 return;
1340 }
1341
1342 if (!pDM_Odm->bUseRAMask) {
1343 ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD,
1344 ("<---- odm_RefreshRateAdaptiveMask23a(): driver does not control rate adaptive mask\n"));
1345 return;
1346 }
1347
1348 /* printk("==> %s \n", __FUNCTION__); */
1349
1350 for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
1351 struct sta_info *pstat = pDM_Odm->pODM_StaInfo[i];
1352 if (IS_STA_VALID(pstat)) {
1353 if (ODM_RAStateCheck23a(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level)) {
1354 ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD,
1355 ("RSSI:%d, RSSI_LEVEL:%d\n",
1356 pstat->rssi_stat.UndecoratedSmoothedPWDB,
1357 pstat->rssi_level));
1358 rtw_hal_update_ra_mask23a(pstat, pstat->rssi_level);
1359 }
1360
1361 }
1362 }
1363
1364}
1365
1366void odm_RefreshRateAdaptiveMask23aAPADSL23a(struct dm_odm_t *pDM_Odm)
1367{
1368}
1369
1370/* Return Value: bool */
1371/* - true: RATRState is changed. */
1372bool ODM_RAStateCheck23a(struct dm_odm_t *pDM_Odm, s32 RSSI, bool bForceUpdate,
1373 u8 *pRATRState)
1374{
1375 struct odm_rate_adapt *pRA = &pDM_Odm->RateAdaptive;
1376 const u8 GoUpGap = 5;
1377 u8 HighRSSIThreshForRA = pRA->HighRSSIThresh;
1378 u8 LowRSSIThreshForRA = pRA->LowRSSIThresh;
1379 u8 RATRState;
1380
1381 /* Threshold Adjustment: */
1382 /* when RSSI state trends to go up one or two levels, make sure RSSI is high enough. */
1383 /* Here GoUpGap is added to solve the boundary's level alternation issue. */
1384 switch (*pRATRState) {
1385 case DM_RATR_STA_INIT:
1386 case DM_RATR_STA_HIGH:
1387 break;
1388 case DM_RATR_STA_MIDDLE:
1389 HighRSSIThreshForRA += GoUpGap;
1390 break;
1391 case DM_RATR_STA_LOW:
1392 HighRSSIThreshForRA += GoUpGap;
1393 LowRSSIThreshForRA += GoUpGap;
1394 break;
1395 default:
1396 ODM_RT_ASSERT(pDM_Odm, false, ("wrong rssi level setting %d !", *pRATRState));
1397 break;
1398 }
1399
1400 /* Decide RATRState by RSSI. */
1401 if (RSSI > HighRSSIThreshForRA)
1402 RATRState = DM_RATR_STA_HIGH;
1403 else if (RSSI > LowRSSIThreshForRA)
1404 RATRState = DM_RATR_STA_MIDDLE;
1405 else
1406 RATRState = DM_RATR_STA_LOW;
1407
1408 if (*pRATRState != RATRState || bForceUpdate) {
1409 ODM_RT_TRACE(pDM_Odm, ODM_COMP_RA_MASK, ODM_DBG_LOUD,
1410 ("RSSI Level %d -> %d\n", *pRATRState, RATRState));
1411 *pRATRState = RATRState;
1412 return true;
1413 }
1414 return false;
1415}
1416
1417/* 3 ============================================================ */
1418/* 3 Dynamic Tx Power */
1419/* 3 ============================================================ */
1420
1421void odm_DynamicTxPower23aInit(struct dm_odm_t *pDM_Odm)
1422{
1423 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
1424 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1425 struct dm_priv *pdmpriv = &pHalData->dmpriv;
1426
1427 pdmpriv->bDynamicTxPowerEnable = false;
1428
1429 pdmpriv->LastDTPLvl = TxHighPwrLevel_Normal;
1430 pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal;
1431}
1432
1433void odm_DynamicTxPower23aSavePowerIndex(struct dm_odm_t *pDM_Odm)
1434{
1435 u8 index;
1436 u32 Power_Index_REG[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};
1437
1438 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
1439 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1440 struct dm_priv *pdmpriv = &pHalData->dmpriv;
1441 for (index = 0; index < 6; index++)
1442 pdmpriv->PowerIndex_backup[index] = rtw_read8(Adapter, Power_Index_REG[index]);
1443}
1444
1445void odm_DynamicTxPower23aRestorePowerIndex(struct dm_odm_t *pDM_Odm)
1446{
1447 u8 index;
1448 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
1449
1450 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1451 u32 Power_Index_REG[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};
1452 struct dm_priv *pdmpriv = &pHalData->dmpriv;
1453 for (index = 0; index < 6; index++)
1454 rtw_write8(Adapter, Power_Index_REG[index], pdmpriv->PowerIndex_backup[index]);
1455}
1456
1457void odm_DynamicTxPower23aWritePowerIndex(struct dm_odm_t *pDM_Odm,
1458 u8 Value)
1459{
1460
1461 u8 index;
1462 u32 Power_Index_REG[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};
1463
1464 for (index = 0; index < 6; index++)
1465 ODM_Write1Byte(pDM_Odm, Power_Index_REG[index], Value);
1466
1467}
1468
1469void odm_DynamicTxPower23a(struct dm_odm_t *pDM_Odm)
1470{
1471}
1472
1473void odm_DynamicTxPower23a_92C(struct dm_odm_t *pDM_Odm)
1474{
1475}
1476
1477void odm_DynamicTxPower23a_92D(struct dm_odm_t *pDM_Odm)
1478{
1479}
1480
1481/* 3 ============================================================ */
1482/* 3 RSSI Monitor */
1483/* 3 ============================================================ */
1484
1485void odm_RSSIMonitorInit(struct dm_odm_t *pDM_Odm)
1486{
1487}
1488
1489void odm_RSSIMonitorCheck23a(struct dm_odm_t *pDM_Odm)
1490{
1491 /* For AP/ADSL use struct rtl8723a_priv * */
1492 /* For CE/NIC use struct rtw_adapter * */
1493
1494 if (!(pDM_Odm->SupportAbility & ODM_BB_RSSI_MONITOR))
1495 return;
1496
1497 /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
1498 /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
1499 /* HW dynamic mechanism. */
1500 odm_RSSIMonitorCheck23aCE(pDM_Odm);
1501} /* odm_RSSIMonitorCheck23a */
1502
1503void odm_RSSIMonitorCheck23aMP(struct dm_odm_t *pDM_Odm)
1504{
1505}
1506
1507static void
1508FindMinimumRSSI(
1509 struct rtw_adapter *pAdapter
1510 )
1511{
1512 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
1513 struct dm_priv *pdmpriv = &pHalData->dmpriv;
1514 struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
1515
1516 /* 1 1.Determine the minimum RSSI */
1517
1518 if ((!pDM_Odm->bLinked) &&
1519 (pdmpriv->EntryMinUndecoratedSmoothedPWDB == 0))
1520 pdmpriv->MinUndecoratedPWDBForDM = 0;
1521 else
1522 pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB;
1523}
1524
1525void odm_RSSIMonitorCheck23aCE(struct dm_odm_t *pDM_Odm)
1526{
1527 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
1528 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1529 struct dm_priv *pdmpriv = &pHalData->dmpriv;
1530 int i;
1531 int tmpEntryMaxPWDB = 0, tmpEntryMinPWDB = 0xff;
1532 u8 sta_cnt = 0;
1533 u32 PWDB_rssi[NUM_STA] = {0};/* 0~15]:MACID, [16~31]:PWDB_rssi */
1534 struct sta_info *psta;
1535
1536 if (!pDM_Odm->bLinked)
1537 return;
1538
1539 for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
1540 psta = pDM_Odm->pODM_StaInfo[i];
1541 if (IS_STA_VALID(psta)) {
1542 if (psta->rssi_stat.UndecoratedSmoothedPWDB < tmpEntryMinPWDB)
1543 tmpEntryMinPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
1544
1545 if (psta->rssi_stat.UndecoratedSmoothedPWDB > tmpEntryMaxPWDB)
1546 tmpEntryMaxPWDB = psta->rssi_stat.UndecoratedSmoothedPWDB;
1547
1548 if (psta->rssi_stat.UndecoratedSmoothedPWDB != (-1))
1549 PWDB_rssi[sta_cnt++] = (psta->mac_id | (psta->rssi_stat.UndecoratedSmoothedPWDB<<16));
1550 }
1551 }
1552
1553 for (i = 0; i < sta_cnt; i++) {
1554 if (PWDB_rssi[i] != (0)) {
1555 if (pHalData->fw_ractrl) /* Report every sta's RSSI to FW */
1556 rtl8723a_set_rssi_cmd(Adapter, (u8 *)&PWDB_rssi[i]);
1557 }
1558 }
1559
1560 if (tmpEntryMaxPWDB != 0) /* If associated entry is found */
1561 pdmpriv->EntryMaxUndecoratedSmoothedPWDB = tmpEntryMaxPWDB;
1562 else
1563 pdmpriv->EntryMaxUndecoratedSmoothedPWDB = 0;
1564
1565 if (tmpEntryMinPWDB != 0xff) /* If associated entry is found */
1566 pdmpriv->EntryMinUndecoratedSmoothedPWDB = tmpEntryMinPWDB;
1567 else
1568 pdmpriv->EntryMinUndecoratedSmoothedPWDB = 0;
1569
1570 FindMinimumRSSI(Adapter);/* get pdmpriv->MinUndecoratedPWDBForDM */
1571
1572 ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_RSSI_MIN, pdmpriv->MinUndecoratedPWDBForDM);
1573}
1574
1575void odm_RSSIMonitorCheck23aAP(struct dm_odm_t *pDM_Odm)
1576{
1577}
1578
1579void ODM_InitAllTimers(struct dm_odm_t *pDM_Odm)
1580{
1581 setup_timer(&pDM_Odm->DM_SWAT_Table.SwAntennaSwitchTimer,
1582 odm_SwAntDivChkAntSwitchCallback23a, (unsigned long)pDM_Odm);
1583}
1584
1585void ODM_CancelAllTimers(struct dm_odm_t *pDM_Odm)
1586{
1587 del_timer_sync(&pDM_Odm->DM_SWAT_Table.SwAntennaSwitchTimer);
1588}
1589
1590void ODM_ReleaseAllTimers(struct dm_odm_t *pDM_Odm)
1591{
1592 ODM_ReleaseTimer(pDM_Odm, &pDM_Odm->DM_SWAT_Table.SwAntennaSwitchTimer);
1593}
1594
1595/* endif */
1596/* 3 ============================================================ */
1597/* 3 Tx Power Tracking */
1598/* 3 ============================================================ */
1599
1600void odm_TXPowerTrackingInit23a(struct dm_odm_t *pDM_Odm)
1601{
1602 odm_TXPowerTrackingThermalMeterInit23a(pDM_Odm);
1603}
1604
1605void odm_TXPowerTrackingThermalMeterInit23a(struct dm_odm_t *pDM_Odm)
1606{
1607 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
1608 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1609 struct dm_priv *pdmpriv = &pHalData->dmpriv;
1610
1611 pdmpriv->bTXPowerTracking = true;
1612 pdmpriv->TXPowercount = 0;
1613 pdmpriv->bTXPowerTrackingInit = false;
1614 pdmpriv->TxPowerTrackControl = true;
1615 MSG_8723A("pdmpriv->TxPowerTrackControl = %d\n", pdmpriv->TxPowerTrackControl);
1616
1617 pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = true;
1618}
1619
1620void ODM_TXPowerTrackingCheck23a(struct dm_odm_t *pDM_Odm)
1621{
1622 /* For AP/ADSL use struct rtl8723a_priv * */
1623 /* For CE/NIC use struct rtw_adapter * */
1624
1625 /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
1626 /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
1627 /* HW dynamic mechanism. */
1628 odm_TXPowerTrackingCheckCE23a(pDM_Odm);
1629}
1630
1631void odm_TXPowerTrackingCheckCE23a(struct dm_odm_t *pDM_Odm)
1632{
1633}
1634
1635void odm_TXPowerTrackingCheckMP(struct dm_odm_t *pDM_Odm)
1636{
1637}
1638
1639void odm_TXPowerTrackingCheckAP(struct dm_odm_t *pDM_Odm)
1640{
1641}
1642
1643/* antenna mapping info */
1644/* 1: right-side antenna */
1645/* 2/0: left-side antenna */
1646/* PpDM_SWAT_Table->CCK_Ant1_Cnt /OFDM_Ant1_Cnt: for right-side antenna: Ant:1 RxDefaultAnt1 */
1647/* PpDM_SWAT_Table->CCK_Ant2_Cnt /OFDM_Ant2_Cnt: for left-side antenna: Ant:0 RxDefaultAnt2 */
1648/* We select left antenna as default antenna in initial process, modify it as needed */
1649/* */
1650
1651/* 3 ============================================================ */
1652/* 3 SW Antenna Diversity */
1653/* 3 ============================================================ */
1654void odm_SwAntDivInit(struct dm_odm_t *pDM_Odm)
1655{
1656}
1657
1658void ODM_SwAntDivChkPerPktRssi(struct dm_odm_t *pDM_Odm, u8 StationID, struct odm_phy_info *pPhyInfo)
1659{
1660}
1661
1662void odm_SwAntDivChkAntSwitch(struct dm_odm_t *pDM_Odm, u8 Step)
1663{
1664}
1665
1666void ODM_SwAntDivRestAfterLink(struct dm_odm_t *pDM_Odm)
1667{
1668}
1669
1670void odm_SwAntDivChkAntSwitchCallback23a(unsigned long data)
1671{
1672}
1673
1674/* 3 ============================================================ */
1675/* 3 SW Antenna Diversity */
1676/* 3 ============================================================ */
1677
1678void odm_InitHybridAntDiv23a(struct dm_odm_t *pDM_Odm)
1679{
1680}
1681
1682void odm_HwAntDiv23a(struct dm_odm_t *pDM_Odm)
1683{
1684}
1685
1686/* EDCA Turbo */
1687void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm)
1688{
1689
1690 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
1691 pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false;
1692 pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false;
1693 Adapter->recvpriv.bIsAnyNonBEPkts = false;
1694
1695 ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VO PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_VO_PARAM)));
1696 ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial VI PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_VI_PARAM)));
1697 ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BE PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_BE_PARAM)));
1698 ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("Orginial BK PARAM: 0x%x\n", ODM_Read4Byte(pDM_Odm, ODM_EDCA_BK_PARAM)));
1699
1700} /* ODM_InitEdcaTurbo */
1701
1702void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm)
1703{
1704 /* For AP/ADSL use struct rtl8723a_priv * */
1705 /* For CE/NIC use struct rtw_adapter * */
1706
1707 /* 2011/09/29 MH In HW integration first stage, we provide 4 different handle to operate */
1708 /* at the same time. In the stage2/3, we need to prive universal interface and merge all */
1709 /* HW dynamic mechanism. */
1710 ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("odm_EdcaTurboCheck23a ========================>\n"));
1711
1712 if (!(pDM_Odm->SupportAbility & ODM_MAC_EDCA_TURBO))
1713 return;
1714
1715 odm_EdcaTurboCheck23aCE23a(pDM_Odm);
1716 ODM_RT_TRACE(pDM_Odm, ODM_COMP_EDCA_TURBO, ODM_DBG_LOUD, ("<======================== odm_EdcaTurboCheck23a\n"));
1717
1718} /* odm_CheckEdcaTurbo */
1719
1720void odm_EdcaTurboCheck23aCE23a(struct dm_odm_t *pDM_Odm)
1721{
1722 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
1723
1724 u32 trafficIndex;
1725 u32 edca_param;
1726 u64 cur_tx_bytes = 0;
1727 u64 cur_rx_bytes = 0;
1728 u8 bbtchange = false;
1729 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1730 struct xmit_priv *pxmitpriv = &Adapter->xmitpriv;
1731 struct recv_priv *precvpriv = &Adapter->recvpriv;
1732 struct registry_priv *pregpriv = &Adapter->registrypriv;
1733 struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
1734 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1735
1736 if ((pregpriv->wifi_spec == 1))/* (pmlmeinfo->HT_enable == 0)) */
1737 goto dm_CheckEdcaTurbo_EXIT;
1738
1739 if (pmlmeinfo->assoc_AP_vendor >= HT_IOT_PEER_MAX)
1740 goto dm_CheckEdcaTurbo_EXIT;
1741
1742#ifdef CONFIG_8723AU_BT_COEXIST
1743 if (BT_DisableEDCATurbo(Adapter))
1744 goto dm_CheckEdcaTurbo_EXIT;
1745#endif
1746
1747 /* Check if the status needs to be changed. */
1748 if ((bbtchange) || (!precvpriv->bIsAnyNonBEPkts)) {
1749 cur_tx_bytes = pxmitpriv->tx_bytes - pxmitpriv->last_tx_bytes;
1750 cur_rx_bytes = precvpriv->rx_bytes - precvpriv->last_rx_bytes;
1751
1752 /* traffic, TX or RX */
1753 if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_RALINK) ||
1754 (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS)) {
1755 if (cur_tx_bytes > (cur_rx_bytes << 2)) {
1756 /* Uplink TP is present. */
1757 trafficIndex = UP_LINK;
1758 } else { /* Balance TP is present. */
1759 trafficIndex = DOWN_LINK;
1760 }
1761 } else {
1762 if (cur_rx_bytes > (cur_tx_bytes << 2)) {
1763 /* Downlink TP is present. */
1764 trafficIndex = DOWN_LINK;
1765 } else { /* Balance TP is present. */
1766 trafficIndex = UP_LINK;
1767 }
1768 }
1769
1770 if ((pDM_Odm->DM_EDCA_Table.prv_traffic_idx != trafficIndex) ||
1771 (!pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA)) {
1772 if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_CISCO) &&
1773 (pmlmeext->cur_wireless_mode & WIRELESS_11_24N))
1774 edca_param = EDCAParam[pmlmeinfo->assoc_AP_vendor][trafficIndex];
1775 else
1776 edca_param = EDCAParam[HT_IOT_PEER_UNKNOWN][trafficIndex];
1777 rtw_write32(Adapter, REG_EDCA_BE_PARAM, edca_param);
1778
1779 pDM_Odm->DM_EDCA_Table.prv_traffic_idx = trafficIndex;
1780 }
1781
1782 pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = true;
1783 } else {
1784 /* Turn Off EDCA turbo here. */
1785 /* Restore original EDCA according to the declaration of AP. */
1786 if (pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA) {
1787 rtw_write32(Adapter, REG_EDCA_BE_PARAM, pHalData->AcParam_BE);
1788 pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false;
1789 }
1790 }
1791
1792dm_CheckEdcaTurbo_EXIT:
1793 /* Set variables for next time. */
1794 precvpriv->bIsAnyNonBEPkts = false;
1795 pxmitpriv->last_tx_bytes = pxmitpriv->tx_bytes;
1796 precvpriv->last_rx_bytes = precvpriv->rx_bytes;
1797}
1798
1799u32 GetPSDData(struct dm_odm_t *pDM_Odm, unsigned int point, u8 initial_gain_psd)
1800{
1801 u32 psd_report;
1802
1803 /* Set DCO frequency index, offset = (40MHz/SamplePts)*point */
1804 ODM_SetBBReg(pDM_Odm, 0x808, 0x3FF, point);
1805
1806 /* Start PSD calculation, Reg808[22]= 0->1 */
1807 ODM_SetBBReg(pDM_Odm, 0x808, BIT22, 1);
1808 /* Need to wait for HW PSD report */
1809 udelay(30);
1810 ODM_SetBBReg(pDM_Odm, 0x808, BIT22, 0);
1811 /* Read PSD report, Reg8B4[15:0] */
1812 psd_report = ODM_GetBBReg(pDM_Odm, 0x8B4, bMaskDWord) & 0x0000FFFF;
1813
1814 psd_report = (u32)(ConvertTo_dB23a(psd_report))+(u32)(initial_gain_psd-0x1c);
1815
1816 return psd_report;
1817}
1818
1819u32
1820ConvertTo_dB23a(
1821 u32 Value)
1822{
1823 u8 i;
1824 u8 j;
1825 u32 dB;
1826
1827 Value = Value & 0xFFFF;
1828
1829 for (i = 0; i < 8; i++) {
1830 if (Value <= dB_Invert_Table[i][11])
1831 break;
1832 }
1833
1834 if (i >= 8)
1835 return 96; /* maximum 96 dB */
1836
1837 for (j = 0; j < 12; j++) {
1838 if (Value <= dB_Invert_Table[i][j])
1839 break;
1840 }
1841
1842 dB = i*12 + j + 1;
1843
1844 return dB;
1845}
1846
1847/* */
1848/* 2011/09/22 MH Add for 92D global spin lock utilization. */
1849/* */
1850void
1851odm_GlobalAdapterCheck(
1852 void
1853 )
1854{
1855} /* odm_GlobalAdapterCheck */
1856
1857/* */
1858/* Description: */
1859/*Set Single/Dual Antenna default setting for products that do not do detection in advance. */
1860/* */
1861/* Added by Joseph, 2012.03.22 */
1862/* */
1863void ODM_SingleDualAntennaDefaultSetting(struct dm_odm_t *pDM_Odm)
1864{
1865 struct sw_ant_sw *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
1866 pDM_SWAT_Table->ANTA_ON = true;
1867 pDM_SWAT_Table->ANTB_ON = true;
1868}
1869
1870/* 2 8723A ANT DETECT */
1871
1872static void odm_PHY_SaveAFERegisters(
1873 struct dm_odm_t *pDM_Odm,
1874 u32 *AFEReg,
1875 u32 *AFEBackup,
1876 u32 RegisterNum
1877 )
1878{
1879 u32 i;
1880
1881 /* RTPRINT(FINIT, INIT_IQK, ("Save ADDA parameters.\n")); */
1882 for (i = 0 ; i < RegisterNum ; i++)
1883 AFEBackup[i] = ODM_GetBBReg(pDM_Odm, AFEReg[i], bMaskDWord);
1884}
1885
1886static void odm_PHY_ReloadAFERegisters(struct dm_odm_t *pDM_Odm, u32 *AFEReg,
1887 u32 *AFEBackup, u32 RegiesterNum)
1888{
1889 u32 i;
1890
1891 for (i = 0 ; i < RegiesterNum; i++)
1892 ODM_SetBBReg(pDM_Odm, AFEReg[i], bMaskDWord, AFEBackup[i]);
1893}
1894
1895/* 2 8723A ANT DETECT */
1896/* Description: */
1897/* Implement IQK single tone for RF DPK loopback and BB PSD scanning. */
1898/* This function is cooperated with BB team Neil. */
1899bool ODM_SingleDualAntennaDetection(struct dm_odm_t *pDM_Odm, u8 mode)
1900{
1901 struct sw_ant_sw *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
1902 u32 CurrentChannel, RfLoopReg;
1903 u8 n;
1904 u32 Reg88c, Regc08, Reg874, Regc50;
1905 u8 initial_gain = 0x5a;
1906 u32 PSD_report_tmp;
1907 u32 AntA_report = 0x0, AntB_report = 0x0, AntO_report = 0x0;
1908 bool bResult = true;
1909 u32 AFE_Backup[16];
1910 u32 AFE_REG_8723A[16] = {
1911 rRx_Wait_CCA, rTx_CCK_RFON,
1912 rTx_CCK_BBON, rTx_OFDM_RFON,
1913 rTx_OFDM_BBON, rTx_To_Rx,
1914 rTx_To_Tx, rRx_CCK,
1915 rRx_OFDM, rRx_Wait_RIFS,
1916 rRx_TO_Rx, rStandby,
1917 rSleep, rPMPD_ANAEN,
1918 rFPGA0_XCD_SwitchControl, rBlue_Tooth};
1919
1920 if (!(pDM_Odm->SupportICType & (ODM_RTL8723A)))
1921 return bResult;
1922
1923 if (!(pDM_Odm->SupportAbility&ODM_BB_ANT_DIV))
1924 return bResult;
1925 /* 1 Backup Current RF/BB Settings */
1926
1927 CurrentChannel = ODM_GetRFReg(pDM_Odm, RF_PATH_A, ODM_CHANNEL, bRFRegOffsetMask);
1928 RfLoopReg = ODM_GetRFReg(pDM_Odm, RF_PATH_A, 0x00, bRFRegOffsetMask);
1929 ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, ODM_DPDT, Antenna_A); /* change to Antenna A */
1930 /* Step 1: USE IQK to transmitter single tone */
1931
1932 udelay(10);
1933
1934 /* Store A Path Register 88c, c08, 874, c50 */
1935 Reg88c = ODM_GetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord);
1936 Regc08 = ODM_GetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord);
1937 Reg874 = ODM_GetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord);
1938 Regc50 = ODM_GetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, bMaskDWord);
1939
1940 /* Store AFE Registers */
1941 odm_PHY_SaveAFERegisters(pDM_Odm, AFE_REG_8723A, AFE_Backup, 16);
1942
1943 /* Set PSD 128 pts */
1944 ODM_SetBBReg(pDM_Odm, rFPGA0_PSDFunction, BIT14|BIT15, 0x0); /* 128 pts */
1945
1946 /* To SET CH1 to do */
1947 ODM_SetRFReg(pDM_Odm, RF_PATH_A, ODM_CHANNEL, bRFRegOffsetMask, 0x01); /* Channel 1 */
1948
1949 /* AFE all on step */
1950 ODM_SetBBReg(pDM_Odm, rRx_Wait_CCA, bMaskDWord, 0x6FDB25A4);
1951 ODM_SetBBReg(pDM_Odm, rTx_CCK_RFON, bMaskDWord, 0x6FDB25A4);
1952 ODM_SetBBReg(pDM_Odm, rTx_CCK_BBON, bMaskDWord, 0x6FDB25A4);
1953 ODM_SetBBReg(pDM_Odm, rTx_OFDM_RFON, bMaskDWord, 0x6FDB25A4);
1954 ODM_SetBBReg(pDM_Odm, rTx_OFDM_BBON, bMaskDWord, 0x6FDB25A4);
1955 ODM_SetBBReg(pDM_Odm, rTx_To_Rx, bMaskDWord, 0x6FDB25A4);
1956 ODM_SetBBReg(pDM_Odm, rTx_To_Tx, bMaskDWord, 0x6FDB25A4);
1957 ODM_SetBBReg(pDM_Odm, rRx_CCK, bMaskDWord, 0x6FDB25A4);
1958 ODM_SetBBReg(pDM_Odm, rRx_OFDM, bMaskDWord, 0x6FDB25A4);
1959 ODM_SetBBReg(pDM_Odm, rRx_Wait_RIFS, bMaskDWord, 0x6FDB25A4);
1960 ODM_SetBBReg(pDM_Odm, rRx_TO_Rx, bMaskDWord, 0x6FDB25A4);
1961 ODM_SetBBReg(pDM_Odm, rStandby, bMaskDWord, 0x6FDB25A4);
1962 ODM_SetBBReg(pDM_Odm, rSleep, bMaskDWord, 0x6FDB25A4);
1963 ODM_SetBBReg(pDM_Odm, rPMPD_ANAEN, bMaskDWord, 0x6FDB25A4);
1964 ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_SwitchControl, bMaskDWord, 0x6FDB25A4);
1965 ODM_SetBBReg(pDM_Odm, rBlue_Tooth, bMaskDWord, 0x6FDB25A4);
1966
1967 /* 3 wire Disable */
1968 ODM_SetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord, 0xCCF000C0);
1969
1970 /* BB IQK Setting */
1971 ODM_SetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord, 0x000800E4);
1972 ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22208000);
1973
1974 /* IQK setting tone@ 4.34Mhz */
1975 ODM_SetBBReg(pDM_Odm, rTx_IQK_Tone_A, bMaskDWord, 0x10008C1C);
1976 ODM_SetBBReg(pDM_Odm, rTx_IQK, bMaskDWord, 0x01007c00);
1977
1978 /* Page B init */
1979 ODM_SetBBReg(pDM_Odm, rConfig_AntA, bMaskDWord, 0x00080000);
1980 ODM_SetBBReg(pDM_Odm, rConfig_AntA, bMaskDWord, 0x0f600000);
1981 ODM_SetBBReg(pDM_Odm, rRx_IQK, bMaskDWord, 0x01004800);
1982 ODM_SetBBReg(pDM_Odm, rRx_IQK_Tone_A, bMaskDWord, 0x10008c1f);
1983 ODM_SetBBReg(pDM_Odm, rTx_IQK_PI_A, bMaskDWord, 0x82150008);
1984 ODM_SetBBReg(pDM_Odm, rRx_IQK_PI_A, bMaskDWord, 0x28150008);
1985 ODM_SetBBReg(pDM_Odm, rIQK_AGC_Rsp, bMaskDWord, 0x001028d0);
1986
1987 /* RF loop Setting */
1988 ODM_SetRFReg(pDM_Odm, RF_PATH_A, 0x0, 0xFFFFF, 0x50008);
1989
1990 /* IQK Single tone start */
1991 ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskDWord, 0x80800000);
1992 ODM_SetBBReg(pDM_Odm, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
1993 udelay(1000);
1994 PSD_report_tmp = 0x0;
1995
1996 for (n = 0; n < 2; n++) {
1997 PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain);
1998 if (PSD_report_tmp > AntA_report)
1999 AntA_report = PSD_report_tmp;
2000 }
2001
2002 PSD_report_tmp = 0x0;
2003
2004 ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, 0x300, Antenna_B); /* change to Antenna B */
2005 udelay(10);
2006
2007 for (n = 0; n < 2; n++) {
2008 PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain);
2009 if (PSD_report_tmp > AntB_report)
2010 AntB_report = PSD_report_tmp;
2011 }
2012
2013 /* change to open case */
2014 ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, 0x300, 0); /* change to Ant A and B all open case */
2015 udelay(10);
2016
2017 for (n = 0; n < 2; n++) {
2018 PSD_report_tmp = GetPSDData(pDM_Odm, 14, initial_gain);
2019 if (PSD_report_tmp > AntO_report)
2020 AntO_report = PSD_report_tmp;
2021 }
2022
2023 /* Close IQK Single Tone function */
2024 ODM_SetBBReg(pDM_Odm, rFPGA0_IQK, bMaskDWord, 0x00000000);
2025 PSD_report_tmp = 0x0;
2026
2027 /* 1 Return to antanna A */
2028 ODM_SetBBReg(pDM_Odm, rFPGA0_XA_RFInterfaceOE, 0x300, Antenna_A);
2029 ODM_SetBBReg(pDM_Odm, rFPGA0_AnalogParameter4, bMaskDWord, Reg88c);
2030 ODM_SetBBReg(pDM_Odm, rOFDM0_TRMuxPar, bMaskDWord, Regc08);
2031 ODM_SetBBReg(pDM_Odm, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, Reg874);
2032 ODM_SetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, 0x7F, 0x40);
2033 ODM_SetBBReg(pDM_Odm, rOFDM0_XAAGCCore1, bMaskDWord, Regc50);
2034 ODM_SetRFReg(pDM_Odm, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, CurrentChannel);
2035 ODM_SetRFReg(pDM_Odm, RF_PATH_A, 0x00, bRFRegOffsetMask, RfLoopReg);
2036
2037 /* Reload AFE Registers */
2038 odm_PHY_ReloadAFERegisters(pDM_Odm, AFE_REG_8723A, AFE_Backup, 16);
2039
2040 ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("psd_report_A[%d]= %d \n", 2416, AntA_report));
2041 ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("psd_report_B[%d]= %d \n", 2416, AntB_report));
2042 ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("psd_report_O[%d]= %d \n", 2416, AntO_report));
2043
2044 /* 2 Test Ant B based on Ant A is ON */
2045 if (mode == ANTTESTB) {
2046 if (AntA_report >= 100) {
2047 if (AntB_report > (AntA_report+1)) {
2048 pDM_SWAT_Table->ANTB_ON = false;
2049 ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Single Antenna A\n"));
2050 } else {
2051 pDM_SWAT_Table->ANTB_ON = true;
2052 ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Dual Antenna is A and B\n"));
2053 }
2054 } else {
2055 ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Need to check again\n"));
2056 pDM_SWAT_Table->ANTB_ON = false; /* Set Antenna B off as default */
2057 bResult = false;
2058 }
2059 } else if (mode == ANTTESTALL) {
2060 /* 2 Test Ant A and B based on DPDT Open */
2061 if ((AntO_report >= 100) & (AntO_report < 118)) {
2062 if (AntA_report > (AntO_report+1)) {
2063 pDM_SWAT_Table->ANTA_ON = false;
2064 ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Ant A is OFF"));
2065 } else {
2066 pDM_SWAT_Table->ANTA_ON = true;
2067 ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Ant A is ON"));
2068 }
2069
2070 if (AntB_report > (AntO_report+2)) {
2071 pDM_SWAT_Table->ANTB_ON = false;
2072 ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Ant B is OFF"));
2073 } else {
2074 pDM_SWAT_Table->ANTB_ON = true;
2075 ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("Ant B is ON"));
2076 }
2077 }
2078 } else {
2079 ODM_RT_TRACE(pDM_Odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD, ("ODM_SingleDualAntennaDetection(): Need to check again\n"));
2080 pDM_SWAT_Table->ANTA_ON = true; /* Set Antenna A on as default */
2081 pDM_SWAT_Table->ANTB_ON = false; /* Set Antenna B off as default */
2082 bResult = false;
2083 }
2084 return bResult;
2085}
2086
2087/* Justin: According to the current RRSI to adjust Response Frame TX power, 2012/11/05 */
2088void odm_dtc(struct dm_odm_t *pDM_Odm)
2089{
2090}
diff --git a/drivers/staging/rtl8723au/hal/odm_HWConfig.c b/drivers/staging/rtl8723au/hal/odm_HWConfig.c
new file mode 100644
index 000000000000..72441709697e
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/odm_HWConfig.c
@@ -0,0 +1,481 @@
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 ******************************************************************************/
15
16/* */
17/* include files */
18/* */
19
20#include "odm_precomp.h"
21
22#define READ_AND_CONFIG READ_AND_CONFIG_MP
23
24#define READ_AND_CONFIG_MP(ic, txt) (ODM_ReadAndConfig##txt##ic(pDM_Odm))
25#define READ_AND_CONFIG_TC(ic, txt) (ODM_ReadAndConfig_TC##txt##ic(pDM_Odm))
26
27static u8 odm_QueryRxPwrPercentage(s8 AntPower)
28{
29 if ((AntPower <= -100) || (AntPower >= 20))
30 return 0;
31 else if (AntPower >= 0)
32 return 100;
33 else
34 return 100 + AntPower;
35}
36
37static s32 odm_SignalScaleMapping_92CSeries(struct dm_odm_t *pDM_Odm, s32 CurrSig)
38{
39 s32 RetSig = 0;
40
41 if ((pDM_Odm->SupportInterface == ODM_ITRF_USB) || (pDM_Odm->SupportInterface == ODM_ITRF_SDIO)) {
42 if (CurrSig >= 51 && CurrSig <= 100)
43 RetSig = 100;
44 else if (CurrSig >= 41 && CurrSig <= 50)
45 RetSig = 80 + ((CurrSig - 40)*2);
46 else if (CurrSig >= 31 && CurrSig <= 40)
47 RetSig = 66 + (CurrSig - 30);
48 else if (CurrSig >= 21 && CurrSig <= 30)
49 RetSig = 54 + (CurrSig - 20);
50 else if (CurrSig >= 10 && CurrSig <= 20)
51 RetSig = 42 + (((CurrSig - 10) * 2) / 3);
52 else if (CurrSig >= 5 && CurrSig <= 9)
53 RetSig = 22 + (((CurrSig - 5) * 3) / 2);
54 else if (CurrSig >= 1 && CurrSig <= 4)
55 RetSig = 6 + (((CurrSig - 1) * 3) / 2);
56 else
57 RetSig = CurrSig;
58 }
59 return RetSig;
60}
61
62static s32 odm_SignalScaleMapping(struct dm_odm_t *pDM_Odm, s32 CurrSig)
63{
64 return odm_SignalScaleMapping_92CSeries(pDM_Odm, CurrSig);
65}
66
67static u8
68odm_EVMdbToPercentage(
69 s8 Value
70 )
71{
72 /* */
73 /* -33dB~0dB to 0%~99% */
74 /* */
75 s8 ret_val;
76
77 ret_val = Value;
78
79 if (ret_val >= 0)
80 ret_val = 0;
81 if (ret_val <= -33)
82 ret_val = -33;
83
84 ret_val = 0 - ret_val;
85 ret_val *= 3;
86
87 if (ret_val == 99)
88 ret_val = 100;
89
90 return ret_val;
91}
92
93static void odm_RxPhyStatus92CSeries_Parsing(struct dm_odm_t *pDM_Odm,
94 struct odm_phy_info *pPhyInfo,
95 u8 *pPhyStatus,
96 struct odm_packet_info *pPktinfo)
97{
98 struct phy_status_rpt *pPhyStaRpt = (struct phy_status_rpt *)pPhyStatus;
99 u8 i, Max_spatial_stream;
100 s8 rx_pwr[4], rx_pwr_all = 0;
101 u8 EVM, PWDB_ALL = 0, PWDB_ALL_BT;
102 u8 RSSI, total_rssi = 0;
103 u8 isCCKrate = 0;
104 u8 rf_rx_num = 0;
105 u8 cck_highpwr = 0;
106
107 isCCKrate = (pPktinfo->Rate <= DESC92C_RATE11M) ? true : false;
108 pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = -1;
109 pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1;
110
111 if (isCCKrate) {
112 u8 report;
113 u8 cck_agc_rpt;
114
115 pDM_Odm->PhyDbgInfo.NumQryPhyStatusCCK++;
116 /* (1)Hardware does not provide RSSI for CCK */
117 /* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */
118
119 cck_highpwr = pDM_Odm->bCckHighPower;
120
121 cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a ;
122
123 /* The RSSI formula should be modified according to the gain table */
124 if (!cck_highpwr) {
125 report = (cck_agc_rpt & 0xc0)>>6;
126 switch (report) {
127 /* Modify the RF RNA gain value to -40, -20, -2, 14 by Jenyu's suggestion */
128 /* Note: different RF with the different RNA gain. */
129 case 0x3:
130 rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
131 break;
132 case 0x2:
133 rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
134 break;
135 case 0x1:
136 rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
137 break;
138 case 0x0:
139 rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
140 break;
141 }
142 } else {
143 report = (cck_agc_rpt & 0x60)>>5;
144 switch (report) {
145 case 0x3:
146 rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f)<<1) ;
147 break;
148 case 0x2:
149 rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f)<<1);
150 break;
151 case 0x1:
152 rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f)<<1) ;
153 break;
154 case 0x0:
155 rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f)<<1) ;
156 break;
157 }
158 }
159
160 PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all);
161
162 /* Modification for ext-LNA board */
163 if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) {
164 if ((cck_agc_rpt>>7) == 0) {
165 PWDB_ALL = (PWDB_ALL > 94) ? 100 : (PWDB_ALL+6);
166 } else {
167 if (PWDB_ALL > 38)
168 PWDB_ALL -= 16;
169 else
170 PWDB_ALL = (PWDB_ALL <= 16) ? (PWDB_ALL>>2) : (PWDB_ALL-12);
171 }
172
173 /* CCK modification */
174 if (PWDB_ALL > 25 && PWDB_ALL <= 60)
175 PWDB_ALL += 6;
176 } else { /* Modification for int-LNA board */
177 if (PWDB_ALL > 99)
178 PWDB_ALL -= 8;
179 else if (PWDB_ALL > 50 && PWDB_ALL <= 68)
180 PWDB_ALL += 4;
181 }
182 pPhyInfo->RxPWDBAll = PWDB_ALL;
183 pPhyInfo->BTRxRSSIPercentage = PWDB_ALL;
184 pPhyInfo->RecvSignalPower = rx_pwr_all;
185 /* (3) Get Signal Quality (EVM) */
186 if (pPktinfo->bPacketMatchBSSID) {
187 u8 SQ, SQ_rpt;
188
189 SQ_rpt = pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all;
190
191 if (SQ_rpt > 64)
192 SQ = 0;
193 else if (SQ_rpt < 20)
194 SQ = 100;
195 else
196 SQ = ((64-SQ_rpt) * 100) / 44;
197
198 pPhyInfo->SignalQuality = SQ;
199 pPhyInfo->RxMIMOSignalQuality[RF_PATH_A] = SQ;
200 pPhyInfo->RxMIMOSignalQuality[RF_PATH_B] = -1;
201 }
202 } else { /* is OFDM rate */
203 pDM_Odm->PhyDbgInfo.NumQryPhyStatusOFDM++;
204
205 /* (1)Get RSSI for HT rate */
206
207 for (i = RF_PATH_A; i < RF_PATH_MAX; i++) {
208 /* 2008/01/30 MH we will judge RF RX path now. */
209 if (pDM_Odm->RFPathRxEnable & BIT(i))
210 rf_rx_num++;
211
212 rx_pwr[i] = ((pPhyStaRpt->path_agc[i].gain & 0x3F)*2) - 110;
213
214 pPhyInfo->RxPwr[i] = rx_pwr[i];
215
216 /* Translate DBM to percentage. */
217 RSSI = odm_QueryRxPwrPercentage(rx_pwr[i]);
218 total_rssi += RSSI;
219
220 /* Modification for ext-LNA board */
221 if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) {
222 if ((pPhyStaRpt->path_agc[i].trsw) == 1)
223 RSSI = (RSSI > 94) ? 100 : (RSSI+6);
224 else
225 RSSI = (RSSI <= 16) ? (RSSI>>3) : (RSSI-16);
226
227 if ((RSSI <= 34) && (RSSI >= 4))
228 RSSI -= 4;
229 }
230
231 pPhyInfo->RxMIMOSignalStrength[i] = (u8) RSSI;
232
233 /* Get Rx snr value in DB */
234 pPhyInfo->RxSNR[i] = pDM_Odm->PhyDbgInfo.RxSNRdB[i] = (s32)(pPhyStaRpt->path_rxsnr[i]/2);
235 }
236
237 /* (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive) */
238 rx_pwr_all = (((pPhyStaRpt->cck_sig_qual_ofdm_pwdb_all) >> 1) & 0x7f)-110;
239
240 PWDB_ALL = odm_QueryRxPwrPercentage(rx_pwr_all);
241 PWDB_ALL_BT = PWDB_ALL;
242
243 pPhyInfo->RxPWDBAll = PWDB_ALL;
244 pPhyInfo->BTRxRSSIPercentage = PWDB_ALL_BT;
245 pPhyInfo->RxPower = rx_pwr_all;
246 pPhyInfo->RecvSignalPower = rx_pwr_all;
247
248 /* (3)EVM of HT rate */
249 if (pPktinfo->Rate >= DESC92C_RATEMCS8 && pPktinfo->Rate <= DESC92C_RATEMCS15)
250 Max_spatial_stream = 2; /* both spatial stream make sense */
251 else
252 Max_spatial_stream = 1; /* only spatial stream 1 makes sense */
253
254 for (i = 0; i < Max_spatial_stream; i++) {
255 /* Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment */
256 /* fill most significant bit to "zero" when doing shifting operation which may change a negative */
257 /* value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore. */
258 EVM = odm_EVMdbToPercentage((pPhyStaRpt->stream_rxevm[i])); /* dbm */
259
260 if (pPktinfo->bPacketMatchBSSID) {
261 if (i == RF_PATH_A) {
262 /* Fill value in RFD, Get the first spatial stream only */
263 pPhyInfo->SignalQuality = (u8)(EVM & 0xff);
264 }
265 pPhyInfo->RxMIMOSignalQuality[i] = (u8)(EVM & 0xff);
266 }
267 }
268 }
269 /* UI BSS List signal strength(in percentage), make it good looking, from 0~100. */
270 /* It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp(). */
271 if (isCCKrate) {
272 pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(pDM_Odm, PWDB_ALL));/* PWDB_ALL; */
273 } else {
274 if (rf_rx_num != 0)
275 pPhyInfo->SignalStrength = (u8)(odm_SignalScaleMapping(pDM_Odm, total_rssi /= rf_rx_num));
276 }
277}
278
279void odm_Init_RSSIForDM23a(struct dm_odm_t *pDM_Odm)
280{
281}
282
283static void odm_Process_RSSIForDM(struct dm_odm_t *pDM_Odm,
284 struct odm_phy_info *pPhyInfo,
285 struct odm_packet_info *pPktinfo)
286{
287 s32 UndecoratedSmoothedPWDB, UndecoratedSmoothedCCK;
288 s32 UndecoratedSmoothedOFDM, RSSI_Ave;
289 u8 isCCKrate = 0;
290 u8 RSSI_max, RSSI_min, i;
291 u32 OFDM_pkt = 0;
292 u32 Weighting = 0;
293 struct sta_info *pEntry;
294
295 if (pPktinfo->StationID == 0xFF)
296 return;
297
298 pEntry = pDM_Odm->pODM_StaInfo[pPktinfo->StationID];
299 if (!IS_STA_VALID(pEntry))
300 return;
301 if ((!pPktinfo->bPacketMatchBSSID))
302 return;
303
304 isCCKrate = (pPktinfo->Rate <= DESC92C_RATE11M) ? true : false;
305
306 /* Smart Antenna Debug Message------------------*/
307
308 UndecoratedSmoothedCCK = pEntry->rssi_stat.UndecoratedSmoothedCCK;
309 UndecoratedSmoothedOFDM = pEntry->rssi_stat.UndecoratedSmoothedOFDM;
310 UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB;
311
312 if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon) {
313 if (!isCCKrate) { /* ofdm rate */
314 if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_B] == 0) {
315 RSSI_Ave = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
316 } else {
317 if (pPhyInfo->RxMIMOSignalStrength[RF_PATH_A] > pPhyInfo->RxMIMOSignalStrength[RF_PATH_B]) {
318 RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
319 RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B];
320 } else {
321 RSSI_max = pPhyInfo->RxMIMOSignalStrength[RF_PATH_B];
322 RSSI_min = pPhyInfo->RxMIMOSignalStrength[RF_PATH_A];
323 }
324 if ((RSSI_max - RSSI_min) < 3)
325 RSSI_Ave = RSSI_max;
326 else if ((RSSI_max - RSSI_min) < 6)
327 RSSI_Ave = RSSI_max - 1;
328 else if ((RSSI_max - RSSI_min) < 10)
329 RSSI_Ave = RSSI_max - 2;
330 else
331 RSSI_Ave = RSSI_max - 3;
332 }
333
334 /* 1 Process OFDM RSSI */
335 if (UndecoratedSmoothedOFDM <= 0) {
336 /* initialize */
337 UndecoratedSmoothedOFDM = pPhyInfo->RxPWDBAll;
338 } else {
339 if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedOFDM) {
340 UndecoratedSmoothedOFDM =
341 (((UndecoratedSmoothedOFDM)*(Rx_Smooth_Factor-1)) +
342 (RSSI_Ave)) / (Rx_Smooth_Factor);
343 UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM + 1;
344 } else {
345 UndecoratedSmoothedOFDM =
346 (((UndecoratedSmoothedOFDM)*(Rx_Smooth_Factor-1)) +
347 (RSSI_Ave)) / (Rx_Smooth_Factor);
348 }
349 }
350 pEntry->rssi_stat.PacketMap = (pEntry->rssi_stat.PacketMap<<1) | BIT0;
351 } else {
352 RSSI_Ave = pPhyInfo->RxPWDBAll;
353
354 /* 1 Process CCK RSSI */
355 if (UndecoratedSmoothedCCK <= 0) {
356 /* initialize */
357 UndecoratedSmoothedCCK = pPhyInfo->RxPWDBAll;
358 } else {
359 if (pPhyInfo->RxPWDBAll > (u32)UndecoratedSmoothedCCK) {
360 UndecoratedSmoothedCCK =
361 (((UndecoratedSmoothedCCK)*(Rx_Smooth_Factor-1)) +
362 (pPhyInfo->RxPWDBAll)) / (Rx_Smooth_Factor);
363 UndecoratedSmoothedCCK = UndecoratedSmoothedCCK + 1;
364 } else {
365 UndecoratedSmoothedCCK =
366 (((UndecoratedSmoothedCCK)*(Rx_Smooth_Factor-1)) +
367 (pPhyInfo->RxPWDBAll)) / (Rx_Smooth_Factor);
368 }
369 }
370 pEntry->rssi_stat.PacketMap = pEntry->rssi_stat.PacketMap<<1;
371 }
372
373 /* 2011.07.28 LukeLee: modified to prevent unstable CCK RSSI */
374 if (pEntry->rssi_stat.ValidBit >= 64)
375 pEntry->rssi_stat.ValidBit = 64;
376 else
377 pEntry->rssi_stat.ValidBit++;
378
379 for (i = 0; i < pEntry->rssi_stat.ValidBit; i++)
380 OFDM_pkt += (u8)(pEntry->rssi_stat.PacketMap>>i)&BIT0;
381
382 if (pEntry->rssi_stat.ValidBit == 64) {
383 Weighting = ((OFDM_pkt<<4) > 64)?64:(OFDM_pkt<<4);
384 UndecoratedSmoothedPWDB = (Weighting*UndecoratedSmoothedOFDM+(64-Weighting)*UndecoratedSmoothedCCK)>>6;
385 } else {
386 if (pEntry->rssi_stat.ValidBit != 0)
387 UndecoratedSmoothedPWDB = (OFDM_pkt*UndecoratedSmoothedOFDM+(pEntry->rssi_stat.ValidBit-OFDM_pkt)*UndecoratedSmoothedCCK)/pEntry->rssi_stat.ValidBit;
388 else
389 UndecoratedSmoothedPWDB = 0;
390 }
391 pEntry->rssi_stat.UndecoratedSmoothedCCK = UndecoratedSmoothedCCK;
392 pEntry->rssi_stat.UndecoratedSmoothedOFDM = UndecoratedSmoothedOFDM;
393 pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB;
394 }
395}
396
397/* Endianness before calling this API */
398static void ODM_PhyStatusQuery23a_92CSeries(struct dm_odm_t *pDM_Odm,
399 struct odm_phy_info *pPhyInfo,
400 u8 *pPhyStatus,
401 struct odm_packet_info *pPktinfo)
402{
403 odm_RxPhyStatus92CSeries_Parsing(pDM_Odm, pPhyInfo,
404 pPhyStatus, pPktinfo);
405 if (pDM_Odm->RSSI_test) {
406 /* Select the packets to do RSSI checking for antenna switching. */
407 if (pPktinfo->bPacketToSelf || pPktinfo->bPacketBeacon)
408 ODM_SwAntDivChkPerPktRssi(pDM_Odm, pPktinfo->StationID, pPhyInfo);
409 } else {
410 odm_Process_RSSIForDM(pDM_Odm, pPhyInfo, pPktinfo);
411 }
412}
413
414void ODM_PhyStatusQuery23a(struct dm_odm_t *pDM_Odm, struct odm_phy_info *pPhyInfo,
415 u8 *pPhyStatus, struct odm_packet_info *pPktinfo)
416{
417 ODM_PhyStatusQuery23a_92CSeries(pDM_Odm, pPhyInfo, pPhyStatus, pPktinfo);
418}
419
420/* For future use. */
421void ODM_MacStatusQuery23a(struct dm_odm_t *pDM_Odm, u8 *pMacStatus, u8 MacID,
422 bool bPacketMatchBSSID, bool bPacketToSelf,
423 bool bPacketBeacon)
424{
425 /* 2011/10/19 Driver team will handle in the future. */
426
427}
428
429enum hal_status
430ODM_ConfigRFWithHeaderFile23a(
431 struct dm_odm_t *pDM_Odm,
432 enum RF_RADIO_PATH Content,
433 enum RF_RADIO_PATH eRFPath
434 )
435{
436 ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
437 ("===>ODM_ConfigRFWithHeaderFile23a\n"));
438 if (pDM_Odm->SupportICType == ODM_RTL8723A) {
439 if (eRFPath == RF_PATH_A)
440 READ_AND_CONFIG_MP(8723A, _RadioA_1T_);
441
442 ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
443 (" ===> ODM_ConfigRFWithHeaderFile23a() Radio_A:Rtl8723RadioA_1TArray\n"));
444 ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
445 (" ===> ODM_ConfigRFWithHeaderFile23a() Radio_B:Rtl8723RadioB_1TArray\n"));
446 }
447 ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_TRACE,
448 ("ODM_ConfigRFWithHeaderFile23a: Radio No %x\n", eRFPath));
449 return HAL_STATUS_SUCCESS;
450}
451
452enum hal_status
453ODM_ConfigBBWithHeaderFile23a(
454 struct dm_odm_t *pDM_Odm,
455 enum odm_bb_config_type ConfigType
456 )
457{
458 if (pDM_Odm->SupportICType == ODM_RTL8723A) {
459 if (ConfigType == CONFIG_BB_PHY_REG)
460 READ_AND_CONFIG_MP(8723A, _PHY_REG_1T_);
461 else if (ConfigType == CONFIG_BB_AGC_TAB)
462 READ_AND_CONFIG_MP(8723A, _AGC_TAB_1T_);
463 ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
464 (" ===> phy_ConfigBBWithHeaderFile() phy:Rtl8723AGCTAB_1TArray\n"));
465 ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
466 (" ===> phy_ConfigBBWithHeaderFile() agc:Rtl8723PHY_REG_1TArray\n"));
467 }
468 return HAL_STATUS_SUCCESS;
469}
470
471enum hal_status
472ODM_ConfigMACWithHeaderFile23a(
473 struct dm_odm_t *pDM_Odm
474 )
475{
476 u8 result = HAL_STATUS_SUCCESS;
477
478 if (pDM_Odm->SupportICType == ODM_RTL8723A)
479 READ_AND_CONFIG_MP(8723A, _MAC_REG_);
480 return result;
481}
diff --git a/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c b/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c
new file mode 100644
index 000000000000..d076e14f36b9
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c
@@ -0,0 +1,162 @@
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 ******************************************************************************/
15
16#include "odm_precomp.h"
17
18void
19odm_ConfigRFReg_8723A(
20 struct dm_odm_t *pDM_Odm,
21 u32 Addr,
22 u32 Data,
23 enum RF_RADIO_PATH RF_PATH,
24 u32 RegAddr
25 )
26{
27 if (Addr == 0xfe) {
28 msleep(50);
29 } else if (Addr == 0xfd) {
30 mdelay(5);
31 } else if (Addr == 0xfc) {
32 mdelay(1);
33 } else if (Addr == 0xfb) {
34 udelay(50);
35 } else if (Addr == 0xfa) {
36 udelay(5);
37 } else if (Addr == 0xf9) {
38 udelay(1);
39 } else {
40 ODM_SetRFReg(pDM_Odm, RF_PATH, RegAddr, bRFRegOffsetMask, Data);
41 /* Add 1us delay between BB/RF register setting. */
42 udelay(1);
43 }
44}
45
46void odm_ConfigRF_RadioA_8723A(struct dm_odm_t *pDM_Odm,
47 u32 Addr,
48 u32 Data
49 )
50{
51 u32 content = 0x1000; /* RF_Content: radioa_txt */
52 u32 maskforPhySet = (u32)(content&0xE000);
53
54 odm_ConfigRFReg_8723A(pDM_Odm, Addr, Data, RF_PATH_A,
55 Addr|maskforPhySet);
56 ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
57 ("===> ODM_ConfigRFWithHeaderFile23a: [RadioA] %08X %08X\n",
58 Addr, Data));
59}
60
61void odm_ConfigRF_RadioB_8723A(struct dm_odm_t *pDM_Odm,
62 u32 Addr,
63 u32 Data
64 )
65{
66 u32 content = 0x1001; /* RF_Content: radiob_txt */
67 u32 maskforPhySet = (u32)(content&0xE000);
68
69 odm_ConfigRFReg_8723A(pDM_Odm, Addr, Data, RF_PATH_B,
70 Addr|maskforPhySet);
71 ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
72 ("===> ODM_ConfigRFWithHeaderFile23a: [RadioB] %08X %08X\n",
73 Addr, Data));
74}
75
76void odm_ConfigMAC_8723A(struct dm_odm_t *pDM_Odm,
77 u32 Addr,
78 u8 Data
79 )
80{
81 ODM_Write1Byte(pDM_Odm, Addr, Data);
82 ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
83 ("===> ODM_ConfigMACWithHeaderFile23a: [MAC_REG] %08X %08X\n",
84 Addr, Data));
85}
86
87void
88odm_ConfigBB_AGC_8723A(
89 struct dm_odm_t *pDM_Odm,
90 u32 Addr,
91 u32 Bitmask,
92 u32 Data
93 )
94{
95 ODM_SetBBReg(pDM_Odm, Addr, Bitmask, Data);
96 /* Add 1us delay between BB/RF register setting. */
97 udelay(1);
98
99 ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
100 ("===> ODM_ConfigBBWithHeaderFile23a: [AGC_TAB] %08X %08X\n",
101 Addr, Data));
102}
103
104void
105odm_ConfigBB_PHY_REG_PG_8723A(
106 struct dm_odm_t *pDM_Odm,
107 u32 Addr,
108 u32 Bitmask,
109 u32 Data
110 )
111{
112 if (Addr == 0xfe)
113 msleep(50);
114 else if (Addr == 0xfd)
115 mdelay(5);
116 else if (Addr == 0xfc)
117 mdelay(1);
118 else if (Addr == 0xfb)
119 udelay(50);
120 else if (Addr == 0xfa)
121 udelay(5);
122 else if (Addr == 0xf9)
123 udelay(1);
124 /* TODO: ODM_StorePwrIndexDiffRateOffset(...) */
125 /* storePwrIndexDiffRateOffset(Adapter, Addr, Bitmask, Data); */
126
127 ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
128 ("===> ODM_ConfigBBWithHeaderFile23a: [PHY_REG] %08X %08X %08X\n",
129 Addr, Bitmask, Data));
130}
131
132void
133odm_ConfigBB_PHY_8723A(
134 struct dm_odm_t *pDM_Odm,
135 u32 Addr,
136 u32 Bitmask,
137 u32 Data
138 )
139{
140 if (Addr == 0xfe)
141 msleep(50);
142 else if (Addr == 0xfd)
143 mdelay(5);
144 else if (Addr == 0xfc)
145 mdelay(1);
146 else if (Addr == 0xfb)
147 udelay(50);
148 else if (Addr == 0xfa)
149 udelay(5);
150 else if (Addr == 0xf9)
151 udelay(1);
152 else if (Addr == 0xa24)
153 pDM_Odm->RFCalibrateInfo.RegA24 = Data;
154 ODM_SetBBReg(pDM_Odm, Addr, Bitmask, Data);
155
156 /* Add 1us delay between BB/RF register setting. */
157 udelay(1);
158
159 ODM_RT_TRACE(pDM_Odm, ODM_COMP_INIT, ODM_DBG_LOUD,
160 ("===> ODM_ConfigBBWithHeaderFile23a: [PHY_REG] %08X %08X\n",
161 Addr, Data));
162}
diff --git a/drivers/staging/rtl8723au/hal/odm_debug.c b/drivers/staging/rtl8723au/hal/odm_debug.c
new file mode 100644
index 000000000000..c912ab89bc3e
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/odm_debug.c
@@ -0,0 +1,24 @@
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 ******************************************************************************/
15
16#include "odm_precomp.h"
17
18void ODM_InitDebugSetting23a(struct dm_odm_t *pDM_Odm)
19{
20 pDM_Odm->DebugLevel = ODM_DBG_TRACE;
21 pDM_Odm->DebugComponents = 0;
22}
23
24u32 GlobalDebugLevel23A;
diff --git a/drivers/staging/rtl8723au/hal/odm_interface.c b/drivers/staging/rtl8723au/hal/odm_interface.c
new file mode 100644
index 000000000000..bef1269749d0
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/odm_interface.c
@@ -0,0 +1,236 @@
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 ******************************************************************************/
15
16/* */
17/* include files */
18/* */
19
20#include "odm_precomp.h"
21/* */
22/* ODM IO Relative API. */
23/* */
24
25u8 ODM_Read1Byte(struct dm_odm_t *pDM_Odm,
26 u32 RegAddr
27 )
28{
29 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
30
31 return rtw_read8(Adapter, RegAddr);
32}
33
34u16 ODM_Read2Byte(struct dm_odm_t *pDM_Odm,
35 u32 RegAddr
36 )
37{
38 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
39
40 return rtw_read16(Adapter, RegAddr);
41}
42
43u32 ODM_Read4Byte(struct dm_odm_t *pDM_Odm,
44 u32 RegAddr
45 )
46{
47 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
48
49 return rtw_read32(Adapter, RegAddr);
50}
51
52void ODM_Write1Byte(
53 struct dm_odm_t *pDM_Odm,
54 u32 RegAddr,
55 u8 Data
56 )
57{
58 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
59
60 rtw_write8(Adapter, RegAddr, Data);
61}
62
63void ODM_Write2Byte(
64 struct dm_odm_t *pDM_Odm,
65 u32 RegAddr,
66 u16 Data
67 )
68{
69 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
70
71 rtw_write16(Adapter, RegAddr, Data);
72}
73
74void ODM_Write4Byte(
75 struct dm_odm_t *pDM_Odm,
76 u32 RegAddr,
77 u32 Data
78 )
79{
80 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
81
82 rtw_write32(Adapter, RegAddr, Data);
83
84}
85
86void ODM_SetMACReg(
87 struct dm_odm_t *pDM_Odm,
88 u32 RegAddr,
89 u32 BitMask,
90 u32 Data
91 )
92{
93 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
94
95 PHY_SetBBReg(Adapter, RegAddr, BitMask, Data);
96}
97
98u32 ODM_GetMACReg(
99 struct dm_odm_t *pDM_Odm,
100 u32 RegAddr,
101 u32 BitMask
102 )
103{
104 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
105
106 return PHY_QueryBBReg(Adapter, RegAddr, BitMask);
107}
108
109void ODM_SetBBReg(
110 struct dm_odm_t *pDM_Odm,
111 u32 RegAddr,
112 u32 BitMask,
113 u32 Data
114 )
115{
116 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
117
118 PHY_SetBBReg(Adapter, RegAddr, BitMask, Data);
119}
120
121u32 ODM_GetBBReg(
122 struct dm_odm_t *pDM_Odm,
123 u32 RegAddr,
124 u32 BitMask
125 )
126{
127 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
128
129 return PHY_QueryBBReg(Adapter, RegAddr, BitMask);
130}
131
132void ODM_SetRFReg(
133 struct dm_odm_t *pDM_Odm,
134 enum RF_RADIO_PATH eRFPath,
135 u32 RegAddr,
136 u32 BitMask,
137 u32 Data
138 )
139{
140 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
141
142 PHY_SetRFReg(Adapter, eRFPath, RegAddr, BitMask, Data);
143}
144
145u32 ODM_GetRFReg(
146 struct dm_odm_t *pDM_Odm,
147 enum RF_RADIO_PATH eRFPath,
148 u32 RegAddr,
149 u32 BitMask
150 )
151{
152 struct rtw_adapter *Adapter = pDM_Odm->Adapter;
153
154 return PHY_QueryRFReg(Adapter, eRFPath, RegAddr, BitMask);
155}
156
157/* */
158/* ODM Memory relative API. */
159/* */
160void ODM_AllocateMemory(
161 struct dm_odm_t *pDM_Odm,
162 void **pPtr,
163 u32 length
164 )
165{
166 *pPtr = rtw_zvmalloc(length);
167}
168
169/* length could be ignored, used to detect memory leakage. */
170void ODM_FreeMemory(
171 struct dm_odm_t *pDM_Odm,
172 void *pPtr,
173 u32 length
174 )
175{
176 rtw_vmfree(pPtr, length);
177}
178
179/* */
180/* ODM MISC relative API. */
181/* */
182void
183ODM_AcquireSpinLock(
184 struct dm_odm_t *pDM_Odm,
185 enum rt_spinlock_type type
186 )
187{
188}
189
190void ODM_ReleaseSpinLock(
191 struct dm_odm_t *pDM_Odm,
192 enum rt_spinlock_type type
193 )
194{
195}
196
197/* */
198/* Work item relative API. FOr MP driver only~! */
199/* */
200void ODM_InitializeWorkItem(
201 struct dm_odm_t *pDM_Odm,
202 void *pRtWorkItem,
203 RT_WORKITEM_CALL_BACK RtWorkItemCallback,
204 void *pContext,
205 const char *szID
206 )
207{
208}
209
210/* */
211/* ODM Timer relative API. */
212/* */
213void ODM_SetTimer(struct dm_odm_t *pDM_Odm, struct timer_list *pTimer, u32 msDelay)
214{
215 mod_timer(pTimer, jiffies + msecs_to_jiffies(msDelay)); /* ms */
216}
217
218void ODM_ReleaseTimer(struct dm_odm_t *pDM_Odm, struct timer_list *pTimer)
219{
220}
221
222/* */
223/* ODM FW relative API. */
224/* */
225u32 ODM_FillH2CCmd(
226 u8 *pH2CBuffer,
227 u32 H2CBufferLen,
228 u32 CmdNum,
229 u32 *pElementID,
230 u32 *pCmdLen,
231 u8 **pCmbBuffer,
232 u8 *CmdStartSeq
233 )
234{
235 return true;
236}
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c
new file mode 100644
index 000000000000..9d738d79de4b
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c
@@ -0,0 +1,11304 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#include <drv_types.h>
16#include <rtl8723a_hal.h>
17#include <rtw_ioctl_set.h>
18
19#define DIS_PS_RX_BCN
20
21#ifdef CONFIG_8723AU_BT_COEXIST
22
23u32 BTCoexDbgLevel = _bt_dbg_off_;
24
25#define RTPRINT(_Comp, _Level, Fmt)\
26do {\
27 if ((BTCoexDbgLevel == _bt_dbg_on_)) {\
28 printk Fmt;\
29 } \
30} while (0)
31
32#define RTPRINT_ADDR(dbgtype, dbgflag, printstr, _Ptr)\
33if ((BTCoexDbgLevel == _bt_dbg_on_)) {\
34 u32 __i; \
35 u8 *ptr = (u8 *)_Ptr; \
36 printk printstr; \
37 printk(" "); \
38 for (__i = 0; __i < 6; __i++) \
39 printk("%02X%s", ptr[__i], (__i == 5)?"":"-"); \
40 printk("\n"); \
41}
42#define RTPRINT_DATA(dbgtype, dbgflag, _TitleString, _HexData, _HexDataLen)\
43if ((BTCoexDbgLevel == _bt_dbg_on_)) {\
44 u32 __i; \
45 u8 *ptr = (u8 *)_HexData; \
46 printk(_TitleString); \
47 for (__i = 0; __i < (u32)_HexDataLen; __i++) { \
48 printk("%02X%s", ptr[__i], (((__i + 1) % 4) == 0)?" ":" ");\
49 if (((__i + 1) % 16) == 0) \
50 printk("\n"); \
51 } \
52 printk("\n"); \
53}
54/* Added by Annie, 2005-11-22. */
55#define MAX_STR_LEN 64
56/* I want to see ASCII 33 to 126 only. Otherwise, I print '?'. */
57#define PRINTABLE(_ch) (_ch >= ' ' && _ch <= '~')
58#define RT_PRINT_STR(_Comp, _Level, _TitleString, _Ptr, _Len) \
59 { \
60 u32 __i; \
61 u8 buffer[MAX_STR_LEN]; \
62 u32 length = (_Len < MAX_STR_LEN) ? _Len : (MAX_STR_LEN-1);\
63 memset(buffer, 0, MAX_STR_LEN); \
64 memcpy(buffer, (u8 *)_Ptr, length); \
65 for (__i = 0; __i < length; __i++) { \
66 if (!PRINTABLE(buffer[__i])) \
67 buffer[__i] = '?'; \
68 } \
69 buffer[length] = '\0'; \
70 printk(_TitleString); \
71 printk(": %d, <%s>\n", _Len, buffer); \
72 }
73#endif
74
75#define DCMD_Printf(...)
76#define RT_ASSERT(...)
77
78#define rsprintf snprintf
79
80#define GetDefaultAdapter(padapter) padapter
81
82#define PlatformZeroMemory(ptr, sz) memset(ptr, 0, sz)
83
84#define PlatformProcessHCICommands(...)
85#define PlatformTxBTQueuedPackets(...)
86#define PlatformIndicateBTACLData(...) (RT_STATUS_SUCCESS)
87#define PlatformAcquireSpinLock(padapter, type)
88#define PlatformReleaseSpinLock(padapter, type)
89
90#define GET_UNDECORATED_AVERAGE_RSSI(padapter) \
91 (GET_HAL_DATA(padapter)->dmpriv.EntryMinUndecoratedSmoothedPWDB)
92#define RT_RF_CHANGE_SOURCE u32
93
94enum {
95 RT_JOIN_INFRA = 1,
96 RT_JOIN_IBSS = 2,
97 RT_START_IBSS = 3,
98 RT_NO_ACTION = 4,
99};
100
101/* power saving */
102
103#ifdef __BT_C__ /* COMMOM/BT.c */
104/* ===== Below this line is sync from SD7 driver COMMOM/BT.c ===== */
105
106static u8 BT_Operation(struct rtw_adapter *padapter)
107{
108 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
109 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
110
111 if (pBtMgnt->BtOperationOn)
112 return true;
113 else
114 return false;
115}
116
117static u8 BT_IsLegalChannel(struct rtw_adapter *padapter, u8 channel)
118{
119 struct rt_channel_info *pChanneList = NULL;
120 u8 channelLen, i;
121
122 pChanneList = padapter->mlmeextpriv.channel_set;
123 channelLen = padapter->mlmeextpriv.max_chan_nums;
124
125 for (i = 0; i < channelLen; i++) {
126 RTPRINT(FIOCTL, IOCTL_STATE,
127 ("Check if chnl(%d) in channel plan contains bt target chnl(%d) for BT connection\n",
128 pChanneList[i].ChannelNum, channel));
129 if ((channel == pChanneList[i].ChannelNum) ||
130 (channel == pChanneList[i].ChannelNum + 2))
131 return channel;
132 }
133 return 0;
134}
135
136void BT_SignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, u8 *rssi_bt)
137{
138 BTDM_SignalCompensation(padapter, rssi_wifi, rssi_bt);
139}
140
141void BT_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType)
142{
143 BTHCI_WifiScanNotify(padapter, scanType);
144 BTDM_CheckAntSelMode(padapter);
145 BTDM_WifiScanNotify(padapter, scanType);
146}
147
148void BT_WifiAssociateNotify(struct rtw_adapter *padapter, u8 action)
149{
150 /* action : */
151 /* true = associate start */
152 /* false = associate finished */
153 if (action)
154 BTDM_CheckAntSelMode(padapter);
155
156 BTDM_WifiAssociateNotify(padapter, action);
157}
158
159void BT_WifiMediaStatusNotify(struct rtw_adapter *padapter, enum rt_media_status mstatus)
160{
161 BTDM_MediaStatusNotify(padapter, mstatus);
162}
163
164void BT_SpecialPacketNotify(struct rtw_adapter *padapter)
165{
166 BTDM_ForDhcp(padapter);
167}
168
169void BT_HaltProcess(struct rtw_adapter *padapter)
170{
171 BTDM_ForHalt(padapter);
172}
173
174void BT_LpsLeave(struct rtw_adapter *padapter)
175{
176 BTDM_LpsLeave(padapter);
177}
178
179/* ===== End of sync from SD7 driver COMMOM/BT.c ===== */
180#endif
181
182#ifdef __BT_HANDLEPACKET_C__ /* COMMOM/bt_handlepacket.c */
183/* ===== Below this line is sync from SD7 driver COMMOM/bt_handlepacket.c ===== */
184
185/* ===== End of sync from SD7 driver COMMOM/bt_handlepacket.c ===== */
186#endif
187
188#ifdef __BT_HCI_C__ /* COMMOM/bt_hci.c */
189
190#define i64fmt "ll"
191#define UINT64_C(v) (v)
192
193#define FillOctetString(_os, _octet, _len) \
194 (_os).Octet = (u8 *)(_octet); \
195 (_os).Length = (_len);
196
197static enum rt_status PlatformIndicateBTEvent(
198 struct rtw_adapter *padapter,
199 void *pEvntData,
200 u32 dataLen
201 )
202{
203 enum rt_status rt_status = RT_STATUS_FAILURE;
204
205 RTPRINT(FIOCTL, IOCTL_BT_EVENT_DETAIL, ("BT event start, %d bytes data to Transferred!!\n", dataLen));
206 RTPRINT_DATA(FIOCTL, IOCTL_BT_EVENT_DETAIL, "To transfer Hex Data :\n",
207 pEvntData, dataLen);
208
209 BT_EventParse(padapter, pEvntData, dataLen);
210
211 printk(KERN_WARNING "%s: Linux has no way to report BT event!!\n", __func__);
212
213 RTPRINT(FIOCTL, IOCTL_BT_EVENT_DETAIL, ("BT event end, %s\n",
214 (rt_status == RT_STATUS_SUCCESS) ? "SUCCESS" : "FAIL"));
215
216 return rt_status;
217}
218
219/* ===== Below this line is sync from SD7 driver COMMOM/bt_hci.c ===== */
220
221static u8 bthci_GetLocalChannel(struct rtw_adapter *padapter)
222{
223 return padapter->mlmeextpriv.cur_channel;
224}
225
226static u8 bthci_GetCurrentEntryNum(struct rtw_adapter *padapter, u8 PhyHandle)
227{
228 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
229 u8 i;
230
231 for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) {
232 if ((pBTInfo->BtAsocEntry[i].bUsed) &&
233 (pBTInfo->BtAsocEntry[i].PhyLinkCmdData.BtPhyLinkhandle == PhyHandle))
234 return i;
235 }
236
237 return 0xFF;
238}
239
240static void bthci_DecideBTChannel(struct rtw_adapter *padapter, u8 EntryNum)
241{
242/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
243 struct mlme_priv *pmlmepriv;
244 struct bt_30info *pBTInfo;
245 struct bt_mgnt *pBtMgnt;
246 struct bt_hci_info *pBtHciInfo;
247 struct chnl_txpower_triple *pTriple_subband = NULL;
248 struct common_triple *pTriple;
249 u8 i, j, localchnl, firstRemoteLegalChnlInTriplet = 0;
250 u8 regulatory_skipLen = 0;
251 u8 subbandTripletCnt = 0;
252
253 pmlmepriv = &padapter->mlmepriv;
254 pBTInfo = GET_BT_INFO(padapter);
255 pBtMgnt = &pBTInfo->BtMgnt;
256 pBtHciInfo = &pBTInfo->BtHciInfo;
257
258 pBtMgnt->CheckChnlIsSuit = true;
259 localchnl = bthci_GetLocalChannel(padapter);
260
261 pTriple = (struct common_triple *)
262 &pBtHciInfo->BTPreChnllist[COUNTRY_STR_LEN];
263
264 /* contains country string, len is 3 */
265 for (i = 0; i < (pBtHciInfo->BtPreChnlListLen-COUNTRY_STR_LEN); i += 3, pTriple++) {
266 /* */
267 /* check every triplet, an triplet may be */
268 /* regulatory extension identifier or sub-band triplet */
269 /* */
270 if (pTriple->byte_1st == 0xc9) {
271 /* Regulatory Extension Identifier, skip it */
272 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO),
273 ("Find Regulatory ID, regulatory class = %d\n", pTriple->byte_2nd));
274 regulatory_skipLen += 3;
275 pTriple_subband = NULL;
276 continue;
277 } else { /* Sub-band triplet */
278 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Find Sub-band triplet \n"));
279 subbandTripletCnt++;
280 pTriple_subband = (struct chnl_txpower_triple *)pTriple;
281 /* if remote first legal channel not found, then find first remote channel */
282 /* and it's legal for our channel plan. */
283
284 /* search the sub-band triplet and find if remote channel is legal to our channel plan. */
285 for (j = pTriple_subband->FirstChnl; j < (pTriple_subband->FirstChnl+pTriple_subband->NumChnls); j++) {
286 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), (" Check if chnl(%d) is legal\n", j));
287 if (BT_IsLegalChannel(padapter, j)) {
288 /* remote channel is legal for our channel plan. */
289 firstRemoteLegalChnlInTriplet = j;
290 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO),
291 ("Find first remote legal channel : %d\n",
292 firstRemoteLegalChnlInTriplet));
293
294 /* If we find a remote legal channel in the sub-band triplet */
295 /* and only BT connection is established(local not connect to any AP or IBSS), */
296 /* then we just switch channel to remote channel. */
297 if (!(check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_ADHOC_STATE|WIFI_AP_STATE) ||
298 BTHCI_HsConnectionEstablished(padapter))) {
299 pBtMgnt->BTChannel = firstRemoteLegalChnlInTriplet;
300 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Remote legal channel (%d) is selected, Local not connect to any!!\n", pBtMgnt->BTChannel));
301 return;
302 } else {
303 if ((localchnl >= firstRemoteLegalChnlInTriplet) &&
304 (localchnl < (pTriple_subband->FirstChnl+pTriple_subband->NumChnls))) {
305 pBtMgnt->BTChannel = localchnl;
306 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Local channel (%d) is selected, wifi or BT connection exists\n", pBtMgnt->BTChannel));
307 return;
308 }
309 }
310 break;
311 }
312 }
313 }
314 }
315
316 if (subbandTripletCnt) {
317 /* if any preferred channel triplet exists */
318 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("There are %d sub band triplet exists, ", subbandTripletCnt));
319 if (firstRemoteLegalChnlInTriplet == 0) {
320 /* no legal channel is found, reject the connection. */
321 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("no legal channel is found!!\n"));
322 } else {
323 /* Remote Legal channel is found but not match to local */
324 /* wifi connection exists), so reject the connection. */
325 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO),
326 ("Remote Legal channel is found but not match to local(wifi connection exists)!!\n"));
327 }
328 pBtMgnt->CheckChnlIsSuit = false;
329 } else {
330 /* There are not any preferred channel triplet exists */
331 /* Use current legal channel as the bt channel. */
332 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("No sub band triplet exists!!\n"));
333 }
334 pBtMgnt->BTChannel = localchnl;
335 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Local channel (%d) is selected!!\n", pBtMgnt->BTChannel));
336}
337
338/* Success:return true */
339/* Fail:return false */
340static u8 bthci_GetAssocInfo(struct rtw_adapter *padapter, u8 EntryNum)
341{
342 struct bt_30info *pBTInfo;
343 struct bt_hci_info *pBtHciInfo;
344 u8 tempBuf[256];
345 u8 i = 0;
346 u8 BaseMemoryShift = 0;
347 u16 TotalLen = 0;
348 struct amp_assoc_structure *pAmpAsoc;
349
350 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("GetAssocInfo start\n"));
351 pBTInfo = GET_BT_INFO(padapter);
352 pBtHciInfo = &pBTInfo->BtHciInfo;
353
354 if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar == 0) {
355 if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen < (MAX_AMP_ASSOC_FRAG_LEN))
356 TotalLen = pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen;
357 else if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen == (MAX_AMP_ASSOC_FRAG_LEN))
358 TotalLen = MAX_AMP_ASSOC_FRAG_LEN;
359 } else if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar > 0)
360 TotalLen = pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar;
361
362 while ((pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar >= BaseMemoryShift) || TotalLen > BaseMemoryShift) {
363 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("GetAssocInfo, TotalLen =%d, BaseMemoryShift =%d\n", TotalLen, BaseMemoryShift));
364 memcpy(tempBuf,
365 (u8 *)pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment+BaseMemoryShift,
366 TotalLen-BaseMemoryShift);
367 RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_DETAIL, "GetAssocInfo :\n",
368 tempBuf, TotalLen-BaseMemoryShift);
369
370 pAmpAsoc = (struct amp_assoc_structure *)tempBuf;
371 pAmpAsoc->Length = le16_to_cpu(pAmpAsoc->Length);
372 BaseMemoryShift += 3 + pAmpAsoc->Length;
373
374 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("TypeID = 0x%x, ", pAmpAsoc->TypeID));
375 RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD, "Hex Data: \n", pAmpAsoc->Data, pAmpAsoc->Length);
376 switch (pAmpAsoc->TypeID) {
377 case AMP_MAC_ADDR:
378 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_MAC_ADDR\n"));
379 if (pAmpAsoc->Length > 6)
380 return false;
381 memcpy(pBTInfo->BtAsocEntry[EntryNum].BTRemoteMACAddr, pAmpAsoc->Data, 6);
382 RTPRINT_ADDR(FIOCTL, IOCTL_BT_HCICMD, ("Remote Mac address \n"), pBTInfo->BtAsocEntry[EntryNum].BTRemoteMACAddr);
383 break;
384 case AMP_PREFERRED_CHANNEL_LIST:
385 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_PREFERRED_CHANNEL_LIST\n"));
386 pBtHciInfo->BtPreChnlListLen = pAmpAsoc->Length;
387 memcpy(pBtHciInfo->BTPreChnllist,
388 pAmpAsoc->Data,
389 pBtHciInfo->BtPreChnlListLen);
390 RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD, "Preferred channel list : \n", pBtHciInfo->BTPreChnllist, pBtHciInfo->BtPreChnlListLen);
391 bthci_DecideBTChannel(padapter, EntryNum);
392 break;
393 case AMP_CONNECTED_CHANNEL:
394 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_CONNECTED_CHANNEL\n"));
395 pBtHciInfo->BTConnectChnlListLen = pAmpAsoc->Length;
396 memcpy(pBtHciInfo->BTConnectChnllist,
397 pAmpAsoc->Data,
398 pBtHciInfo->BTConnectChnlListLen);
399 break;
400 case AMP_80211_PAL_CAP_LIST:
401 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_80211_PAL_CAP_LIST\n"));
402 pBTInfo->BtAsocEntry[EntryNum].BTCapability = *(u32 *)(pAmpAsoc->Data);
403 if (pBTInfo->BtAsocEntry[EntryNum].BTCapability & 0x00000001) {
404 /* TODO: */
405
406 /* Signifies PAL capable of utilizing received activity reports. */
407 }
408 if (pBTInfo->BtAsocEntry[EntryNum].BTCapability & 0x00000002) {
409 /* TODO: */
410 /* Signifies PAL is capable of utilizing scheduling information received in an activity reports. */
411 }
412 break;
413 case AMP_80211_PAL_VISION:
414 pBtHciInfo->BTPalVersion = *(u8 *)(pAmpAsoc->Data);
415 pBtHciInfo->BTPalCompanyID = *(u16 *)(((u8 *)(pAmpAsoc->Data))+1);
416 pBtHciInfo->BTPalsubversion = *(u16 *)(((u8 *)(pAmpAsoc->Data))+3);
417 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("==> AMP_80211_PAL_VISION PalVersion 0x%x, PalCompanyID 0x%x, Palsubversion 0x%x\n",
418 pBtHciInfo->BTPalVersion,
419 pBtHciInfo->BTPalCompanyID,
420 pBtHciInfo->BTPalsubversion));
421 break;
422 default:
423 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> Unsupport TypeID !!\n"));
424 break;
425 }
426 i++;
427 }
428 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("GetAssocInfo end\n"));
429
430 return true;
431}
432
433static u8 bthci_AddEntry(struct rtw_adapter *padapter)
434{
435 struct bt_30info *pBTInfo;
436 struct bt_mgnt *pBtMgnt;
437 u8 i;
438
439 pBTInfo = GET_BT_INFO(padapter);
440 pBtMgnt = &pBTInfo->BtMgnt;
441
442 for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) {
443 if (pBTInfo->BtAsocEntry[i].bUsed == false) {
444 pBTInfo->BtAsocEntry[i].bUsed = true;
445 pBtMgnt->CurrentConnectEntryNum = i;
446 break;
447 }
448 }
449
450 if (i == MAX_BT_ASOC_ENTRY_NUM) {
451 RTPRINT(FIOCTL, IOCTL_STATE, ("bthci_AddEntry(), Add entry fail!!\n"));
452 return false;
453 }
454 return true;
455}
456
457static u8 bthci_DiscardTxPackets(struct rtw_adapter *padapter, u16 LLH)
458{
459 return false;
460}
461
462static u8
463bthci_CheckLogLinkBehavior(
464 struct rtw_adapter *padapter,
465 struct hci_flow_spec TxFlowSpec
466 )
467{
468 u8 ID = TxFlowSpec.Identifier;
469 u8 ServiceType = TxFlowSpec.ServiceType;
470 u16 MaxSDUSize = TxFlowSpec.MaximumSDUSize;
471 u32 SDUInterArrivatime = TxFlowSpec.SDUInterArrivalTime;
472 u8 match = false;
473
474 switch (ID) {
475 case 1:
476 if (ServiceType == BT_LL_BE) {
477 match = true;
478 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX best effort flowspec\n"));
479 } else if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 0xffff)) {
480 match = true;
481 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = RX guaranteed latency flowspec\n"));
482 } else if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 2500)) {
483 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = RX guaranteed Large latency flowspec\n"));
484 }
485 break;
486 case 2:
487 if (ServiceType == BT_LL_BE) {
488 match = true;
489 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = RX best effort flowspec\n"));
490
491 }
492 break;
493 case 3:
494 if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 1492)) {
495 match = true;
496 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX guaranteed latency flowspec\n"));
497 } else if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 2500)) {
498 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX guaranteed Large latency flowspec\n"));
499 }
500 break;
501 case 4:
502 if (ServiceType == BT_LL_BE) {
503 if ((SDUInterArrivatime == 0xffffffff) && (ServiceType == BT_LL_BE) && (MaxSDUSize == 1492)) {
504 match = true;
505 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX/RX aggregated best effort flowspec\n"));
506 }
507 } else if (ServiceType == BT_LL_GU) {
508 if (SDUInterArrivatime == 100) {
509 match = true;
510 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = TX/RX guaranteed bandwidth flowspec\n"));
511 }
512 }
513 break;
514 default:
515 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type = Unknow Type !!!!!!!!\n"));
516 break;
517 }
518
519 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO),
520 ("ID = 0x%x, ServiceType = 0x%x, MaximumSDUSize = 0x%x, SDUInterArrivalTime = 0x%x, AccessLatency = 0x%x, FlushTimeout = 0x%x\n",
521 TxFlowSpec.Identifier, TxFlowSpec.ServiceType, MaxSDUSize,
522 SDUInterArrivatime, TxFlowSpec.AccessLatency, TxFlowSpec.FlushTimeout));
523 return match;
524}
525
526static u16 bthci_AssocMACAddr(struct rtw_adapter *padapter, void *pbuf)
527{
528 struct amp_assoc_structure *pAssoStrc = (struct amp_assoc_structure *)pbuf;
529 pAssoStrc->TypeID = AMP_MAC_ADDR;
530 pAssoStrc->Length = 0x06;
531 memcpy(&pAssoStrc->Data[0], padapter->eeprompriv.mac_addr, 6);
532 RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO),
533 ("AssocMACAddr : \n"), pAssoStrc, pAssoStrc->Length+3);
534
535 return pAssoStrc->Length + 3;
536}
537
538static u16
539bthci_PALCapabilities(
540 struct rtw_adapter *padapter,
541 void *pbuf
542 )
543{
544 struct amp_assoc_structure *pAssoStrc = (struct amp_assoc_structure *)pbuf;
545
546 pAssoStrc->TypeID = AMP_80211_PAL_CAP_LIST;
547 pAssoStrc->Length = 0x04;
548
549 pAssoStrc->Data[0] = 0x00;
550 pAssoStrc->Data[1] = 0x00;
551
552 RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("PALCapabilities:\n"), pAssoStrc, pAssoStrc->Length+3);
553 RTPRINT(FIOCTL, IOCTL_BT_LOGO, ("PALCapabilities \n"));
554
555 RTPRINT(FIOCTL, IOCTL_BT_LOGO, (" TypeID = 0x%x,\n Length = 0x%x,\n Content = 0x0000\n",
556 pAssoStrc->TypeID,
557 pAssoStrc->Length));
558
559 return pAssoStrc->Length + 3;
560}
561
562static u16 bthci_AssocPreferredChannelList(struct rtw_adapter *padapter,
563 void *pbuf, u8 EntryNum)
564{
565 struct bt_30info *pBTInfo;
566 struct amp_assoc_structure *pAssoStrc;
567 struct amp_pref_chnl_regulatory *pReg;
568 struct chnl_txpower_triple *pTriple;
569 char ctrString[3] = {'X', 'X', 'X'};
570 u32 len = 0;
571 u8 preferredChnl;
572
573 pBTInfo = GET_BT_INFO(padapter);
574 pAssoStrc = (struct amp_assoc_structure *)pbuf;
575 pReg = (struct amp_pref_chnl_regulatory *)&pAssoStrc->Data[3];
576
577 preferredChnl = bthci_GetLocalChannel(padapter);
578 pAssoStrc->TypeID = AMP_PREFERRED_CHANNEL_LIST;
579
580 /* locale unknown */
581 memcpy(&pAssoStrc->Data[0], &ctrString[0], 3);
582 pReg->reXId = 201;
583 pReg->regulatoryClass = 254;
584 pReg->coverageClass = 0;
585 len += 6;
586 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD | IOCTL_BT_LOGO), ("PREFERRED_CHNL_LIST\n"));
587 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD | IOCTL_BT_LOGO), ("XXX, 201, 254, 0\n"));
588 /* at the following, chnl 1~11 should be contained */
589 pTriple = (struct chnl_txpower_triple *)&pAssoStrc->Data[len];
590
591 /* (1) if any wifi or bt HS connection exists */
592 if ((pBTInfo->BtAsocEntry[EntryNum].AMPRole == AMP_BTAP_CREATOR) ||
593 (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE |
594 WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE |
595 WIFI_AP_STATE)) ||
596 BTHCI_HsConnectionEstablished(padapter)) {
597 pTriple->FirstChnl = preferredChnl;
598 pTriple->NumChnls = 1;
599 pTriple->MaxTxPowerInDbm = 20;
600 len += 3;
601 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD | IOCTL_BT_LOGO), ("First Channel = %d, Channel Num = %d, MaxDbm = %d\n",
602 pTriple->FirstChnl,
603 pTriple->NumChnls,
604 pTriple->MaxTxPowerInDbm));
605 }
606
607 pAssoStrc->Length = (u16)len;
608 RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD, ("AssocPreferredChannelList : \n"), pAssoStrc, pAssoStrc->Length+3);
609
610 return pAssoStrc->Length + 3;
611}
612
613static u16 bthci_AssocPALVer(struct rtw_adapter *padapter, void *pbuf)
614{
615 struct amp_assoc_structure *pAssoStrc = (struct amp_assoc_structure *)pbuf;
616 u8 *pu1Tmp;
617 u16 *pu2Tmp;
618
619 pAssoStrc->TypeID = AMP_80211_PAL_VISION;
620 pAssoStrc->Length = 0x5;
621 pu1Tmp = &pAssoStrc->Data[0];
622 *pu1Tmp = 0x1; /* PAL Version */
623 pu2Tmp = (u16 *)&pAssoStrc->Data[1];
624 *pu2Tmp = 0x5D; /* SIG Company identifier of 802.11 PAL vendor */
625 pu2Tmp = (u16 *)&pAssoStrc->Data[3];
626 *pu2Tmp = 0x1; /* PAL Sub-version specifier */
627
628 RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("AssocPALVer : \n"), pAssoStrc, pAssoStrc->Length+3);
629 RTPRINT(FIOCTL, IOCTL_BT_LOGO, ("AssocPALVer \n"));
630
631 RTPRINT(FIOCTL, IOCTL_BT_LOGO, (" TypeID = 0x%x,\n Length = 0x%x,\n PAL Version = 0x01,\n PAL vendor = 0x01,\n PAL Sub-version specifier = 0x01\n",
632 pAssoStrc->TypeID,
633 pAssoStrc->Length));
634 return pAssoStrc->Length + 3;
635}
636
637static u8 bthci_CheckRfStateBeforeConnect(struct rtw_adapter *padapter)
638{
639 struct bt_30info *pBTInfo;
640 enum rt_rf_power_state RfState;
641
642 pBTInfo = GET_BT_INFO(padapter);
643
644 RfState = padapter->pwrctrlpriv.rf_pwrstate;
645
646 if (RfState != rf_on) {
647 mod_timer(&pBTInfo->BTPsDisableTimer,
648 jiffies + msecs_to_jiffies(50));
649 return false;
650 }
651 return true;
652}
653
654static void bthci_ResponderStartToScan(struct rtw_adapter *padapter)
655{
656}
657
658static u8 bthci_PhyLinkConnectionInProgress(struct rtw_adapter *padapter, u8 PhyLinkHandle)
659{
660 struct bt_30info *pBTInfo;
661 struct bt_mgnt *pBtMgnt;
662
663 pBTInfo = GET_BT_INFO(padapter);
664 pBtMgnt = &pBTInfo->BtMgnt;
665
666 if (pBtMgnt->bPhyLinkInProgress &&
667 (pBtMgnt->BtCurrentPhyLinkhandle == PhyLinkHandle))
668 return true;
669 return false;
670}
671
672static void bthci_ResetFlowSpec(struct rtw_adapter *padapter, u8 EntryNum, u8 index)
673{
674 struct bt_30info *pBTinfo;
675
676 pBTinfo = GET_BT_INFO(padapter);
677
678 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].BtLogLinkhandle = 0;
679 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].BtPhyLinkhandle = 0;
680 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].bLLCompleteEventIsSet = false;
681 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].bLLCancelCMDIsSetandComplete = false;
682 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].BtTxFlowSpecID = 0;
683 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].TxPacketCount = 0;
684
685 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.Identifier = 0x01;
686 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.ServiceType = SERVICE_BEST_EFFORT;
687 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.MaximumSDUSize = 0xffff;
688 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.SDUInterArrivalTime = 0xffffffff;
689 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.AccessLatency = 0xffffffff;
690 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.FlushTimeout = 0xffffffff;
691
692 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.Identifier = 0x01;
693 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.ServiceType = SERVICE_BEST_EFFORT;
694 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.MaximumSDUSize = 0xffff;
695 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.SDUInterArrivalTime = 0xffffffff;
696 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.AccessLatency = 0xffffffff;
697 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.FlushTimeout = 0xffffffff;
698}
699
700static void bthci_ResetEntry(struct rtw_adapter *padapter, u8 EntryNum)
701{
702 struct bt_30info *pBTinfo;
703 struct bt_mgnt *pBtMgnt;
704 u8 j;
705
706 pBTinfo = GET_BT_INFO(padapter);
707 pBtMgnt = &pBTinfo->BtMgnt;
708
709 pBTinfo->BtAsocEntry[EntryNum].bUsed = false;
710 pBTinfo->BtAsocEntry[EntryNum].BtCurrentState = HCI_STATE_DISCONNECTED;
711 pBTinfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTED;
712
713 pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen = 0;
714 pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.BtPhyLinkhandle = 0;
715 if (pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment != NULL)
716 memset(pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment, 0, TOTAL_ALLOCIATE_ASSOC_LEN);
717 pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar = 0;
718
719 pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyType = 0;
720 pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle = 0;
721 memset(pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey, 0,
722 pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen);
723 pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen = 0;
724
725 /* 0x640; 0.625ms*1600 = 1000ms, 0.625ms*16000 = 10000ms */
726 pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout = 0x3e80;
727
728 pBTinfo->BtAsocEntry[EntryNum].AMPRole = AMP_BTAP_NONE;
729
730 pBTinfo->BtAsocEntry[EntryNum].mAssoc = false;
731 pBTinfo->BtAsocEntry[EntryNum].b4waySuccess = false;
732
733 /* Reset BT WPA */
734 pBTinfo->BtAsocEntry[EntryNum].KeyReplayCounter = 0;
735 pBTinfo->BtAsocEntry[EntryNum].BTWPAAuthState = STATE_WPA_AUTH_UNINITIALIZED;
736
737 pBTinfo->BtAsocEntry[EntryNum].bSendSupervisionPacket = false;
738 pBTinfo->BtAsocEntry[EntryNum].NoRxPktCnt = 0;
739 pBTinfo->BtAsocEntry[EntryNum].ShortRangeMode = 0;
740 pBTinfo->BtAsocEntry[EntryNum].rxSuvpPktCnt = 0;
741
742 for (j = 0; j < MAX_LOGICAL_LINK_NUM; j++)
743 bthci_ResetFlowSpec(padapter, EntryNum, j);
744
745 pBtMgnt->BTAuthCount = 0;
746 pBtMgnt->BTAsocCount = 0;
747 pBtMgnt->BTCurrentConnectType = BT_DISCONNECT;
748 pBtMgnt->BTReceiveConnectPkt = BT_DISCONNECT;
749
750 HALBT_RemoveKey(padapter, EntryNum);
751}
752
753static void bthci_RemoveEntryByEntryNum(struct rtw_adapter *padapter, u8 EntryNum)
754{
755 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
756 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
757
758 bthci_ResetEntry(padapter, EntryNum);
759
760 if (pBtMgnt->CurrentBTConnectionCnt > 0)
761 pBtMgnt->CurrentBTConnectionCnt--;
762
763 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], CurrentBTConnectionCnt = %d!!\n",
764 pBtMgnt->CurrentBTConnectionCnt));
765
766 if (pBtMgnt->CurrentBTConnectionCnt > 0) {
767 pBtMgnt->BtOperationOn = true;
768 } else {
769 pBtMgnt->BtOperationOn = false;
770 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], Bt Operation OFF!!\n"));
771 }
772
773 if (!pBtMgnt->BtOperationOn) {
774 del_timer_sync(&pBTInfo->BTHCIDiscardAclDataTimer);
775 del_timer_sync(&pBTInfo->BTBeaconTimer);
776 pBtMgnt->bStartSendSupervisionPkt = false;
777 }
778}
779
780static u8
781bthci_CommandCompleteHeader(
782 u8 *pbuf,
783 u16 OGF,
784 u16 OCF,
785 enum hci_status status
786 )
787{
788 struct packet_irp_hcievent_data *PPacketIrpEvent = (struct packet_irp_hcievent_data *)pbuf;
789 u8 NumHCI_Comm = 0x1;
790
791 PPacketIrpEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
792 PPacketIrpEvent->Data[0] = NumHCI_Comm; /* packet # */
793 PPacketIrpEvent->Data[1] = HCIOPCODELOW(OCF, OGF);
794 PPacketIrpEvent->Data[2] = HCIOPCODEHIGHT(OCF, OGF);
795
796 if (OGF == OGF_EXTENSION) {
797 if (OCF == HCI_SET_RSSI_VALUE) {
798 RTPRINT(FIOCTL, (IOCTL_BT_EVENT_PERIODICAL),
799 ("[BT event], CommandComplete, Num_HCI_Comm = 0x%x, Opcode = 0x%02x%02x, status = 0x%x, OGF = 0x%x, OCF = 0x%x\n",
800 NumHCI_Comm, (HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), status, OGF, OCF));
801 } else {
802 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_EXT),
803 ("[BT event], CommandComplete, Num_HCI_Comm = 0x%x, Opcode = 0x%02x%02x, status = 0x%x, OGF = 0x%x, OCF = 0x%x\n",
804 NumHCI_Comm, (HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), status, OGF, OCF));
805 }
806 } else {
807 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO),
808 ("[BT event], CommandComplete, Num_HCI_Comm = 0x%x, Opcode = 0x%02x%02x, status = 0x%x, OGF = 0x%x, OCF = 0x%x\n",
809 NumHCI_Comm, (HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), status, OGF, OCF));
810 }
811 return 3;
812}
813
814static u8 bthci_ExtensionEventHeaderRtk(u8 *pbuf, u8 extensionEvent)
815{
816 struct packet_irp_hcievent_data *PPacketIrpEvent = (struct packet_irp_hcievent_data *)pbuf;
817 PPacketIrpEvent->EventCode = HCI_EVENT_EXTENSION_RTK;
818 PPacketIrpEvent->Data[0] = extensionEvent; /* extension event code */
819
820 return 1;
821}
822
823static enum rt_status
824bthci_IndicateEvent(
825 struct rtw_adapter *padapter,
826 void *pEvntData,
827 u32 dataLen
828 )
829{
830 enum rt_status rt_status;
831
832 rt_status = PlatformIndicateBTEvent(padapter, pEvntData, dataLen);
833
834 return rt_status;
835}
836
837static void
838bthci_EventWriteRemoteAmpAssoc(
839 struct rtw_adapter *padapter,
840 enum hci_status status,
841 u8 PLHandle
842 )
843{
844 u8 localBuf[TmpLocalBufSize] = "";
845 u8 *pRetPar;
846 u8 len = 0;
847 struct packet_irp_hcievent_data *PPacketIrpEvent;
848
849 PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
850 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
851
852 len += bthci_CommandCompleteHeader(&localBuf[0],
853 OGF_STATUS_PARAMETERS,
854 HCI_WRITE_REMOTE_AMP_ASSOC,
855 status);
856 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("PhyLinkHandle = 0x%x, status = %d\n", PLHandle, status));
857 /* Return parameters starts from here */
858 pRetPar = &PPacketIrpEvent->Data[len];
859 pRetPar[0] = status; /* status */
860 pRetPar[1] = PLHandle;
861 len += 2;
862 PPacketIrpEvent->Length = len;
863
864 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
865}
866
867static void
868bthci_EventEnhancedFlushComplete(
869 struct rtw_adapter *padapter,
870 u16 LLH
871 )
872{
873 u8 localBuf[4] = "";
874 struct packet_irp_hcievent_data *PPacketIrpEvent;
875
876 RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("EventEnhancedFlushComplete, LLH = 0x%x\n", LLH));
877
878 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
879 PPacketIrpEvent->EventCode = HCI_EVENT_ENHANCED_FLUSH_COMPLETE;
880 PPacketIrpEvent->Length = 2;
881 /* Logical link handle */
882 PPacketIrpEvent->Data[0] = TWOBYTE_LOWBYTE(LLH);
883 PPacketIrpEvent->Data[1] = TWOBYTE_HIGHTBYTE(LLH);
884
885 bthci_IndicateEvent(padapter, PPacketIrpEvent, 4);
886}
887
888static void
889bthci_EventShortRangeModeChangeComplete(
890 struct rtw_adapter *padapter,
891 enum hci_status HciStatus,
892 u8 ShortRangeState,
893 u8 EntryNum
894 )
895{
896 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
897 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
898 u8 localBuf[5] = "";
899 struct packet_irp_hcievent_data *PPacketIrpEvent;
900
901 if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_SHORT_RANGE_MODE_CHANGE_COMPLETE)) {
902 RTPRINT(FIOCTL, IOCTL_BT_EVENT,
903 ("[BT event], Short Range Mode Change Complete, Ignore to send this event due to event mask page 2\n"));
904 return;
905 }
906 RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Short Range Mode Change Complete, Status = %d\n , PLH = 0x%x\n, Short_Range_Mode_State = 0x%x\n",
907 HciStatus, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle, ShortRangeState));
908
909 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
910 PPacketIrpEvent->EventCode = HCI_EVENT_SHORT_RANGE_MODE_CHANGE_COMPLETE;
911 PPacketIrpEvent->Length = 3;
912 PPacketIrpEvent->Data[0] = HciStatus;
913 PPacketIrpEvent->Data[1] = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle;
914 PPacketIrpEvent->Data[2] = ShortRangeState;
915 bthci_IndicateEvent(padapter, PPacketIrpEvent, 5);
916}
917
918static void bthci_EventSendFlowSpecModifyComplete(struct rtw_adapter *padapter,
919 enum hci_status HciStatus,
920 u16 logicHandle)
921{
922 u8 localBuf[5] = "";
923 struct packet_irp_hcievent_data *PPacketIrpEvent;
924 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
925 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
926
927 if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_FLOW_SPEC_MODIFY_COMPLETE)) {
928 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO),
929 ("[BT event], Flow Spec Modify Complete, Ignore to send this event due to event mask page 2\n"));
930 return;
931 }
932 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO),
933 ("[BT event], Flow Spec Modify Complete, status = 0x%x, LLH = 0x%x\n", HciStatus, logicHandle));
934 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
935 PPacketIrpEvent->EventCode = HCI_EVENT_FLOW_SPEC_MODIFY_COMPLETE;
936 PPacketIrpEvent->Length = 3;
937
938 PPacketIrpEvent->Data[0] = HciStatus;
939 /* Logical link handle */
940 PPacketIrpEvent->Data[1] = TWOBYTE_LOWBYTE(logicHandle);
941 PPacketIrpEvent->Data[2] = TWOBYTE_HIGHTBYTE(logicHandle);
942
943 bthci_IndicateEvent(padapter, PPacketIrpEvent, 5);
944}
945
946static void
947bthci_EventExtWifiScanNotify(
948 struct rtw_adapter *padapter,
949 u8 scanType
950 )
951{
952 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
953 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
954 u8 len = 0;
955 u8 localBuf[7] = "";
956 u8 *pRetPar;
957 u8 *pu1Temp;
958 struct packet_irp_hcievent_data *PPacketIrpEvent;
959
960 if (!pBtMgnt->BtOperationOn)
961 return;
962
963 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
964
965 len += bthci_ExtensionEventHeaderRtk(&localBuf[0], HCI_EVENT_EXT_WIFI_SCAN_NOTIFY);
966
967 /* Return parameters starts from here */
968 pRetPar = &PPacketIrpEvent->Data[len];
969 pu1Temp = (u8 *)&pRetPar[0];
970 *pu1Temp = scanType;
971 len += 1;
972
973 PPacketIrpEvent->Length = len;
974
975 if (bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2) == RT_STATUS_SUCCESS) {
976 RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Wifi scan notify, scan type = %d\n",
977 scanType));
978 }
979}
980
981static void
982bthci_EventAMPReceiverReport(
983 struct rtw_adapter *padapter,
984 u8 Reason
985 )
986{
987 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
988 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
989
990 if (pBtHciInfo->bTestNeedReport) {
991 u8 localBuf[20] = "";
992 u32 *pu4Temp;
993 u16 *pu2Temp;
994 struct packet_irp_hcievent_data *PPacketIrpEvent;
995
996 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), (" HCI_EVENT_AMP_RECEIVER_REPORT\n"));
997 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
998 PPacketIrpEvent->EventCode = HCI_EVENT_AMP_RECEIVER_REPORT;
999 PPacketIrpEvent->Length = 2;
1000
1001 PPacketIrpEvent->Data[0] = pBtHciInfo->TestCtrType;
1002
1003 PPacketIrpEvent->Data[1] = Reason;
1004
1005 pu4Temp = (u32 *)&PPacketIrpEvent->Data[2];
1006 *pu4Temp = pBtHciInfo->TestEventType;
1007
1008 pu2Temp = (u16 *)&PPacketIrpEvent->Data[6];
1009 *pu2Temp = pBtHciInfo->TestNumOfFrame;
1010
1011 pu2Temp = (u16 *)&PPacketIrpEvent->Data[8];
1012 *pu2Temp = pBtHciInfo->TestNumOfErrFrame;
1013
1014 pu4Temp = (u32 *)&PPacketIrpEvent->Data[10];
1015 *pu4Temp = pBtHciInfo->TestNumOfBits;
1016
1017 pu4Temp = (u32 *)&PPacketIrpEvent->Data[14];
1018 *pu4Temp = pBtHciInfo->TestNumOfErrBits;
1019
1020 bthci_IndicateEvent(padapter, PPacketIrpEvent, 20);
1021
1022 /* Return to Idel state with RX and TX off. */
1023
1024 }
1025
1026 pBtHciInfo->TestNumOfFrame = 0x00;
1027}
1028
1029static void
1030bthci_EventChannelSelected(
1031 struct rtw_adapter *padapter,
1032 u8 EntryNum
1033 )
1034{
1035 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
1036 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
1037 u8 localBuf[3] = "";
1038 struct packet_irp_hcievent_data *PPacketIrpEvent;
1039
1040 if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_CHANNEL_SELECT)) {
1041 RTPRINT(FIOCTL, IOCTL_BT_EVENT,
1042 ("[BT event], Channel Selected, Ignore to send this event due to event mask page 2\n"));
1043 return;
1044 }
1045
1046 RTPRINT(FIOCTL, IOCTL_BT_EVENT|IOCTL_STATE,
1047 ("[BT event], Channel Selected, PhyLinkHandle %d\n",
1048 pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle));
1049
1050 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
1051 PPacketIrpEvent->EventCode = HCI_EVENT_CHANNEL_SELECT;
1052 PPacketIrpEvent->Length = 1;
1053 PPacketIrpEvent->Data[0] = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle;
1054 bthci_IndicateEvent(padapter, PPacketIrpEvent, 3);
1055}
1056
1057static void
1058bthci_EventDisconnectPhyLinkComplete(
1059 struct rtw_adapter *padapter,
1060 enum hci_status HciStatus,
1061 enum hci_status Reason,
1062 u8 EntryNum
1063 )
1064{
1065 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
1066 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
1067 u8 localBuf[5] = "";
1068 struct packet_irp_hcievent_data *PPacketIrpEvent;
1069
1070 if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE)) {
1071 RTPRINT(FIOCTL, IOCTL_BT_EVENT,
1072 ("[BT event], Disconnect Physical Link Complete, Ignore to send this event due to event mask page 2\n"));
1073 return;
1074 }
1075 RTPRINT(FIOCTL, IOCTL_BT_EVENT,
1076 ("[BT event], Disconnect Physical Link Complete, Status = 0x%x, PLH = 0x%x Reason = 0x%x\n",
1077 HciStatus, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle, Reason));
1078 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
1079 PPacketIrpEvent->EventCode = HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE;
1080 PPacketIrpEvent->Length = 3;
1081 PPacketIrpEvent->Data[0] = HciStatus;
1082 PPacketIrpEvent->Data[1] = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle;
1083 PPacketIrpEvent->Data[2] = Reason;
1084 bthci_IndicateEvent(padapter, PPacketIrpEvent, 5);
1085}
1086
1087static void
1088bthci_EventPhysicalLinkComplete(
1089 struct rtw_adapter *padapter,
1090 enum hci_status HciStatus,
1091 u8 EntryNum,
1092 u8 PLHandle
1093 )
1094{
1095 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
1096 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
1097 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
1098 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
1099 u8 localBuf[4] = "";
1100 struct packet_irp_hcievent_data *PPacketIrpEvent;
1101 u8 PL_handle;
1102
1103 pBtMgnt->bPhyLinkInProgress = false;
1104 pBtDbg->dbgHciInfo.hciCmdPhyLinkStatus = HciStatus;
1105 if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_PHY_LINK_COMPLETE)) {
1106 RTPRINT(FIOCTL, IOCTL_BT_EVENT,
1107 ("[BT event], Physical Link Complete, Ignore to send this event due to event mask page 2\n"));
1108 return;
1109 }
1110
1111 if (EntryNum == 0xff) {
1112 /* connection not started yet, just use the input physical link handle to response. */
1113 PL_handle = PLHandle;
1114 } else {
1115 /* connection is under progress, use the phy link handle we recorded. */
1116 PL_handle = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle;
1117 pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent = false;
1118 }
1119
1120 RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Physical Link Complete, Status = 0x%x PhyLinkHandle = 0x%x\n", HciStatus,
1121 PL_handle));
1122
1123 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
1124 PPacketIrpEvent->EventCode = HCI_EVENT_PHY_LINK_COMPLETE;
1125 PPacketIrpEvent->Length = 2;
1126
1127 PPacketIrpEvent->Data[0] = HciStatus;
1128 PPacketIrpEvent->Data[1] = PL_handle;
1129 bthci_IndicateEvent(padapter, PPacketIrpEvent, 4);
1130
1131}
1132
1133static void
1134bthci_EventCommandStatus(
1135 struct rtw_adapter *padapter,
1136 u8 OGF,
1137 u16 OCF,
1138 enum hci_status HciStatus
1139 )
1140{
1141
1142 u8 localBuf[6] = "";
1143 struct packet_irp_hcievent_data *PPacketIrpEvent;
1144 u8 Num_Hci_Comm = 0x1;
1145 RTPRINT(FIOCTL, IOCTL_BT_EVENT,
1146 ("[BT event], CommandStatus, Opcode = 0x%02x%02x, OGF = 0x%x, OCF = 0x%x, Status = 0x%x, Num_HCI_COMM = 0x%x\n",
1147 (HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), OGF, OCF, HciStatus, Num_Hci_Comm));
1148
1149 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
1150 PPacketIrpEvent->EventCode = HCI_EVENT_COMMAND_STATUS;
1151 PPacketIrpEvent->Length = 4;
1152 PPacketIrpEvent->Data[0] = HciStatus; /* current pending */
1153 PPacketIrpEvent->Data[1] = Num_Hci_Comm; /* packet # */
1154 PPacketIrpEvent->Data[2] = HCIOPCODELOW(OCF, OGF);
1155 PPacketIrpEvent->Data[3] = HCIOPCODEHIGHT(OCF, OGF);
1156
1157 bthci_IndicateEvent(padapter, PPacketIrpEvent, 6);
1158
1159}
1160
1161static void
1162bthci_EventLogicalLinkComplete(
1163 struct rtw_adapter *padapter,
1164 enum hci_status HciStatus,
1165 u8 PhyLinkHandle,
1166 u16 LogLinkHandle,
1167 u8 LogLinkIndex,
1168 u8 EntryNum
1169 )
1170{
1171/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
1172 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
1173 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
1174 u8 localBuf[7] = "";
1175 struct packet_irp_hcievent_data *PPacketIrpEvent;
1176
1177 if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_LOGICAL_LINK_COMPLETE)) {
1178 RTPRINT(FIOCTL, IOCTL_BT_EVENT,
1179 ("[BT event], Logical Link Complete, Ignore to send this event due to event mask page 2\n"));
1180 return;
1181 }
1182 RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Logical Link Complete, PhyLinkHandle = 0x%x, LogLinkHandle = 0x%x, Status = 0x%x\n",
1183 PhyLinkHandle, LogLinkHandle, HciStatus));
1184
1185 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
1186 PPacketIrpEvent->EventCode = HCI_EVENT_LOGICAL_LINK_COMPLETE;
1187 PPacketIrpEvent->Length = 5;
1188
1189 PPacketIrpEvent->Data[0] = HciStatus;/* status code */
1190 /* Logical link handle */
1191 PPacketIrpEvent->Data[1] = TWOBYTE_LOWBYTE(LogLinkHandle);
1192 PPacketIrpEvent->Data[2] = TWOBYTE_HIGHTBYTE(LogLinkHandle);
1193 /* Physical link handle */
1194 PPacketIrpEvent->Data[3] = TWOBYTE_LOWBYTE(PhyLinkHandle);
1195 /* corresponding Tx flow spec ID */
1196 if (HciStatus == HCI_STATUS_SUCCESS) {
1197 PPacketIrpEvent->Data[4] =
1198 pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData[LogLinkIndex].Tx_Flow_Spec.Identifier;
1199 } else {
1200 PPacketIrpEvent->Data[4] = 0x0;
1201 }
1202
1203 bthci_IndicateEvent(padapter, PPacketIrpEvent, 7);
1204}
1205
1206static void
1207bthci_EventDisconnectLogicalLinkComplete(
1208 struct rtw_adapter *padapter,
1209 enum hci_status HciStatus,
1210 u16 LogLinkHandle,
1211 enum hci_status Reason
1212 )
1213{
1214 u8 localBuf[6] = "";
1215 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
1216 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
1217 struct packet_irp_hcievent_data *PPacketIrpEvent;
1218
1219 if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_DISCONNECT_LOGICAL_LINK_COMPLETE)) {
1220 RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Disconnect Logical Link Complete, Ignore to send this event due to event mask page 2\n"));
1221 return;
1222 }
1223 RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Disconnect Logical Link Complete, Status = 0x%x, LLH = 0x%x Reason = 0x%x\n", HciStatus, LogLinkHandle, Reason));
1224
1225 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
1226 PPacketIrpEvent->EventCode = HCI_EVENT_DISCONNECT_LOGICAL_LINK_COMPLETE;
1227 PPacketIrpEvent->Length = 4;
1228
1229 PPacketIrpEvent->Data[0] = HciStatus;
1230 /* Logical link handle */
1231 PPacketIrpEvent->Data[1] = TWOBYTE_LOWBYTE(LogLinkHandle);
1232 PPacketIrpEvent->Data[2] = TWOBYTE_HIGHTBYTE(LogLinkHandle);
1233 /* Disconnect reason */
1234 PPacketIrpEvent->Data[3] = Reason;
1235
1236 bthci_IndicateEvent(padapter, PPacketIrpEvent, 6);
1237}
1238
1239static void
1240bthci_EventFlushOccurred(
1241 struct rtw_adapter *padapter,
1242 u16 LogLinkHandle
1243 )
1244{
1245 u8 localBuf[4] = "";
1246 struct packet_irp_hcievent_data *PPacketIrpEvent;
1247 RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("bthci_EventFlushOccurred(), LLH = 0x%x\n", LogLinkHandle));
1248
1249 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
1250 PPacketIrpEvent->EventCode = HCI_EVENT_FLUSH_OCCRUED;
1251 PPacketIrpEvent->Length = 2;
1252 /* Logical link handle */
1253 PPacketIrpEvent->Data[0] = TWOBYTE_LOWBYTE(LogLinkHandle);
1254 PPacketIrpEvent->Data[1] = TWOBYTE_HIGHTBYTE(LogLinkHandle);
1255
1256 bthci_IndicateEvent(padapter, PPacketIrpEvent, 4);
1257}
1258
1259static enum hci_status
1260bthci_BuildPhysicalLink(
1261 struct rtw_adapter *padapter,
1262 struct packet_irp_hcicmd_data *pHciCmd,
1263 u16 OCF
1264)
1265{
1266 enum hci_status status = HCI_STATUS_SUCCESS;
1267 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
1268 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
1269 u8 EntryNum, PLH;
1270
1271 /* Send HCI Command status event to AMP. */
1272 bthci_EventCommandStatus(padapter,
1273 LINK_CONTROL_COMMANDS,
1274 OCF,
1275 HCI_STATUS_SUCCESS);
1276
1277 PLH = *((u8 *)pHciCmd->Data);
1278
1279 /* Check if resource or bt connection is under progress, if yes, reject the link creation. */
1280 if (!bthci_AddEntry(padapter)) {
1281 status = HCI_STATUS_CONNECT_RJT_LIMIT_RESOURCE;
1282 bthci_EventPhysicalLinkComplete(padapter, status, INVALID_ENTRY_NUM, PLH);
1283 return status;
1284 }
1285
1286 EntryNum = pBtMgnt->CurrentConnectEntryNum;
1287 pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle = PLH;
1288 pBtMgnt->BtCurrentPhyLinkhandle = PLH;
1289
1290 if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment == NULL) {
1291 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Create/Accept PhysicalLink, AMP controller is busy\n"));
1292 status = HCI_STATUS_CONTROLLER_BUSY;
1293 bthci_EventPhysicalLinkComplete(padapter, status, INVALID_ENTRY_NUM, PLH);
1294 return status;
1295 }
1296
1297 /* Record Key and the info */
1298 pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen = (*((u8 *)pHciCmd->Data+1));
1299 pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyType = (*((u8 *)pHciCmd->Data+2));
1300 memcpy(pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey,
1301 (((u8 *)pHciCmd->Data+3)), pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen);
1302 memcpy(pBTInfo->BtAsocEntry[EntryNum].PMK, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey, PMK_LEN);
1303 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("BuildPhysicalLink, EntryNum = %d, PLH = 0x%x KeyLen = 0x%x, KeyType = 0x%x\n",
1304 EntryNum, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle,
1305 pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen,
1306 pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyType));
1307 RTPRINT_DATA(FIOCTL, (IOCTL_BT_LOGO|IOCTL_BT_HCICMD), ("BtAMPKey\n"), pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey,
1308 pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen);
1309 RTPRINT_DATA(FIOCTL, (IOCTL_BT_LOGO|IOCTL_BT_HCICMD), ("PMK\n"), pBTInfo->BtAsocEntry[EntryNum].PMK,
1310 PMK_LEN);
1311
1312 if (OCF == HCI_CREATE_PHYSICAL_LINK) {
1313 /* These macros require braces */
1314 BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_CREATE_PHY_LINK, EntryNum);
1315 } else if (OCF == HCI_ACCEPT_PHYSICAL_LINK) {
1316 BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_ACCEPT_PHY_LINK, EntryNum);
1317 }
1318
1319 return status;
1320}
1321
1322static void
1323bthci_BuildLogicalLink(
1324 struct rtw_adapter *padapter,
1325 struct packet_irp_hcicmd_data *pHciCmd,
1326 u16 OCF
1327 )
1328{
1329 enum hci_status status = HCI_STATUS_SUCCESS;
1330 struct bt_30info *pBTinfo = GET_BT_INFO(padapter);
1331 struct bt_mgnt *pBtMgnt = &pBTinfo->BtMgnt;
1332 u8 PhyLinkHandle, EntryNum;
1333 static u16 AssignLogHandle = 1;
1334
1335 struct hci_flow_spec TxFlowSpec;
1336 struct hci_flow_spec RxFlowSpec;
1337 u32 MaxSDUSize, ArriveTime, Bandwidth;
1338
1339 PhyLinkHandle = *((u8 *)pHciCmd->Data);
1340
1341 EntryNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle);
1342
1343 memcpy(&TxFlowSpec,
1344 &pHciCmd->Data[1], sizeof(struct hci_flow_spec));
1345 memcpy(&RxFlowSpec,
1346 &pHciCmd->Data[17], sizeof(struct hci_flow_spec));
1347
1348 MaxSDUSize = TxFlowSpec.MaximumSDUSize;
1349 ArriveTime = TxFlowSpec.SDUInterArrivalTime;
1350
1351 if (bthci_CheckLogLinkBehavior(padapter, TxFlowSpec) && bthci_CheckLogLinkBehavior(padapter, RxFlowSpec))
1352 Bandwidth = BTTOTALBANDWIDTH;
1353 else if (MaxSDUSize == 0xffff && ArriveTime == 0xffffffff)
1354 Bandwidth = BTTOTALBANDWIDTH;
1355 else
1356 Bandwidth = MaxSDUSize*8*1000/(ArriveTime+244);
1357
1358 RTPRINT(FIOCTL, IOCTL_BT_HCICMD,
1359 ("BuildLogicalLink, PhyLinkHandle = 0x%x, MaximumSDUSize = 0x%x, SDUInterArrivalTime = 0x%x, Bandwidth = 0x%x\n",
1360 PhyLinkHandle, MaxSDUSize, ArriveTime, Bandwidth));
1361
1362 if (EntryNum == 0xff) {
1363 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Invalid Physical Link handle = 0x%x, status = HCI_STATUS_UNKNOW_CONNECT_ID, return\n", PhyLinkHandle));
1364 status = HCI_STATUS_UNKNOW_CONNECT_ID;
1365
1366 /* When we receive Create/Accept logical link command, we should send command status event first. */
1367 bthci_EventCommandStatus(padapter,
1368 LINK_CONTROL_COMMANDS,
1369 OCF,
1370 status);
1371 return;
1372 }
1373
1374 if (!pBtMgnt->bLogLinkInProgress) {
1375 if (bthci_PhyLinkConnectionInProgress(padapter, PhyLinkHandle)) {
1376 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Physical link connection in progress, status = HCI_STATUS_CMD_DISALLOW, return\n"));
1377 status = HCI_STATUS_CMD_DISALLOW;
1378
1379 pBtMgnt->bPhyLinkInProgressStartLL = true;
1380 /* When we receive Create/Accept logical link command, we should send command status event first. */
1381 bthci_EventCommandStatus(padapter,
1382 LINK_CONTROL_COMMANDS,
1383 OCF,
1384 status);
1385
1386 return;
1387 }
1388
1389 if (Bandwidth > BTTOTALBANDWIDTH) {
1390 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("status = HCI_STATUS_QOS_REJECT, Bandwidth = 0x%x, return\n", Bandwidth));
1391 status = HCI_STATUS_QOS_REJECT;
1392
1393 /* When we receive Create/Accept logical link command, we should send command status event first. */
1394 bthci_EventCommandStatus(padapter,
1395 LINK_CONTROL_COMMANDS,
1396 OCF,
1397 status);
1398 } else {
1399 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("status = HCI_STATUS_SUCCESS\n"));
1400 status = HCI_STATUS_SUCCESS;
1401
1402 /* When we receive Create/Accept logical link command, we should send command status event first. */
1403 bthci_EventCommandStatus(padapter,
1404 LINK_CONTROL_COMMANDS,
1405 OCF,
1406 status);
1407
1408 }
1409
1410 if (pBTinfo->BtAsocEntry[EntryNum].BtCurrentState != HCI_STATE_CONNECTED) {
1411 bthci_EventLogicalLinkComplete(padapter,
1412 HCI_STATUS_CMD_DISALLOW, 0, 0, 0, EntryNum);
1413 } else {
1414 u8 i, find = 0;
1415
1416 pBtMgnt->bLogLinkInProgress = true;
1417
1418 /* find an unused logical link index and copy the data */
1419 for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) {
1420 if (pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle == 0) {
1421 enum hci_status LogCompEventstatus = HCI_STATUS_SUCCESS;
1422
1423 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtPhyLinkhandle = *((u8 *)pHciCmd->Data);
1424 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle = AssignLogHandle;
1425 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("BuildLogicalLink, EntryNum = %d, physical link handle = 0x%x, logical link handle = 0x%x\n",
1426 EntryNum, pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle,
1427 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle));
1428 memcpy(&pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].Tx_Flow_Spec,
1429 &TxFlowSpec, sizeof(struct hci_flow_spec));
1430 memcpy(&pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].Rx_Flow_Spec,
1431 &RxFlowSpec, sizeof(struct hci_flow_spec));
1432
1433 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].bLLCompleteEventIsSet = false;
1434
1435 if (pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].bLLCancelCMDIsSetandComplete)
1436 LogCompEventstatus = HCI_STATUS_UNKNOW_CONNECT_ID;
1437 bthci_EventLogicalLinkComplete(padapter,
1438 LogCompEventstatus,
1439 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtPhyLinkhandle,
1440 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle, i, EntryNum);
1441
1442 pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].bLLCompleteEventIsSet = true;
1443
1444 find = 1;
1445 pBtMgnt->BtCurrentLogLinkhandle = AssignLogHandle;
1446 AssignLogHandle++;
1447 break;
1448 }
1449 }
1450
1451 if (!find) {
1452 bthci_EventLogicalLinkComplete(padapter,
1453 HCI_STATUS_CONNECT_RJT_LIMIT_RESOURCE, 0, 0, 0, EntryNum);
1454 }
1455 pBtMgnt->bLogLinkInProgress = false;
1456 }
1457 } else {
1458 bthci_EventLogicalLinkComplete(padapter,
1459 HCI_STATUS_CONTROLLER_BUSY, 0, 0, 0, EntryNum);
1460 }
1461
1462}
1463
1464static void
1465bthci_StartBeaconAndConnect(
1466 struct rtw_adapter *padapter,
1467 struct packet_irp_hcicmd_data *pHciCmd,
1468 u8 CurrentAssocNum
1469 )
1470{
1471/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
1472 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
1473 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
1474
1475 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("StartBeaconAndConnect, CurrentAssocNum =%d, AMPRole =%d\n",
1476 CurrentAssocNum,
1477 pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole));
1478
1479 if (!pBtMgnt->CheckChnlIsSuit) {
1480 bthci_EventPhysicalLinkComplete(padapter, HCI_STATUS_CONNECT_REJ_NOT_SUIT_CHNL_FOUND, CurrentAssocNum, INVALID_PL_HANDLE);
1481 bthci_RemoveEntryByEntryNum(padapter, CurrentAssocNum);
1482 return;
1483 }
1484
1485 if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_CREATOR) {
1486 rsprintf((char *)pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 32, "AMP-%02x-%02x-%02x-%02x-%02x-%02x",
1487 padapter->eeprompriv.mac_addr[0],
1488 padapter->eeprompriv.mac_addr[1],
1489 padapter->eeprompriv.mac_addr[2],
1490 padapter->eeprompriv.mac_addr[3],
1491 padapter->eeprompriv.mac_addr[4],
1492 padapter->eeprompriv.mac_addr[5]);
1493 } else if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_JOINER) {
1494 rsprintf((char *)pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 32, "AMP-%02x-%02x-%02x-%02x-%02x-%02x",
1495 pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[0],
1496 pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[1],
1497 pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[2],
1498 pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[3],
1499 pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[4],
1500 pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[5]);
1501 }
1502
1503 FillOctetString(pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsid, pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 21);
1504 pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsid.Length = 21;
1505
1506 /* To avoid set the start ap or connect twice, or the original connection will be disconnected. */
1507 if (!pBtMgnt->bBTConnectInProgress) {
1508 pBtMgnt->bBTConnectInProgress = true;
1509 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress ON!!\n"));
1510 BTHCI_SM_WITH_INFO(padapter, HCI_STATE_STARTING, STATE_CMD_MAC_START_COMPLETE, CurrentAssocNum);
1511
1512 /* 20100325 Joseph: Check RF ON/OFF. */
1513 /* If RF OFF, it reschedule connecting operation after 50ms. */
1514 if (!bthci_CheckRfStateBeforeConnect(padapter))
1515 return;
1516
1517 if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_CREATOR) {
1518 /* These macros need braces */
1519 BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTING, STATE_CMD_MAC_CONNECT_COMPLETE, CurrentAssocNum);
1520 } else if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_JOINER) {
1521 bthci_ResponderStartToScan(padapter);
1522 }
1523 }
1524 RT_PRINT_STR(_module_rtl871x_mlme_c_, _drv_notice_,
1525 "StartBeaconAndConnect, SSID:\n",
1526 pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].BTSsid.Octet,
1527 pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].BTSsid.Length);
1528}
1529
1530static void bthci_ResetBtMgnt(struct bt_mgnt *pBtMgnt)
1531{
1532 pBtMgnt->BtOperationOn = false;
1533 pBtMgnt->bBTConnectInProgress = false;
1534 pBtMgnt->bLogLinkInProgress = false;
1535 pBtMgnt->bPhyLinkInProgress = false;
1536 pBtMgnt->bPhyLinkInProgressStartLL = false;
1537 pBtMgnt->DisconnectEntryNum = 0xff;
1538 pBtMgnt->bStartSendSupervisionPkt = false;
1539 pBtMgnt->JoinerNeedSendAuth = false;
1540 pBtMgnt->CurrentBTConnectionCnt = 0;
1541 pBtMgnt->BTCurrentConnectType = BT_DISCONNECT;
1542 pBtMgnt->BTReceiveConnectPkt = BT_DISCONNECT;
1543 pBtMgnt->BTAuthCount = 0;
1544 pBtMgnt->btLogoTest = 0;
1545}
1546
1547static void bthci_ResetBtHciInfo(struct bt_hci_info *pBtHciInfo)
1548{
1549 pBtHciInfo->BTEventMask = 0;
1550 pBtHciInfo->BTEventMaskPage2 = 0;
1551 pBtHciInfo->ConnAcceptTimeout = 10000;
1552 pBtHciInfo->PageTimeout = 0x30;
1553 pBtHciInfo->LocationDomainAware = 0x0;
1554 pBtHciInfo->LocationDomain = 0x5858;
1555 pBtHciInfo->LocationDomainOptions = 0x58;
1556 pBtHciInfo->LocationOptions = 0x0;
1557 pBtHciInfo->FlowControlMode = 0x1; /* 0:Packet based data flow control mode(BR/EDR), 1: Data block based data flow control mode(AMP). */
1558
1559 pBtHciInfo->enFlush_LLH = 0;
1560 pBtHciInfo->FLTO_LLH = 0;
1561
1562 /* Test command only */
1563 pBtHciInfo->bTestIsEnd = true;
1564 pBtHciInfo->bInTestMode = false;
1565 pBtHciInfo->bTestNeedReport = false;
1566 pBtHciInfo->TestScenario = 0xff;
1567 pBtHciInfo->TestReportInterval = 0x01;
1568 pBtHciInfo->TestCtrType = 0x5d;
1569 pBtHciInfo->TestEventType = 0x00;
1570 pBtHciInfo->TestNumOfFrame = 0;
1571 pBtHciInfo->TestNumOfErrFrame = 0;
1572 pBtHciInfo->TestNumOfBits = 0;
1573 pBtHciInfo->TestNumOfErrBits = 0;
1574}
1575
1576static void bthci_ResetBtSec(struct rtw_adapter *padapter, struct bt_security *pBtSec)
1577{
1578/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
1579
1580 /* Set BT used HW or SW encrypt !! */
1581 if (GET_HAL_DATA(padapter)->bBTMode)
1582 pBtSec->bUsedHwEncrypt = true;
1583 else
1584 pBtSec->bUsedHwEncrypt = false;
1585 RT_TRACE(_module_rtl871x_security_c_, _drv_info_, ("%s: bUsedHwEncrypt =%d\n", __func__, pBtSec->bUsedHwEncrypt));
1586
1587 pBtSec->RSNIE.Octet = pBtSec->RSNIEBuf;
1588}
1589
1590static void bthci_ResetBtExtInfo(struct bt_mgnt *pBtMgnt)
1591{
1592 u8 i;
1593
1594 for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) {
1595 pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = 0;
1596 pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = 0;
1597 pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = 0;
1598 pBtMgnt->ExtConfig.linkInfo[i].BTProfile = BT_PROFILE_NONE;
1599 pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec = BT_SPEC_2_1_EDR;
1600 pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI = 0;
1601 pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = BT_PROFILE_NONE;
1602 pBtMgnt->ExtConfig.linkInfo[i].linkRole = BT_LINK_MASTER;
1603 }
1604
1605 pBtMgnt->ExtConfig.CurrentConnectHandle = 0;
1606 pBtMgnt->ExtConfig.CurrentIncomingTrafficMode = 0;
1607 pBtMgnt->ExtConfig.CurrentOutgoingTrafficMode = 0;
1608 pBtMgnt->ExtConfig.MIN_BT_RSSI = 0;
1609 pBtMgnt->ExtConfig.NumberOfHandle = 0;
1610 pBtMgnt->ExtConfig.NumberOfSCO = 0;
1611 pBtMgnt->ExtConfig.CurrentBTStatus = 0;
1612 pBtMgnt->ExtConfig.HCIExtensionVer = 0;
1613
1614 pBtMgnt->ExtConfig.bManualControl = false;
1615 pBtMgnt->ExtConfig.bBTBusy = false;
1616 pBtMgnt->ExtConfig.bBTA2DPBusy = false;
1617}
1618
1619static enum hci_status bthci_CmdReset(struct rtw_adapter *_padapter, u8 bNeedSendEvent)
1620{
1621 enum hci_status status = HCI_STATUS_SUCCESS;
1622 struct rtw_adapter *padapter;
1623/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
1624 struct bt_30info *pBTInfo;
1625 struct bt_mgnt *pBtMgnt;
1626 struct bt_hci_info *pBtHciInfo;
1627 struct bt_security *pBtSec;
1628 struct bt_dgb *pBtDbg;
1629 u8 i;
1630
1631 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_CmdReset()\n"));
1632
1633 padapter = GetDefaultAdapter(_padapter);
1634 pBTInfo = GET_BT_INFO(padapter);
1635 pBtMgnt = &pBTInfo->BtMgnt;
1636 pBtHciInfo = &pBTInfo->BtHciInfo;
1637 pBtSec = &pBTInfo->BtSec;
1638 pBtDbg = &pBTInfo->BtDbg;
1639
1640 pBTInfo->padapter = padapter;
1641
1642 for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++)
1643 bthci_ResetEntry(padapter, i);
1644
1645 bthci_ResetBtMgnt(pBtMgnt);
1646 bthci_ResetBtHciInfo(pBtHciInfo);
1647 bthci_ResetBtSec(padapter, pBtSec);
1648
1649 pBtMgnt->BTChannel = BT_Default_Chnl;
1650 pBtMgnt->CheckChnlIsSuit = true;
1651
1652 pBTInfo->BTBeaconTmrOn = false;
1653
1654 pBtMgnt->bCreateSpportQos = true;
1655
1656 del_timer_sync(&pBTInfo->BTHCIDiscardAclDataTimer);
1657 del_timer_sync(&pBTInfo->BTBeaconTimer);
1658
1659 HALBT_SetRtsCtsNoLenLimit(padapter);
1660 /* */
1661 /* Maybe we need to take care Group != AES case !! */
1662 /* now we Pairwise and Group all used AES !! */
1663
1664 bthci_ResetBtExtInfo(pBtMgnt);
1665
1666 /* send command complete event here when all data are received. */
1667 if (bNeedSendEvent) {
1668 u8 localBuf[6] = "";
1669 u8 *pRetPar;
1670 u8 len = 0;
1671 struct packet_irp_hcievent_data *PPacketIrpEvent;
1672
1673 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
1674
1675 len += bthci_CommandCompleteHeader(&localBuf[0],
1676 OGF_SET_EVENT_MASK_COMMAND,
1677 HCI_RESET,
1678 status);
1679
1680 /* Return parameters starts from here */
1681 pRetPar = &PPacketIrpEvent->Data[len];
1682 pRetPar[0] = status; /* status */
1683 len += 1;
1684 PPacketIrpEvent->Length = len;
1685
1686 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
1687 }
1688
1689 return status;
1690}
1691
1692static enum hci_status
1693bthci_CmdWriteRemoteAMPAssoc(
1694 struct rtw_adapter *padapter,
1695 struct packet_irp_hcicmd_data *pHciCmd
1696 )
1697{
1698 enum hci_status status = HCI_STATUS_SUCCESS;
1699 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
1700 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
1701 u8 CurrentAssocNum;
1702 u8 PhyLinkHandle;
1703
1704 pBtDbg->dbgHciInfo.hciCmdCntWriteRemoteAmpAssoc++;
1705 PhyLinkHandle = *((u8 *)pHciCmd->Data);
1706 CurrentAssocNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle);
1707
1708 if (CurrentAssocNum == 0xff) {
1709 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("WriteRemoteAMPAssoc, No such Handle in the Entry\n"));
1710 status = HCI_STATUS_UNKNOW_CONNECT_ID;
1711 bthci_EventWriteRemoteAmpAssoc(padapter, status, PhyLinkHandle);
1712 return status;
1713 }
1714
1715 if (pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocfragment == NULL) {
1716 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("WriteRemoteAMPAssoc, AMP controller is busy\n"));
1717 status = HCI_STATUS_CONTROLLER_BUSY;
1718 bthci_EventWriteRemoteAmpAssoc(padapter, status, PhyLinkHandle);
1719 return status;
1720 }
1721
1722 pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.BtPhyLinkhandle = PhyLinkHandle;/* u8 *)pHciCmd->Data); */
1723 pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar = *((u16 *)((u8 *)pHciCmd->Data+1));
1724 pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen = *((u16 *)((u8 *)pHciCmd->Data+3));
1725
1726 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("WriteRemoteAMPAssoc, LenSoFar = 0x%x, AssocRemLen = 0x%x\n",
1727 pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar,
1728 pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen));
1729
1730 RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO),
1731 ("WriteRemoteAMPAssoc fragment \n"),
1732 pHciCmd->Data,
1733 pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen+5);
1734 if ((pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen) > MAX_AMP_ASSOC_FRAG_LEN) {
1735 memcpy(((u8 *)pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocfragment+(pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar*(sizeof(u8)))),
1736 (u8 *)pHciCmd->Data+5,
1737 MAX_AMP_ASSOC_FRAG_LEN);
1738 } else {
1739 memcpy((u8 *)(pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocfragment)+(pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar*(sizeof(u8))),
1740 ((u8 *)pHciCmd->Data+5),
1741 (pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen));
1742
1743 RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), "WriteRemoteAMPAssoc :\n",
1744 pHciCmd->Data+5, pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen);
1745
1746 if (!bthci_GetAssocInfo(padapter, CurrentAssocNum))
1747 status = HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE;
1748
1749 bthci_EventWriteRemoteAmpAssoc(padapter, status, PhyLinkHandle);
1750
1751 bthci_StartBeaconAndConnect(padapter, pHciCmd, CurrentAssocNum);
1752 }
1753
1754 return status;
1755}
1756
1757/* 7.3.13 */
1758static enum hci_status bthci_CmdReadConnectionAcceptTimeout(struct rtw_adapter *padapter)
1759{
1760 enum hci_status status = HCI_STATUS_SUCCESS;
1761/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
1762 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
1763 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
1764 u8 localBuf[8] = "";
1765 u8 *pRetPar;
1766 u8 len = 0;
1767 struct packet_irp_hcievent_data *PPacketIrpEvent;
1768 u16 *pu2Temp;
1769
1770 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
1771
1772 len += bthci_CommandCompleteHeader(&localBuf[0],
1773 OGF_SET_EVENT_MASK_COMMAND,
1774 HCI_READ_CONNECTION_ACCEPT_TIMEOUT,
1775 status);
1776
1777 /* Return parameters starts from here */
1778 pRetPar = &PPacketIrpEvent->Data[len];
1779 pRetPar[0] = status; /* status */
1780 pu2Temp = (u16 *)&pRetPar[1]; /* Conn_Accept_Timeout */
1781 *pu2Temp = pBtHciInfo->ConnAcceptTimeout;
1782 len += 3;
1783 PPacketIrpEvent->Length = len;
1784
1785 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
1786
1787 return status;
1788}
1789
1790/* 7.3.3 */
1791static enum hci_status
1792bthci_CmdSetEventFilter(
1793 struct rtw_adapter *padapter,
1794 struct packet_irp_hcicmd_data *pHciCmd
1795 )
1796{
1797 enum hci_status status = HCI_STATUS_SUCCESS;
1798
1799 return status;
1800}
1801
1802/* 7.3.14 */
1803static enum hci_status
1804bthci_CmdWriteConnectionAcceptTimeout(
1805 struct rtw_adapter *padapter,
1806 struct packet_irp_hcicmd_data *pHciCmd
1807 )
1808{
1809 enum hci_status status = HCI_STATUS_SUCCESS;
1810 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
1811 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
1812 u16 *pu2Temp;
1813 u8 localBuf[6] = "";
1814 u8 *pRetPar;
1815 u8 len = 0;
1816 struct packet_irp_hcievent_data *PPacketIrpEvent;
1817
1818 pu2Temp = (u16 *)&pHciCmd->Data[0];
1819 pBtHciInfo->ConnAcceptTimeout = *pu2Temp;
1820 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("ConnAcceptTimeout = 0x%x",
1821 pBtHciInfo->ConnAcceptTimeout));
1822
1823 /* send command complete event here when all data are received. */
1824 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
1825
1826 len += bthci_CommandCompleteHeader(&localBuf[0],
1827 OGF_SET_EVENT_MASK_COMMAND,
1828 HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT,
1829 status);
1830
1831 /* Return parameters starts from here */
1832 pRetPar = &PPacketIrpEvent->Data[len];
1833 pRetPar[0] = status; /* status */
1834 len += 1;
1835 PPacketIrpEvent->Length = len;
1836
1837 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
1838
1839 return status;
1840}
1841
1842static enum hci_status
1843bthci_CmdReadPageTimeout(
1844 struct rtw_adapter *padapter,
1845 struct packet_irp_hcicmd_data *pHciCmd
1846 )
1847{
1848 enum hci_status status = HCI_STATUS_SUCCESS;
1849 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
1850 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
1851 u8 localBuf[8] = "";
1852 u8 *pRetPar;
1853 u8 len = 0;
1854 struct packet_irp_hcievent_data *PPacketIrpEvent;
1855 u16 *pu2Temp;
1856
1857 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
1858
1859 len += bthci_CommandCompleteHeader(&localBuf[0],
1860 OGF_SET_EVENT_MASK_COMMAND,
1861 HCI_READ_PAGE_TIMEOUT,
1862 status);
1863
1864 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Read PageTimeout = 0x%x\n", pBtHciInfo->PageTimeout));
1865 /* Return parameters starts from here */
1866 pRetPar = &PPacketIrpEvent->Data[len];
1867 pRetPar[0] = status; /* status */
1868 pu2Temp = (u16 *)&pRetPar[1]; /* Page_Timeout */
1869 *pu2Temp = pBtHciInfo->PageTimeout;
1870 len += 3;
1871 PPacketIrpEvent->Length = len;
1872
1873 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
1874
1875 return status;
1876}
1877
1878static enum hci_status
1879bthci_CmdWritePageTimeout(
1880 struct rtw_adapter *padapter,
1881 struct packet_irp_hcicmd_data *pHciCmd
1882 )
1883{
1884 enum hci_status status = HCI_STATUS_SUCCESS;
1885 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
1886 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
1887 u16 *pu2Temp;
1888
1889 pu2Temp = (u16 *)&pHciCmd->Data[0];
1890 pBtHciInfo->PageTimeout = *pu2Temp;
1891 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Write PageTimeout = 0x%x\n",
1892 pBtHciInfo->PageTimeout));
1893
1894 /* send command complete event here when all data are received. */
1895 {
1896 u8 localBuf[6] = "";
1897 u8 *pRetPar;
1898 u8 len = 0;
1899 struct packet_irp_hcievent_data *PPacketIrpEvent;
1900
1901 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
1902
1903 len += bthci_CommandCompleteHeader(&localBuf[0],
1904 OGF_SET_EVENT_MASK_COMMAND,
1905 HCI_WRITE_PAGE_TIMEOUT,
1906 status);
1907
1908 /* Return parameters starts from here */
1909 pRetPar = &PPacketIrpEvent->Data[len];
1910 pRetPar[0] = status; /* status */
1911 len += 1;
1912 PPacketIrpEvent->Length = len;
1913
1914 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
1915 }
1916
1917 return status;
1918}
1919
1920static enum hci_status
1921bthci_CmdReadLinkSupervisionTimeout(
1922 struct rtw_adapter *padapter,
1923 struct packet_irp_hcicmd_data *pHciCmd
1924 )
1925{
1926 enum hci_status status = HCI_STATUS_SUCCESS;
1927 struct bt_30info *pBTinfo = GET_BT_INFO(padapter);
1928 u8 physicalLinkHandle, EntryNum;
1929
1930 physicalLinkHandle = *((u8 *)pHciCmd->Data);
1931
1932 EntryNum = bthci_GetCurrentEntryNum(padapter, physicalLinkHandle);
1933
1934 if (EntryNum == 0xff) {
1935 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLinkSupervisionTimeout, No such Handle in the Entry\n"));
1936 status = HCI_STATUS_UNKNOW_CONNECT_ID;
1937 return status;
1938 }
1939
1940 if (pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle != physicalLinkHandle)
1941 status = HCI_STATUS_UNKNOW_CONNECT_ID;
1942
1943 {
1944 u8 localBuf[10] = "";
1945 u8 *pRetPar;
1946 u8 len = 0;
1947 struct packet_irp_hcievent_data *PPacketIrpEvent;
1948 u16 *pu2Temp;
1949
1950 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
1951
1952 len += bthci_CommandCompleteHeader(&localBuf[0],
1953 OGF_SET_EVENT_MASK_COMMAND,
1954 HCI_READ_LINK_SUPERVISION_TIMEOUT,
1955 status);
1956
1957 /* Return parameters starts from here */
1958 pRetPar = &PPacketIrpEvent->Data[len];
1959 pRetPar[0] = status;
1960 pRetPar[1] = pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle;
1961 pRetPar[2] = 0;
1962 pu2Temp = (u16 *)&pRetPar[3]; /* Conn_Accept_Timeout */
1963 *pu2Temp = pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout;
1964 len += 5;
1965 PPacketIrpEvent->Length = len;
1966
1967 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
1968 }
1969
1970 return status;
1971}
1972
1973static enum hci_status
1974bthci_CmdWriteLinkSupervisionTimeout(
1975 struct rtw_adapter *padapter,
1976 struct packet_irp_hcicmd_data *pHciCmd
1977 )
1978{
1979 enum hci_status status = HCI_STATUS_SUCCESS;
1980 struct bt_30info *pBTinfo = GET_BT_INFO(padapter);
1981 u8 physicalLinkHandle, EntryNum;
1982
1983 physicalLinkHandle = *((u8 *)pHciCmd->Data);
1984
1985 EntryNum = bthci_GetCurrentEntryNum(padapter, physicalLinkHandle);
1986
1987 if (EntryNum == 0xff) {
1988 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("WriteLinkSupervisionTimeout, No such Handle in the Entry\n"));
1989 status = HCI_STATUS_UNKNOW_CONNECT_ID;
1990 } else {
1991 if (pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle != physicalLinkHandle) {
1992 status = HCI_STATUS_UNKNOW_CONNECT_ID;
1993 } else {
1994 pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout = *((u16 *)(((u8 *)pHciCmd->Data)+2));
1995 RTPRINT(FIOCTL, IOCTL_STATE, ("BT Write LinkSuperversionTimeout[%d] = 0x%x\n",
1996 EntryNum, pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout));
1997 }
1998 }
1999
2000 {
2001 u8 localBuf[8] = "";
2002 u8 *pRetPar;
2003 u8 len = 0;
2004 struct packet_irp_hcievent_data *PPacketIrpEvent;
2005
2006 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2007
2008 len += bthci_CommandCompleteHeader(&localBuf[0],
2009 OGF_SET_EVENT_MASK_COMMAND,
2010 HCI_WRITE_LINK_SUPERVISION_TIMEOUT,
2011 status);
2012
2013 /* Return parameters starts from here */
2014 pRetPar = &PPacketIrpEvent->Data[len];
2015 pRetPar[0] = status;
2016 pRetPar[1] = pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle;
2017 pRetPar[2] = 0;
2018 len += 3;
2019 PPacketIrpEvent->Length = len;
2020
2021 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2022 }
2023
2024 return status;
2025}
2026
2027static enum hci_status
2028bthci_CmdEnhancedFlush(
2029 struct rtw_adapter *padapter,
2030 struct packet_irp_hcicmd_data *pHciCmd
2031 )
2032{
2033 enum hci_status status = HCI_STATUS_SUCCESS;
2034 struct bt_30info *pBTinfo = GET_BT_INFO(padapter);
2035 struct bt_hci_info *pBtHciInfo = &pBTinfo->BtHciInfo;
2036 u16 logicHandle;
2037 u8 Packet_Type;
2038
2039 logicHandle = *((u16 *)&pHciCmd->Data[0]);
2040 Packet_Type = pHciCmd->Data[2];
2041
2042 if (Packet_Type != 0)
2043 status = HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE;
2044 else
2045 pBtHciInfo->enFlush_LLH = logicHandle;
2046
2047 if (bthci_DiscardTxPackets(padapter, pBtHciInfo->enFlush_LLH))
2048 bthci_EventFlushOccurred(padapter, pBtHciInfo->enFlush_LLH);
2049
2050 /* should send command status event */
2051 bthci_EventCommandStatus(padapter,
2052 OGF_SET_EVENT_MASK_COMMAND,
2053 HCI_ENHANCED_FLUSH,
2054 status);
2055
2056 if (pBtHciInfo->enFlush_LLH) {
2057 bthci_EventEnhancedFlushComplete(padapter, pBtHciInfo->enFlush_LLH);
2058 pBtHciInfo->enFlush_LLH = 0;
2059 }
2060
2061 return status;
2062}
2063
2064static enum hci_status
2065bthci_CmdReadLogicalLinkAcceptTimeout(
2066 struct rtw_adapter *padapter,
2067 struct packet_irp_hcicmd_data *pHciCmd
2068 )
2069{
2070 enum hci_status status = HCI_STATUS_SUCCESS;
2071/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
2072 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
2073 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
2074 u8 localBuf[8] = "";
2075 u8 *pRetPar;
2076 u8 len = 0;
2077 struct packet_irp_hcievent_data *PPacketIrpEvent;
2078 u16 *pu2Temp;
2079
2080 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2081
2082 len += bthci_CommandCompleteHeader(&localBuf[0],
2083 OGF_SET_EVENT_MASK_COMMAND,
2084 HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT,
2085 status);
2086
2087 /* Return parameters starts from here */
2088 pRetPar = &PPacketIrpEvent->Data[len];
2089 pRetPar[0] = status;
2090
2091 pu2Temp = (u16 *)&pRetPar[1]; /* Conn_Accept_Timeout */
2092 *pu2Temp = pBtHciInfo->LogicalAcceptTimeout;
2093 len += 3;
2094 PPacketIrpEvent->Length = len;
2095
2096 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2097
2098 return status;
2099}
2100
2101static enum hci_status
2102bthci_CmdWriteLogicalLinkAcceptTimeout(
2103 struct rtw_adapter *padapter,
2104 struct packet_irp_hcicmd_data *pHciCmd
2105 )
2106{
2107 enum hci_status status = HCI_STATUS_SUCCESS;
2108/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
2109 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
2110 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
2111 u8 localBuf[6] = "";
2112 u8 *pRetPar;
2113 u8 len = 0;
2114 struct packet_irp_hcievent_data *PPacketIrpEvent;
2115
2116 pBtHciInfo->LogicalAcceptTimeout = *((u16 *)pHciCmd->Data);
2117
2118 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2119
2120 len += bthci_CommandCompleteHeader(&localBuf[0],
2121 OGF_SET_EVENT_MASK_COMMAND,
2122 HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT,
2123 status);
2124
2125 /* Return parameters starts from here */
2126 pRetPar = &PPacketIrpEvent->Data[len];
2127 pRetPar[0] = status;
2128
2129 len += 1;
2130 PPacketIrpEvent->Length = len;
2131
2132 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2133 return status;
2134}
2135
2136static enum hci_status
2137bthci_CmdSetEventMask(
2138 struct rtw_adapter *padapter,
2139 struct packet_irp_hcicmd_data *pHciCmd
2140 )
2141{
2142 enum hci_status status = HCI_STATUS_SUCCESS;
2143/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
2144 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
2145 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
2146 u8 *pu8Temp;
2147 u8 localBuf[6] = "";
2148 u8 *pRetPar;
2149 u8 len = 0;
2150 struct packet_irp_hcievent_data *PPacketIrpEvent;
2151
2152 pu8Temp = (u8 *)&pHciCmd->Data[0];
2153 pBtHciInfo->BTEventMask = *pu8Temp;
2154 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("BTEventMask = 0x%"i64fmt"x\n",
2155 pBtHciInfo->BTEventMask));
2156
2157 /* send command complete event here when all data are received. */
2158 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2159
2160 len += bthci_CommandCompleteHeader(&localBuf[0],
2161 OGF_SET_EVENT_MASK_COMMAND,
2162 HCI_SET_EVENT_MASK,
2163 status);
2164
2165 /* Return parameters starts from here */
2166 pRetPar = &PPacketIrpEvent->Data[len];
2167 pRetPar[0] = status; /* status */
2168 len += 1;
2169 PPacketIrpEvent->Length = len;
2170
2171 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2172
2173 return status;
2174}
2175
2176/* 7.3.69 */
2177static enum hci_status
2178bthci_CmdSetEventMaskPage2(
2179 struct rtw_adapter *padapter,
2180 struct packet_irp_hcicmd_data *pHciCmd
2181 )
2182{
2183 enum hci_status status = HCI_STATUS_SUCCESS;
2184 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
2185 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
2186 u8 *pu8Temp;
2187 u8 localBuf[6] = "";
2188 u8 *pRetPar;
2189 u8 len = 0;
2190 struct packet_irp_hcievent_data *PPacketIrpEvent;
2191
2192 pu8Temp = (u8 *)&pHciCmd->Data[0];
2193 pBtHciInfo->BTEventMaskPage2 = *pu8Temp;
2194 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("BTEventMaskPage2 = 0x%"i64fmt"x\n",
2195 pBtHciInfo->BTEventMaskPage2));
2196
2197 /* send command complete event here when all data are received. */
2198 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2199
2200 len += bthci_CommandCompleteHeader(&localBuf[0],
2201 OGF_SET_EVENT_MASK_COMMAND,
2202 HCI_SET_EVENT_MASK_PAGE_2,
2203 status);
2204
2205 /* Return parameters starts from here */
2206 pRetPar = &PPacketIrpEvent->Data[len];
2207 pRetPar[0] = status; /* status */
2208 len += 1;
2209 PPacketIrpEvent->Length = len;
2210
2211 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2212
2213 return status;
2214}
2215
2216static enum hci_status
2217bthci_CmdReadLocationData(
2218 struct rtw_adapter *padapter,
2219 struct packet_irp_hcicmd_data *pHciCmd
2220 )
2221{
2222 enum hci_status status = HCI_STATUS_SUCCESS;
2223 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
2224 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
2225 u8 localBuf[12] = "";
2226 u8 *pRetPar;
2227 u8 len = 0;
2228 struct packet_irp_hcievent_data *PPacketIrpEvent;
2229 u16 *pu2Temp;
2230
2231 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2232
2233 len += bthci_CommandCompleteHeader(&localBuf[0],
2234 OGF_SET_EVENT_MASK_COMMAND,
2235 HCI_READ_LOCATION_DATA,
2236 status);
2237 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainAware = 0x%x\n", pBtHciInfo->LocationDomainAware));
2238 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Domain = 0x%x\n", pBtHciInfo->LocationDomain));
2239 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainOptions = 0x%x\n", pBtHciInfo->LocationDomainOptions));
2240 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Options = 0x%x\n", pBtHciInfo->LocationOptions));
2241
2242 /* Return parameters starts from here */
2243 pRetPar = &PPacketIrpEvent->Data[len];
2244 pRetPar[0] = status;
2245
2246 pRetPar[1] = pBtHciInfo->LocationDomainAware; /* 0x0; Location_Domain_Aware */
2247 pu2Temp = (u16 *)&pRetPar[2]; /* Location_Domain */
2248 *pu2Temp = pBtHciInfo->LocationDomain; /* 0x5858; */
2249 pRetPar[4] = pBtHciInfo->LocationDomainOptions; /* 0x58; Location_Domain_Options */
2250 pRetPar[5] = pBtHciInfo->LocationOptions; /* 0x0; Location_Options */
2251 len += 6;
2252 PPacketIrpEvent->Length = len;
2253
2254 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2255 return status;
2256}
2257
2258static enum hci_status
2259bthci_CmdWriteLocationData(
2260 struct rtw_adapter *padapter,
2261 struct packet_irp_hcicmd_data *pHciCmd
2262 )
2263{
2264 enum hci_status status = HCI_STATUS_SUCCESS;
2265 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
2266 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
2267 u16 *pu2Temp;
2268 u8 localBuf[6] = "";
2269 u8 *pRetPar;
2270 u8 len = 0;
2271 struct packet_irp_hcievent_data *PPacketIrpEvent;
2272
2273 pBtHciInfo->LocationDomainAware = pHciCmd->Data[0];
2274 pu2Temp = (u16 *)&pHciCmd->Data[1];
2275 pBtHciInfo->LocationDomain = *pu2Temp;
2276 pBtHciInfo->LocationDomainOptions = pHciCmd->Data[3];
2277 pBtHciInfo->LocationOptions = pHciCmd->Data[4];
2278 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainAware = 0x%x\n", pBtHciInfo->LocationDomainAware));
2279 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Domain = 0x%x\n", pBtHciInfo->LocationDomain));
2280 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainOptions = 0x%x\n", pBtHciInfo->LocationDomainOptions));
2281 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Options = 0x%x\n", pBtHciInfo->LocationOptions));
2282
2283 /* send command complete event here when all data are received. */
2284 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2285
2286 len += bthci_CommandCompleteHeader(&localBuf[0],
2287 OGF_SET_EVENT_MASK_COMMAND,
2288 HCI_WRITE_LOCATION_DATA,
2289 status);
2290
2291 /* Return parameters starts from here */
2292 pRetPar = &PPacketIrpEvent->Data[len];
2293 pRetPar[0] = status; /* status */
2294 len += 1;
2295 PPacketIrpEvent->Length = len;
2296
2297 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2298
2299 return status;
2300}
2301
2302static enum hci_status
2303bthci_CmdReadFlowControlMode(
2304 struct rtw_adapter *padapter,
2305 struct packet_irp_hcicmd_data *pHciCmd
2306 )
2307{
2308 enum hci_status status = HCI_STATUS_SUCCESS;
2309 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
2310 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
2311 u8 localBuf[7] = "";
2312 u8 *pRetPar;
2313 u8 len = 0;
2314 struct packet_irp_hcievent_data *PPacketIrpEvent;
2315
2316 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2317
2318 len += bthci_CommandCompleteHeader(&localBuf[0],
2319 OGF_SET_EVENT_MASK_COMMAND,
2320 HCI_READ_FLOW_CONTROL_MODE,
2321 status);
2322
2323 /* Return parameters starts from here */
2324 pRetPar = &PPacketIrpEvent->Data[len];
2325 pRetPar[0] = status;
2326 pRetPar[1] = pBtHciInfo->FlowControlMode; /* Flow Control Mode */
2327 len += 2;
2328 PPacketIrpEvent->Length = len;
2329
2330 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2331 return status;
2332}
2333
2334static enum hci_status
2335bthci_CmdWriteFlowControlMode(
2336 struct rtw_adapter *padapter,
2337 struct packet_irp_hcicmd_data *pHciCmd
2338 )
2339{
2340 enum hci_status status = HCI_STATUS_SUCCESS;
2341 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
2342 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
2343 u8 localBuf[6] = "";
2344 u8 *pRetPar;
2345 u8 len = 0;
2346 struct packet_irp_hcievent_data *PPacketIrpEvent;
2347
2348 pBtHciInfo->FlowControlMode = pHciCmd->Data[0];
2349
2350 /* send command complete event here when all data are received. */
2351 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2352
2353 len += bthci_CommandCompleteHeader(&localBuf[0],
2354 OGF_SET_EVENT_MASK_COMMAND,
2355 HCI_WRITE_FLOW_CONTROL_MODE,
2356 status);
2357
2358 /* Return parameters starts from here */
2359 pRetPar = &PPacketIrpEvent->Data[len];
2360 pRetPar[0] = status; /* status */
2361 len += 1;
2362 PPacketIrpEvent->Length = len;
2363
2364 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2365
2366 return status;
2367}
2368
2369static enum hci_status
2370bthci_CmdReadBestEffortFlushTimeout(
2371 struct rtw_adapter *padapter,
2372 struct packet_irp_hcicmd_data *pHciCmd
2373 )
2374{
2375 enum hci_status status = HCI_STATUS_SUCCESS;
2376 struct bt_30info *pBTinfo = GET_BT_INFO(padapter);
2377 u16 i, j, logicHandle;
2378 u32 BestEffortFlushTimeout = 0xffffffff;
2379 u8 find = 0;
2380
2381 logicHandle = *((u16 *)pHciCmd->Data);
2382 /* find an matched logical link index and copy the data */
2383 for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) {
2384 for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) {
2385 if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle) {
2386 BestEffortFlushTimeout = pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BestEffortFlushTimeout;
2387 find = 1;
2388 break;
2389 }
2390 }
2391 }
2392
2393 if (!find)
2394 status = HCI_STATUS_UNKNOW_CONNECT_ID;
2395
2396 {
2397 u8 localBuf[10] = "";
2398 u8 *pRetPar;
2399 u8 len = 0;
2400 struct packet_irp_hcievent_data *PPacketIrpEvent;
2401 u32 *pu4Temp;
2402
2403 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2404
2405 len += bthci_CommandCompleteHeader(&localBuf[0],
2406 OGF_SET_EVENT_MASK_COMMAND,
2407 HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT,
2408 status);
2409
2410 /* Return parameters starts from here */
2411 pRetPar = &PPacketIrpEvent->Data[len];
2412 pRetPar[0] = status;
2413 pu4Temp = (u32 *)&pRetPar[1]; /* Best_Effort_Flush_Timeout */
2414 *pu4Temp = BestEffortFlushTimeout;
2415 len += 5;
2416 PPacketIrpEvent->Length = len;
2417
2418 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2419 }
2420 return status;
2421}
2422
2423static enum hci_status
2424bthci_CmdWriteBestEffortFlushTimeout(
2425 struct rtw_adapter *padapter,
2426 struct packet_irp_hcicmd_data *pHciCmd
2427 )
2428{
2429 enum hci_status status = HCI_STATUS_SUCCESS;
2430 struct bt_30info *pBTinfo = GET_BT_INFO(padapter);
2431 u16 i, j, logicHandle;
2432 u32 BestEffortFlushTimeout = 0xffffffff;
2433 u8 find = 0;
2434
2435 logicHandle = *((u16 *)pHciCmd->Data);
2436 BestEffortFlushTimeout = *((u32 *)(pHciCmd->Data+1));
2437
2438 /* find an matched logical link index and copy the data */
2439 for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) {
2440 for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) {
2441 if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle) {
2442 pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BestEffortFlushTimeout = BestEffortFlushTimeout;
2443 find = 1;
2444 break;
2445 }
2446 }
2447 }
2448
2449 if (!find)
2450 status = HCI_STATUS_UNKNOW_CONNECT_ID;
2451
2452 {
2453 u8 localBuf[6] = "";
2454 u8 *pRetPar;
2455 u8 len = 0;
2456 struct packet_irp_hcievent_data *PPacketIrpEvent;
2457
2458 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2459
2460 len += bthci_CommandCompleteHeader(&localBuf[0],
2461 OGF_SET_EVENT_MASK_COMMAND,
2462 HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT,
2463 status);
2464
2465 /* Return parameters starts from here */
2466 pRetPar = &PPacketIrpEvent->Data[len];
2467 pRetPar[0] = status;
2468 len += 1;
2469 PPacketIrpEvent->Length = len;
2470
2471 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2472 }
2473 return status;
2474}
2475
2476static enum hci_status
2477bthci_CmdShortRangeMode(
2478 struct rtw_adapter *padapter,
2479 struct packet_irp_hcicmd_data *pHciCmd
2480 )
2481{
2482 enum hci_status status = HCI_STATUS_SUCCESS;
2483 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
2484 u8 PhyLinkHandle, EntryNum, ShortRangeMode;
2485
2486 PhyLinkHandle = pHciCmd->Data[0];
2487 ShortRangeMode = pHciCmd->Data[1];
2488 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("PLH = 0x%x, Short_Range_Mode = 0x%x\n", PhyLinkHandle, ShortRangeMode));
2489
2490 EntryNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle);
2491 if (EntryNum != 0xff) {
2492 pBTInfo->BtAsocEntry[EntryNum].ShortRangeMode = ShortRangeMode;
2493 } else {
2494 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("No such PLH(0x%x)\n", PhyLinkHandle));
2495 status = HCI_STATUS_UNKNOW_CONNECT_ID;
2496 }
2497
2498 bthci_EventCommandStatus(padapter,
2499 OGF_SET_EVENT_MASK_COMMAND,
2500 HCI_SHORT_RANGE_MODE,
2501 status);
2502
2503 bthci_EventShortRangeModeChangeComplete(padapter, status, ShortRangeMode, EntryNum);
2504
2505 return status;
2506}
2507
2508static enum hci_status bthci_CmdReadLocalSupportedCommands(struct rtw_adapter *padapter)
2509{
2510 enum hci_status status = HCI_STATUS_SUCCESS;
2511 u8 localBuf[TmpLocalBufSize] = "";
2512 u8 *pRetPar, *pSupportedCmds;
2513 u8 len = 0;
2514 struct packet_irp_hcievent_data *PPacketIrpEvent;
2515
2516 /* send command complete event here when all data are received. */
2517 PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
2518 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2519
2520 len += bthci_CommandCompleteHeader(&localBuf[0],
2521 OGF_INFORMATIONAL_PARAMETERS,
2522 HCI_READ_LOCAL_SUPPORTED_COMMANDS,
2523 status);
2524
2525 /* Return parameters starts from here */
2526 pRetPar = &PPacketIrpEvent->Data[len];
2527 pRetPar[0] = status; /* status */
2528 len += 1;
2529 pSupportedCmds = &pRetPar[1];
2530 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[5]= 0xc0\nBit [6]= Set Event Mask, [7]= Reset\n"));
2531 pSupportedCmds[5] = 0xc0;
2532 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[6]= 0x01\nBit [0]= Set Event Filter\n"));
2533 pSupportedCmds[6] = 0x01;
2534 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[7]= 0x0c\nBit [2]= Read Connection Accept Timeout, [3]= Write Connection Accept Timeout\n"));
2535 pSupportedCmds[7] = 0x0c;
2536 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[10]= 0x80\nBit [7]= Host Number Of Completed Packets\n"));
2537 pSupportedCmds[10] = 0x80;
2538 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[11]= 0x03\nBit [0]= Read Link Supervision Timeout, [1]= Write Link Supervision Timeout\n"));
2539 pSupportedCmds[11] = 0x03;
2540 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[14]= 0xa8\nBit [3]= Read Local Version Information, [5]= Read Local Supported Features, [7]= Read Buffer Size\n"));
2541 pSupportedCmds[14] = 0xa8;
2542 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[15]= 0x1c\nBit [2]= Read Failed Contact Count, [3]= Reset Failed Contact Count, [4]= Get Link Quality\n"));
2543 pSupportedCmds[15] = 0x1c;
2544 /* pSupportedCmds[16] = 0x04; */
2545 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[19]= 0x40\nBit [6]= Enhanced Flush\n"));
2546 pSupportedCmds[19] = 0x40;
2547 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[21]= 0xff\nBit [0]= Create Physical Link, [1]= Accept Physical Link, [2]= Disconnect Physical Link, [3]= Create Logical Link\n"));
2548 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), (" [4]= Accept Logical Link, [5]= Disconnect Logical Link, [6]= Logical Link Cancel, [7]= Flow Spec Modify\n"));
2549 pSupportedCmds[21] = 0xff;
2550 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[22]= 0xff\nBit [0]= Read Logical Link Accept Timeout, [1]= Write Logical Link Accept Timeout, [2]= Set Event Mask Page 2, [3]= Read Location Data\n"));
2551 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), (" [4]= Write Location Data, [5]= Read Local AMP Info, [6]= Read Local AMP_ASSOC, [7]= Write Remote AMP_ASSOC\n"));
2552 pSupportedCmds[22] = 0xff;
2553 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[23]= 0x07\nBit [0]= Read Flow Control Mode, [1]= Write Flow Control Mode, [2]= Read Data Block Size\n"));
2554 pSupportedCmds[23] = 0x07;
2555 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[24]= 0x1c\nBit [2]= Read Best Effort Flush Timeout, [3]= Write Best Effort Flush Timeout, [4]= Short Range Mode\n"));
2556 pSupportedCmds[24] = 0x1c;
2557 len += 64;
2558 PPacketIrpEvent->Length = len;
2559
2560 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2561
2562 return status;
2563}
2564
2565static enum hci_status bthci_CmdReadLocalSupportedFeatures(struct rtw_adapter *padapter)
2566{
2567 enum hci_status status = HCI_STATUS_SUCCESS;
2568 u8 localBuf[TmpLocalBufSize] = "";
2569 u8 *pRetPar;
2570 u8 len = 0;
2571 struct packet_irp_hcievent_data *PPacketIrpEvent;
2572
2573 /* send command complete event here when all data are received. */
2574 PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
2575 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2576
2577 len += bthci_CommandCompleteHeader(&localBuf[0],
2578 OGF_INFORMATIONAL_PARAMETERS,
2579 HCI_READ_LOCAL_SUPPORTED_FEATURES,
2580 status);
2581
2582 /* Return parameters starts from here */
2583 pRetPar = &PPacketIrpEvent->Data[len];
2584 pRetPar[0] = status; /* status */
2585 len += 9;
2586 PPacketIrpEvent->Length = len;
2587
2588 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2589 return status;
2590}
2591
2592static enum hci_status bthci_CmdReadLocalAMPAssoc(struct rtw_adapter *padapter,
2593 struct packet_irp_hcicmd_data *pHciCmd)
2594{
2595 enum hci_status status = HCI_STATUS_SUCCESS;
2596 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
2597 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
2598 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
2599 u8 PhyLinkHandle, EntryNum;
2600
2601 pBtDbg->dbgHciInfo.hciCmdCntReadLocalAmpAssoc++;
2602 PhyLinkHandle = *((u8 *)pHciCmd->Data);
2603 EntryNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle);
2604
2605 if ((EntryNum == 0xff) && PhyLinkHandle != 0) {
2606 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, EntryNum = %d !!!!!, physical link handle = 0x%x\n",
2607 EntryNum, PhyLinkHandle));
2608 status = HCI_STATUS_UNKNOW_CONNECT_ID;
2609 } else if (pBtMgnt->bPhyLinkInProgressStartLL) {
2610 status = HCI_STATUS_UNKNOW_CONNECT_ID;
2611 pBtMgnt->bPhyLinkInProgressStartLL = false;
2612 } else {
2613 pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.BtPhyLinkhandle = *((u8 *)pHciCmd->Data);
2614 pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar = *((u16 *)((u8 *)pHciCmd->Data+1));
2615 pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.MaxRemoteASSOCLen = *((u16 *)((u8 *)pHciCmd->Data+3));
2616 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("ReadLocalAMPAssoc, LenSoFar =%d, MaxRemoteASSOCLen =%d\n",
2617 pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar,
2618 pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.MaxRemoteASSOCLen));
2619 }
2620
2621 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, EntryNum = %d !!!!!, physical link handle = 0x%x, LengthSoFar = %x \n",
2622 EntryNum, PhyLinkHandle, pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar));
2623
2624 /* send command complete event here when all data are received. */
2625 {
2626 struct packet_irp_hcievent_data *PPacketIrpEvent;
2627
2628 /* PVOID buffer = padapter->IrpHCILocalbuf.Ptr; */
2629 u8 localBuf[TmpLocalBufSize] = "";
2630 u16 *pRemainLen;
2631 u32 totalLen = 0;
2632 u16 typeLen = 0, remainLen = 0, ret_index = 0;
2633 u8 *pRetPar;
2634
2635 PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
2636 /* PPacketIrpEvent = (struct packet_irp_hcievent_data *)(buffer); */
2637 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2638
2639 totalLen += bthci_CommandCompleteHeader(&localBuf[0],
2640 OGF_STATUS_PARAMETERS,
2641 HCI_READ_LOCAL_AMP_ASSOC,
2642 status);
2643 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, Remaining_Len =%d \n", remainLen));
2644 /* Return parameters starts from here */
2645 pRetPar = &PPacketIrpEvent->Data[totalLen];
2646 pRetPar[0] = status; /* status */
2647 pRetPar[1] = *((u8 *)pHciCmd->Data);
2648 pRemainLen = (u16 *)&pRetPar[2]; /* AMP_ASSOC_Remaining_Length */
2649 totalLen += 4; /* 0]~[3] */
2650 ret_index = 4;
2651
2652 typeLen = bthci_AssocMACAddr(padapter, &pRetPar[ret_index]);
2653 totalLen += typeLen;
2654 remainLen += typeLen;
2655 ret_index += typeLen;
2656 typeLen = bthci_AssocPreferredChannelList(padapter, &pRetPar[ret_index], EntryNum);
2657 totalLen += typeLen;
2658 remainLen += typeLen;
2659 ret_index += typeLen;
2660 typeLen = bthci_PALCapabilities(padapter, &pRetPar[ret_index]);
2661 totalLen += typeLen;
2662 remainLen += typeLen;
2663 ret_index += typeLen;
2664 typeLen = bthci_AssocPALVer(padapter, &pRetPar[ret_index]);
2665 totalLen += typeLen;
2666 remainLen += typeLen;
2667 PPacketIrpEvent->Length = (u8)totalLen;
2668 *pRemainLen = remainLen; /* AMP_ASSOC_Remaining_Length */
2669 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, Remaining_Len =%d \n", remainLen));
2670 RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("AMP_ASSOC_fragment : \n"), PPacketIrpEvent->Data, totalLen);
2671
2672 bthci_IndicateEvent(padapter, PPacketIrpEvent, totalLen+2);
2673 }
2674
2675 return status;
2676}
2677
2678static enum hci_status bthci_CmdReadFailedContactCounter(struct rtw_adapter *padapter,
2679 struct packet_irp_hcicmd_data *pHciCmd)
2680{
2681
2682 enum hci_status status = HCI_STATUS_SUCCESS;
2683 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
2684 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
2685 u8 localBuf[TmpLocalBufSize] = "";
2686 u8 *pRetPar;
2687 u8 len = 0;
2688 struct packet_irp_hcievent_data *PPacketIrpEvent;
2689 u16 handle;
2690
2691 handle = *((u16 *)pHciCmd->Data);
2692 /* send command complete event here when all data are received. */
2693 PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
2694 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2695
2696 len += bthci_CommandCompleteHeader(&localBuf[0],
2697 OGF_STATUS_PARAMETERS,
2698 HCI_READ_FAILED_CONTACT_COUNTER,
2699 status);
2700
2701 /* Return parameters starts from here */
2702 pRetPar = &PPacketIrpEvent->Data[len];
2703 pRetPar[0] = status; /* status */
2704 pRetPar[1] = TWOBYTE_LOWBYTE(handle);
2705 pRetPar[2] = TWOBYTE_HIGHTBYTE(handle);
2706 pRetPar[3] = TWOBYTE_LOWBYTE(pBtHciInfo->FailContactCount);
2707 pRetPar[4] = TWOBYTE_HIGHTBYTE(pBtHciInfo->FailContactCount);
2708 len += 5;
2709 PPacketIrpEvent->Length = len;
2710
2711 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2712
2713 return status;
2714}
2715
2716static enum hci_status
2717bthci_CmdResetFailedContactCounter(
2718 struct rtw_adapter *padapter,
2719 struct packet_irp_hcicmd_data *pHciCmd
2720 )
2721{
2722 enum hci_status status = HCI_STATUS_SUCCESS;
2723/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
2724 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
2725 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
2726 u16 handle;
2727 u8 localBuf[TmpLocalBufSize] = "";
2728 u8 *pRetPar;
2729 u8 len = 0;
2730 struct packet_irp_hcievent_data *PPacketIrpEvent;
2731
2732 handle = *((u16 *)pHciCmd->Data);
2733 pBtHciInfo->FailContactCount = 0;
2734
2735 /* send command complete event here when all data are received. */
2736 PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
2737 /* PPacketIrpEvent = (struct packet_irp_hcievent_data *)(buffer); */
2738 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2739
2740 len += bthci_CommandCompleteHeader(&localBuf[0],
2741 OGF_STATUS_PARAMETERS,
2742 HCI_RESET_FAILED_CONTACT_COUNTER,
2743 status);
2744
2745 /* Return parameters starts from here */
2746 pRetPar = &PPacketIrpEvent->Data[len];
2747 pRetPar[0] = status; /* status */
2748 pRetPar[1] = TWOBYTE_LOWBYTE(handle);
2749 pRetPar[2] = TWOBYTE_HIGHTBYTE(handle);
2750 len += 3;
2751 PPacketIrpEvent->Length = len;
2752
2753 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2754 return status;
2755}
2756
2757/* */
2758/* BT 3.0+HS [Vol 2] 7.4.1 */
2759/* */
2760static enum hci_status
2761bthci_CmdReadLocalVersionInformation(
2762 struct rtw_adapter *padapter
2763 )
2764{
2765 enum hci_status status = HCI_STATUS_SUCCESS;
2766 /* send command complete event here when all data are received. */
2767 u8 localBuf[TmpLocalBufSize] = "";
2768 u8 *pRetPar;
2769 u8 len = 0;
2770 struct packet_irp_hcievent_data *PPacketIrpEvent;
2771 u16 *pu2Temp;
2772
2773 PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
2774 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2775
2776 len += bthci_CommandCompleteHeader(&localBuf[0],
2777 OGF_INFORMATIONAL_PARAMETERS,
2778 HCI_READ_LOCAL_VERSION_INFORMATION,
2779 status);
2780
2781 /* Return parameters starts from here */
2782 pRetPar = &PPacketIrpEvent->Data[len];
2783 pRetPar[0] = status; /* status */
2784 pRetPar[1] = 0x05; /* HCI_Version */
2785 pu2Temp = (u16 *)&pRetPar[2]; /* HCI_Revision */
2786 *pu2Temp = 0x0001;
2787 pRetPar[4] = 0x05; /* LMP/PAL_Version */
2788 pu2Temp = (u16 *)&pRetPar[5]; /* Manufacturer_Name */
2789 *pu2Temp = 0x005d;
2790 pu2Temp = (u16 *)&pRetPar[7]; /* LMP/PAL_Subversion */
2791 *pu2Temp = 0x0001;
2792 len += 9;
2793 PPacketIrpEvent->Length = len;
2794
2795 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("LOCAL_VERSION_INFORMATION\n"));
2796 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("Status %x\n", status));
2797 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("HCI_Version = 0x05\n"));
2798 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("HCI_Revision = 0x0001\n"));
2799 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("LMP/PAL_Version = 0x05\n"));
2800 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("Manufacturer_Name = 0x0001\n"));
2801 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("LMP/PAL_Subversion = 0x0001\n"));
2802
2803 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2804
2805 return status;
2806}
2807
2808/* 7.4.7 */
2809static enum hci_status bthci_CmdReadDataBlockSize(struct rtw_adapter *padapter)
2810{
2811 enum hci_status status = HCI_STATUS_SUCCESS;
2812 u8 localBuf[TmpLocalBufSize] = "";
2813 u8 *pRetPar;
2814 u8 len = 0;
2815 struct packet_irp_hcievent_data *PPacketIrpEvent;
2816 u16 *pu2Temp;
2817
2818 PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
2819 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2820
2821 len += bthci_CommandCompleteHeader(&localBuf[0],
2822 OGF_INFORMATIONAL_PARAMETERS,
2823 HCI_READ_DATA_BLOCK_SIZE,
2824 status);
2825
2826 /* Return parameters starts from here */
2827 pRetPar = &PPacketIrpEvent->Data[len];
2828 pRetPar[0] = HCI_STATUS_SUCCESS; /* status */
2829 pu2Temp = (u16 *)&pRetPar[1]; /* Max_ACL_Data_Packet_Length */
2830 *pu2Temp = Max80211PALPDUSize;
2831
2832 pu2Temp = (u16 *)&pRetPar[3]; /* Data_Block_Length */
2833 *pu2Temp = Max80211PALPDUSize;
2834 pu2Temp = (u16 *)&pRetPar[5]; /* Total_Num_Data_Blocks */
2835 *pu2Temp = BTTotalDataBlockNum;
2836 len += 7;
2837 PPacketIrpEvent->Length = len;
2838
2839 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2840
2841 return status;
2842}
2843
2844/* 7.4.5 */
2845static enum hci_status bthci_CmdReadBufferSize(struct rtw_adapter *padapter)
2846{
2847 enum hci_status status = HCI_STATUS_SUCCESS;
2848 u8 localBuf[TmpLocalBufSize] = "";
2849 u8 *pRetPar;
2850 u8 len = 0;
2851 struct packet_irp_hcievent_data *PPacketIrpEvent;
2852 u16 *pu2Temp;
2853
2854 PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
2855 /* PPacketIrpEvent = (struct packet_irp_hcievent_data *)(buffer); */
2856 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2857
2858 len += bthci_CommandCompleteHeader(&localBuf[0],
2859 OGF_INFORMATIONAL_PARAMETERS,
2860 HCI_READ_BUFFER_SIZE,
2861 status);
2862 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Synchronous_Data_Packet_Length = 0x%x\n", BTSynDataPacketLength));
2863 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Total_Num_ACL_Data_Packets = 0x%x\n", BTTotalDataBlockNum));
2864 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Total_Num_Synchronous_Data_Packets = 0x%x\n", BTTotalDataBlockNum));
2865 /* Return parameters starts from here */
2866 pRetPar = &PPacketIrpEvent->Data[len];
2867 pRetPar[0] = status; /* status */
2868 pu2Temp = (u16 *)&pRetPar[1]; /* HC_ACL_Data_Packet_Length */
2869 *pu2Temp = Max80211PALPDUSize;
2870
2871 pRetPar[3] = BTSynDataPacketLength; /* HC_Synchronous_Data_Packet_Length */
2872 pu2Temp = (u16 *)&pRetPar[4]; /* HC_Total_Num_ACL_Data_Packets */
2873 *pu2Temp = BTTotalDataBlockNum;
2874 pu2Temp = (u16 *)&pRetPar[6]; /* HC_Total_Num_Synchronous_Data_Packets */
2875 *pu2Temp = BTTotalDataBlockNum;
2876 len += 8;
2877 PPacketIrpEvent->Length = len;
2878
2879 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2880
2881 return status;
2882}
2883
2884static enum hci_status bthci_CmdReadLocalAMPInfo(struct rtw_adapter *padapter)
2885{
2886 enum hci_status status = HCI_STATUS_SUCCESS;
2887 struct pwrctrl_priv *ppwrctrl = &padapter->pwrctrlpriv;
2888 u8 localBuf[TmpLocalBufSize] = "";
2889 u8 *pRetPar;
2890 u8 len = 0;
2891 struct packet_irp_hcievent_data *PPacketIrpEvent;
2892 u16 *pu2Temp;
2893 u32 *pu4Temp;
2894 u32 TotalBandwidth = BTTOTALBANDWIDTH, MaxBandGUBandwidth = BTMAXBANDGUBANDWIDTH;
2895 u8 ControlType = 0x01, AmpStatus = 0x01;
2896 u32 MaxFlushTimeout = 10000, BestEffortFlushTimeout = 5000;
2897 u16 MaxPDUSize = Max80211PALPDUSize, PalCap = 0x1, AmpAssocLen = Max80211AMPASSOCLen, MinLatency = 20;
2898
2899 if ((ppwrctrl->rfoff_reason & RF_CHANGE_BY_HW) ||
2900 (ppwrctrl->rfoff_reason & RF_CHANGE_BY_SW)) {
2901 AmpStatus = AMP_STATUS_NO_CAPACITY_FOR_BT;
2902 }
2903
2904 PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
2905 /* PPacketIrpEvent = (struct packet_irp_hcievent_data *)(buffer); */
2906 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2907
2908 len += bthci_CommandCompleteHeader(&localBuf[0],
2909 OGF_STATUS_PARAMETERS,
2910 HCI_READ_LOCAL_AMP_INFO,
2911 status);
2912
2913 /* Return parameters starts from here */
2914 pRetPar = &PPacketIrpEvent->Data[len];
2915 pRetPar[0] = status; /* status */
2916 pRetPar[1] = AmpStatus; /* AMP_Status */
2917 pu4Temp = (u32 *)&pRetPar[2]; /* Total_Bandwidth */
2918 *pu4Temp = TotalBandwidth; /* 0x19bfcc00;0x7530; */
2919 pu4Temp = (u32 *)&pRetPar[6]; /* Max_Guaranteed_Bandwidth */
2920 *pu4Temp = MaxBandGUBandwidth; /* 0x19bfcc00;0x4e20; */
2921 pu4Temp = (u32 *)&pRetPar[10]; /* Min_Latency */
2922 *pu4Temp = MinLatency; /* 150; */
2923 pu4Temp = (u32 *)&pRetPar[14]; /* Max_PDU_Size */
2924 *pu4Temp = MaxPDUSize;
2925 pRetPar[18] = ControlType; /* Controller_Type */
2926 pu2Temp = (u16 *)&pRetPar[19]; /* PAL_Capabilities */
2927 *pu2Temp = PalCap;
2928 pu2Temp = (u16 *)&pRetPar[21]; /* AMP_ASSOC_Length */
2929 *pu2Temp = AmpAssocLen;
2930 pu4Temp = (u32 *)&pRetPar[23]; /* Max_Flush_Timeout */
2931 *pu4Temp = MaxFlushTimeout;
2932 pu4Temp = (u32 *)&pRetPar[27]; /* Best_Effort_Flush_Timeout */
2933 *pu4Temp = BestEffortFlushTimeout;
2934 len += 31;
2935 PPacketIrpEvent->Length = len;
2936 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("AmpStatus = 0x%x\n",
2937 AmpStatus));
2938 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("TotalBandwidth = 0x%x, MaxBandGUBandwidth = 0x%x, MinLatency = 0x%x, \n MaxPDUSize = 0x%x, ControlType = 0x%x\n",
2939 TotalBandwidth, MaxBandGUBandwidth, MinLatency, MaxPDUSize, ControlType));
2940 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("PalCap = 0x%x, AmpAssocLen = 0x%x, MaxFlushTimeout = 0x%x, BestEffortFlushTimeout = 0x%x\n",
2941 PalCap, AmpAssocLen, MaxFlushTimeout, BestEffortFlushTimeout));
2942 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
2943 return status;
2944}
2945
2946static enum hci_status
2947bthci_CmdCreatePhysicalLink(
2948 struct rtw_adapter *padapter,
2949 struct packet_irp_hcicmd_data *pHciCmd
2950 )
2951{
2952 enum hci_status status;
2953 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
2954 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
2955
2956 pBtDbg->dbgHciInfo.hciCmdCntCreatePhyLink++;
2957
2958 status = bthci_BuildPhysicalLink(padapter,
2959 pHciCmd, HCI_CREATE_PHYSICAL_LINK);
2960
2961 return status;
2962}
2963
2964static enum hci_status
2965bthci_CmdReadLinkQuality(
2966 struct rtw_adapter *padapter,
2967 struct packet_irp_hcicmd_data *pHciCmd
2968 )
2969{
2970 enum hci_status status = HCI_STATUS_SUCCESS;
2971 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
2972 u16 PLH;
2973 u8 EntryNum, LinkQuality = 0x55;
2974
2975 PLH = *((u16 *)&pHciCmd->Data[0]);
2976 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("PLH = 0x%x\n", PLH));
2977
2978 EntryNum = bthci_GetCurrentEntryNum(padapter, (u8)PLH);
2979 if (EntryNum == 0xff) {
2980 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("No such PLH(0x%x)\n", PLH));
2981 status = HCI_STATUS_UNKNOW_CONNECT_ID;
2982 }
2983
2984 {
2985 u8 localBuf[11] = "";
2986 u8 *pRetPar;
2987 u8 len = 0;
2988 struct packet_irp_hcievent_data *PPacketIrpEvent;
2989
2990 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
2991
2992 len += bthci_CommandCompleteHeader(&localBuf[0],
2993 OGF_STATUS_PARAMETERS,
2994 HCI_READ_LINK_QUALITY,
2995 status);
2996
2997 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, (" PLH = 0x%x\n Link Quality = 0x%x\n", PLH, LinkQuality));
2998
2999 /* Return parameters starts from here */
3000 pRetPar = &PPacketIrpEvent->Data[len];
3001 pRetPar[0] = status; /* status */
3002 *((u16 *)&pRetPar[1]) = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle; /* Handle */
3003 pRetPar[3] = 0x55; /* Link Quailty */
3004 len += 4;
3005 PPacketIrpEvent->Length = len;
3006
3007 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3008 }
3009
3010 return status;
3011}
3012
3013static enum hci_status bthci_CmdReadRSSI(struct rtw_adapter *padapter)
3014{
3015 enum hci_status status = HCI_STATUS_SUCCESS;
3016 return status;
3017}
3018
3019static enum hci_status
3020bthci_CmdCreateLogicalLink(
3021 struct rtw_adapter *padapter,
3022 struct packet_irp_hcicmd_data *pHciCmd
3023 )
3024{
3025 enum hci_status status = HCI_STATUS_SUCCESS;
3026 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3027 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
3028
3029 pBtDbg->dbgHciInfo.hciCmdCntCreateLogLink++;
3030
3031 bthci_BuildLogicalLink(padapter, pHciCmd,
3032 HCI_CREATE_LOGICAL_LINK);
3033
3034 return status;
3035}
3036
3037static enum hci_status
3038bthci_CmdAcceptLogicalLink(
3039 struct rtw_adapter *padapter,
3040 struct packet_irp_hcicmd_data *pHciCmd
3041 )
3042{
3043 enum hci_status status = HCI_STATUS_SUCCESS;
3044 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3045 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
3046
3047 pBtDbg->dbgHciInfo.hciCmdCntAcceptLogLink++;
3048
3049 bthci_BuildLogicalLink(padapter, pHciCmd,
3050 HCI_ACCEPT_LOGICAL_LINK);
3051
3052 return status;
3053}
3054
3055static enum hci_status
3056bthci_CmdDisconnectLogicalLink(
3057 struct rtw_adapter *padapter,
3058 struct packet_irp_hcicmd_data *pHciCmd
3059 )
3060{
3061 enum hci_status status = HCI_STATUS_SUCCESS;
3062/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
3063 struct bt_30info *pBTinfo = GET_BT_INFO(padapter);
3064 struct bt_mgnt *pBtMgnt = &pBTinfo->BtMgnt;
3065 struct bt_dgb *pBtDbg = &pBTinfo->BtDbg;
3066 u16 logicHandle;
3067 u8 i, j, find = 0, LogLinkCount = 0;
3068
3069 pBtDbg->dbgHciInfo.hciCmdCntDisconnectLogLink++;
3070
3071 logicHandle = *((u16 *)pHciCmd->Data);
3072 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DisconnectLogicalLink, logicHandle = 0x%x\n", logicHandle));
3073
3074 /* find an created logical link index and clear the data */
3075 for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) {
3076 for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) {
3077 if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle) {
3078 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DisconnectLogicalLink, logicHandle is matched 0x%x\n", logicHandle));
3079 bthci_ResetFlowSpec(padapter, j, i);
3080 find = 1;
3081 pBtMgnt->DisconnectEntryNum = j;
3082 break;
3083 }
3084 }
3085 }
3086
3087 if (!find)
3088 status = HCI_STATUS_UNKNOW_CONNECT_ID;
3089
3090 /* To check each */
3091 for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) {
3092 if (pBTinfo->BtAsocEntry[pBtMgnt->DisconnectEntryNum].LogLinkCmdData[i].BtLogLinkhandle != 0)
3093 LogLinkCount++;
3094 }
3095
3096 /* When we receive Create logical link command, we should send command status event first. */
3097 bthci_EventCommandStatus(padapter,
3098 LINK_CONTROL_COMMANDS,
3099 HCI_DISCONNECT_LOGICAL_LINK,
3100 status);
3101 /* */
3102 /* When we determines the logical link is established, we should send command complete event. */
3103 /* */
3104 if (status == HCI_STATUS_SUCCESS) {
3105 bthci_EventDisconnectLogicalLinkComplete(padapter, status,
3106 logicHandle, HCI_STATUS_CONNECT_TERMINATE_LOCAL_HOST);
3107 }
3108
3109 if (LogLinkCount == 0)
3110 mod_timer(&pBTinfo->BTDisconnectPhyLinkTimer,
3111 jiffies + msecs_to_jiffies(100));
3112
3113 return status;
3114}
3115
3116static enum hci_status
3117bthci_CmdLogicalLinkCancel(struct rtw_adapter *padapter,
3118 struct packet_irp_hcicmd_data *pHciCmd)
3119{
3120 enum hci_status status = HCI_STATUS_SUCCESS;
3121 struct bt_30info *pBTinfo = GET_BT_INFO(padapter);
3122 struct bt_mgnt *pBtMgnt = &pBTinfo->BtMgnt;
3123 u8 CurrentEntryNum, CurrentLogEntryNum;
3124
3125 u8 physicalLinkHandle, TxFlowSpecID, i;
3126 u16 CurrentLogicalHandle;
3127
3128 physicalLinkHandle = *((u8 *)pHciCmd->Data);
3129 TxFlowSpecID = *(((u8 *)pHciCmd->Data)+1);
3130
3131 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("LogicalLinkCancel, physicalLinkHandle = 0x%x, TxFlowSpecID = 0x%x\n",
3132 physicalLinkHandle, TxFlowSpecID));
3133
3134 CurrentEntryNum = pBtMgnt->CurrentConnectEntryNum;
3135 CurrentLogicalHandle = pBtMgnt->BtCurrentLogLinkhandle;
3136
3137 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("CurrentEntryNum = 0x%x, CurrentLogicalHandle = 0x%x\n",
3138 CurrentEntryNum, CurrentLogicalHandle));
3139
3140 CurrentLogEntryNum = 0xff;
3141 for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) {
3142 if ((CurrentLogicalHandle == pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[i].BtLogLinkhandle) &&
3143 (physicalLinkHandle == pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[i].BtPhyLinkhandle)) {
3144 CurrentLogEntryNum = i;
3145 break;
3146 }
3147 }
3148
3149 if (CurrentLogEntryNum == 0xff) {
3150 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("LogicalLinkCancel, CurrentLogEntryNum == 0xff !!!!\n"));
3151 status = HCI_STATUS_UNKNOW_CONNECT_ID;
3152 return status;
3153 } else {
3154 if (pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].bLLCompleteEventIsSet) {
3155 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("LogicalLinkCancel, LLCompleteEventIsSet!!!!\n"));
3156 status = HCI_STATUS_ACL_CONNECT_EXISTS;
3157 }
3158 }
3159
3160 {
3161 u8 localBuf[8] = "";
3162 u8 *pRetPar;
3163 u8 len = 0;
3164 struct packet_irp_hcievent_data *PPacketIrpEvent;
3165
3166 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3167
3168 len += bthci_CommandCompleteHeader(&localBuf[0],
3169 LINK_CONTROL_COMMANDS,
3170 HCI_LOGICAL_LINK_CANCEL,
3171 status);
3172
3173 /* Return parameters starts from here */
3174 pRetPar = &PPacketIrpEvent->Data[len];
3175 pRetPar[0] = status; /* status */
3176 pRetPar[1] = pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].BtPhyLinkhandle;
3177 pRetPar[2] = pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].BtTxFlowSpecID;
3178 len += 3;
3179 PPacketIrpEvent->Length = len;
3180
3181 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3182 }
3183
3184 pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].bLLCancelCMDIsSetandComplete = true;
3185
3186 return status;
3187}
3188
3189static enum hci_status
3190bthci_CmdFlowSpecModify(struct rtw_adapter *padapter,
3191 struct packet_irp_hcicmd_data *pHciCmd)
3192{
3193 enum hci_status status = HCI_STATUS_SUCCESS;
3194/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
3195 struct bt_30info *pBTinfo = GET_BT_INFO(padapter);
3196 u8 i, j, find = 0;
3197 u16 logicHandle;
3198
3199 logicHandle = *((u16 *)pHciCmd->Data);
3200 /* find an matched logical link index and copy the data */
3201 for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) {
3202 for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) {
3203 if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle) {
3204 memcpy(&pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].Tx_Flow_Spec,
3205 &pHciCmd->Data[2], sizeof(struct hci_flow_spec));
3206 memcpy(&pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].Rx_Flow_Spec,
3207 &pHciCmd->Data[18], sizeof(struct hci_flow_spec));
3208
3209 bthci_CheckLogLinkBehavior(padapter, pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].Tx_Flow_Spec);
3210 find = 1;
3211 break;
3212 }
3213 }
3214 }
3215 RTPRINT(FIOCTL, IOCTL_BT_LOGO, ("FlowSpecModify, LLH = 0x%x, \n", logicHandle));
3216
3217 /* When we receive Flow Spec Modify command, we should send command status event first. */
3218 bthci_EventCommandStatus(padapter,
3219 LINK_CONTROL_COMMANDS,
3220 HCI_FLOW_SPEC_MODIFY,
3221 HCI_STATUS_SUCCESS);
3222
3223 if (!find)
3224 status = HCI_STATUS_UNKNOW_CONNECT_ID;
3225
3226 bthci_EventSendFlowSpecModifyComplete(padapter, status, logicHandle);
3227
3228 return status;
3229}
3230
3231static enum hci_status
3232bthci_CmdAcceptPhysicalLink(struct rtw_adapter *padapter,
3233 struct packet_irp_hcicmd_data *pHciCmd)
3234{
3235 enum hci_status status;
3236 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3237 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
3238
3239 pBtDbg->dbgHciInfo.hciCmdCntAcceptPhyLink++;
3240
3241 status = bthci_BuildPhysicalLink(padapter,
3242 pHciCmd, HCI_ACCEPT_PHYSICAL_LINK);
3243
3244 return status;
3245}
3246
3247static enum hci_status
3248bthci_CmdDisconnectPhysicalLink(struct rtw_adapter *padapter,
3249 struct packet_irp_hcicmd_data *pHciCmd)
3250{
3251 enum hci_status status = HCI_STATUS_SUCCESS;
3252 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3253 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
3254 u8 PLH, CurrentEntryNum, PhysLinkDisconnectReason;
3255
3256 pBtDbg->dbgHciInfo.hciCmdCntDisconnectPhyLink++;
3257
3258 PLH = *((u8 *)pHciCmd->Data);
3259 PhysLinkDisconnectReason = (*((u8 *)pHciCmd->Data+1));
3260 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_DISCONNECT_PHYSICAL_LINK PhyHandle = 0x%x, Reason = 0x%x\n",
3261 PLH, PhysLinkDisconnectReason));
3262
3263 CurrentEntryNum = bthci_GetCurrentEntryNum(padapter, PLH);
3264
3265 if (CurrentEntryNum == 0xff) {
3266 RTPRINT(FIOCTL, IOCTL_BT_HCICMD,
3267 ("DisconnectPhysicalLink, No such Handle in the Entry\n"));
3268 status = HCI_STATUS_UNKNOW_CONNECT_ID;
3269 } else {
3270 pBTInfo->BtAsocEntry[CurrentEntryNum].PhyLinkDisconnectReason =
3271 (enum hci_status)PhysLinkDisconnectReason;
3272 }
3273 /* Send HCI Command status event to AMP. */
3274 bthci_EventCommandStatus(padapter, LINK_CONTROL_COMMANDS,
3275 HCI_DISCONNECT_PHYSICAL_LINK, status);
3276
3277 if (status != HCI_STATUS_SUCCESS)
3278 return status;
3279
3280 /* The macros below require { and } in the if statement */
3281 if (pBTInfo->BtAsocEntry[CurrentEntryNum].BtCurrentState == HCI_STATE_DISCONNECTED) {
3282 BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_DISCONNECT_PHY_LINK, CurrentEntryNum);
3283 } else {
3284 BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTING, STATE_CMD_DISCONNECT_PHY_LINK, CurrentEntryNum);
3285 }
3286 return status;
3287}
3288
3289static enum hci_status
3290bthci_CmdSetACLLinkDataFlowMode(struct rtw_adapter *padapter,
3291 struct packet_irp_hcicmd_data *pHciCmd)
3292{
3293 enum hci_status status = HCI_STATUS_SUCCESS;
3294 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3295 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
3296 u8 localBuf[8] = "";
3297 u8 *pRetPar;
3298 u8 len = 0;
3299 struct packet_irp_hcievent_data *PPacketIrpEvent;
3300 u16 *pu2Temp;
3301
3302 pBtMgnt->ExtConfig.CurrentConnectHandle = *((u16 *)pHciCmd->Data);
3303 pBtMgnt->ExtConfig.CurrentIncomingTrafficMode = *((u8 *)pHciCmd->Data)+2;
3304 pBtMgnt->ExtConfig.CurrentOutgoingTrafficMode = *((u8 *)pHciCmd->Data)+3;
3305 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("Connection Handle = 0x%x, Incoming Traffic mode = 0x%x, Outgoing Traffic mode = 0x%x",
3306 pBtMgnt->ExtConfig.CurrentConnectHandle,
3307 pBtMgnt->ExtConfig.CurrentIncomingTrafficMode,
3308 pBtMgnt->ExtConfig.CurrentOutgoingTrafficMode));
3309
3310
3311 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3312
3313 len += bthci_CommandCompleteHeader(&localBuf[0],
3314 OGF_EXTENSION,
3315 HCI_SET_ACL_LINK_DATA_FLOW_MODE,
3316 status);
3317
3318 /* Return parameters starts from here */
3319 pRetPar = &PPacketIrpEvent->Data[len];
3320 pRetPar[0] = status; /* status */
3321
3322 pu2Temp = (u16 *)&pRetPar[1];
3323 *pu2Temp = pBtMgnt->ExtConfig.CurrentConnectHandle;
3324 len += 3;
3325 PPacketIrpEvent->Length = len;
3326
3327 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3328 return status;
3329}
3330
3331static enum hci_status
3332bthci_CmdSetACLLinkStatus(struct rtw_adapter *padapter,
3333 struct packet_irp_hcicmd_data *pHciCmd)
3334{
3335 enum hci_status status = HCI_STATUS_SUCCESS;
3336 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3337 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
3338 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
3339 u8 i;
3340 u8 *pTriple;
3341
3342 pBtDbg->dbgHciInfo.hciCmdCntSetAclLinkStatus++;
3343 RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "SetACLLinkStatus, Hex Data :\n",
3344 &pHciCmd->Data[0], pHciCmd->Length);
3345
3346 /* Only Core Stack v251 and later version support this command. */
3347 pBtMgnt->bSupportProfile = true;
3348
3349 pBtMgnt->ExtConfig.NumberOfHandle = *((u8 *)pHciCmd->Data);
3350 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("NumberOfHandle = 0x%x\n", pBtMgnt->ExtConfig.NumberOfHandle));
3351
3352 pTriple = &pHciCmd->Data[1];
3353 for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) {
3354 pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = *((u16 *)&pTriple[0]);
3355 pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = pTriple[2];
3356 pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = pTriple[3];
3357 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT,
3358 ("Connection_Handle = 0x%x, Incoming Traffic mode = 0x%x, Outgoing Traffic Mode = 0x%x\n",
3359 pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle,
3360 pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode,
3361 pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode));
3362 pTriple += 4;
3363 }
3364
3365 {
3366 u8 localBuf[6] = "";
3367 u8 *pRetPar;
3368 u8 len = 0;
3369 struct packet_irp_hcievent_data *PPacketIrpEvent;
3370
3371 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3372
3373 len += bthci_CommandCompleteHeader(&localBuf[0],
3374 OGF_EXTENSION,
3375 HCI_SET_ACL_LINK_STATUS,
3376 status);
3377
3378 /* Return parameters starts from here */
3379 pRetPar = &PPacketIrpEvent->Data[len];
3380 pRetPar[0] = status; /* status */
3381
3382 len += 1;
3383 PPacketIrpEvent->Length = len;
3384
3385 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3386 }
3387
3388 return status;
3389}
3390
3391static enum hci_status
3392bthci_CmdSetSCOLinkStatus(
3393 struct rtw_adapter *padapter,
3394 struct packet_irp_hcicmd_data *pHciCmd
3395 )
3396{
3397 enum hci_status status = HCI_STATUS_SUCCESS;
3398 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3399 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
3400 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
3401
3402 pBtDbg->dbgHciInfo.hciCmdCntSetScoLinkStatus++;
3403 pBtMgnt->ExtConfig.NumberOfSCO = *((u8 *)pHciCmd->Data);
3404 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("NumberOfSCO = 0x%x\n",
3405 pBtMgnt->ExtConfig.NumberOfSCO));
3406
3407 {
3408 u8 localBuf[6] = "";
3409 u8 *pRetPar;
3410 u8 len = 0;
3411 struct packet_irp_hcievent_data *PPacketIrpEvent;
3412
3413 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3414
3415 len += bthci_CommandCompleteHeader(&localBuf[0],
3416 OGF_EXTENSION,
3417 HCI_SET_SCO_LINK_STATUS,
3418 status);
3419
3420 /* Return parameters starts from here */
3421 pRetPar = &PPacketIrpEvent->Data[len];
3422 pRetPar[0] = status; /* status */
3423
3424 len += 1;
3425 PPacketIrpEvent->Length = len;
3426
3427 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3428 }
3429
3430 return status;
3431}
3432
3433static enum hci_status
3434bthci_CmdSetRSSIValue(
3435 struct rtw_adapter *padapter,
3436 struct packet_irp_hcicmd_data *pHciCmd
3437 )
3438{
3439 enum hci_status status = HCI_STATUS_SUCCESS;
3440 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3441 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
3442 s8 min_bt_rssi = 0;
3443 u8 i;
3444 for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) {
3445 if (pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle == *((u16 *)&pHciCmd->Data[0])) {
3446 pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI = (s8)(pHciCmd->Data[2]);
3447 RTPRINT(FIOCTL, IOCTL_BT_EVENT_PERIODICAL,
3448 ("Connection_Handle = 0x%x, RSSI = %d \n",
3449 pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle,
3450 pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI));
3451 }
3452 /* get the minimum bt rssi value */
3453 if (pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI <= min_bt_rssi)
3454 min_bt_rssi = pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI;
3455 }
3456
3457 pBtMgnt->ExtConfig.MIN_BT_RSSI = min_bt_rssi;
3458 RTPRINT(FBT, BT_TRACE, ("[bt rssi], the min rssi is %d\n", min_bt_rssi));
3459
3460 {
3461 u8 localBuf[6] = "";
3462 u8 *pRetPar;
3463 u8 len = 0;
3464 struct packet_irp_hcievent_data *PPacketIrpEvent;
3465
3466 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3467
3468 len += bthci_CommandCompleteHeader(&localBuf[0],
3469 OGF_EXTENSION,
3470 HCI_SET_RSSI_VALUE,
3471 status);
3472
3473 /* Return parameters starts from here */
3474 pRetPar = &PPacketIrpEvent->Data[len];
3475 pRetPar[0] = status; /* status */
3476
3477 len += 1;
3478 PPacketIrpEvent->Length = len;
3479
3480 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3481 }
3482
3483 return status;
3484}
3485
3486static enum hci_status
3487bthci_CmdSetCurrentBluetoothStatus(
3488 struct rtw_adapter *padapter,
3489 struct packet_irp_hcicmd_data *pHciCmd
3490 )
3491{
3492 enum hci_status status = HCI_STATUS_SUCCESS;
3493/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
3494 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3495 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
3496
3497 pBtMgnt->ExtConfig.CurrentBTStatus = *((u8 *)&pHciCmd->Data[0]);
3498 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("SetCurrentBluetoothStatus, CurrentBTStatus = 0x%x\n",
3499 pBtMgnt->ExtConfig.CurrentBTStatus));
3500
3501 {
3502 u8 localBuf[6] = "";
3503 u8 *pRetPar;
3504 u8 len = 0;
3505 struct packet_irp_hcievent_data *PPacketIrpEvent;
3506
3507 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3508
3509 len += bthci_CommandCompleteHeader(&localBuf[0],
3510 OGF_EXTENSION,
3511 HCI_SET_CURRENT_BLUETOOTH_STATUS,
3512 status);
3513
3514 /* Return parameters starts from here */
3515 pRetPar = &PPacketIrpEvent->Data[len];
3516 pRetPar[0] = status; /* status */
3517 len += 1;
3518
3519 PPacketIrpEvent->Length = len;
3520
3521 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3522 }
3523
3524 return status;
3525}
3526
3527static enum hci_status
3528bthci_CmdExtensionVersionNotify(
3529 struct rtw_adapter *padapter,
3530 struct packet_irp_hcicmd_data *pHciCmd
3531 )
3532{
3533 enum hci_status status = HCI_STATUS_SUCCESS;
3534 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3535 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
3536 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
3537
3538 pBtDbg->dbgHciInfo.hciCmdCntExtensionVersionNotify++;
3539 RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "ExtensionVersionNotify, Hex Data :\n",
3540 &pHciCmd->Data[0], pHciCmd->Length);
3541
3542 pBtMgnt->ExtConfig.HCIExtensionVer = *((u16 *)&pHciCmd->Data[0]);
3543 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCIExtensionVer = 0x%x\n", pBtMgnt->ExtConfig.HCIExtensionVer));
3544
3545 {
3546 u8 localBuf[6] = "";
3547 u8 *pRetPar;
3548 u8 len = 0;
3549 struct packet_irp_hcievent_data *PPacketIrpEvent;
3550
3551 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3552
3553 len += bthci_CommandCompleteHeader(&localBuf[0],
3554 OGF_EXTENSION,
3555 HCI_EXTENSION_VERSION_NOTIFY,
3556 status);
3557
3558 /* Return parameters starts from here */
3559 pRetPar = &PPacketIrpEvent->Data[len];
3560 pRetPar[0] = status; /* status */
3561
3562 len += 1;
3563 PPacketIrpEvent->Length = len;
3564
3565 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3566 }
3567
3568 return status;
3569}
3570
3571static enum hci_status
3572bthci_CmdLinkStatusNotify(
3573 struct rtw_adapter *padapter,
3574 struct packet_irp_hcicmd_data *pHciCmd
3575 )
3576{
3577 enum hci_status status = HCI_STATUS_SUCCESS;
3578 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3579 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
3580 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
3581 u8 i;
3582 u8 *pTriple;
3583
3584 pBtDbg->dbgHciInfo.hciCmdCntLinkStatusNotify++;
3585 RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "LinkStatusNotify, Hex Data :\n",
3586 &pHciCmd->Data[0], pHciCmd->Length);
3587
3588 /* Current only RTL8723 support this command. */
3589 pBtMgnt->bSupportProfile = true;
3590
3591 pBtMgnt->ExtConfig.NumberOfHandle = *((u8 *)pHciCmd->Data);
3592 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("NumberOfHandle = 0x%x\n", pBtMgnt->ExtConfig.NumberOfHandle));
3593 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCIExtensionVer = %d\n", pBtMgnt->ExtConfig.HCIExtensionVer));
3594
3595 pTriple = &pHciCmd->Data[1];
3596 for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) {
3597 if (pBtMgnt->ExtConfig.HCIExtensionVer < 1) {
3598 pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = *((u16 *)&pTriple[0]);
3599 pBtMgnt->ExtConfig.linkInfo[i].BTProfile = pTriple[2];
3600 pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec = pTriple[3];
3601 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT,
3602 ("Connection_Handle = 0x%x, BTProfile =%d, BTSpec =%d\n",
3603 pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle,
3604 pBtMgnt->ExtConfig.linkInfo[i].BTProfile,
3605 pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec));
3606 pTriple += 4;
3607 } else if (pBtMgnt->ExtConfig.HCIExtensionVer >= 1) {
3608 pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = *((u16 *)&pTriple[0]);
3609 pBtMgnt->ExtConfig.linkInfo[i].BTProfile = pTriple[2];
3610 pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec = pTriple[3];
3611 pBtMgnt->ExtConfig.linkInfo[i].linkRole = pTriple[4];
3612 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT,
3613 ("Connection_Handle = 0x%x, BTProfile =%d, BTSpec =%d, LinkRole =%d\n",
3614 pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle,
3615 pBtMgnt->ExtConfig.linkInfo[i].BTProfile,
3616 pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec,
3617 pBtMgnt->ExtConfig.linkInfo[i].linkRole));
3618 pTriple += 5;
3619 }
3620
3621 }
3622 BTHCI_UpdateBTProfileRTKToMoto(padapter);
3623 {
3624 u8 localBuf[6] = "";
3625 u8 *pRetPar;
3626 u8 len = 0;
3627 struct packet_irp_hcievent_data *PPacketIrpEvent;
3628
3629 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3630
3631 len += bthci_CommandCompleteHeader(&localBuf[0],
3632 OGF_EXTENSION,
3633 HCI_LINK_STATUS_NOTIFY,
3634 status);
3635
3636 /* Return parameters starts from here */
3637 pRetPar = &PPacketIrpEvent->Data[len];
3638 pRetPar[0] = status; /* status */
3639
3640 len += 1;
3641 PPacketIrpEvent->Length = len;
3642
3643 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3644 }
3645
3646 return status;
3647}
3648
3649static enum hci_status
3650bthci_CmdBtOperationNotify(
3651 struct rtw_adapter *padapter,
3652 struct packet_irp_hcicmd_data *pHciCmd
3653 )
3654{
3655 enum hci_status status = HCI_STATUS_SUCCESS;
3656 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3657 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
3658
3659 RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "Bt Operation notify, Hex Data :\n",
3660 &pHciCmd->Data[0], pHciCmd->Length);
3661
3662 pBtMgnt->ExtConfig.btOperationCode = *((u8 *)pHciCmd->Data);
3663 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("btOperationCode = 0x%x\n", pBtMgnt->ExtConfig.btOperationCode));
3664 switch (pBtMgnt->ExtConfig.btOperationCode) {
3665 case HCI_BT_OP_NONE:
3666 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Operation None!!\n"));
3667 break;
3668 case HCI_BT_OP_INQUIRY_START:
3669 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Inquire start!!\n"));
3670 break;
3671 case HCI_BT_OP_INQUIRY_FINISH:
3672 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Inquire finished!!\n"));
3673 break;
3674 case HCI_BT_OP_PAGING_START:
3675 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Paging is started!!\n"));
3676 break;
3677 case HCI_BT_OP_PAGING_SUCCESS:
3678 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Paging complete successfully!!\n"));
3679 break;
3680 case HCI_BT_OP_PAGING_UNSUCCESS:
3681 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Paging complete unsuccessfully!!\n"));
3682 break;
3683 case HCI_BT_OP_PAIRING_START:
3684 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Pairing start!!\n"));
3685 break;
3686 case HCI_BT_OP_PAIRING_FINISH:
3687 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Pairing finished!!\n"));
3688 break;
3689 case HCI_BT_OP_BT_DEV_ENABLE:
3690 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : BT Device is enabled!!\n"));
3691 break;
3692 case HCI_BT_OP_BT_DEV_DISABLE:
3693 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : BT Device is disabled!!\n"));
3694 break;
3695 default:
3696 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Unknown, error!!\n"));
3697 break;
3698 }
3699 BTDM_AdjustForBtOperation(padapter);
3700 {
3701 u8 localBuf[6] = "";
3702 u8 *pRetPar;
3703 u8 len = 0;
3704 struct packet_irp_hcievent_data *PPacketIrpEvent;
3705
3706 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3707
3708 len += bthci_CommandCompleteHeader(&localBuf[0],
3709 OGF_EXTENSION,
3710 HCI_BT_OPERATION_NOTIFY,
3711 status);
3712
3713 /* Return parameters starts from here */
3714 pRetPar = &PPacketIrpEvent->Data[len];
3715 pRetPar[0] = status; /* status */
3716
3717 len += 1;
3718 PPacketIrpEvent->Length = len;
3719
3720 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3721 }
3722
3723 return status;
3724}
3725
3726static enum hci_status
3727bthci_CmdEnableWifiScanNotify(struct rtw_adapter *padapter,
3728 struct packet_irp_hcicmd_data *pHciCmd)
3729{
3730 enum hci_status status = HCI_STATUS_SUCCESS;
3731 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3732 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
3733
3734 RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "Enable Wifi scan notify, Hex Data :\n",
3735 &pHciCmd->Data[0], pHciCmd->Length);
3736
3737 pBtMgnt->ExtConfig.bEnableWifiScanNotify = *((u8 *)pHciCmd->Data);
3738 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("bEnableWifiScanNotify = %d\n", pBtMgnt->ExtConfig.bEnableWifiScanNotify));
3739
3740 {
3741 u8 localBuf[6] = "";
3742 u8 *pRetPar;
3743 u8 len = 0;
3744 struct packet_irp_hcievent_data *PPacketIrpEvent;
3745
3746 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3747
3748 len += bthci_CommandCompleteHeader(&localBuf[0],
3749 OGF_EXTENSION,
3750 HCI_ENABLE_WIFI_SCAN_NOTIFY,
3751 status);
3752
3753 /* Return parameters starts from here */
3754 pRetPar = &PPacketIrpEvent->Data[len];
3755 pRetPar[0] = status; /* status */
3756
3757 len += 1;
3758 PPacketIrpEvent->Length = len;
3759
3760 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3761 }
3762
3763 return status;
3764}
3765
3766static enum hci_status
3767bthci_CmdWIFICurrentChannel(struct rtw_adapter *padapter,
3768 struct packet_irp_hcicmd_data *pHciCmd)
3769{
3770 enum hci_status status = HCI_STATUS_SUCCESS;
3771 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3772 u8 chnl = pmlmeext->cur_channel;
3773
3774 if (pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) {
3775 if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
3776 chnl += 2;
3777 else if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
3778 chnl -= 2;
3779 }
3780
3781 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("Current Channel = 0x%x\n", chnl));
3782
3783 {
3784 u8 localBuf[8] = "";
3785 u8 *pRetPar;
3786 u8 len = 0;
3787 struct packet_irp_hcievent_data *PPacketIrpEvent;
3788
3789 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3790
3791 len += bthci_CommandCompleteHeader(&localBuf[0],
3792 OGF_EXTENSION,
3793 HCI_WIFI_CURRENT_CHANNEL,
3794 status);
3795
3796 /* Return parameters starts from here */
3797 pRetPar = &PPacketIrpEvent->Data[len];
3798 pRetPar[0] = status; /* status */
3799 pRetPar[1] = chnl; /* current channel */
3800 len += 2;
3801 PPacketIrpEvent->Length = len;
3802
3803 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3804 }
3805
3806 return status;
3807}
3808
3809static enum hci_status
3810bthci_CmdWIFICurrentBandwidth(struct rtw_adapter *padapter,
3811 struct packet_irp_hcicmd_data *pHciCmd)
3812{
3813 enum hci_status status = HCI_STATUS_SUCCESS;
3814 enum ht_channel_width bw;
3815 u8 CurrentBW = 0;
3816
3817 bw = padapter->mlmeextpriv.cur_bwmode;
3818
3819 if (bw == HT_CHANNEL_WIDTH_20)
3820 CurrentBW = 0;
3821 else if (bw == HT_CHANNEL_WIDTH_40)
3822 CurrentBW = 1;
3823
3824 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("Current BW = 0x%x\n",
3825 CurrentBW));
3826
3827 {
3828 u8 localBuf[8] = "";
3829 u8 *pRetPar;
3830 u8 len = 0;
3831 struct packet_irp_hcievent_data *PPacketIrpEvent;
3832
3833 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3834
3835 len += bthci_CommandCompleteHeader(&localBuf[0],
3836 OGF_EXTENSION,
3837 HCI_WIFI_CURRENT_BANDWIDTH,
3838 status);
3839
3840 /* Return parameters starts from here */
3841 pRetPar = &PPacketIrpEvent->Data[len];
3842 pRetPar[0] = status; /* status */
3843 pRetPar[1] = CurrentBW; /* current BW */
3844 len += 2;
3845 PPacketIrpEvent->Length = len;
3846
3847 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3848 }
3849
3850 return status;
3851}
3852
3853static enum hci_status
3854bthci_CmdWIFIConnectionStatus(
3855 struct rtw_adapter *padapter,
3856 struct packet_irp_hcicmd_data *pHciCmd
3857 )
3858{
3859 enum hci_status status = HCI_STATUS_SUCCESS;
3860 u8 connectStatus = HCI_WIFI_NOT_CONNECTED;
3861
3862 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE)) {
3863 if (padapter->stapriv.asoc_sta_count >= 3)
3864 connectStatus = HCI_WIFI_CONNECTED;
3865 else
3866 connectStatus = HCI_WIFI_NOT_CONNECTED;
3867 } else if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_ASOC_STATE)) {
3868 connectStatus = HCI_WIFI_CONNECTED;
3869 } else if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING)) {
3870 connectStatus = HCI_WIFI_CONNECT_IN_PROGRESS;
3871 } else {
3872 connectStatus = HCI_WIFI_NOT_CONNECTED;
3873 }
3874
3875 {
3876 u8 localBuf[8] = "";
3877 u8 *pRetPar;
3878 u8 len = 0;
3879 struct packet_irp_hcievent_data *PPacketIrpEvent;
3880
3881 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3882
3883 len += bthci_CommandCompleteHeader(&localBuf[0],
3884 OGF_EXTENSION,
3885 HCI_WIFI_CONNECTION_STATUS,
3886 status);
3887
3888 /* Return parameters starts from here */
3889 pRetPar = &PPacketIrpEvent->Data[len];
3890 pRetPar[0] = status; /* status */
3891 pRetPar[1] = connectStatus; /* connect status */
3892 len += 2;
3893 PPacketIrpEvent->Length = len;
3894
3895 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3896 }
3897
3898 return status;
3899}
3900
3901static enum hci_status
3902bthci_CmdEnableDeviceUnderTestMode(
3903 struct rtw_adapter *padapter,
3904 struct packet_irp_hcicmd_data *pHciCmd
3905 )
3906{
3907 enum hci_status status = HCI_STATUS_SUCCESS;
3908 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3909 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
3910
3911 pBtHciInfo->bInTestMode = true;
3912 pBtHciInfo->bTestIsEnd = false;
3913
3914 /* send command complete event here when all data are received. */
3915 {
3916 u8 localBuf[6] = "";
3917 u8 *pRetPar;
3918 u8 len = 0;
3919 struct packet_irp_hcievent_data *PPacketIrpEvent;
3920
3921 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3922
3923 len += bthci_CommandCompleteHeader(&localBuf[0],
3924 OGF_TESTING_COMMANDS,
3925 HCI_ENABLE_DEVICE_UNDER_TEST_MODE,
3926 status);
3927
3928 /* Return parameters starts from here */
3929 pRetPar = &PPacketIrpEvent->Data[len];
3930 pRetPar[0] = status; /* status */
3931 len += 1;
3932 PPacketIrpEvent->Length = len;
3933
3934 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
3935 }
3936
3937 return status;
3938}
3939
3940static enum hci_status
3941bthci_CmdAMPTestEnd(struct rtw_adapter *padapter,
3942 struct packet_irp_hcicmd_data *pHciCmd)
3943{
3944 enum hci_status status = HCI_STATUS_SUCCESS;
3945 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3946 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
3947 u8 bFilterOutNonAssociatedBSSID = true;
3948
3949 if (!pBtHciInfo->bInTestMode) {
3950 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Not in Test mode, return status = HCI_STATUS_CMD_DISALLOW\n"));
3951 status = HCI_STATUS_CMD_DISALLOW;
3952 return status;
3953 }
3954
3955 pBtHciInfo->bTestIsEnd = true;
3956
3957 del_timer_sync(&pBTInfo->BTTestSendPacketTimer);
3958
3959 rtw_hal_set_hwreg23a(padapter, HW_VAR_CHECK_BSSID, (u8 *)(&bFilterOutNonAssociatedBSSID));
3960
3961 /* send command complete event here when all data are received. */
3962 {
3963 u8 localBuf[4] = "";
3964 struct packet_irp_hcievent_data *PPacketIrpEvent;
3965
3966 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("AMP Test End Event \n"));
3967 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
3968 PPacketIrpEvent->EventCode = HCI_EVENT_AMP_TEST_END;
3969 PPacketIrpEvent->Length = 2;
3970
3971 PPacketIrpEvent->Data[0] = status;
3972 PPacketIrpEvent->Data[1] = pBtHciInfo->TestScenario;
3973
3974 bthci_IndicateEvent(padapter, PPacketIrpEvent, 4);
3975 }
3976
3977 bthci_EventAMPReceiverReport(padapter, 0x01);
3978
3979 return status;
3980}
3981
3982static enum hci_status
3983bthci_CmdAMPTestCommand(struct rtw_adapter *padapter,
3984 struct packet_irp_hcicmd_data *pHciCmd)
3985{
3986 enum hci_status status = HCI_STATUS_SUCCESS;
3987 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
3988 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
3989
3990 if (!pBtHciInfo->bInTestMode) {
3991 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Not in Test mode, return status = HCI_STATUS_CMD_DISALLOW\n"));
3992 status = HCI_STATUS_CMD_DISALLOW;
3993 return status;
3994 }
3995
3996 pBtHciInfo->TestScenario = *((u8 *)pHciCmd->Data);
3997
3998 if (pBtHciInfo->TestScenario == 0x01)
3999 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("TX Single Test \n"));
4000 else if (pBtHciInfo->TestScenario == 0x02)
4001 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Receive Frame Test \n"));
4002 else
4003 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("No Such Test !!!!!!!!!!!!!!!!!! \n"));
4004
4005 if (pBtHciInfo->bTestIsEnd) {
4006 u8 localBuf[5] = "";
4007 struct packet_irp_hcievent_data *PPacketIrpEvent;
4008
4009 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("AMP Test End Event \n"));
4010 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
4011 PPacketIrpEvent->EventCode = HCI_EVENT_AMP_TEST_END;
4012 PPacketIrpEvent->Length = 2;
4013
4014 PPacketIrpEvent->Data[0] = status;
4015 PPacketIrpEvent->Data[1] = pBtHciInfo->TestScenario ;
4016
4017 bthci_IndicateEvent(padapter, PPacketIrpEvent, 4);
4018
4019 /* Return to Idel state with RX and TX off. */
4020
4021 return status;
4022 }
4023
4024 /* should send command status event */
4025 bthci_EventCommandStatus(padapter,
4026 OGF_TESTING_COMMANDS,
4027 HCI_AMP_TEST_COMMAND,
4028 status);
4029
4030 /* The HCI_AMP_Start Test Event shall be generated when the */
4031 /* HCI_AMP_Test_Command has completed and the first data is ready to be sent */
4032 /* or received. */
4033
4034 {
4035 u8 localBuf[5] = "";
4036 struct packet_irp_hcievent_data *PPacketIrpEvent;
4037
4038 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), (" HCI_AMP_Start Test Event \n"));
4039 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
4040 PPacketIrpEvent->EventCode = HCI_EVENT_AMP_START_TEST;
4041 PPacketIrpEvent->Length = 2;
4042
4043 PPacketIrpEvent->Data[0] = status;
4044 PPacketIrpEvent->Data[1] = pBtHciInfo->TestScenario ;
4045
4046 bthci_IndicateEvent(padapter, PPacketIrpEvent, 4);
4047
4048 /* Return to Idel state with RX and TX off. */
4049 }
4050
4051 if (pBtHciInfo->TestScenario == 0x01) {
4052 /*
4053 When in a transmitter test scenario and the frames/bursts count have been
4054 transmitted the HCI_AMP_Test_End event shall be sent.
4055 */
4056 mod_timer(&pBTInfo->BTTestSendPacketTimer,
4057 jiffies + msecs_to_jiffies(50));
4058 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("TX Single Test \n"));
4059 } else if (pBtHciInfo->TestScenario == 0x02) {
4060 u8 bFilterOutNonAssociatedBSSID = false;
4061 rtw_hal_set_hwreg23a(padapter, HW_VAR_CHECK_BSSID, (u8 *)(&bFilterOutNonAssociatedBSSID));
4062 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Receive Frame Test \n"));
4063 }
4064
4065 return status;
4066}
4067
4068static enum hci_status
4069bthci_CmdEnableAMPReceiverReports(struct rtw_adapter *padapter,
4070 struct packet_irp_hcicmd_data *pHciCmd)
4071{
4072 enum hci_status status = HCI_STATUS_SUCCESS;
4073 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
4074 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
4075
4076 if (!pBtHciInfo->bInTestMode) {
4077 status = HCI_STATUS_CMD_DISALLOW;
4078 /* send command complete event here when all data are received. */
4079 {
4080 u8 localBuf[6] = "";
4081 u8 *pRetPar;
4082 u8 len = 0;
4083 struct packet_irp_hcievent_data *PPacketIrpEvent;
4084
4085 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
4086
4087 len += bthci_CommandCompleteHeader(&localBuf[0],
4088 OGF_TESTING_COMMANDS,
4089 HCI_ENABLE_AMP_RECEIVER_REPORTS,
4090 status);
4091
4092 /* Return parameters starts from here */
4093 pRetPar = &PPacketIrpEvent->Data[len];
4094 pRetPar[0] = status; /* status */
4095 len += 1;
4096 PPacketIrpEvent->Length = len;
4097
4098 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
4099 }
4100 return status;
4101 }
4102
4103 pBtHciInfo->bTestNeedReport = *((u8 *)pHciCmd->Data);
4104 pBtHciInfo->TestReportInterval = (*((u8 *)pHciCmd->Data+2));
4105
4106 bthci_EventAMPReceiverReport(padapter, 0x00);
4107
4108 /* send command complete event here when all data are received. */
4109 {
4110 u8 localBuf[6] = "";
4111 u8 *pRetPar;
4112 u8 len = 0;
4113 struct packet_irp_hcievent_data *PPacketIrpEvent;
4114
4115 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
4116
4117 len += bthci_CommandCompleteHeader(&localBuf[0],
4118 OGF_TESTING_COMMANDS,
4119 HCI_ENABLE_AMP_RECEIVER_REPORTS,
4120 status);
4121
4122 /* Return parameters starts from here */
4123 pRetPar = &PPacketIrpEvent->Data[len];
4124 pRetPar[0] = status; /* status */
4125 len += 1;
4126 PPacketIrpEvent->Length = len;
4127
4128 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
4129 }
4130
4131 return status;
4132}
4133
4134static enum hci_status
4135bthci_CmdHostBufferSize(struct rtw_adapter *padapter,
4136 struct packet_irp_hcicmd_data *pHciCmd)
4137{
4138 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
4139 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
4140 struct packet_irp_hcievent_data *PPacketIrpEvent;
4141 enum hci_status status = HCI_STATUS_SUCCESS;
4142 u8 localBuf[6] = "";
4143 u8 *pRetPar;
4144 u8 len = 0;
4145
4146 pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].ACLPacketsData.ACLDataPacketLen = *((u16 *)pHciCmd->Data);
4147 pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].SyncDataPacketLen = *((u8 *)(pHciCmd->Data+2));
4148 pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].TotalNumACLDataPackets = *((u16 *)(pHciCmd->Data+3));
4149 pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].TotalSyncNumDataPackets = *((u16 *)(pHciCmd->Data+5));
4150
4151 /* send command complete event here when all data are received. */
4152 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
4153
4154 len += bthci_CommandCompleteHeader(&localBuf[0],
4155 OGF_SET_EVENT_MASK_COMMAND,
4156 HCI_HOST_BUFFER_SIZE,
4157 status);
4158
4159 /* Return parameters starts from here */
4160 pRetPar = &PPacketIrpEvent->Data[len];
4161 pRetPar[0] = status; /* status */
4162 len += 1;
4163 PPacketIrpEvent->Length = len;
4164
4165 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
4166
4167 return status;
4168}
4169
4170static enum hci_status
4171bthci_CmdHostNumberOfCompletedPackets(struct rtw_adapter *padapter,
4172 struct packet_irp_hcicmd_data *pHciCmd)
4173{
4174 enum hci_status status = HCI_STATUS_SUCCESS;
4175
4176 return status;
4177}
4178
4179static enum hci_status
4180bthci_UnknownCMD(struct rtw_adapter *padapter, struct packet_irp_hcicmd_data *pHciCmd)
4181{
4182 enum hci_status status = HCI_STATUS_UNKNOW_HCI_CMD;
4183 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
4184 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
4185
4186 pBtDbg->dbgHciInfo.hciCmdCntUnknown++;
4187 bthci_EventCommandStatus(padapter,
4188 (u8)pHciCmd->OGF,
4189 pHciCmd->OCF,
4190 status);
4191
4192 return status;
4193}
4194
4195static enum hci_status
4196bthci_HandleOGFInformationalParameters(struct rtw_adapter *padapter,
4197 struct packet_irp_hcicmd_data *pHciCmd)
4198{
4199 enum hci_status status = HCI_STATUS_SUCCESS;
4200
4201 switch (pHciCmd->OCF) {
4202 case HCI_READ_LOCAL_VERSION_INFORMATION:
4203 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_VERSION_INFORMATION\n"));
4204 status = bthci_CmdReadLocalVersionInformation(padapter);
4205 break;
4206 case HCI_READ_LOCAL_SUPPORTED_COMMANDS:
4207 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_SUPPORTED_COMMANDS\n"));
4208 status = bthci_CmdReadLocalSupportedCommands(padapter);
4209 break;
4210 case HCI_READ_LOCAL_SUPPORTED_FEATURES:
4211 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_SUPPORTED_FEATURES\n"));
4212 status = bthci_CmdReadLocalSupportedFeatures(padapter);
4213 break;
4214 case HCI_READ_BUFFER_SIZE:
4215 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_BUFFER_SIZE\n"));
4216 status = bthci_CmdReadBufferSize(padapter);
4217 break;
4218 case HCI_READ_DATA_BLOCK_SIZE:
4219 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_DATA_BLOCK_SIZE\n"));
4220 status = bthci_CmdReadDataBlockSize(padapter);
4221 break;
4222 default:
4223 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFInformationalParameters(), Unknown case = 0x%x\n", pHciCmd->OCF));
4224 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n"));
4225 status = bthci_UnknownCMD(padapter, pHciCmd);
4226 break;
4227 }
4228 return status;
4229}
4230
4231static enum hci_status
4232bthci_HandleOGFSetEventMaskCMD(struct rtw_adapter *padapter,
4233 struct packet_irp_hcicmd_data *pHciCmd)
4234{
4235 enum hci_status status = HCI_STATUS_SUCCESS;
4236
4237 switch (pHciCmd->OCF) {
4238 case HCI_SET_EVENT_MASK:
4239 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SET_EVENT_MASK\n"));
4240 status = bthci_CmdSetEventMask(padapter, pHciCmd);
4241 break;
4242 case HCI_RESET:
4243 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_RESET\n"));
4244 status = bthci_CmdReset(padapter, true);
4245 break;
4246 case HCI_READ_CONNECTION_ACCEPT_TIMEOUT:
4247 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_CONNECTION_ACCEPT_TIMEOUT\n"));
4248 status = bthci_CmdReadConnectionAcceptTimeout(padapter);
4249 break;
4250 case HCI_SET_EVENT_FILTER:
4251 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SET_EVENT_FILTER\n"));
4252 status = bthci_CmdSetEventFilter(padapter, pHciCmd);
4253 break;
4254 case HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT:
4255 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT\n"));
4256 status = bthci_CmdWriteConnectionAcceptTimeout(padapter, pHciCmd);
4257 break;
4258 case HCI_READ_PAGE_TIMEOUT:
4259 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_PAGE_TIMEOUT\n"));
4260 status = bthci_CmdReadPageTimeout(padapter, pHciCmd);
4261 break;
4262 case HCI_WRITE_PAGE_TIMEOUT:
4263 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_PAGE_TIMEOUT\n"));
4264 status = bthci_CmdWritePageTimeout(padapter, pHciCmd);
4265 break;
4266 case HCI_HOST_NUMBER_OF_COMPLETED_PACKETS:
4267 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_HOST_NUMBER_OF_COMPLETED_PACKETS\n"));
4268 status = bthci_CmdHostNumberOfCompletedPackets(padapter, pHciCmd);
4269 break;
4270 case HCI_READ_LINK_SUPERVISION_TIMEOUT:
4271 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LINK_SUPERVISION_TIMEOUT\n"));
4272 status = bthci_CmdReadLinkSupervisionTimeout(padapter, pHciCmd);
4273 break;
4274 case HCI_WRITE_LINK_SUPERVISION_TIMEOUT:
4275 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_LINK_SUPERVISION_TIMEOUT\n"));
4276 status = bthci_CmdWriteLinkSupervisionTimeout(padapter, pHciCmd);
4277 break;
4278 case HCI_ENHANCED_FLUSH:
4279 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ENHANCED_FLUSH\n"));
4280 status = bthci_CmdEnhancedFlush(padapter, pHciCmd);
4281 break;
4282 case HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT:
4283 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT\n"));
4284 status = bthci_CmdReadLogicalLinkAcceptTimeout(padapter, pHciCmd);
4285 break;
4286 case HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT:
4287 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT\n"));
4288 status = bthci_CmdWriteLogicalLinkAcceptTimeout(padapter, pHciCmd);
4289 break;
4290 case HCI_SET_EVENT_MASK_PAGE_2:
4291 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SET_EVENT_MASK_PAGE_2\n"));
4292 status = bthci_CmdSetEventMaskPage2(padapter, pHciCmd);
4293 break;
4294 case HCI_READ_LOCATION_DATA:
4295 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCATION_DATA\n"));
4296 status = bthci_CmdReadLocationData(padapter, pHciCmd);
4297 break;
4298 case HCI_WRITE_LOCATION_DATA:
4299 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_LOCATION_DATA\n"));
4300 status = bthci_CmdWriteLocationData(padapter, pHciCmd);
4301 break;
4302 case HCI_READ_FLOW_CONTROL_MODE:
4303 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_FLOW_CONTROL_MODE\n"));
4304 status = bthci_CmdReadFlowControlMode(padapter, pHciCmd);
4305 break;
4306 case HCI_WRITE_FLOW_CONTROL_MODE:
4307 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_FLOW_CONTROL_MODE\n"));
4308 status = bthci_CmdWriteFlowControlMode(padapter, pHciCmd);
4309 break;
4310 case HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT:
4311 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT\n"));
4312 status = bthci_CmdReadBestEffortFlushTimeout(padapter, pHciCmd);
4313 break;
4314 case HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT:
4315 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT\n"));
4316 status = bthci_CmdWriteBestEffortFlushTimeout(padapter, pHciCmd);
4317 break;
4318 case HCI_SHORT_RANGE_MODE:
4319 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SHORT_RANGE_MODE\n"));
4320 status = bthci_CmdShortRangeMode(padapter, pHciCmd);
4321 break;
4322 case HCI_HOST_BUFFER_SIZE:
4323 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_HOST_BUFFER_SIZE\n"));
4324 status = bthci_CmdHostBufferSize(padapter, pHciCmd);
4325 break;
4326 default:
4327 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFSetEventMaskCMD(), Unknown case = 0x%x\n", pHciCmd->OCF));
4328 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n"));
4329 status = bthci_UnknownCMD(padapter, pHciCmd);
4330 break;
4331 }
4332 return status;
4333}
4334
4335static enum hci_status
4336bthci_HandleOGFStatusParameters(struct rtw_adapter *padapter,
4337 struct packet_irp_hcicmd_data *pHciCmd)
4338{
4339 enum hci_status status = HCI_STATUS_SUCCESS;
4340
4341 switch (pHciCmd->OCF) {
4342 case HCI_READ_FAILED_CONTACT_COUNTER:
4343 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_FAILED_CONTACT_COUNTER\n"));
4344 status = bthci_CmdReadFailedContactCounter(padapter, pHciCmd);
4345 break;
4346 case HCI_RESET_FAILED_CONTACT_COUNTER:
4347 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_RESET_FAILED_CONTACT_COUNTER\n"));
4348 status = bthci_CmdResetFailedContactCounter(padapter, pHciCmd);
4349 break;
4350 case HCI_READ_LINK_QUALITY:
4351 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LINK_QUALITY\n"));
4352 status = bthci_CmdReadLinkQuality(padapter, pHciCmd);
4353 break;
4354 case HCI_READ_RSSI:
4355 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_RSSI\n"));
4356 status = bthci_CmdReadRSSI(padapter);
4357 break;
4358 case HCI_READ_LOCAL_AMP_INFO:
4359 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_AMP_INFO\n"));
4360 status = bthci_CmdReadLocalAMPInfo(padapter);
4361 break;
4362 case HCI_READ_LOCAL_AMP_ASSOC:
4363 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_AMP_ASSOC\n"));
4364 status = bthci_CmdReadLocalAMPAssoc(padapter, pHciCmd);
4365 break;
4366 case HCI_WRITE_REMOTE_AMP_ASSOC:
4367 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_REMOTE_AMP_ASSOC\n"));
4368 status = bthci_CmdWriteRemoteAMPAssoc(padapter, pHciCmd);
4369 break;
4370 default:
4371 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFStatusParameters(), Unknown case = 0x%x\n", pHciCmd->OCF));
4372 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n"));
4373 status = bthci_UnknownCMD(padapter, pHciCmd);
4374 break;
4375 }
4376 return status;
4377}
4378
4379static enum hci_status
4380bthci_HandleOGFLinkControlCMD(struct rtw_adapter *padapter,
4381 struct packet_irp_hcicmd_data *pHciCmd)
4382{
4383 enum hci_status status = HCI_STATUS_SUCCESS;
4384
4385 switch (pHciCmd->OCF) {
4386 case HCI_CREATE_PHYSICAL_LINK:
4387 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_CREATE_PHYSICAL_LINK\n"));
4388 status = bthci_CmdCreatePhysicalLink(padapter, pHciCmd);
4389 break;
4390 case HCI_ACCEPT_PHYSICAL_LINK:
4391 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ACCEPT_PHYSICAL_LINK\n"));
4392 status = bthci_CmdAcceptPhysicalLink(padapter, pHciCmd);
4393 break;
4394 case HCI_DISCONNECT_PHYSICAL_LINK:
4395 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_DISCONNECT_PHYSICAL_LINK\n"));
4396 status = bthci_CmdDisconnectPhysicalLink(padapter, pHciCmd);
4397 break;
4398 case HCI_CREATE_LOGICAL_LINK:
4399 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_CREATE_LOGICAL_LINK\n"));
4400 status = bthci_CmdCreateLogicalLink(padapter, pHciCmd);
4401 break;
4402 case HCI_ACCEPT_LOGICAL_LINK:
4403 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ACCEPT_LOGICAL_LINK\n"));
4404 status = bthci_CmdAcceptLogicalLink(padapter, pHciCmd);
4405 break;
4406 case HCI_DISCONNECT_LOGICAL_LINK:
4407 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_DISCONNECT_LOGICAL_LINK\n"));
4408 status = bthci_CmdDisconnectLogicalLink(padapter, pHciCmd);
4409 break;
4410 case HCI_LOGICAL_LINK_CANCEL:
4411 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_LOGICAL_LINK_CANCEL\n"));
4412 status = bthci_CmdLogicalLinkCancel(padapter, pHciCmd);
4413 break;
4414 case HCI_FLOW_SPEC_MODIFY:
4415 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_FLOW_SPEC_MODIFY\n"));
4416 status = bthci_CmdFlowSpecModify(padapter, pHciCmd);
4417 break;
4418 default:
4419 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFLinkControlCMD(), Unknown case = 0x%x\n", pHciCmd->OCF));
4420 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n"));
4421 status = bthci_UnknownCMD(padapter, pHciCmd);
4422 break;
4423 }
4424 return status;
4425}
4426
4427static enum hci_status
4428bthci_HandleOGFTestingCMD(struct rtw_adapter *padapter,
4429 struct packet_irp_hcicmd_data *pHciCmd)
4430{
4431 enum hci_status status = HCI_STATUS_SUCCESS;
4432 switch (pHciCmd->OCF) {
4433 case HCI_ENABLE_DEVICE_UNDER_TEST_MODE:
4434 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ENABLE_DEVICE_UNDER_TEST_MODE\n"));
4435 bthci_CmdEnableDeviceUnderTestMode(padapter, pHciCmd);
4436 break;
4437 case HCI_AMP_TEST_END:
4438 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_AMP_TEST_END\n"));
4439 bthci_CmdAMPTestEnd(padapter, pHciCmd);
4440 break;
4441 case HCI_AMP_TEST_COMMAND:
4442 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_AMP_TEST_COMMAND\n"));
4443 bthci_CmdAMPTestCommand(padapter, pHciCmd);
4444 break;
4445 case HCI_ENABLE_AMP_RECEIVER_REPORTS:
4446 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ENABLE_AMP_RECEIVER_REPORTS\n"));
4447 bthci_CmdEnableAMPReceiverReports(padapter, pHciCmd);
4448 break;
4449 default:
4450 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n"));
4451 status = bthci_UnknownCMD(padapter, pHciCmd);
4452 break;
4453 }
4454 return status;
4455}
4456
4457static enum hci_status
4458bthci_HandleOGFExtension(struct rtw_adapter *padapter,
4459 struct packet_irp_hcicmd_data *pHciCmd)
4460{
4461 enum hci_status status = HCI_STATUS_SUCCESS;
4462 switch (pHciCmd->OCF) {
4463 case HCI_SET_ACL_LINK_DATA_FLOW_MODE:
4464 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_ACL_LINK_DATA_FLOW_MODE\n"));
4465 status = bthci_CmdSetACLLinkDataFlowMode(padapter, pHciCmd);
4466 break;
4467 case HCI_SET_ACL_LINK_STATUS:
4468 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_ACL_LINK_STATUS\n"));
4469 status = bthci_CmdSetACLLinkStatus(padapter, pHciCmd);
4470 break;
4471 case HCI_SET_SCO_LINK_STATUS:
4472 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_SCO_LINK_STATUS\n"));
4473 status = bthci_CmdSetSCOLinkStatus(padapter, pHciCmd);
4474 break;
4475 case HCI_SET_RSSI_VALUE:
4476 RTPRINT(FIOCTL, IOCTL_BT_EVENT_PERIODICAL, ("HCI_SET_RSSI_VALUE\n"));
4477 status = bthci_CmdSetRSSIValue(padapter, pHciCmd);
4478 break;
4479 case HCI_SET_CURRENT_BLUETOOTH_STATUS:
4480 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_CURRENT_BLUETOOTH_STATUS\n"));
4481 status = bthci_CmdSetCurrentBluetoothStatus(padapter, pHciCmd);
4482 break;
4483 /* The following is for RTK8723 */
4484
4485 case HCI_EXTENSION_VERSION_NOTIFY:
4486 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_EXTENSION_VERSION_NOTIFY\n"));
4487 status = bthci_CmdExtensionVersionNotify(padapter, pHciCmd);
4488 break;
4489 case HCI_LINK_STATUS_NOTIFY:
4490 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_LINK_STATUS_NOTIFY\n"));
4491 status = bthci_CmdLinkStatusNotify(padapter, pHciCmd);
4492 break;
4493 case HCI_BT_OPERATION_NOTIFY:
4494 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_BT_OPERATION_NOTIFY\n"));
4495 status = bthci_CmdBtOperationNotify(padapter, pHciCmd);
4496 break;
4497 case HCI_ENABLE_WIFI_SCAN_NOTIFY:
4498 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_ENABLE_WIFI_SCAN_NOTIFY\n"));
4499 status = bthci_CmdEnableWifiScanNotify(padapter, pHciCmd);
4500 break;
4501
4502 /* The following is for IVT */
4503 case HCI_WIFI_CURRENT_CHANNEL:
4504 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_WIFI_CURRENT_CHANNEL\n"));
4505 status = bthci_CmdWIFICurrentChannel(padapter, pHciCmd);
4506 break;
4507 case HCI_WIFI_CURRENT_BANDWIDTH:
4508 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_WIFI_CURRENT_BANDWIDTH\n"));
4509 status = bthci_CmdWIFICurrentBandwidth(padapter, pHciCmd);
4510 break;
4511 case HCI_WIFI_CONNECTION_STATUS:
4512 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_WIFI_CONNECTION_STATUS\n"));
4513 status = bthci_CmdWIFIConnectionStatus(padapter, pHciCmd);
4514 break;
4515
4516 default:
4517 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_UNKNOWN_COMMAND\n"));
4518 status = bthci_UnknownCMD(padapter, pHciCmd);
4519 break;
4520 }
4521 return status;
4522}
4523
4524static void
4525bthci_StateStarting(struct rtw_adapter *padapter,
4526 enum hci_state_with_cmd StateCmd, u8 EntryNum)
4527{
4528 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
4529 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
4530
4531 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Starting], "));
4532 switch (StateCmd) {
4533 case STATE_CMD_CONNECT_ACCEPT_TIMEOUT:
4534 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CONNECT_ACCEPT_TIMEOUT\n"));
4535 pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_CONNECT_ACCEPT_TIMEOUT;
4536 pBtMgnt->bNeedNotifyAMPNoCap = true;
4537 BTHCI_DisconnectPeer(padapter, EntryNum);
4538 break;
4539 case STATE_CMD_DISCONNECT_PHY_LINK:
4540 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n"));
4541
4542 bthci_EventDisconnectPhyLinkComplete(padapter,
4543 HCI_STATUS_SUCCESS,
4544 pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason,
4545 EntryNum);
4546
4547 del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer);
4548
4549 pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_UNKNOW_CONNECT_ID;
4550
4551 BTHCI_DisconnectPeer(padapter, EntryNum);
4552 break;
4553 case STATE_CMD_MAC_START_COMPLETE:
4554 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_START_COMPLETE\n"));
4555 if (pBTInfo->BtAsocEntry[EntryNum].AMPRole == AMP_BTAP_CREATOR)
4556 bthci_EventChannelSelected(padapter, EntryNum);
4557 break;
4558 default:
4559 RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd));
4560 break;
4561 }
4562}
4563
4564static void
4565bthci_StateConnecting(struct rtw_adapter *padapter,
4566 enum hci_state_with_cmd StateCmd, u8 EntryNum)
4567{
4568 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
4569 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
4570
4571 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Connecting], "));
4572 switch (StateCmd) {
4573 case STATE_CMD_CONNECT_ACCEPT_TIMEOUT:
4574 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CONNECT_ACCEPT_TIMEOUT\n"));
4575 pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_CONNECT_ACCEPT_TIMEOUT;
4576 pBtMgnt->bNeedNotifyAMPNoCap = true;
4577 BTHCI_DisconnectPeer(padapter, EntryNum);
4578 break;
4579 case STATE_CMD_MAC_CONNECT_COMPLETE:
4580 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_CONNECT_COMPLETE\n"));
4581
4582 if (pBTInfo->BtAsocEntry[EntryNum].AMPRole == AMP_BTAP_JOINER) {
4583 RT_TRACE(_module_rtl871x_security_c_,
4584 _drv_info_, ("StateConnecting \n"));
4585 }
4586 break;
4587 case STATE_CMD_DISCONNECT_PHY_LINK:
4588 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n"));
4589
4590 bthci_EventDisconnectPhyLinkComplete(padapter,
4591 HCI_STATUS_SUCCESS,
4592 pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason,
4593 EntryNum);
4594
4595 pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_UNKNOW_CONNECT_ID;
4596
4597 del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer);
4598
4599 BTHCI_DisconnectPeer(padapter, EntryNum);
4600
4601 break;
4602 case STATE_CMD_MAC_CONNECT_CANCEL_INDICATE:
4603 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_CONNECT_CANCEL_INDICATE\n"));
4604 pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_CONTROLLER_BUSY;
4605 /* Because this state cmd is caused by the BTHCI_EventAMPStatusChange(), */
4606 /* we don't need to send event in the following BTHCI_DisconnectPeer() again. */
4607 pBtMgnt->bNeedNotifyAMPNoCap = false;
4608 BTHCI_DisconnectPeer(padapter, EntryNum);
4609 break;
4610 default:
4611 RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd));
4612 break;
4613 }
4614}
4615
4616static void
4617bthci_StateConnected(struct rtw_adapter *padapter,
4618 enum hci_state_with_cmd StateCmd, u8 EntryNum)
4619{
4620/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
4621 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
4622 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
4623 u8 i;
4624 u16 logicHandle = 0;
4625
4626 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Connected], "));
4627 switch (StateCmd) {
4628 case STATE_CMD_DISCONNECT_PHY_LINK:
4629 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n"));
4630
4631 /* When we are trying to disconnect the phy link, we should disconnect log link first, */
4632 for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) {
4633 if (pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData->BtLogLinkhandle != 0) {
4634 logicHandle = pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData->BtLogLinkhandle;
4635
4636 bthci_EventDisconnectLogicalLinkComplete(padapter, HCI_STATUS_SUCCESS,
4637 logicHandle, pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason);
4638
4639 pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData->BtLogLinkhandle = 0;
4640 }
4641 }
4642
4643 bthci_EventDisconnectPhyLinkComplete(padapter,
4644 HCI_STATUS_SUCCESS,
4645 pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason,
4646 EntryNum);
4647
4648 del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer);
4649
4650 BTHCI_DisconnectPeer(padapter, EntryNum);
4651 break;
4652
4653 case STATE_CMD_MAC_DISCONNECT_INDICATE:
4654 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_DISCONNECT_INDICATE\n"));
4655
4656 bthci_EventDisconnectPhyLinkComplete(padapter,
4657 HCI_STATUS_SUCCESS,
4658 /* TODO: Remote Host not local host */
4659 HCI_STATUS_CONNECT_TERMINATE_LOCAL_HOST,
4660 EntryNum);
4661 BTHCI_DisconnectPeer(padapter, EntryNum);
4662
4663 break;
4664 case STATE_CMD_ENTER_STATE:
4665 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_ENTER_STATE\n"));
4666
4667 if (pBtMgnt->bBTConnectInProgress) {
4668 pBtMgnt->bBTConnectInProgress = false;
4669 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n"));
4670 }
4671 pBTInfo->BtAsocEntry[EntryNum].BtCurrentState = HCI_STATE_CONNECTED;
4672 pBTInfo->BtAsocEntry[EntryNum].b4waySuccess = true;
4673 pBtMgnt->bStartSendSupervisionPkt = true;
4674
4675 /* for rate adaptive */
4676
4677 if (padapter->HalFunc.UpdateRAMaskHandler)
4678 padapter->HalFunc.UpdateRAMaskHandler(padapter, MAX_FW_SUPPORT_MACID_NUM-1-EntryNum, 0);
4679
4680 rtw_hal_set_hwreg23a(padapter, HW_VAR_BASIC_RATE, padapter->mlmepriv.cur_network.network.SupportedRates);
4681 BTDM_SetFwChnlInfo(padapter, RT_MEDIA_CONNECT);
4682 break;
4683 default:
4684 RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd));
4685 break;
4686 }
4687}
4688
4689static void
4690bthci_StateAuth(struct rtw_adapter *padapter, enum hci_state_with_cmd StateCmd,
4691 u8 EntryNum)
4692{
4693 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
4694 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
4695
4696 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Authenticating], "));
4697 switch (StateCmd) {
4698 case STATE_CMD_CONNECT_ACCEPT_TIMEOUT:
4699 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CONNECT_ACCEPT_TIMEOUT\n"));
4700 pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_CONNECT_ACCEPT_TIMEOUT;
4701 pBtMgnt->bNeedNotifyAMPNoCap = true;
4702 BTHCI_DisconnectPeer(padapter, EntryNum);
4703 break;
4704 case STATE_CMD_DISCONNECT_PHY_LINK:
4705 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n"));
4706 bthci_EventDisconnectPhyLinkComplete(padapter,
4707 HCI_STATUS_SUCCESS,
4708 pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason,
4709 EntryNum);
4710
4711 pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_UNKNOW_CONNECT_ID;
4712
4713 del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer);
4714
4715 BTHCI_DisconnectPeer(padapter, EntryNum);
4716 break;
4717 case STATE_CMD_4WAY_FAILED:
4718 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_4WAY_FAILED\n"));
4719
4720 pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus = HCI_STATUS_AUTH_FAIL;
4721 pBtMgnt->bNeedNotifyAMPNoCap = true;
4722
4723 BTHCI_DisconnectPeer(padapter, EntryNum);
4724
4725 del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer);
4726 break;
4727 case STATE_CMD_4WAY_SUCCESSED:
4728 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_4WAY_SUCCESSED\n"));
4729
4730 bthci_EventPhysicalLinkComplete(padapter, HCI_STATUS_SUCCESS, EntryNum, INVALID_PL_HANDLE);
4731
4732 del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer);
4733
4734 BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTED, STATE_CMD_ENTER_STATE, EntryNum);
4735 break;
4736 default:
4737 RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd));
4738 break;
4739 }
4740}
4741
4742static void
4743bthci_StateDisconnecting(struct rtw_adapter *padapter,
4744 enum hci_state_with_cmd StateCmd, u8 EntryNum)
4745{
4746 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
4747 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
4748
4749 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Disconnecting], "));
4750 switch (StateCmd) {
4751 case STATE_CMD_MAC_CONNECT_CANCEL_INDICATE:
4752 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_CONNECT_CANCEL_INDICATE\n"));
4753 if (pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent) {
4754 bthci_EventPhysicalLinkComplete(padapter,
4755 pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus,
4756 EntryNum, INVALID_PL_HANDLE);
4757 }
4758
4759 if (pBtMgnt->bBTConnectInProgress) {
4760 pBtMgnt->bBTConnectInProgress = false;
4761 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n"));
4762 }
4763
4764 BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_ENTER_STATE, EntryNum);
4765 break;
4766 case STATE_CMD_DISCONNECT_PHY_LINK:
4767 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n"));
4768
4769 bthci_EventDisconnectPhyLinkComplete(padapter,
4770 HCI_STATUS_SUCCESS,
4771 pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason,
4772 EntryNum);
4773
4774 del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer);
4775
4776 BTHCI_DisconnectPeer(padapter, EntryNum);
4777 break;
4778 default:
4779 RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd));
4780 break;
4781 }
4782}
4783
4784static void
4785bthci_StateDisconnected(struct rtw_adapter *padapter,
4786 enum hci_state_with_cmd StateCmd, u8 EntryNum)
4787{
4788/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
4789 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
4790 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
4791 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
4792
4793 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Disconnected], "));
4794 switch (StateCmd) {
4795 case STATE_CMD_CREATE_PHY_LINK:
4796 case STATE_CMD_ACCEPT_PHY_LINK:
4797 if (StateCmd == STATE_CMD_CREATE_PHY_LINK)
4798 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CREATE_PHY_LINK\n"));
4799 else
4800 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_ACCEPT_PHY_LINK\n"));
4801
4802 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT PS], Disable IPS and LPS\n"));
4803 ips_leave23a(padapter);
4804 LPS_Leave23a(padapter);
4805
4806 pBtMgnt->bPhyLinkInProgress = true;
4807 pBtMgnt->BTCurrentConnectType = BT_DISCONNECT;
4808 pBtMgnt->CurrentBTConnectionCnt++;
4809 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], CurrentBTConnectionCnt = %d\n",
4810 pBtMgnt->CurrentBTConnectionCnt));
4811 pBtMgnt->BtOperationOn = true;
4812 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], Bt Operation ON!! CurrentConnectEntryNum = %d\n",
4813 pBtMgnt->CurrentConnectEntryNum));
4814
4815 if (pBtMgnt->bBTConnectInProgress) {
4816 bthci_EventPhysicalLinkComplete(padapter, HCI_STATUS_CONTROLLER_BUSY, INVALID_ENTRY_NUM, pBtMgnt->BtCurrentPhyLinkhandle);
4817 bthci_RemoveEntryByEntryNum(padapter, EntryNum);
4818 return;
4819 }
4820
4821 if (StateCmd == STATE_CMD_CREATE_PHY_LINK)
4822 pBTInfo->BtAsocEntry[EntryNum].AMPRole = AMP_BTAP_CREATOR;
4823 else
4824 pBTInfo->BtAsocEntry[EntryNum].AMPRole = AMP_BTAP_JOINER;
4825
4826 /* 1. MAC not yet in selected channel */
4827 while (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)) {
4828 RTPRINT(FIOCTL, IOCTL_STATE, ("Scan/Roaming/Wifi Link is in Progress, wait 200 ms\n"));
4829 mdelay(200);
4830 }
4831 /* 2. MAC already in selected channel */
4832 RTPRINT(FIOCTL, IOCTL_STATE, ("Channel is Ready\n"));
4833 mod_timer(&pBTInfo->BTHCIJoinTimeoutTimer,
4834 jiffies + msecs_to_jiffies(pBtHciInfo->ConnAcceptTimeout));
4835
4836 pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent = true;
4837 break;
4838 case STATE_CMD_DISCONNECT_PHY_LINK:
4839 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n"));
4840
4841 del_timer_sync(&pBTInfo->BTHCIJoinTimeoutTimer);
4842
4843 bthci_EventDisconnectPhyLinkComplete(padapter,
4844 HCI_STATUS_SUCCESS,
4845 pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason,
4846 EntryNum);
4847
4848 if (pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent) {
4849 bthci_EventPhysicalLinkComplete(padapter,
4850 HCI_STATUS_UNKNOW_CONNECT_ID,
4851 EntryNum, INVALID_PL_HANDLE);
4852 }
4853
4854 if (pBtMgnt->bBTConnectInProgress) {
4855 pBtMgnt->bBTConnectInProgress = false;
4856 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n"));
4857 }
4858 BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_ENTER_STATE, EntryNum);
4859 bthci_RemoveEntryByEntryNum(padapter, EntryNum);
4860 break;
4861 case STATE_CMD_ENTER_STATE:
4862 RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_ENTER_STATE\n"));
4863 break;
4864 default:
4865 RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd));
4866 break;
4867 }
4868}
4869
4870void BTHCI_EventParse(struct rtw_adapter *padapter, void *pEvntData, u32 dataLen)
4871{
4872}
4873
4874u8 BTHCI_HsConnectionEstablished(struct rtw_adapter *padapter)
4875{
4876 u8 bBtConnectionExist = false;
4877 struct bt_30info *pBtinfo = GET_BT_INFO(padapter);
4878 u8 i;
4879
4880 for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) {
4881 if (pBtinfo->BtAsocEntry[i].b4waySuccess) {
4882 bBtConnectionExist = true;
4883 break;
4884 }
4885 }
4886
4887/*RTPRINT(FIOCTL, IOCTL_STATE, (" BTHCI_HsConnectionEstablished(), connection exist = %d\n", bBtConnectionExist)); */
4888
4889 return bBtConnectionExist;
4890}
4891
4892static u8
4893BTHCI_CheckProfileExist(struct rtw_adapter *padapter,
4894 enum bt_traffic_mode_profile Profile)
4895{
4896 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
4897 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
4898 u8 IsPRofile = false;
4899 u8 i = 0;
4900
4901 for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) {
4902 if (pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile == Profile) {
4903 IsPRofile = true;
4904 break;
4905 }
4906 }
4907
4908 return IsPRofile;
4909}
4910
4911void BTHCI_UpdateBTProfileRTKToMoto(struct rtw_adapter *padapter)
4912{
4913 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
4914 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
4915 u8 i = 0;
4916
4917 pBtMgnt->ExtConfig.NumberOfSCO = 0;
4918
4919 for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) {
4920 pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = BT_PROFILE_NONE;
4921
4922 if (pBtMgnt->ExtConfig.linkInfo[i].BTProfile == BT_PROFILE_SCO)
4923 pBtMgnt->ExtConfig.NumberOfSCO++;
4924
4925 pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = pBtMgnt->ExtConfig.linkInfo[i].BTProfile;
4926 switch (pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile) {
4927 case BT_PROFILE_SCO:
4928 break;
4929 case BT_PROFILE_PAN:
4930 pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = BT_MOTOR_EXT_BE;
4931 pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = BT_MOTOR_EXT_BE;
4932 break;
4933 case BT_PROFILE_A2DP:
4934 pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = BT_MOTOR_EXT_GULB;
4935 pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = BT_MOTOR_EXT_GULB;
4936 break;
4937 case BT_PROFILE_HID:
4938 pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = BT_MOTOR_EXT_GUL;
4939 pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = BT_MOTOR_EXT_BE;
4940 break;
4941 default:
4942 break;
4943 }
4944 }
4945
4946 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RTK, NumberOfHandle = %d, NumberOfSCO = %d\n",
4947 pBtMgnt->ExtConfig.NumberOfHandle, pBtMgnt->ExtConfig.NumberOfSCO));
4948}
4949
4950void BTHCI_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType)
4951{
4952 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
4953 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
4954
4955 if (pBtMgnt->ExtConfig.bEnableWifiScanNotify)
4956 bthci_EventExtWifiScanNotify(padapter, scanType);
4957}
4958
4959void
4960BTHCI_StateMachine(
4961 struct rtw_adapter *padapter,
4962 u8 StateToEnter,
4963 enum hci_state_with_cmd StateCmd,
4964 u8 EntryNum
4965 )
4966{
4967 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
4968 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
4969
4970 if (EntryNum == 0xff) {
4971 RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, error EntryNum = 0x%x \n", EntryNum));
4972 return;
4973 }
4974 RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, EntryNum = 0x%x, CurrentState = 0x%x, BtNextState = 0x%x, StateCmd = 0x%x , StateToEnter = 0x%x\n",
4975 EntryNum, pBTInfo->BtAsocEntry[EntryNum].BtCurrentState, pBTInfo->BtAsocEntry[EntryNum].BtNextState, StateCmd, StateToEnter));
4976
4977 if (pBTInfo->BtAsocEntry[EntryNum].BtNextState & StateToEnter) {
4978 pBTInfo->BtAsocEntry[EntryNum].BtCurrentState = StateToEnter;
4979
4980 switch (StateToEnter) {
4981 case HCI_STATE_STARTING:
4982 pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTING | HCI_STATE_CONNECTING;
4983 bthci_StateStarting(padapter, StateCmd, EntryNum);
4984 break;
4985 case HCI_STATE_CONNECTING:
4986 pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_CONNECTING | HCI_STATE_DISCONNECTING | HCI_STATE_AUTHENTICATING;
4987 bthci_StateConnecting(padapter, StateCmd, EntryNum);
4988 break;
4989 case HCI_STATE_AUTHENTICATING:
4990 pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTING | HCI_STATE_CONNECTED;
4991 bthci_StateAuth(padapter, StateCmd, EntryNum);
4992 break;
4993 case HCI_STATE_CONNECTED:
4994 pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_CONNECTED | HCI_STATE_DISCONNECTING;
4995 bthci_StateConnected(padapter, StateCmd, EntryNum);
4996 break;
4997 case HCI_STATE_DISCONNECTING:
4998 pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTED | HCI_STATE_DISCONNECTING;
4999 bthci_StateDisconnecting(padapter, StateCmd, EntryNum);
5000 break;
5001 case HCI_STATE_DISCONNECTED:
5002 pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTED | HCI_STATE_STARTING | HCI_STATE_CONNECTING;
5003 bthci_StateDisconnected(padapter, StateCmd, EntryNum);
5004 break;
5005 default:
5006 RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, Unknown state to enter!!!\n"));
5007 break;
5008 }
5009 } else {
5010 RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, Wrong state to enter\n"));
5011 }
5012
5013 /* 20100325 Joseph: Disable/Enable IPS/LPS according to BT status. */
5014 if (!pBtMgnt->bBTConnectInProgress && !pBtMgnt->BtOperationOn) {
5015 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT PS], ips_enter23a()\n"));
5016 ips_enter23a(padapter);
5017 }
5018}
5019
5020void BTHCI_DisconnectPeer(struct rtw_adapter *padapter, u8 EntryNum)
5021{
5022 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
5023 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
5024
5025 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, (" BTHCI_DisconnectPeer()\n"));
5026
5027 BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTING, STATE_CMD_MAC_CONNECT_CANCEL_INDICATE, EntryNum);
5028
5029 if (pBTInfo->BtAsocEntry[EntryNum].bUsed) {
5030/*BTPKT_SendDeauthentication(padapter, pBTInfo->BtAsocEntry[EntryNum].BTRemoteMACAddr, unspec_reason); not porting yet */
5031 }
5032
5033 if (pBtMgnt->bBTConnectInProgress) {
5034 pBtMgnt->bBTConnectInProgress = false;
5035 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n"));
5036 }
5037
5038 bthci_RemoveEntryByEntryNum(padapter, EntryNum);
5039
5040 if (pBtMgnt->bNeedNotifyAMPNoCap) {
5041 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT AMPStatus], set to invalid in BTHCI_DisconnectPeer()\n"));
5042 BTHCI_EventAMPStatusChange(padapter, AMP_STATUS_NO_CAPACITY_FOR_BT);
5043 }
5044}
5045
5046void BTHCI_EventNumOfCompletedDataBlocks(struct rtw_adapter *padapter)
5047{
5048/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
5049 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
5050 struct bt_hci_info *pBtHciInfo = &pBTInfo->BtHciInfo;
5051 u8 localBuf[TmpLocalBufSize] = "";
5052 u8 *pRetPar, *pTriple;
5053 u8 len = 0, i, j, handleNum = 0;
5054 struct packet_irp_hcievent_data *PPacketIrpEvent;
5055 u16 *pu2Temp, *pPackets, *pHandle, *pDblocks;
5056 u8 sent = 0;
5057
5058 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
5059
5060 if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_NUM_OF_COMPLETE_DATA_BLOCKS)) {
5061 RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Num Of Completed DataBlocks, Ignore to send NumOfCompletedDataBlocksEvent due to event mask page 2\n"));
5062 return;
5063 }
5064
5065 /* Return parameters starts from here */
5066 pRetPar = &PPacketIrpEvent->Data[0];
5067 pTriple = &pRetPar[3];
5068 for (j = 0; j < MAX_BT_ASOC_ENTRY_NUM; j++) {
5069
5070 for (i = 0; i < MAX_LOGICAL_LINK_NUM; i++) {
5071 if (pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle) {
5072 handleNum++;
5073 pHandle = (u16 *)&pTriple[0]; /* Handle[i] */
5074 pPackets = (u16 *)&pTriple[2]; /* Num_Of_Completed_Packets[i] */
5075 pDblocks = (u16 *)&pTriple[4]; /* Num_Of_Completed_Blocks[i] */
5076 *pHandle = pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle;
5077 *pPackets = (u16)pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount;
5078 *pDblocks = (u16)pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount;
5079 if (pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount) {
5080 sent = 1;
5081 RTPRINT(FIOCTL, IOCTL_BT_EVENT_DETAIL,
5082 ("[BT event], Num Of Completed DataBlocks, Handle = 0x%x, Num_Of_Completed_Packets = 0x%x, Num_Of_Completed_Blocks = 0x%x\n",
5083 *pHandle, *pPackets, *pDblocks));
5084 }
5085 pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount = 0;
5086 len += 6;
5087 pTriple += len;
5088 }
5089 }
5090 }
5091
5092 pRetPar[2] = handleNum; /* Number_of_Handles */
5093 len += 1;
5094 pu2Temp = (u16 *)&pRetPar[0];
5095 *pu2Temp = BTTotalDataBlockNum;
5096 len += 2;
5097
5098 PPacketIrpEvent->EventCode = HCI_EVENT_NUM_OF_COMPLETE_DATA_BLOCKS;
5099 PPacketIrpEvent->Length = len;
5100 if (handleNum && sent)
5101 bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
5102}
5103
5104void BTHCI_EventAMPStatusChange(struct rtw_adapter *padapter, u8 AMP_Status)
5105{
5106 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
5107 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
5108 struct packet_irp_hcievent_data *PPacketIrpEvent;
5109 u8 len = 0;
5110 u8 localBuf[7] = "";
5111 u8 *pRetPar;
5112
5113 if (AMP_Status == AMP_STATUS_NO_CAPACITY_FOR_BT) {
5114 pBtMgnt->BTNeedAMPStatusChg = true;
5115 pBtMgnt->bNeedNotifyAMPNoCap = false;
5116
5117 BTHCI_DisconnectAll(padapter);
5118 } else if (AMP_Status == AMP_STATUS_FULL_CAPACITY_FOR_BT) {
5119 pBtMgnt->BTNeedAMPStatusChg = false;
5120 }
5121
5122 PPacketIrpEvent = (struct packet_irp_hcievent_data *)(&localBuf[0]);
5123 /* Return parameters starts from here */
5124 pRetPar = &PPacketIrpEvent->Data[0];
5125
5126 pRetPar[0] = 0; /* Status */
5127 len += 1;
5128 pRetPar[1] = AMP_Status; /* AMP_Status */
5129 len += 1;
5130
5131 PPacketIrpEvent->EventCode = HCI_EVENT_AMP_STATUS_CHANGE;
5132 PPacketIrpEvent->Length = len;
5133 if (bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2) == RT_STATUS_SUCCESS)
5134 RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_STATE), ("[BT event], AMP Status Change, AMP_Status = %d\n", AMP_Status));
5135}
5136
5137void BTHCI_DisconnectAll(struct rtw_adapter *padapter)
5138{
5139 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
5140 u8 i;
5141
5142 RTPRINT(FIOCTL, IOCTL_STATE, (" DisconnectALL()\n"));
5143
5144 for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) {
5145 if (pBTInfo->BtAsocEntry[i].b4waySuccess) {
5146 BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTED, STATE_CMD_DISCONNECT_PHY_LINK, i);
5147 } else if (pBTInfo->BtAsocEntry[i].bUsed) {
5148 if (pBTInfo->BtAsocEntry[i].BtCurrentState == HCI_STATE_CONNECTING) {
5149 BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTING, STATE_CMD_MAC_CONNECT_CANCEL_INDICATE, i);
5150 } else if (pBTInfo->BtAsocEntry[i].BtCurrentState == HCI_STATE_DISCONNECTING) {
5151 BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTING, STATE_CMD_MAC_CONNECT_CANCEL_INDICATE, i);
5152 }
5153 }
5154 }
5155}
5156
5157enum hci_status
5158BTHCI_HandleHCICMD(
5159 struct rtw_adapter *padapter,
5160 struct packet_irp_hcicmd_data *pHciCmd
5161 )
5162{
5163 enum hci_status status = HCI_STATUS_SUCCESS;
5164 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
5165 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
5166
5167 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("\n"));
5168 RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("HCI Command start, OGF = 0x%x, OCF = 0x%x, Length = 0x%x\n",
5169 pHciCmd->OGF, pHciCmd->OCF, pHciCmd->Length));
5170 if (pHciCmd->Length) {
5171 RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), "HCI Command, Hex Data :\n",
5172 &pHciCmd->Data[0], pHciCmd->Length);
5173 }
5174 if (pHciCmd->OGF == OGF_EXTENSION) {
5175 if (pHciCmd->OCF == HCI_SET_RSSI_VALUE)
5176 RTPRINT(FIOCTL, IOCTL_BT_EVENT_PERIODICAL, ("[BT cmd], "));
5177 else
5178 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT cmd], "));
5179 } else {
5180 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("[BT cmd], "));
5181 }
5182
5183 pBtDbg->dbgHciInfo.hciCmdCnt++;
5184
5185 switch (pHciCmd->OGF) {
5186 case LINK_CONTROL_COMMANDS:
5187 status = bthci_HandleOGFLinkControlCMD(padapter, pHciCmd);
5188 break;
5189 case HOLD_MODE_COMMAND:
5190 break;
5191 case OGF_SET_EVENT_MASK_COMMAND:
5192 status = bthci_HandleOGFSetEventMaskCMD(padapter, pHciCmd);
5193 break;
5194 case OGF_INFORMATIONAL_PARAMETERS:
5195 status = bthci_HandleOGFInformationalParameters(padapter, pHciCmd);
5196 break;
5197 case OGF_STATUS_PARAMETERS:
5198 status = bthci_HandleOGFStatusParameters(padapter, pHciCmd);
5199 break;
5200 case OGF_TESTING_COMMANDS:
5201 status = bthci_HandleOGFTestingCMD(padapter, pHciCmd);
5202 break;
5203 case OGF_EXTENSION:
5204 status = bthci_HandleOGFExtension(padapter, pHciCmd);
5205 break;
5206 default:
5207 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI Command(), Unknown OGF = 0x%x\n", pHciCmd->OGF));
5208 RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n"));
5209 status = bthci_UnknownCMD(padapter, pHciCmd);
5210 break;
5211 }
5212 RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("HCI Command execution end!!\n"));
5213
5214 return status;
5215}
5216
5217/* ===== End of sync from SD7 driver COMMOM/bt_hci.c ===== */
5218#endif
5219
5220#ifdef __HALBTC87231ANT_C__ /* HAL/BTCoexist/HalBtc87231Ant.c */
5221
5222static const char *const BtStateString[] = {
5223 "BT_DISABLED",
5224 "BT_NO_CONNECTION",
5225 "BT_CONNECT_IDLE",
5226 "BT_INQ_OR_PAG",
5227 "BT_ACL_ONLY_BUSY",
5228 "BT_SCO_ONLY_BUSY",
5229 "BT_ACL_SCO_BUSY",
5230 "BT_ACL_INQ_OR_PAG",
5231 "BT_STATE_NOT_DEFINED"
5232};
5233
5234/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.c ===== */
5235
5236static void btdm_SetFwIgnoreWlanAct(struct rtw_adapter *padapter, u8 bEnable)
5237{
5238 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
5239 u8 H2C_Parameter[1] = {0};
5240
5241 if (bEnable) {
5242 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Ignore Wlan_Act !!\n"));
5243 H2C_Parameter[0] |= BIT(0); /* function enable */
5244 pHalData->bt_coexist.bFWCoexistAllOff = false;
5245 } else {
5246 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT don't ignore Wlan_Act !!\n"));
5247 }
5248
5249 RTPRINT(FBT, BT_TRACE, ("[BTCoex], set FW for BT Ignore Wlan_Act, write 0x25 = 0x%02x\n",
5250 H2C_Parameter[0]));
5251
5252 FillH2CCmd(padapter, BT_IGNORE_WLAN_ACT_EID, 1, H2C_Parameter);
5253}
5254
5255static void btdm_NotifyFwScan(struct rtw_adapter *padapter, u8 scanType)
5256{
5257 u8 H2C_Parameter[1] = {0};
5258
5259 if (scanType == true)
5260 H2C_Parameter[0] = 0x1;
5261
5262 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Notify FW for wifi scan, write 0x3b = 0x%02x\n",
5263 H2C_Parameter[0]));
5264
5265 FillH2CCmd(padapter, 0x3b, 1, H2C_Parameter);
5266}
5267
5268static void btdm_1AntSetPSMode(struct rtw_adapter *padapter,
5269 u8 enable, u8 smartps, u8 mode)
5270{
5271 struct pwrctrl_priv *pwrctrl;
5272
5273 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Current LPS(%s, %d), smartps =%d\n", enable == true?"ON":"OFF", mode, smartps));
5274
5275 pwrctrl = &padapter->pwrctrlpriv;
5276
5277 if (enable == true) {
5278 rtw_set_ps_mode23a(padapter, PS_MODE_MIN, smartps, mode);
5279 } else {
5280 rtw_set_ps_mode23a(padapter, PS_MODE_ACTIVE, 0, 0);
5281 LPS_RF_ON_check23a(padapter, 100);
5282 }
5283}
5284
5285static void btdm_1AntTSFSwitch(struct rtw_adapter *padapter, u8 enable)
5286{
5287 u8 oldVal, newVal;
5288
5289 oldVal = rtw_read8(padapter, 0x550);
5290
5291 if (enable)
5292 newVal = oldVal | EN_BCN_FUNCTION;
5293 else
5294 newVal = oldVal & ~EN_BCN_FUNCTION;
5295
5296 if (oldVal != newVal)
5297 rtw_write8(padapter, 0x550, newVal);
5298}
5299
5300static u8 btdm_Is1AntPsTdmaStateChange(struct rtw_adapter *padapter)
5301{
5302 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
5303 struct btdm_8723a_1ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;
5304
5305 if ((pBtdm8723->bPrePsTdmaOn != pBtdm8723->bCurPsTdmaOn) ||
5306 (pBtdm8723->prePsTdma != pBtdm8723->curPsTdma))
5307 return true;
5308 else
5309 return false;
5310}
5311
5312/* Before enter TDMA, make sure Power Saving is enable! */
5313static void
5314btdm_1AntPsTdma(
5315 struct rtw_adapter *padapter,
5316 u8 bTurnOn,
5317 u8 type
5318 )
5319{
5320 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
5321 struct btdm_8723a_1ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;
5322
5323 pBtdm8723->bCurPsTdmaOn = bTurnOn;
5324 pBtdm8723->curPsTdma = type;
5325 if (bTurnOn) {
5326 switch (type) {
5327 case 1: /* A2DP Level-1 or FTP/OPP */
5328 default:
5329 if (btdm_Is1AntPsTdmaStateChange(padapter)) {
5330 /* wide duration for WiFi */
5331 BTDM_SetFw3a(padapter, 0xd3, 0x1a, 0x1a, 0x0, 0x58);
5332 }
5333 break;
5334 case 2: /* A2DP Level-2 */
5335 if (btdm_Is1AntPsTdmaStateChange(padapter)) {
5336 /* normal duration for WiFi */
5337 BTDM_SetFw3a(padapter, 0xd3, 0x12, 0x12, 0x0, 0x58);
5338 }
5339 break;
5340 case 3: /* BT FTP/OPP */
5341 if (btdm_Is1AntPsTdmaStateChange(padapter)) {
5342 /* normal duration for WiFi */
5343 BTDM_SetFw3a(padapter, 0xd3, 0x30, 0x03, 0x10, 0x58);
5344
5345 }
5346 break;
5347 case 4: /* for wifi scan & BT is connected */
5348 if (btdm_Is1AntPsTdmaStateChange(padapter)) {
5349 /* protect 3 beacons in 3-beacon period & no Tx pause at BT slot */
5350 BTDM_SetFw3a(padapter, 0x93, 0x15, 0x03, 0x14, 0x0);
5351 }
5352 break;
5353 case 5: /* for WiFi connected-busy & BT is Non-Connected-Idle */
5354 if (btdm_Is1AntPsTdmaStateChange(padapter)) {
5355 /* SCO mode, Ant fixed at WiFi, WLAN_Act toggle */
5356 BTDM_SetFw3a(padapter, 0x61, 0x15, 0x03, 0x31, 0x00);
5357 }
5358 break;
5359 case 9: /* ACL high-retry type - 2 */
5360 if (btdm_Is1AntPsTdmaStateChange(padapter)) {
5361 /* narrow duration for WiFi */
5362 BTDM_SetFw3a(padapter, 0xd3, 0xa, 0xa, 0x0, 0x58); /* narrow duration for WiFi */
5363 }
5364 break;
5365 case 10: /* for WiFi connect idle & BT ACL busy or WiFi Connected-Busy & BT is Inquiry */
5366 if (btdm_Is1AntPsTdmaStateChange(padapter))
5367 BTDM_SetFw3a(padapter, 0x13, 0xa, 0xa, 0x0, 0x40);
5368 break;
5369 case 11: /* ACL high-retry type - 3 */
5370 if (btdm_Is1AntPsTdmaStateChange(padapter)) {
5371 /* narrow duration for WiFi */
5372 BTDM_SetFw3a(padapter, 0xd3, 0x05, 0x05, 0x00, 0x58);
5373 }
5374 break;
5375 case 12: /* for WiFi Connected-Busy & BT is Connected-Idle */
5376 if (btdm_Is1AntPsTdmaStateChange(padapter)) {
5377 /* Allow High-Pri BT */
5378 BTDM_SetFw3a(padapter, 0xeb, 0x0a, 0x03, 0x31, 0x18);
5379 }
5380 break;
5381 case 20: /* WiFi only busy , TDMA mode for power saving */
5382 if (btdm_Is1AntPsTdmaStateChange(padapter))
5383 BTDM_SetFw3a(padapter, 0x13, 0x25, 0x25, 0x00, 0x00);
5384 break;
5385 case 27: /* WiFi DHCP/Site Survey & BT SCO busy */
5386 if (btdm_Is1AntPsTdmaStateChange(padapter))
5387 BTDM_SetFw3a(padapter, 0xa3, 0x25, 0x03, 0x31, 0x98);
5388 break;
5389 case 28: /* WiFi DHCP/Site Survey & BT idle */
5390 if (btdm_Is1AntPsTdmaStateChange(padapter))
5391 BTDM_SetFw3a(padapter, 0x69, 0x25, 0x03, 0x31, 0x00);
5392 break;
5393 case 29: /* WiFi DHCP/Site Survey & BT ACL busy */
5394 if (btdm_Is1AntPsTdmaStateChange(padapter)) {
5395 BTDM_SetFw3a(padapter, 0xeb, 0x1a, 0x1a, 0x01, 0x18);
5396 rtw_write32(padapter, 0x6c0, 0x5afa5afa);
5397 rtw_write32(padapter, 0x6c4, 0x5afa5afa);
5398 }
5399 break;
5400 case 30: /* WiFi idle & BT Inquiry */
5401 if (btdm_Is1AntPsTdmaStateChange(padapter))
5402 BTDM_SetFw3a(padapter, 0x93, 0x15, 0x03, 0x14, 0x00);
5403 break;
5404 case 31: /* BT HID */
5405 if (btdm_Is1AntPsTdmaStateChange(padapter))
5406 BTDM_SetFw3a(padapter, 0xd3, 0x1a, 0x1a, 0x00, 0x58);
5407 break;
5408 case 32: /* BT SCO & Inquiry */
5409 if (btdm_Is1AntPsTdmaStateChange(padapter))
5410 BTDM_SetFw3a(padapter, 0xab, 0x0a, 0x03, 0x11, 0x98);
5411 break;
5412 case 33: /* BT SCO & WiFi site survey */
5413 if (btdm_Is1AntPsTdmaStateChange(padapter))
5414 BTDM_SetFw3a(padapter, 0xa3, 0x25, 0x03, 0x30, 0x98);
5415 break;
5416 case 34: /* BT HID & WiFi site survey */
5417 if (btdm_Is1AntPsTdmaStateChange(padapter))
5418 BTDM_SetFw3a(padapter, 0xd3, 0x1a, 0x1a, 0x00, 0x18);
5419 break;
5420 case 35: /* BT HID & WiFi Connecting */
5421 if (btdm_Is1AntPsTdmaStateChange(padapter))
5422 BTDM_SetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0x00, 0x18);
5423 break;
5424 }
5425 } else {
5426 /* disable PS-TDMA */
5427 switch (type) {
5428 case 8:
5429 if (btdm_Is1AntPsTdmaStateChange(padapter)) {
5430 /* Antenna control by PTA, 0x870 = 0x310 */
5431 BTDM_SetFw3a(padapter, 0x8, 0x0, 0x0, 0x0, 0x0);
5432 }
5433 break;
5434 case 0:
5435 default:
5436 if (btdm_Is1AntPsTdmaStateChange(padapter)) {
5437 /* Antenna control by PTA, 0x870 = 0x310 */
5438 BTDM_SetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0);
5439 }
5440 rtw_write16(padapter, 0x860, 0x210); /* Switch Antenna to BT */
5441 RTPRINT(FBT, BT_TRACE, ("[BTCoex], 0x860 = 0x210, Switch Antenna to BT\n"));
5442 break;
5443 case 9:
5444 if (btdm_Is1AntPsTdmaStateChange(padapter)) {
5445 /* Antenna control by PTA, 0x870 = 0x310 */
5446 BTDM_SetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0);
5447 }
5448 rtw_write16(padapter, 0x860, 0x110); /* Switch Antenna to WiFi */
5449 RTPRINT(FBT, BT_TRACE, ("[BTCoex], 0x860 = 0x110, Switch Antenna to WiFi\n"));
5450 break;
5451 }
5452 }
5453
5454 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Current TDMA(%s, %d)\n",
5455 pBtdm8723->bCurPsTdmaOn?"ON":"OFF", pBtdm8723->curPsTdma));
5456
5457 /* update pre state */
5458 pBtdm8723->bPrePsTdmaOn = pBtdm8723->bCurPsTdmaOn;
5459 pBtdm8723->prePsTdma = pBtdm8723->curPsTdma;
5460}
5461
5462static void
5463_btdm_1AntSetPSTDMA(struct rtw_adapter *padapter, u8 bPSEn, u8 smartps,
5464 u8 psOption, u8 bTDMAOn, u8 tdmaType)
5465{
5466 struct pwrctrl_priv *pwrctrl;
5467 struct hal_data_8723a *pHalData;
5468 struct btdm_8723a_1ant *pBtdm8723;
5469 u8 psMode;
5470 u8 bSwitchPS;
5471
5472 if (!check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) &&
5473 (get_fwstate(&padapter->mlmepriv) != WIFI_NULL_STATE)) {
5474 btdm_1AntPsTdma(padapter, bTDMAOn, tdmaType);
5475 return;
5476 }
5477 psOption &= ~BIT(0);
5478
5479 RTPRINT(FBT, BT_TRACE,
5480 ("[BTCoex], Set LPS(%s, %d) TDMA(%s, %d)\n",
5481 bPSEn == true?"ON":"OFF", psOption,
5482 bTDMAOn == true?"ON":"OFF", tdmaType));
5483
5484 pwrctrl = &padapter->pwrctrlpriv;
5485 pHalData = GET_HAL_DATA(padapter);
5486 pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;
5487
5488 if (bPSEn) {
5489 if (pBtdm8723->bWiFiHalt) {
5490 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi in Halt!!\n"));
5491 return;
5492 }
5493
5494 if (pwrctrl->bInSuspend) {
5495 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi in Suspend!!\n"));
5496 return;
5497 }
5498
5499 if (padapter->bDriverStopped) {
5500 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi driver stopped!!\n"));
5501 return;
5502 }
5503
5504 if (padapter->bSurpriseRemoved) {
5505 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi Surprise Removed!!\n"));
5506 return;
5507 }
5508
5509 psMode = PS_MODE_MIN;
5510 } else {
5511 psMode = PS_MODE_ACTIVE;
5512 psOption = 0;
5513 }
5514
5515 if (psMode != pwrctrl->pwr_mode) {
5516 bSwitchPS = true;
5517 } else if (psMode != PS_MODE_ACTIVE) {
5518 if (psOption != pwrctrl->bcn_ant_mode)
5519 bSwitchPS = true;
5520 else if (smartps != pwrctrl->smart_ps)
5521 bSwitchPS = true;
5522 else
5523 bSwitchPS = false;
5524 } else {
5525 bSwitchPS = false;
5526 }
5527
5528 if (bSwitchPS) {
5529 /* disable TDMA */
5530 if (pBtdm8723->bCurPsTdmaOn) {
5531 if (!bTDMAOn) {
5532 btdm_1AntPsTdma(padapter, false, tdmaType);
5533 } else {
5534 if ((BT_IsBtDisabled(padapter)) ||
5535 (pHalData->bt_coexist.halCoex8723.c2hBtInfo == BT_INFO_STATE_NO_CONNECTION) ||
5536 (pHalData->bt_coexist.halCoex8723.c2hBtInfo == BT_INFO_STATE_CONNECT_IDLE) ||
5537 (tdmaType == 29))
5538 btdm_1AntPsTdma(padapter, false, 9);
5539 else
5540 btdm_1AntPsTdma(padapter, false, 0);
5541 }
5542 }
5543
5544 /* change Power Save State */
5545 btdm_1AntSetPSMode(padapter, bPSEn, smartps, psOption);
5546 }
5547
5548 btdm_1AntPsTdma(padapter, bTDMAOn, tdmaType);
5549}
5550
5551static void
5552btdm_1AntSetPSTDMA(struct rtw_adapter *padapter, u8 bPSEn,
5553 u8 psOption, u8 bTDMAOn, u8 tdmaType)
5554{
5555 _btdm_1AntSetPSTDMA(padapter, bPSEn, 0, psOption, bTDMAOn, tdmaType);
5556}
5557
5558static void btdm_1AntWifiParaAdjust(struct rtw_adapter *padapter, u8 bEnable)
5559{
5560 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
5561 struct btdm_8723a_1ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;
5562
5563 if (bEnable) {
5564 pBtdm8723->curWifiPara = 1;
5565 if (pBtdm8723->preWifiPara != pBtdm8723->curWifiPara)
5566 BTDM_SetSwPenaltyTxRateAdaptive(padapter, BT_TX_RATE_ADAPTIVE_LOW_PENALTY);
5567 } else {
5568 pBtdm8723->curWifiPara = 2;
5569 if (pBtdm8723->preWifiPara != pBtdm8723->curWifiPara)
5570 BTDM_SetSwPenaltyTxRateAdaptive(padapter, BT_TX_RATE_ADAPTIVE_NORMAL);
5571 }
5572
5573}
5574
5575static void btdm_1AntPtaParaReload(struct rtw_adapter *padapter)
5576{
5577 /* PTA parameter */
5578 rtw_write8(padapter, 0x6cc, 0x0); /* 1-Ant coex */
5579 rtw_write32(padapter, 0x6c8, 0xffff); /* wifi break table */
5580 rtw_write32(padapter, 0x6c4, 0x55555555); /* coex table */
5581
5582 /* Antenna switch control parameter */
5583 rtw_write32(padapter, 0x858, 0xaaaaaaaa);
5584 if (IS_8723A_A_CUT(GET_HAL_DATA(padapter)->VersionID)) {
5585 rtw_write32(padapter, 0x870, 0x0); /* SPDT(connected with TRSW) control by hardware PTA */
5586 rtw_write8(padapter, 0x40, 0x24);
5587 } else {
5588 rtw_write8(padapter, 0x40, 0x20);
5589 rtw_write16(padapter, 0x860, 0x210); /* set antenna at bt side if ANTSW is software control */
5590 rtw_write32(padapter, 0x870, 0x300); /* SPDT(connected with TRSW) control by hardware PTA */
5591 rtw_write32(padapter, 0x874, 0x22804000); /* ANTSW keep by GNT_BT */
5592 }
5593
5594 /* coexistence parameters */
5595 rtw_write8(padapter, 0x778, 0x1); /* enable RTK mode PTA */
5596
5597 /* BT don't ignore WLAN_Act */
5598 btdm_SetFwIgnoreWlanAct(padapter, false);
5599}
5600
5601/*
5602 * Return
5603 *1: upgrade (add WiFi duration time)
5604 *0: keep
5605 *-1: downgrade (add BT duration time)
5606 */
5607static s8 btdm_1AntTdmaJudgement(struct rtw_adapter *padapter, u8 retry)
5608{
5609 struct hal_data_8723a *pHalData;
5610 struct btdm_8723a_1ant *pBtdm8723;
5611 static s8 up, dn, m = 1, n = 3, WaitCount;
5612 s8 ret;
5613
5614 pHalData = GET_HAL_DATA(padapter);
5615 pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;
5616 ret = 0;
5617
5618 if (pBtdm8723->psTdmaMonitorCnt == 0) {
5619 up = 0;
5620 dn = 0;
5621 m = 1;
5622 n = 3;
5623 WaitCount = 0;
5624 } else {
5625 WaitCount++;
5626 }
5627
5628 if (retry == 0) {
5629 /* no retry in the last 2-second duration */
5630 up++;
5631 dn--;
5632 if (dn < 0)
5633 dn = 0;
5634 if (up >= 3*m) {
5635 /* retry = 0 in consecutive 3m*(2s), add WiFi duration */
5636 ret = 1;
5637
5638 n = 3;
5639 up = 0;
5640 dn = 0;
5641 WaitCount = 0;
5642 }
5643 } else if (retry <= 3) {
5644 /* retry<= 3 in the last 2-second duration */
5645 up--;
5646 dn++;
5647 if (up < 0)
5648 up = 0;
5649
5650 if (dn == 2) {
5651 /* retry<= 3 in consecutive 2*(2s), minus WiFi duration (add BT duration) */
5652 ret = -1;
5653
5654 /* record how many time downgrad WiFi duration */
5655 if (WaitCount <= 2)
5656 m++;
5657 else
5658 m = 1;
5659 /* the max number of m is 20 */
5660 /* the longest time of upgrade WiFi duration is 20*3*2s = 120s */
5661 if (m >= 20)
5662 m = 20;
5663 up = 0;
5664 dn = 0;
5665 WaitCount = 0;
5666 }
5667 } else {
5668 /* retry count > 3 */
5669 /* retry>3, minus WiFi duration (add BT duration) */
5670 ret = -1;
5671
5672 /* record how many time downgrad WiFi duration */
5673 if (WaitCount == 1)
5674 m++;
5675 else
5676 m = 1;
5677 if (m >= 20)
5678 m = 20;
5679
5680 up = 0;
5681 dn = 0;
5682 WaitCount = 0;
5683 }
5684 return ret;
5685}
5686
5687static void btdm_1AntTdmaDurationAdjustForACL(struct rtw_adapter *padapter)
5688{
5689 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
5690 struct btdm_8723a_1ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;
5691
5692 if (pBtdm8723->psTdmaGlobalCnt != pBtdm8723->psTdmaMonitorCnt) {
5693 pBtdm8723->psTdmaMonitorCnt = 0;
5694 pBtdm8723->psTdmaGlobalCnt = 0;
5695 }
5696 if (pBtdm8723->psTdmaMonitorCnt == 0) {
5697 btdm_1AntSetPSTDMA(padapter, true, 0, true, 2);
5698 pBtdm8723->psTdmaDuAdjType = 2;
5699 } else {
5700 /* Now we only have 4 level Ps Tdma, */
5701 /* if that's not the following 4 level(will changed by wifi scan, dhcp...), */
5702 /* then we have to adjust it back to the previous record one. */
5703 if ((pBtdm8723->curPsTdma != 1) &&
5704 (pBtdm8723->curPsTdma != 2) &&
5705 (pBtdm8723->curPsTdma != 9) &&
5706 (pBtdm8723->curPsTdma != 11)) {
5707 btdm_1AntSetPSTDMA(padapter, true, 0, true, pBtdm8723->psTdmaDuAdjType);
5708 } else {
5709 s32 judge = 0;
5710
5711 judge = btdm_1AntTdmaJudgement(padapter, pHalData->bt_coexist.halCoex8723.btRetryCnt);
5712 if (judge == -1) {
5713 if (pBtdm8723->curPsTdma == 1) {
5714 /* Decrease WiFi duration for high BT retry */
5715 if (pHalData->bt_coexist.halCoex8723.btInfoExt)
5716 pBtdm8723->psTdmaDuAdjType = 9;
5717 else
5718 pBtdm8723->psTdmaDuAdjType = 2;
5719 btdm_1AntSetPSTDMA(padapter, true, 0, true, pBtdm8723->psTdmaDuAdjType);
5720 } else if (pBtdm8723->curPsTdma == 2) {
5721 btdm_1AntSetPSTDMA(padapter, true, 0, true, 9);
5722 pBtdm8723->psTdmaDuAdjType = 9;
5723 } else if (pBtdm8723->curPsTdma == 9) {
5724 btdm_1AntSetPSTDMA(padapter, true, 0, true, 11);
5725 pBtdm8723->psTdmaDuAdjType = 11;
5726 }
5727 } else if (judge == 1) {
5728 if (pBtdm8723->curPsTdma == 11) {
5729 btdm_1AntSetPSTDMA(padapter, true, 0, true, 9);
5730 pBtdm8723->psTdmaDuAdjType = 9;
5731 } else if (pBtdm8723->curPsTdma == 9) {
5732 if (pHalData->bt_coexist.halCoex8723.btInfoExt)
5733 pBtdm8723->psTdmaDuAdjType = 9;
5734 else
5735 pBtdm8723->psTdmaDuAdjType = 2;
5736 btdm_1AntSetPSTDMA(padapter, true, 0, true, pBtdm8723->psTdmaDuAdjType);
5737 } else if (pBtdm8723->curPsTdma == 2) {
5738 if (pHalData->bt_coexist.halCoex8723.btInfoExt)
5739 pBtdm8723->psTdmaDuAdjType = 9;
5740 else
5741 pBtdm8723->psTdmaDuAdjType = 1;
5742 btdm_1AntSetPSTDMA(padapter, true, 0, true, pBtdm8723->psTdmaDuAdjType);
5743 }
5744 }
5745 }
5746 RTPRINT(FBT, BT_TRACE,
5747 ("[BTCoex], ACL current TDMA(%s, %d)\n",
5748 (pBtdm8723->bCurPsTdmaOn ? "ON" : "OFF"), pBtdm8723->curPsTdma));
5749 }
5750 pBtdm8723->psTdmaMonitorCnt++;
5751}
5752
5753static void btdm_1AntCoexProcessForWifiConnect(struct rtw_adapter *padapter)
5754{
5755 struct mlme_priv *pmlmepriv;
5756 struct hal_data_8723a *pHalData;
5757 struct bt_coexist_8723a *pBtCoex;
5758 struct btdm_8723a_1ant *pBtdm8723;
5759 u8 BtState;
5760
5761 pmlmepriv = &padapter->mlmepriv;
5762 pHalData = GET_HAL_DATA(padapter);
5763 pBtCoex = &pHalData->bt_coexist.halCoex8723;
5764 pBtdm8723 = &pBtCoex->btdm1Ant;
5765 BtState = pBtCoex->c2hBtInfo;
5766
5767 RTPRINT(FBT, BT_TRACE, ("[BTCoex], WiFi is %s\n", BTDM_IsWifiBusy(padapter)?"Busy":"IDLE"));
5768 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT is %s\n", BtStateString[BtState]));
5769
5770 padapter->pwrctrlpriv.btcoex_rfon = false;
5771
5772 if ((!BTDM_IsWifiBusy(padapter)) && (!check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE)) &&
5773 ((BtState == BT_INFO_STATE_NO_CONNECTION) || (BtState == BT_INFO_STATE_CONNECT_IDLE))) {
5774 switch (BtState) {
5775 case BT_INFO_STATE_NO_CONNECTION:
5776 _btdm_1AntSetPSTDMA(padapter, true, 2, 0x26, false, 9);
5777 break;
5778 case BT_INFO_STATE_CONNECT_IDLE:
5779 _btdm_1AntSetPSTDMA(padapter, true, 2, 0x26, false, 0);
5780 break;
5781 }
5782 } else {
5783 switch (BtState) {
5784 case BT_INFO_STATE_NO_CONNECTION:
5785 case BT_INFO_STATE_CONNECT_IDLE:
5786 /* WiFi is Busy */
5787 btdm_1AntSetPSTDMA(padapter, false, 0, true, 5);
5788 rtw_write32(padapter, 0x6c0, 0x5a5a5a5a);
5789 rtw_write32(padapter, 0x6c4, 0x5a5a5a5a);
5790 break;
5791 case BT_INFO_STATE_ACL_INQ_OR_PAG:
5792 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT PROFILE is BT_INFO_STATE_ACL_INQ_OR_PAG\n"));
5793 case BT_INFO_STATE_INQ_OR_PAG:
5794 padapter->pwrctrlpriv.btcoex_rfon = true;
5795 btdm_1AntSetPSTDMA(padapter, true, 0, true, 30);
5796 break;
5797 case BT_INFO_STATE_SCO_ONLY_BUSY:
5798 case BT_INFO_STATE_ACL_SCO_BUSY:
5799 if (true == pBtCoex->bC2hBtInquiryPage) {
5800 btdm_1AntSetPSTDMA(padapter, false, 0, true, 32);
5801 } else {
5802#ifdef BTCOEX_CMCC_TEST
5803 btdm_1AntSetPSTDMA(padapter, false, 0, true, 23);
5804#else /* !BTCOEX_CMCC_TEST */
5805 btdm_1AntSetPSTDMA(padapter, false, 0, false, 8);
5806 rtw_write32(padapter, 0x6c0, 0x5a5a5a5a);
5807 rtw_write32(padapter, 0x6c4, 0x5a5a5a5a);
5808#endif /* !BTCOEX_CMCC_TEST */
5809 }
5810 break;
5811 case BT_INFO_STATE_ACL_ONLY_BUSY:
5812 padapter->pwrctrlpriv.btcoex_rfon = true;
5813 if (pBtCoex->c2hBtProfile == BT_INFO_HID) {
5814 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT PROFILE is HID\n"));
5815 btdm_1AntSetPSTDMA(padapter, true, 0, true, 31);
5816 } else if (pBtCoex->c2hBtProfile == BT_INFO_FTP) {
5817 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT PROFILE is FTP/OPP\n"));
5818 btdm_1AntSetPSTDMA(padapter, true, 0, true, 3);
5819 } else if (pBtCoex->c2hBtProfile == (BT_INFO_A2DP|BT_INFO_FTP)) {
5820 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT PROFILE is A2DP_FTP\n"));
5821 btdm_1AntSetPSTDMA(padapter, true, 0, true, 11);
5822 } else {
5823 if (pBtCoex->c2hBtProfile == BT_INFO_A2DP)
5824 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT PROFILE is A2DP\n"));
5825 else
5826 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT PROFILE is UNKNOWN(0x%02X)! Use A2DP Profile\n", pBtCoex->c2hBtProfile));
5827 btdm_1AntTdmaDurationAdjustForACL(padapter);
5828 }
5829 break;
5830 }
5831 }
5832
5833 pBtdm8723->psTdmaGlobalCnt++;
5834}
5835
5836static void btdm_1AntUpdateHalRAMask(struct rtw_adapter *padapter, u32 mac_id, u32 filter)
5837{
5838 u8 init_rate = 0;
5839 u8 raid;
5840 u32 mask;
5841 u8 shortGIrate = false;
5842 int supportRateNum = 0;
5843 struct sta_info *psta;
5844 struct hal_data_8723a *pHalData;
5845 struct dm_priv *pdmpriv;
5846 struct mlme_ext_priv *pmlmeext;
5847 struct mlme_ext_info *pmlmeinfo;
5848 struct wlan_bssid_ex *cur_network;
5849
5850 RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s, MACID =%d, filter = 0x%08x!!\n", __func__, mac_id, filter));
5851
5852 pHalData = GET_HAL_DATA(padapter);
5853 pdmpriv = &pHalData->dmpriv;
5854 pmlmeext = &padapter->mlmeextpriv;
5855 pmlmeinfo = &pmlmeext->mlmext_info;
5856 cur_network = &pmlmeinfo->network;
5857
5858 if (mac_id >= NUM_STA) { /* CAM_SIZE */
5859 RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s, MACID =%d illegal!!\n", __func__, mac_id));
5860 return;
5861 }
5862
5863 psta = pmlmeinfo->FW_sta_info[mac_id].psta;
5864 if (psta == NULL) {
5865 RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s, Can't find station!!\n", __func__));
5866 return;
5867 }
5868
5869 raid = psta->raid;
5870
5871 switch (mac_id) {
5872 case 0:/* for infra mode */
5873 supportRateNum = rtw_get_rateset_len23a(cur_network->SupportedRates);
5874 mask = update_supported_rate23a(cur_network->SupportedRates, supportRateNum);
5875 mask |= (pmlmeinfo->HT_enable) ? update_MSC_rate23a(&pmlmeinfo->HT_caps):0;
5876 if (support_short_GI23a(padapter, &pmlmeinfo->HT_caps))
5877 shortGIrate = true;
5878 break;
5879 case 1:/* for broadcast/multicast */
5880 supportRateNum = rtw_get_rateset_len23a(pmlmeinfo->FW_sta_info[mac_id].SupportedRates);
5881 mask = update_basic_rate23a(cur_network->SupportedRates, supportRateNum);
5882 break;
5883 default: /* for each sta in IBSS */
5884 supportRateNum = rtw_get_rateset_len23a(pmlmeinfo->FW_sta_info[mac_id].SupportedRates);
5885 mask = update_supported_rate23a(cur_network->SupportedRates, supportRateNum);
5886 break;
5887 }
5888 mask |= ((raid<<28)&0xf0000000);
5889 mask &= 0xffffffff;
5890 mask &= ~filter;
5891 init_rate = get_highest_rate_idx23a(mask)&0x3f;
5892
5893 if (pHalData->fw_ractrl) {
5894 u8 arg = 0;
5895
5896 arg = mac_id&0x1f;/* MACID */
5897 arg |= BIT(7);
5898 if (true == shortGIrate)
5899 arg |= BIT(5);
5900
5901 RTPRINT(FBT, BT_TRACE,
5902 ("[BTCoex], Update FW RAID entry, MASK = 0x%08x, arg = 0x%02x\n",
5903 mask, arg));
5904
5905 rtl8723a_set_raid_cmd(padapter, mask, arg);
5906 } else {
5907 if (shortGIrate)
5908 init_rate |= BIT(6);
5909
5910 rtw_write8(padapter, (REG_INIDATA_RATE_SEL+mac_id), init_rate);
5911 }
5912
5913 psta->init_rate = init_rate;
5914 pdmpriv->INIDATA_RATE[mac_id] = init_rate;
5915}
5916
5917static void btdm_1AntUpdateHalRAMaskForSCO(struct rtw_adapter *padapter, u8 forceUpdate)
5918{
5919 struct btdm_8723a_1ant *pBtdm8723;
5920 struct sta_priv *pstapriv;
5921 struct wlan_bssid_ex *cur_network;
5922 struct sta_info *psta;
5923 u32 macid;
5924 u32 filter = 0;
5925
5926 pBtdm8723 = &GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant;
5927
5928 if ((pBtdm8723->bRAChanged == true) && (forceUpdate == false))
5929 return;
5930
5931 pstapriv = &padapter->stapriv;
5932 cur_network = &padapter->mlmeextpriv.mlmext_info.network;
5933 psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
5934 macid = psta->mac_id;
5935
5936 filter |= BIT(_1M_RATE_);
5937 filter |= BIT(_2M_RATE_);
5938 filter |= BIT(_5M_RATE_);
5939 filter |= BIT(_11M_RATE_);
5940 filter |= BIT(_6M_RATE_);
5941 filter |= BIT(_9M_RATE_);
5942
5943 btdm_1AntUpdateHalRAMask(padapter, macid, filter);
5944
5945 pBtdm8723->bRAChanged = true;
5946}
5947
5948static void btdm_1AntRecoverHalRAMask(struct rtw_adapter *padapter)
5949{
5950 struct btdm_8723a_1ant *pBtdm8723;
5951 struct sta_priv *pstapriv;
5952 struct wlan_bssid_ex *cur_network;
5953 struct sta_info *psta;
5954
5955 pBtdm8723 = &GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant;
5956
5957 if (pBtdm8723->bRAChanged == false)
5958 return;
5959
5960 pstapriv = &padapter->stapriv;
5961 cur_network = &padapter->mlmeextpriv.mlmext_info.network;
5962 psta = rtw_get_stainfo23a(pstapriv, cur_network->MacAddress);
5963
5964 Update_RA_Entry23a(padapter, psta);
5965
5966 pBtdm8723->bRAChanged = false;
5967}
5968
5969static void
5970btdm_1AntBTStateChangeHandler(struct rtw_adapter *padapter,
5971 enum bt_state_1ant oldState, enum bt_state_1ant newState)
5972{
5973 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT state change, %s => %s\n", BtStateString[oldState], BtStateString[newState]));
5974
5975 /* BT default ignore wlan active, */
5976 /* WiFi MUST disable this when BT is enable */
5977 if (newState > BT_INFO_STATE_DISABLED)
5978 btdm_SetFwIgnoreWlanAct(padapter, false);
5979
5980 if ((check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE)) &&
5981 (BTDM_IsWifiConnectionExist(padapter))) {
5982 if ((newState == BT_INFO_STATE_SCO_ONLY_BUSY) ||
5983 (newState == BT_INFO_STATE_ACL_SCO_BUSY)) {
5984 btdm_1AntUpdateHalRAMaskForSCO(padapter, false);
5985 } else {
5986 /* Recover original RA setting */
5987 btdm_1AntRecoverHalRAMask(padapter);
5988 }
5989 } else {
5990 GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant.bRAChanged = false;
5991 }
5992
5993 if (oldState == newState)
5994 return;
5995
5996 if (oldState == BT_INFO_STATE_ACL_ONLY_BUSY) {
5997 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
5998 pHalData->bt_coexist.halCoex8723.btdm1Ant.psTdmaMonitorCnt = 0;
5999 pHalData->bt_coexist.halCoex8723.btdm1Ant.psTdmaMonitorCntForSCO = 0;
6000 }
6001
6002 if ((oldState == BT_INFO_STATE_SCO_ONLY_BUSY) ||
6003 (oldState == BT_INFO_STATE_ACL_SCO_BUSY)) {
6004 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6005 pHalData->bt_coexist.halCoex8723.btdm1Ant.psTdmaMonitorCntForSCO = 0;
6006 }
6007
6008 /* Active 2Ant mechanism when BT Connected */
6009 if ((oldState == BT_INFO_STATE_DISABLED) ||
6010 (oldState == BT_INFO_STATE_NO_CONNECTION)) {
6011 if ((newState != BT_INFO_STATE_DISABLED) &&
6012 (newState != BT_INFO_STATE_NO_CONNECTION)) {
6013 BTDM_SetSwRfRxLpfCorner(padapter, BT_RF_RX_LPF_CORNER_SHRINK);
6014 BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
6015 BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
6016 }
6017 } else {
6018 if ((newState == BT_INFO_STATE_DISABLED) ||
6019 (newState == BT_INFO_STATE_NO_CONNECTION)) {
6020 BTDM_SetSwRfRxLpfCorner(padapter, BT_RF_RX_LPF_CORNER_RESUME);
6021 BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
6022 BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF);
6023 }
6024 }
6025}
6026
6027static void btdm_1AntBtCoexistHandler(struct rtw_adapter *padapter)
6028{
6029 struct hal_data_8723a *pHalData;
6030 struct bt_coexist_8723a *pBtCoex8723;
6031 struct btdm_8723a_1ant *pBtdm8723;
6032
6033 pHalData = GET_HAL_DATA(padapter);
6034 pBtCoex8723 = &pHalData->bt_coexist.halCoex8723;
6035 pBtdm8723 = &pBtCoex8723->btdm1Ant;
6036 padapter->pwrctrlpriv.btcoex_rfon = false;
6037 if (BT_IsBtDisabled(padapter)) {
6038 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT is disabled\n"));
6039
6040 if (BTDM_IsWifiConnectionExist(padapter)) {
6041 RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is connected\n"));
6042
6043 if (BTDM_IsWifiBusy(padapter)) {
6044 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Wifi is busy\n"));
6045 btdm_1AntSetPSTDMA(padapter, false, 0, false, 9);
6046 } else {
6047 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Wifi is idle\n"));
6048 _btdm_1AntSetPSTDMA(padapter, true, 2, 1, false, 9);
6049 }
6050 } else {
6051 RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is disconnected\n"));
6052
6053 btdm_1AntSetPSTDMA(padapter, false, 0, false, 9);
6054 }
6055 } else {
6056 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT is enabled\n"));
6057
6058 if (BTDM_IsWifiConnectionExist(padapter)) {
6059 RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is connected\n"));
6060
6061 btdm_1AntWifiParaAdjust(padapter, true);
6062 btdm_1AntCoexProcessForWifiConnect(padapter);
6063 } else {
6064 RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is disconnected\n"));
6065
6066 /* Antenna switch at BT side(0x870 = 0x300, 0x860 = 0x210) after PSTDMA off */
6067 btdm_1AntWifiParaAdjust(padapter, false);
6068 btdm_1AntSetPSTDMA(padapter, false, 0, false, 0);
6069 }
6070 }
6071
6072 btdm_1AntBTStateChangeHandler(padapter, pBtCoex8723->prec2hBtInfo, pBtCoex8723->c2hBtInfo);
6073 pBtCoex8723->prec2hBtInfo = pBtCoex8723->c2hBtInfo;
6074}
6075
6076void BTDM_1AntSignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, u8 *rssi_bt)
6077{
6078 struct hal_data_8723a *pHalData;
6079 struct btdm_8723a_1ant *pBtdm8723;
6080 u8 RSSI_WiFi_Cmpnstn, RSSI_BT_Cmpnstn;
6081
6082 pHalData = GET_HAL_DATA(padapter);
6083 pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;
6084 RSSI_WiFi_Cmpnstn = 0;
6085 RSSI_BT_Cmpnstn = 0;
6086
6087 switch (pBtdm8723->curPsTdma) {
6088 case 1: /* WiFi 52ms */
6089 RSSI_WiFi_Cmpnstn = 11; /* 22*0.48 */
6090 break;
6091 case 2: /* WiFi 36ms */
6092 RSSI_WiFi_Cmpnstn = 14; /* 22*0.64 */
6093 break;
6094 case 9: /* WiFi 20ms */
6095 RSSI_WiFi_Cmpnstn = 18; /* 22*0.80 */
6096 break;
6097 case 11: /* WiFi 10ms */
6098 RSSI_WiFi_Cmpnstn = 20; /* 22*0.90 */
6099 break;
6100 case 4: /* WiFi 21ms */
6101 RSSI_WiFi_Cmpnstn = 17; /* 22*0.79 */
6102 break;
6103 case 16: /* WiFi 24ms */
6104 RSSI_WiFi_Cmpnstn = 18; /* 22*0.76 */
6105 break;
6106 case 18: /* WiFi 37ms */
6107 RSSI_WiFi_Cmpnstn = 14; /* 22*0.64 */
6108 break;
6109 case 23: /* Level-1, Antenna switch to BT at all time */
6110 case 24: /* Level-2, Antenna switch to BT at all time */
6111 case 25: /* Level-3a, Antenna switch to BT at all time */
6112 case 26: /* Level-3b, Antenna switch to BT at all time */
6113 case 27: /* Level-3b, Antenna switch to BT at all time */
6114 case 33: /* BT SCO & WiFi site survey */
6115 RSSI_WiFi_Cmpnstn = 22;
6116 break;
6117 default:
6118 break;
6119 }
6120
6121 if (rssi_wifi && RSSI_WiFi_Cmpnstn) {
6122 RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntSgnlCmpnstn, case %d, WiFiCmpnstn =%d(%d => %d)\n",
6123 pBtdm8723->curPsTdma, RSSI_WiFi_Cmpnstn, *rssi_wifi, *rssi_wifi+RSSI_WiFi_Cmpnstn));
6124 *rssi_wifi += RSSI_WiFi_Cmpnstn;
6125 }
6126
6127 if (rssi_bt && RSSI_BT_Cmpnstn) {
6128 RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntSgnlCmpnstn, case %d, BTCmpnstn =%d(%d => %d)\n",
6129 pBtdm8723->curPsTdma, RSSI_BT_Cmpnstn, *rssi_bt, *rssi_bt+RSSI_BT_Cmpnstn));
6130 *rssi_bt += RSSI_BT_Cmpnstn;
6131 }
6132}
6133
6134static void BTDM_1AntParaInit(struct rtw_adapter *padapter)
6135{
6136 struct hal_data_8723a *pHalData;
6137 struct bt_coexist_8723a *pBtCoex;
6138 struct btdm_8723a_1ant *pBtdm8723;
6139
6140 pHalData = GET_HAL_DATA(padapter);
6141 pBtCoex = &pHalData->bt_coexist.halCoex8723;
6142 pBtdm8723 = &pBtCoex->btdm1Ant;
6143
6144 /* Enable counter statistics */
6145 rtw_write8(padapter, 0x76e, 0x4);
6146 btdm_1AntPtaParaReload(padapter);
6147
6148 pBtdm8723->wifiRssiThresh = 48;
6149
6150 pBtdm8723->bWiFiHalt = false;
6151 pBtdm8723->bRAChanged = false;
6152
6153 if ((pBtCoex->c2hBtInfo != BT_INFO_STATE_DISABLED) &&
6154 (pBtCoex->c2hBtInfo != BT_INFO_STATE_NO_CONNECTION)) {
6155 BTDM_SetSwRfRxLpfCorner(padapter, BT_RF_RX_LPF_CORNER_SHRINK);
6156 BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
6157 BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
6158 }
6159}
6160
6161static void BTDM_1AntForHalt(struct rtw_adapter *padapter)
6162{
6163 RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for halt\n"));
6164
6165 GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant.bWiFiHalt = true;
6166
6167 btdm_1AntWifiParaAdjust(padapter, false);
6168
6169 /* don't use btdm_1AntSetPSTDMA() here */
6170 /* it will call rtw_set_ps_mode23a() and request pwrpriv->lock. */
6171 /* This will lead to deadlock, if this function is called in IPS */
6172 /* Lucas@20130205 */
6173 btdm_1AntPsTdma(padapter, false, 0);
6174
6175 btdm_SetFwIgnoreWlanAct(padapter, true);
6176}
6177
6178static void BTDM_1AntLpsLeave(struct rtw_adapter *padapter)
6179{
6180 RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for LPS Leave\n"));
6181
6182 /* Prevent from entering LPS again */
6183 GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant.bWiFiHalt = true;
6184
6185 btdm_1AntSetPSTDMA(padapter, false, 0, false, 8);
6186/*btdm_1AntPsTdma(padapter, false, 8); */
6187}
6188
6189static void BTDM_1AntWifiAssociateNotify(struct rtw_adapter *padapter, u8 type)
6190{
6191 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6192
6193 RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for associate, type =%d\n", type));
6194
6195 if (type) {
6196 rtl8723a_CheckAntenna_Selection(padapter);
6197 if (BT_IsBtDisabled(padapter)) {
6198 btdm_1AntSetPSTDMA(padapter, false, 0, false, 9);
6199 } else {
6200 struct bt_coexist_8723a *pBtCoex;
6201 u8 BtState;
6202
6203 pBtCoex = &pHalData->bt_coexist.halCoex8723;
6204 BtState = pBtCoex->c2hBtInfo;
6205
6206 btdm_1AntTSFSwitch(padapter, true);
6207
6208 if ((BtState == BT_INFO_STATE_NO_CONNECTION) ||
6209 (BtState == BT_INFO_STATE_CONNECT_IDLE)) {
6210 btdm_1AntSetPSTDMA(padapter, false, 0, true, 28);
6211 } else if ((BtState == BT_INFO_STATE_SCO_ONLY_BUSY) ||
6212 (BtState == BT_INFO_STATE_ACL_SCO_BUSY)) {
6213 btdm_1AntSetPSTDMA(padapter, false, 0, false, 8);
6214 rtw_write32(padapter, 0x6c0, 0x5a5a5a5a);
6215 rtw_write32(padapter, 0x6c4, 0x5a5a5a5a);
6216 } else if ((BtState == BT_INFO_STATE_ACL_ONLY_BUSY) ||
6217 (BtState == BT_INFO_STATE_ACL_INQ_OR_PAG)) {
6218 if (pBtCoex->c2hBtProfile == BT_INFO_HID)
6219 btdm_1AntSetPSTDMA(padapter, false, 0, true, 35);
6220 else
6221 btdm_1AntSetPSTDMA(padapter, false, 0, true, 29);
6222 }
6223 }
6224 } else {
6225 if (BT_IsBtDisabled(padapter)) {
6226 if (!BTDM_IsWifiConnectionExist(padapter)) {
6227 btdm_1AntPsTdma(padapter, false, 0);
6228 btdm_1AntTSFSwitch(padapter, false);
6229 }
6230 }
6231
6232 btdm_1AntBtCoexistHandler(padapter);
6233 }
6234}
6235
6236static void
6237BTDM_1AntMediaStatusNotify(struct rtw_adapter *padapter,
6238 enum rt_media_status mstatus)
6239{
6240 struct bt_coexist_8723a *pBtCoex;
6241
6242 pBtCoex = &GET_HAL_DATA(padapter)->bt_coexist.halCoex8723;
6243
6244 RTPRINT(FBT, BT_TRACE, ("\n\n[BTCoex]******************************\n"));
6245 RTPRINT(FBT, BT_TRACE, ("[BTCoex], MediaStatus, WiFi %s !!\n",
6246 mstatus == RT_MEDIA_CONNECT?"CONNECT":"DISCONNECT"));
6247 RTPRINT(FBT, BT_TRACE, ("[BTCoex]******************************\n"));
6248
6249 if (RT_MEDIA_CONNECT == mstatus) {
6250 if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE)) {
6251 if ((pBtCoex->c2hBtInfo == BT_INFO_STATE_SCO_ONLY_BUSY) ||
6252 (pBtCoex->c2hBtInfo == BT_INFO_STATE_ACL_SCO_BUSY))
6253 btdm_1AntUpdateHalRAMaskForSCO(padapter, true);
6254 }
6255
6256 padapter->pwrctrlpriv.DelayLPSLastTimeStamp = jiffies;
6257 BTDM_1AntForDhcp(padapter);
6258 } else {
6259 /* DBG_8723A("%s rtl8723a_DeinitAntenna_Selection\n", __func__); */
6260 rtl8723a_DeinitAntenna_Selection(padapter);
6261 btdm_1AntBtCoexistHandler(padapter);
6262 pBtCoex->btdm1Ant.bRAChanged = false;
6263 }
6264}
6265
6266void BTDM_1AntForDhcp(struct rtw_adapter *padapter)
6267{
6268 struct hal_data_8723a *pHalData;
6269 u8 BtState;
6270 struct bt_coexist_8723a *pBtCoex;
6271 struct btdm_8723a_1ant *pBtdm8723;
6272
6273 pHalData = GET_HAL_DATA(padapter);
6274 pBtCoex = &pHalData->bt_coexist.halCoex8723;
6275 BtState = pBtCoex->c2hBtInfo;
6276 pBtdm8723 = &pBtCoex->btdm1Ant;
6277
6278 RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for DHCP\n"));
6279 RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for DHCP, WiFi is %s\n", BTDM_IsWifiBusy(padapter)?"Busy":"IDLE"));
6280 RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for DHCP, %s\n", BtStateString[BtState]));
6281
6282 BTDM_1AntWifiAssociateNotify(padapter, true);
6283}
6284
6285static void BTDM_1AntWifiScanNotify(struct rtw_adapter *padapter, u8 scanType)
6286{
6287 struct hal_data_8723a *pHalData;
6288 u8 BtState;
6289 struct bt_coexist_8723a *pBtCoex;
6290 struct btdm_8723a_1ant *pBtdm8723;
6291
6292 pHalData = GET_HAL_DATA(padapter);
6293 BtState = pHalData->bt_coexist.halCoex8723.c2hBtInfo;
6294 pBtCoex = &pHalData->bt_coexist.halCoex8723;
6295 pBtdm8723 = &pBtCoex->btdm1Ant;
6296
6297 RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for wifi scan =%d!!\n", scanType));
6298 RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for wifi scan, WiFi is %s\n", BTDM_IsWifiBusy(padapter)?"Busy":"IDLE"));
6299 RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for wifi scan, %s\n", BtStateString[BtState]));
6300
6301 if (scanType) {
6302 rtl8723a_CheckAntenna_Selection(padapter);
6303 if (BT_IsBtDisabled(padapter)) {
6304 btdm_1AntSetPSTDMA(padapter, false, 0, false, 9);
6305 } else if (BTDM_IsWifiConnectionExist(padapter) == false) {
6306 BTDM_1AntWifiAssociateNotify(padapter, true);
6307 } else {
6308 if ((BtState == BT_INFO_STATE_SCO_ONLY_BUSY) ||
6309 (BtState == BT_INFO_STATE_ACL_SCO_BUSY)) {
6310 if (pBtCoex->bC2hBtInquiryPage) {
6311 btdm_1AntSetPSTDMA(padapter, false, 0, true, 32);
6312 } else {
6313 padapter->pwrctrlpriv.btcoex_rfon = true;
6314 btdm_1AntSetPSTDMA(padapter, true, 0, true, 33);
6315 }
6316 } else if (true == pBtCoex->bC2hBtInquiryPage) {
6317 padapter->pwrctrlpriv.btcoex_rfon = true;
6318 btdm_1AntSetPSTDMA(padapter, true, 0, true, 30);
6319 } else if (BtState == BT_INFO_STATE_ACL_ONLY_BUSY) {
6320 padapter->pwrctrlpriv.btcoex_rfon = true;
6321 if (pBtCoex->c2hBtProfile == BT_INFO_HID)
6322 btdm_1AntSetPSTDMA(padapter, true, 0, true, 34);
6323 else
6324 btdm_1AntSetPSTDMA(padapter, true, 0, true, 4);
6325 } else {
6326 padapter->pwrctrlpriv.btcoex_rfon = true;
6327 btdm_1AntSetPSTDMA(padapter, true, 0, true, 5);
6328 }
6329 }
6330
6331 btdm_NotifyFwScan(padapter, 1);
6332 } else {
6333 /* WiFi_Finish_Scan */
6334 btdm_NotifyFwScan(padapter, 0);
6335 btdm_1AntBtCoexistHandler(padapter);
6336 }
6337}
6338
6339static void BTDM_1AntFwC2hBtInfo8723A(struct rtw_adapter *padapter)
6340{
6341 struct hal_data_8723a *pHalData;
6342 struct bt_30info *pBTInfo;
6343 struct bt_mgnt *pBtMgnt;
6344 struct bt_coexist_8723a *pBtCoex;
6345 u8 u1tmp, btState;
6346
6347 pHalData = GET_HAL_DATA(padapter);
6348 pBTInfo = GET_BT_INFO(padapter);
6349 pBtMgnt = &pBTInfo->BtMgnt;
6350 pBtCoex = &pHalData->bt_coexist.halCoex8723;
6351
6352 u1tmp = pBtCoex->c2hBtInfoOriginal;
6353 /* sco BUSY bit is not used on voice over PCM platform */
6354 btState = u1tmp & 0xF;
6355 pBtCoex->c2hBtProfile = u1tmp & 0xE0;
6356
6357 /* default set bt to idle state. */
6358 pBtMgnt->ExtConfig.bBTBusy = false;
6359 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE;
6360
6361 /* check BIT2 first ==> check if bt is under inquiry or page scan */
6362 if (btState & BIT(2))
6363 pBtCoex->bC2hBtInquiryPage = true;
6364 else
6365 pBtCoex->bC2hBtInquiryPage = false;
6366 btState &= ~BIT(2);
6367
6368 if (!(btState & BIT(0))) {
6369 pBtCoex->c2hBtInfo = BT_INFO_STATE_NO_CONNECTION;
6370 } else {
6371 if (btState == 0x1) {
6372 pBtCoex->c2hBtInfo = BT_INFO_STATE_CONNECT_IDLE;
6373 } else if (btState == 0x9) {
6374 if (pBtCoex->bC2hBtInquiryPage == true)
6375 pBtCoex->c2hBtInfo = BT_INFO_STATE_ACL_INQ_OR_PAG;
6376 else
6377 pBtCoex->c2hBtInfo = BT_INFO_STATE_ACL_ONLY_BUSY;
6378 pBtMgnt->ExtConfig.bBTBusy = true;
6379 } else if (btState == 0x3) {
6380 pBtCoex->c2hBtInfo = BT_INFO_STATE_SCO_ONLY_BUSY;
6381 pBtMgnt->ExtConfig.bBTBusy = true;
6382 } else if (btState == 0xb) {
6383 pBtCoex->c2hBtInfo = BT_INFO_STATE_ACL_SCO_BUSY;
6384 pBtMgnt->ExtConfig.bBTBusy = true;
6385 } else {
6386 pBtCoex->c2hBtInfo = BT_INFO_STATE_MAX;
6387 }
6388 if (pBtMgnt->ExtConfig.bBTBusy)
6389 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_IDLE;
6390 }
6391
6392 if ((BT_INFO_STATE_NO_CONNECTION == pBtCoex->c2hBtInfo) ||
6393 (BT_INFO_STATE_CONNECT_IDLE == pBtCoex->c2hBtInfo)) {
6394 if (pBtCoex->bC2hBtInquiryPage)
6395 pBtCoex->c2hBtInfo = BT_INFO_STATE_INQ_OR_PAG;
6396 }
6397
6398 RTPRINT(FBT, BT_TRACE, ("[BTC2H], %s(%d)\n",
6399 BtStateString[pBtCoex->c2hBtInfo], pBtCoex->c2hBtInfo));
6400
6401 if (pBtCoex->c2hBtProfile != BT_INFO_HID)
6402 pBtCoex->c2hBtProfile &= ~BT_INFO_HID;
6403}
6404
6405void BTDM_1AntBtCoexist8723A(struct rtw_adapter *padapter)
6406{
6407 struct mlme_priv *pmlmepriv;
6408 struct hal_data_8723a *pHalData;
6409 unsigned long delta_time;
6410
6411 pmlmepriv = &padapter->mlmepriv;
6412 pHalData = GET_HAL_DATA(padapter);
6413
6414 if (check_fwstate(pmlmepriv, WIFI_SITE_MONITOR)) {
6415 /* already done in BTDM_1AntForScan() */
6416 RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is under scan progress!!\n"));
6417 return;
6418 }
6419
6420 if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING)) {
6421 RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is under link progress!!\n"));
6422 return;
6423 }
6424
6425 /* under DHCP(Special packet) */
6426 delta_time = jiffies - padapter->pwrctrlpriv.DelayLPSLastTimeStamp;
6427 delta_time = jiffies_to_msecs(delta_time);
6428 if (delta_time < 500) {
6429 RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is under DHCP "
6430 "progress(%li ms)!!\n", delta_time));
6431 return;
6432 }
6433
6434 BTDM_CheckWiFiState(padapter);
6435
6436 btdm_1AntBtCoexistHandler(padapter);
6437}
6438
6439/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.c ===== */
6440#endif
6441
6442#ifdef __HALBTC87232ANT_C__ /* HAL/BTCoexist/HalBtc87232Ant.c */
6443/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.c ===== */
6444
6445/* local function start with btdm_ */
6446static u8 btdm_ActionAlgorithm(struct rtw_adapter *padapter)
6447{
6448 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
6449 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
6450 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6451 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
6452 u8 bScoExist = false, bBtLinkExist = false, bBtHsModeExist = false;
6453 u8 algorithm = BT_2ANT_COEX_ALGO_UNDEFINED;
6454
6455 if (pBtMgnt->ExtConfig.NumberOfHandle)
6456 bBtLinkExist = true;
6457 if (pBtMgnt->ExtConfig.NumberOfSCO)
6458 bScoExist = true;
6459 if (BT_HsConnectionEstablished(padapter))
6460 bBtHsModeExist = true;
6461
6462 /* here we get BT status first */
6463 /* 1) initialize */
6464 pBtdm8723->btStatus = BT_2ANT_BT_STATUS_IDLE;
6465
6466 if ((bScoExist) || (bBtHsModeExist) ||
6467 (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID))) {
6468 RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO or HID or HS exists, set BT non-idle !!!\n"));
6469 pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE;
6470 } else {
6471 /* A2dp profile */
6472 if ((pBtMgnt->ExtConfig.NumberOfHandle == 1) &&
6473 (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP))) {
6474 if (BTDM_BtTxRxCounterL(padapter) < 100) {
6475 RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP, low priority tx+rx < 100, set BT connected-idle!!!\n"));
6476 pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE;
6477 } else {
6478 RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP, low priority tx+rx >= 100, set BT non-idle!!!\n"));
6479 pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE;
6480 }
6481 }
6482 /* Pan profile */
6483 if ((pBtMgnt->ExtConfig.NumberOfHandle == 1) &&
6484 (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN))) {
6485 if (BTDM_BtTxRxCounterL(padapter) < 600) {
6486 RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN, low priority tx+rx < 600, set BT connected-idle!!!\n"));
6487 pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE;
6488 } else {
6489 if (pHalData->bt_coexist.halCoex8723.lowPriorityTx) {
6490 if ((pHalData->bt_coexist.halCoex8723.lowPriorityRx /
6491 pHalData->bt_coexist.halCoex8723.lowPriorityTx) > 9) {
6492 RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN, low priority rx/tx > 9, set BT connected-idle!!!\n"));
6493 pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE;
6494 }
6495 }
6496 }
6497 if (BT_2ANT_BT_STATUS_CONNECTED_IDLE != pBtdm8723->btStatus) {
6498 RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN, set BT non-idle!!!\n"));
6499 pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE;
6500 }
6501 }
6502 /* Pan+A2dp profile */
6503 if ((pBtMgnt->ExtConfig.NumberOfHandle == 2) &&
6504 (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) &&
6505 (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN))) {
6506 if (BTDM_BtTxRxCounterL(padapter) < 600) {
6507 RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN+A2DP, low priority tx+rx < 600, set BT connected-idle!!!\n"));
6508 pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE;
6509 } else {
6510 if (pHalData->bt_coexist.halCoex8723.lowPriorityTx) {
6511 if ((pHalData->bt_coexist.halCoex8723.lowPriorityRx /
6512 pHalData->bt_coexist.halCoex8723.lowPriorityTx) > 9) {
6513 RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN+A2DP, low priority rx/tx > 9, set BT connected-idle!!!\n"));
6514 pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE;
6515 }
6516 }
6517 }
6518 if (BT_2ANT_BT_STATUS_CONNECTED_IDLE != pBtdm8723->btStatus) {
6519 RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN+A2DP, set BT non-idle!!!\n"));
6520 pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE;
6521 }
6522 }
6523 }
6524 if (BT_2ANT_BT_STATUS_IDLE != pBtdm8723->btStatus)
6525 pBtMgnt->ExtConfig.bBTBusy = true;
6526 else
6527 pBtMgnt->ExtConfig.bBTBusy = false;
6528
6529 if (!bBtLinkExist) {
6530 RTPRINT(FBT, BT_TRACE, ("[BTCoex], No profile exists!!!\n"));
6531 return algorithm;
6532 }
6533
6534 if (pBtMgnt->ExtConfig.NumberOfHandle == 1) {
6535 if (bScoExist) {
6536 RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO only\n"));
6537 algorithm = BT_2ANT_COEX_ALGO_SCO;
6538 } else {
6539 if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID)) {
6540 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID only\n"));
6541 algorithm = BT_2ANT_COEX_ALGO_HID;
6542 } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) {
6543 RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP only\n"));
6544 algorithm = BT_2ANT_COEX_ALGO_A2DP;
6545 } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) {
6546 if (bBtHsModeExist) {
6547 RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN(HS) only\n"));
6548 algorithm = BT_2ANT_COEX_ALGO_PANHS;
6549 } else {
6550 RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN(EDR) only\n"));
6551 algorithm = BT_2ANT_COEX_ALGO_PANEDR;
6552 }
6553 } else {
6554 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle =%d \n",
6555 pBtMgnt->ExtConfig.NumberOfHandle));
6556 }
6557 }
6558 } else if (pBtMgnt->ExtConfig.NumberOfHandle == 2) {
6559 if (bScoExist) {
6560 if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID)) {
6561 RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID\n"));
6562 algorithm = BT_2ANT_COEX_ALGO_HID;
6563 } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) {
6564 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP\n"));
6565 } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) {
6566 if (bBtHsModeExist) {
6567 RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(HS)\n"));
6568 algorithm = BT_2ANT_COEX_ALGO_SCO;
6569 } else {
6570 RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(EDR)\n"));
6571 algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID;
6572 }
6573 } else {
6574 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO exists but why NO matched ACL profile for NumberOfHandle =%d\n",
6575 pBtMgnt->ExtConfig.NumberOfHandle));
6576 }
6577 } else {
6578 if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) &&
6579 BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) {
6580 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP\n"));
6581 algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
6582 } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) &&
6583 BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) {
6584 if (bBtHsModeExist) {
6585 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(HS)\n"));
6586 algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
6587 } else {
6588 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(EDR)\n"));
6589 algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID;
6590 }
6591 } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) &&
6592 BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) {
6593 if (bBtHsModeExist) {
6594 RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(HS)\n"));
6595 algorithm = BT_2ANT_COEX_ALGO_A2DP;
6596 } else {
6597 RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(EDR)\n"));
6598 algorithm = BT_2ANT_COEX_ALGO_PANEDR_A2DP;
6599 }
6600 } else {
6601 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle =%d\n",
6602 pBtMgnt->ExtConfig.NumberOfHandle));
6603 }
6604 }
6605 } else if (pBtMgnt->ExtConfig.NumberOfHandle == 3) {
6606 if (bScoExist) {
6607 if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) &&
6608 BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) {
6609 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + HID + A2DP\n"));
6610 } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) &&
6611 BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) {
6612 if (bBtHsModeExist) {
6613 RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID + PAN(HS)\n"));
6614 algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
6615 } else {
6616 RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID + PAN(EDR)\n"));
6617 algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID;
6618 }
6619 } else if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) &&
6620 BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) {
6621 if (bBtHsModeExist) {
6622 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP + PAN(HS)\n"));
6623 algorithm = BT_2ANT_COEX_ALGO_SCO;
6624 } else {
6625 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP + PAN(EDR)\n"));
6626 }
6627 } else {
6628 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO exists but why NO matched profile for NumberOfHandle =%d\n",
6629 pBtMgnt->ExtConfig.NumberOfHandle));
6630 }
6631 } else {
6632 if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) &&
6633 BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) &&
6634 BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) {
6635 if (bBtHsModeExist) {
6636 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(HS)\n"));
6637 algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANHS;
6638 } else {
6639 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(EDR)\n"));
6640 algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR;
6641 }
6642 } else {
6643 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle =%d\n",
6644 pBtMgnt->ExtConfig.NumberOfHandle));
6645 }
6646 }
6647 } else if (pBtMgnt->ExtConfig.NumberOfHandle >= 3) {
6648 if (bScoExist) {
6649 if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) &&
6650 BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) &&
6651 BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) {
6652 if (bBtHsModeExist)
6653 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + HID + A2DP + PAN(HS)\n"));
6654 else
6655 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + HID + A2DP + PAN(EDR)\n"));
6656 } else {
6657 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO exists but why NO matched profile for NumberOfHandle =%d\n",
6658 pBtMgnt->ExtConfig.NumberOfHandle));
6659 }
6660 } else {
6661 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle =%d\n",
6662 pBtMgnt->ExtConfig.NumberOfHandle));
6663 }
6664 }
6665 return algorithm;
6666}
6667
6668static u8 btdm_NeedToDecBtPwr(struct rtw_adapter *padapter)
6669{
6670 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6671 u8 bRet = false;
6672
6673 if (BT_Operation(padapter)) {
6674 if (pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB > 47) {
6675 RTPRINT(FBT, BT_TRACE, ("Need to decrease bt power for HS mode!!\n"));
6676 bRet = true;
6677 } else {
6678 RTPRINT(FBT, BT_TRACE, ("NO Need to decrease bt power for HS mode!!\n"));
6679 }
6680 } else {
6681 if (BTDM_IsWifiConnectionExist(padapter)) {
6682 RTPRINT(FBT, BT_TRACE, ("Need to decrease bt power for Wifi is connected!!\n"));
6683 bRet = true;
6684 }
6685 }
6686 return bRet;
6687}
6688
6689static void
6690btdm_SetCoexTable(struct rtw_adapter *padapter, u32 val0x6c0,
6691 u32 val0x6c8, u8 val0x6cc)
6692{
6693 RTPRINT(FBT, BT_TRACE, ("set coex table, set 0x6c0 = 0x%x\n", val0x6c0));
6694 rtw_write32(padapter, 0x6c0, val0x6c0);
6695
6696 RTPRINT(FBT, BT_TRACE, ("set coex table, set 0x6c8 = 0x%x\n", val0x6c8));
6697 rtw_write32(padapter, 0x6c8, val0x6c8);
6698
6699 RTPRINT(FBT, BT_TRACE, ("set coex table, set 0x6cc = 0x%x\n", val0x6cc));
6700 rtw_write8(padapter, 0x6cc, val0x6cc);
6701}
6702
6703static void
6704btdm_SetSwFullTimeDacSwing(struct rtw_adapter *padapter, u8 bSwDacSwingOn,
6705 u32 swDacSwingLvl)
6706{
6707 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6708
6709 if (bSwDacSwingOn) {
6710 RTPRINT(FBT, BT_TRACE, ("[BTCoex], SwDacSwing = 0x%x\n", swDacSwingLvl));
6711 PHY_SetBBReg(padapter, 0x880, 0xff000000, swDacSwingLvl);
6712 pHalData->bt_coexist.bSWCoexistAllOff = false;
6713 } else {
6714 RTPRINT(FBT, BT_TRACE, ("[BTCoex], SwDacSwing Off!\n"));
6715 PHY_SetBBReg(padapter, 0x880, 0xff000000, 0xc0);
6716 }
6717}
6718
6719static void
6720btdm_SetFwDacSwingLevel(struct rtw_adapter *padapter, u8 dacSwingLvl)
6721{
6722 u8 H2C_Parameter[1] = {0};
6723
6724 H2C_Parameter[0] = dacSwingLvl;
6725
6726 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Set Dac Swing Level = 0x%x\n", dacSwingLvl));
6727 RTPRINT(FBT, BT_TRACE, ("[BTCoex], write 0x29 = 0x%x\n", H2C_Parameter[0]));
6728
6729 FillH2CCmd(padapter, 0x29, 1, H2C_Parameter);
6730}
6731
6732static void btdm_2AntDecBtPwr(struct rtw_adapter *padapter, u8 bDecBtPwr)
6733{
6734 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6735 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
6736
6737 RTPRINT(FBT, BT_TRACE,
6738 ("[BTCoex], Dec BT power = %s\n",
6739 ((bDecBtPwr) ? "ON" : "OFF")));
6740 pBtdm8723->bCurDecBtPwr = bDecBtPwr;
6741
6742 if (pBtdm8723->bPreDecBtPwr == pBtdm8723->bCurDecBtPwr)
6743 return;
6744
6745 BTDM_SetFwDecBtPwr(padapter, pBtdm8723->bCurDecBtPwr);
6746
6747 pBtdm8723->bPreDecBtPwr = pBtdm8723->bCurDecBtPwr;
6748}
6749
6750static void
6751btdm_2AntFwDacSwingLvl(struct rtw_adapter *padapter, u8 fwDacSwingLvl)
6752{
6753 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6754 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
6755
6756 RTPRINT(FBT, BT_TRACE, ("[BTCoex], set FW Dac Swing level = %d\n", fwDacSwingLvl));
6757 pBtdm8723->curFwDacSwingLvl = fwDacSwingLvl;
6758
6759 /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], preFwDacSwingLvl =%d, curFwDacSwingLvl =%d\n", */
6760 /*pBtdm8723->preFwDacSwingLvl, pBtdm8723->curFwDacSwingLvl)); */
6761
6762 if (pBtdm8723->preFwDacSwingLvl == pBtdm8723->curFwDacSwingLvl)
6763 return;
6764
6765 btdm_SetFwDacSwingLevel(padapter, pBtdm8723->curFwDacSwingLvl);
6766
6767 pBtdm8723->preFwDacSwingLvl = pBtdm8723->curFwDacSwingLvl;
6768}
6769
6770static void
6771btdm_2AntRfShrink(struct rtw_adapter *padapter, u8 bRxRfShrinkOn)
6772{
6773 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6774 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
6775
6776 RTPRINT(FBT, BT_TRACE,
6777 ("[BTCoex], turn Rx RF Shrink = %s\n",
6778 ((bRxRfShrinkOn) ? "ON" : "OFF")));
6779 pBtdm8723->bCurRfRxLpfShrink = bRxRfShrinkOn;
6780
6781 /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreRfRxLpfShrink =%d, bCurRfRxLpfShrink =%d\n", */
6782 /*pBtdm8723->bPreRfRxLpfShrink, pBtdm8723->bCurRfRxLpfShrink)); */
6783
6784 if (pBtdm8723->bPreRfRxLpfShrink == pBtdm8723->bCurRfRxLpfShrink)
6785 return;
6786
6787 BTDM_SetSwRfRxLpfCorner(padapter, (u8)pBtdm8723->bCurRfRxLpfShrink);
6788
6789 pBtdm8723->bPreRfRxLpfShrink = pBtdm8723->bCurRfRxLpfShrink;
6790}
6791
6792static void
6793btdm_2AntLowPenaltyRa(struct rtw_adapter *padapter, u8 bLowPenaltyRa)
6794{
6795 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6796 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
6797
6798 RTPRINT(FBT, BT_TRACE,
6799 ("[BTCoex], turn LowPenaltyRA = %s\n",
6800 ((bLowPenaltyRa) ? "ON" : "OFF")));
6801 pBtdm8723->bCurLowPenaltyRa = bLowPenaltyRa;
6802
6803 /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreLowPenaltyRa =%d, bCurLowPenaltyRa =%d\n", */
6804 /*pBtdm8723->bPreLowPenaltyRa, pBtdm8723->bCurLowPenaltyRa)); */
6805
6806 if (pBtdm8723->bPreLowPenaltyRa == pBtdm8723->bCurLowPenaltyRa)
6807 return;
6808
6809 BTDM_SetSwPenaltyTxRateAdaptive(padapter, (u8)pBtdm8723->bCurLowPenaltyRa);
6810
6811 pBtdm8723->bPreLowPenaltyRa = pBtdm8723->bCurLowPenaltyRa;
6812}
6813
6814static void
6815btdm_2AntDacSwing(struct rtw_adapter *padapter,
6816 u8 bDacSwingOn, u32 dacSwingLvl)
6817{
6818 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6819 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
6820
6821 RTPRINT(FBT, BT_TRACE,
6822 ("[BTCoex], turn DacSwing =%s, dacSwingLvl = 0x%x\n",
6823 (bDacSwingOn ? "ON" : "OFF"), dacSwingLvl));
6824 pBtdm8723->bCurDacSwingOn = bDacSwingOn;
6825 pBtdm8723->curDacSwingLvl = dacSwingLvl;
6826
6827 if ((pBtdm8723->bPreDacSwingOn == pBtdm8723->bCurDacSwingOn) &&
6828 (pBtdm8723->preDacSwingLvl == pBtdm8723->curDacSwingLvl))
6829 return;
6830
6831 mdelay(30);
6832 btdm_SetSwFullTimeDacSwing(padapter, bDacSwingOn, dacSwingLvl);
6833
6834 pBtdm8723->bPreDacSwingOn = pBtdm8723->bCurDacSwingOn;
6835 pBtdm8723->preDacSwingLvl = pBtdm8723->curDacSwingLvl;
6836}
6837
6838static void btdm_2AntAdcBackOff(struct rtw_adapter *padapter, u8 bAdcBackOff)
6839{
6840 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6841 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
6842
6843 RTPRINT(FBT, BT_TRACE,
6844 ("[BTCoex], turn AdcBackOff = %s\n",
6845 ((bAdcBackOff) ? "ON" : "OFF")));
6846 pBtdm8723->bCurAdcBackOff = bAdcBackOff;
6847
6848 if (pBtdm8723->bPreAdcBackOff == pBtdm8723->bCurAdcBackOff)
6849 return;
6850
6851 BTDM_BBBackOffLevel(padapter, (u8)pBtdm8723->bCurAdcBackOff);
6852
6853 pBtdm8723->bPreAdcBackOff = pBtdm8723->bCurAdcBackOff;
6854}
6855
6856static void btdm_2AntAgcTable(struct rtw_adapter *padapter, u8 bAgcTableEn)
6857{
6858 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6859 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
6860
6861 RTPRINT(FBT, BT_TRACE,
6862 ("[BTCoex], %s Agc Table\n", ((bAgcTableEn) ? "Enable" : "Disable")));
6863 pBtdm8723->bCurAgcTableEn = bAgcTableEn;
6864
6865 /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreAgcTableEn =%d, bCurAgcTableEn =%d\n", */
6866 /*pBtdm8723->bPreAgcTableEn, pBtdm8723->bCurAgcTableEn)); */
6867
6868 if (pBtdm8723->bPreAgcTableEn == pBtdm8723->bCurAgcTableEn)
6869 return;
6870
6871 BTDM_AGCTable(padapter, (u8)bAgcTableEn);
6872
6873 pBtdm8723->bPreAgcTableEn = pBtdm8723->bCurAgcTableEn;
6874}
6875
6876static void
6877btdm_2AntCoexTable(struct rtw_adapter *padapter,
6878 u32 val0x6c0, u32 val0x6c8, u8 val0x6cc)
6879{
6880 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6881 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
6882
6883 RTPRINT(FBT, BT_TRACE, ("[BTCoex], write Coex Table 0x6c0 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n",
6884 val0x6c0, val0x6c8, val0x6cc));
6885 pBtdm8723->curVal0x6c0 = val0x6c0;
6886 pBtdm8723->curVal0x6c8 = val0x6c8;
6887 pBtdm8723->curVal0x6cc = val0x6cc;
6888
6889 /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], preVal0x6c0 = 0x%x, preVal0x6c8 = 0x%x, preVal0x6cc = 0x%x !!\n", */
6890 /*pBtdm8723->preVal0x6c0, pBtdm8723->preVal0x6c8, pBtdm8723->preVal0x6cc)); */
6891 /* RTPRINT(FBT, BT_TRACE, ("[BTCoex], curVal0x6c0 = 0x%x, curVal0x6c8 = 0x%x, curVal0x6cc = 0x%x !!\n", */
6892 /*pBtdm8723->curVal0x6c0, pBtdm8723->curVal0x6c8, pBtdm8723->curVal0x6cc)); */
6893
6894 if ((pBtdm8723->preVal0x6c0 == pBtdm8723->curVal0x6c0) &&
6895 (pBtdm8723->preVal0x6c8 == pBtdm8723->curVal0x6c8) &&
6896 (pBtdm8723->preVal0x6cc == pBtdm8723->curVal0x6cc))
6897 return;
6898
6899 btdm_SetCoexTable(padapter, val0x6c0, val0x6c8, val0x6cc);
6900
6901 pBtdm8723->preVal0x6c0 = pBtdm8723->curVal0x6c0;
6902 pBtdm8723->preVal0x6c8 = pBtdm8723->curVal0x6c8;
6903 pBtdm8723->preVal0x6cc = pBtdm8723->curVal0x6cc;
6904}
6905
6906static void btdm_2AntIgnoreWlanAct(struct rtw_adapter *padapter, u8 bEnable)
6907{
6908 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6909 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
6910
6911 RTPRINT(FBT, BT_TRACE,
6912 ("[BTCoex], turn Ignore WlanAct %s\n", (bEnable ? "ON" : "OFF")));
6913 pBtdm8723->bCurIgnoreWlanAct = bEnable;
6914
6915
6916 if (pBtdm8723->bPreIgnoreWlanAct == pBtdm8723->bCurIgnoreWlanAct)
6917 return;
6918
6919 btdm_SetFwIgnoreWlanAct(padapter, bEnable);
6920 pBtdm8723->bPreIgnoreWlanAct = pBtdm8723->bCurIgnoreWlanAct;
6921}
6922
6923static void
6924btdm_2AntSetFw3a(struct rtw_adapter *padapter, u8 byte1, u8 byte2,
6925 u8 byte3, u8 byte4, u8 byte5)
6926{
6927 u8 H2C_Parameter[5] = {0};
6928
6929 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6930
6931 /* byte1[1:0] != 0 means enable pstdma */
6932 /* for 2Ant bt coexist, if byte1 != 0 means enable pstdma */
6933 if (byte1)
6934 pHalData->bt_coexist.bFWCoexistAllOff = false;
6935 H2C_Parameter[0] = byte1;
6936 H2C_Parameter[1] = byte2;
6937 H2C_Parameter[2] = byte3;
6938 H2C_Parameter[3] = byte4;
6939 H2C_Parameter[4] = byte5;
6940
6941 pHalData->bt_coexist.fw3aVal[0] = byte1;
6942 pHalData->bt_coexist.fw3aVal[1] = byte2;
6943 pHalData->bt_coexist.fw3aVal[2] = byte3;
6944 pHalData->bt_coexist.fw3aVal[3] = byte4;
6945 pHalData->bt_coexist.fw3aVal[4] = byte5;
6946
6947 RTPRINT(FBT, BT_TRACE, ("[BTCoex], FW write 0x3a(5bytes) = 0x%x%08x\n",
6948 H2C_Parameter[0],
6949 H2C_Parameter[1]<<24|H2C_Parameter[2]<<16|H2C_Parameter[3]<<8|H2C_Parameter[4]));
6950
6951 FillH2CCmd(padapter, 0x3a, 5, H2C_Parameter);
6952 }
6953
6954static void btdm_2AntPsTdma(struct rtw_adapter *padapter, u8 bTurnOn, u8 type)
6955{
6956 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
6957 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
6958 u32 btTxRxCnt = 0;
6959 u8 bTurnOnByCnt = false;
6960 u8 psTdmaTypeByCnt = 0;
6961
6962 btTxRxCnt = BTDM_BtTxRxCounterH(padapter)+BTDM_BtTxRxCounterL(padapter);
6963 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT TxRx Counters = %d\n", btTxRxCnt));
6964 if (btTxRxCnt > 3000) {
6965 bTurnOnByCnt = true;
6966 psTdmaTypeByCnt = 8;
6967
6968 RTPRINT(FBT, BT_TRACE,
6969 ("[BTCoex], For BTTxRxCounters, turn %s PS TDMA, type =%d\n",
6970 (bTurnOnByCnt ? "ON" : "OFF"), psTdmaTypeByCnt));
6971 pBtdm8723->bCurPsTdmaOn = bTurnOnByCnt;
6972 pBtdm8723->curPsTdma = psTdmaTypeByCnt;
6973 } else {
6974 RTPRINT(FBT, BT_TRACE,
6975 ("[BTCoex], turn %s PS TDMA, type =%d\n",
6976 (bTurnOn ? "ON" : "OFF"), type));
6977 pBtdm8723->bCurPsTdmaOn = bTurnOn;
6978 pBtdm8723->curPsTdma = type;
6979 }
6980
6981 if ((pBtdm8723->bPrePsTdmaOn == pBtdm8723->bCurPsTdmaOn) &&
6982 (pBtdm8723->prePsTdma == pBtdm8723->curPsTdma))
6983 return;
6984
6985 if (bTurnOn) {
6986 switch (type) {
6987 case 1:
6988 default:
6989 btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0xa1, 0x98);
6990 break;
6991 case 2:
6992 btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0xa1, 0x98);
6993 break;
6994 case 3:
6995 btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0xa1, 0x98);
6996 break;
6997 case 4:
6998 btdm_2AntSetFw3a(padapter, 0xa3, 0x5, 0x5, 0xa1, 0x80);
6999 break;
7000 case 5:
7001 btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0x20, 0x98);
7002 break;
7003 case 6:
7004 btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0x20, 0x98);
7005 break;
7006 case 7:
7007 btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0x20, 0x98);
7008 break;
7009 case 8:
7010 btdm_2AntSetFw3a(padapter, 0xa3, 0x5, 0x5, 0x20, 0x80);
7011 break;
7012 case 9:
7013 btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0xa1, 0x98);
7014 break;
7015 case 10:
7016 btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0xa1, 0x98);
7017 break;
7018 case 11:
7019 btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0xa1, 0x98);
7020 break;
7021 case 12:
7022 btdm_2AntSetFw3a(padapter, 0xe3, 0x5, 0x5, 0xa1, 0x98);
7023 break;
7024 case 13:
7025 btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0x20, 0x98);
7026 break;
7027 case 14:
7028 btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0x20, 0x98);
7029 break;
7030 case 15:
7031 btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0x20, 0x98);
7032 break;
7033 case 16:
7034 btdm_2AntSetFw3a(padapter, 0xe3, 0x5, 0x5, 0x20, 0x98);
7035 break;
7036 case 17:
7037 btdm_2AntSetFw3a(padapter, 0xa3, 0x2f, 0x2f, 0x20, 0x80);
7038 break;
7039 case 18:
7040 btdm_2AntSetFw3a(padapter, 0xe3, 0x5, 0x5, 0xa1, 0x98);
7041 break;
7042 case 19:
7043 btdm_2AntSetFw3a(padapter, 0xe3, 0x25, 0x25, 0xa1, 0x98);
7044 break;
7045 case 20:
7046 btdm_2AntSetFw3a(padapter, 0xe3, 0x25, 0x25, 0x20, 0x98);
7047 break;
7048 }
7049 } else {
7050 /* disable PS tdma */
7051 switch (type) {
7052 case 0:
7053 btdm_2AntSetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0);
7054 break;
7055 case 1:
7056 btdm_2AntSetFw3a(padapter, 0x0, 0x0, 0x0, 0x0, 0x0);
7057 break;
7058 default:
7059 btdm_2AntSetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0);
7060 break;
7061 }
7062 }
7063
7064 /* update pre state */
7065 pBtdm8723->bPrePsTdmaOn = pBtdm8723->bCurPsTdmaOn;
7066 pBtdm8723->prePsTdma = pBtdm8723->curPsTdma;
7067}
7068
7069static void btdm_2AntBtInquiryPage(struct rtw_adapter *padapter)
7070{
7071 btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
7072 btdm_2AntIgnoreWlanAct(padapter, false);
7073 btdm_2AntPsTdma(padapter, true, 8);
7074}
7075
7076static u8 btdm_HoldForBtInqPage(struct rtw_adapter *padapter)
7077{
7078 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
7079 u32 curTime = jiffies;
7080
7081 if (pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage) {
7082 /* bt inquiry or page is started. */
7083 if (pHalData->bt_coexist.halCoex8723.btInqPageStartTime == 0) {
7084 pHalData->bt_coexist.halCoex8723.btInqPageStartTime = curTime;
7085 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Inquiry/page is started at time : 0x%lx \n",
7086 pHalData->bt_coexist.halCoex8723.btInqPageStartTime));
7087 }
7088 }
7089 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Inquiry/page started time : 0x%lx, curTime : 0x%x \n",
7090 pHalData->bt_coexist.halCoex8723.btInqPageStartTime, curTime));
7091
7092 if (pHalData->bt_coexist.halCoex8723.btInqPageStartTime) {
7093 if (((curTime - pHalData->bt_coexist.halCoex8723.btInqPageStartTime)/1000000) >= 10) {
7094 RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Inquiry/page >= 10sec!!!"));
7095 pHalData->bt_coexist.halCoex8723.btInqPageStartTime = 0;
7096 }
7097 }
7098
7099 if (pHalData->bt_coexist.halCoex8723.btInqPageStartTime) {
7100 btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
7101 btdm_2AntIgnoreWlanAct(padapter, false);
7102 btdm_2AntPsTdma(padapter, true, 8);
7103 return true;
7104 } else {
7105 return false;
7106 }
7107}
7108
7109static u8 btdm_Is2Ant8723ACommonAction(struct rtw_adapter *padapter)
7110{
7111 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
7112 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
7113 u8 bCommon = false;
7114
7115 RTPRINT(FBT, BT_TRACE, ("%s :BTDM_IsWifiConnectionExist =%x check_fwstate =%x pmlmepriv->fw_state = 0x%x\n", __func__, BTDM_IsWifiConnectionExist(padapter), check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)), padapter->mlmepriv.fw_state));
7116
7117 if ((!BTDM_IsWifiConnectionExist(padapter)) &&
7118 (!check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) &&
7119 (BT_2ANT_BT_STATUS_IDLE == pBtdm8723->btStatus)) {
7120 RTPRINT(FBT, BT_TRACE, ("Wifi idle + Bt idle!!\n"));
7121
7122 btdm_2AntLowPenaltyRa(padapter, false);
7123 btdm_2AntRfShrink(padapter, false);
7124 btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
7125
7126 btdm_2AntIgnoreWlanAct(padapter, false);
7127 btdm_2AntPsTdma(padapter, false, 0);
7128 btdm_2AntFwDacSwingLvl(padapter, 0x20);
7129 btdm_2AntDecBtPwr(padapter, false);
7130
7131 btdm_2AntAgcTable(padapter, false);
7132 btdm_2AntAdcBackOff(padapter, false);
7133 btdm_2AntDacSwing(padapter, false, 0xc0);
7134
7135 bCommon = true;
7136 } else if (((BTDM_IsWifiConnectionExist(padapter)) ||
7137 (check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)))) &&
7138 (BT_2ANT_BT_STATUS_IDLE == pBtdm8723->btStatus)) {
7139 RTPRINT(FBT, BT_TRACE, ("Wifi non-idle + BT idle!!\n"));
7140
7141 btdm_2AntLowPenaltyRa(padapter, true);
7142 btdm_2AntRfShrink(padapter, false);
7143 btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
7144
7145 btdm_2AntIgnoreWlanAct(padapter, false);
7146 btdm_2AntPsTdma(padapter, false, 0);
7147 btdm_2AntFwDacSwingLvl(padapter, 0x20);
7148 btdm_2AntDecBtPwr(padapter, true);
7149
7150 btdm_2AntAgcTable(padapter, false);
7151 btdm_2AntAdcBackOff(padapter, false);
7152 btdm_2AntDacSwing(padapter, false, 0xc0);
7153
7154 bCommon = true;
7155 } else if ((!BTDM_IsWifiConnectionExist(padapter)) &&
7156 (!check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) &&
7157 (BT_2ANT_BT_STATUS_CONNECTED_IDLE == pBtdm8723->btStatus)) {
7158 RTPRINT(FBT, BT_TRACE, ("Wifi idle + Bt connected idle!!\n"));
7159
7160 btdm_2AntLowPenaltyRa(padapter, true);
7161 btdm_2AntRfShrink(padapter, true);
7162 btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
7163
7164 btdm_2AntIgnoreWlanAct(padapter, false);
7165 btdm_2AntPsTdma(padapter, false, 0);
7166 btdm_2AntFwDacSwingLvl(padapter, 0x20);
7167 btdm_2AntDecBtPwr(padapter, false);
7168
7169 btdm_2AntAgcTable(padapter, false);
7170 btdm_2AntAdcBackOff(padapter, false);
7171 btdm_2AntDacSwing(padapter, false, 0xc0);
7172
7173 bCommon = true;
7174 } else if (((BTDM_IsWifiConnectionExist(padapter)) ||
7175 (check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)))) &&
7176 (BT_2ANT_BT_STATUS_CONNECTED_IDLE == pBtdm8723->btStatus)) {
7177 RTPRINT(FBT, BT_TRACE, ("Wifi non-idle + Bt connected idle!!\n"));
7178
7179 btdm_2AntLowPenaltyRa(padapter, true);
7180 btdm_2AntRfShrink(padapter, true);
7181 btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
7182
7183 btdm_2AntIgnoreWlanAct(padapter, false);
7184 btdm_2AntPsTdma(padapter, false, 0);
7185 btdm_2AntFwDacSwingLvl(padapter, 0x20);
7186 btdm_2AntDecBtPwr(padapter, true);
7187
7188 btdm_2AntAgcTable(padapter, false);
7189 btdm_2AntAdcBackOff(padapter, false);
7190 btdm_2AntDacSwing(padapter, false, 0xc0);
7191
7192 bCommon = true;
7193 } else if ((!BTDM_IsWifiConnectionExist(padapter)) &&
7194 (!check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))) &&
7195 (BT_2ANT_BT_STATUS_NON_IDLE == pBtdm8723->btStatus)) {
7196 RTPRINT(FBT, BT_TRACE, ("Wifi idle + BT non-idle!!\n"));
7197
7198 btdm_2AntLowPenaltyRa(padapter, true);
7199 btdm_2AntRfShrink(padapter, true);
7200 btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
7201
7202 btdm_2AntIgnoreWlanAct(padapter, false);
7203 btdm_2AntPsTdma(padapter, false, 0);
7204 btdm_2AntFwDacSwingLvl(padapter, 0x20);
7205 btdm_2AntDecBtPwr(padapter, false);
7206
7207 btdm_2AntAgcTable(padapter, false);
7208 btdm_2AntAdcBackOff(padapter, false);
7209 btdm_2AntDacSwing(padapter, false, 0xc0);
7210
7211 bCommon = true;
7212 } else {
7213 RTPRINT(FBT, BT_TRACE, ("Wifi non-idle + BT non-idle!!\n"));
7214 btdm_2AntLowPenaltyRa(padapter, true);
7215 btdm_2AntRfShrink(padapter, true);
7216 btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
7217 btdm_2AntIgnoreWlanAct(padapter, false);
7218 btdm_2AntFwDacSwingLvl(padapter, 0x20);
7219
7220 bCommon = false;
7221 }
7222 return bCommon;
7223}
7224
7225static void
7226btdm_2AntTdmaDurationAdjust(struct rtw_adapter *padapter, u8 bScoHid,
7227 u8 bTxPause, u8 maxInterval)
7228{
7229 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
7230 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
7231 static s32 up, dn, m, n, WaitCount;
7232 s32 result; /* 0: no change, +1: increase WiFi duration, -1: decrease WiFi duration */
7233 u8 retryCount = 0;
7234
7235 RTPRINT(FBT, BT_TRACE, ("[BTCoex], TdmaDurationAdjust()\n"));
7236
7237 if (pBtdm8723->bResetTdmaAdjust) {
7238 pBtdm8723->bResetTdmaAdjust = false;
7239 RTPRINT(FBT, BT_TRACE, ("[BTCoex], first run TdmaDurationAdjust()!!\n"));
7240 if (bScoHid) {
7241 if (bTxPause) {
7242 if (maxInterval == 1) {
7243 btdm_2AntPsTdma(padapter, true, 15);
7244 pBtdm8723->psTdmaDuAdjType = 15;
7245 } else if (maxInterval == 2) {
7246 btdm_2AntPsTdma(padapter, true, 15);
7247 pBtdm8723->psTdmaDuAdjType = 15;
7248 } else if (maxInterval == 3) {
7249 btdm_2AntPsTdma(padapter, true, 15);
7250 pBtdm8723->psTdmaDuAdjType = 15;
7251 } else {
7252 btdm_2AntPsTdma(padapter, true, 15);
7253 pBtdm8723->psTdmaDuAdjType = 15;
7254 }
7255 } else {
7256 if (maxInterval == 1) {
7257 btdm_2AntPsTdma(padapter, true, 11);
7258 pBtdm8723->psTdmaDuAdjType = 11;
7259 } else if (maxInterval == 2) {
7260 btdm_2AntPsTdma(padapter, true, 11);
7261 pBtdm8723->psTdmaDuAdjType = 11;
7262 } else if (maxInterval == 3) {
7263 btdm_2AntPsTdma(padapter, true, 11);
7264 pBtdm8723->psTdmaDuAdjType = 11;
7265 } else {
7266 btdm_2AntPsTdma(padapter, true, 11);
7267 pBtdm8723->psTdmaDuAdjType = 11;
7268 }
7269 }
7270 } else {
7271 if (bTxPause) {
7272 if (maxInterval == 1) {
7273 btdm_2AntPsTdma(padapter, true, 7);
7274 pBtdm8723->psTdmaDuAdjType = 7;
7275 } else if (maxInterval == 2) {
7276 btdm_2AntPsTdma(padapter, true, 7);
7277 pBtdm8723->psTdmaDuAdjType = 7;
7278 } else if (maxInterval == 3) {
7279 btdm_2AntPsTdma(padapter, true, 7);
7280 pBtdm8723->psTdmaDuAdjType = 7;
7281 } else {
7282 btdm_2AntPsTdma(padapter, true, 7);
7283 pBtdm8723->psTdmaDuAdjType = 7;
7284 }
7285 } else {
7286 if (maxInterval == 1) {
7287 btdm_2AntPsTdma(padapter, true, 3);
7288 pBtdm8723->psTdmaDuAdjType = 3;
7289 } else if (maxInterval == 2) {
7290 btdm_2AntPsTdma(padapter, true, 3);
7291 pBtdm8723->psTdmaDuAdjType = 3;
7292 } else if (maxInterval == 3) {
7293 btdm_2AntPsTdma(padapter, true, 3);
7294 pBtdm8723->psTdmaDuAdjType = 3;
7295 } else {
7296 btdm_2AntPsTdma(padapter, true, 3);
7297 pBtdm8723->psTdmaDuAdjType = 3;
7298 }
7299 }
7300 }
7301 up = 0;
7302 dn = 0;
7303 m = 1;
7304 n = 3;
7305 result = 0;
7306 WaitCount = 0;
7307 } else {
7308 /* accquire the BT TRx retry count from BT_Info byte2 */
7309 retryCount = pHalData->bt_coexist.halCoex8723.btRetryCnt;
7310 RTPRINT(FBT, BT_TRACE, ("[BTCoex], retryCount = %d\n", retryCount));
7311 result = 0;
7312 WaitCount++;
7313
7314 if (retryCount == 0) { /* no retry in the last 2-second duration */
7315 up++;
7316 dn--;
7317
7318 if (dn <= 0)
7319 dn = 0;
7320
7321 if (up >= n) { /* if ³sÄò n ­Ó2¬í retry count¬°0, «h½Õ¼eWiFi duration */
7322 WaitCount = 0;
7323 n = 3;
7324 up = 0;
7325 dn = 0;
7326 result = 1;
7327 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Increase wifi duration!!\n"));
7328 }
7329 } else if (retryCount <= 3) { /* <= 3 retry in the last 2-second duration */
7330 up--;
7331 dn++;
7332
7333 if (up <= 0)
7334 up = 0;
7335
7336 if (dn == 2) { /* if ³sÄò 2 ­Ó2¬í retry count< 3, «h½Õ¯¶WiFi duration */
7337 if (WaitCount <= 2)
7338 m++; /* ÁקK¤@ª½¦b¨â­Ólevel¤¤¨Ó¦^ */
7339 else
7340 m = 1;
7341
7342 if (m >= 20) /* m ³Ì¤j­È = 20 ' ³Ì¤j120¬í recheck¬O§_½Õ¾ã WiFi duration. */
7343 m = 20;
7344
7345 n = 3*m;
7346 up = 0;
7347 dn = 0;
7348 WaitCount = 0;
7349 result = -1;
7350 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Decrease wifi duration for retryCounter<3!!\n"));
7351 }
7352 } else { /* retry count > 3, ¥u­n1¦¸ retry count > 3, «h½Õ¯¶WiFi duration */
7353 if (WaitCount == 1)
7354 m++; /* ÁקK¤@ª½¦b¨â­Ólevel¤¤¨Ó¦^ */
7355 else
7356 m = 1;
7357
7358 if (m >= 20) /* m ³Ì¤j­È = 20 ' ³Ì¤j120¬í recheck¬O§_½Õ¾ã WiFi duration. */
7359 m = 20;
7360 n = 3*m;
7361 up = 0;
7362 dn = 0;
7363 WaitCount = 0;
7364 result = -1;
7365 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Decrease wifi duration for retryCounter>3!!\n"));
7366 }
7367
7368 RTPRINT(FBT, BT_TRACE, ("[BTCoex], max Interval = %d\n", maxInterval));
7369 if (maxInterval == 1) {
7370 if (bTxPause) {
7371 RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 1\n"));
7372 if (pBtdm8723->curPsTdma == 1) {
7373 btdm_2AntPsTdma(padapter, true, 5);
7374 pBtdm8723->psTdmaDuAdjType = 5;
7375 } else if (pBtdm8723->curPsTdma == 2) {
7376 btdm_2AntPsTdma(padapter, true, 6);
7377 pBtdm8723->psTdmaDuAdjType = 6;
7378 } else if (pBtdm8723->curPsTdma == 3) {
7379 btdm_2AntPsTdma(padapter, true, 7);
7380 pBtdm8723->psTdmaDuAdjType = 7;
7381 } else if (pBtdm8723->curPsTdma == 4) {
7382 btdm_2AntPsTdma(padapter, true, 8);
7383 pBtdm8723->psTdmaDuAdjType = 8;
7384 }
7385 if (pBtdm8723->curPsTdma == 9) {
7386 btdm_2AntPsTdma(padapter, true, 13);
7387 pBtdm8723->psTdmaDuAdjType = 13;
7388 } else if (pBtdm8723->curPsTdma == 10) {
7389 btdm_2AntPsTdma(padapter, true, 14);
7390 pBtdm8723->psTdmaDuAdjType = 14;
7391 } else if (pBtdm8723->curPsTdma == 11) {
7392 btdm_2AntPsTdma(padapter, true, 15);
7393 pBtdm8723->psTdmaDuAdjType = 15;
7394 } else if (pBtdm8723->curPsTdma == 12) {
7395 btdm_2AntPsTdma(padapter, true, 16);
7396 pBtdm8723->psTdmaDuAdjType = 16;
7397 }
7398
7399 if (result == -1) {
7400 if (pBtdm8723->curPsTdma == 5) {
7401 btdm_2AntPsTdma(padapter, true, 6);
7402 pBtdm8723->psTdmaDuAdjType = 6;
7403 } else if (pBtdm8723->curPsTdma == 6) {
7404 btdm_2AntPsTdma(padapter, true, 7);
7405 pBtdm8723->psTdmaDuAdjType = 7;
7406 } else if (pBtdm8723->curPsTdma == 7) {
7407 btdm_2AntPsTdma(padapter, true, 8);
7408 pBtdm8723->psTdmaDuAdjType = 8;
7409 } else if (pBtdm8723->curPsTdma == 13) {
7410 btdm_2AntPsTdma(padapter, true, 14);
7411 pBtdm8723->psTdmaDuAdjType = 14;
7412 } else if (pBtdm8723->curPsTdma == 14) {
7413 btdm_2AntPsTdma(padapter, true, 15);
7414 pBtdm8723->psTdmaDuAdjType = 15;
7415 } else if (pBtdm8723->curPsTdma == 15) {
7416 btdm_2AntPsTdma(padapter, true, 16);
7417 pBtdm8723->psTdmaDuAdjType = 16;
7418 }
7419 } else if (result == 1) {
7420 if (pBtdm8723->curPsTdma == 8) {
7421 btdm_2AntPsTdma(padapter, true, 7);
7422 pBtdm8723->psTdmaDuAdjType = 7;
7423 } else if (pBtdm8723->curPsTdma == 7) {
7424 btdm_2AntPsTdma(padapter, true, 6);
7425 pBtdm8723->psTdmaDuAdjType = 6;
7426 } else if (pBtdm8723->curPsTdma == 6) {
7427 btdm_2AntPsTdma(padapter, true, 5);
7428 pBtdm8723->psTdmaDuAdjType = 5;
7429 } else if (pBtdm8723->curPsTdma == 16) {
7430 btdm_2AntPsTdma(padapter, true, 15);
7431 pBtdm8723->psTdmaDuAdjType = 15;
7432 } else if (pBtdm8723->curPsTdma == 15) {
7433 btdm_2AntPsTdma(padapter, true, 14);
7434 pBtdm8723->psTdmaDuAdjType = 14;
7435 } else if (pBtdm8723->curPsTdma == 14) {
7436 btdm_2AntPsTdma(padapter, true, 13);
7437 pBtdm8723->psTdmaDuAdjType = 13;
7438 }
7439 }
7440 } else {
7441 RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 0\n"));
7442 if (pBtdm8723->curPsTdma == 5) {
7443 btdm_2AntPsTdma(padapter, true, 1);
7444 pBtdm8723->psTdmaDuAdjType = 1;
7445 } else if (pBtdm8723->curPsTdma == 6) {
7446 btdm_2AntPsTdma(padapter, true, 2);
7447 pBtdm8723->psTdmaDuAdjType = 2;
7448 } else if (pBtdm8723->curPsTdma == 7) {
7449 btdm_2AntPsTdma(padapter, true, 3);
7450 pBtdm8723->psTdmaDuAdjType = 3;
7451 } else if (pBtdm8723->curPsTdma == 8) {
7452 btdm_2AntPsTdma(padapter, true, 4);
7453 pBtdm8723->psTdmaDuAdjType = 4;
7454 }
7455 if (pBtdm8723->curPsTdma == 13) {
7456 btdm_2AntPsTdma(padapter, true, 9);
7457 pBtdm8723->psTdmaDuAdjType = 9;
7458 } else if (pBtdm8723->curPsTdma == 14) {
7459 btdm_2AntPsTdma(padapter, true, 10);
7460 pBtdm8723->psTdmaDuAdjType = 10;
7461 } else if (pBtdm8723->curPsTdma == 15) {
7462 btdm_2AntPsTdma(padapter, true, 11);
7463 pBtdm8723->psTdmaDuAdjType = 11;
7464 } else if (pBtdm8723->curPsTdma == 16) {
7465 btdm_2AntPsTdma(padapter, true, 12);
7466 pBtdm8723->psTdmaDuAdjType = 12;
7467 }
7468
7469 if (result == -1) {
7470 if (pBtdm8723->curPsTdma == 1) {
7471 btdm_2AntPsTdma(padapter, true, 2);
7472 pBtdm8723->psTdmaDuAdjType = 2;
7473 } else if (pBtdm8723->curPsTdma == 2) {
7474 btdm_2AntPsTdma(padapter, true, 3);
7475 pBtdm8723->psTdmaDuAdjType = 3;
7476 } else if (pBtdm8723->curPsTdma == 3) {
7477 btdm_2AntPsTdma(padapter, true, 4);
7478 pBtdm8723->psTdmaDuAdjType = 4;
7479 } else if (pBtdm8723->curPsTdma == 9) {
7480 btdm_2AntPsTdma(padapter, true, 10);
7481 pBtdm8723->psTdmaDuAdjType = 10;
7482 } else if (pBtdm8723->curPsTdma == 10) {
7483 btdm_2AntPsTdma(padapter, true, 11);
7484 pBtdm8723->psTdmaDuAdjType = 11;
7485 } else if (pBtdm8723->curPsTdma == 11) {
7486 btdm_2AntPsTdma(padapter, true, 12);
7487 pBtdm8723->psTdmaDuAdjType = 12;
7488 }
7489 } else if (result == 1) {
7490 if (pBtdm8723->curPsTdma == 4) {
7491 btdm_2AntPsTdma(padapter, true, 3);
7492 pBtdm8723->psTdmaDuAdjType = 3;
7493 } else if (pBtdm8723->curPsTdma == 3) {
7494 btdm_2AntPsTdma(padapter, true, 2);
7495 pBtdm8723->psTdmaDuAdjType = 2;
7496 } else if (pBtdm8723->curPsTdma == 2) {
7497 btdm_2AntPsTdma(padapter, true, 1);
7498 pBtdm8723->psTdmaDuAdjType = 1;
7499 } else if (pBtdm8723->curPsTdma == 12) {
7500 btdm_2AntPsTdma(padapter, true, 11);
7501 pBtdm8723->psTdmaDuAdjType = 11;
7502 } else if (pBtdm8723->curPsTdma == 11) {
7503 btdm_2AntPsTdma(padapter, true, 10);
7504 pBtdm8723->psTdmaDuAdjType = 10;
7505 } else if (pBtdm8723->curPsTdma == 10) {
7506 btdm_2AntPsTdma(padapter, true, 9);
7507 pBtdm8723->psTdmaDuAdjType = 9;
7508 }
7509 }
7510 }
7511 } else if (maxInterval == 2) {
7512 if (bTxPause) {
7513 RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 1\n"));
7514 if (pBtdm8723->curPsTdma == 1) {
7515 btdm_2AntPsTdma(padapter, true, 6);
7516 pBtdm8723->psTdmaDuAdjType = 6;
7517 } else if (pBtdm8723->curPsTdma == 2) {
7518 btdm_2AntPsTdma(padapter, true, 6);
7519 pBtdm8723->psTdmaDuAdjType = 6;
7520 } else if (pBtdm8723->curPsTdma == 3) {
7521 btdm_2AntPsTdma(padapter, true, 7);
7522 pBtdm8723->psTdmaDuAdjType = 7;
7523 } else if (pBtdm8723->curPsTdma == 4) {
7524 btdm_2AntPsTdma(padapter, true, 8);
7525 pBtdm8723->psTdmaDuAdjType = 8;
7526 }
7527 if (pBtdm8723->curPsTdma == 9) {
7528 btdm_2AntPsTdma(padapter, true, 14);
7529 pBtdm8723->psTdmaDuAdjType = 14;
7530 } else if (pBtdm8723->curPsTdma == 10) {
7531 btdm_2AntPsTdma(padapter, true, 14);
7532 pBtdm8723->psTdmaDuAdjType = 14;
7533 } else if (pBtdm8723->curPsTdma == 11) {
7534 btdm_2AntPsTdma(padapter, true, 15);
7535 pBtdm8723->psTdmaDuAdjType = 15;
7536 } else if (pBtdm8723->curPsTdma == 12) {
7537 btdm_2AntPsTdma(padapter, true, 16);
7538 pBtdm8723->psTdmaDuAdjType = 16;
7539 }
7540 if (result == -1) {
7541 if (pBtdm8723->curPsTdma == 5) {
7542 btdm_2AntPsTdma(padapter, true, 6);
7543 pBtdm8723->psTdmaDuAdjType = 6;
7544 } else if (pBtdm8723->curPsTdma == 6) {
7545 btdm_2AntPsTdma(padapter, true, 7);
7546 pBtdm8723->psTdmaDuAdjType = 7;
7547 } else if (pBtdm8723->curPsTdma == 7) {
7548 btdm_2AntPsTdma(padapter, true, 8);
7549 pBtdm8723->psTdmaDuAdjType = 8;
7550 } else if (pBtdm8723->curPsTdma == 13) {
7551 btdm_2AntPsTdma(padapter, true, 14);
7552 pBtdm8723->psTdmaDuAdjType = 14;
7553 } else if (pBtdm8723->curPsTdma == 14) {
7554 btdm_2AntPsTdma(padapter, true, 15);
7555 pBtdm8723->psTdmaDuAdjType = 15;
7556 } else if (pBtdm8723->curPsTdma == 15) {
7557 btdm_2AntPsTdma(padapter, true, 16);
7558 pBtdm8723->psTdmaDuAdjType = 16;
7559 }
7560 } else if (result == 1) {
7561 if (pBtdm8723->curPsTdma == 8) {
7562 btdm_2AntPsTdma(padapter, true, 7);
7563 pBtdm8723->psTdmaDuAdjType = 7;
7564 } else if (pBtdm8723->curPsTdma == 7) {
7565 btdm_2AntPsTdma(padapter, true, 6);
7566 pBtdm8723->psTdmaDuAdjType = 6;
7567 } else if (pBtdm8723->curPsTdma == 6) {
7568 btdm_2AntPsTdma(padapter, true, 6);
7569 pBtdm8723->psTdmaDuAdjType = 6;
7570 } else if (pBtdm8723->curPsTdma == 16) {
7571 btdm_2AntPsTdma(padapter, true, 15);
7572 pBtdm8723->psTdmaDuAdjType = 15;
7573 } else if (pBtdm8723->curPsTdma == 15) {
7574 btdm_2AntPsTdma(padapter, true, 14);
7575 pBtdm8723->psTdmaDuAdjType = 14;
7576 } else if (pBtdm8723->curPsTdma == 14) {
7577 btdm_2AntPsTdma(padapter, true, 14);
7578 pBtdm8723->psTdmaDuAdjType = 14;
7579 }
7580 }
7581 } else {
7582 RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 0\n"));
7583 if (pBtdm8723->curPsTdma == 5) {
7584 btdm_2AntPsTdma(padapter, true, 2);
7585 pBtdm8723->psTdmaDuAdjType = 2;
7586 } else if (pBtdm8723->curPsTdma == 6) {
7587 btdm_2AntPsTdma(padapter, true, 2);
7588 pBtdm8723->psTdmaDuAdjType = 2;
7589 } else if (pBtdm8723->curPsTdma == 7) {
7590 btdm_2AntPsTdma(padapter, true, 3);
7591 pBtdm8723->psTdmaDuAdjType = 3;
7592 } else if (pBtdm8723->curPsTdma == 8) {
7593 btdm_2AntPsTdma(padapter, true, 4);
7594 pBtdm8723->psTdmaDuAdjType = 4;
7595 }
7596 if (pBtdm8723->curPsTdma == 13) {
7597 btdm_2AntPsTdma(padapter, true, 10);
7598 pBtdm8723->psTdmaDuAdjType = 10;
7599 } else if (pBtdm8723->curPsTdma == 14) {
7600 btdm_2AntPsTdma(padapter, true, 10);
7601 pBtdm8723->psTdmaDuAdjType = 10;
7602 } else if (pBtdm8723->curPsTdma == 15) {
7603 btdm_2AntPsTdma(padapter, true, 11);
7604 pBtdm8723->psTdmaDuAdjType = 11;
7605 } else if (pBtdm8723->curPsTdma == 16) {
7606 btdm_2AntPsTdma(padapter, true, 12);
7607 pBtdm8723->psTdmaDuAdjType = 12;
7608 }
7609 if (result == -1) {
7610 if (pBtdm8723->curPsTdma == 1) {
7611 btdm_2AntPsTdma(padapter, true, 2);
7612 pBtdm8723->psTdmaDuAdjType = 2;
7613 } else if (pBtdm8723->curPsTdma == 2) {
7614 btdm_2AntPsTdma(padapter, true, 3);
7615 pBtdm8723->psTdmaDuAdjType = 3;
7616 } else if (pBtdm8723->curPsTdma == 3) {
7617 btdm_2AntPsTdma(padapter, true, 4);
7618 pBtdm8723->psTdmaDuAdjType = 4;
7619 } else if (pBtdm8723->curPsTdma == 9) {
7620 btdm_2AntPsTdma(padapter, true, 10);
7621 pBtdm8723->psTdmaDuAdjType = 10;
7622 } else if (pBtdm8723->curPsTdma == 10) {
7623 btdm_2AntPsTdma(padapter, true, 11);
7624 pBtdm8723->psTdmaDuAdjType = 11;
7625 } else if (pBtdm8723->curPsTdma == 11) {
7626 btdm_2AntPsTdma(padapter, true, 12);
7627 pBtdm8723->psTdmaDuAdjType = 12;
7628 }
7629 } else if (result == 1) {
7630 if (pBtdm8723->curPsTdma == 4) {
7631 btdm_2AntPsTdma(padapter, true, 3);
7632 pBtdm8723->psTdmaDuAdjType = 3;
7633 } else if (pBtdm8723->curPsTdma == 3) {
7634 btdm_2AntPsTdma(padapter, true, 2);
7635 pBtdm8723->psTdmaDuAdjType = 2;
7636 } else if (pBtdm8723->curPsTdma == 2) {
7637 btdm_2AntPsTdma(padapter, true, 2);
7638 pBtdm8723->psTdmaDuAdjType = 2;
7639 } else if (pBtdm8723->curPsTdma == 12) {
7640 btdm_2AntPsTdma(padapter, true, 11);
7641 pBtdm8723->psTdmaDuAdjType = 11;
7642 } else if (pBtdm8723->curPsTdma == 11) {
7643 btdm_2AntPsTdma(padapter, true, 10);
7644 pBtdm8723->psTdmaDuAdjType = 10;
7645 } else if (pBtdm8723->curPsTdma == 10) {
7646 btdm_2AntPsTdma(padapter, true, 10);
7647 pBtdm8723->psTdmaDuAdjType = 10;
7648 }
7649 }
7650 }
7651 } else if (maxInterval == 3) {
7652 if (bTxPause) {
7653 RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 1\n"));
7654 if (pBtdm8723->curPsTdma == 1) {
7655 btdm_2AntPsTdma(padapter, true, 7);
7656 pBtdm8723->psTdmaDuAdjType = 7;
7657 } else if (pBtdm8723->curPsTdma == 2) {
7658 btdm_2AntPsTdma(padapter, true, 7);
7659 pBtdm8723->psTdmaDuAdjType = 7;
7660 } else if (pBtdm8723->curPsTdma == 3) {
7661 btdm_2AntPsTdma(padapter, true, 7);
7662 pBtdm8723->psTdmaDuAdjType = 7;
7663 } else if (pBtdm8723->curPsTdma == 4) {
7664 btdm_2AntPsTdma(padapter, true, 8);
7665 pBtdm8723->psTdmaDuAdjType = 8;
7666 }
7667 if (pBtdm8723->curPsTdma == 9) {
7668 btdm_2AntPsTdma(padapter, true, 15);
7669 pBtdm8723->psTdmaDuAdjType = 15;
7670 } else if (pBtdm8723->curPsTdma == 10) {
7671 btdm_2AntPsTdma(padapter, true, 15);
7672 pBtdm8723->psTdmaDuAdjType = 15;
7673 } else if (pBtdm8723->curPsTdma == 11) {
7674 btdm_2AntPsTdma(padapter, true, 15);
7675 pBtdm8723->psTdmaDuAdjType = 15;
7676 } else if (pBtdm8723->curPsTdma == 12) {
7677 btdm_2AntPsTdma(padapter, true, 16);
7678 pBtdm8723->psTdmaDuAdjType = 16;
7679 }
7680 if (result == -1) {
7681 if (pBtdm8723->curPsTdma == 5) {
7682 btdm_2AntPsTdma(padapter, true, 7);
7683 pBtdm8723->psTdmaDuAdjType = 7;
7684 } else if (pBtdm8723->curPsTdma == 6) {
7685 btdm_2AntPsTdma(padapter, true, 7);
7686 pBtdm8723->psTdmaDuAdjType = 7;
7687 } else if (pBtdm8723->curPsTdma == 7) {
7688 btdm_2AntPsTdma(padapter, true, 8);
7689 pBtdm8723->psTdmaDuAdjType = 8;
7690 } else if (pBtdm8723->curPsTdma == 13) {
7691 btdm_2AntPsTdma(padapter, true, 15);
7692 pBtdm8723->psTdmaDuAdjType = 15;
7693 } else if (pBtdm8723->curPsTdma == 14) {
7694 btdm_2AntPsTdma(padapter, true, 15);
7695 pBtdm8723->psTdmaDuAdjType = 15;
7696 } else if (pBtdm8723->curPsTdma == 15) {
7697 btdm_2AntPsTdma(padapter, true, 16);
7698 pBtdm8723->psTdmaDuAdjType = 16;
7699 }
7700 } else if (result == 1) {
7701 if (pBtdm8723->curPsTdma == 8) {
7702 btdm_2AntPsTdma(padapter, true, 7);
7703 pBtdm8723->psTdmaDuAdjType = 7;
7704 } else if (pBtdm8723->curPsTdma == 7) {
7705 btdm_2AntPsTdma(padapter, true, 7);
7706 pBtdm8723->psTdmaDuAdjType = 7;
7707 } else if (pBtdm8723->curPsTdma == 6) {
7708 btdm_2AntPsTdma(padapter, true, 7);
7709 pBtdm8723->psTdmaDuAdjType = 7;
7710 } else if (pBtdm8723->curPsTdma == 16) {
7711 btdm_2AntPsTdma(padapter, true, 15);
7712 pBtdm8723->psTdmaDuAdjType = 15;
7713 } else if (pBtdm8723->curPsTdma == 15) {
7714 btdm_2AntPsTdma(padapter, true, 15);
7715 pBtdm8723->psTdmaDuAdjType = 15;
7716 } else if (pBtdm8723->curPsTdma == 14) {
7717 btdm_2AntPsTdma(padapter, true, 15);
7718 pBtdm8723->psTdmaDuAdjType = 15;
7719 }
7720 }
7721 } else {
7722 RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 0\n"));
7723 if (pBtdm8723->curPsTdma == 5) {
7724 btdm_2AntPsTdma(padapter, true, 3);
7725 pBtdm8723->psTdmaDuAdjType = 3;
7726 } else if (pBtdm8723->curPsTdma == 6) {
7727 btdm_2AntPsTdma(padapter, true, 3);
7728 pBtdm8723->psTdmaDuAdjType = 3;
7729 } else if (pBtdm8723->curPsTdma == 7) {
7730 btdm_2AntPsTdma(padapter, true, 3);
7731 pBtdm8723->psTdmaDuAdjType = 3;
7732 } else if (pBtdm8723->curPsTdma == 8) {
7733 btdm_2AntPsTdma(padapter, true, 4);
7734 pBtdm8723->psTdmaDuAdjType = 4;
7735 }
7736 if (pBtdm8723->curPsTdma == 13) {
7737 btdm_2AntPsTdma(padapter, true, 11);
7738 pBtdm8723->psTdmaDuAdjType = 11;
7739 } else if (pBtdm8723->curPsTdma == 14) {
7740 btdm_2AntPsTdma(padapter, true, 11);
7741 pBtdm8723->psTdmaDuAdjType = 11;
7742 } else if (pBtdm8723->curPsTdma == 15) {
7743 btdm_2AntPsTdma(padapter, true, 11);
7744 pBtdm8723->psTdmaDuAdjType = 11;
7745 } else if (pBtdm8723->curPsTdma == 16) {
7746 btdm_2AntPsTdma(padapter, true, 12);
7747 pBtdm8723->psTdmaDuAdjType = 12;
7748 }
7749 if (result == -1) {
7750 if (pBtdm8723->curPsTdma == 1) {
7751 btdm_2AntPsTdma(padapter, true, 3);
7752 pBtdm8723->psTdmaDuAdjType = 3;
7753 } else if (pBtdm8723->curPsTdma == 2) {
7754 btdm_2AntPsTdma(padapter, true, 3);
7755 pBtdm8723->psTdmaDuAdjType = 3;
7756 } else if (pBtdm8723->curPsTdma == 3) {
7757 btdm_2AntPsTdma(padapter, true, 4);
7758 pBtdm8723->psTdmaDuAdjType = 4;
7759 } else if (pBtdm8723->curPsTdma == 9) {
7760 btdm_2AntPsTdma(padapter, true, 11);
7761 pBtdm8723->psTdmaDuAdjType = 11;
7762 } else if (pBtdm8723->curPsTdma == 10) {
7763 btdm_2AntPsTdma(padapter, true, 11);
7764 pBtdm8723->psTdmaDuAdjType = 11;
7765 } else if (pBtdm8723->curPsTdma == 11) {
7766 btdm_2AntPsTdma(padapter, true, 12);
7767 pBtdm8723->psTdmaDuAdjType = 12;
7768 }
7769 } else if (result == 1) {
7770 if (pBtdm8723->curPsTdma == 4) {
7771 btdm_2AntPsTdma(padapter, true, 3);
7772 pBtdm8723->psTdmaDuAdjType = 3;
7773 } else if (pBtdm8723->curPsTdma == 3) {
7774 btdm_2AntPsTdma(padapter, true, 3);
7775 pBtdm8723->psTdmaDuAdjType = 3;
7776 } else if (pBtdm8723->curPsTdma == 2) {
7777 btdm_2AntPsTdma(padapter, true, 3);
7778 pBtdm8723->psTdmaDuAdjType = 3;
7779 } else if (pBtdm8723->curPsTdma == 12) {
7780 btdm_2AntPsTdma(padapter, true, 11);
7781 pBtdm8723->psTdmaDuAdjType = 11;
7782 } else if (pBtdm8723->curPsTdma == 11) {
7783 btdm_2AntPsTdma(padapter, true, 11);
7784 pBtdm8723->psTdmaDuAdjType = 11;
7785 } else if (pBtdm8723->curPsTdma == 10) {
7786 btdm_2AntPsTdma(padapter, true, 11);
7787 pBtdm8723->psTdmaDuAdjType = 11;
7788 }
7789 }
7790 }
7791 }
7792 }
7793 RTPRINT(FBT, BT_TRACE, ("[BTCoex], PsTdma type : recordPsTdma =%d\n", pBtdm8723->psTdmaDuAdjType));
7794 /* if current PsTdma not match with the recorded one (when scan, dhcp...), */
7795 /* then we have to adjust it back to the previous record one. */
7796 if (pBtdm8723->curPsTdma != pBtdm8723->psTdmaDuAdjType) {
7797 RTPRINT(FBT, BT_TRACE, ("[BTCoex], PsTdma type dismatch!!!, curPsTdma =%d, recordPsTdma =%d\n",
7798 pBtdm8723->curPsTdma, pBtdm8723->psTdmaDuAdjType));
7799
7800 if (!check_fwstate(&padapter->mlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING))
7801 btdm_2AntPsTdma(padapter, true, pBtdm8723->psTdmaDuAdjType);
7802 else
7803 RTPRINT(FBT, BT_TRACE, ("[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n"));
7804 }
7805}
7806
7807/* default Action */
7808/* SCO only or SCO+PAN(HS) */
7809static void btdm_2Ant8723ASCOAction(struct rtw_adapter *padapter)
7810{
7811 u8 btRssiState, btRssiState1;
7812
7813 if (btdm_NeedToDecBtPwr(padapter))
7814 btdm_2AntDecBtPwr(padapter, true);
7815 else
7816 btdm_2AntDecBtPwr(padapter, false);
7817
7818 if (BTDM_IsHT40(padapter)) {
7819 RTPRINT(FBT, BT_TRACE, ("HT40\n"));
7820 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
7821 /* fw mechanism */
7822 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
7823 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
7824 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
7825 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
7826 btdm_2AntPsTdma(padapter, true, 11);
7827 } else {
7828 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
7829 btdm_2AntPsTdma(padapter, true, 15);
7830 }
7831
7832 /* sw mechanism */
7833 btdm_2AntAgcTable(padapter, false);
7834 btdm_2AntAdcBackOff(padapter, true);
7835 btdm_2AntDacSwing(padapter, false, 0xc0);
7836 } else {
7837 RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
7838 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
7839 btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);
7840
7841 /* fw mechanism */
7842 if ((btRssiState1 == BT_RSSI_STATE_HIGH) ||
7843 (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) {
7844 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
7845 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
7846 btdm_2AntPsTdma(padapter, true, 11);
7847 } else {
7848 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
7849 btdm_2AntPsTdma(padapter, true, 15);
7850 }
7851
7852 /* sw mechanism */
7853 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
7854 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
7855 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
7856 btdm_2AntAgcTable(padapter, true);
7857 btdm_2AntAdcBackOff(padapter, true);
7858 btdm_2AntDacSwing(padapter, false, 0xc0);
7859 } else {
7860 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
7861 btdm_2AntAgcTable(padapter, false);
7862 btdm_2AntAdcBackOff(padapter, false);
7863 btdm_2AntDacSwing(padapter, false, 0xc0);
7864 }
7865 }
7866}
7867
7868static void btdm_2Ant8723AHIDAction(struct rtw_adapter *padapter)
7869{
7870 u8 btRssiState, btRssiState1;
7871
7872 if (btdm_NeedToDecBtPwr(padapter))
7873 btdm_2AntDecBtPwr(padapter, true);
7874 else
7875 btdm_2AntDecBtPwr(padapter, false);
7876
7877 if (BTDM_IsHT40(padapter)) {
7878 RTPRINT(FBT, BT_TRACE, ("HT40\n"));
7879 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
7880 /* fw mechanism */
7881 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
7882 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
7883 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
7884 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
7885 btdm_2AntPsTdma(padapter, true, 9);
7886 } else {
7887 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
7888 btdm_2AntPsTdma(padapter, true, 13);
7889 }
7890
7891 /* sw mechanism */
7892 btdm_2AntAgcTable(padapter, false);
7893 btdm_2AntAdcBackOff(padapter, false);
7894 btdm_2AntDacSwing(padapter, false, 0xc0);
7895 } else {
7896 RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
7897 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
7898 btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);
7899
7900 /* fw mechanism */
7901 if ((btRssiState1 == BT_RSSI_STATE_HIGH) ||
7902 (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) {
7903 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
7904 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
7905 btdm_2AntPsTdma(padapter, true, 9);
7906 } else {
7907 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
7908 btdm_2AntPsTdma(padapter, true, 13);
7909 }
7910
7911 /* sw mechanism */
7912 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
7913 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
7914 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
7915 btdm_2AntAgcTable(padapter, true);
7916 btdm_2AntAdcBackOff(padapter, true);
7917 btdm_2AntDacSwing(padapter, false, 0xc0);
7918 } else {
7919 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
7920 btdm_2AntAgcTable(padapter, false);
7921 btdm_2AntAdcBackOff(padapter, false);
7922 btdm_2AntDacSwing(padapter, false, 0xc0);
7923 }
7924 }
7925}
7926
7927/* A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */
7928static void btdm_2Ant8723AA2DPAction(struct rtw_adapter *padapter)
7929{
7930 u8 btRssiState, btRssiState1;
7931 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
7932 u8 btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt;
7933
7934 if (btdm_NeedToDecBtPwr(padapter))
7935 btdm_2AntDecBtPwr(padapter, true);
7936 else
7937 btdm_2AntDecBtPwr(padapter, false);
7938
7939 if (BTDM_IsHT40(padapter)) {
7940 RTPRINT(FBT, BT_TRACE, ("HT40\n"));
7941 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
7942
7943 /* fw mechanism */
7944 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
7945 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
7946 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
7947 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
7948
7949 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
7950 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
7951 btdm_2AntTdmaDurationAdjust(padapter, false, false, 3);
7952 } else {
7953 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
7954 btdm_2AntTdmaDurationAdjust(padapter, false, false, 1);
7955 }
7956 } else {
7957 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
7958 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
7959 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
7960 btdm_2AntTdmaDurationAdjust(padapter, false, true, 3);
7961 } else {
7962 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
7963 btdm_2AntTdmaDurationAdjust(padapter, false, true, 1);
7964 }
7965 }
7966
7967 /* sw mechanism */
7968 btdm_2AntAgcTable(padapter, false);
7969 btdm_2AntAdcBackOff(padapter, true);
7970 btdm_2AntDacSwing(padapter, false, 0xc0);
7971 } else {
7972 RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
7973 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
7974 btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);
7975
7976 /* fw mechanism */
7977 if ((btRssiState1 == BT_RSSI_STATE_HIGH) ||
7978 (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) {
7979 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
7980 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
7981 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
7982 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
7983 btdm_2AntTdmaDurationAdjust(padapter, false, false, 3);
7984 } else {
7985 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
7986 btdm_2AntTdmaDurationAdjust(padapter, false, false, 1);
7987 }
7988 } else {
7989 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
7990 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
7991 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
7992 btdm_2AntTdmaDurationAdjust(padapter, false, true, 3);
7993 } else {
7994 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
7995 btdm_2AntTdmaDurationAdjust(padapter, false, true, 1);
7996 }
7997 }
7998
7999 /* sw mechanism */
8000 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8001 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8002 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
8003 btdm_2AntAgcTable(padapter, true);
8004 btdm_2AntAdcBackOff(padapter, true);
8005 btdm_2AntDacSwing(padapter, false, 0xc0);
8006 } else {
8007 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
8008 btdm_2AntAgcTable(padapter, false);
8009 btdm_2AntAdcBackOff(padapter, false);
8010 btdm_2AntDacSwing(padapter, false, 0xc0);
8011 }
8012 }
8013}
8014
8015static void btdm_2Ant8723APANEDRAction(struct rtw_adapter *padapter)
8016{
8017 u8 btRssiState, btRssiState1;
8018
8019 if (btdm_NeedToDecBtPwr(padapter))
8020 btdm_2AntDecBtPwr(padapter, true);
8021 else
8022 btdm_2AntDecBtPwr(padapter, false);
8023
8024 if (BTDM_IsHT40(padapter)) {
8025 RTPRINT(FBT, BT_TRACE, ("HT40\n"));
8026 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
8027
8028 /* fw mechanism */
8029 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8030 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8031 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
8032 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
8033 btdm_2AntPsTdma(padapter, true, 2);
8034 } else {
8035 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
8036 btdm_2AntPsTdma(padapter, true, 6);
8037 }
8038
8039 /* sw mechanism */
8040 btdm_2AntAgcTable(padapter, false);
8041 btdm_2AntAdcBackOff(padapter, true);
8042 btdm_2AntDacSwing(padapter, false, 0xc0);
8043 } else {
8044 RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
8045 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
8046 btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);
8047
8048 /* fw mechanism */
8049 if ((btRssiState1 == BT_RSSI_STATE_HIGH) ||
8050 (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) {
8051 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
8052 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
8053 btdm_2AntPsTdma(padapter, true, 2);
8054 } else {
8055 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
8056 btdm_2AntPsTdma(padapter, true, 6);
8057 }
8058
8059 /* sw mechanism */
8060 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8061 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8062 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
8063 btdm_2AntAgcTable(padapter, true);
8064 btdm_2AntAdcBackOff(padapter, true);
8065 btdm_2AntDacSwing(padapter, false, 0xc0);
8066 } else {
8067 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
8068 btdm_2AntAgcTable(padapter, false);
8069 btdm_2AntAdcBackOff(padapter, false);
8070 btdm_2AntDacSwing(padapter, false, 0xc0);
8071 }
8072 }
8073}
8074
8075/* PAN(HS) only */
8076static void btdm_2Ant8723APANHSAction(struct rtw_adapter *padapter)
8077{
8078 u8 btRssiState;
8079
8080 if (BTDM_IsHT40(padapter)) {
8081 RTPRINT(FBT, BT_TRACE, ("HT40\n"));
8082 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0);
8083 /* fw mechanism */
8084 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8085 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8086 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
8087 btdm_2AntDecBtPwr(padapter, true);
8088 } else {
8089 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
8090 btdm_2AntDecBtPwr(padapter, false);
8091 }
8092 btdm_2AntPsTdma(padapter, false, 0);
8093
8094 /* sw mechanism */
8095 btdm_2AntAgcTable(padapter, false);
8096 btdm_2AntAdcBackOff(padapter, true);
8097 btdm_2AntDacSwing(padapter, false, 0xc0);
8098 } else {
8099 RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
8100 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0);
8101
8102 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8103 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8104 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high\n"));
8105 /* fw mechanism */
8106 btdm_2AntDecBtPwr(padapter, true);
8107 btdm_2AntPsTdma(padapter, false, 0);
8108
8109 /* sw mechanism */
8110 btdm_2AntAgcTable(padapter, true);
8111 btdm_2AntAdcBackOff(padapter, true);
8112 btdm_2AntDacSwing(padapter, false, 0xc0);
8113 } else {
8114 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low\n"));
8115 /* fw mechanism */
8116 btdm_2AntDecBtPwr(padapter, false);
8117 btdm_2AntPsTdma(padapter, false, 0);
8118
8119 /* sw mechanism */
8120 btdm_2AntAgcTable(padapter, false);
8121 btdm_2AntAdcBackOff(padapter, false);
8122 btdm_2AntDacSwing(padapter, false, 0xc0);
8123 }
8124 }
8125}
8126
8127/* PAN(EDR)+A2DP */
8128static void btdm_2Ant8723APANEDRA2DPAction(struct rtw_adapter *padapter)
8129{
8130 u8 btRssiState, btRssiState1, btInfoExt;
8131 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
8132
8133 btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt;
8134
8135 if (btdm_NeedToDecBtPwr(padapter))
8136 btdm_2AntDecBtPwr(padapter, true);
8137 else
8138 btdm_2AntDecBtPwr(padapter, false);
8139
8140 if (BTDM_IsHT40(padapter)) {
8141 RTPRINT(FBT, BT_TRACE, ("HT40\n"));
8142 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
8143
8144 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8145 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8146 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
8147 /* fw mechanism */
8148 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
8149
8150 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
8151 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
8152 btdm_2AntPsTdma(padapter, true, 4);
8153 } else {
8154 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
8155 btdm_2AntPsTdma(padapter, true, 2);
8156 }
8157 } else {
8158 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
8159 /* fw mechanism */
8160 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
8161 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
8162 btdm_2AntPsTdma(padapter, true, 8);
8163 } else {
8164 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
8165 btdm_2AntPsTdma(padapter, true, 6);
8166 }
8167 }
8168
8169 /* sw mechanism */
8170 btdm_2AntAgcTable(padapter, false);
8171 btdm_2AntAdcBackOff(padapter, true);
8172 btdm_2AntDacSwing(padapter, false, 0xc0);
8173 } else {
8174 RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
8175 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
8176 btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);
8177
8178 if ((btRssiState1 == BT_RSSI_STATE_HIGH) ||
8179 (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) {
8180 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
8181 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
8182 /* fw mechanism */
8183 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
8184 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
8185 btdm_2AntPsTdma(padapter, true, 4);
8186 } else {
8187 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
8188 btdm_2AntPsTdma(padapter, true, 2);
8189 }
8190 } else {
8191 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
8192 /* fw mechanism */
8193 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
8194 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
8195 btdm_2AntPsTdma(padapter, true, 8);
8196 } else {
8197 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
8198 btdm_2AntPsTdma(padapter, true, 6);
8199 }
8200 }
8201
8202 /* sw mechanism */
8203 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8204 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8205 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
8206 btdm_2AntAgcTable(padapter, true);
8207 btdm_2AntAdcBackOff(padapter, true);
8208 btdm_2AntDacSwing(padapter, false, 0xc0);
8209 } else {
8210 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
8211 btdm_2AntAgcTable(padapter, false);
8212 btdm_2AntAdcBackOff(padapter, false);
8213 btdm_2AntDacSwing(padapter, false, 0xc0);
8214 }
8215 }
8216}
8217
8218static void btdm_2Ant8723APANEDRHIDAction(struct rtw_adapter *padapter)
8219{
8220 u8 btRssiState, btRssiState1;
8221
8222 if (btdm_NeedToDecBtPwr(padapter))
8223 btdm_2AntDecBtPwr(padapter, true);
8224 else
8225 btdm_2AntDecBtPwr(padapter, false);
8226
8227 if (BTDM_IsHT40(padapter)) {
8228 RTPRINT(FBT, BT_TRACE, ("HT40\n"));
8229 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
8230 /* fw mechanism */
8231 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8232 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8233 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
8234 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
8235 btdm_2AntPsTdma(padapter, true, 10);
8236 } else {
8237 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
8238 btdm_2AntPsTdma(padapter, true, 14);
8239 }
8240
8241 /* sw mechanism */
8242 btdm_2AntAgcTable(padapter, false);
8243 btdm_2AntAdcBackOff(padapter, true);
8244 btdm_2AntDacSwing(padapter, false, 0xc0);
8245 } else {
8246 RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
8247 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
8248 btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);
8249
8250 /* fw mechanism */
8251 if ((btRssiState1 == BT_RSSI_STATE_HIGH) ||
8252 (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) {
8253 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
8254 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
8255 btdm_2AntPsTdma(padapter, true, 10);
8256 } else {
8257 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
8258 btdm_2AntPsTdma(padapter, true, 14);
8259 }
8260
8261 /* sw mechanism */
8262 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8263 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8264 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
8265 btdm_2AntAgcTable(padapter, true);
8266 btdm_2AntAdcBackOff(padapter, true);
8267 btdm_2AntDacSwing(padapter, false, 0xc0);
8268 } else {
8269 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
8270 btdm_2AntAgcTable(padapter, false);
8271 btdm_2AntAdcBackOff(padapter, false);
8272 btdm_2AntDacSwing(padapter, false, 0xc0);
8273 }
8274 }
8275}
8276
8277/* HID+A2DP+PAN(EDR) */
8278static void btdm_2Ant8723AHIDA2DPPANEDRAction(struct rtw_adapter *padapter)
8279{
8280 u8 btRssiState, btRssiState1, btInfoExt;
8281 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
8282
8283 btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt;
8284
8285 if (btdm_NeedToDecBtPwr(padapter))
8286 btdm_2AntDecBtPwr(padapter, true);
8287 else
8288 btdm_2AntDecBtPwr(padapter, false);
8289
8290 if (BTDM_IsHT40(padapter)) {
8291 RTPRINT(FBT, BT_TRACE, ("HT40\n"));
8292 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
8293 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8294 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8295 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
8296 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
8297
8298 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
8299 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
8300 btdm_2AntPsTdma(padapter, true, 12);
8301 } else {
8302 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
8303 btdm_2AntPsTdma(padapter, true, 10);
8304 }
8305 } else {
8306 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
8307 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
8308 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
8309 btdm_2AntPsTdma(padapter, true, 16);
8310 } else {
8311 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
8312 btdm_2AntPsTdma(padapter, true, 14);
8313 }
8314 }
8315
8316 /* sw mechanism */
8317 btdm_2AntAgcTable(padapter, false);
8318 btdm_2AntAdcBackOff(padapter, true);
8319 btdm_2AntDacSwing(padapter, false, 0xc0);
8320 } else {
8321 RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
8322 btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 37, 0);
8323 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 27, 0);
8324 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8325 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8326 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
8327 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
8328
8329 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
8330 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
8331 btdm_2AntPsTdma(padapter, true, 12);
8332 } else {
8333 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
8334 btdm_2AntPsTdma(padapter, true, 10);
8335 }
8336 } else {
8337 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
8338 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
8339 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
8340 btdm_2AntPsTdma(padapter, true, 16);
8341 } else {
8342 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
8343 btdm_2AntPsTdma(padapter, true, 14);
8344 }
8345 }
8346
8347 /* sw mechanism */
8348 if ((btRssiState1 == BT_RSSI_STATE_HIGH) ||
8349 (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) {
8350 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
8351 btdm_2AntAgcTable(padapter, true);
8352 btdm_2AntAdcBackOff(padapter, true);
8353 btdm_2AntDacSwing(padapter, false, 0xc0);
8354 } else {
8355 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
8356 btdm_2AntAgcTable(padapter, false);
8357 btdm_2AntAdcBackOff(padapter, false);
8358 btdm_2AntDacSwing(padapter, false, 0xc0);
8359 }
8360 }
8361}
8362
8363static void btdm_2Ant8723AHIDA2DPAction(struct rtw_adapter *padapter)
8364{
8365 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
8366 u8 btRssiState, btRssiState1, btInfoExt;
8367
8368 btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt;
8369
8370 if (btdm_NeedToDecBtPwr(padapter))
8371 btdm_2AntDecBtPwr(padapter, true);
8372 else
8373 btdm_2AntDecBtPwr(padapter, false);
8374
8375 if (BTDM_IsHT40(padapter)) {
8376 RTPRINT(FBT, BT_TRACE, ("HT40\n"));
8377 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
8378 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8379 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8380 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
8381 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
8382
8383 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
8384 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
8385 btdm_2AntTdmaDurationAdjust(padapter, true, false, 3);
8386 } else {
8387 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
8388 btdm_2AntTdmaDurationAdjust(padapter, true, false, 1);
8389 }
8390 } else {
8391 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
8392 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
8393 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
8394 btdm_2AntTdmaDurationAdjust(padapter, true, true, 3);
8395 } else {
8396 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
8397 btdm_2AntTdmaDurationAdjust(padapter, true, true, 1);
8398 }
8399 }
8400 /* sw mechanism */
8401 btdm_2AntAgcTable(padapter, false);
8402 btdm_2AntAdcBackOff(padapter, true);
8403 btdm_2AntDacSwing(padapter, false, 0xc0);
8404 } else {
8405 RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
8406 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
8407 btRssiState1 = BTDM_CheckCoexRSSIState(padapter, 2, 27, 0);
8408
8409 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8410 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8411 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
8412 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
8413
8414 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
8415 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
8416 btdm_2AntTdmaDurationAdjust(padapter, true, false, 3);
8417 } else {
8418 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
8419 btdm_2AntTdmaDurationAdjust(padapter, true, false, 1);
8420 }
8421 } else {
8422 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
8423 if (btInfoExt&BIT(0)) { /* a2dp rate, 1:basic /0:edr */
8424 RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
8425 btdm_2AntTdmaDurationAdjust(padapter, true, true, 3);
8426 } else {
8427 RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
8428 btdm_2AntTdmaDurationAdjust(padapter, true, true, 1);
8429 }
8430 }
8431 if ((btRssiState1 == BT_RSSI_STATE_HIGH) ||
8432 (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) {
8433 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
8434 /* sw mechanism */
8435 btdm_2AntAgcTable(padapter, true);
8436 btdm_2AntAdcBackOff(padapter, true);
8437 btdm_2AntDacSwing(padapter, false, 0xc0);
8438 } else {
8439 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
8440 /* sw mechanism */
8441 btdm_2AntAgcTable(padapter, false);
8442 btdm_2AntAdcBackOff(padapter, false);
8443 btdm_2AntDacSwing(padapter, false, 0xc0);
8444 }
8445 }
8446}
8447
8448static void btdm_2Ant8723AA2dp(struct rtw_adapter *padapter)
8449{
8450 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
8451 u8 btRssiState, btRssiState1, btInfoExt;
8452
8453 btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt;
8454
8455 if (btdm_NeedToDecBtPwr(padapter))
8456 btdm_2AntDecBtPwr(padapter, true);
8457 else
8458 btdm_2AntDecBtPwr(padapter, false);
8459 /* coex table */
8460 btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
8461 btdm_2AntIgnoreWlanAct(padapter, false);
8462
8463 if (BTDM_IsHT40(padapter)) {
8464 RTPRINT(FBT, BT_TRACE, ("HT40\n"));
8465 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
8466 /* fw mechanism */
8467 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8468 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8469 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
8470 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
8471 btdm_2AntTdmaDurationAdjust(padapter, false, false, 1);
8472 } else {
8473 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
8474 btdm_2AntTdmaDurationAdjust(padapter, false, true, 1);
8475 }
8476
8477 /* sw mechanism */
8478 btdm_2AntAgcTable(padapter, false);
8479 btdm_2AntAdcBackOff(padapter, true);
8480 btdm_2AntDacSwing(padapter, false, 0xc0);
8481 } else {
8482 RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
8483 btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0);
8484 btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);
8485
8486 /* fw mechanism */
8487 if ((btRssiState1 == BT_RSSI_STATE_HIGH) ||
8488 (btRssiState1 == BT_RSSI_STATE_STAY_HIGH)) {
8489 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
8490 PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
8491 btdm_2AntTdmaDurationAdjust(padapter, false, false, 1);
8492 } else {
8493 RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
8494 btdm_2AntTdmaDurationAdjust(padapter, false, true, 1);
8495 }
8496
8497 /* sw mechanism */
8498 if ((btRssiState == BT_RSSI_STATE_HIGH) ||
8499 (btRssiState == BT_RSSI_STATE_STAY_HIGH)) {
8500 RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
8501 btdm_2AntAgcTable(padapter, true);
8502 btdm_2AntAdcBackOff(padapter, true);
8503 btdm_2AntDacSwing(padapter, false, 0xc0);
8504 } else {
8505 RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
8506 btdm_2AntAgcTable(padapter, false);
8507 btdm_2AntAdcBackOff(padapter, false);
8508 btdm_2AntDacSwing(padapter, false, 0xc0);
8509 }
8510 }
8511}
8512
8513/* extern function start with BTDM_ */
8514static void BTDM_2AntParaInit(struct rtw_adapter *padapter)
8515{
8516
8517 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
8518 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
8519
8520 RTPRINT(FBT, BT_TRACE, ("[BTCoex], 2Ant Parameter Init!!\n"));
8521
8522 /* Enable counter statistics */
8523 rtw_write8(padapter, 0x76e, 0x4);
8524 rtw_write8(padapter, 0x778, 0x3);
8525 rtw_write8(padapter, 0x40, 0x20);
8526
8527 /* force to reset coex mechanism */
8528 pBtdm8723->preVal0x6c0 = 0x0;
8529 btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
8530
8531 pBtdm8723->bPrePsTdmaOn = true;
8532 btdm_2AntPsTdma(padapter, false, 0);
8533
8534 pBtdm8723->preFwDacSwingLvl = 0x10;
8535 btdm_2AntFwDacSwingLvl(padapter, 0x20);
8536
8537 pBtdm8723->bPreDecBtPwr = true;
8538 btdm_2AntDecBtPwr(padapter, false);
8539
8540 pBtdm8723->bPreAgcTableEn = true;
8541 btdm_2AntAgcTable(padapter, false);
8542
8543 pBtdm8723->bPreAdcBackOff = true;
8544 btdm_2AntAdcBackOff(padapter, false);
8545
8546 pBtdm8723->bPreLowPenaltyRa = true;
8547 btdm_2AntLowPenaltyRa(padapter, false);
8548
8549 pBtdm8723->bPreRfRxLpfShrink = true;
8550 btdm_2AntRfShrink(padapter, false);
8551
8552 pBtdm8723->bPreDacSwingOn = true;
8553 btdm_2AntDacSwing(padapter, false, 0xc0);
8554
8555 pBtdm8723->bPreIgnoreWlanAct = true;
8556 btdm_2AntIgnoreWlanAct(padapter, false);
8557}
8558
8559static void BTDM_2AntHwCoexAllOff8723A(struct rtw_adapter *padapter)
8560{
8561 btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
8562}
8563
8564static void BTDM_2AntFwCoexAllOff8723A(struct rtw_adapter *padapter)
8565{
8566 btdm_2AntIgnoreWlanAct(padapter, false);
8567 btdm_2AntPsTdma(padapter, false, 0);
8568 btdm_2AntFwDacSwingLvl(padapter, 0x20);
8569 btdm_2AntDecBtPwr(padapter, false);
8570}
8571
8572static void BTDM_2AntSwCoexAllOff8723A(struct rtw_adapter *padapter)
8573{
8574 btdm_2AntAgcTable(padapter, false);
8575 btdm_2AntAdcBackOff(padapter, false);
8576 btdm_2AntLowPenaltyRa(padapter, false);
8577 btdm_2AntRfShrink(padapter, false);
8578 btdm_2AntDacSwing(padapter, false, 0xc0);
8579}
8580
8581static void BTDM_2AntFwC2hBtInfo8723A(struct rtw_adapter *padapter)
8582{
8583 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
8584 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
8585 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
8586 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
8587 u8 btInfo = 0;
8588 u8 algorithm = BT_2ANT_COEX_ALGO_UNDEFINED;
8589 u8 bBtLinkExist = false, bBtHsModeExist = false;
8590
8591 btInfo = pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal;
8592 pBtdm8723->btStatus = BT_2ANT_BT_STATUS_IDLE;
8593
8594 /* check BIT2 first ==> check if bt is under inquiry or page scan */
8595 if (btInfo & BIT(2)) {
8596 if (!pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage) {
8597 pBtMgnt->ExtConfig.bHoldForBtOperation = true;
8598 pBtMgnt->ExtConfig.bHoldPeriodCnt = 1;
8599 btdm_2AntBtInquiryPage(padapter);
8600 } else {
8601 pBtMgnt->ExtConfig.bHoldPeriodCnt++;
8602 btdm_HoldForBtInqPage(padapter);
8603 }
8604 pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage = true;
8605
8606 } else {
8607 pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage = false;
8608 pBtMgnt->ExtConfig.bHoldForBtOperation = false;
8609 pBtMgnt->ExtConfig.bHoldPeriodCnt = 0;
8610
8611 }
8612 RTPRINT(FBT, BT_TRACE,
8613 ("[BTC2H], pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage =%x pBtMgnt->ExtConfig.bHoldPeriodCnt =%x pBtMgnt->ExtConfig.bHoldForBtOperation =%x\n",
8614 pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage,
8615 pBtMgnt->ExtConfig.bHoldPeriodCnt,
8616 pBtMgnt->ExtConfig.bHoldForBtOperation));
8617
8618 RTPRINT(FBT, BT_TRACE,
8619 ("[BTC2H], btInfo =%x pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal =%x\n",
8620 btInfo, pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal));
8621 if (btInfo&BT_INFO_ACL) {
8622 RTPRINT(FBT, BT_TRACE, ("[BTC2H], BTInfo: bConnect = true btInfo =%x\n", btInfo));
8623 bBtLinkExist = true;
8624 if (((btInfo&(BT_INFO_FTP|BT_INFO_A2DP|BT_INFO_HID|BT_INFO_SCO_BUSY)) != 0) ||
8625 pHalData->bt_coexist.halCoex8723.btRetryCnt > 0) {
8626 pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE;
8627 } else {
8628 pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE;
8629 }
8630
8631 if (btInfo&BT_INFO_SCO || btInfo&BT_INFO_SCO_BUSY) {
8632 if (btInfo&BT_INFO_FTP || btInfo&BT_INFO_A2DP || btInfo&BT_INFO_HID) {
8633 switch (btInfo&0xe0) {
8634 case BT_INFO_HID:
8635 RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID\n"));
8636 algorithm = BT_2ANT_COEX_ALGO_HID;
8637 break;
8638 case BT_INFO_A2DP:
8639 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP\n"));
8640 break;
8641 case BT_INFO_FTP:
8642 if (bBtHsModeExist) {
8643 RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(HS)\n"));
8644 algorithm = BT_2ANT_COEX_ALGO_SCO;
8645 } else {
8646 RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(EDR)\n"));
8647 algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID;
8648 }
8649 break;
8650 case (BT_INFO_HID | BT_INFO_A2DP):
8651 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP\n"));
8652 algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
8653 break;
8654 case (BT_INFO_HID | BT_INFO_FTP):
8655 if (bBtHsModeExist) {
8656 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(HS)\n"));
8657 algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
8658 } else {
8659 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(EDR)\n"));
8660 algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID;
8661 }
8662 break;
8663 case (BT_INFO_A2DP | BT_INFO_FTP):
8664 if (bBtHsModeExist) {
8665 RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(HS)\n"));
8666 algorithm = BT_2ANT_COEX_ALGO_A2DP;
8667 } else {
8668 RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(EDR)\n"));
8669 algorithm = BT_2ANT_COEX_ALGO_PANEDR_A2DP;
8670 }
8671 break;
8672 case (BT_INFO_HID | BT_INFO_A2DP | BT_INFO_FTP):
8673 if (bBtHsModeExist) {
8674 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(HS)\n"));
8675 algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
8676 } else {
8677 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(EDR)\n"));
8678 algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR;
8679 }
8680 break;
8681 }
8682 } else {
8683 RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO only\n"));
8684 algorithm = BT_2ANT_COEX_ALGO_SCO;
8685 }
8686 } else {
8687 RTPRINT(FBT, BT_TRACE, ("[BTCoex], non SCO\n"));
8688 switch (btInfo&0xe0) {
8689 case BT_INFO_HID:
8690 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID\n"));
8691 algorithm = BT_2ANT_COEX_ALGO_HID;
8692 break;
8693 case BT_INFO_A2DP:
8694 RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP\n"));
8695 algorithm = BT_2ANT_COEX_ALGO_A2DP;
8696 break;
8697 case BT_INFO_FTP:
8698 RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN(EDR)\n"));
8699 algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID;
8700 break;
8701 case (BT_INFO_HID | BT_INFO_A2DP):
8702 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP\n"));
8703 algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
8704 break;
8705 case (BT_INFO_HID|BT_INFO_FTP):
8706 if (bBtHsModeExist) {
8707 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(HS)\n"));
8708 algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
8709 } else {
8710 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(EDR)\n"));
8711 algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID;
8712 }
8713 break;
8714 case (BT_INFO_A2DP|BT_INFO_FTP):
8715 if (bBtHsModeExist) {
8716 RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(HS)\n"));
8717 algorithm = BT_2ANT_COEX_ALGO_A2DP;
8718 } else {
8719 RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(EDR)\n"));
8720 algorithm = BT_2ANT_COEX_ALGO_PANEDR_A2DP;
8721 }
8722 break;
8723 case (BT_INFO_HID|BT_INFO_A2DP|BT_INFO_FTP):
8724 if (bBtHsModeExist) {
8725 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(HS)\n"));
8726 algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
8727 } else {
8728 RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(EDR)\n"));
8729 algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR;
8730 }
8731 break;
8732 }
8733
8734 }
8735 } else {
8736 RTPRINT(FBT, BT_TRACE, ("[BTC2H], BTInfo: bConnect = false\n"));
8737 pBtdm8723->btStatus = BT_2ANT_BT_STATUS_IDLE;
8738 }
8739
8740 pBtdm8723->curAlgorithm = algorithm;
8741 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Algorithm = %d \n", pBtdm8723->curAlgorithm));
8742
8743/* From */
8744 BTDM_CheckWiFiState(padapter);
8745 if (pBtMgnt->ExtConfig.bManualControl) {
8746 RTPRINT(FBT, BT_TRACE, ("Action Manual control, won't execute bt coexist mechanism!!\n"));
8747 return;
8748 }
8749}
8750
8751void BTDM_2AntBtCoexist8723A(struct rtw_adapter *padapter)
8752{
8753 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
8754 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
8755 struct bt_dgb *pBtDbg = &pBTInfo->BtDbg;
8756 u8 btInfoOriginal = 0;
8757 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
8758 struct btdm_8723a_2ant *pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
8759
8760 if (BTDM_BtProfileSupport(padapter)) {
8761 if (pBtMgnt->ExtConfig.bHoldForBtOperation) {
8762 RTPRINT(FBT, BT_TRACE, ("Action for BT Operation adjust!!\n"));
8763 return;
8764 }
8765 if (pBtMgnt->ExtConfig.bHoldPeriodCnt) {
8766 RTPRINT(FBT, BT_TRACE, ("Hold BT inquiry/page scan setting (cnt = %d)!!\n",
8767 pBtMgnt->ExtConfig.bHoldPeriodCnt));
8768 if (pBtMgnt->ExtConfig.bHoldPeriodCnt >= 11) {
8769 pBtMgnt->ExtConfig.bHoldPeriodCnt = 0;
8770 /* next time the coexist parameters should be reset again. */
8771 } else {
8772 pBtMgnt->ExtConfig.bHoldPeriodCnt++;
8773 }
8774 return;
8775 }
8776
8777 if (pBtDbg->dbgCtrl)
8778 RTPRINT(FBT, BT_TRACE, ("[Dbg control], "));
8779
8780 pBtdm8723->curAlgorithm = btdm_ActionAlgorithm(padapter);
8781 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Algorithm = %d \n", pBtdm8723->curAlgorithm));
8782
8783 if (btdm_Is2Ant8723ACommonAction(padapter)) {
8784 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant common.\n"));
8785 pBtdm8723->bResetTdmaAdjust = true;
8786 } else {
8787 if (pBtdm8723->curAlgorithm != pBtdm8723->preAlgorithm) {
8788 RTPRINT(FBT, BT_TRACE, ("[BTCoex], preAlgorithm =%d, curAlgorithm =%d\n",
8789 pBtdm8723->preAlgorithm, pBtdm8723->curAlgorithm));
8790 pBtdm8723->bResetTdmaAdjust = true;
8791 }
8792 switch (pBtdm8723->curAlgorithm) {
8793 case BT_2ANT_COEX_ALGO_SCO:
8794 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = SCO.\n"));
8795 btdm_2Ant8723ASCOAction(padapter);
8796 break;
8797 case BT_2ANT_COEX_ALGO_HID:
8798 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID.\n"));
8799 btdm_2Ant8723AHIDAction(padapter);
8800 break;
8801 case BT_2ANT_COEX_ALGO_A2DP:
8802 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = A2DP.\n"));
8803 btdm_2Ant8723AA2DPAction(padapter);
8804 break;
8805 case BT_2ANT_COEX_ALGO_PANEDR:
8806 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR).\n"));
8807 btdm_2Ant8723APANEDRAction(padapter);
8808 break;
8809 case BT_2ANT_COEX_ALGO_PANHS:
8810 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HS mode.\n"));
8811 btdm_2Ant8723APANHSAction(padapter);
8812 break;
8813 case BT_2ANT_COEX_ALGO_PANEDR_A2DP:
8814 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN+A2DP.\n"));
8815 btdm_2Ant8723APANEDRA2DPAction(padapter);
8816 break;
8817 case BT_2ANT_COEX_ALGO_PANEDR_HID:
8818 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR)+HID.\n"));
8819 btdm_2Ant8723APANEDRHIDAction(padapter);
8820 break;
8821 case BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR:
8822 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP+PAN.\n"));
8823 btdm_2Ant8723AHIDA2DPPANEDRAction(padapter);
8824 break;
8825 case BT_2ANT_COEX_ALGO_HID_A2DP:
8826 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP.\n"));
8827 btdm_2Ant8723AHIDA2DPAction(padapter);
8828 break;
8829 default:
8830 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = 0.\n"));
8831 btdm_2Ant8723AA2DPAction(padapter);
8832 break;
8833 }
8834 pBtdm8723->preAlgorithm = pBtdm8723->curAlgorithm;
8835 }
8836 } else {
8837 RTPRINT(FBT, BT_TRACE, ("[BTCoex] Get bt info by fw!!\n"));
8838 /* msg shows c2h rsp for bt_info is received or not. */
8839 if (pHalData->bt_coexist.halCoex8723.bC2hBtInfoReqSent)
8840 RTPRINT(FBT, BT_TRACE, ("[BTCoex] c2h for btInfo not rcvd yet!!\n"));
8841
8842 btInfoOriginal = pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal;
8843
8844 if (pBtMgnt->ExtConfig.bHoldForBtOperation) {
8845 RTPRINT(FBT, BT_TRACE, ("Action for BT Operation adjust!!\n"));
8846 return;
8847 }
8848 if (pBtMgnt->ExtConfig.bHoldPeriodCnt) {
8849 RTPRINT(FBT, BT_TRACE,
8850 ("Hold BT inquiry/page scan setting (cnt = %d)!!\n",
8851 pBtMgnt->ExtConfig.bHoldPeriodCnt));
8852 if (pBtMgnt->ExtConfig.bHoldPeriodCnt >= 11) {
8853 pBtMgnt->ExtConfig.bHoldPeriodCnt = 0;
8854 /* next time the coexist parameters should be reset again. */
8855 } else {
8856 pBtMgnt->ExtConfig.bHoldPeriodCnt++;
8857 }
8858 return;
8859 }
8860
8861 if (pBtDbg->dbgCtrl)
8862 RTPRINT(FBT, BT_TRACE, ("[Dbg control], "));
8863 if (btdm_Is2Ant8723ACommonAction(padapter)) {
8864 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant common.\n"));
8865 pBtdm8723->bResetTdmaAdjust = true;
8866 } else {
8867 if (pBtdm8723->curAlgorithm != pBtdm8723->preAlgorithm) {
8868 RTPRINT(FBT, BT_TRACE,
8869 ("[BTCoex], preAlgorithm =%d, curAlgorithm =%d\n",
8870 pBtdm8723->preAlgorithm,
8871 pBtdm8723->curAlgorithm));
8872 pBtdm8723->bResetTdmaAdjust = true;
8873 }
8874 switch (pBtdm8723->curAlgorithm) {
8875 case BT_2ANT_COEX_ALGO_SCO:
8876 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = SCO.\n"));
8877 btdm_2Ant8723ASCOAction(padapter);
8878 break;
8879 case BT_2ANT_COEX_ALGO_HID:
8880 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID.\n"));
8881 btdm_2Ant8723AHIDAction(padapter);
8882 break;
8883 case BT_2ANT_COEX_ALGO_A2DP:
8884 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = A2DP.\n"));
8885 btdm_2Ant8723AA2dp(padapter);
8886 break;
8887 case BT_2ANT_COEX_ALGO_PANEDR:
8888 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR).\n"));
8889 btdm_2Ant8723APANEDRAction(padapter);
8890 break;
8891 case BT_2ANT_COEX_ALGO_PANHS:
8892 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HS mode.\n"));
8893 btdm_2Ant8723APANHSAction(padapter);
8894 break;
8895 case BT_2ANT_COEX_ALGO_PANEDR_A2DP:
8896 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN+A2DP.\n"));
8897 btdm_2Ant8723APANEDRA2DPAction(padapter);
8898 break;
8899 case BT_2ANT_COEX_ALGO_PANEDR_HID:
8900 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR)+HID.\n"));
8901 btdm_2Ant8723APANEDRHIDAction(padapter);
8902 break;
8903 case BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR:
8904 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP+PAN.\n"));
8905 btdm_2Ant8723AHIDA2DPPANEDRAction(padapter);
8906 break;
8907 case BT_2ANT_COEX_ALGO_HID_A2DP:
8908 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP.\n"));
8909 btdm_2Ant8723AHIDA2DPAction(padapter);
8910 break;
8911 default:
8912 RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = 0.\n"));
8913 btdm_2Ant8723AA2DPAction(padapter);
8914 break;
8915 }
8916 pBtdm8723->preAlgorithm = pBtdm8723->curAlgorithm;
8917 }
8918 }
8919}
8920
8921/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.c ===== */
8922#endif
8923
8924#ifdef __HALBTC8723_C__ /* HAL/BTCoexist/HalBtc8723.c */
8925/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc8723.c ===== */
8926
8927static u8 btCoexDbgBuf[BT_TMP_BUF_SIZE];
8928
8929static const char *const BtProfileString[] = {
8930 "NONE",
8931 "A2DP",
8932 "PAN",
8933 "HID",
8934 "SCO",
8935};
8936
8937static const char *const BtSpecString[] = {
8938 "1.0b",
8939 "1.1",
8940 "1.2",
8941 "2.0+EDR",
8942 "2.1+EDR",
8943 "3.0+HS",
8944 "4.0",
8945};
8946
8947static const char *const BtLinkRoleString[] = {
8948 "Master",
8949 "Slave",
8950};
8951
8952static u8 btdm_BtWifiAntNum(struct rtw_adapter *padapter)
8953{
8954 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
8955 struct bt_coexist_8723a *pBtCoex = &pHalData->bt_coexist.halCoex8723;
8956
8957 if (Ant_x2 == pHalData->bt_coexist.BT_Ant_Num) {
8958 if (Ant_x2 == pBtCoex->TotalAntNum)
8959 return Ant_x2;
8960 else
8961 return Ant_x1;
8962 } else {
8963 return Ant_x1;
8964 }
8965 return Ant_x2;
8966}
8967
8968static void btdm_BtHwCountersMonitor(struct rtw_adapter *padapter)
8969{
8970 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
8971 u32 regHPTxRx, regLPTxRx, u4Tmp;
8972 u32 regHPTx = 0, regHPRx = 0, regLPTx = 0, regLPRx = 0;
8973
8974 regHPTxRx = REG_HIGH_PRIORITY_TXRX;
8975 regLPTxRx = REG_LOW_PRIORITY_TXRX;
8976
8977 u4Tmp = rtw_read32(padapter, regHPTxRx);
8978 regHPTx = u4Tmp & bMaskLWord;
8979 regHPRx = (u4Tmp & bMaskHWord)>>16;
8980
8981 u4Tmp = rtw_read32(padapter, regLPTxRx);
8982 regLPTx = u4Tmp & bMaskLWord;
8983 regLPRx = (u4Tmp & bMaskHWord)>>16;
8984
8985 pHalData->bt_coexist.halCoex8723.highPriorityTx = regHPTx;
8986 pHalData->bt_coexist.halCoex8723.highPriorityRx = regHPRx;
8987 pHalData->bt_coexist.halCoex8723.lowPriorityTx = regLPTx;
8988 pHalData->bt_coexist.halCoex8723.lowPriorityRx = regLPRx;
8989
8990 RTPRINT(FBT, BT_TRACE, ("High Priority Tx/Rx = %d / %d\n", regHPTx, regHPRx));
8991 RTPRINT(FBT, BT_TRACE, ("Low Priority Tx/Rx = %d / %d\n", regLPTx, regLPRx));
8992
8993 /* reset counter */
8994 rtw_write8(padapter, 0x76e, 0xc);
8995}
8996
8997/* This function check if 8723 bt is disabled */
8998static void btdm_BtEnableDisableCheck8723A(struct rtw_adapter *padapter)
8999{
9000 u8 btAlife = true;
9001 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
9002
9003#ifdef CHECK_BT_EXIST_FROM_REG
9004 u8 val8;
9005
9006 /* ox68[28]= 1 => BT enable; otherwise disable */
9007 val8 = rtw_read8(padapter, 0x6B);
9008 if (!(val8 & BIT(4)))
9009 btAlife = false;
9010
9011 if (btAlife)
9012 pHalData->bt_coexist.bCurBtDisabled = false;
9013 else
9014 pHalData->bt_coexist.bCurBtDisabled = true;
9015#else
9016 if (pHalData->bt_coexist.halCoex8723.highPriorityTx == 0 &&
9017 pHalData->bt_coexist.halCoex8723.highPriorityRx == 0 &&
9018 pHalData->bt_coexist.halCoex8723.lowPriorityTx == 0 &&
9019 pHalData->bt_coexist.halCoex8723.lowPriorityRx == 0)
9020 btAlife = false;
9021 if (pHalData->bt_coexist.halCoex8723.highPriorityTx == 0xeaea &&
9022 pHalData->bt_coexist.halCoex8723.highPriorityRx == 0xeaea &&
9023 pHalData->bt_coexist.halCoex8723.lowPriorityTx == 0xeaea &&
9024 pHalData->bt_coexist.halCoex8723.lowPriorityRx == 0xeaea)
9025 btAlife = false;
9026 if (pHalData->bt_coexist.halCoex8723.highPriorityTx == 0xffff &&
9027 pHalData->bt_coexist.halCoex8723.highPriorityRx == 0xffff &&
9028 pHalData->bt_coexist.halCoex8723.lowPriorityTx == 0xffff &&
9029 pHalData->bt_coexist.halCoex8723.lowPriorityRx == 0xffff)
9030 btAlife = false;
9031 if (btAlife) {
9032 pHalData->bt_coexist.btActiveZeroCnt = 0;
9033 pHalData->bt_coexist.bCurBtDisabled = false;
9034 RTPRINT(FBT, BT_TRACE, ("8723A BT is enabled !!\n"));
9035 } else {
9036 pHalData->bt_coexist.btActiveZeroCnt++;
9037 RTPRINT(FBT, BT_TRACE, ("8723A bt all counters = 0, %d times!!\n",
9038 pHalData->bt_coexist.btActiveZeroCnt));
9039 if (pHalData->bt_coexist.btActiveZeroCnt >= 2) {
9040 pHalData->bt_coexist.bCurBtDisabled = true;
9041 RTPRINT(FBT, BT_TRACE, ("8723A BT is disabled !!\n"));
9042 }
9043 }
9044#endif
9045
9046 if (!pHalData->bt_coexist.bCurBtDisabled) {
9047 if (BTDM_IsWifiConnectionExist(padapter))
9048 BTDM_SetFwChnlInfo(padapter, RT_MEDIA_CONNECT);
9049 else
9050 BTDM_SetFwChnlInfo(padapter, RT_MEDIA_DISCONNECT);
9051 }
9052
9053 if (pHalData->bt_coexist.bPreBtDisabled !=
9054 pHalData->bt_coexist.bCurBtDisabled) {
9055 RTPRINT(FBT, BT_TRACE, ("8723A BT is from %s to %s!!\n",
9056 (pHalData->bt_coexist.bPreBtDisabled ? "disabled":"enabled"),
9057 (pHalData->bt_coexist.bCurBtDisabled ? "disabled":"enabled")));
9058 pHalData->bt_coexist.bPreBtDisabled = pHalData->bt_coexist.bCurBtDisabled;
9059 }
9060}
9061
9062static void btdm_BTCoexist8723AHandler(struct rtw_adapter *padapter)
9063{
9064 struct hal_data_8723a *pHalData;
9065
9066 pHalData = GET_HAL_DATA(padapter);
9067
9068 if (btdm_BtWifiAntNum(padapter) == Ant_x2) {
9069 RTPRINT(FBT, BT_TRACE, ("[BTCoex], 2 Ant mechanism\n"));
9070 BTDM_2AntBtCoexist8723A(padapter);
9071 } else {
9072 RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1 Ant mechanism\n"));
9073 BTDM_1AntBtCoexist8723A(padapter);
9074 }
9075
9076 if (!BTDM_IsSameCoexistState(padapter)) {
9077 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Coexist State[bitMap] change from 0x%"i64fmt"x to 0x%"i64fmt"x\n",
9078 pHalData->bt_coexist.PreviousState,
9079 pHalData->bt_coexist.CurrentState));
9080 pHalData->bt_coexist.PreviousState = pHalData->bt_coexist.CurrentState;
9081
9082 RTPRINT(FBT, BT_TRACE, ("["));
9083 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT30)
9084 RTPRINT(FBT, BT_TRACE, ("BT 3.0, "));
9085 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_HT20)
9086 RTPRINT(FBT, BT_TRACE, ("HT20, "));
9087 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_HT40)
9088 RTPRINT(FBT, BT_TRACE, ("HT40, "));
9089 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_LEGACY)
9090 RTPRINT(FBT, BT_TRACE, ("Legacy, "));
9091 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_LOW)
9092 RTPRINT(FBT, BT_TRACE, ("Rssi_Low, "));
9093 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_MEDIUM)
9094 RTPRINT(FBT, BT_TRACE, ("Rssi_Mid, "));
9095 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_HIGH)
9096 RTPRINT(FBT, BT_TRACE, ("Rssi_High, "));
9097 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_IDLE)
9098 RTPRINT(FBT, BT_TRACE, ("Wifi_Idle, "));
9099 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_UPLINK)
9100 RTPRINT(FBT, BT_TRACE, ("Wifi_Uplink, "));
9101 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_DOWNLINK)
9102 RTPRINT(FBT, BT_TRACE, ("Wifi_Downlink, "));
9103 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_IDLE)
9104 RTPRINT(FBT, BT_TRACE, ("BT_idle, "));
9105 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_HID)
9106 RTPRINT(FBT, BT_TRACE, ("PRO_HID, "));
9107 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_A2DP)
9108 RTPRINT(FBT, BT_TRACE, ("PRO_A2DP, "));
9109 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_PAN)
9110 RTPRINT(FBT, BT_TRACE, ("PRO_PAN, "));
9111 if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_SCO)
9112 RTPRINT(FBT, BT_TRACE, ("PRO_SCO, "));
9113 RTPRINT(FBT, BT_TRACE, ("]\n"));
9114 }
9115}
9116
9117/* extern function start with BTDM_ */
9118u32 BTDM_BtTxRxCounterH(struct rtw_adapter *padapter)
9119{
9120 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
9121 u32 counters = 0;
9122
9123 counters = pHalData->bt_coexist.halCoex8723.highPriorityTx+
9124 pHalData->bt_coexist.halCoex8723.highPriorityRx;
9125 return counters;
9126}
9127
9128u32 BTDM_BtTxRxCounterL(struct rtw_adapter *padapter)
9129{
9130 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
9131 u32 counters = 0;
9132
9133 counters = pHalData->bt_coexist.halCoex8723.lowPriorityTx+
9134 pHalData->bt_coexist.halCoex8723.lowPriorityRx ;
9135 return counters;
9136}
9137
9138void BTDM_SetFwChnlInfo(struct rtw_adapter *padapter, enum rt_media_status mstatus)
9139{
9140 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
9141 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
9142 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
9143 u8 H2C_Parameter[3] = {0};
9144 u8 chnl;
9145
9146 /* opMode */
9147 if (RT_MEDIA_CONNECT == mstatus)
9148 H2C_Parameter[0] = 0x1; /* 0: disconnected, 1:connected */
9149
9150 if (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)) {
9151 /* channel */
9152 chnl = pmlmeext->cur_channel;
9153 if (BTDM_IsHT40(padapter)) {
9154 if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
9155 chnl -= 2;
9156 else if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
9157 chnl += 2;
9158 }
9159 H2C_Parameter[1] = chnl;
9160 } else { /* check if HS link is exists */
9161 /* channel */
9162 if (BT_Operation(padapter))
9163 H2C_Parameter[1] = pBtMgnt->BTChannel;
9164 else
9165 H2C_Parameter[1] = pmlmeext->cur_channel;
9166 }
9167
9168 if (BTDM_IsHT40(padapter))
9169 H2C_Parameter[2] = 0x30;
9170 else
9171 H2C_Parameter[2] = 0x20;
9172
9173 FillH2CCmd(padapter, 0x19, 3, H2C_Parameter);
9174}
9175
9176u8 BTDM_IsWifiConnectionExist(struct rtw_adapter *padapter)
9177{
9178 u8 bRet = false;
9179
9180 if (BTHCI_HsConnectionEstablished(padapter))
9181 bRet = true;
9182
9183 if (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE) == true)
9184 bRet = true;
9185
9186 return bRet;
9187}
9188
9189void BTDM_SetFw3a(
9190 struct rtw_adapter *padapter,
9191 u8 byte1,
9192 u8 byte2,
9193 u8 byte3,
9194 u8 byte4,
9195 u8 byte5
9196 )
9197{
9198 u8 H2C_Parameter[5] = {0};
9199
9200 if (BTDM_1Ant8723A(padapter)) {
9201 if ((!check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE)) &&
9202 (get_fwstate(&padapter->mlmepriv) != WIFI_NULL_STATE)) {
9203 /* for softap mode */
9204 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
9205 struct bt_coexist_8723a *pBtCoex = &pHalData->bt_coexist.halCoex8723;
9206 u8 BtState = pBtCoex->c2hBtInfo;
9207
9208 if ((BtState != BT_INFO_STATE_NO_CONNECTION) &&
9209 (BtState != BT_INFO_STATE_CONNECT_IDLE)) {
9210 if (byte1 & BIT(4)) {
9211 byte1 &= ~BIT(4);
9212 byte1 |= BIT(5);
9213 }
9214
9215 byte5 |= BIT(5);
9216 if (byte5 & BIT(6))
9217 byte5 &= ~BIT(6);
9218 }
9219 }
9220 }
9221
9222 H2C_Parameter[0] = byte1;
9223 H2C_Parameter[1] = byte2;
9224 H2C_Parameter[2] = byte3;
9225 H2C_Parameter[3] = byte4;
9226 H2C_Parameter[4] = byte5;
9227
9228 RTPRINT(FBT, BT_TRACE, ("[BTCoex], FW write 0x3a(5bytes) = 0x%02x%08x\n",
9229 H2C_Parameter[0],
9230 H2C_Parameter[1]<<24|H2C_Parameter[2]<<16|H2C_Parameter[3]<<8|H2C_Parameter[4]));
9231
9232 FillH2CCmd(padapter, 0x3a, 5, H2C_Parameter);
9233}
9234
9235void BTDM_QueryBtInformation(struct rtw_adapter *padapter)
9236{
9237 u8 H2C_Parameter[1] = {0};
9238 struct hal_data_8723a *pHalData;
9239 struct bt_coexist_8723a *pBtCoex;
9240
9241 pHalData = GET_HAL_DATA(padapter);
9242 pBtCoex = &pHalData->bt_coexist.halCoex8723;
9243
9244 if (BT_IsBtDisabled(padapter)) {
9245 pBtCoex->c2hBtInfo = BT_INFO_STATE_DISABLED;
9246 pBtCoex->bC2hBtInfoReqSent = false;
9247 return;
9248 }
9249
9250 if (pBtCoex->c2hBtInfo == BT_INFO_STATE_DISABLED)
9251 pBtCoex->c2hBtInfo = BT_INFO_STATE_NO_CONNECTION;
9252
9253 if (pBtCoex->bC2hBtInfoReqSent == true)
9254 RTPRINT(FBT, BT_TRACE, ("[BTCoex], didn't recv previous BtInfo report!\n"));
9255 else
9256 pBtCoex->bC2hBtInfoReqSent = true;
9257
9258 H2C_Parameter[0] |= BIT(0); /* trigger */
9259
9260/*RTPRINT(FBT, BT_TRACE, ("[BTCoex], Query Bt information, write 0x38 = 0x%x\n", */
9261/*H2C_Parameter[0])); */
9262
9263 FillH2CCmd(padapter, 0x38, 1, H2C_Parameter);
9264}
9265
9266void BTDM_SetSwRfRxLpfCorner(struct rtw_adapter *padapter, u8 type)
9267{
9268 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
9269
9270 if (BT_RF_RX_LPF_CORNER_SHRINK == type) {
9271 /* Shrink RF Rx LPF corner */
9272 RTPRINT(FBT, BT_TRACE, ("Shrink RF Rx LPF corner!!\n"));
9273 PHY_SetRFReg(padapter, PathA, 0x1e, bRFRegOffsetMask, 0xf0ff7);
9274 pHalData->bt_coexist.bSWCoexistAllOff = false;
9275 } else if (BT_RF_RX_LPF_CORNER_RESUME == type) {
9276 /* Resume RF Rx LPF corner */
9277 RTPRINT(FBT, BT_TRACE, ("Resume RF Rx LPF corner!!\n"));
9278 PHY_SetRFReg(padapter, PathA, 0x1e, bRFRegOffsetMask, pHalData->bt_coexist.BtRfRegOrigin1E);
9279 }
9280}
9281
9282void
9283BTDM_SetSwPenaltyTxRateAdaptive(
9284 struct rtw_adapter *padapter,
9285 u8 raType
9286 )
9287{
9288 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
9289 u8 tmpU1;
9290
9291 tmpU1 = rtw_read8(padapter, 0x4fd);
9292 tmpU1 |= BIT(0);
9293 if (BT_TX_RATE_ADAPTIVE_LOW_PENALTY == raType) {
9294 tmpU1 &= ~BIT(2);
9295 pHalData->bt_coexist.bSWCoexistAllOff = false;
9296 } else if (BT_TX_RATE_ADAPTIVE_NORMAL == raType) {
9297 tmpU1 |= BIT(2);
9298 }
9299
9300 rtw_write8(padapter, 0x4fd, tmpU1);
9301}
9302
9303void BTDM_SetFwDecBtPwr(struct rtw_adapter *padapter, u8 bDecBtPwr)
9304{
9305 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
9306 u8 H2C_Parameter[1] = {0};
9307
9308 H2C_Parameter[0] = 0;
9309
9310 if (bDecBtPwr) {
9311 H2C_Parameter[0] |= BIT(1);
9312 pHalData->bt_coexist.bFWCoexistAllOff = false;
9313 }
9314
9315 RTPRINT(FBT, BT_TRACE, ("[BTCoex], decrease Bt Power : %s, write 0x21 = 0x%x\n",
9316 (bDecBtPwr ? "Yes!!" : "No!!"), H2C_Parameter[0]));
9317
9318 FillH2CCmd(padapter, 0x21, 1, H2C_Parameter);
9319}
9320
9321u8 BTDM_BtProfileSupport(struct rtw_adapter *padapter)
9322{
9323 u8 bRet = false;
9324 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
9325 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
9326 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
9327
9328 if (pBtMgnt->bSupportProfile &&
9329 !pHalData->bt_coexist.halCoex8723.bForceFwBtInfo)
9330 bRet = true;
9331
9332 return bRet;
9333}
9334
9335static void BTDM_AdjustForBtOperation8723A(struct rtw_adapter *padapter)
9336{
9337 /* BTDM_2AntAdjustForBtOperation8723(padapter); */
9338}
9339
9340static void BTDM_FwC2hBtRssi8723A(struct rtw_adapter *padapter, u8 *tmpBuf)
9341{
9342 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
9343 u8 percent = 0, u1tmp = 0;
9344
9345 u1tmp = tmpBuf[0];
9346 percent = u1tmp*2+10;
9347
9348 pHalData->bt_coexist.halCoex8723.btRssi = percent;
9349/*RTPRINT(FBT, BT_TRACE, ("[BTC2H], BT RSSI =%d\n", percent)); */
9350}
9351
9352static void
9353BTDM_FwC2hBtInfo8723A(struct rtw_adapter *padapter, u8 *tmpBuf, u8 length)
9354{
9355 struct hal_data_8723a *pHalData;
9356 struct bt_30info *pBTInfo;
9357 struct bt_mgnt *pBtMgnt;
9358 struct bt_coexist_8723a *pBtCoex;
9359 u8 i;
9360
9361 pHalData = GET_HAL_DATA(padapter);
9362 pBTInfo = GET_BT_INFO(padapter);
9363 pBtMgnt = &pBTInfo->BtMgnt;
9364 pBtCoex = &pHalData->bt_coexist.halCoex8723;
9365
9366 pBtCoex->bC2hBtInfoReqSent = false;
9367
9368 RTPRINT(FBT, BT_TRACE, ("[BTC2H], BT info[%d]=[", length));
9369
9370 pBtCoex->btRetryCnt = 0;
9371 for (i = 0; i < length; i++) {
9372 switch (i) {
9373 case 0:
9374 pBtCoex->c2hBtInfoOriginal = tmpBuf[i];
9375 break;
9376 case 1:
9377 pBtCoex->btRetryCnt = tmpBuf[i];
9378 break;
9379 case 2:
9380 BTDM_FwC2hBtRssi8723A(padapter, &tmpBuf[i]);
9381 break;
9382 case 3:
9383 pBtCoex->btInfoExt = tmpBuf[i]&BIT(0);
9384 break;
9385 }
9386
9387 if (i == length-1)
9388 RTPRINT(FBT, BT_TRACE, ("0x%02x]\n", tmpBuf[i]));
9389 else
9390 RTPRINT(FBT, BT_TRACE, ("0x%02x, ", tmpBuf[i]));
9391 }
9392 RTPRINT(FBT, BT_TRACE, ("[BTC2H], BT RSSI =%d\n", pBtCoex->btRssi));
9393 if (pBtCoex->btInfoExt)
9394 RTPRINT(FBT, BT_TRACE, ("[BTC2H], pBtCoex->btInfoExt =%x\n", pBtCoex->btInfoExt));
9395
9396 if (btdm_BtWifiAntNum(padapter) == Ant_x1)
9397 BTDM_1AntFwC2hBtInfo8723A(padapter);
9398 else
9399 BTDM_2AntFwC2hBtInfo8723A(padapter);
9400
9401 if (pBtMgnt->ExtConfig.bManualControl) {
9402 RTPRINT(FBT, BT_TRACE, ("%s: Action Manual control!!\n", __func__));
9403 return;
9404 }
9405
9406 btdm_BTCoexist8723AHandler(padapter);
9407}
9408
9409static void BTDM_Display8723ABtCoexInfo(struct rtw_adapter *padapter)
9410{
9411 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
9412 struct bt_coexist_8723a *pBtCoex = &pHalData->bt_coexist.halCoex8723;
9413 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
9414 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
9415 u8 u1Tmp, u1Tmp1, u1Tmp2, i, btInfoExt, psTdmaCase = 0;
9416 u32 u4Tmp[4];
9417 u8 antNum = Ant_x2;
9418
9419 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n ============[BT Coexist info]============");
9420 DCMD_Printf(btCoexDbgBuf);
9421
9422 if (!pHalData->bt_coexist.BluetoothCoexist) {
9423 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n BT not exists !!!");
9424 DCMD_Printf(btCoexDbgBuf);
9425 return;
9426 }
9427
9428 antNum = btdm_BtWifiAntNum(padapter);
9429 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d/%d ", "Ant mechanism PG/Now run :", \
9430 ((pHalData->bt_coexist.BT_Ant_Num == Ant_x2) ? 2 : 1), ((antNum == Ant_x2) ? 2 : 1));
9431 DCMD_Printf(btCoexDbgBuf);
9432
9433 if (pBtMgnt->ExtConfig.bManualControl) {
9434 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "[Action Manual control]!!");
9435 DCMD_Printf(btCoexDbgBuf);
9436 } else {
9437 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s / %d", "BT stack/ hci ext ver", \
9438 ((pBtMgnt->bSupportProfile) ? "Yes" : "No"), pBtMgnt->ExtConfig.HCIExtensionVer);
9439 DCMD_Printf(btCoexDbgBuf);
9440 }
9441
9442 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\n %-35s = / %d", "Dot11 channel / BT channel", \
9443 pBtMgnt->BTChannel);
9444 DCMD_Printf(btCoexDbgBuf);
9445
9446 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\n %-35s = %d / %d / %d", "Wifi/BT/HS rssi", \
9447 BTDM_GetRxSS(padapter),
9448 pHalData->bt_coexist.halCoex8723.btRssi,
9449 pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB);
9450 DCMD_Printf(btCoexDbgBuf);
9451
9452 if (!pBtMgnt->ExtConfig.bManualControl) {
9453 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\n %-35s = %s / %s ", "WIfi status",
9454 ((BTDM_Legacy(padapter)) ? "Legacy" : (((BTDM_IsHT40(padapter)) ? "HT40" : "HT20"))),
9455 ((!BTDM_IsWifiBusy(padapter)) ? "idle" : ((BTDM_IsWifiUplink(padapter)) ? "uplink" : "downlink")));
9456 DCMD_Printf(btCoexDbgBuf);
9457
9458 if (pBtMgnt->bSupportProfile) {
9459 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP",
9460 ((BTHCI_CheckProfileExist(padapter, BT_PROFILE_SCO)) ? 1 : 0),
9461 ((BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID)) ? 1 : 0),
9462 ((BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) ? 1 : 0),
9463 ((BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) ? 1 : 0));
9464 DCMD_Printf(btCoexDbgBuf);
9465
9466 for (i = 0; i < pBtMgnt->ExtConfig.NumberOfHandle; i++) {
9467 if (pBtMgnt->ExtConfig.HCIExtensionVer >= 1) {
9468 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s/ %s/ %s", "Bt link type/spec/role",
9469 BtProfileString[pBtMgnt->ExtConfig.linkInfo[i].BTProfile],
9470 BtSpecString[pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec],
9471 BtLinkRoleString[pBtMgnt->ExtConfig.linkInfo[i].linkRole]);
9472 DCMD_Printf(btCoexDbgBuf);
9473
9474 btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt;
9475 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s", "A2DP rate", \
9476 (btInfoExt&BIT0) ? "Basic rate" : "EDR rate");
9477 DCMD_Printf(btCoexDbgBuf);
9478 } else {
9479 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s/ %s", "Bt link type/spec", \
9480 BtProfileString[pBtMgnt->ExtConfig.linkInfo[i].BTProfile],
9481 BtSpecString[pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec]);
9482 DCMD_Printf(btCoexDbgBuf);
9483 }
9484 }
9485 }
9486 }
9487
9488 /* Sw mechanism */
9489 if (!pBtMgnt->ExtConfig.bManualControl) {
9490 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Sw BT Coex mechanism]============");
9491 DCMD_Printf(btCoexDbgBuf);
9492 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "AGC Table", \
9493 pBtCoex->btdm2Ant.bCurAgcTableEn);
9494 DCMD_Printf(btCoexDbgBuf);
9495 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "ADC Backoff", \
9496 pBtCoex->btdm2Ant.bCurAdcBackOff);
9497 DCMD_Printf(btCoexDbgBuf);
9498 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "Low penalty RA", \
9499 pBtCoex->btdm2Ant.bCurLowPenaltyRa);
9500 DCMD_Printf(btCoexDbgBuf);
9501 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "RF Rx LPF Shrink", \
9502 pBtCoex->btdm2Ant.bCurRfRxLpfShrink);
9503 DCMD_Printf(btCoexDbgBuf);
9504 }
9505 u4Tmp[0] = PHY_QueryRFReg(padapter, PathA, 0x1e, 0xff0);
9506 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x", "RF-A, 0x1e[11:4]/original val", \
9507 u4Tmp[0], pHalData->bt_coexist.BtRfRegOrigin1E);
9508 DCMD_Printf(btCoexDbgBuf);
9509
9510 /* Fw mechanism */
9511 if (!pBtMgnt->ExtConfig.bManualControl) {
9512 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Fw BT Coex mechanism]============");
9513 DCMD_Printf(btCoexDbgBuf);
9514 }
9515 if (!pBtMgnt->ExtConfig.bManualControl) {
9516 if (btdm_BtWifiAntNum(padapter) == Ant_x1)
9517 psTdmaCase = pHalData->bt_coexist.halCoex8723.btdm1Ant.curPsTdma;
9518 else
9519 psTdmaCase = pHalData->bt_coexist.halCoex8723.btdm2Ant.curPsTdma;
9520 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %02x %02x %02x %02x %02x case-%d", "PS TDMA(0x3a)", \
9521 pHalData->bt_coexist.fw3aVal[0], pHalData->bt_coexist.fw3aVal[1],
9522 pHalData->bt_coexist.fw3aVal[2], pHalData->bt_coexist.fw3aVal[3],
9523 pHalData->bt_coexist.fw3aVal[4], psTdmaCase);
9524 DCMD_Printf(btCoexDbgBuf);
9525
9526 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "Decrease Bt Power", \
9527 pBtCoex->btdm2Ant.bCurDecBtPwr);
9528 DCMD_Printf(btCoexDbgBuf);
9529 }
9530 u1Tmp = rtw_read8(padapter, 0x778);
9531 u1Tmp1 = rtw_read8(padapter, 0x783);
9532 u1Tmp2 = rtw_read8(padapter, 0x796);
9533 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x778/ 0x783/ 0x796", \
9534 u1Tmp, u1Tmp1, u1Tmp2);
9535 DCMD_Printf(btCoexDbgBuf);
9536
9537 if (!pBtMgnt->ExtConfig.bManualControl) {
9538 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x / 0x%x", "Sw DacSwing Ctrl/Val", \
9539 pBtCoex->btdm2Ant.bCurDacSwingOn, pBtCoex->btdm2Ant.curDacSwingLvl);
9540 DCMD_Printf(btCoexDbgBuf);
9541 }
9542 u4Tmp[0] = rtw_read32(padapter, 0x880);
9543 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x880", \
9544 u4Tmp[0]);
9545 DCMD_Printf(btCoexDbgBuf);
9546
9547 /* Hw mechanism */
9548 if (!pBtMgnt->ExtConfig.bManualControl) {
9549 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Hw BT Coex mechanism]============");
9550 DCMD_Printf(btCoexDbgBuf);
9551 }
9552
9553 u1Tmp = rtw_read8(padapter, 0x40);
9554 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x40", \
9555 u1Tmp);
9556 DCMD_Printf(btCoexDbgBuf);
9557
9558 u4Tmp[0] = rtw_read32(padapter, 0x550);
9559 u1Tmp = rtw_read8(padapter, 0x522);
9560 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/0x%x", "0x550(bcn contrl)/0x522", \
9561 u4Tmp[0], u1Tmp);
9562 DCMD_Printf(btCoexDbgBuf);
9563
9564 u4Tmp[0] = rtw_read32(padapter, 0x484);
9565 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x484(rate adaptive)", \
9566 u4Tmp[0]);
9567 DCMD_Printf(btCoexDbgBuf);
9568
9569 u4Tmp[0] = rtw_read32(padapter, 0x50);
9570 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0xc50(dig)", \
9571 u4Tmp[0]);
9572 DCMD_Printf(btCoexDbgBuf);
9573
9574 u4Tmp[0] = rtw_read32(padapter, 0xda0);
9575 u4Tmp[1] = rtw_read32(padapter, 0xda4);
9576 u4Tmp[2] = rtw_read32(padapter, 0xda8);
9577 u4Tmp[3] = rtw_read32(padapter, 0xdac);
9578 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0xda0/0xda4/0xda8/0xdac(FA cnt)", \
9579 u4Tmp[0], u4Tmp[1], u4Tmp[2], u4Tmp[3]);
9580 DCMD_Printf(btCoexDbgBuf);
9581
9582 u4Tmp[0] = rtw_read32(padapter, 0x6c0);
9583 u4Tmp[1] = rtw_read32(padapter, 0x6c4);
9584 u4Tmp[2] = rtw_read32(padapter, 0x6c8);
9585 u1Tmp = rtw_read8(padapter, 0x6cc);
9586 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x6c0/0x6c4/0x6c8/0x6cc(coexTable)", \
9587 u4Tmp[0], u4Tmp[1], u4Tmp[2], u1Tmp);
9588 DCMD_Printf(btCoexDbgBuf);
9589
9590 /* u4Tmp = rtw_read32(padapter, 0x770); */
9591 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d / %d", "0x770(Hi pri Rx[31:16]/Tx[15:0])", \
9592 pHalData->bt_coexist.halCoex8723.highPriorityRx,
9593 pHalData->bt_coexist.halCoex8723.highPriorityTx);
9594 DCMD_Printf(btCoexDbgBuf);
9595 /* u4Tmp = rtw_read32(padapter, 0x774); */
9596 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d / %d", "0x774(Lo pri Rx[31:16]/Tx[15:0])", \
9597 pHalData->bt_coexist.halCoex8723.lowPriorityRx,
9598 pHalData->bt_coexist.halCoex8723.lowPriorityTx);
9599 DCMD_Printf(btCoexDbgBuf);
9600
9601 /* Tx mgnt queue hang or not, 0x41b should = 0xf, ex: 0xd ==>hang */
9602 u1Tmp = rtw_read8(padapter, 0x41b);
9603 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x41b (hang chk == 0xf)", \
9604 u1Tmp);
9605 DCMD_Printf(btCoexDbgBuf);
9606 rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "lastHMEBoxNum", \
9607 pHalData->LastHMEBoxNum);
9608 DCMD_Printf(btCoexDbgBuf);
9609}
9610
9611static void
9612BTDM_8723ASignalCompensation(struct rtw_adapter *padapter,
9613 u8 *rssi_wifi, u8 *rssi_bt)
9614{
9615 if (btdm_BtWifiAntNum(padapter) == Ant_x1)
9616 BTDM_1AntSignalCompensation(padapter, rssi_wifi, rssi_bt);
9617}
9618
9619static void BTDM_8723AInit(struct rtw_adapter *padapter)
9620{
9621 if (btdm_BtWifiAntNum(padapter) == Ant_x2)
9622 BTDM_2AntParaInit(padapter);
9623 else
9624 BTDM_1AntParaInit(padapter);
9625}
9626
9627static void BTDM_HWCoexAllOff8723A(struct rtw_adapter *padapter)
9628{
9629 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
9630 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
9631
9632 if (pBtMgnt->ExtConfig.bManualControl)
9633 return;
9634
9635 if (btdm_BtWifiAntNum(padapter) == Ant_x2)
9636 BTDM_2AntHwCoexAllOff8723A(padapter);
9637}
9638
9639static void BTDM_FWCoexAllOff8723A(struct rtw_adapter *padapter)
9640{
9641 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
9642 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
9643
9644 if (pBtMgnt->ExtConfig.bManualControl)
9645 return;
9646
9647 if (btdm_BtWifiAntNum(padapter) == Ant_x2)
9648 BTDM_2AntFwCoexAllOff8723A(padapter);
9649}
9650
9651static void BTDM_SWCoexAllOff8723A(struct rtw_adapter *padapter)
9652{
9653 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
9654 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
9655
9656 if (pBtMgnt->ExtConfig.bManualControl)
9657 return;
9658
9659 if (btdm_BtWifiAntNum(padapter) == Ant_x2)
9660 BTDM_2AntSwCoexAllOff8723A(padapter);
9661}
9662
9663static void
9664BTDM_Set8723ABtCoexCurrAntNum(struct rtw_adapter *padapter, u8 antNum)
9665{
9666 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
9667 struct bt_coexist_8723a *pBtCoex = &pHalData->bt_coexist.halCoex8723;
9668
9669 if (antNum == 1)
9670 pBtCoex->TotalAntNum = Ant_x1;
9671 else if (antNum == 2)
9672 pBtCoex->TotalAntNum = Ant_x2;
9673}
9674
9675void BTDM_LpsLeave(struct rtw_adapter *padapter)
9676{
9677 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
9678 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
9679
9680 if (pBtMgnt->ExtConfig.bManualControl)
9681 return;
9682
9683 if (btdm_BtWifiAntNum(padapter) == Ant_x1)
9684 BTDM_1AntLpsLeave(padapter);
9685}
9686
9687static void BTDM_ForHalt8723A(struct rtw_adapter *padapter)
9688{
9689 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
9690 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
9691
9692 if (pBtMgnt->ExtConfig.bManualControl)
9693 return;
9694
9695 if (btdm_BtWifiAntNum(padapter) == Ant_x1)
9696 BTDM_1AntForHalt(padapter);
9697}
9698
9699static void BTDM_WifiScanNotify8723A(struct rtw_adapter *padapter, u8 scanType)
9700{
9701 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
9702 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
9703
9704 if (pBtMgnt->ExtConfig.bManualControl)
9705 return;
9706
9707 if (btdm_BtWifiAntNum(padapter) == Ant_x1)
9708 BTDM_1AntWifiScanNotify(padapter, scanType);
9709}
9710
9711static void
9712BTDM_WifiAssociateNotify8723A(struct rtw_adapter *padapter, u8 action)
9713{
9714 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
9715 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
9716
9717 if (pBtMgnt->ExtConfig.bManualControl)
9718 return;
9719
9720 if (btdm_BtWifiAntNum(padapter) == Ant_x1)
9721 BTDM_1AntWifiAssociateNotify(padapter, action);
9722}
9723
9724static void
9725BTDM_MediaStatusNotify8723A(struct rtw_adapter *padapter,
9726 enum rt_media_status mstatus)
9727{
9728 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
9729 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
9730
9731 RTPRINT(FBT, BT_TRACE, ("[BTCoex], MediaStatusNotify, %s\n",
9732 mstatus?"connect":"disconnect"));
9733
9734 BTDM_SetFwChnlInfo(padapter, mstatus);
9735
9736 if (pBtMgnt->ExtConfig.bManualControl)
9737 return;
9738
9739 if (btdm_BtWifiAntNum(padapter) == Ant_x1)
9740 BTDM_1AntMediaStatusNotify(padapter, mstatus);
9741}
9742
9743static void BTDM_ForDhcp8723A(struct rtw_adapter *padapter)
9744{
9745 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
9746 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
9747
9748 if (pBtMgnt->ExtConfig.bManualControl)
9749 return;
9750
9751 if (btdm_BtWifiAntNum(padapter) == Ant_x1)
9752 BTDM_1AntForDhcp(padapter);
9753}
9754
9755u8 BTDM_1Ant8723A(struct rtw_adapter *padapter)
9756{
9757 if (btdm_BtWifiAntNum(padapter) == Ant_x1)
9758 return true;
9759 else
9760 return false;
9761}
9762
9763static void BTDM_BTCoexist8723A(struct rtw_adapter *padapter)
9764{
9765 struct hal_data_8723a *pHalData;
9766 struct bt_30info *pBTInfo;
9767 struct bt_mgnt *pBtMgnt;
9768 struct bt_coexist_8723a *pBtCoex;
9769
9770 pHalData = GET_HAL_DATA(padapter);
9771 pBTInfo = GET_BT_INFO(padapter);
9772 pBtMgnt = &pBTInfo->BtMgnt;
9773 pBtCoex = &pHalData->bt_coexist.halCoex8723;
9774
9775 RTPRINT(FBT, BT_TRACE, ("[BTCoex], beacon RSSI = 0x%x(%d)\n",
9776 pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB,
9777 pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB));
9778
9779 btdm_BtHwCountersMonitor(padapter);
9780 btdm_BtEnableDisableCheck8723A(padapter);
9781
9782 if (pBtMgnt->ExtConfig.bManualControl) {
9783 RTPRINT(FBT, BT_TRACE, ("%s: Action Manual control!!\n", __func__));
9784 return;
9785 }
9786
9787 if (pBtCoex->bC2hBtInfoReqSent) {
9788 if (BT_IsBtDisabled(padapter)) {
9789 pBtCoex->c2hBtInfo = BT_INFO_STATE_DISABLED;
9790 } else {
9791 if (pBtCoex->c2hBtInfo == BT_INFO_STATE_DISABLED)
9792 pBtCoex->c2hBtInfo = BT_INFO_STATE_NO_CONNECTION;
9793 }
9794
9795 btdm_BTCoexist8723AHandler(padapter);
9796 } else if (BT_IsBtDisabled(padapter) == true) {
9797 pBtCoex->c2hBtInfo = BT_INFO_STATE_DISABLED;
9798 btdm_BTCoexist8723AHandler(padapter);
9799 }
9800
9801 BTDM_QueryBtInformation(padapter);
9802}
9803
9804/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc8723.c ===== */
9805#endif
9806
9807#ifdef __HALBTCCSR1ANT_C__ /* HAL/BTCoexist/HalBtcCsr1Ant.c */
9808/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.c ===== */
9809
9810/* local function start with btdm_ */
9811/* extern function start with BTDM_ */
9812
9813static void BTDM_SetAntenna(struct rtw_adapter *padapter, u8 who)
9814{
9815}
9816
9817void
9818BTDM_SingleAnt(
9819 struct rtw_adapter *padapter,
9820 u8 bSingleAntOn,
9821 u8 bInterruptOn,
9822 u8 bMultiNAVOn
9823 )
9824{
9825 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
9826 u8 H2C_Parameter[3] = {0};
9827
9828 if (pHalData->bt_coexist.BT_Ant_Num != Ant_x1)
9829 return;
9830
9831 H2C_Parameter[2] = 0;
9832 H2C_Parameter[1] = 0;
9833 H2C_Parameter[0] = 0;
9834
9835 if (bInterruptOn) {
9836 H2C_Parameter[2] |= 0x02; /* BIT1 */
9837 pHalData->bt_coexist.bFWCoexistAllOff = false;
9838 }
9839 pHalData->bt_coexist.bInterruptOn = bInterruptOn;
9840
9841 if (bSingleAntOn) {
9842 H2C_Parameter[2] |= 0x10; /* BIT4 */
9843 pHalData->bt_coexist.bFWCoexistAllOff = false;
9844 }
9845 pHalData->bt_coexist.bSingleAntOn = bSingleAntOn;
9846
9847 if (bMultiNAVOn) {
9848 H2C_Parameter[2] |= 0x20; /* BIT5 */
9849 pHalData->bt_coexist.bFWCoexistAllOff = false;
9850 }
9851 pHalData->bt_coexist.bMultiNAVOn = bMultiNAVOn;
9852
9853 RTPRINT(FBT, BT_TRACE, ("[DM][BT], SingleAntenna =[%s:%s:%s], write 0xe = 0x%x\n",
9854 bSingleAntOn?"ON":"OFF", bInterruptOn?"ON":"OFF", bMultiNAVOn?"ON":"OFF",
9855 H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2]));
9856}
9857
9858void BTDM_CheckBTIdleChange1Ant(struct rtw_adapter *padapter)
9859{
9860 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
9861 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
9862 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
9863/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
9864 u8 stateChange = false;
9865 u32 BT_Polling, Ratio_Act, Ratio_STA;
9866 u32 BT_Active, BT_State;
9867 u32 regBTActive = 0, regBTState = 0, regBTPolling = 0;
9868
9869 if (!pHalData->bt_coexist.BluetoothCoexist)
9870 return;
9871 if (pBtMgnt->ExtConfig.bManualControl)
9872 return;
9873 if (pHalData->bt_coexist.BT_CoexistType != BT_CSR_BC8)
9874 return;
9875 if (pHalData->bt_coexist.BT_Ant_Num != Ant_x1)
9876 return;
9877
9878 /* The following we only consider CSR BC8 and fw version should be >= 62 */
9879 RTPRINT(FBT, BT_TRACE, ("[DM][BT], FirmwareVersion = 0x%x(%d)\n",
9880 pHalData->FirmwareVersion, pHalData->FirmwareVersion));
9881 regBTActive = REG_BT_ACTIVE;
9882 regBTState = REG_BT_STATE;
9883 if (pHalData->FirmwareVersion >= FW_VER_BT_REG1)
9884 regBTPolling = REG_BT_POLLING1;
9885 else
9886 regBTPolling = REG_BT_POLLING;
9887
9888 BT_Active = rtw_read32(padapter, regBTActive);
9889 RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_Active(0x%x) =%x\n", regBTActive, BT_Active));
9890 BT_Active = BT_Active & 0x00ffffff;
9891
9892 BT_State = rtw_read32(padapter, regBTState);
9893 RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_State(0x%x) =%x\n", regBTState, BT_State));
9894 BT_State = BT_State & 0x00ffffff;
9895
9896 BT_Polling = rtw_read32(padapter, regBTPolling);
9897 RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_Polling(0x%x) =%x\n", regBTPolling, BT_Polling));
9898
9899 if (BT_Active == 0xffffffff && BT_State == 0xffffffff && BT_Polling == 0xffffffff)
9900 return;
9901 if (BT_Polling == 0)
9902 return;
9903
9904 Ratio_Act = BT_Active*1000/BT_Polling;
9905 Ratio_STA = BT_State*1000/BT_Polling;
9906
9907 pHalData->bt_coexist.Ratio_Tx = Ratio_Act;
9908 pHalData->bt_coexist.Ratio_PRI = Ratio_STA;
9909
9910 RTPRINT(FBT, BT_TRACE, ("[DM][BT], Ratio_Act =%d\n", Ratio_Act));
9911 RTPRINT(FBT, BT_TRACE, ("[DM][BT], Ratio_STA =%d\n", Ratio_STA));
9912
9913 if (Ratio_STA < 60 && Ratio_Act < 500) { /* BT PAN idle */
9914 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_IDLE;
9915 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_DOWNLINK;
9916 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK;
9917 } else {
9918 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_IDLE;
9919
9920 if (Ratio_STA) {
9921 /* Check if BT PAN (under BT 2.1) is uplink or downlink */
9922 if ((Ratio_Act/Ratio_STA) < 2) {
9923 /* BT PAN Uplink */
9924 pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic = true;
9925 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_UPLINK;
9926 pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic = false;
9927 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_DOWNLINK;
9928 } else {
9929 /* BT PAN downlink */
9930 pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic = false;
9931 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK;
9932 pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic = true;
9933 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_DOWNLINK;
9934 }
9935 } else {
9936 /* BT PAN downlink */
9937 pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic = false;
9938 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK;
9939 pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic = true;
9940 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_DOWNLINK;
9941 }
9942 }
9943
9944 /* Check BT is idle or not */
9945 if (pBtMgnt->ExtConfig.NumberOfHandle == 0 &&
9946 pBtMgnt->ExtConfig.NumberOfSCO == 0) {
9947 pBtMgnt->ExtConfig.bBTBusy = false;
9948 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE;
9949 } else {
9950 if (Ratio_STA < 60) {
9951 pBtMgnt->ExtConfig.bBTBusy = false;
9952 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE;
9953 } else {
9954 pBtMgnt->ExtConfig.bBTBusy = true;
9955 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_IDLE;
9956 }
9957 }
9958
9959 if (pBtMgnt->ExtConfig.NumberOfHandle == 0 &&
9960 pBtMgnt->ExtConfig.NumberOfSCO == 0) {
9961 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_RSSI_LOW;
9962 pBtMgnt->ExtConfig.MIN_BT_RSSI = 0;
9963 BTDM_SetAntenna(padapter, BTDM_ANT_BT_IDLE);
9964 } else {
9965 if (pBtMgnt->ExtConfig.MIN_BT_RSSI <= -5) {
9966 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_RSSI_LOW;
9967 RTPRINT(FBT, BT_TRACE, ("[DM][BT], core stack notify bt rssi Low\n"));
9968 } else {
9969 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_RSSI_LOW;
9970 RTPRINT(FBT, BT_TRACE, ("[DM][BT], core stack notify bt rssi Normal\n"));
9971 }
9972 }
9973
9974 if (pHalData->bt_coexist.bBTBusyTraffic != pBtMgnt->ExtConfig.bBTBusy) {
9975 /* BT idle or BT non-idle */
9976 pHalData->bt_coexist.bBTBusyTraffic = pBtMgnt->ExtConfig.bBTBusy;
9977 stateChange = true;
9978 }
9979
9980 if (stateChange) {
9981 if (!pBtMgnt->ExtConfig.bBTBusy)
9982 RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT is idle or disable\n"));
9983 else
9984 RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT is non-idle\n"));
9985 }
9986 if (!pBtMgnt->ExtConfig.bBTBusy) {
9987 RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT is idle or disable\n"));
9988 if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING|WIFI_SITE_MONITOR) == true)
9989 BTDM_SetAntenna(padapter, BTDM_ANT_WIFI);
9990 }
9991}
9992
9993/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.c ===== */
9994#endif
9995
9996#ifdef __HALBTCCSR2ANT_C__ /* HAL/BTCoexist/HalBtcCsr2Ant.c */
9997/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.c ===== */
9998
9999/* local function start with btdm_ */
10000
10001/* Note: */
10002/* In the following, FW should be done before SW mechanism. */
10003/* BTDM_Balance(), BTDM_DiminishWiFi(), BT_NAV() should be done */
10004/* before BTDM_AGCTable(), BTDM_BBBackOffLevel(), btdm_DacSwing(). */
10005
10006/* extern function start with BTDM_ */
10007
10008void
10009BTDM_DiminishWiFi(
10010 struct rtw_adapter *padapter,
10011 u8 bDACOn,
10012 u8 bInterruptOn,
10013 u8 DACSwingLevel,
10014 u8 bNAVOn
10015 )
10016{
10017 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10018 u8 H2C_Parameter[3] = {0};
10019
10020 if (pHalData->bt_coexist.BT_Ant_Num != Ant_x2)
10021 return;
10022
10023 if ((pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_RSSI_LOW) &&
10024 (DACSwingLevel == 0x20)) {
10025 RTPRINT(FBT, BT_TRACE, ("[BT]DiminishWiFi 0x20 original, but set 0x18 for Low RSSI!\n"));
10026 DACSwingLevel = 0x18;
10027 }
10028
10029 H2C_Parameter[2] = 0;
10030 H2C_Parameter[1] = DACSwingLevel;
10031 H2C_Parameter[0] = 0;
10032 if (bDACOn) {
10033 H2C_Parameter[2] |= 0x01; /* BIT0 */
10034 if (bInterruptOn)
10035 H2C_Parameter[2] |= 0x02; /* BIT1 */
10036 pHalData->bt_coexist.bFWCoexistAllOff = false;
10037 }
10038 if (bNAVOn) {
10039 H2C_Parameter[2] |= 0x08; /* BIT3 */
10040 pHalData->bt_coexist.bFWCoexistAllOff = false;
10041 }
10042
10043 RTPRINT(FBT, BT_TRACE, ("[DM][BT], bDACOn = %s, bInterruptOn = %s, write 0xe = 0x%x\n",
10044 bDACOn?"ON":"OFF", bInterruptOn?"ON":"OFF",
10045 H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2]));
10046 RTPRINT(FBT, BT_TRACE, ("[DM][BT], bNAVOn = %s\n",
10047 bNAVOn?"ON":"OFF"));
10048}
10049
10050/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.c ===== */
10051#endif
10052
10053#ifdef __HALBTCOEXIST_C__ /* HAL/BTCoexist/HalBtCoexist.c */
10054/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtCoexist.c ===== */
10055
10056/* local function */
10057static void btdm_ResetFWCoexState(struct rtw_adapter *padapter)
10058{
10059 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10060
10061 pHalData->bt_coexist.CurrentState = 0;
10062 pHalData->bt_coexist.PreviousState = 0;
10063}
10064
10065static void btdm_InitBtCoexistDM(struct rtw_adapter *padapter)
10066{
10067 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10068
10069 /* 20100415 Joseph: Restore RF register 0x1E and 0x1F value for further usage. */
10070 pHalData->bt_coexist.BtRfRegOrigin1E = PHY_QueryRFReg(padapter, PathA, RF_RCK1, bRFRegOffsetMask);
10071 pHalData->bt_coexist.BtRfRegOrigin1F = PHY_QueryRFReg(padapter, PathA, RF_RCK2, 0xf0);
10072
10073 pHalData->bt_coexist.CurrentState = 0;
10074 pHalData->bt_coexist.PreviousState = 0;
10075
10076 BTDM_8723AInit(padapter);
10077 pHalData->bt_coexist.bInitlized = true;
10078}
10079
10080/* */
10081/* extern function */
10082/* */
10083void BTDM_CheckAntSelMode(struct rtw_adapter *padapter)
10084{
10085}
10086
10087void BTDM_FwC2hBtRssi(struct rtw_adapter *padapter, u8 *tmpBuf)
10088{
10089 BTDM_FwC2hBtRssi8723A(padapter, tmpBuf);
10090}
10091
10092void BTDM_FwC2hBtInfo(struct rtw_adapter *padapter, u8 *tmpBuf, u8 length)
10093{
10094 BTDM_FwC2hBtInfo8723A(padapter, tmpBuf, length);
10095}
10096
10097void BTDM_DisplayBtCoexInfo(struct rtw_adapter *padapter)
10098{
10099 BTDM_Display8723ABtCoexInfo(padapter);
10100}
10101
10102void BTDM_RejectAPAggregatedPacket(struct rtw_adapter *padapter, u8 bReject)
10103{
10104}
10105
10106u8 BTDM_IsHT40(struct rtw_adapter *padapter)
10107{
10108 u8 isht40 = true;
10109 enum ht_channel_width bw;
10110
10111 bw = padapter->mlmeextpriv.cur_bwmode;
10112
10113 if (bw == HT_CHANNEL_WIDTH_20)
10114 isht40 = false;
10115 else if (bw == HT_CHANNEL_WIDTH_40)
10116 isht40 = true;
10117
10118 return isht40;
10119}
10120
10121u8 BTDM_Legacy(struct rtw_adapter *padapter)
10122{
10123 struct mlme_ext_priv *pmlmeext;
10124 u8 isLegacy = false;
10125
10126 pmlmeext = &padapter->mlmeextpriv;
10127 if ((pmlmeext->cur_wireless_mode == WIRELESS_11B) ||
10128 (pmlmeext->cur_wireless_mode == WIRELESS_11G) ||
10129 (pmlmeext->cur_wireless_mode == WIRELESS_11BG))
10130 isLegacy = true;
10131
10132 return isLegacy;
10133}
10134
10135void BTDM_CheckWiFiState(struct rtw_adapter *padapter)
10136{
10137 struct hal_data_8723a *pHalData;
10138 struct mlme_priv *pmlmepriv;
10139 struct bt_30info *pBTInfo;
10140 struct bt_mgnt *pBtMgnt;
10141
10142 pHalData = GET_HAL_DATA(padapter);
10143 pmlmepriv = &padapter->mlmepriv;
10144 pBTInfo = GET_BT_INFO(padapter);
10145 pBtMgnt = &pBTInfo->BtMgnt;
10146
10147 if (pmlmepriv->LinkDetectInfo.bBusyTraffic) {
10148 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_IDLE;
10149
10150 if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
10151 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_UPLINK;
10152 else
10153 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_UPLINK;
10154
10155 if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
10156 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_DOWNLINK;
10157 else
10158 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_DOWNLINK;
10159 } else {
10160 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_IDLE;
10161 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_UPLINK;
10162 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_DOWNLINK;
10163 }
10164
10165 if (BTDM_Legacy(padapter)) {
10166 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_LEGACY;
10167 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT20;
10168 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT40;
10169 } else {
10170 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_LEGACY;
10171 if (BTDM_IsHT40(padapter)) {
10172 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_HT40;
10173 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT20;
10174 } else {
10175 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_HT20;
10176 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT40;
10177 }
10178 }
10179
10180 if (pBtMgnt->BtOperationOn)
10181 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT30;
10182 else
10183 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT30;
10184}
10185
10186s32 BTDM_GetRxSS(struct rtw_adapter *padapter)
10187{
10188/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
10189 struct mlme_priv *pmlmepriv;
10190 struct hal_data_8723a *pHalData;
10191 s32 UndecoratedSmoothedPWDB = 0;
10192
10193 pmlmepriv = &padapter->mlmepriv;
10194 pHalData = GET_HAL_DATA(padapter);
10195
10196 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
10197 UndecoratedSmoothedPWDB = GET_UNDECORATED_AVERAGE_RSSI(padapter);
10198 } else { /* associated entry pwdb */
10199 UndecoratedSmoothedPWDB = pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB;
10200 /* pHalData->BT_EntryMinUndecoratedSmoothedPWDB */
10201 }
10202 RTPRINT(FBT, BT_TRACE, ("BTDM_GetRxSS() = %d\n", UndecoratedSmoothedPWDB));
10203 return UndecoratedSmoothedPWDB;
10204}
10205
10206static s32 BTDM_GetRxBeaconSS(struct rtw_adapter *padapter)
10207{
10208/*PMGNT_INFO pMgntInfo = &padapter->MgntInfo; */
10209 struct mlme_priv *pmlmepriv;
10210 struct hal_data_8723a *pHalData;
10211 s32 pwdbBeacon = 0;
10212
10213 pmlmepriv = &padapter->mlmepriv;
10214 pHalData = GET_HAL_DATA(padapter);
10215
10216 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
10217 /* pwdbBeacon = pHalData->dmpriv.UndecoratedSmoothedBeacon; */
10218 pwdbBeacon = pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB;
10219 }
10220 RTPRINT(FBT, BT_TRACE, ("BTDM_GetRxBeaconSS() = %d\n", pwdbBeacon));
10221 return pwdbBeacon;
10222}
10223
10224/* Get beacon rssi state */
10225u8 BTDM_CheckCoexBcnRssiState(struct rtw_adapter *padapter, u8 levelNum,
10226 u8 RssiThresh, u8 RssiThresh1)
10227{
10228 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10229 s32 pwdbBeacon = 0;
10230 u8 bcnRssiState = 0;
10231
10232 pwdbBeacon = BTDM_GetRxBeaconSS(padapter);
10233
10234 if (levelNum == 2) {
10235 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM;
10236
10237 if ((pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_LOW) ||
10238 (pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_STAY_LOW)) {
10239 if (pwdbBeacon >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) {
10240 bcnRssiState = BT_RSSI_STATE_HIGH;
10241 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH;
10242 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW;
10243 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to High\n"));
10244 } else {
10245 bcnRssiState = BT_RSSI_STATE_STAY_LOW;
10246 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at Low\n"));
10247 }
10248 } else {
10249 if (pwdbBeacon < RssiThresh) {
10250 bcnRssiState = BT_RSSI_STATE_LOW;
10251 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_LOW;
10252 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH;
10253 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Low\n"));
10254 } else {
10255 bcnRssiState = BT_RSSI_STATE_STAY_HIGH;
10256 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at High\n"));
10257 }
10258 }
10259 } else if (levelNum == 3) {
10260 if (RssiThresh > RssiThresh1) {
10261 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON thresh error!!\n"));
10262 return pHalData->bt_coexist.preRssiStateBeacon;
10263 }
10264
10265 if ((pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_LOW) ||
10266 (pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_STAY_LOW)) {
10267 if (pwdbBeacon >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) {
10268 bcnRssiState = BT_RSSI_STATE_MEDIUM;
10269 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM;
10270 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW;
10271 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH;
10272 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Medium\n"));
10273 } else {
10274 bcnRssiState = BT_RSSI_STATE_STAY_LOW;
10275 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at Low\n"));
10276 }
10277 } else if ((pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_MEDIUM) ||
10278 (pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_STAY_MEDIUM)) {
10279 if (pwdbBeacon >= (RssiThresh1+BT_FW_COEX_THRESH_TOL)) {
10280 bcnRssiState = BT_RSSI_STATE_HIGH;
10281 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH;
10282 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW;
10283 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM;
10284 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to High\n"));
10285 } else if (pwdbBeacon < RssiThresh) {
10286 bcnRssiState = BT_RSSI_STATE_LOW;
10287 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_LOW;
10288 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH;
10289 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM;
10290 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Low\n"));
10291 } else {
10292 bcnRssiState = BT_RSSI_STATE_STAY_MEDIUM;
10293 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at Medium\n"));
10294 }
10295 } else {
10296 if (pwdbBeacon < RssiThresh1) {
10297 bcnRssiState = BT_RSSI_STATE_MEDIUM;
10298 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM;
10299 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH;
10300 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW;
10301 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Medium\n"));
10302 } else {
10303 bcnRssiState = BT_RSSI_STATE_STAY_HIGH;
10304 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at High\n"));
10305 }
10306 }
10307 }
10308
10309 pHalData->bt_coexist.preRssiStateBeacon = bcnRssiState;
10310
10311 return bcnRssiState;
10312}
10313
10314u8 BTDM_CheckCoexRSSIState1(struct rtw_adapter *padapter, u8 levelNum,
10315 u8 RssiThresh, u8 RssiThresh1)
10316{
10317 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10318 s32 UndecoratedSmoothedPWDB = 0;
10319 u8 btRssiState = 0;
10320
10321 UndecoratedSmoothedPWDB = BTDM_GetRxSS(padapter);
10322
10323 if (levelNum == 2) {
10324 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
10325
10326 if ((pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_LOW) ||
10327 (pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_STAY_LOW)) {
10328 if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) {
10329 btRssiState = BT_RSSI_STATE_HIGH;
10330 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_HIGH;
10331 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
10332 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to High\n"));
10333 } else {
10334 btRssiState = BT_RSSI_STATE_STAY_LOW;
10335 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at Low\n"));
10336 }
10337 } else {
10338 if (UndecoratedSmoothedPWDB < RssiThresh) {
10339 btRssiState = BT_RSSI_STATE_LOW;
10340 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_LOW;
10341 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
10342 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Low\n"));
10343 } else {
10344 btRssiState = BT_RSSI_STATE_STAY_HIGH;
10345 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at High\n"));
10346 }
10347 }
10348 } else if (levelNum == 3) {
10349 if (RssiThresh > RssiThresh1) {
10350 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 thresh error!!\n"));
10351 return pHalData->bt_coexist.preRssiState1;
10352 }
10353
10354 if ((pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_LOW) ||
10355 (pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_STAY_LOW)) {
10356 if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) {
10357 btRssiState = BT_RSSI_STATE_MEDIUM;
10358 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
10359 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
10360 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
10361 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Medium\n"));
10362 } else {
10363 btRssiState = BT_RSSI_STATE_STAY_LOW;
10364 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at Low\n"));
10365 }
10366 } else if ((pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_MEDIUM) ||
10367 (pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_STAY_MEDIUM)) {
10368 if (UndecoratedSmoothedPWDB >= (RssiThresh1+BT_FW_COEX_THRESH_TOL)) {
10369 btRssiState = BT_RSSI_STATE_HIGH;
10370 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_HIGH;
10371 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
10372 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
10373 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to High\n"));
10374 } else if (UndecoratedSmoothedPWDB < RssiThresh) {
10375 btRssiState = BT_RSSI_STATE_LOW;
10376 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_LOW;
10377 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
10378 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
10379 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Low\n"));
10380 } else {
10381 btRssiState = BT_RSSI_STATE_STAY_MEDIUM;
10382 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at Medium\n"));
10383 }
10384 } else {
10385 if (UndecoratedSmoothedPWDB < RssiThresh1) {
10386 btRssiState = BT_RSSI_STATE_MEDIUM;
10387 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
10388 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
10389 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
10390 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Medium\n"));
10391 } else {
10392 btRssiState = BT_RSSI_STATE_STAY_HIGH;
10393 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at High\n"));
10394 }
10395 }
10396 }
10397
10398 pHalData->bt_coexist.preRssiState1 = btRssiState;
10399
10400 return btRssiState;
10401}
10402
10403u8 BTDM_CheckCoexRSSIState(struct rtw_adapter *padapter, u8 levelNum,
10404 u8 RssiThresh, u8 RssiThresh1)
10405{
10406 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10407 s32 UndecoratedSmoothedPWDB = 0;
10408 u8 btRssiState = 0;
10409
10410 UndecoratedSmoothedPWDB = BTDM_GetRxSS(padapter);
10411
10412 if (levelNum == 2) {
10413 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
10414
10415 if ((pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_LOW) ||
10416 (pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_STAY_LOW)) {
10417 if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) {
10418 btRssiState = BT_RSSI_STATE_HIGH;
10419 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_HIGH;
10420 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
10421 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to High\n"));
10422 } else {
10423 btRssiState = BT_RSSI_STATE_STAY_LOW;
10424 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at Low\n"));
10425 }
10426 } else {
10427 if (UndecoratedSmoothedPWDB < RssiThresh) {
10428 btRssiState = BT_RSSI_STATE_LOW;
10429 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_LOW;
10430 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
10431 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Low\n"));
10432 } else {
10433 btRssiState = BT_RSSI_STATE_STAY_HIGH;
10434 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at High\n"));
10435 }
10436 }
10437 } else if (levelNum == 3) {
10438 if (RssiThresh > RssiThresh1) {
10439 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI thresh error!!\n"));
10440 return pHalData->bt_coexist.preRssiState;
10441 }
10442
10443 if ((pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_LOW) ||
10444 (pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_STAY_LOW)) {
10445 if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL)) {
10446 btRssiState = BT_RSSI_STATE_MEDIUM;
10447 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_MEDIUM;
10448 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
10449 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
10450 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Medium\n"));
10451 } else {
10452 btRssiState = BT_RSSI_STATE_STAY_LOW;
10453 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at Low\n"));
10454 }
10455 } else if ((pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_MEDIUM) ||
10456 (pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_STAY_MEDIUM)) {
10457 if (UndecoratedSmoothedPWDB >= (RssiThresh1+BT_FW_COEX_THRESH_TOL)) {
10458 btRssiState = BT_RSSI_STATE_HIGH;
10459 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_HIGH;
10460 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
10461 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
10462 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to High\n"));
10463 } else if (UndecoratedSmoothedPWDB < RssiThresh) {
10464 btRssiState = BT_RSSI_STATE_LOW;
10465 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_LOW;
10466 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
10467 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
10468 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Low\n"));
10469 } else {
10470 btRssiState = BT_RSSI_STATE_STAY_MEDIUM;
10471 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at Medium\n"));
10472 }
10473 } else {
10474 if (UndecoratedSmoothedPWDB < RssiThresh1) {
10475 btRssiState = BT_RSSI_STATE_MEDIUM;
10476 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_MEDIUM;
10477 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
10478 pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
10479 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Medium\n"));
10480 } else {
10481 btRssiState = BT_RSSI_STATE_STAY_HIGH;
10482 RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at High\n"));
10483 }
10484 }
10485 }
10486
10487 pHalData->bt_coexist.preRssiState = btRssiState;
10488
10489 return btRssiState;
10490}
10491
10492u8 BTDM_DisableEDCATurbo(struct rtw_adapter *padapter)
10493{
10494 struct bt_mgnt *pBtMgnt;
10495 struct hal_data_8723a *pHalData;
10496 u8 bBtChangeEDCA = false;
10497 u32 EDCA_BT_BE = 0x5ea42b, cur_EDCA_reg;
10498 u8 bRet = false;
10499
10500 pHalData = GET_HAL_DATA(padapter);
10501 pBtMgnt = &pHalData->BtInfo.BtMgnt;
10502
10503 if (!pHalData->bt_coexist.BluetoothCoexist) {
10504 bRet = false;
10505 pHalData->bt_coexist.lastBtEdca = 0;
10506 return bRet;
10507 }
10508 if (!((pBtMgnt->bSupportProfile) ||
10509 (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8))) {
10510 bRet = false;
10511 pHalData->bt_coexist.lastBtEdca = 0;
10512 return bRet;
10513 }
10514
10515 if (BT_1Ant(padapter)) {
10516 bRet = false;
10517 pHalData->bt_coexist.lastBtEdca = 0;
10518 return bRet;
10519 }
10520
10521 if (pHalData->bt_coexist.exec_cnt < 3)
10522 pHalData->bt_coexist.exec_cnt++;
10523 else
10524 pHalData->bt_coexist.bEDCAInitialized = true;
10525
10526 /* When BT is non idle */
10527 if (!(pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_IDLE)) {
10528 RTPRINT(FBT, BT_TRACE, ("BT state non idle, set bt EDCA\n"));
10529
10530 /* aggr_num = 0x0909; */
10531 if (pHalData->odmpriv.DM_EDCA_Table.bCurrentTurboEDCA) {
10532 bBtChangeEDCA = true;
10533 pHalData->odmpriv.DM_EDCA_Table.bCurrentTurboEDCA = false;
10534 pHalData->dmpriv.prv_traffic_idx = 3;
10535 }
10536 cur_EDCA_reg = rtw_read32(padapter, REG_EDCA_BE_PARAM);
10537
10538 if (cur_EDCA_reg != EDCA_BT_BE)
10539 bBtChangeEDCA = true;
10540 if (bBtChangeEDCA || !pHalData->bt_coexist.bEDCAInitialized) {
10541 rtw_write32(padapter, REG_EDCA_BE_PARAM, EDCA_BT_BE);
10542 pHalData->bt_coexist.lastBtEdca = EDCA_BT_BE;
10543 }
10544 bRet = true;
10545 } else {
10546 RTPRINT(FBT, BT_TRACE, ("BT state idle, set original EDCA\n"));
10547 pHalData->bt_coexist.lastBtEdca = 0;
10548 bRet = false;
10549 }
10550 return bRet;
10551}
10552
10553void
10554BTDM_Balance(
10555 struct rtw_adapter *padapter,
10556 u8 bBalanceOn,
10557 u8 ms0,
10558 u8 ms1
10559 )
10560{
10561 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10562 u8 H2C_Parameter[3] = {0};
10563
10564 if (bBalanceOn) {
10565 H2C_Parameter[2] = 1;
10566 H2C_Parameter[1] = ms1;
10567 H2C_Parameter[0] = ms0;
10568 pHalData->bt_coexist.bFWCoexistAllOff = false;
10569 } else {
10570 H2C_Parameter[2] = 0;
10571 H2C_Parameter[1] = 0;
10572 H2C_Parameter[0] = 0;
10573 }
10574 pHalData->bt_coexist.bBalanceOn = bBalanceOn;
10575
10576 RTPRINT(FBT, BT_TRACE, ("[DM][BT], Balance =[%s:%dms:%dms], write 0xc = 0x%x\n",
10577 bBalanceOn?"ON":"OFF", ms0, ms1,
10578 H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2]));
10579
10580 FillH2CCmd(padapter, 0xc, 3, H2C_Parameter);
10581}
10582
10583void BTDM_AGCTable(struct rtw_adapter *padapter, u8 type)
10584{
10585 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10586 if (type == BT_AGCTABLE_OFF) {
10587 RTPRINT(FBT, BT_TRACE, ("[BT]AGCTable Off!\n"));
10588 rtw_write32(padapter, 0xc78, 0x641c0001);
10589 rtw_write32(padapter, 0xc78, 0x631d0001);
10590 rtw_write32(padapter, 0xc78, 0x621e0001);
10591 rtw_write32(padapter, 0xc78, 0x611f0001);
10592 rtw_write32(padapter, 0xc78, 0x60200001);
10593
10594 PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x32000);
10595 PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x71000);
10596 PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0xb0000);
10597 PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0xfc000);
10598 PHY_SetRFReg(padapter, PathA, RF_RX_G1, bRFRegOffsetMask, 0x30355);
10599
10600 pHalData->bt_coexist.b8723aAgcTableOn = false;
10601 } else if (type == BT_AGCTABLE_ON) {
10602 RTPRINT(FBT, BT_TRACE, ("[BT]AGCTable On!\n"));
10603 rtw_write32(padapter, 0xc78, 0x4e1c0001);
10604 rtw_write32(padapter, 0xc78, 0x4d1d0001);
10605 rtw_write32(padapter, 0xc78, 0x4c1e0001);
10606 rtw_write32(padapter, 0xc78, 0x4b1f0001);
10607 rtw_write32(padapter, 0xc78, 0x4a200001);
10608
10609 PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0xdc000);
10610 PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x90000);
10611 PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x51000);
10612 PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x12000);
10613 PHY_SetRFReg(padapter, PathA, RF_RX_G1, bRFRegOffsetMask, 0x00355);
10614
10615 pHalData->bt_coexist.b8723aAgcTableOn = true;
10616
10617 pHalData->bt_coexist.bSWCoexistAllOff = false;
10618 }
10619}
10620
10621void BTDM_BBBackOffLevel(struct rtw_adapter *padapter, u8 type)
10622{
10623 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10624
10625 if (type == BT_BB_BACKOFF_OFF) {
10626 RTPRINT(FBT, BT_TRACE, ("[BT]BBBackOffLevel Off!\n"));
10627 rtw_write32(padapter, 0xc04, 0x3a05611);
10628 } else if (type == BT_BB_BACKOFF_ON) {
10629 RTPRINT(FBT, BT_TRACE, ("[BT]BBBackOffLevel On!\n"));
10630 rtw_write32(padapter, 0xc04, 0x3a07611);
10631 pHalData->bt_coexist.bSWCoexistAllOff = false;
10632 }
10633}
10634
10635void BTDM_FWCoexAllOff(struct rtw_adapter *padapter)
10636{
10637 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);;
10638
10639 RTPRINT(FBT, BT_TRACE, ("BTDM_FWCoexAllOff()\n"));
10640 if (pHalData->bt_coexist.bFWCoexistAllOff)
10641 return;
10642 RTPRINT(FBT, BT_TRACE, ("BTDM_FWCoexAllOff(), real Do\n"));
10643
10644 BTDM_FWCoexAllOff8723A(padapter);
10645
10646 pHalData->bt_coexist.bFWCoexistAllOff = true;
10647}
10648
10649void BTDM_SWCoexAllOff(struct rtw_adapter *padapter)
10650{
10651 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);;
10652
10653 RTPRINT(FBT, BT_TRACE, ("BTDM_SWCoexAllOff()\n"));
10654 if (pHalData->bt_coexist.bSWCoexistAllOff)
10655 return;
10656 RTPRINT(FBT, BT_TRACE, ("BTDM_SWCoexAllOff(), real Do\n"));
10657 BTDM_SWCoexAllOff8723A(padapter);
10658
10659 pHalData->bt_coexist.bSWCoexistAllOff = true;
10660}
10661
10662void BTDM_HWCoexAllOff(struct rtw_adapter *padapter)
10663{
10664 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);;
10665
10666 RTPRINT(FBT, BT_TRACE, ("BTDM_HWCoexAllOff()\n"));
10667 if (pHalData->bt_coexist.bHWCoexistAllOff)
10668 return;
10669 RTPRINT(FBT, BT_TRACE, ("BTDM_HWCoexAllOff(), real Do\n"));
10670
10671 BTDM_HWCoexAllOff8723A(padapter);
10672
10673 pHalData->bt_coexist.bHWCoexistAllOff = true;
10674}
10675
10676void BTDM_CoexAllOff(struct rtw_adapter *padapter)
10677{
10678 BTDM_FWCoexAllOff(padapter);
10679 BTDM_SWCoexAllOff(padapter);
10680 BTDM_HWCoexAllOff(padapter);
10681}
10682
10683void BTDM_TurnOffBtCoexistBeforeEnterIPS(struct rtw_adapter *padapter)
10684{
10685 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10686 struct pwrctrl_priv *ppwrctrl = &padapter->pwrctrlpriv;
10687
10688 if (!pHalData->bt_coexist.BluetoothCoexist)
10689 return;
10690
10691 /* 8723 1Ant doesn't need to turn off bt coexist mechanism. */
10692 if (BTDM_1Ant8723A(padapter))
10693 return;
10694
10695 /* Before enter IPS, turn off FW BT Co-exist mechanism */
10696 if (ppwrctrl->reg_rfoff == rf_on) {
10697 RTPRINT(FBT, BT_TRACE, ("[BT][DM], Before enter IPS, turn off all Coexist DM\n"));
10698 btdm_ResetFWCoexState(padapter);
10699 BTDM_CoexAllOff(padapter);
10700 BTDM_SetAntenna(padapter, BTDM_ANT_BT);
10701 }
10702}
10703
10704void BTDM_SignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, u8 *rssi_bt)
10705{
10706 BTDM_8723ASignalCompensation(padapter, rssi_wifi, rssi_bt);
10707}
10708
10709void BTDM_Coexist(struct rtw_adapter *padapter)
10710{
10711 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10712
10713 if (!pHalData->bt_coexist.BluetoothCoexist) {
10714 RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT not exists!!\n"));
10715 return;
10716 }
10717
10718 if (!pHalData->bt_coexist.bInitlized) {
10719 RTPRINT(FBT, BT_TRACE, ("[DM][BT], btdm_InitBtCoexistDM()\n"));
10720 btdm_InitBtCoexistDM(padapter);
10721 }
10722
10723 RTPRINT(FBT, BT_TRACE, ("\n\n[DM][BT], BTDM start!!\n"));
10724
10725 BTDM_PWDBMonitor(padapter);
10726
10727 RTPRINT(FBT, BT_TRACE, ("[DM][BT], HW type is 8723\n"));
10728 BTDM_BTCoexist8723A(padapter);
10729 RTPRINT(FBT, BT_TRACE, ("[DM][BT], BTDM end!!\n\n"));
10730}
10731
10732void BTDM_UpdateCoexState(struct rtw_adapter *padapter)
10733{
10734 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10735
10736 if (!BTDM_IsSameCoexistState(padapter)) {
10737 RTPRINT(FBT, BT_TRACE, ("[BTCoex], Coexist State[bitMap] change from 0x%"i64fmt"x to 0x%"i64fmt"x, changeBits = 0x%"i64fmt"x\n",
10738 pHalData->bt_coexist.PreviousState,
10739 pHalData->bt_coexist.CurrentState,
10740 (pHalData->bt_coexist.PreviousState^pHalData->bt_coexist.CurrentState)));
10741 pHalData->bt_coexist.PreviousState = pHalData->bt_coexist.CurrentState;
10742 }
10743}
10744
10745u8 BTDM_IsSameCoexistState(struct rtw_adapter *padapter)
10746{
10747 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10748
10749 if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState) {
10750 return true;
10751 } else {
10752 RTPRINT(FBT, BT_TRACE, ("[DM][BT], Coexist state changed!!\n"));
10753 return false;
10754 }
10755}
10756
10757void BTDM_PWDBMonitor(struct rtw_adapter *padapter)
10758{
10759 struct bt_30info *pBTInfo = GET_BT_INFO(GetDefaultAdapter(padapter));
10760 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
10761 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10762 u8 H2C_Parameter[3] = {0};
10763 s32 tmpBTEntryMaxPWDB = 0, tmpBTEntryMinPWDB = 0xff;
10764 u8 i;
10765
10766 if (pBtMgnt->BtOperationOn) {
10767 for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) {
10768 if (pBTInfo->BtAsocEntry[i].bUsed) {
10769 if (pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB < tmpBTEntryMinPWDB)
10770 tmpBTEntryMinPWDB = pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB;
10771 if (pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB > tmpBTEntryMaxPWDB)
10772 tmpBTEntryMaxPWDB = pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB;
10773 /* Report every BT connection (HS mode) RSSI to FW */
10774 H2C_Parameter[2] = (u8)(pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB & 0xFF);
10775 H2C_Parameter[0] = (MAX_FW_SUPPORT_MACID_NUM-1-i);
10776 RTPRINT(FDM, DM_BT30, ("RSSI report for BT[%d], H2C_Par = 0x%x\n", i, H2C_Parameter[0]));
10777 FillH2CCmd(padapter, RSSI_SETTING_EID, 3, H2C_Parameter);
10778 RTPRINT_ADDR(FDM, (DM_PWDB|DM_BT30), ("BT_Entry Mac :"),
10779 pBTInfo->BtAsocEntry[i].BTRemoteMACAddr)
10780 RTPRINT(FDM, (DM_PWDB|DM_BT30),
10781 ("BT rx pwdb[%d] = 0x%x(%d)\n", i,
10782 pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB,
10783 pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB));
10784 }
10785 }
10786 if (tmpBTEntryMaxPWDB != 0) { /* If associated entry is found */
10787 pHalData->dmpriv.BT_EntryMaxUndecoratedSmoothedPWDB = tmpBTEntryMaxPWDB;
10788 RTPRINT(FDM, (DM_PWDB|DM_BT30), ("BT_EntryMaxPWDB = 0x%x(%d)\n",
10789 tmpBTEntryMaxPWDB, tmpBTEntryMaxPWDB));
10790 } else {
10791 pHalData->dmpriv.BT_EntryMaxUndecoratedSmoothedPWDB = 0;
10792 }
10793 if (tmpBTEntryMinPWDB != 0xff) { /* If associated entry is found */
10794 pHalData->dmpriv.BT_EntryMinUndecoratedSmoothedPWDB = tmpBTEntryMinPWDB;
10795 RTPRINT(FDM, (DM_PWDB|DM_BT30), ("BT_EntryMinPWDB = 0x%x(%d)\n",
10796 tmpBTEntryMinPWDB, tmpBTEntryMinPWDB));
10797 } else {
10798 pHalData->dmpriv.BT_EntryMinUndecoratedSmoothedPWDB = 0;
10799 }
10800 }
10801}
10802
10803u8 BTDM_IsBTBusy(struct rtw_adapter *padapter)
10804{
10805 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
10806 struct bt_mgnt *pBtMgnt = &pBTInfo->BtMgnt;
10807
10808 if (pBtMgnt->ExtConfig.bBTBusy)
10809 return true;
10810 else
10811 return false;
10812}
10813
10814u8 BTDM_IsWifiBusy(struct rtw_adapter *padapter)
10815{
10816/*PMGNT_INFO pMgntInfo = &GetDefaultAdapter(padapter)->MgntInfo; */
10817 struct mlme_priv *pmlmepriv = &GetDefaultAdapter(padapter)->mlmepriv;
10818 struct bt_30info *pBTInfo = GET_BT_INFO(padapter);
10819 struct bt_traffic *pBtTraffic = &pBTInfo->BtTraffic;
10820
10821 if (pmlmepriv->LinkDetectInfo.bBusyTraffic ||
10822 pBtTraffic->Bt30TrafficStatistics.bTxBusyTraffic ||
10823 pBtTraffic->Bt30TrafficStatistics.bRxBusyTraffic)
10824 return true;
10825 else
10826 return false;
10827}
10828
10829u8 BTDM_IsCoexistStateChanged(struct rtw_adapter *padapter)
10830{
10831 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10832
10833 if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
10834 return false;
10835 else
10836 return true;
10837}
10838
10839u8 BTDM_IsWifiUplink(struct rtw_adapter *padapter)
10840{
10841/*PMGNT_INFO pMgntInfo = &GetDefaultAdapter(padapter)->MgntInfo; */
10842 struct mlme_priv *pmlmepriv;
10843 struct bt_30info *pBTInfo;
10844 struct bt_traffic *pBtTraffic;
10845
10846 pmlmepriv = &padapter->mlmepriv;
10847 pBTInfo = GET_BT_INFO(padapter);
10848 pBtTraffic = &pBTInfo->BtTraffic;
10849
10850 if ((pmlmepriv->LinkDetectInfo.bTxBusyTraffic) ||
10851 (pBtTraffic->Bt30TrafficStatistics.bTxBusyTraffic))
10852 return true;
10853 else
10854 return false;
10855}
10856
10857u8 BTDM_IsWifiDownlink(struct rtw_adapter *padapter)
10858{
10859/*PMGNT_INFO pMgntInfo = &GetDefaultAdapter(padapter)->MgntInfo; */
10860 struct mlme_priv *pmlmepriv;
10861 struct bt_30info *pBTInfo;
10862 struct bt_traffic *pBtTraffic;
10863
10864 pmlmepriv = &padapter->mlmepriv;
10865 pBTInfo = GET_BT_INFO(padapter);
10866 pBtTraffic = &pBTInfo->BtTraffic;
10867
10868 if ((pmlmepriv->LinkDetectInfo.bRxBusyTraffic) ||
10869 (pBtTraffic->Bt30TrafficStatistics.bRxBusyTraffic))
10870 return true;
10871 else
10872 return false;
10873}
10874
10875u8 BTDM_IsBTHSMode(struct rtw_adapter *padapter)
10876{
10877/*PMGNT_INFO pMgntInfo = &GetDefaultAdapter(padapter)->MgntInfo; */
10878 struct hal_data_8723a *pHalData;
10879 struct bt_mgnt *pBtMgnt;
10880
10881 pHalData = GET_HAL_DATA(padapter);
10882 pBtMgnt = &pHalData->BtInfo.BtMgnt;
10883
10884 if (pBtMgnt->BtOperationOn)
10885 return true;
10886 else
10887 return false;
10888}
10889
10890u8 BTDM_IsBTUplink(struct rtw_adapter *padapter)
10891{
10892 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10893
10894 if (pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic)
10895 return true;
10896 else
10897 return false;
10898}
10899
10900u8 BTDM_IsBTDownlink(struct rtw_adapter *padapter)
10901{
10902 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10903
10904 if (pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic)
10905 return true;
10906 else
10907 return false;
10908}
10909
10910void BTDM_AdjustForBtOperation(struct rtw_adapter *padapter)
10911{
10912 RTPRINT(FBT, BT_TRACE, ("[BT][DM], BTDM_AdjustForBtOperation()\n"));
10913 BTDM_AdjustForBtOperation8723A(padapter);
10914}
10915
10916void BTDM_SetBtCoexCurrAntNum(struct rtw_adapter *padapter, u8 antNum)
10917{
10918 BTDM_Set8723ABtCoexCurrAntNum(padapter, antNum);
10919}
10920
10921void BTDM_ForHalt(struct rtw_adapter *padapter)
10922{
10923 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10924
10925 if (!pHalData->bt_coexist.BluetoothCoexist)
10926 return;
10927
10928 BTDM_ForHalt8723A(padapter);
10929 GET_HAL_DATA(padapter)->bt_coexist.bInitlized = false;
10930}
10931
10932void BTDM_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType)
10933{
10934 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10935
10936 if (!pHalData->bt_coexist.BluetoothCoexist)
10937 return;
10938
10939 BTDM_WifiScanNotify8723A(padapter, scanType);
10940}
10941
10942void BTDM_WifiAssociateNotify(struct rtw_adapter *padapter, u8 action)
10943{
10944 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10945
10946 if (!pHalData->bt_coexist.BluetoothCoexist)
10947 return;
10948
10949 BTDM_WifiAssociateNotify8723A(padapter, action);
10950}
10951
10952void BTDM_MediaStatusNotify(struct rtw_adapter *padapter, enum rt_media_status mstatus)
10953{
10954 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10955
10956 if (!pHalData->bt_coexist.BluetoothCoexist)
10957 return;
10958
10959 BTDM_MediaStatusNotify8723A(padapter, mstatus);
10960}
10961
10962void BTDM_ForDhcp(struct rtw_adapter *padapter)
10963{
10964 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10965
10966 if (!pHalData->bt_coexist.BluetoothCoexist)
10967 return;
10968
10969 BTDM_ForDhcp8723A(padapter);
10970}
10971
10972void BTDM_ResetActionProfileState(struct rtw_adapter *padapter)
10973{
10974 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
10975
10976 pHalData->bt_coexist.CurrentState &= ~\
10977 (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP|
10978 BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_SCO);
10979}
10980
10981u8 BTDM_IsActionSCO(struct rtw_adapter *padapter)
10982{
10983 struct hal_data_8723a *pHalData;
10984 struct bt_30info *pBTInfo;
10985 struct bt_mgnt *pBtMgnt;
10986 struct bt_dgb *pBtDbg;
10987 u8 bRet;
10988
10989 pHalData = GET_HAL_DATA(padapter);
10990 pBTInfo = GET_BT_INFO(padapter);
10991 pBtMgnt = &pBTInfo->BtMgnt;
10992 pBtDbg = &pBTInfo->BtDbg;
10993 bRet = false;
10994
10995 if (pBtDbg->dbgCtrl) {
10996 if (pBtDbg->dbgProfile == BT_DBG_PROFILE_SCO) {
10997 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_SCO;
10998 bRet = true;
10999 }
11000 } else {
11001 if (pBtMgnt->ExtConfig.NumberOfSCO > 0) {
11002 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_SCO;
11003 bRet = true;
11004 }
11005 }
11006 return bRet;
11007}
11008
11009u8 BTDM_IsActionHID(struct rtw_adapter *padapter)
11010{
11011 struct bt_30info *pBTInfo;
11012 struct hal_data_8723a *pHalData;
11013 struct bt_mgnt *pBtMgnt;
11014 struct bt_dgb *pBtDbg;
11015 u8 bRet;
11016
11017 pHalData = GET_HAL_DATA(padapter);
11018 pBTInfo = GET_BT_INFO(padapter);
11019 pBtMgnt = &pBTInfo->BtMgnt;
11020 pBtDbg = &pBTInfo->BtDbg;
11021 bRet = false;
11022
11023 if (pBtDbg->dbgCtrl) {
11024 if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID) {
11025 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_HID;
11026 bRet = true;
11027 }
11028 } else {
11029 if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) &&
11030 pBtMgnt->ExtConfig.NumberOfHandle == 1) {
11031 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_HID;
11032 bRet = true;
11033 }
11034 }
11035 return bRet;
11036}
11037
11038u8 BTDM_IsActionA2DP(struct rtw_adapter *padapter)
11039{
11040 struct hal_data_8723a *pHalData;
11041 struct bt_30info *pBTInfo;
11042 struct bt_mgnt *pBtMgnt;
11043 struct bt_dgb *pBtDbg;
11044 u8 bRet;
11045
11046 pHalData = GET_HAL_DATA(padapter);
11047 pBTInfo = GET_BT_INFO(padapter);
11048 pBtMgnt = &pBTInfo->BtMgnt;
11049 pBtDbg = &pBTInfo->BtDbg;
11050 bRet = false;
11051
11052 if (pBtDbg->dbgCtrl) {
11053 if (pBtDbg->dbgProfile == BT_DBG_PROFILE_A2DP) {
11054 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_A2DP;
11055 bRet = true;
11056 }
11057 } else {
11058 if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP) &&
11059 pBtMgnt->ExtConfig.NumberOfHandle == 1) {
11060 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_A2DP;
11061 bRet = true;
11062 }
11063 }
11064 return bRet;
11065}
11066
11067u8 BTDM_IsActionPAN(struct rtw_adapter *padapter)
11068{
11069 struct hal_data_8723a *pHalData;
11070 struct bt_30info *pBTInfo;
11071 struct bt_mgnt *pBtMgnt;
11072 struct bt_dgb *pBtDbg;
11073 u8 bRet;
11074
11075 pHalData = GET_HAL_DATA(padapter);
11076 pBTInfo = GET_BT_INFO(padapter);
11077 pBtMgnt = &pBTInfo->BtMgnt;
11078 pBtDbg = &pBTInfo->BtDbg;
11079 bRet = false;
11080
11081 if (pBtDbg->dbgCtrl) {
11082 if (pBtDbg->dbgProfile == BT_DBG_PROFILE_PAN) {
11083 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_PAN;
11084 bRet = true;
11085 }
11086 } else {
11087 if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) &&
11088 pBtMgnt->ExtConfig.NumberOfHandle == 1) {
11089 pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_PAN;
11090 bRet = true;
11091 }
11092 }
11093 return bRet;
11094}
11095
11096u8 BTDM_IsActionHIDA2DP(struct rtw_adapter *padapter)
11097{
11098 struct hal_data_8723a *pHalData;
11099 struct bt_30info *pBTInfo;
11100 struct bt_mgnt *pBtMgnt;
11101 struct bt_dgb *pBtDbg;
11102 u8 bRet;
11103
11104 pHalData = GET_HAL_DATA(padapter);
11105 pBTInfo = GET_BT_INFO(padapter);
11106 pBtMgnt = &pBTInfo->BtMgnt;
11107 pBtDbg = &pBTInfo->BtDbg;
11108 bRet = false;
11109
11110 if (pBtDbg->dbgCtrl) {
11111 if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID_A2DP) {
11112 pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP);
11113 bRet = true;
11114 }
11115 } else {
11116 if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) &&
11117 BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) {
11118 pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP);
11119 bRet = true;
11120 }
11121 }
11122 return bRet;
11123}
11124
11125u8 BTDM_IsActionHIDPAN(struct rtw_adapter *padapter)
11126{
11127 struct hal_data_8723a *pHalData;
11128 struct bt_30info *pBTInfo;
11129 struct bt_dgb *pBtDbg;
11130 u8 bRet;
11131
11132 pHalData = GET_HAL_DATA(padapter);
11133 pBTInfo = GET_BT_INFO(padapter);
11134 pBtDbg = &pBTInfo->BtDbg;
11135 bRet = false;
11136
11137 if (pBtDbg->dbgCtrl) {
11138 if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID_PAN) {
11139 pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_PAN);
11140 bRet = true;
11141 }
11142 } else {
11143 if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID) &&
11144 BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) {
11145 pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_PAN);
11146 bRet = true;
11147 }
11148 }
11149 return bRet;
11150}
11151
11152u8 BTDM_IsActionPANA2DP(struct rtw_adapter *padapter)
11153{
11154 struct hal_data_8723a *pHalData;
11155 struct bt_30info *pBTInfo;
11156 struct bt_dgb *pBtDbg;
11157 u8 bRet;
11158
11159 pHalData = GET_HAL_DATA(padapter);
11160 pBTInfo = GET_BT_INFO(padapter);
11161 pBtDbg = &pBTInfo->BtDbg;
11162 bRet = false;
11163
11164 if (pBtDbg->dbgCtrl) {
11165 if (pBtDbg->dbgProfile == BT_DBG_PROFILE_PAN_A2DP) {
11166 pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_A2DP);
11167 bRet = true;
11168 }
11169 } else {
11170 if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN) && BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) {
11171 pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_A2DP);
11172 bRet = true;
11173 }
11174 }
11175 return bRet;
11176}
11177
11178u8 BTDM_IsBtDisabled(struct rtw_adapter *padapter)
11179{
11180 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
11181
11182 if (pHalData->bt_coexist.bCurBtDisabled)
11183 return true;
11184 else
11185 return false;
11186}
11187
11188/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtCoexist.c ===== */
11189#endif
11190
11191#ifdef __HALBT_C__ /* HAL/HalBT.c */
11192/* ===== Below this line is sync from SD7 driver HAL/HalBT.c ===== */
11193
11194/* */
11195/*local function */
11196/* */
11197
11198static void halbt_InitHwConfig8723A(struct rtw_adapter *padapter)
11199{
11200}
11201
11202/* */
11203/*extern function */
11204/* */
11205u8 HALBT_GetPGAntNum(struct rtw_adapter *padapter)
11206{
11207 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
11208
11209 return pHalData->bt_coexist.BT_Ant_Num;
11210}
11211
11212void HALBT_SetKey(struct rtw_adapter *padapter, u8 EntryNum)
11213{
11214 struct bt_30info *pBTinfo;
11215 struct bt_asoc_entry *pBtAssocEntry;
11216 u16 usConfig = 0;
11217
11218 pBTinfo = GET_BT_INFO(padapter);
11219 pBtAssocEntry = &pBTinfo->BtAsocEntry[EntryNum];
11220
11221 pBtAssocEntry->HwCAMIndex = BT_HWCAM_STAR + EntryNum;
11222
11223 usConfig = CAM_VALID | (CAM_AES << 2);
11224 write_cam23a(padapter, pBtAssocEntry->HwCAMIndex, usConfig, pBtAssocEntry->BTRemoteMACAddr, pBtAssocEntry->PTK + TKIP_ENC_KEY_POS);
11225}
11226
11227void HALBT_RemoveKey(struct rtw_adapter *padapter, u8 EntryNum)
11228{
11229 struct bt_30info *pBTinfo;
11230 struct bt_asoc_entry *pBtAssocEntry;
11231
11232 pBTinfo = GET_BT_INFO(padapter);
11233 pBtAssocEntry = &pBTinfo->BtAsocEntry[EntryNum];
11234
11235 if (pBTinfo->BtAsocEntry[EntryNum].HwCAMIndex != 0) {
11236 /* ToDo : add New HALBT_RemoveKey function !! */
11237 if (pBtAssocEntry->HwCAMIndex >= BT_HWCAM_STAR && pBtAssocEntry->HwCAMIndex < HALF_CAM_ENTRY)
11238 CAM_empty_entry23a(padapter, pBtAssocEntry->HwCAMIndex);
11239 pBTinfo->BtAsocEntry[EntryNum].HwCAMIndex = 0;
11240 }
11241}
11242
11243void HALBT_InitBTVars8723A(struct rtw_adapter *padapter)
11244{
11245 struct hal_data_8723a *pHalData;
11246
11247 pHalData = GET_HAL_DATA(padapter);
11248
11249 pHalData->bt_coexist.BluetoothCoexist = pHalData->EEPROMBluetoothCoexist;
11250 pHalData->bt_coexist.BT_Ant_Num = pHalData->EEPROMBluetoothAntNum;
11251 pHalData->bt_coexist.BT_CoexistType = pHalData->EEPROMBluetoothType;
11252 pHalData->bt_coexist.BT_Ant_isolation = pHalData->EEPROMBluetoothAntIsolation;
11253 pHalData->bt_coexist.bt_radiosharedtype = pHalData->EEPROMBluetoothRadioShared;
11254
11255 RT_TRACE(_module_hal_init_c_, _drv_info_, ("BT Coexistance = 0x%x\n", pHalData->bt_coexist.BluetoothCoexist));
11256 if (pHalData->bt_coexist.BluetoothCoexist) {
11257 if (pHalData->bt_coexist.BT_Ant_Num == Ant_x2) {
11258 BTDM_SetBtCoexCurrAntNum(padapter, 2);
11259 RT_TRACE(_module_hal_init_c_, _drv_info_, ("BlueTooth BT_Ant_Num = Antx2\n"));
11260 } else if (pHalData->bt_coexist.BT_Ant_Num == Ant_x1) {
11261 BTDM_SetBtCoexCurrAntNum(padapter, 1);
11262 RT_TRACE(_module_hal_init_c_, _drv_info_, ("BlueTooth BT_Ant_Num = Antx1\n"));
11263 }
11264 pHalData->bt_coexist.bBTBusyTraffic = false;
11265 pHalData->bt_coexist.bBTTrafficModeSet = false;
11266 pHalData->bt_coexist.bBTNonTrafficModeSet = false;
11267 pHalData->bt_coexist.CurrentState = 0;
11268 pHalData->bt_coexist.PreviousState = 0;
11269
11270 RT_TRACE(_module_hal_init_c_, _drv_info_,
11271 ("bt_radiosharedType = 0x%x\n",
11272 pHalData->bt_coexist.bt_radiosharedtype));
11273 }
11274}
11275
11276u8 HALBT_IsBTExist(struct rtw_adapter *padapter)
11277{
11278 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
11279
11280 if (pHalData->bt_coexist.BluetoothCoexist)
11281 return true;
11282 else
11283 return false;
11284}
11285
11286u8 HALBT_BTChipType(struct rtw_adapter *padapter)
11287{
11288 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
11289
11290 return pHalData->bt_coexist.BT_CoexistType;
11291}
11292
11293void HALBT_InitHwConfig(struct rtw_adapter *padapter)
11294{
11295 halbt_InitHwConfig8723A(padapter);
11296 BTDM_Coexist(padapter);
11297}
11298
11299void HALBT_SetRtsCtsNoLenLimit(struct rtw_adapter *padapter)
11300{
11301}
11302
11303/* ===== End of sync from SD7 driver HAL/HalBT.c ===== */
11304#endif
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c b/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c
new file mode 100644
index 000000000000..0b205e1204fc
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_cmd.c
@@ -0,0 +1,845 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _RTL8723A_CMD_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <recv_osdep.h>
20#include <cmd_osdep.h>
21#include <mlme_osdep.h>
22#include <rtw_ioctl_set.h>
23#include <rtl8723a_hal.h>
24
25#define RTL92C_MAX_H2C_BOX_NUMS 4
26#define RTL92C_MAX_CMD_LEN 5
27#define MESSAGE_BOX_SIZE 4
28#define EX_MESSAGE_BOX_SIZE 2
29
30static u8 _is_fw_read_cmd_down(struct rtw_adapter *padapter, u8 msgbox_num)
31{
32 u8 read_down = false;
33 int retry_cnts = 100;
34 u8 valid;
35
36 do {
37 valid = rtw_read8(padapter, REG_HMETFR) & BIT(msgbox_num);
38 if (0 == valid)
39 read_down = true;
40 } while ((!read_down) && (retry_cnts--));
41
42 return read_down;
43}
44
45/*****************************************
46* H2C Msg format :
47*| 31 - 8 |7 | 6 - 0 |
48*| h2c_msg |Ext_bit |CMD_ID |
49*
50******************************************/
51s32 FillH2CCmd(struct rtw_adapter *padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer)
52{
53 u8 bcmd_down = false;
54 s32 retry_cnts = 100;
55 u8 h2c_box_num;
56 u32 msgbox_addr;
57 u32 msgbox_ex_addr;
58 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
59 u32 h2c_cmd = 0;
60 u16 h2c_cmd_ex = 0;
61 s32 ret = _FAIL;
62
63 padapter = GET_PRIMARY_ADAPTER(padapter);
64 pHalData = GET_HAL_DATA(padapter);
65
66 mutex_lock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex);
67
68 if (!pCmdBuffer)
69 goto exit;
70 if (CmdLen > RTL92C_MAX_CMD_LEN)
71 goto exit;
72 if (padapter->bSurpriseRemoved == true)
73 goto exit;
74
75 /* pay attention to if race condition happened in H2C cmd setting. */
76 do {
77 h2c_box_num = pHalData->LastHMEBoxNum;
78
79 if (!_is_fw_read_cmd_down(padapter, h2c_box_num)) {
80 DBG_8723A(" fw read cmd failed...\n");
81 goto exit;
82 }
83
84 if (CmdLen <= 3) {
85 memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer, CmdLen);
86 } else {
87 memcpy((u8 *)(&h2c_cmd_ex), pCmdBuffer, EX_MESSAGE_BOX_SIZE);
88 memcpy((u8 *)(&h2c_cmd)+1, pCmdBuffer+2, (CmdLen-EX_MESSAGE_BOX_SIZE));
89 *(u8 *)(&h2c_cmd) |= BIT(7);
90 }
91
92 *(u8 *)(&h2c_cmd) |= ElementID;
93
94 if (h2c_cmd & BIT(7)) {
95 msgbox_ex_addr = REG_HMEBOX_EXT_0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE);
96 h2c_cmd_ex = le16_to_cpu(h2c_cmd_ex);
97 rtw_write16(padapter, msgbox_ex_addr, h2c_cmd_ex);
98 }
99 msgbox_addr = REG_HMEBOX_0 + (h2c_box_num * MESSAGE_BOX_SIZE);
100 h2c_cmd = le32_to_cpu(h2c_cmd);
101 rtw_write32(padapter, msgbox_addr, h2c_cmd);
102
103 bcmd_down = true;
104
105 pHalData->LastHMEBoxNum = (h2c_box_num+1) % RTL92C_MAX_H2C_BOX_NUMS;
106
107 } while ((!bcmd_down) && (retry_cnts--));
108
109 ret = _SUCCESS;
110
111exit:
112 mutex_unlock(&adapter_to_dvobj(padapter)->h2c_fwcmd_mutex);
113 return ret;
114}
115
116u8 rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u8 *param)
117{
118 u8 res = _SUCCESS;
119
120 *((u32 *)param) = cpu_to_le32(*((u32 *)param));
121
122 FillH2CCmd(padapter, RSSI_SETTING_EID, 3, param);
123
124 return res;
125}
126
127u8 rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg)
128{
129 u8 buf[5];
130 u8 res = _SUCCESS;
131
132 memset(buf, 0, 5);
133 mask = cpu_to_le32(mask);
134 memcpy(buf, &mask, 4);
135 buf[4] = arg;
136
137 FillH2CCmd(padapter, MACID_CONFIG_EID, 5, buf);
138
139 return res;
140
141}
142
143/* bitmap[0:27] = tx_rate_bitmap */
144/* bitmap[28:31]= Rate Adaptive id */
145/* arg[0:4] = macid */
146/* arg[5] = Short GI */
147void rtl8723a_add_rateatid(struct rtw_adapter *pAdapter, u32 bitmap, u8 arg, u8 rssi_level)
148{
149 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
150 u8 macid = arg&0x1f;
151 u8 raid = (bitmap>>28) & 0x0f;
152
153 bitmap &= 0x0fffffff;
154 if (rssi_level != DM_RATR_STA_INIT)
155 bitmap = ODM_Get_Rate_Bitmap23a(&pHalData->odmpriv, macid, bitmap, rssi_level);
156
157 bitmap |= ((raid<<28)&0xf0000000);
158
159 if (pHalData->fw_ractrl == true) {
160 rtl8723a_set_raid_cmd(pAdapter, bitmap, arg);
161 } else {
162 u8 init_rate, shortGIrate = false;
163
164 init_rate = get_highest_rate_idx23a(bitmap&0x0fffffff)&0x3f;
165
166 shortGIrate = (arg&BIT(5)) ? true:false;
167
168 if (shortGIrate == true)
169 init_rate |= BIT(6);
170
171 rtw_write8(pAdapter, (REG_INIDATA_RATE_SEL+macid), (u8)init_rate);
172 }
173}
174
175void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter *padapter, u8 Mode)
176{
177 struct setpwrmode_parm H2CSetPwrMode;
178 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
179 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
180
181 DBG_8723A("%s: Mode =%d SmartPS =%d UAPSD =%d BcnMode = 0x%02x\n", __FUNCTION__,
182 Mode, pwrpriv->smart_ps, padapter->registrypriv.uapsd_enable, pwrpriv->bcn_ant_mode);
183
184 /* Forece leave RF low power mode for 1T1R to
185 prevent conficting setting in Fw power */
186 /* saving sequence. 2010.06.07. Added by tynli.
187 Suggested by SD3 yschang. */
188 if ((Mode != PS_MODE_ACTIVE) &&
189 (!IS_92C_SERIAL(pHalData->VersionID))) {
190 ODM_RF_Saving23a(&pHalData->odmpriv, true);
191 }
192
193 H2CSetPwrMode.Mode = Mode;
194 H2CSetPwrMode.SmartPS = pwrpriv->smart_ps;
195 H2CSetPwrMode.AwakeInterval = 1;
196 H2CSetPwrMode.bAllQueueUAPSD = padapter->registrypriv.uapsd_enable;
197 H2CSetPwrMode.BcnAntMode = pwrpriv->bcn_ant_mode;
198
199 FillH2CCmd(padapter, SET_PWRMODE_EID, sizeof(H2CSetPwrMode), (u8 *)&H2CSetPwrMode);
200
201}
202
203static void ConstructBeacon(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
204{
205 struct ieee80211_hdr *pwlanhdr;
206 u16 *fctrl;
207 u32 rate_len, pktlen;
208 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
209 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
210 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
211 u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
212
213 /* DBG_8723A("%s\n", __FUNCTION__); */
214
215 pwlanhdr = (struct ieee80211_hdr *)pframe;
216
217 fctrl = &pwlanhdr->frame_control;
218 *(fctrl) = 0;
219
220 memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
221 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
222 memcpy(pwlanhdr->addr3, get_my_bssid23a(cur_network), ETH_ALEN);
223
224 SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
225 /* pmlmeext->mgnt_seq++; */
226 SetFrameSubType(pframe, WIFI_BEACON);
227
228 pframe += sizeof(struct ieee80211_hdr_3addr);
229 pktlen = sizeof (struct ieee80211_hdr_3addr);
230
231 /* timestamp will be inserted by hardware */
232 pframe += 8;
233 pktlen += 8;
234
235 /* beacon interval: 2 bytes */
236 memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval23a_from_ie(cur_network->IEs)), 2);
237
238 pframe += 2;
239 pktlen += 2;
240
241 /* capability info: 2 bytes */
242 memcpy(pframe, (unsigned char *)(rtw_get_capability23a_from_ie(cur_network->IEs)), 2);
243
244 pframe += 2;
245 pktlen += 2;
246
247 if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
248 /* DBG_8723A("ie len =%d\n", cur_network->IELength); */
249 pktlen += cur_network->IELength - sizeof(struct ndis_802_11_fixed_ies);
250 memcpy(pframe, cur_network->IEs+sizeof(struct ndis_802_11_fixed_ies), pktlen);
251
252 goto _ConstructBeacon;
253 }
254
255 /* below for ad-hoc mode */
256
257 /* SSID */
258 pframe = rtw_set_ie23a(pframe, _SSID_IE_, cur_network->Ssid.ssid_len,
259 cur_network->Ssid.ssid, &pktlen);
260
261 /* supported rates... */
262 rate_len = rtw_get_rateset_len23a(cur_network->SupportedRates);
263 pframe = rtw_set_ie23a(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ?
264 8 : rate_len), cur_network->SupportedRates, &pktlen);
265
266 /* DS parameter set */
267 pframe = rtw_set_ie23a(pframe, _DSSET_IE_, 1, (unsigned char *)&cur_network->Configuration.DSConfig, &pktlen);
268
269 if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
270 u32 ATIMWindow;
271 /* IBSS Parameter Set... */
272 /* ATIMWindow = cur->Configuration.ATIMWindow; */
273 ATIMWindow = 0;
274 pframe = rtw_set_ie23a(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
275 }
276
277 /* todo: ERP IE */
278
279 /* EXTERNDED SUPPORTED RATE */
280 if (rate_len > 8)
281 pframe = rtw_set_ie23a(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
282
283 /* todo:HT for adhoc */
284
285_ConstructBeacon:
286
287 if ((pktlen + TXDESC_SIZE) > 512) {
288 DBG_8723A("beacon frame too large\n");
289 return;
290 }
291
292 *pLength = pktlen;
293
294 /* DBG_8723A("%s bcn_sz =%d\n", __FUNCTION__, pktlen); */
295
296}
297
298static void ConstructPSPoll(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength)
299{
300 struct ieee80211_hdr *pwlanhdr;
301 u16 *fctrl;
302 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
303 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
304
305 pwlanhdr = (struct ieee80211_hdr *)pframe;
306
307 /* Frame control. */
308 fctrl = &pwlanhdr->frame_control;
309 *(fctrl) = 0;
310 SetPwrMgt(fctrl);
311 SetFrameSubType(pframe, WIFI_PSPOLL);
312
313 /* AID. */
314 SetDuration(pframe, (pmlmeinfo->aid | 0xc000));
315
316 /* BSSID. */
317 memcpy(pwlanhdr->addr1, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
318
319 /* TA. */
320 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
321
322 *pLength = 16;
323}
324
325static void ConstructNullFunctionData(
326 struct rtw_adapter *padapter,
327 u8 *pframe,
328 u32 *pLength,
329 u8 *StaAddr,
330 u8 bQoS,
331 u8 AC,
332 u8 bEosp,
333 u8 bForcePowerSave)
334{
335 struct ieee80211_hdr *pwlanhdr;
336 u16 *fctrl;
337 u32 pktlen;
338 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
339 struct wlan_network *cur_network = &pmlmepriv->cur_network;
340 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
341 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
342
343 pwlanhdr = (struct ieee80211_hdr *)pframe;
344
345 fctrl = &pwlanhdr->frame_control;
346 *(fctrl) = 0;
347 if (bForcePowerSave)
348 SetPwrMgt(fctrl);
349
350 switch (cur_network->network.InfrastructureMode) {
351 case Ndis802_11Infrastructure:
352 SetToDs(fctrl);
353 memcpy(pwlanhdr->addr1,
354 get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
355 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv),
356 ETH_ALEN);
357 memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN);
358 break;
359 case Ndis802_11APMode:
360 SetFrDs(fctrl);
361 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
362 memcpy(pwlanhdr->addr2,
363 get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
364 memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv),
365 ETH_ALEN);
366 break;
367 case Ndis802_11IBSS:
368 default:
369 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
370 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
371 memcpy(pwlanhdr->addr3,
372 get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
373 break;
374 }
375
376 SetSeqNum(pwlanhdr, 0);
377
378 if (bQoS == true) {
379 struct ieee80211_qos_hdr *pwlanqoshdr;
380
381 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
382
383 pwlanqoshdr = (struct ieee80211_qos_hdr *)pframe;
384 SetPriority(&pwlanqoshdr->qos_ctrl, AC);
385 SetEOSP(&pwlanqoshdr->qos_ctrl, bEosp);
386
387 pktlen = sizeof(struct ieee80211_qos_hdr);
388 } else {
389 SetFrameSubType(pframe, WIFI_DATA_NULL);
390
391 pktlen = sizeof(struct ieee80211_hdr_3addr);
392 }
393
394 *pLength = pktlen;
395}
396
397static void ConstructProbeRsp(struct rtw_adapter *padapter, u8 *pframe, u32 *pLength, u8 *StaAddr, bool bHideSSID)
398{
399 struct ieee80211_hdr *pwlanhdr;
400 u16 *fctrl;
401 u8 *mac, *bssid;
402 u32 pktlen;
403 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
404 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
405 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
406
407 /* DBG_8723A("%s\n", __FUNCTION__); */
408
409 pwlanhdr = (struct ieee80211_hdr *)pframe;
410
411 mac = myid(&padapter->eeprompriv);
412 bssid = cur_network->MacAddress;
413
414 fctrl = &pwlanhdr->frame_control;
415 *(fctrl) = 0;
416 memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN);
417 memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
418 memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
419
420 SetSeqNum(pwlanhdr, 0);
421 SetFrameSubType(fctrl, WIFI_PROBERSP);
422
423 pktlen = sizeof(struct ieee80211_hdr_3addr);
424 pframe += pktlen;
425
426 if (cur_network->IELength > MAX_IE_SZ)
427 return;
428
429 memcpy(pframe, cur_network->IEs, cur_network->IELength);
430 pframe += cur_network->IELength;
431 pktlen += cur_network->IELength;
432
433 *pLength = pktlen;
434}
435
436/* To check if reserved page content is destroyed by beacon beacuse beacon is too large. */
437void CheckFwRsvdPageContent23a(struct rtw_adapter *Adapter)
438{
439}
440
441/* */
442/* Description: Fill the reserved packets that FW will use to RSVD page. */
443/* Now we just send 4 types packet to rsvd page. */
444/* (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp. */
445/* Input: */
446/* bDLFinished - false: At the first time we will send all the packets as a large packet to Hw, */
447/* so we need to set the packet length to total lengh. */
448/* true: At the second time, we should send the first packet (default:beacon) */
449/* to Hw again and set the lengh in descriptor to the real beacon lengh. */
450/* 2009.10.15 by tynli. */
451static void SetFwRsvdPagePkt(struct rtw_adapter *padapter, bool bDLFinished)
452{
453 struct hal_data_8723a *pHalData;
454 struct xmit_frame *pmgntframe;
455 struct pkt_attrib *pattrib;
456 struct xmit_priv *pxmitpriv;
457 struct mlme_ext_priv *pmlmeext;
458 struct mlme_ext_info *pmlmeinfo;
459 u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength;
460 u32 NullDataLength, QosNullLength, BTQosNullLength;
461 u8 *ReservedPagePacket;
462 u8 PageNum, PageNeed, TxDescLen;
463 u16 BufIndex;
464 u32 TotalPacketLen;
465 struct rsvdpage_loc RsvdPageLoc;
466
467 DBG_8723A("%s\n", __FUNCTION__);
468
469 ReservedPagePacket = kzalloc(1000, GFP_KERNEL);
470 if (ReservedPagePacket == NULL) {
471 DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
472 return;
473 }
474
475 pHalData = GET_HAL_DATA(padapter);
476 pxmitpriv = &padapter->xmitpriv;
477 pmlmeext = &padapter->mlmeextpriv;
478 pmlmeinfo = &pmlmeext->mlmext_info;
479
480 TxDescLen = TXDESC_SIZE;
481 PageNum = 0;
482
483 /* 3 (1) beacon */
484 BufIndex = TXDESC_OFFSET;
485 ConstructBeacon(padapter, &ReservedPagePacket[BufIndex], &BeaconLength);
486
487 /* When we count the first page size, we need to reserve description size for the RSVD */
488 /* packet, it will be filled in front of the packet in TXPKTBUF. */
489 PageNeed = (u8)PageNum_128(TxDescLen + BeaconLength);
490 /* To reserved 2 pages for beacon buffer. 2010.06.24. */
491 if (PageNeed == 1)
492 PageNeed += 1;
493 PageNum += PageNeed;
494 pHalData->FwRsvdPageStartOffset = PageNum;
495
496 BufIndex += PageNeed*128;
497
498 /* 3 (2) ps-poll */
499 RsvdPageLoc.LocPsPoll = PageNum;
500 ConstructPSPoll(padapter, &ReservedPagePacket[BufIndex], &PSPollLength);
501 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], PSPollLength, true, false);
502
503 PageNeed = (u8)PageNum_128(TxDescLen + PSPollLength);
504 PageNum += PageNeed;
505
506 BufIndex += PageNeed*128;
507
508 /* 3 (3) null data */
509 RsvdPageLoc.LocNullData = PageNum;
510 ConstructNullFunctionData(
511 padapter,
512 &ReservedPagePacket[BufIndex],
513 &NullDataLength,
514 get_my_bssid23a(&pmlmeinfo->network),
515 false, 0, 0, false);
516 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
517
518 PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
519 PageNum += PageNeed;
520
521 BufIndex += PageNeed*128;
522
523 /* 3 (4) probe response */
524 RsvdPageLoc.LocProbeRsp = PageNum;
525 ConstructProbeRsp(
526 padapter,
527 &ReservedPagePacket[BufIndex],
528 &ProbeRspLength,
529 get_my_bssid23a(&pmlmeinfo->network),
530 false);
531 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, false, false);
532
533 PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength);
534 PageNum += PageNeed;
535
536 BufIndex += PageNeed*128;
537
538 /* 3 (5) Qos null data */
539 RsvdPageLoc.LocQosNull = PageNum;
540 ConstructNullFunctionData(
541 padapter,
542 &ReservedPagePacket[BufIndex],
543 &QosNullLength,
544 get_my_bssid23a(&pmlmeinfo->network),
545 true, 0, 0, false);
546 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false);
547
548 PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength);
549 PageNum += PageNeed;
550
551 BufIndex += PageNeed*128;
552
553 /* 3 (6) BT Qos null data */
554 RsvdPageLoc.LocBTQosNull = PageNum;
555 ConstructNullFunctionData(
556 padapter,
557 &ReservedPagePacket[BufIndex],
558 &BTQosNullLength,
559 get_my_bssid23a(&pmlmeinfo->network),
560 true, 0, 0, false);
561 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
562
563 TotalPacketLen = BufIndex + BTQosNullLength;
564
565 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
566 if (pmgntframe == NULL)
567 goto exit;
568
569 /* update attribute */
570 pattrib = &pmgntframe->attrib;
571 update_mgntframe_attrib23a(padapter, pattrib);
572 pattrib->qsel = 0x10;
573 pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
574 memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
575
576 rtw_hal_mgnt_xmit23a(padapter, pmgntframe);
577
578 DBG_8723A("%s: Set RSVD page location to Fw\n", __FUNCTION__);
579 FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
580
581exit:
582 kfree(ReservedPagePacket);
583}
584
585void rtl8723a_set_FwJoinBssReport_cmd(struct rtw_adapter *padapter, u8 mstatus)
586{
587 struct joinbssrpt_parm JoinBssRptParm;
588 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
589 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
590 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
591
592 DBG_8723A("%s mstatus(%x)\n", __FUNCTION__, mstatus);
593
594 if (mstatus == 1) {
595 bool bRecover = false;
596 u8 v8;
597
598 /* We should set AID, correct TSF, HW seq enable before set JoinBssReport to Fw in 88/92C. */
599 /* Suggested by filen. Added by tynli. */
600 rtw_write16(padapter, REG_BCN_PSR_RPT, (0xC000|pmlmeinfo->aid));
601 /* Do not set TSF again here or vWiFi beacon DMA INT will not work. */
602 /* correct_TSF23a(padapter, pmlmeext); */
603 /* Hw sequende enable by dedault. 2010.06.23. by tynli. */
604 /* rtw_write16(padapter, REG_NQOS_SEQ, ((pmlmeext->mgnt_seq+100)&0xFFF)); */
605 /* rtw_write8(padapter, REG_HWSEQ_CTRL, 0xFF); */
606
607 /* set REG_CR bit 8 */
608 v8 = rtw_read8(padapter, REG_CR+1);
609 v8 |= BIT(0); /* ENSWBCN */
610 rtw_write8(padapter, REG_CR+1, v8);
611
612 /* Disable Hw protection for a time which revserd for Hw sending beacon. */
613 /* Fix download reserved page packet fail that access collision with the protection time. */
614 /* 2010.05.11. Added by tynli. */
615/* SetBcnCtrlReg23a(padapter, 0, BIT(3)); */
616/* SetBcnCtrlReg23a(padapter, BIT(4), 0); */
617 SetBcnCtrlReg23a(padapter, BIT(4), BIT(3));
618
619 /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
620 if (pHalData->RegFwHwTxQCtrl & BIT(6))
621 bRecover = true;
622
623 /* To tell Hw the packet is not a real beacon frame. */
624 /* U1bTmp = rtw_read8(padapter, REG_FWHW_TXQ_CTRL+2); */
625 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl & ~BIT(6));
626 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
627 SetFwRsvdPagePkt(padapter, 0);
628
629 /* 2010.05.11. Added by tynli. */
630 SetBcnCtrlReg23a(padapter, BIT(3), BIT(4));
631
632 /* To make sure that if there exists an adapter which would like to send beacon. */
633 /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
634 /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
635 /* the beacon cannot be sent by HW. */
636 /* 2010.06.23. Added by tynli. */
637 if (bRecover) {
638 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl | BIT(6));
639 pHalData->RegFwHwTxQCtrl |= BIT(6);
640 }
641
642 /* Clear CR[8] or beacon packet will not be send to TxBuf anymore. */
643 v8 = rtw_read8(padapter, REG_CR+1);
644 v8 &= ~BIT(0); /* ~ENSWBCN */
645 rtw_write8(padapter, REG_CR+1, v8);
646 }
647
648 JoinBssRptParm.OpMode = mstatus;
649
650 FillH2CCmd(padapter, JOINBSS_RPT_EID, sizeof(JoinBssRptParm), (u8 *)&JoinBssRptParm);
651
652}
653
654#ifdef CONFIG_8723AU_BT_COEXIST
655static void SetFwRsvdPagePkt_BTCoex(struct rtw_adapter *padapter)
656{
657 struct hal_data_8723a *pHalData;
658 struct xmit_frame *pmgntframe;
659 struct pkt_attrib *pattrib;
660 struct xmit_priv *pxmitpriv;
661 struct mlme_ext_priv *pmlmeext;
662 struct mlme_ext_info *pmlmeinfo;
663 u8 fakemac[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x00};
664 u32 NullDataLength, BTQosNullLength;
665 u8 *ReservedPagePacket;
666 u8 PageNum, PageNeed, TxDescLen;
667 u16 BufIndex;
668 u32 TotalPacketLen;
669 struct rsvdpage_loc RsvdPageLoc;
670
671 DBG_8723A("+%s\n", __FUNCTION__);
672
673 ReservedPagePacket = kzalloc(1024, GFP_KERNEL);
674 if (ReservedPagePacket == NULL) {
675 DBG_8723A("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
676 return;
677 }
678
679 pHalData = GET_HAL_DATA(padapter);
680 pxmitpriv = &padapter->xmitpriv;
681 pmlmeext = &padapter->mlmeextpriv;
682 pmlmeinfo = &pmlmeext->mlmext_info;
683
684 TxDescLen = TXDESC_SIZE;
685 PageNum = 0;
686
687 /* 3 (1) beacon */
688 BufIndex = TXDESC_OFFSET;
689 /* skip Beacon Packet */
690 PageNeed = 3;
691
692 PageNum += PageNeed;
693 pHalData->FwRsvdPageStartOffset = PageNum;
694
695 BufIndex += PageNeed*128;
696
697 /* 3 (3) null data */
698 RsvdPageLoc.LocNullData = PageNum;
699 ConstructNullFunctionData(
700 padapter,
701 &ReservedPagePacket[BufIndex],
702 &NullDataLength,
703 fakemac,
704 false, 0, 0, false);
705 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false);
706
707 PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength);
708 PageNum += PageNeed;
709
710 BufIndex += PageNeed*128;
711
712 /* 3 (6) BT Qos null data */
713 RsvdPageLoc.LocBTQosNull = PageNum;
714 ConstructNullFunctionData(
715 padapter,
716 &ReservedPagePacket[BufIndex],
717 &BTQosNullLength,
718 fakemac,
719 true, 0, 0, false);
720 rtl8723a_fill_fake_txdesc(padapter, &ReservedPagePacket[BufIndex-TxDescLen], BTQosNullLength, false, true);
721
722 TotalPacketLen = BufIndex + BTQosNullLength;
723
724 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
725 if (pmgntframe == NULL)
726 goto exit;
727
728 /* update attribute */
729 pattrib = &pmgntframe->attrib;
730 update_mgntframe_attrib23a(padapter, pattrib);
731 pattrib->qsel = 0x10;
732 pattrib->pktlen = pattrib->last_txcmdsz = TotalPacketLen - TXDESC_OFFSET;
733 memcpy(pmgntframe->buf_addr, ReservedPagePacket, TotalPacketLen);
734
735 rtw_hal_mgnt_xmit23a(padapter, pmgntframe);
736
737 DBG_8723A("%s: Set RSVD page location to Fw\n", __FUNCTION__);
738 FillH2CCmd(padapter, RSVD_PAGE_EID, sizeof(RsvdPageLoc), (u8 *)&RsvdPageLoc);
739
740exit:
741 kfree(ReservedPagePacket);
742}
743
744void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(struct rtw_adapter *padapter)
745{
746 struct hal_data_8723a *pHalData;
747 u8 bRecover = false;
748
749 DBG_8723A("+%s\n", __FUNCTION__);
750
751 pHalData = GET_HAL_DATA(padapter);
752
753 /* Set FWHW_TXQ_CTRL 0x422[6]= 0 to tell Hw the packet is not a real beacon frame. */
754 if (pHalData->RegFwHwTxQCtrl & BIT(6))
755 bRecover = true;
756
757 /* To tell Hw the packet is not a real beacon frame. */
758 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
759 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
760 SetFwRsvdPagePkt_BTCoex(padapter);
761
762 /* To make sure that if there exists an adapter which would like to send beacon. */
763 /* If exists, the origianl value of 0x422[6] will be 1, we should check this to */
764 /* prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
765 /* the beacon cannot be sent by HW. */
766 /* 2010.06.23. Added by tynli. */
767 if (bRecover) {
768 pHalData->RegFwHwTxQCtrl |= BIT(6);
769 rtw_write8(padapter, REG_FWHW_TXQ_CTRL+2, pHalData->RegFwHwTxQCtrl);
770 }
771}
772#endif
773
774#ifdef CONFIG_8723AU_P2P
775void rtl8723a_set_p2p_ps_offload_cmd(struct rtw_adapter *padapter, u8 p2p_ps_state)
776{
777 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
778 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
779 struct P2P_PS_Offload_t *p2p_ps_offload = &pHalData->p2p_ps_offload;
780 u8 i;
781
782 switch (p2p_ps_state) {
783 case P2P_PS_DISABLE:
784 DBG_8723A("P2P_PS_DISABLE \n");
785 memset(p2p_ps_offload, 0, 1);
786 break;
787 case P2P_PS_ENABLE:
788 DBG_8723A("P2P_PS_ENABLE \n");
789 /* update CTWindow value. */
790 if (pwdinfo->ctwindow > 0) {
791 p2p_ps_offload->CTWindow_En = 1;
792 rtw_write8(padapter, REG_P2P_CTWIN, pwdinfo->ctwindow);
793 }
794
795 /* hw only support 2 set of NoA */
796 for (i = 0; i < pwdinfo->noa_num; i++) {
797 /* To control the register setting for which NOA */
798 rtw_write8(padapter, REG_NOA_DESC_SEL, (i << 4));
799 if (i == 0)
800 p2p_ps_offload->NoA0_En = 1;
801 else
802 p2p_ps_offload->NoA1_En = 1;
803
804 /* config P2P NoA Descriptor Register */
805 rtw_write32(padapter, REG_NOA_DESC_DURATION, pwdinfo->noa_duration[i]);
806
807 rtw_write32(padapter, REG_NOA_DESC_INTERVAL, pwdinfo->noa_interval[i]);
808
809 rtw_write32(padapter, REG_NOA_DESC_START, pwdinfo->noa_start_time[i]);
810
811 rtw_write8(padapter, REG_NOA_DESC_COUNT, pwdinfo->noa_count[i]);
812 }
813
814 if ((pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0)) {
815 /* rst p2p circuit */
816 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(4));
817
818 p2p_ps_offload->Offload_En = 1;
819
820 if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
821 p2p_ps_offload->role = 1;
822 p2p_ps_offload->AllStaSleep = 0;
823 } else {
824 p2p_ps_offload->role = 0;
825 }
826
827 p2p_ps_offload->discovery = 0;
828 }
829 break;
830 case P2P_PS_SCAN:
831 DBG_8723A("P2P_PS_SCAN \n");
832 p2p_ps_offload->discovery = 1;
833 break;
834 case P2P_PS_SCAN_DONE:
835 DBG_8723A("P2P_PS_SCAN_DONE \n");
836 p2p_ps_offload->discovery = 0;
837 pwdinfo->p2p_ps_state = P2P_PS_ENABLE;
838 break;
839 default:
840 break;
841 }
842
843 FillH2CCmd(padapter, P2P_PS_OFFLOAD_EID, 1, (u8 *)p2p_ps_offload);
844}
845#endif /* CONFIG_8723AU_P2P */
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_dm.c b/drivers/staging/rtl8723au/hal/rtl8723a_dm.c
new file mode 100644
index 000000000000..f204ab1714e7
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_dm.c
@@ -0,0 +1,273 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15/* */
16/* Description: */
17/* */
18/* This file is for 92CE/92CU dynamic mechanism only */
19/* */
20/* */
21/* */
22#define _RTL8723A_DM_C_
23
24/* */
25/* include files */
26/* */
27#include <osdep_service.h>
28#include <drv_types.h>
29
30#include <rtl8723a_hal.h>
31
32/* */
33/* Global var */
34/* */
35
36static void dm_CheckStatistics(struct rtw_adapter *Adapter)
37{
38}
39
40static void dm_CheckPbcGPIO(struct rtw_adapter *padapter)
41{
42 u8 tmp1byte;
43 u8 bPbcPressed = false;
44
45 if (!padapter->registrypriv.hw_wps_pbc)
46 return;
47
48 tmp1byte = rtw_read8(padapter, GPIO_IO_SEL);
49 tmp1byte |= (HAL_8192C_HW_GPIO_WPS_BIT);
50 rtw_write8(padapter, GPIO_IO_SEL, tmp1byte); /* enable GPIO[2] as output mode */
51
52 tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT);
53 rtw_write8(padapter, GPIO_IN, tmp1byte); /* reset the floating voltage level */
54
55 tmp1byte = rtw_read8(padapter, GPIO_IO_SEL);
56 tmp1byte &= ~(HAL_8192C_HW_GPIO_WPS_BIT);
57 rtw_write8(padapter, GPIO_IO_SEL, tmp1byte); /* enable GPIO[2] as input mode */
58
59 tmp1byte = rtw_read8(padapter, GPIO_IN);
60
61 if (tmp1byte == 0xff)
62 return;
63
64 if (tmp1byte&HAL_8192C_HW_GPIO_WPS_BIT)
65 bPbcPressed = true;
66
67 if (bPbcPressed) {
68 /* Here we only set bPbcPressed to true */
69 /* After trigger PBC, the variable will be set to false */
70 DBG_8723A("CheckPbcGPIO - PBC is pressed\n");
71
72 if (padapter->pid[0] == 0) {
73 /* 0 is the default value and it means the application
74 * monitors the HW PBC doesn't privde its pid to driver.
75 */
76 return;
77 }
78
79 rtw_signal_process(padapter->pid[0], SIGUSR1);
80 }
81}
82
83/* Initialize GPIO setting registers */
84/* functions */
85static void Init_ODM_ComInfo_8723a(struct rtw_adapter *Adapter)
86{
87
88 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
89 struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
90 u8 cut_ver, fab_ver;
91
92 /* */
93 /* Init Value */
94 /* */
95 memset(pDM_Odm, 0, sizeof(*pDM_Odm));
96
97 pDM_Odm->Adapter = Adapter;
98 ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_PLATFORM, 0x04);
99 ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_INTERFACE, RTW_USB);/* RTL871X_HCI_TYPE */
100
101 ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_IC_TYPE, ODM_RTL8723A);
102
103 if (IS_8723A_A_CUT(pHalData->VersionID)) {
104 fab_ver = ODM_UMC;
105 cut_ver = ODM_CUT_A;
106 } else if (IS_8723A_B_CUT(pHalData->VersionID)) {
107 fab_ver = ODM_UMC;
108 cut_ver = ODM_CUT_B;
109 } else {
110 fab_ver = ODM_TSMC;
111 cut_ver = ODM_CUT_A;
112 }
113 ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_FAB_VER, fab_ver);
114 ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_CUT_VER, cut_ver);
115 ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_MP_TEST_CHIP, IS_NORMAL_CHIP(pHalData->VersionID));
116
117 ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_BOARD_TYPE, pHalData->BoardType);
118
119 if (pHalData->BoardType == BOARD_USB_High_PA) {
120 ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_EXT_LNA, true);
121 ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_EXT_PA, true);
122 }
123 ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_PATCH_ID, pHalData->CustomerID);
124 ODM_CmnInfoInit23a(pDM_Odm, ODM_CMNINFO_BWIFI_TEST, Adapter->registrypriv.wifi_spec);
125
126 if (pHalData->rf_type == RF_1T1R)
127 ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_1T1R);
128 else if (pHalData->rf_type == RF_2T2R)
129 ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_2T2R);
130 else if (pHalData->rf_type == RF_1T2R)
131 ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_RF_TYPE, ODM_1T2R);
132}
133
134static void Update_ODM_ComInfo_8723a(struct rtw_adapter *Adapter)
135{
136 struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
137 struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
138 struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
139 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
140 struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
141 struct dm_priv *pdmpriv = &pHalData->dmpriv;
142 int i;
143 pdmpriv->InitODMFlag = ODM_BB_DIG |
144 ODM_BB_RA_MASK |
145 ODM_BB_DYNAMIC_TXPWR |
146 ODM_BB_FA_CNT |
147 ODM_BB_RSSI_MONITOR |
148 ODM_BB_CCK_PD |
149 ODM_BB_PWR_SAVE |
150 ODM_MAC_EDCA_TURBO |
151 ODM_RF_TX_PWR_TRACK |
152 ODM_RF_CALIBRATION;
153 /* Pointer reference */
154
155 ODM_CmnInfoUpdate23a(pDM_Odm, ODM_CMNINFO_ABILITY, pdmpriv->InitODMFlag);
156
157 ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_TX_UNI,
158 &Adapter->xmitpriv.tx_bytes);
159 ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_RX_UNI,
160 &Adapter->recvpriv.rx_bytes);
161 ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_WM_MODE,
162 &pmlmeext->cur_wireless_mode);
163 ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SEC_CHNL_OFFSET,
164 &pHalData->nCur40MhzPrimeSC);
165 ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SEC_MODE,
166 &Adapter->securitypriv.dot11PrivacyAlgrthm);
167 ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_BW,
168 &pHalData->CurrentChannelBW);
169 ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_CHNL,
170 &pHalData->CurrentChannel);
171 ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_NET_CLOSED, &Adapter->net_closed);
172
173 ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_SCAN, &pmlmepriv->bScanInProcess);
174 ODM23a_CmnInfoHook(pDM_Odm, ODM_CMNINFO_POWER_SAVING,
175 &pwrctrlpriv->bpower_saving);
176
177 for (i = 0; i < NUM_STA; i++)
178 ODM_CmnInfoPtrArrayHook23a(pDM_Odm, ODM_CMNINFO_STA_STATUS, i, NULL);
179}
180
181void rtl8723a_InitHalDm(struct rtw_adapter *Adapter)
182{
183 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
184 struct dm_priv *pdmpriv = &pHalData->dmpriv;
185 struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
186 u8 i;
187
188 pdmpriv->DM_Type = DM_Type_ByDriver;
189 pdmpriv->DMFlag = DYNAMIC_FUNC_DISABLE;
190
191#ifdef CONFIG_8723AU_BT_COEXIST
192 pdmpriv->DMFlag |= DYNAMIC_FUNC_BT;
193#endif
194 pdmpriv->InitDMFlag = pdmpriv->DMFlag;
195
196 Update_ODM_ComInfo_8723a(Adapter);
197 ODM23a_DMInit(pDM_Odm);
198 /* Save REG_INIDATA_RATE_SEL value for TXDESC. */
199 for (i = 0; i < 32; i++)
200 pdmpriv->INIDATA_RATE[i] = rtw_read8(Adapter, REG_INIDATA_RATE_SEL+i) & 0x3f;
201}
202
203void
204rtl8723a_HalDmWatchDog(
205 struct rtw_adapter *Adapter
206 )
207{
208 bool bFwCurrentInPSMode = false;
209 bool bFwPSAwake = true;
210 u8 hw_init_completed = false;
211 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
212 struct dm_priv *pdmpriv = &pHalData->dmpriv;
213
214 hw_init_completed = Adapter->hw_init_completed;
215
216 if (hw_init_completed == false)
217 goto skip_dm;
218
219 bFwCurrentInPSMode = Adapter->pwrctrlpriv.bFwCurrentInPSMode;
220 rtw23a_hal_get_hwreg(Adapter, HW_VAR_FWLPS_RF_ON, (u8 *)(&bFwPSAwake));
221
222#ifdef CONFIG_8723AU_P2P
223 /* Fw is under p2p powersaving mode, driver should stop dynamic mechanism. */
224 /* modifed by thomas. 2011.06.11. */
225 if (Adapter->wdinfo.p2p_ps_mode)
226 bFwPSAwake = false;
227#endif /* CONFIG_8723AU_P2P */
228
229 if ((hw_init_completed) && ((!bFwCurrentInPSMode) && bFwPSAwake)) {
230 /* Calculate Tx/Rx statistics. */
231 dm_CheckStatistics(Adapter);
232
233 /* Read REG_INIDATA_RATE_SEL value for TXDESC. */
234 if (check_fwstate(&Adapter->mlmepriv, WIFI_STATION_STATE)) {
235 pdmpriv->INIDATA_RATE[0] = rtw_read8(Adapter, REG_INIDATA_RATE_SEL) & 0x3f;
236 } else {
237 u8 i;
238 for (i = 1 ; i < (Adapter->stapriv.asoc_sta_count + 1); i++)
239 pdmpriv->INIDATA_RATE[i] = rtw_read8(Adapter, (REG_INIDATA_RATE_SEL+i)) & 0x3f;
240 }
241 }
242
243 /* ODM */
244 if (hw_init_completed == true) {
245 u8 bLinked = false;
246
247 if (rtw_linked_check(Adapter))
248 bLinked = true;
249
250 ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_LINK,
251 bLinked);
252 ODM_DMWatchdog23a(&pHalData->odmpriv);
253 }
254
255skip_dm:
256
257 /* Check GPIO to determine current RF on/off and Pbc status. */
258 /* Check Hardware Radio ON/OFF or not */
259 dm_CheckPbcGPIO(Adapter);
260}
261
262void rtl8723a_init_dm_priv(struct rtw_adapter *Adapter)
263{
264 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
265 struct dm_priv *pdmpriv = &pHalData->dmpriv;
266
267 memset(pdmpriv, 0, sizeof(struct dm_priv));
268 Init_ODM_ComInfo_8723a(Adapter);
269}
270
271void rtl8723a_deinit_dm_priv(struct rtw_adapter *Adapter)
272{
273}
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c b/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c
new file mode 100644
index 000000000000..0982b0a4ab9b
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c
@@ -0,0 +1,3452 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _HAL_INIT_C_
16
17#include <linux/firmware.h>
18#include <drv_types.h>
19#include <rtw_efuse.h>
20
21#include <rtl8723a_hal.h>
22
23static void _FWDownloadEnable(struct rtw_adapter *padapter, bool enable)
24{
25 u8 tmp;
26
27 if (enable) {
28 /* 8051 enable */
29 tmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
30 rtw_write8(padapter, REG_SYS_FUNC_EN + 1, tmp | 0x04);
31
32 /* MCU firmware download enable. */
33 tmp = rtw_read8(padapter, REG_MCUFWDL);
34 rtw_write8(padapter, REG_MCUFWDL, tmp | 0x01);
35
36 /* 8051 reset */
37 tmp = rtw_read8(padapter, REG_MCUFWDL + 2);
38 rtw_write8(padapter, REG_MCUFWDL + 2, tmp & 0xf7);
39 } else {
40 /* MCU firmware download disable. */
41 tmp = rtw_read8(padapter, REG_MCUFWDL);
42 rtw_write8(padapter, REG_MCUFWDL, tmp & 0xfe);
43
44 /* Reserved for fw extension. */
45 rtw_write8(padapter, REG_MCUFWDL + 1, 0x00);
46 }
47}
48
49static int _BlockWrite(struct rtw_adapter *padapter, void *buffer, u32 buffSize)
50{
51 int ret = _SUCCESS;
52 /* (Default) Phase #1 : PCI muse use 4-byte write to download FW */
53 u32 blockSize_p1 = 4;
54 /* Phase #2 : Use 8-byte, if Phase#1 use big size to write FW. */
55 u32 blockSize_p2 = 8;
56 /* Phase #3 : Use 1-byte, the remnant of FW image. */
57 u32 blockSize_p3 = 1;
58 u32 blockCount_p1 = 0, blockCount_p2 = 0, blockCount_p3 = 0;
59 u32 remainSize_p1 = 0, remainSize_p2 = 0;
60 u8 *bufferPtr = (u8 *) buffer;
61 u32 i = 0, offset = 0;
62
63 blockSize_p1 = 254;
64
65 /* 3 Phase #1 */
66 blockCount_p1 = buffSize / blockSize_p1;
67 remainSize_p1 = buffSize % blockSize_p1;
68
69 if (blockCount_p1) {
70 RT_TRACE(_module_hal_init_c_, _drv_notice_,
71 ("_BlockWrite: [P1] buffSize(%d) blockSize_p1(%d) "
72 "blockCount_p1(%d) remainSize_p1(%d)\n",
73 buffSize, blockSize_p1, blockCount_p1,
74 remainSize_p1));
75 }
76
77 for (i = 0; i < blockCount_p1; i++) {
78 ret = rtw_writeN(padapter,
79 (FW_8723A_START_ADDRESS + i * blockSize_p1),
80 blockSize_p1, (bufferPtr + i * blockSize_p1));
81 if (ret == _FAIL)
82 goto exit;
83 }
84
85 /* 3 Phase #2 */
86 if (remainSize_p1) {
87 offset = blockCount_p1 * blockSize_p1;
88
89 blockCount_p2 = remainSize_p1 / blockSize_p2;
90 remainSize_p2 = remainSize_p1 % blockSize_p2;
91
92 if (blockCount_p2) {
93 RT_TRACE(_module_hal_init_c_, _drv_notice_,
94 ("_BlockWrite: [P2] buffSize_p2(%d) "
95 "blockSize_p2(%d) blockCount_p2(%d) "
96 "remainSize_p2(%d)\n",
97 (buffSize - offset), blockSize_p2,
98 blockCount_p2, remainSize_p2));
99 }
100
101 for (i = 0; i < blockCount_p2; i++) {
102 ret = rtw_writeN(padapter,
103 (FW_8723A_START_ADDRESS + offset +
104 i * blockSize_p2), blockSize_p2,
105 (bufferPtr + offset +
106 i * blockSize_p2));
107
108 if (ret == _FAIL)
109 goto exit;
110 }
111 }
112
113 /* 3 Phase #3 */
114 if (remainSize_p2) {
115 offset = (blockCount_p1 * blockSize_p1) +
116 (blockCount_p2 * blockSize_p2);
117
118 blockCount_p3 = remainSize_p2 / blockSize_p3;
119
120 RT_TRACE(_module_hal_init_c_, _drv_notice_,
121 ("_BlockWrite: [P3] buffSize_p3(%d) blockSize_p3(%d) "
122 "blockCount_p3(%d)\n",
123 (buffSize - offset), blockSize_p3, blockCount_p3));
124
125 for (i = 0; i < blockCount_p3; i++) {
126 ret = rtw_write8(padapter,
127 (FW_8723A_START_ADDRESS + offset + i),
128 *(bufferPtr + offset + i));
129
130 if (ret == _FAIL)
131 goto exit;
132 }
133 }
134
135exit:
136 return ret;
137}
138
139static int
140_PageWrite(struct rtw_adapter *padapter, u32 page, void *buffer, u32 size)
141{
142 u8 value8;
143 u8 u8Page = (u8) (page & 0x07);
144
145 value8 = (rtw_read8(padapter, REG_MCUFWDL + 2) & 0xF8) | u8Page;
146 rtw_write8(padapter, REG_MCUFWDL + 2, value8);
147
148 return _BlockWrite(padapter, buffer, size);
149}
150
151static int _WriteFW(struct rtw_adapter *padapter, void *buffer, u32 size)
152{
153 /* Since we need dynamic decide method of dwonload fw, so we
154 call this function to get chip version. */
155 /* We can remove _ReadChipVersion from ReadpadapterInfo8192C later. */
156 int ret = _SUCCESS;
157 u32 pageNums, remainSize;
158 u32 page, offset;
159 u8 *bufferPtr = (u8 *) buffer;
160
161 pageNums = size / MAX_PAGE_SIZE;
162 /* RT_ASSERT((pageNums <= 4),
163 ("Page numbers should not greater then 4 \n")); */
164 remainSize = size % MAX_PAGE_SIZE;
165
166 for (page = 0; page < pageNums; page++) {
167 offset = page * MAX_PAGE_SIZE;
168 ret = _PageWrite(padapter, page, bufferPtr + offset,
169 MAX_PAGE_SIZE);
170
171 if (ret == _FAIL)
172 goto exit;
173 }
174 if (remainSize) {
175 offset = pageNums * MAX_PAGE_SIZE;
176 page = pageNums;
177 ret = _PageWrite(padapter, page, bufferPtr + offset,
178 remainSize);
179
180 if (ret == _FAIL)
181 goto exit;
182 }
183 RT_TRACE(_module_hal_init_c_, _drv_info_,
184 ("_WriteFW Done- for Normal chip.\n"));
185
186exit:
187 return ret;
188}
189
190static s32 _FWFreeToGo(struct rtw_adapter *padapter)
191{
192 u32 counter = 0;
193 u32 value32;
194
195 /* polling CheckSum report */
196 do {
197 value32 = rtw_read32(padapter, REG_MCUFWDL);
198 if (value32 & FWDL_ChkSum_rpt)
199 break;
200 } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
201
202 if (counter >= POLLING_READY_TIMEOUT_COUNT) {
203 RT_TRACE(_module_hal_init_c_, _drv_err_,
204 ("%s: chksum report fail! REG_MCUFWDL:0x%08x\n",
205 __func__, value32));
206 return _FAIL;
207 }
208 RT_TRACE(_module_hal_init_c_, _drv_info_,
209 ("%s: Checksum report OK! REG_MCUFWDL:0x%08x\n", __func__,
210 value32));
211
212 value32 = rtw_read32(padapter, REG_MCUFWDL);
213 value32 |= MCUFWDL_RDY;
214 value32 &= ~WINTINI_RDY;
215 rtw_write32(padapter, REG_MCUFWDL, value32);
216
217 /* polling for FW ready */
218 counter = 0;
219 do {
220 value32 = rtw_read32(padapter, REG_MCUFWDL);
221 if (value32 & WINTINI_RDY) {
222 RT_TRACE(_module_hal_init_c_, _drv_info_,
223 ("%s: Polling FW ready success!! "
224 "REG_MCUFWDL:0x%08x\n",
225 __func__, value32));
226 return _SUCCESS;
227 }
228 udelay(5);
229 } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
230
231 RT_TRACE(_module_hal_init_c_, _drv_err_,
232 ("%s: Polling FW ready fail!! REG_MCUFWDL:0x%08x\n",
233 __func__, value32));
234 return _FAIL;
235}
236
237#define IS_FW_81xxC(padapter) (((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0)
238
239void rtl8723a_FirmwareSelfReset(struct rtw_adapter *padapter)
240{
241 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
242 u8 u1bTmp;
243 u8 Delay = 100;
244
245 if (!(IS_FW_81xxC(padapter) &&
246 ((pHalData->FirmwareVersion < 0x21) ||
247 (pHalData->FirmwareVersion == 0x21 &&
248 pHalData->FirmwareSubVersion < 0x01)))) {
249 /* after 88C Fw v33.1 */
250 /* 0x1cf = 0x20. Inform 8051 to reset. 2009.12.25. tynli_test */
251 rtw_write8(padapter, REG_HMETFR + 3, 0x20);
252
253 u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
254 while (u1bTmp & BIT2) {
255 Delay--;
256 if (Delay == 0)
257 break;
258 udelay(50);
259 u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
260 }
261 RT_TRACE(_module_hal_init_c_, _drv_info_,
262 ("-%s: 8051 reset success (%d)\n", __func__,
263 Delay));
264
265 if ((Delay == 0)) {
266 /* force firmware reset */
267 u1bTmp = rtw_read8(padapter, REG_SYS_FUNC_EN + 1);
268 rtw_write8(padapter, REG_SYS_FUNC_EN + 1,
269 u1bTmp & (~BIT2));
270 }
271 }
272}
273
274/* */
275/* Description: */
276/* Download 8192C firmware code. */
277/* */
278/* */
279s32 rtl8723a_FirmwareDownload(struct rtw_adapter *padapter)
280{
281 s32 rtStatus = _SUCCESS;
282 u8 writeFW_retry = 0;
283 unsigned long fwdl_start_time;
284 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
285 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
286 struct device *device = dvobj_to_dev(dvobj);
287 struct rt_8723a_firmware_hdr *pFwHdr = NULL;
288 const struct firmware *fw;
289 char *fw_name;
290 u8 *firmware_buf = NULL;
291 u8 *buf;
292 int fw_size;
293 static int log_version;
294
295 RT_TRACE(_module_hal_init_c_, _drv_info_, ("+%s\n", __func__));
296
297 if (IS_8723A_A_CUT(pHalData->VersionID)) {
298 fw_name = "rtlwifi/rtl8723aufw.bin";
299 RT_TRACE(_module_hal_init_c_, _drv_info_,
300 ("rtl8723a_FirmwareDownload: R8723FwImageArray_UMC "
301 "for RTL8723A A CUT\n"));
302 } else if (IS_8723A_B_CUT(pHalData->VersionID)) {
303 /* WLAN Fw. */
304 if (padapter->registrypriv.wifi_spec == 1) {
305 fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin";
306 DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithoutBT for "
307 "RTL8723A B CUT\n");
308 } else {
309#ifdef CONFIG_8723AU_BT_COEXIST
310 fw_name = "rtlwifi/rtl8723aufw_B.bin";
311 DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithBT for "
312 "RTL8723A B CUT\n");
313#else
314 fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin";
315 DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithoutBT for "
316 "RTL8723A B CUT\n");
317#endif
318 }
319 } else {
320 /* <Roger_TODO> We should download proper RAM Code here
321 to match the ROM code. */
322 RT_TRACE(_module_hal_init_c_, _drv_err_,
323 ("%s: unknow version!\n", __func__));
324 rtStatus = _FAIL;
325 goto Exit;
326 }
327
328 pr_info("rtl8723au: Loading firmware %s\n", fw_name);
329 if (request_firmware(&fw, fw_name, device)) {
330 pr_err("rtl8723au: request_firmware load failed\n");
331 rtStatus = _FAIL;
332 goto Exit;
333 }
334 if (!fw) {
335 pr_err("rtl8723au: Firmware %s not available\n", fw_name);
336 rtStatus = _FAIL;
337 goto Exit;
338 }
339 firmware_buf = kzalloc(fw->size, GFP_KERNEL);
340 if (!firmware_buf) {
341 rtStatus = _FAIL;
342 goto Exit;
343 }
344 memcpy(firmware_buf, fw->data, fw->size);
345 buf = firmware_buf;
346 fw_size = fw->size;
347 release_firmware(fw);
348
349 /* To Check Fw header. Added by tynli. 2009.12.04. */
350 pFwHdr = (struct rt_8723a_firmware_hdr *)firmware_buf;
351
352 pHalData->FirmwareVersion = le16_to_cpu(pFwHdr->Version);
353 pHalData->FirmwareSubVersion = pFwHdr->Subversion;
354 pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->Signature);
355
356 DBG_8723A("%s: fw_ver =%d fw_subver =%d sig = 0x%x\n",
357 __func__, pHalData->FirmwareVersion,
358 pHalData->FirmwareSubVersion, pHalData->FirmwareSignature);
359
360 if (!log_version++)
361 pr_info("%sFirmware Version %d, SubVersion %d, Signature "
362 "0x%x\n", DRIVER_PREFIX, pHalData->FirmwareVersion,
363 pHalData->FirmwareSubVersion,
364 pHalData->FirmwareSignature);
365
366 if (IS_FW_HEADER_EXIST(pFwHdr)) {
367 /* Shift 32 bytes for FW header */
368 buf = buf + 32;
369 fw_size = fw_size - 32;
370 }
371
372 /* Suggested by Filen. If 8051 is running in RAM code, driver should
373 inform Fw to reset by itself, */
374 /* or it will cause download Fw fail. 2010.02.01. by tynli. */
375 if (rtw_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) {
376 /* 8051 RAM code */
377 rtl8723a_FirmwareSelfReset(padapter);
378 rtw_write8(padapter, REG_MCUFWDL, 0x00);
379 }
380
381 _FWDownloadEnable(padapter, true);
382 fwdl_start_time = jiffies;
383 while (1) {
384 /* reset the FWDL chksum */
385 rtw_write8(padapter, REG_MCUFWDL,
386 rtw_read8(padapter, REG_MCUFWDL) | FWDL_ChkSum_rpt);
387
388 rtStatus = _WriteFW(padapter, buf, fw_size);
389
390 if (rtStatus == _SUCCESS ||
391 (jiffies_to_msecs(jiffies - fwdl_start_time) > 500 &&
392 writeFW_retry++ >= 3))
393 break;
394
395 DBG_8723A("%s writeFW_retry:%u, time after fwdl_start_time:"
396 "%ums\n", __func__, writeFW_retry,
397 jiffies_to_msecs(jiffies - fwdl_start_time));
398 }
399 _FWDownloadEnable(padapter, false);
400 if (_SUCCESS != rtStatus) {
401 DBG_8723A("DL Firmware failed!\n");
402 goto Exit;
403 }
404
405 rtStatus = _FWFreeToGo(padapter);
406 if (_SUCCESS != rtStatus) {
407 RT_TRACE(_module_hal_init_c_, _drv_err_,
408 ("DL Firmware failed!\n"));
409 goto Exit;
410 }
411 RT_TRACE(_module_hal_init_c_, _drv_info_,
412 ("Firmware is ready to run!\n"));
413
414Exit:
415 kfree(firmware_buf);
416 return rtStatus;
417}
418
419void rtl8723a_InitializeFirmwareVars(struct rtw_adapter *padapter)
420{
421 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
422
423 /* Init Fw LPS related. */
424 padapter->pwrctrlpriv.bFwCurrentInPSMode = false;
425
426 /* Init H2C counter. by tynli. 2009.12.09. */
427 pHalData->LastHMEBoxNum = 0;
428}
429
430static void rtl8723a_free_hal_data(struct rtw_adapter *padapter)
431{
432
433 kfree(padapter->HalData);
434 padapter->HalData = NULL;
435
436}
437
438/* */
439/* Efuse related code */
440/* */
441static u8
442hal_EfuseSwitchToBank(struct rtw_adapter *padapter, u8 bank)
443{
444 u8 bRet = false;
445 u32 value32 = 0;
446
447 DBG_8723A("%s: Efuse switch bank to %d\n", __func__, bank);
448 value32 = rtw_read32(padapter, EFUSE_TEST);
449 bRet = true;
450 switch (bank) {
451 case 0:
452 value32 = (value32 & ~EFUSE_SEL_MASK) |
453 EFUSE_SEL(EFUSE_WIFI_SEL_0);
454 break;
455 case 1:
456 value32 = (value32 & ~EFUSE_SEL_MASK) |
457 EFUSE_SEL(EFUSE_BT_SEL_0);
458 break;
459 case 2:
460 value32 = (value32 & ~EFUSE_SEL_MASK) |
461 EFUSE_SEL(EFUSE_BT_SEL_1);
462 break;
463 case 3:
464 value32 = (value32 & ~EFUSE_SEL_MASK) |
465 EFUSE_SEL(EFUSE_BT_SEL_2);
466 break;
467 default:
468 value32 = (value32 & ~EFUSE_SEL_MASK) |
469 EFUSE_SEL(EFUSE_WIFI_SEL_0);
470 bRet = false;
471 break;
472 }
473 rtw_write32(padapter, EFUSE_TEST, value32);
474
475 return bRet;
476}
477
478static void
479Hal_GetEfuseDefinition(struct rtw_adapter *padapter,
480 u8 efuseType, u8 type, void *pOut)
481{
482 u8 *pu1Tmp;
483 u16 *pu2Tmp;
484 u8 *pMax_section;
485
486 switch (type) {
487 case TYPE_EFUSE_MAX_SECTION:
488 pMax_section = (u8 *) pOut;
489
490 if (efuseType == EFUSE_WIFI)
491 *pMax_section = EFUSE_MAX_SECTION_8723A;
492 else
493 *pMax_section = EFUSE_BT_MAX_SECTION;
494 break;
495
496 case TYPE_EFUSE_REAL_CONTENT_LEN:
497 pu2Tmp = (u16 *) pOut;
498
499 if (efuseType == EFUSE_WIFI)
500 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A;
501 else
502 *pu2Tmp = EFUSE_BT_REAL_CONTENT_LEN;
503 break;
504
505 case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
506 pu2Tmp = (u16 *) pOut;
507
508 if (efuseType == EFUSE_WIFI)
509 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A -
510 EFUSE_OOB_PROTECT_BYTES);
511 else
512 *pu2Tmp = (EFUSE_BT_REAL_BANK_CONTENT_LEN -
513 EFUSE_PROTECT_BYTES_BANK);
514 break;
515
516 case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
517 pu2Tmp = (u16 *) pOut;
518
519 if (efuseType == EFUSE_WIFI)
520 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723A -
521 EFUSE_OOB_PROTECT_BYTES);
522 else
523 *pu2Tmp = (EFUSE_BT_REAL_CONTENT_LEN -
524 (EFUSE_PROTECT_BYTES_BANK * 3));
525 break;
526
527 case TYPE_EFUSE_MAP_LEN:
528 pu2Tmp = (u16 *) pOut;
529
530 if (efuseType == EFUSE_WIFI)
531 *pu2Tmp = EFUSE_MAP_LEN_8723A;
532 else
533 *pu2Tmp = EFUSE_BT_MAP_LEN;
534 break;
535
536 case TYPE_EFUSE_PROTECT_BYTES_BANK:
537 pu1Tmp = (u8 *) pOut;
538
539 if (efuseType == EFUSE_WIFI)
540 *pu1Tmp = EFUSE_OOB_PROTECT_BYTES;
541 else
542 *pu1Tmp = EFUSE_PROTECT_BYTES_BANK;
543 break;
544
545 case TYPE_EFUSE_CONTENT_LEN_BANK:
546 pu2Tmp = (u16 *) pOut;
547
548 if (efuseType == EFUSE_WIFI)
549 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723A;
550 else
551 *pu2Tmp = EFUSE_BT_REAL_BANK_CONTENT_LEN;
552 break;
553
554 default:
555 pu1Tmp = (u8 *) pOut;
556 *pu1Tmp = 0;
557 break;
558 }
559}
560
561#define VOLTAGE_V25 0x03
562#define LDOE25_SHIFT 28
563
564static void
565Hal_EfusePowerSwitch(struct rtw_adapter *padapter, u8 bWrite, u8 PwrState)
566{
567 u8 tempval;
568 u16 tmpV16;
569
570 if (PwrState == true) {
571 rtw_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
572
573 /* 1.2V Power: From VDDON with Power
574 Cut(0x0000h[15]), defualt valid */
575 tmpV16 = rtw_read16(padapter, REG_SYS_ISO_CTRL);
576 if (!(tmpV16 & PWC_EV12V)) {
577 tmpV16 |= PWC_EV12V;
578 rtw_write16(padapter, REG_SYS_ISO_CTRL, tmpV16);
579 }
580 /* Reset: 0x0000h[28], default valid */
581 tmpV16 = rtw_read16(padapter, REG_SYS_FUNC_EN);
582 if (!(tmpV16 & FEN_ELDR)) {
583 tmpV16 |= FEN_ELDR;
584 rtw_write16(padapter, REG_SYS_FUNC_EN, tmpV16);
585 }
586
587 /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock
588 from ANA, default valid */
589 tmpV16 = rtw_read16(padapter, REG_SYS_CLKR);
590 if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) {
591 tmpV16 |= (LOADER_CLK_EN | ANA8M);
592 rtw_write16(padapter, REG_SYS_CLKR, tmpV16);
593 }
594
595 if (bWrite == true) {
596 /* Enable LDO 2.5V before read/write action */
597 tempval = rtw_read8(padapter, EFUSE_TEST + 3);
598 tempval &= 0x0F;
599 tempval |= (VOLTAGE_V25 << 4);
600 rtw_write8(padapter, EFUSE_TEST + 3, (tempval | 0x80));
601 }
602 } else {
603 rtw_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
604
605 if (bWrite == true) {
606 /* Disable LDO 2.5V after read/write action */
607 tempval = rtw_read8(padapter, EFUSE_TEST + 3);
608 rtw_write8(padapter, EFUSE_TEST + 3, (tempval & 0x7F));
609 }
610 }
611}
612
613static void
614hal_ReadEFuse_WiFi(struct rtw_adapter *padapter,
615 u16 _offset, u16 _size_byte, u8 *pbuf)
616{
617 u8 *efuseTbl = NULL;
618 u16 eFuse_Addr = 0;
619 u8 offset, wden;
620 u8 efuseHeader, efuseExtHdr, efuseData;
621 u16 i, total, used;
622
623 /* Do NOT excess total size of EFuse table.
624 Added by Roger, 2008.11.10. */
625 if ((_offset + _size_byte) > EFUSE_MAP_LEN_8723A) {
626 DBG_8723A("%s: Invalid offset(%#x) with read bytes(%#x)!!\n",
627 __func__, _offset, _size_byte);
628 return;
629 }
630
631 efuseTbl = (u8 *) kmalloc(EFUSE_MAP_LEN_8723A, GFP_KERNEL);
632 if (efuseTbl == NULL) {
633 DBG_8723A("%s: alloc efuseTbl fail!\n", __func__);
634 return;
635 }
636 /* 0xff will be efuse default value instead of 0x00. */
637 memset(efuseTbl, 0xFF, EFUSE_MAP_LEN_8723A);
638
639 /* switch bank back to bank 0 for later BT and wifi use. */
640 hal_EfuseSwitchToBank(padapter, 0);
641
642 while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
643 ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseHeader);
644 if (efuseHeader == 0xFF) {
645 DBG_8723A("%s: data end at address =%#x\n", __func__,
646 eFuse_Addr);
647 break;
648 }
649
650 /* Check PG header for section num. */
651 if (EXT_HEADER(efuseHeader)) { /* extended header */
652 offset = GET_HDR_OFFSET_2_0(efuseHeader);
653
654 ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseExtHdr);
655 if (ALL_WORDS_DISABLED(efuseExtHdr)) {
656 continue;
657 }
658
659 offset |= ((efuseExtHdr & 0xF0) >> 1);
660 wden = (efuseExtHdr & 0x0F);
661 } else {
662 offset = ((efuseHeader >> 4) & 0x0f);
663 wden = (efuseHeader & 0x0f);
664 }
665
666 if (offset < EFUSE_MAX_SECTION_8723A) {
667 u16 addr;
668 /* Get word enable value from PG header */
669
670 addr = offset * PGPKT_DATA_SIZE;
671 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
672 /* Check word enable condition in the section */
673 if (!(wden & (0x01 << i))) {
674 ReadEFuseByte23a(padapter, eFuse_Addr++,
675 &efuseData);
676 efuseTbl[addr] = efuseData;
677
678 ReadEFuseByte23a(padapter, eFuse_Addr++,
679 &efuseData);
680 efuseTbl[addr + 1] = efuseData;
681 }
682 addr += 2;
683 }
684 } else {
685 DBG_8723A(KERN_ERR "%s: offset(%d) is illegal!!\n",
686 __func__, offset);
687 eFuse_Addr += Efuse_CalculateWordCnts23a(wden) * 2;
688 }
689 }
690
691 /* Copy from Efuse map to output pointer memory!!! */
692 for (i = 0; i < _size_byte; i++)
693 pbuf[i] = efuseTbl[_offset + i];
694
695 /* Calculate Efuse utilization */
696 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
697 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total);
698 used = eFuse_Addr - 1;
699 rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&used);
700
701 kfree(efuseTbl);
702}
703
704static void
705hal_ReadEFuse_BT(struct rtw_adapter *padapter,
706 u16 _offset, u16 _size_byte, u8 *pbuf)
707{
708 u8 *efuseTbl;
709 u8 bank;
710 u16 eFuse_Addr;
711 u8 efuseHeader, efuseExtHdr, efuseData;
712 u8 offset, wden;
713 u16 i, total, used;
714
715 /* Do NOT excess total size of EFuse table.
716 Added by Roger, 2008.11.10. */
717 if ((_offset + _size_byte) > EFUSE_BT_MAP_LEN) {
718 DBG_8723A("%s: Invalid offset(%#x) with read bytes(%#x)!!\n",
719 __func__, _offset, _size_byte);
720 return;
721 }
722
723 efuseTbl = kmalloc(EFUSE_BT_MAP_LEN, GFP_KERNEL);
724 if (efuseTbl == NULL) {
725 DBG_8723A("%s: efuseTbl malloc fail!\n", __func__);
726 return;
727 }
728 /* 0xff will be efuse default value instead of 0x00. */
729 memset(efuseTbl, 0xFF, EFUSE_BT_MAP_LEN);
730
731 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
732 TYPE_AVAILABLE_EFUSE_BYTES_BANK, &total);
733
734 for (bank = 1; bank < EFUSE_MAX_BANK; bank++) {
735 if (hal_EfuseSwitchToBank(padapter, bank) == false) {
736 DBG_8723A("%s: hal_EfuseSwitchToBank Fail!!\n",
737 __func__);
738 goto exit;
739 }
740
741 eFuse_Addr = 0;
742
743 while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
744 ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseHeader);
745 if (efuseHeader == 0xFF)
746 break;
747
748 /* Check PG header for section num. */
749 if (EXT_HEADER(efuseHeader)) { /* extended header */
750 offset = GET_HDR_OFFSET_2_0(efuseHeader);
751
752 ReadEFuseByte23a(padapter, eFuse_Addr++,
753 &efuseExtHdr);
754 if (ALL_WORDS_DISABLED(efuseExtHdr)) {
755 continue;
756 }
757
758 offset |= ((efuseExtHdr & 0xF0) >> 1);
759 wden = (efuseExtHdr & 0x0F);
760 } else {
761 offset = ((efuseHeader >> 4) & 0x0f);
762 wden = (efuseHeader & 0x0f);
763 }
764
765 if (offset < EFUSE_BT_MAX_SECTION) {
766 u16 addr;
767
768 /* Get word enable value from PG header */
769
770 addr = offset * PGPKT_DATA_SIZE;
771 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
772 /* Check word enable condition in
773 the section */
774 if (!(wden & (0x01 << i))) {
775 ReadEFuseByte23a(padapter,
776 eFuse_Addr++,
777 &efuseData);
778 efuseTbl[addr] = efuseData;
779
780 ReadEFuseByte23a(padapter,
781 eFuse_Addr++,
782 &efuseData);
783 efuseTbl[addr + 1] = efuseData;
784 }
785 addr += 2;
786 }
787 } else {
788 DBG_8723A(KERN_ERR
789 "%s: offset(%d) is illegal!!\n",
790 __func__, offset);
791 eFuse_Addr += Efuse_CalculateWordCnts23a(wden) * 2;
792 }
793 }
794
795 if ((eFuse_Addr - 1) < total) {
796 DBG_8723A("%s: bank(%d) data end at %#x\n",
797 __func__, bank, eFuse_Addr - 1);
798 break;
799 }
800 }
801
802 /* switch bank back to bank 0 for later BT and wifi use. */
803 hal_EfuseSwitchToBank(padapter, 0);
804
805 /* Copy from Efuse map to output pointer memory!!! */
806 for (i = 0; i < _size_byte; i++)
807 pbuf[i] = efuseTbl[_offset + i];
808
809 /* */
810 /* Calculate Efuse utilization. */
811 /* */
812 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
813 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total);
814 used = (EFUSE_BT_REAL_BANK_CONTENT_LEN * (bank - 1)) + eFuse_Addr - 1;
815 rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *) &used);
816
817exit:
818 kfree(efuseTbl);
819}
820
821static void
822Hal_ReadEFuse(struct rtw_adapter *padapter,
823 u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf)
824{
825 if (efuseType == EFUSE_WIFI)
826 hal_ReadEFuse_WiFi(padapter, _offset, _size_byte, pbuf);
827 else
828 hal_ReadEFuse_BT(padapter, _offset, _size_byte, pbuf);
829}
830
831static u16
832hal_EfuseGetCurrentSize_WiFi(struct rtw_adapter *padapter)
833{
834 u16 efuse_addr = 0;
835 u8 hoffset = 0, hworden = 0;
836 u8 efuse_data, word_cnts = 0;
837
838 rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *) &efuse_addr);
839
840 DBG_8723A("%s: start_efuse_addr = 0x%X\n", __func__, efuse_addr);
841
842 /* switch bank back to bank 0 for later BT and wifi use. */
843 hal_EfuseSwitchToBank(padapter, 0);
844
845 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
846 if (efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data) ==
847 false) {
848 DBG_8723A(KERN_ERR "%s: efuse_OneByteRead23a Fail! "
849 "addr = 0x%X !!\n", __func__, efuse_addr);
850 break;
851 }
852
853 if (efuse_data == 0xFF)
854 break;
855
856 if (EXT_HEADER(efuse_data)) {
857 hoffset = GET_HDR_OFFSET_2_0(efuse_data);
858 efuse_addr++;
859 efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data);
860 if (ALL_WORDS_DISABLED(efuse_data)) {
861 continue;
862 }
863
864 hoffset |= ((efuse_data & 0xF0) >> 1);
865 hworden = efuse_data & 0x0F;
866 } else {
867 hoffset = (efuse_data >> 4) & 0x0F;
868 hworden = efuse_data & 0x0F;
869 }
870
871 word_cnts = Efuse_CalculateWordCnts23a(hworden);
872 efuse_addr += (word_cnts * 2) + 1;
873 }
874
875 rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BYTES, (u8 *) &efuse_addr);
876
877 DBG_8723A("%s: CurrentSize =%d\n", __func__, efuse_addr);
878
879 return efuse_addr;
880}
881
882static u16
883hal_EfuseGetCurrentSize_BT(struct rtw_adapter *padapter)
884{
885 u16 btusedbytes;
886 u16 efuse_addr;
887 u8 bank, startBank;
888 u8 hoffset = 0, hworden = 0;
889 u8 efuse_data, word_cnts = 0;
890 u16 retU2 = 0;
891
892 rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *) &btusedbytes);
893
894 efuse_addr = (u16) ((btusedbytes % EFUSE_BT_REAL_BANK_CONTENT_LEN));
895 startBank = (u8) (1 + (btusedbytes / EFUSE_BT_REAL_BANK_CONTENT_LEN));
896
897 DBG_8723A("%s: start from bank =%d addr = 0x%X\n", __func__, startBank,
898 efuse_addr);
899
900 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
901 TYPE_AVAILABLE_EFUSE_BYTES_BANK, &retU2);
902
903 for (bank = startBank; bank < EFUSE_MAX_BANK; bank++) {
904 if (hal_EfuseSwitchToBank(padapter, bank) == false) {
905 DBG_8723A(KERN_ERR "%s: switch bank(%d) Fail!!\n",
906 __func__, bank);
907 bank = EFUSE_MAX_BANK;
908 break;
909 }
910
911 /* only when bank is switched we have to reset
912 the efuse_addr. */
913 if (bank != startBank)
914 efuse_addr = 0;
915
916 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
917 if (efuse_OneByteRead23a(padapter, efuse_addr,
918 &efuse_data) == false) {
919 DBG_8723A(KERN_ERR "%s: efuse_OneByteRead23a Fail!"
920 " addr = 0x%X !!\n",
921 __func__, efuse_addr);
922 bank = EFUSE_MAX_BANK;
923 break;
924 }
925
926 if (efuse_data == 0xFF)
927 break;
928
929 if (EXT_HEADER(efuse_data)) {
930 hoffset = GET_HDR_OFFSET_2_0(efuse_data);
931 efuse_addr++;
932 efuse_OneByteRead23a(padapter, efuse_addr,
933 &efuse_data);
934 if (ALL_WORDS_DISABLED(efuse_data)) {
935 efuse_addr++;
936 continue;
937 }
938
939 hoffset |= ((efuse_data & 0xF0) >> 1);
940 hworden = efuse_data & 0x0F;
941 } else {
942 hoffset = (efuse_data >> 4) & 0x0F;
943 hworden = efuse_data & 0x0F;
944 }
945 word_cnts = Efuse_CalculateWordCnts23a(hworden);
946 /* read next header */
947 efuse_addr += (word_cnts * 2) + 1;
948 }
949
950 /* Check if we need to check next bank efuse */
951 if (efuse_addr < retU2) {
952 break; /* don't need to check next bank. */
953 }
954 }
955
956 retU2 = ((bank - 1) * EFUSE_BT_REAL_BANK_CONTENT_LEN) + efuse_addr;
957 rtw_hal_set_hwreg23a(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&retU2);
958
959 DBG_8723A("%s: CurrentSize =%d\n", __func__, retU2);
960 return retU2;
961}
962
963static u16
964Hal_EfuseGetCurrentSize(struct rtw_adapter *pAdapter, u8 efuseType)
965{
966 u16 ret = 0;
967
968 if (efuseType == EFUSE_WIFI)
969 ret = hal_EfuseGetCurrentSize_WiFi(pAdapter);
970 else
971 ret = hal_EfuseGetCurrentSize_BT(pAdapter);
972
973 return ret;
974}
975
976static u8
977Hal_EfuseWordEnableDataWrite(struct rtw_adapter *padapter,
978 u16 efuse_addr, u8 word_en, u8 *data)
979{
980 u16 tmpaddr = 0;
981 u16 start_addr = efuse_addr;
982 u8 badworden = 0x0F;
983 u8 tmpdata[PGPKT_DATA_SIZE];
984
985 memset(tmpdata, 0xFF, PGPKT_DATA_SIZE);
986
987 if (!(word_en & BIT(0))) {
988 tmpaddr = start_addr;
989 efuse_OneByteWrite23a(padapter, start_addr++, data[0]);
990 efuse_OneByteWrite23a(padapter, start_addr++, data[1]);
991
992 efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[0]);
993 efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[1]);
994 if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) {
995 badworden &= (~BIT(0));
996 }
997 }
998 if (!(word_en & BIT(1))) {
999 tmpaddr = start_addr;
1000 efuse_OneByteWrite23a(padapter, start_addr++, data[2]);
1001 efuse_OneByteWrite23a(padapter, start_addr++, data[3]);
1002
1003 efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[2]);
1004 efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[3]);
1005 if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) {
1006 badworden &= (~BIT(1));
1007 }
1008 }
1009 if (!(word_en & BIT(2))) {
1010 tmpaddr = start_addr;
1011 efuse_OneByteWrite23a(padapter, start_addr++, data[4]);
1012 efuse_OneByteWrite23a(padapter, start_addr++, data[5]);
1013
1014 efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[4]);
1015 efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[5]);
1016 if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) {
1017 badworden &= (~BIT(2));
1018 }
1019 }
1020 if (!(word_en & BIT(3))) {
1021 tmpaddr = start_addr;
1022 efuse_OneByteWrite23a(padapter, start_addr++, data[6]);
1023 efuse_OneByteWrite23a(padapter, start_addr++, data[7]);
1024
1025 efuse_OneByteRead23a(padapter, tmpaddr, &tmpdata[6]);
1026 efuse_OneByteRead23a(padapter, tmpaddr + 1, &tmpdata[7]);
1027 if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) {
1028 badworden &= (~BIT(3));
1029 }
1030 }
1031
1032 return badworden;
1033}
1034
1035static s32
1036Hal_EfusePgPacketRead(struct rtw_adapter *padapter, u8 offset, u8 *data)
1037{
1038 u8 efuse_data, word_cnts = 0;
1039 u16 efuse_addr = 0;
1040 u8 hoffset = 0, hworden = 0;
1041 u8 i;
1042 u8 max_section = 0;
1043 s32 ret;
1044
1045 if (data == NULL)
1046 return false;
1047
1048 EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION,
1049 &max_section);
1050 if (offset > max_section) {
1051 DBG_8723A("%s: Packet offset(%d) is illegal(>%d)!\n",
1052 __func__, offset, max_section);
1053 return false;
1054 }
1055
1056 memset(data, 0xFF, PGPKT_DATA_SIZE);
1057 ret = true;
1058
1059 /* */
1060 /* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the
1061 end of Efuse by CP. */
1062 /* Skip dummy parts to prevent unexpected data read from Efuse. */
1063 /* By pass right now. 2009.02.19. */
1064 /* */
1065 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
1066 if (efuse_OneByteRead23a(padapter, efuse_addr++, &efuse_data) ==
1067 false) {
1068 ret = false;
1069 break;
1070 }
1071
1072 if (efuse_data == 0xFF)
1073 break;
1074
1075 if (EXT_HEADER(efuse_data)) {
1076 hoffset = GET_HDR_OFFSET_2_0(efuse_data);
1077 efuse_OneByteRead23a(padapter, efuse_addr++, &efuse_data);
1078 if (ALL_WORDS_DISABLED(efuse_data)) {
1079 DBG_8723A("%s: Error!! All words disabled!\n",
1080 __func__);
1081 continue;
1082 }
1083
1084 hoffset |= ((efuse_data & 0xF0) >> 1);
1085 hworden = efuse_data & 0x0F;
1086 } else {
1087 hoffset = (efuse_data >> 4) & 0x0F;
1088 hworden = efuse_data & 0x0F;
1089 }
1090
1091 if (hoffset == offset) {
1092 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
1093 /* Check word enable condition in the section */
1094 if (!(hworden & (0x01 << i))) {
1095 ReadEFuseByte23a(padapter, efuse_addr++,
1096 &efuse_data);
1097 data[i * 2] = efuse_data;
1098
1099 ReadEFuseByte23a(padapter, efuse_addr++,
1100 &efuse_data);
1101 data[(i * 2) + 1] = efuse_data;
1102 }
1103 }
1104 } else {
1105 word_cnts = Efuse_CalculateWordCnts23a(hworden);
1106 efuse_addr += word_cnts * 2;
1107 }
1108 }
1109
1110 return ret;
1111}
1112
1113static u8
1114hal_EfusePgCheckAvailableAddr(struct rtw_adapter *pAdapter, u8 efuseType)
1115{
1116 u16 max_available = 0;
1117 u16 current_size;
1118
1119 EFUSE_GetEfuseDefinition23a(pAdapter, efuseType,
1120 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
1121 &max_available);
1122
1123 current_size = Efuse_GetCurrentSize23a(pAdapter, efuseType);
1124 if (current_size >= max_available) {
1125 DBG_8723A("%s: Error!! current_size(%d)>max_available(%d)\n",
1126 __func__, current_size, max_available);
1127 return false;
1128 }
1129 return true;
1130}
1131
1132static void
1133hal_EfuseConstructPGPkt(u8 offset, u8 word_en, u8 *pData,
1134 struct pg_pkt_struct *pTargetPkt)
1135{
1136 memset(pTargetPkt->data, 0xFF, PGPKT_DATA_SIZE);
1137 pTargetPkt->offset = offset;
1138 pTargetPkt->word_en = word_en;
1139 efuse_WordEnableDataRead23a(word_en, pData, pTargetPkt->data);
1140 pTargetPkt->word_cnts = Efuse_CalculateWordCnts23a(pTargetPkt->word_en);
1141}
1142
1143static u8
1144hal_EfusePartialWriteCheck(struct rtw_adapter *padapter, u8 efuseType,
1145 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1146{
1147 u8 bRet = false;
1148 u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
1149 u8 efuse_data = 0;
1150
1151 EFUSE_GetEfuseDefinition23a(padapter, efuseType,
1152 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL,
1153 &efuse_max_available_len);
1154 EFUSE_GetEfuseDefinition23a(padapter, efuseType,
1155 TYPE_EFUSE_CONTENT_LEN_BANK, &efuse_max);
1156
1157 if (efuseType == EFUSE_WIFI) {
1158 rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES,
1159 (u8 *) &startAddr);
1160 } else {
1161 rtw23a_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES,
1162 (u8 *) &startAddr);
1163 }
1164 startAddr %= efuse_max;
1165
1166 while (1) {
1167 if (startAddr >= efuse_max_available_len) {
1168 bRet = false;
1169 DBG_8723A("%s: startAddr(%d) >= efuse_max_available_"
1170 "len(%d)\n", __func__, startAddr,
1171 efuse_max_available_len);
1172 break;
1173 }
1174
1175 if (efuse_OneByteRead23a(padapter, startAddr, &efuse_data) &&
1176 (efuse_data != 0xFF)) {
1177 bRet = false;
1178 DBG_8723A("%s: Something Wrong! last bytes(%#X = 0x%02X) "
1179 "is not 0xFF\n", __func__,
1180 startAddr, efuse_data);
1181 break;
1182 } else {
1183 /* not used header, 0xff */
1184 *pAddr = startAddr;
1185 bRet = true;
1186 break;
1187 }
1188 }
1189
1190 return bRet;
1191}
1192
1193static u8
1194hal_EfusePgPacketWrite1ByteHeader(struct rtw_adapter *pAdapter, u8 efuseType,
1195 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1196{
1197 u8 pg_header = 0, tmp_header = 0;
1198 u16 efuse_addr = *pAddr;
1199 u8 repeatcnt = 0;
1200
1201 pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
1202
1203 do {
1204 efuse_OneByteWrite23a(pAdapter, efuse_addr, pg_header);
1205 efuse_OneByteRead23a(pAdapter, efuse_addr, &tmp_header);
1206 if (tmp_header != 0xFF)
1207 break;
1208 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
1209 DBG_8723A("%s: Repeat over limit for pg_header!!\n",
1210 __func__);
1211 return false;
1212 }
1213 } while (1);
1214
1215 if (tmp_header != pg_header) {
1216 DBG_8723A(KERN_ERR "%s: PG Header Fail!!(pg = 0x%02X "
1217 "read = 0x%02X)\n", __func__,
1218 pg_header, tmp_header);
1219 return false;
1220 }
1221
1222 *pAddr = efuse_addr;
1223
1224 return true;
1225}
1226
1227static u8
1228hal_EfusePgPacketWrite2ByteHeader(struct rtw_adapter *padapter, u8 efuseType,
1229 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1230{
1231 u16 efuse_addr, efuse_max_available_len = 0;
1232 u8 pg_header = 0, tmp_header = 0;
1233 u8 repeatcnt = 0;
1234
1235 EFUSE_GetEfuseDefinition23a(padapter, efuseType,
1236 TYPE_AVAILABLE_EFUSE_BYTES_BANK,
1237 &efuse_max_available_len);
1238
1239 efuse_addr = *pAddr;
1240 if (efuse_addr >= efuse_max_available_len) {
1241 DBG_8723A("%s: addr(%d) over avaliable(%d)!!\n", __func__,
1242 efuse_addr, efuse_max_available_len);
1243 return false;
1244 }
1245
1246 pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
1247
1248 do {
1249 efuse_OneByteWrite23a(padapter, efuse_addr, pg_header);
1250 efuse_OneByteRead23a(padapter, efuse_addr, &tmp_header);
1251 if (tmp_header != 0xFF)
1252 break;
1253 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
1254 DBG_8723A("%s: Repeat over limit for pg_header!!\n",
1255 __func__);
1256 return false;
1257 }
1258 } while (1);
1259
1260 if (tmp_header != pg_header) {
1261 DBG_8723A(KERN_ERR
1262 "%s: PG Header Fail!!(pg = 0x%02X read = 0x%02X)\n",
1263 __func__, pg_header, tmp_header);
1264 return false;
1265 }
1266
1267 /* to write ext_header */
1268 efuse_addr++;
1269 pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
1270
1271 do {
1272 efuse_OneByteWrite23a(padapter, efuse_addr, pg_header);
1273 efuse_OneByteRead23a(padapter, efuse_addr, &tmp_header);
1274 if (tmp_header != 0xFF)
1275 break;
1276 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_) {
1277 DBG_8723A("%s: Repeat over limit for ext_header!!\n",
1278 __func__);
1279 return false;
1280 }
1281 } while (1);
1282
1283 if (tmp_header != pg_header) { /* offset PG fail */
1284 DBG_8723A(KERN_ERR
1285 "%s: PG EXT Header Fail!!(pg = 0x%02X read = 0x%02X)\n",
1286 __func__, pg_header, tmp_header);
1287 return false;
1288 }
1289
1290 *pAddr = efuse_addr;
1291
1292 return true;
1293}
1294
1295static u8
1296hal_EfusePgPacketWriteHeader(struct rtw_adapter *padapter, u8 efuseType,
1297 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1298{
1299 u8 bRet = false;
1300
1301 if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE) {
1302 bRet = hal_EfusePgPacketWrite2ByteHeader(padapter, efuseType,
1303 pAddr, pTargetPkt);
1304 } else {
1305 bRet = hal_EfusePgPacketWrite1ByteHeader(padapter, efuseType,
1306 pAddr, pTargetPkt);
1307 }
1308
1309 return bRet;
1310}
1311
1312static u8
1313hal_EfusePgPacketWriteData(struct rtw_adapter *pAdapter, u8 efuseType,
1314 u16 *pAddr, struct pg_pkt_struct *pTargetPkt)
1315{
1316 u16 efuse_addr;
1317 u8 badworden;
1318
1319 efuse_addr = *pAddr;
1320 badworden =
1321 Efuse_WordEnableDataWrite23a(pAdapter, efuse_addr + 1,
1322 pTargetPkt->word_en, pTargetPkt->data);
1323 if (badworden != 0x0F) {
1324 DBG_8723A("%s: Fail!!\n", __func__);
1325 return false;
1326 }
1327
1328 return true;
1329}
1330
1331static s32
1332Hal_EfusePgPacketWrite(struct rtw_adapter *padapter,
1333 u8 offset, u8 word_en, u8 *pData)
1334{
1335 struct pg_pkt_struct targetPkt;
1336 u16 startAddr = 0;
1337 u8 efuseType = EFUSE_WIFI;
1338
1339 if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType))
1340 return false;
1341
1342 hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
1343
1344 if (!hal_EfusePartialWriteCheck(padapter, efuseType,
1345 &startAddr, &targetPkt))
1346 return false;
1347
1348 if (!hal_EfusePgPacketWriteHeader(padapter, efuseType,
1349 &startAddr, &targetPkt))
1350 return false;
1351
1352 if (!hal_EfusePgPacketWriteData(padapter, efuseType,
1353 &startAddr, &targetPkt))
1354 return false;
1355
1356 return true;
1357}
1358
1359static bool
1360Hal_EfusePgPacketWrite_BT(struct rtw_adapter *pAdapter,
1361 u8 offset, u8 word_en, u8 *pData)
1362{
1363 struct pg_pkt_struct targetPkt;
1364 u16 startAddr = 0;
1365 u8 efuseType = EFUSE_BT;
1366
1367 if (!hal_EfusePgCheckAvailableAddr(pAdapter, efuseType))
1368 return false;
1369
1370 hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
1371
1372 if (!hal_EfusePartialWriteCheck(pAdapter, efuseType,
1373 &startAddr, &targetPkt))
1374 return false;
1375
1376 if (!hal_EfusePgPacketWriteHeader(pAdapter, efuseType,
1377 &startAddr, &targetPkt))
1378 return false;
1379
1380 if (!hal_EfusePgPacketWriteData(pAdapter, efuseType,
1381 &startAddr, &targetPkt))
1382 return false;
1383
1384 return true;
1385}
1386
1387static struct hal_version ReadChipVersion8723A(struct rtw_adapter *padapter)
1388{
1389 u32 value32;
1390 struct hal_version ChipVersion;
1391 struct hal_data_8723a *pHalData;
1392
1393 pHalData = GET_HAL_DATA(padapter);
1394
1395 value32 = rtw_read32(padapter, REG_SYS_CFG);
1396 ChipVersion.ICType = CHIP_8723A;
1397 ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
1398 ChipVersion.RFType = RF_TYPE_1T1R;
1399 ChipVersion.VendorType =
1400 ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
1401 ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK) >> CHIP_VER_RTL_SHIFT; /* IC version (CUT) */
1402
1403 /* For regulator mode. by tynli. 2011.01.14 */
1404 pHalData->RegulatorMode = ((value32 & SPS_SEL) ?
1405 RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR);
1406
1407 value32 = rtw_read32(padapter, REG_GPIO_OUTSTS);
1408 /* ROM code version. */
1409 ChipVersion.ROMVer = ((value32 & RF_RL_ID) >> 20);
1410
1411 /* For multi-function consideration. Added by Roger, 2010.10.06. */
1412 pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
1413 value32 = rtw_read32(padapter, REG_MULTI_FUNC_CTRL);
1414 pHalData->MultiFunc |=
1415 ((value32 & WL_FUNC_EN) ? RT_MULTI_FUNC_WIFI : 0);
1416 pHalData->MultiFunc |= ((value32 & BT_FUNC_EN) ? RT_MULTI_FUNC_BT : 0);
1417 pHalData->MultiFunc |=
1418 ((value32 & GPS_FUNC_EN) ? RT_MULTI_FUNC_GPS : 0);
1419 pHalData->PolarityCtl =
1420 ((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT :
1421 RT_POLARITY_LOW_ACT);
1422 dump_chip_info23a(ChipVersion);
1423 pHalData->VersionID = ChipVersion;
1424
1425 if (IS_1T2R(ChipVersion))
1426 pHalData->rf_type = RF_1T2R;
1427 else if (IS_2T2R(ChipVersion))
1428 pHalData->rf_type = RF_2T2R;
1429 else
1430 pHalData->rf_type = RF_1T1R;
1431
1432 MSG_8723A("RF_Type is %x!!\n", pHalData->rf_type);
1433
1434 return ChipVersion;
1435}
1436
1437static void rtl8723a_read_chip_version(struct rtw_adapter *padapter)
1438{
1439 ReadChipVersion8723A(padapter);
1440}
1441
1442/* */
1443/* */
1444/* 20100209 Joseph: */
1445/* This function is used only for 92C to set REG_BCN_CTRL(0x550) register. */
1446/* We just reserve the value of the register in variable
1447 pHalData->RegBcnCtrlVal and then operate */
1448/* the value of the register via atomic operation. */
1449/* This prevents from race condition when setting this register. */
1450/* The value of pHalData->RegBcnCtrlVal is initialized in
1451 HwConfigureRTL8192CE() function. */
1452/* */
1453void SetBcnCtrlReg23a(struct rtw_adapter *padapter, u8 SetBits, u8 ClearBits)
1454{
1455 struct hal_data_8723a *pHalData;
1456 u32 addr;
1457 u8 *pRegBcnCtrlVal;
1458
1459 pHalData = GET_HAL_DATA(padapter);
1460 pRegBcnCtrlVal = (u8 *)&pHalData->RegBcnCtrlVal;
1461
1462 addr = REG_BCN_CTRL;
1463
1464 *pRegBcnCtrlVal = rtw_read8(padapter, addr);
1465 *pRegBcnCtrlVal |= SetBits;
1466 *pRegBcnCtrlVal &= ~ClearBits;
1467
1468 rtw_write8(padapter, addr, *pRegBcnCtrlVal);
1469}
1470
1471void rtl8723a_InitBeaconParameters(struct rtw_adapter *padapter)
1472{
1473 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1474
1475 rtw_write16(padapter, REG_BCN_CTRL, 0x1010);
1476 pHalData->RegBcnCtrlVal = 0x1010;
1477
1478 /* TODO: Remove these magic number */
1479 rtw_write16(padapter, REG_TBTT_PROHIBIT, 0x6404); /* ms */
1480 /* Firmware will control REG_DRVERLYINT when power saving is enable, */
1481 /* so don't set this register on STA mode. */
1482 if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == false)
1483 rtw_write8(padapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);
1484 /* 2ms */
1485 rtw_write8(padapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
1486
1487 /* Suggested by designer timchen. Change beacon AIFS to the
1488 largest number beacause test chip does not contension before
1489 sending beacon. by tynli. 2009.11.03 */
1490 rtw_write16(padapter, REG_BCNTCFG, 0x660F);
1491}
1492
1493static void ResumeTxBeacon(struct rtw_adapter *padapter)
1494{
1495 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1496
1497 /* 2010.03.01. Marked by tynli. No need to call workitem beacause
1498 we record the value */
1499 /* which should be read from register to a global variable. */
1500
1501 RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+ResumeTxBeacon\n"));
1502
1503 pHalData->RegFwHwTxQCtrl |= BIT(6);
1504 rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2, pHalData->RegFwHwTxQCtrl);
1505 rtw_write8(padapter, REG_TBTT_PROHIBIT + 1, 0xff);
1506 pHalData->RegReg542 |= BIT(0);
1507 rtw_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542);
1508}
1509
1510static void StopTxBeacon(struct rtw_adapter *padapter)
1511{
1512 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1513
1514 /* 2010.03.01. Marked by tynli. No need to call workitem beacause
1515 we record the value */
1516 /* which should be read from register to a global variable. */
1517
1518 RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+StopTxBeacon\n"));
1519
1520 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
1521 rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2, pHalData->RegFwHwTxQCtrl);
1522 rtw_write8(padapter, REG_TBTT_PROHIBIT + 1, 0x64);
1523 pHalData->RegReg542 &= ~BIT(0);
1524 rtw_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542);
1525
1526 CheckFwRsvdPageContent23a(padapter); /* 2010.06.23. Added by tynli. */
1527}
1528
1529static void _BeaconFunctionEnable(struct rtw_adapter *padapter, u8 Enable,
1530 u8 Linked)
1531{
1532 SetBcnCtrlReg23a(padapter, DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB,
1533 0);
1534 rtw_write8(padapter, REG_RD_CTRL + 1, 0x6F);
1535}
1536
1537static void rtl8723a_SetBeaconRelatedRegisters(struct rtw_adapter *padapter)
1538{
1539 u32 value32;
1540 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1541 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1542
1543 /* reset TSF, enable update TSF, correcting TSF On Beacon */
1544
1545 /* REG_BCN_INTERVAL */
1546 /* REG_BCNDMATIM */
1547 /* REG_ATIMWND */
1548 /* REG_TBTT_PROHIBIT */
1549 /* REG_DRVERLYINT */
1550 /* REG_BCN_MAX_ERR */
1551 /* REG_BCNTCFG (0x510) */
1552 /* REG_DUAL_TSF_RST */
1553 /* REG_BCN_CTRL (0x550) */
1554
1555 /* */
1556 /* ATIM window */
1557 /* */
1558 rtw_write16(padapter, REG_ATIMWND, 2);
1559
1560 /* */
1561 /* Beacon interval (in unit of TU). */
1562 /* */
1563 rtw_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
1564
1565 rtl8723a_InitBeaconParameters(padapter);
1566
1567 rtw_write8(padapter, REG_SLOT, 0x09);
1568
1569 /* */
1570 /* Reset TSF Timer to zero, added by Roger. 2008.06.24 */
1571 /* */
1572 value32 = rtw_read32(padapter, REG_TCR);
1573 value32 &= ~TSFRST;
1574 rtw_write32(padapter, REG_TCR, value32);
1575
1576 value32 |= TSFRST;
1577 rtw_write32(padapter, REG_TCR, value32);
1578
1579 /* NOTE: Fix test chip's bug (about contention windows's randomness) */
1580 if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE |
1581 WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE) == true) {
1582 rtw_write8(padapter, REG_RXTSF_OFFSET_CCK, 0x50);
1583 rtw_write8(padapter, REG_RXTSF_OFFSET_OFDM, 0x50);
1584 }
1585
1586 _BeaconFunctionEnable(padapter, true, true);
1587
1588 ResumeTxBeacon(padapter);
1589 SetBcnCtrlReg23a(padapter, DIS_BCNQ_SUB, 0);
1590}
1591
1592static void rtl8723a_GetHalODMVar(struct rtw_adapter *Adapter,
1593 enum hal_odm_variable eVariable,
1594 void *pValue1, bool bSet)
1595{
1596 switch (eVariable) {
1597 case HAL_ODM_STA_INFO:
1598 break;
1599 default:
1600 break;
1601 }
1602}
1603
1604static void rtl8723a_SetHalODMVar(struct rtw_adapter *Adapter,
1605 enum hal_odm_variable eVariable,
1606 void *pValue1, bool bSet)
1607{
1608 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1609 struct dm_odm_t *podmpriv = &pHalData->odmpriv;
1610 switch (eVariable) {
1611 case HAL_ODM_STA_INFO:
1612 {
1613 struct sta_info *psta = (struct sta_info *)pValue1;
1614
1615 if (bSet) {
1616 DBG_8723A("Set STA_(%d) info\n", psta->mac_id);
1617 ODM_CmnInfoPtrArrayHook23a(podmpriv,
1618 ODM_CMNINFO_STA_STATUS,
1619 psta->mac_id, psta);
1620 } else {
1621 DBG_8723A("Clean STA_(%d) info\n", psta->mac_id);
1622 ODM_CmnInfoPtrArrayHook23a(podmpriv,
1623 ODM_CMNINFO_STA_STATUS,
1624 psta->mac_id, NULL);
1625 }
1626 }
1627 break;
1628 case HAL_ODM_P2P_STATE:
1629 ODM_CmnInfoUpdate23a(podmpriv, ODM_CMNINFO_WIFI_DIRECT, bSet);
1630 break;
1631 case HAL_ODM_WIFI_DISPLAY_STATE:
1632 ODM_CmnInfoUpdate23a(podmpriv, ODM_CMNINFO_WIFI_DISPLAY, bSet);
1633 break;
1634 default:
1635 break;
1636 }
1637}
1638
1639static void hal_notch_filter_8723a(struct rtw_adapter *adapter, bool enable)
1640{
1641 if (enable) {
1642 DBG_8723A("Enable notch filter\n");
1643 rtw_write8(adapter, rOFDM0_RxDSP + 1,
1644 rtw_read8(adapter, rOFDM0_RxDSP + 1) | BIT1);
1645 } else {
1646 DBG_8723A("Disable notch filter\n");
1647 rtw_write8(adapter, rOFDM0_RxDSP + 1,
1648 rtw_read8(adapter, rOFDM0_RxDSP + 1) & ~BIT1);
1649 }
1650}
1651
1652s32 c2h_id_filter_ccx_8723a(u8 id)
1653{
1654 s32 ret = false;
1655 if (id == C2H_CCX_TX_RPT)
1656 ret = true;
1657
1658 return ret;
1659}
1660
1661static s32 c2h_handler_8723a(struct rtw_adapter *padapter,
1662 struct c2h_evt_hdr *c2h_evt)
1663{
1664 s32 ret = _SUCCESS;
1665 u8 i = 0;
1666
1667 if (c2h_evt == NULL) {
1668 DBG_8723A("%s c2h_evt is NULL\n", __func__);
1669 ret = _FAIL;
1670 goto exit;
1671 }
1672
1673 switch (c2h_evt->id) {
1674 case C2H_DBG:
1675 RT_TRACE(_module_hal_init_c_, _drv_info_,
1676 ("C2HCommandHandler: %s\n", c2h_evt->payload));
1677 break;
1678
1679 case C2H_CCX_TX_RPT:
1680 handle_txrpt_ccx_8723a(padapter, c2h_evt->payload);
1681 break;
1682 case C2H_EXT_RA_RPT:
1683 break;
1684 case C2H_HW_INFO_EXCH:
1685 RT_TRACE(_module_hal_init_c_, _drv_info_,
1686 ("[BT], C2H_HW_INFO_EXCH\n"));
1687 for (i = 0; i < c2h_evt->plen; i++) {
1688 RT_TRACE(_module_hal_init_c_, _drv_info_,
1689 ("[BT], tmpBuf[%d]= 0x%x\n", i,
1690 c2h_evt->payload[i]));
1691 }
1692 break;
1693
1694 case C2H_C2H_H2C_TEST:
1695 RT_TRACE(_module_hal_init_c_, _drv_info_,
1696 ("[BT], C2H_H2C_TEST\n"));
1697 RT_TRACE(_module_hal_init_c_, _drv_info_,
1698 ("[BT], tmpBuf[0]/[1]/[2]/[3]/[4]= 0x%x/ 0x%x/ "
1699 "0x%x/ 0x%x/ 0x%x\n", c2h_evt->payload[0],
1700 c2h_evt->payload[1], c2h_evt->payload[2],
1701 c2h_evt->payload[3], c2h_evt->payload[4]));
1702 break;
1703
1704#ifdef CONFIG_8723AU_BT_COEXIST
1705 case C2H_BT_INFO:
1706 DBG_8723A("%s , Got C2H_BT_INFO \n", __func__);
1707 BT_FwC2hBtInfo(padapter, c2h_evt->payload, c2h_evt->plen);
1708 break;
1709#endif
1710
1711 default:
1712 ret = _FAIL;
1713 break;
1714 }
1715
1716exit:
1717 return ret;
1718}
1719
1720void rtl8723a_set_hal_ops(struct hal_ops *pHalFunc)
1721{
1722 pHalFunc->free_hal_data = &rtl8723a_free_hal_data;
1723
1724 pHalFunc->dm_init = &rtl8723a_init_dm_priv;
1725 pHalFunc->dm_deinit = &rtl8723a_deinit_dm_priv;
1726
1727 pHalFunc->read_chip_version = &rtl8723a_read_chip_version;
1728
1729 pHalFunc->set_bwmode_handler = &PHY_SetBWMode23a8723A;
1730 pHalFunc->set_channel_handler = &PHY_SwChnl8723A;
1731
1732 pHalFunc->hal_dm_watchdog = &rtl8723a_HalDmWatchDog;
1733
1734 pHalFunc->SetBeaconRelatedRegistersHandler =
1735 &rtl8723a_SetBeaconRelatedRegisters;
1736
1737 pHalFunc->Add_RateATid = &rtl8723a_add_rateatid;
1738 pHalFunc->run_thread = &rtl8723a_start_thread;
1739 pHalFunc->cancel_thread = &rtl8723a_stop_thread;
1740
1741 pHalFunc->read_bbreg = &PHY_QueryBBReg;
1742 pHalFunc->write_bbreg = &PHY_SetBBReg;
1743 pHalFunc->read_rfreg = &PHY_QueryRFReg;
1744 pHalFunc->write_rfreg = &PHY_SetRFReg;
1745
1746 /* Efuse related function */
1747 pHalFunc->EfusePowerSwitch = &Hal_EfusePowerSwitch;
1748 pHalFunc->ReadEFuse = &Hal_ReadEFuse;
1749 pHalFunc->EFUSEGetEfuseDefinition = &Hal_GetEfuseDefinition;
1750 pHalFunc->EfuseGetCurrentSize = &Hal_EfuseGetCurrentSize;
1751 pHalFunc->Efuse_PgPacketRead23a = &Hal_EfusePgPacketRead;
1752 pHalFunc->Efuse_PgPacketWrite23a = &Hal_EfusePgPacketWrite;
1753 pHalFunc->Efuse_WordEnableDataWrite23a = &Hal_EfuseWordEnableDataWrite;
1754 pHalFunc->Efuse_PgPacketWrite23a_BT = &Hal_EfusePgPacketWrite_BT;
1755
1756 pHalFunc->sreset_init_value23a = &sreset_init_value23a;
1757 pHalFunc->sreset_reset_value23a = &sreset_reset_value23a;
1758 pHalFunc->silentreset = &sreset_reset;
1759 pHalFunc->sreset_xmit_status_check = &rtl8723a_sreset_xmit_status_check;
1760 pHalFunc->sreset_linked_status_check =
1761 &rtl8723a_sreset_linked_status_check;
1762 pHalFunc->sreset_get_wifi_status23a = &sreset_get_wifi_status23a;
1763 pHalFunc->sreset_inprogress = &sreset_inprogress;
1764 pHalFunc->GetHalODMVarHandler = &rtl8723a_GetHalODMVar;
1765 pHalFunc->SetHalODMVarHandler = &rtl8723a_SetHalODMVar;
1766
1767 pHalFunc->hal_notch_filter = &hal_notch_filter_8723a;
1768
1769 pHalFunc->c2h_handler = c2h_handler_8723a;
1770 pHalFunc->c2h_id_filter_ccx = c2h_id_filter_ccx_8723a;
1771}
1772
1773void rtl8723a_InitAntenna_Selection(struct rtw_adapter *padapter)
1774{
1775 struct hal_data_8723a *pHalData;
1776 u8 val;
1777
1778 pHalData = GET_HAL_DATA(padapter);
1779
1780 val = rtw_read8(padapter, REG_LEDCFG2);
1781 /* Let 8051 take control antenna settting */
1782 val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */
1783 rtw_write8(padapter, REG_LEDCFG2, val);
1784}
1785
1786void rtl8723a_CheckAntenna_Selection(struct rtw_adapter *padapter)
1787{
1788 struct hal_data_8723a *pHalData;
1789 u8 val;
1790
1791 pHalData = GET_HAL_DATA(padapter);
1792
1793 val = rtw_read8(padapter, REG_LEDCFG2);
1794 /* Let 8051 take control antenna settting */
1795 if (!(val & BIT(7))) {
1796 val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */
1797 rtw_write8(padapter, REG_LEDCFG2, val);
1798 }
1799}
1800
1801void rtl8723a_DeinitAntenna_Selection(struct rtw_adapter *padapter)
1802{
1803 struct hal_data_8723a *pHalData;
1804 u8 val;
1805
1806 pHalData = GET_HAL_DATA(padapter);
1807 val = rtw_read8(padapter, REG_LEDCFG2);
1808 /* Let 8051 take control antenna settting */
1809 val &= ~BIT(7); /* DPDT_SEL_EN, clear 0x4C[23] */
1810 rtw_write8(padapter, REG_LEDCFG2, val);
1811}
1812
1813void rtl8723a_init_default_value(struct rtw_adapter *padapter)
1814{
1815 struct hal_data_8723a *pHalData;
1816 struct dm_priv *pdmpriv;
1817 u8 i;
1818
1819 pHalData = GET_HAL_DATA(padapter);
1820 pdmpriv = &pHalData->dmpriv;
1821
1822 /* init default value */
1823 pHalData->fw_ractrl = false;
1824 pHalData->bIQKInitialized = false;
1825 if (!padapter->pwrctrlpriv.bkeepfwalive)
1826 pHalData->LastHMEBoxNum = 0;
1827
1828 pHalData->bIQKInitialized = false;
1829
1830 /* init dm default value */
1831 pdmpriv->TM_Trigger = 0; /* for IQK */
1832/* pdmpriv->binitialized = false; */
1833/* pdmpriv->prv_traffic_idx = 3; */
1834/* pdmpriv->initialize = 0; */
1835
1836 pdmpriv->ThermalValue_HP_index = 0;
1837 for (i = 0; i < HP_THERMAL_NUM; i++)
1838 pdmpriv->ThermalValue_HP[i] = 0;
1839
1840 /* init Efuse variables */
1841 pHalData->EfuseUsedBytes = 0;
1842 pHalData->BTEfuseUsedBytes = 0;
1843}
1844
1845u8 GetEEPROMSize8723A(struct rtw_adapter *padapter)
1846{
1847 u8 size = 0;
1848 u32 cr;
1849
1850 cr = rtw_read16(padapter, REG_9346CR);
1851 /* 6: EEPROM used is 93C46, 4: boot from E-Fuse. */
1852 size = (cr & BOOT_FROM_EEPROM) ? 6 : 4;
1853
1854 MSG_8723A("EEPROM type is %s\n", size == 4 ? "E-FUSE" : "93C46");
1855
1856 return size;
1857}
1858
1859/* */
1860/* */
1861/* LLT R/W/Init function */
1862/* */
1863/* */
1864static s32 _LLTWrite(struct rtw_adapter *padapter, u32 address, u32 data)
1865{
1866 s32 status = _SUCCESS;
1867 s32 count = 0;
1868 u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) |
1869 _LLT_OP(_LLT_WRITE_ACCESS);
1870 u16 LLTReg = REG_LLT_INIT;
1871
1872 rtw_write32(padapter, LLTReg, value);
1873
1874 /* polling */
1875 do {
1876 value = rtw_read32(padapter, LLTReg);
1877 if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) {
1878 break;
1879 }
1880
1881 if (count > POLLING_LLT_THRESHOLD) {
1882 RT_TRACE(_module_hal_init_c_, _drv_err_,
1883 ("Failed to polling write LLT done at "
1884 "address %d!\n", address));
1885 status = _FAIL;
1886 break;
1887 }
1888 } while (count++);
1889
1890 return status;
1891}
1892
1893s32 InitLLTTable23a(struct rtw_adapter *padapter, u32 boundary)
1894{
1895 s32 status = _SUCCESS;
1896 u32 i;
1897 u32 txpktbuf_bndy = boundary;
1898 u32 Last_Entry_Of_TxPktBuf = LAST_ENTRY_OF_TX_PKT_BUFFER;
1899
1900 for (i = 0; i < (txpktbuf_bndy - 1); i++) {
1901 status = _LLTWrite(padapter, i, i + 1);
1902 if (_SUCCESS != status) {
1903 return status;
1904 }
1905 }
1906
1907 /* end of list */
1908 status = _LLTWrite(padapter, (txpktbuf_bndy - 1), 0xFF);
1909 if (_SUCCESS != status) {
1910 return status;
1911 }
1912
1913 /* Make the other pages as ring buffer */
1914 /* This ring buffer is used as beacon buffer if we config this
1915 MAC as two MAC transfer. */
1916 /* Otherwise used as local loopback buffer. */
1917 for (i = txpktbuf_bndy; i < Last_Entry_Of_TxPktBuf; i++) {
1918 status = _LLTWrite(padapter, i, (i + 1));
1919 if (_SUCCESS != status) {
1920 return status;
1921 }
1922 }
1923
1924 /* Let last entry point to the start entry of ring buffer */
1925 status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy);
1926 if (_SUCCESS != status) {
1927 return status;
1928 }
1929
1930 return status;
1931}
1932
1933static void _DisableGPIO(struct rtw_adapter *padapter)
1934{
1935/***************************************
1936j. GPIO_PIN_CTRL 0x44[31:0]= 0x000
1937k.Value = GPIO_PIN_CTRL[7:0]
1938l. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); write external PIN level
1939m. GPIO_MUXCFG 0x42 [15:0] = 0x0780
1940n. LEDCFG 0x4C[15:0] = 0x8080
1941***************************************/
1942 u32 value32;
1943 u32 u4bTmp;
1944
1945 /* 1. Disable GPIO[7:0] */
1946 rtw_write16(padapter, REG_GPIO_PIN_CTRL + 2, 0x0000);
1947 value32 = rtw_read32(padapter, REG_GPIO_PIN_CTRL) & 0xFFFF00FF;
1948 u4bTmp = value32 & 0x000000FF;
1949 value32 |= ((u4bTmp << 8) | 0x00FF0000);
1950 rtw_write32(padapter, REG_GPIO_PIN_CTRL, value32);
1951
1952 /* */
1953 /* <Roger_Notes> For RTL8723u multi-function configuration which
1954 was autoload from Efuse offset 0x0a and 0x0b, */
1955 /* WLAN HW GPIO[9], GPS HW GPIO[10] and BT HW GPIO[11]. */
1956 /* Added by Roger, 2010.10.07. */
1957 /* */
1958 /* 2. Disable GPIO[8] and GPIO[12] */
1959
1960 /* Configure all pins as input mode. */
1961 rtw_write16(padapter, REG_GPIO_IO_SEL_2, 0x0000);
1962 value32 = rtw_read32(padapter, REG_GPIO_PIN_CTRL_2) & 0xFFFF001F;
1963 u4bTmp = value32 & 0x0000001F;
1964 /* Set pin 8, 10, 11 and pin 12 to output mode. */
1965 value32 |= ((u4bTmp << 8) | 0x001D0000);
1966 rtw_write32(padapter, REG_GPIO_PIN_CTRL_2, value32);
1967
1968 /* 3. Disable LED0 & 1 */
1969 rtw_write16(padapter, REG_LEDCFG0, 0x8080);
1970} /* end of _DisableGPIO() */
1971
1972static void _DisableRFAFEAndResetBB8192C(struct rtw_adapter *padapter)
1973{
1974/**************************************
1975a. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue
1976b. RF path 0 offset 0x00 = 0x00 disable RF
1977c. APSD_CTRL 0x600[7:0] = 0x40
1978d. SYS_FUNC_EN 0x02[7:0] = 0x16 reset BB state machine
1979e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine
1980***************************************/
1981 u8 eRFPath = 0, value8 = 0;
1982
1983 rtw_write8(padapter, REG_TXPAUSE, 0xFF);
1984
1985 PHY_SetRFReg(padapter, (enum RF_RADIO_PATH) eRFPath, 0x0, bMaskByte0, 0x0);
1986
1987 value8 |= APSDOFF;
1988 rtw_write8(padapter, REG_APSD_CTRL, value8); /* 0x40 */
1989
1990 /* Set BB reset at first */
1991 value8 = 0;
1992 value8 |= (FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTn);
1993 rtw_write8(padapter, REG_SYS_FUNC_EN, value8); /* 0x16 */
1994
1995 /* Set global reset. */
1996 value8 &= ~FEN_BB_GLB_RSTn;
1997 rtw_write8(padapter, REG_SYS_FUNC_EN, value8); /* 0x14 */
1998
1999 /* 2010/08/12 MH We need to set BB/GLBAL reset to save power
2000 for SS mode. */
2001
2002/* RT_TRACE(COMP_INIT, DBG_LOUD, ("======> RF off and reset BB.\n")); */
2003}
2004
2005static void _DisableRFAFEAndResetBB(struct rtw_adapter *padapter)
2006{
2007 _DisableRFAFEAndResetBB8192C(padapter);
2008}
2009
2010static void _ResetDigitalProcedure1_92C(struct rtw_adapter *padapter,
2011 bool bWithoutHWSM)
2012{
2013 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2014
2015 if (IS_FW_81xxC(padapter) && (pHalData->FirmwareVersion <= 0x20)) {
2016 /*****************************
2017 f. MCUFWDL 0x80[7:0]= 0 reset MCU ready status
2018 g. SYS_FUNC_EN 0x02[10]= 0 reset MCU register, (8051 reset)
2019 h. SYS_FUNC_EN 0x02[15-12]= 5 reset MAC register, DCORE
2020 i. SYS_FUNC_EN 0x02[10]= 1 enable MCU register,
2021 (8051 enable)
2022 ******************************/
2023 u16 valu16 = 0;
2024 rtw_write8(padapter, REG_MCUFWDL, 0);
2025
2026 valu16 = rtw_read16(padapter, REG_SYS_FUNC_EN);
2027 /* reset MCU , 8051 */
2028 rtw_write16(padapter, REG_SYS_FUNC_EN, (valu16 & (~FEN_CPUEN)));
2029
2030 valu16 = rtw_read16(padapter, REG_SYS_FUNC_EN) & 0x0FFF;
2031 rtw_write16(padapter, REG_SYS_FUNC_EN,
2032 (valu16 | (FEN_HWPDN | FEN_ELDR))); /* reset MAC */
2033
2034 valu16 = rtw_read16(padapter, REG_SYS_FUNC_EN);
2035 /* enable MCU , 8051 */
2036 rtw_write16(padapter, REG_SYS_FUNC_EN, (valu16 | FEN_CPUEN));
2037 } else {
2038 u8 retry_cnts = 0;
2039
2040 /* 2010/08/12 MH For USB SS, we can not stop 8051 when we
2041 are trying to enter IPS/HW&SW radio off. For
2042 S3/S4/S5/Disable, we can stop 8051 because */
2043 /* we will init FW when power on again. */
2044 /* if (!pDevice->RegUsbSS) */
2045 /* If we want to SS mode, we can not reset 8051. */
2046 if (rtw_read8(padapter, REG_MCUFWDL) & BIT1) {
2047 /* IF fw in RAM code, do reset */
2048 if (padapter->bFWReady) {
2049 /* 2010/08/25 MH Accordign to RD alfred's
2050 suggestion, we need to disable other */
2051 /* HRCV INT to influence 8051 reset. */
2052 rtw_write8(padapter, REG_FWIMR, 0x20);
2053 /* 2011/02/15 MH According to Alex's
2054 suggestion, close mask to prevent
2055 incorrect FW write operation. */
2056 rtw_write8(padapter, REG_FTIMR, 0x00);
2057 rtw_write8(padapter, REG_FSIMR, 0x00);
2058
2059 /* 8051 reset by self */
2060 rtw_write8(padapter, REG_HMETFR + 3, 0x20);
2061
2062 while ((retry_cnts++ < 100) &&
2063 (FEN_CPUEN &
2064 rtw_read16(padapter, REG_SYS_FUNC_EN))) {
2065 udelay(50); /* us */
2066 }
2067
2068 if (retry_cnts >= 100) {
2069 /* Reset MAC and Enable 8051 */
2070 rtw_write8(padapter,
2071 REG_SYS_FUNC_EN + 1, 0x50);
2072 mdelay(10);
2073 }
2074 }
2075 }
2076 /* Reset MAC and Enable 8051 */
2077 rtw_write8(padapter, REG_SYS_FUNC_EN + 1, 0x54);
2078 rtw_write8(padapter, REG_MCUFWDL, 0);
2079 }
2080
2081 if (bWithoutHWSM) {
2082 /*****************************
2083 Without HW auto state machine
2084 g. SYS_CLKR 0x08[15:0] = 0x30A3 disable MAC clock
2085 h. AFE_PLL_CTRL 0x28[7:0] = 0x80 disable AFE PLL
2086 i. AFE_XTAL_CTRL 0x24[15:0] = 0x880F gated AFE DIG_CLOCK
2087 j. SYS_ISO_CTRL 0x00[7:0] = 0xF9 isolated digital to PON
2088 ******************************/
2089 /* modify to 0x70A3 by Scott. */
2090 rtw_write16(padapter, REG_SYS_CLKR, 0x70A3);
2091 rtw_write8(padapter, REG_AFE_PLL_CTRL, 0x80);
2092 rtw_write16(padapter, REG_AFE_XTAL_CTRL, 0x880F);
2093 rtw_write8(padapter, REG_SYS_ISO_CTRL, 0xF9);
2094 } else {
2095 /* Disable all RF/BB power */
2096 rtw_write8(padapter, REG_RF_CTRL, 0x00);
2097 }
2098}
2099
2100static void _ResetDigitalProcedure1(struct rtw_adapter *padapter,
2101 bool bWithoutHWSM)
2102{
2103 _ResetDigitalProcedure1_92C(padapter, bWithoutHWSM);
2104}
2105
2106static void _ResetDigitalProcedure2(struct rtw_adapter *padapter)
2107{
2108/*****************************
2109k. SYS_FUNC_EN 0x03[7:0] = 0x44 disable ELDR runction
2110l. SYS_CLKR 0x08[15:0] = 0x3083 disable ELDR clock
2111m. SYS_ISO_CTRL 0x01[7:0] = 0x83 isolated ELDR to PON
2112******************************/
2113 /* modify to 0x70a3 by Scott. */
2114 rtw_write16(padapter, REG_SYS_CLKR, 0x70a3);
2115 /* modify to 0x82 by Scott. */
2116 rtw_write8(padapter, REG_SYS_ISO_CTRL + 1, 0x82);
2117}
2118
2119static void _DisableAnalog(struct rtw_adapter *padapter, bool bWithoutHWSM)
2120{
2121 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2122 u16 value16 = 0;
2123 u8 value8 = 0;
2124
2125 if (bWithoutHWSM) {
2126 /*****************************
2127 n. LDOA15_CTRL 0x20[7:0] = 0x04 disable A15 power
2128 o. LDOV12D_CTRL 0x21[7:0] = 0x54 disable digital core power
2129 r. When driver call disable, the ASIC will turn off remaining
2130 clock automatically
2131 ******************************/
2132
2133 rtw_write8(padapter, REG_LDOA15_CTRL, 0x04);
2134 /* rtw_write8(padapter, REG_LDOV12D_CTRL, 0x54); */
2135
2136 value8 = rtw_read8(padapter, REG_LDOV12D_CTRL);
2137 value8 &= (~LDV12_EN);
2138 rtw_write8(padapter, REG_LDOV12D_CTRL, value8);
2139/* RT_TRACE(COMP_INIT, DBG_LOUD,
2140 (" REG_LDOV12D_CTRL Reg0x21:0x%02x.\n", value8)); */
2141 }
2142
2143 /*****************************
2144 h. SPS0_CTRL 0x11[7:0] = 0x23 enter PFM mode
2145 i. APS_FSMCO 0x04[15:0] = 0x4802 set USB suspend
2146 ******************************/
2147 value8 = 0x23;
2148 if (IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID))
2149 value8 |= BIT3;
2150
2151 rtw_write8(padapter, REG_SPS0_CTRL, value8);
2152
2153 if (bWithoutHWSM) {
2154 /* value16 |= (APDM_HOST | FSM_HSUS |/PFM_ALDN); */
2155 /* 2010/08/31 According to Filen description, we need to
2156 use HW to shut down 8051 automatically. */
2157 /* Becasue suspend operatione need the asistance of 8051
2158 to wait for 3ms. */
2159 value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN);
2160 } else {
2161 value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN);
2162 }
2163
2164 rtw_write16(padapter, REG_APS_FSMCO, value16); /* 0x4802 */
2165
2166 rtw_write8(padapter, REG_RSV_CTRL, 0x0e);
2167}
2168
2169/* HW Auto state machine */
2170s32 CardDisableHWSM(struct rtw_adapter *padapter, u8 resetMCU)
2171{
2172 int rtStatus = _SUCCESS;
2173
2174 if (padapter->bSurpriseRemoved) {
2175 return rtStatus;
2176 }
2177 /* RF Off Sequence ==== */
2178 _DisableRFAFEAndResetBB(padapter);
2179
2180 /* ==== Reset digital sequence ====== */
2181 _ResetDigitalProcedure1(padapter, false);
2182
2183 /* ==== Pull GPIO PIN to balance level and LED control ====== */
2184 _DisableGPIO(padapter);
2185
2186 /* ==== Disable analog sequence === */
2187 _DisableAnalog(padapter, false);
2188
2189 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2190 ("======> Card disable finished.\n"));
2191
2192 return rtStatus;
2193}
2194
2195/* without HW Auto state machine */
2196s32 CardDisableWithoutHWSM(struct rtw_adapter *padapter)
2197{
2198 s32 rtStatus = _SUCCESS;
2199
2200 /* RT_TRACE(COMP_INIT, DBG_LOUD,
2201 ("======> Card Disable Without HWSM .\n")); */
2202 if (padapter->bSurpriseRemoved) {
2203 return rtStatus;
2204 }
2205
2206 /* RF Off Sequence ==== */
2207 _DisableRFAFEAndResetBB(padapter);
2208
2209 /* ==== Reset digital sequence ====== */
2210 _ResetDigitalProcedure1(padapter, true);
2211
2212 /* ==== Pull GPIO PIN to balance level and LED control ====== */
2213 _DisableGPIO(padapter);
2214
2215 /* ==== Reset digital sequence ====== */
2216 _ResetDigitalProcedure2(padapter);
2217
2218 /* ==== Disable analog sequence === */
2219 _DisableAnalog(padapter, true);
2220
2221 /* RT_TRACE(COMP_INIT, DBG_LOUD,
2222 ("<====== Card Disable Without HWSM .\n")); */
2223 return rtStatus;
2224}
2225
2226void Hal_InitPGData(struct rtw_adapter *padapter, u8 *PROMContent)
2227{
2228 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
2229
2230 if (false == pEEPROM->bautoload_fail_flag) { /* autoload OK. */
2231 if (!pEEPROM->EepromOrEfuse) {
2232 /* Read EFUSE real map to shadow. */
2233 EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI);
2234 memcpy((void *)PROMContent,
2235 (void *)pEEPROM->efuse_eeprom_data,
2236 HWSET_MAX_SIZE);
2237 }
2238 } else { /* autoload fail */
2239 RT_TRACE(_module_hci_hal_init_c_, _drv_notice_,
2240 ("AutoLoad Fail reported from CR9346!!\n"));
2241/* pHalData->AutoloadFailFlag = true; */
2242 /* update to default value 0xFF */
2243 if (false == pEEPROM->EepromOrEfuse)
2244 EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI);
2245 memcpy((void *)PROMContent, (void *)pEEPROM->efuse_eeprom_data,
2246 HWSET_MAX_SIZE);
2247 }
2248}
2249
2250void Hal_EfuseParseIDCode(struct rtw_adapter *padapter, u8 *hwinfo)
2251{
2252 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
2253/* struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); */
2254 u16 EEPROMId;
2255
2256 /* Checl 0x8129 again for making sure autoload status!! */
2257 EEPROMId = le16_to_cpu(*((u16 *) hwinfo));
2258 if (EEPROMId != RTL_EEPROM_ID) {
2259 DBG_8723A("EEPROM ID(%#x) is invalid!!\n", EEPROMId);
2260 pEEPROM->bautoload_fail_flag = true;
2261 } else {
2262 pEEPROM->bautoload_fail_flag = false;
2263 }
2264
2265 RT_TRACE(_module_hal_init_c_, _drv_info_,
2266 ("EEPROM ID = 0x%04x\n", EEPROMId));
2267}
2268
2269static void Hal_EEValueCheck(u8 EEType, void *pInValue, void *pOutValue)
2270{
2271 switch (EEType) {
2272 case EETYPE_TX_PWR:
2273 {
2274 u8 *pIn, *pOut;
2275 pIn = (u8 *) pInValue;
2276 pOut = (u8 *) pOutValue;
2277 if (*pIn >= 0 && *pIn <= 63) {
2278 *pOut = *pIn;
2279 } else {
2280 RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
2281 ("EETYPE_TX_PWR, value =%d is invalid, set "
2282 "to default = 0x%x\n",
2283 *pIn, EEPROM_Default_TxPowerLevel));
2284 *pOut = EEPROM_Default_TxPowerLevel;
2285 }
2286 }
2287 break;
2288 default:
2289 break;
2290 }
2291}
2292
2293static void
2294Hal_ReadPowerValueFromPROM_8723A(struct txpowerinfo *pwrInfo,
2295 u8 *PROMContent, bool AutoLoadFail)
2296{
2297 u32 rfPath, eeAddr, group, rfPathMax = 1;
2298
2299 memset(pwrInfo, 0, sizeof(*pwrInfo));
2300
2301 if (AutoLoadFail) {
2302 for (group = 0; group < MAX_CHNL_GROUP; group++) {
2303 for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
2304 pwrInfo->CCKIndex[rfPath][group] =
2305 EEPROM_Default_TxPowerLevel;
2306 pwrInfo->HT40_1SIndex[rfPath][group] =
2307 EEPROM_Default_TxPowerLevel;
2308 pwrInfo->HT40_2SIndexDiff[rfPath][group] =
2309 EEPROM_Default_HT40_2SDiff;
2310 pwrInfo->HT20IndexDiff[rfPath][group] =
2311 EEPROM_Default_HT20_Diff;
2312 pwrInfo->OFDMIndexDiff[rfPath][group] =
2313 EEPROM_Default_LegacyHTTxPowerDiff;
2314 pwrInfo->HT40MaxOffset[rfPath][group] =
2315 EEPROM_Default_HT40_PwrMaxOffset;
2316 pwrInfo->HT20MaxOffset[rfPath][group] =
2317 EEPROM_Default_HT20_PwrMaxOffset;
2318 }
2319 }
2320 pwrInfo->TSSI_A[0] = EEPROM_Default_TSSI;
2321 return;
2322 }
2323
2324 for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
2325 for (group = 0; group < MAX_CHNL_GROUP; group++) {
2326 eeAddr =
2327 EEPROM_CCK_TX_PWR_INX_8723A + (rfPath * 3) + group;
2328 /* pwrInfo->CCKIndex[rfPath][group] =
2329 PROMContent[eeAddr]; */
2330 Hal_EEValueCheck(EETYPE_TX_PWR, &PROMContent[eeAddr],
2331 &pwrInfo->CCKIndex[rfPath][group]);
2332 eeAddr = EEPROM_HT40_1S_TX_PWR_INX_8723A +
2333 (rfPath * 3) + group;
2334 /* pwrInfo->HT40_1SIndex[rfPath][group] =
2335 PROMContent[eeAddr]; */
2336 Hal_EEValueCheck(EETYPE_TX_PWR, &PROMContent[eeAddr],
2337 &pwrInfo->HT40_1SIndex[rfPath][group]);
2338 }
2339 }
2340
2341 for (group = 0; group < MAX_CHNL_GROUP; group++) {
2342 for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
2343 pwrInfo->HT40_2SIndexDiff[rfPath][group] = 0;
2344 pwrInfo->HT20IndexDiff[rfPath][group] =
2345 (PROMContent
2346 [EEPROM_HT20_TX_PWR_INX_DIFF_8723A +
2347 group] >> (rfPath * 4)) & 0xF;
2348 /* 4bit sign number to 8 bit sign number */
2349 if (pwrInfo->HT20IndexDiff[rfPath][group] & BIT3)
2350 pwrInfo->HT20IndexDiff[rfPath][group] |= 0xF0;
2351
2352 pwrInfo->OFDMIndexDiff[rfPath][group] =
2353 (PROMContent[EEPROM_OFDM_TX_PWR_INX_DIFF_8723A +
2354 group] >> (rfPath * 4)) & 0xF;
2355
2356 pwrInfo->HT40MaxOffset[rfPath][group] =
2357 (PROMContent[EEPROM_HT40_MAX_PWR_OFFSET_8723A +
2358 group] >> (rfPath * 4)) & 0xF;
2359
2360 pwrInfo->HT20MaxOffset[rfPath][group] =
2361 (PROMContent[EEPROM_HT20_MAX_PWR_OFFSET_8723A +
2362 group] >> (rfPath * 4)) & 0xF;
2363 }
2364 }
2365
2366 pwrInfo->TSSI_A[0] = PROMContent[EEPROM_TSSI_A_8723A];
2367}
2368
2369static u8 Hal_GetChnlGroup(u8 chnl)
2370{
2371 u8 group = 0;
2372
2373 if (chnl < 3) /* Cjanel 1-3 */
2374 group = 0;
2375 else if (chnl < 9) /* Channel 4-9 */
2376 group = 1;
2377 else /* Channel 10-14 */
2378 group = 2;
2379
2380 return group;
2381}
2382
2383void
2384Hal_EfuseParsetxpowerinfo_8723A(struct rtw_adapter *padapter,
2385 u8 *PROMContent, bool AutoLoadFail)
2386{
2387 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2388 struct txpowerinfo pwrInfo;
2389 u8 rfPath, ch, group, rfPathMax = 1;
2390 u8 pwr, diff;
2391
2392 Hal_ReadPowerValueFromPROM_8723A(&pwrInfo, PROMContent, AutoLoadFail);
2393 for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
2394 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
2395 group = Hal_GetChnlGroup(ch);
2396
2397 pHalData->TxPwrLevelCck[rfPath][ch] =
2398 pwrInfo.CCKIndex[rfPath][group];
2399 pHalData->TxPwrLevelHT40_1S[rfPath][ch] =
2400 pwrInfo.HT40_1SIndex[rfPath][group];
2401
2402 pHalData->TxPwrHt20Diff[rfPath][ch] =
2403 pwrInfo.HT20IndexDiff[rfPath][group];
2404 pHalData->TxPwrLegacyHtDiff[rfPath][ch] =
2405 pwrInfo.OFDMIndexDiff[rfPath][group];
2406 pHalData->PwrGroupHT20[rfPath][ch] =
2407 pwrInfo.HT20MaxOffset[rfPath][group];
2408 pHalData->PwrGroupHT40[rfPath][ch] =
2409 pwrInfo.HT40MaxOffset[rfPath][group];
2410
2411 pwr = pwrInfo.HT40_1SIndex[rfPath][group];
2412 diff = pwrInfo.HT40_2SIndexDiff[rfPath][group];
2413
2414 pHalData->TxPwrLevelHT40_2S[rfPath][ch] =
2415 (pwr > diff) ? (pwr - diff) : 0;
2416 }
2417 }
2418 for (rfPath = 0; rfPath < RF_PATH_MAX; rfPath++) {
2419 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
2420 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2421 ("RF(%u)-Ch(%u) [CCK / HT40_1S / HT40_2S] = "
2422 "[0x%x / 0x%x / 0x%x]\n",
2423 rfPath, ch,
2424 pHalData->TxPwrLevelCck[rfPath][ch],
2425 pHalData->TxPwrLevelHT40_1S[rfPath][ch],
2426 pHalData->TxPwrLevelHT40_2S[rfPath][ch]));
2427
2428 }
2429 }
2430 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
2431 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2432 ("RF-A Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch,
2433 pHalData->TxPwrHt20Diff[RF_PATH_A][ch],
2434 pHalData->TxPwrHt20Diff[RF_PATH_A][ch]));
2435 }
2436 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++)
2437 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2438 ("RF-A Legacy to Ht40 Diff[%u] = 0x%x\n", ch,
2439 pHalData->TxPwrLegacyHtDiff[RF_PATH_A][ch]));
2440 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
2441 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2442 ("RF-B Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch,
2443 pHalData->TxPwrHt20Diff[RF_PATH_B][ch],
2444 pHalData->TxPwrHt20Diff[RF_PATH_B][ch]));
2445 }
2446 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++)
2447 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2448 ("RF-B Legacy to HT40 Diff[%u] = 0x%x\n", ch,
2449 pHalData->TxPwrLegacyHtDiff[RF_PATH_B][ch]));
2450 if (!AutoLoadFail) {
2451 struct registry_priv *registry_par = &padapter->registrypriv;
2452 if (registry_par->regulatory_tid == 0xff) {
2453 if (PROMContent[RF_OPTION1_8723A] == 0xff)
2454 pHalData->EEPROMRegulatory = 0;
2455 else
2456 pHalData->EEPROMRegulatory =
2457 PROMContent[RF_OPTION1_8723A] & 0x7;
2458 } else {
2459 pHalData->EEPROMRegulatory =
2460 registry_par->regulatory_tid;
2461 }
2462 } else {
2463 pHalData->EEPROMRegulatory = 0;
2464 }
2465 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2466 ("EEPROMRegulatory = 0x%x\n", pHalData->EEPROMRegulatory));
2467
2468 if (!AutoLoadFail)
2469 pHalData->bTXPowerDataReadFromEEPORM = true;
2470}
2471
2472void
2473Hal_EfuseParseBTCoexistInfo_8723A(struct rtw_adapter *padapter,
2474 u8 *hwinfo, bool AutoLoadFail)
2475{
2476 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2477 u8 tempval;
2478 u32 tmpu4;
2479
2480 if (!AutoLoadFail) {
2481 tmpu4 = rtw_read32(padapter, REG_MULTI_FUNC_CTRL);
2482 if (tmpu4 & BT_FUNC_EN)
2483 pHalData->EEPROMBluetoothCoexist = 1;
2484 else
2485 pHalData->EEPROMBluetoothCoexist = 0;
2486 pHalData->EEPROMBluetoothType = BT_RTL8723A;
2487
2488 /* The following need to be checked with newer version of */
2489 /* eeprom spec */
2490 tempval = hwinfo[RF_OPTION4_8723A];
2491 pHalData->EEPROMBluetoothAntNum = (tempval & 0x1);
2492 pHalData->EEPROMBluetoothAntIsolation = ((tempval & 0x10) >> 4);
2493 pHalData->EEPROMBluetoothRadioShared = ((tempval & 0x20) >> 5);
2494 } else {
2495 pHalData->EEPROMBluetoothCoexist = 0;
2496 pHalData->EEPROMBluetoothType = BT_RTL8723A;
2497 pHalData->EEPROMBluetoothAntNum = Ant_x2;
2498 pHalData->EEPROMBluetoothAntIsolation = 0;
2499 pHalData->EEPROMBluetoothRadioShared = BT_Radio_Shared;
2500 }
2501#ifdef CONFIG_8723AU_BT_COEXIST
2502 BT_InitHalVars(padapter);
2503#endif
2504}
2505
2506void
2507Hal_EfuseParseEEPROMVer(struct rtw_adapter *padapter,
2508 u8 *hwinfo, bool AutoLoadFail)
2509{
2510 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2511
2512 if (!AutoLoadFail)
2513 pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_8723A];
2514 else
2515 pHalData->EEPROMVersion = 1;
2516 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2517 ("Hal_EfuseParseEEPROMVer(), EEVer = %d\n",
2518 pHalData->EEPROMVersion));
2519}
2520
2521void
2522rtl8723a_EfuseParseChnlPlan(struct rtw_adapter *padapter,
2523 u8 *hwinfo, bool AutoLoadFail)
2524{
2525 padapter->mlmepriv.ChannelPlan =
2526 hal_com_get_channel_plan23a(padapter, hwinfo ?
2527 hwinfo[EEPROM_ChannelPlan_8723A]:0xFF,
2528 padapter->registrypriv.channel_plan,
2529 RT_CHANNEL_DOMAIN_WORLD_WIDE_13,
2530 AutoLoadFail);
2531
2532 DBG_8723A("mlmepriv.ChannelPlan = 0x%02x\n",
2533 padapter->mlmepriv.ChannelPlan);
2534}
2535
2536void
2537Hal_EfuseParseCustomerID(struct rtw_adapter *padapter,
2538 u8 *hwinfo, bool AutoLoadFail)
2539{
2540 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2541
2542 if (!AutoLoadFail) {
2543 pHalData->EEPROMCustomerID = hwinfo[EEPROM_CustomID_8723A];
2544 pHalData->EEPROMSubCustomerID =
2545 hwinfo[EEPROM_SubCustomID_8723A];
2546 } else {
2547 pHalData->EEPROMCustomerID = 0;
2548 pHalData->EEPROMSubCustomerID = 0;
2549 }
2550 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2551 ("EEPROM Customer ID: 0x%2x\n", pHalData->EEPROMCustomerID));
2552 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2553 ("EEPROM SubCustomer ID: 0x%02x\n",
2554 pHalData->EEPROMSubCustomerID));
2555}
2556
2557void
2558Hal_EfuseParseAntennaDiversity(struct rtw_adapter *padapter,
2559 u8 *hwinfo, bool AutoLoadFail)
2560{
2561}
2562
2563void
2564Hal_EfuseParseRateIndicationOption(struct rtw_adapter *padapter,
2565 u8 *hwinfo, bool AutoLoadFail)
2566{
2567}
2568
2569void
2570Hal_EfuseParseXtal_8723A(struct rtw_adapter *pAdapter,
2571 u8 *hwinfo, u8 AutoLoadFail)
2572{
2573 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
2574
2575 if (!AutoLoadFail) {
2576 pHalData->CrystalCap = hwinfo[EEPROM_XTAL_K_8723A];
2577 if (pHalData->CrystalCap == 0xFF)
2578 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A;
2579 } else {
2580 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A;
2581 }
2582 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
2583 ("%s: CrystalCap = 0x%2x\n", __func__,
2584 pHalData->CrystalCap));
2585}
2586
2587void
2588Hal_EfuseParseThermalMeter_8723A(struct rtw_adapter *padapter,
2589 u8 *PROMContent, u8 AutoloadFail)
2590{
2591 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2592
2593 /* */
2594 /* ThermalMeter from EEPROM */
2595 /* */
2596 if (false == AutoloadFail)
2597 pHalData->EEPROMThermalMeter =
2598 PROMContent[EEPROM_THERMAL_METER_8723A];
2599 else
2600 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2601
2602 if ((pHalData->EEPROMThermalMeter == 0xff) || (true == AutoloadFail)) {
2603 pHalData->bAPKThermalMeterIgnore = true;
2604 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2605 }
2606
2607 DBG_8723A("%s: ThermalMeter = 0x%x\n", __func__,
2608 pHalData->EEPROMThermalMeter);
2609}
2610
2611void Hal_InitChannelPlan23a(struct rtw_adapter *padapter)
2612{
2613}
2614
2615static void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc)
2616{
2617 u16 *usPtr = (u16 *) ptxdesc;
2618 u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */
2619 u32 index;
2620 u16 checksum = 0;
2621
2622 /* Clear first */
2623 ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
2624
2625 for (index = 0; index < count; index++) {
2626 checksum ^= le16_to_cpu(*(usPtr + index));
2627 }
2628
2629 ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff);
2630}
2631
2632static void fill_txdesc_sectype(struct pkt_attrib *pattrib,
2633 struct txdesc_8723a *ptxdesc)
2634{
2635 if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
2636 switch (pattrib->encrypt) {
2637 /* SEC_TYPE */
2638 case _WEP40_:
2639 case _WEP104_:
2640 case _TKIP_:
2641 case _TKIP_WTMIC_:
2642 ptxdesc->sectype = 1;
2643 break;
2644
2645 case _AES_:
2646 ptxdesc->sectype = 3;
2647 break;
2648
2649 case _NO_PRIVACY_:
2650 default:
2651 break;
2652 }
2653 }
2654}
2655
2656static void fill_txdesc_vcs(struct pkt_attrib *pattrib,
2657 struct txdesc_8723a *ptxdesc)
2658{
2659 /* DBG_8723A("cvs_mode =%d\n", pattrib->vcs_mode); */
2660
2661 switch (pattrib->vcs_mode) {
2662 case RTS_CTS:
2663 ptxdesc->rtsen = 1;
2664 break;
2665
2666 case CTS_TO_SELF:
2667 ptxdesc->cts2self = 1;
2668 break;
2669
2670 case NONE_VCS:
2671 default:
2672 break;
2673 }
2674
2675 if (pattrib->vcs_mode) {
2676 ptxdesc->hw_rts_en = 1; /* ENABLE HW RTS */
2677
2678 /* Set RTS BW */
2679 if (pattrib->ht_en) {
2680 if (pattrib->bwmode & HT_CHANNEL_WIDTH_40)
2681 ptxdesc->rts_bw = 1;
2682
2683 switch (pattrib->ch_offset) {
2684 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
2685 ptxdesc->rts_sc = 0;
2686 break;
2687
2688 case HAL_PRIME_CHNL_OFFSET_LOWER:
2689 ptxdesc->rts_sc = 1;
2690 break;
2691
2692 case HAL_PRIME_CHNL_OFFSET_UPPER:
2693 ptxdesc->rts_sc = 2;
2694 break;
2695
2696 default:
2697 ptxdesc->rts_sc = 3; /* Duplicate */
2698 break;
2699 }
2700 }
2701 }
2702}
2703
2704static void fill_txdesc_phy(struct pkt_attrib *pattrib,
2705 struct txdesc_8723a *ptxdesc)
2706{
2707 if (pattrib->ht_en) {
2708 if (pattrib->bwmode & HT_CHANNEL_WIDTH_40)
2709 ptxdesc->data_bw = 1;
2710
2711 switch (pattrib->ch_offset) {
2712 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
2713 ptxdesc->data_sc = 0;
2714 break;
2715
2716 case HAL_PRIME_CHNL_OFFSET_LOWER:
2717 ptxdesc->data_sc = 1;
2718 break;
2719
2720 case HAL_PRIME_CHNL_OFFSET_UPPER:
2721 ptxdesc->data_sc = 2;
2722 break;
2723
2724 default:
2725 ptxdesc->data_sc = 3; /* Duplicate */
2726 break;
2727 }
2728 }
2729}
2730
2731static void rtl8723a_fill_default_txdesc(struct xmit_frame *pxmitframe,
2732 u8 *pbuf)
2733{
2734 struct rtw_adapter *padapter;
2735 struct hal_data_8723a *pHalData;
2736 struct dm_priv *pdmpriv;
2737 struct mlme_ext_priv *pmlmeext;
2738 struct mlme_ext_info *pmlmeinfo;
2739 struct pkt_attrib *pattrib;
2740 struct txdesc_8723a *ptxdesc;
2741 s32 bmcst;
2742
2743 padapter = pxmitframe->padapter;
2744 pHalData = GET_HAL_DATA(padapter);
2745 pdmpriv = &pHalData->dmpriv;
2746 pmlmeext = &padapter->mlmeextpriv;
2747 pmlmeinfo = &pmlmeext->mlmext_info;
2748
2749 pattrib = &pxmitframe->attrib;
2750 bmcst = is_multicast_ether_addr(pattrib->ra);
2751
2752 ptxdesc = (struct txdesc_8723a *)pbuf;
2753
2754 if (pxmitframe->frame_tag == DATA_FRAMETAG) {
2755 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2756
2757 if (pattrib->ampdu_en == true)
2758 ptxdesc->agg_en = 1; /* AGG EN */
2759 else
2760 ptxdesc->bk = 1; /* AGG BK */
2761
2762 ptxdesc->qsel = pattrib->qsel;
2763 ptxdesc->rate_id = pattrib->raid;
2764
2765 fill_txdesc_sectype(pattrib, ptxdesc);
2766
2767 ptxdesc->seq = pattrib->seqnum;
2768
2769 if ((pattrib->ether_type != 0x888e) &&
2770 (pattrib->ether_type != 0x0806) &&
2771 (pattrib->dhcp_pkt != 1)) {
2772 /* Non EAP & ARP & DHCP type data packet */
2773
2774 fill_txdesc_vcs(pattrib, ptxdesc);
2775 fill_txdesc_phy(pattrib, ptxdesc);
2776
2777 ptxdesc->rtsrate = 8; /* RTS Rate = 24M */
2778 ptxdesc->data_ratefb_lmt = 0x1F;
2779 ptxdesc->rts_ratefb_lmt = 0xF;
2780
2781 /* use REG_INIDATA_RATE_SEL value */
2782 ptxdesc->datarate =
2783 pdmpriv->INIDATA_RATE[pattrib->mac_id];
2784
2785 } else {
2786 /* EAP data packet and ARP packet. */
2787 /* Use the 1M data rate to send the EAP/ARP packet. */
2788 /* This will maybe make the handshake smooth. */
2789
2790 ptxdesc->bk = 1; /* AGG BK */
2791 ptxdesc->userate = 1; /* driver uses rate */
2792 if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
2793 ptxdesc->data_short = 1;
2794 ptxdesc->datarate = MRateToHwRate23a(pmlmeext->tx_rate);
2795 }
2796 } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
2797/* RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
2798 ("%s: MGNT_FRAMETAG\n", __func__)); */
2799
2800 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2801 ptxdesc->qsel = pattrib->qsel;
2802 ptxdesc->rate_id = pattrib->raid; /* Rate ID */
2803 ptxdesc->seq = pattrib->seqnum;
2804 ptxdesc->userate = 1; /* driver uses rate, 1M */
2805 ptxdesc->rty_lmt_en = 1; /* retry limit enable */
2806 ptxdesc->data_rt_lmt = 6; /* retry limit = 6 */
2807
2808 /* CCX-TXRPT ack for xmit mgmt frames. */
2809 if (pxmitframe->ack_report)
2810 ptxdesc->ccx = 1;
2811
2812 ptxdesc->datarate = MRateToHwRate23a(pmlmeext->tx_rate);
2813 } else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) {
2814 RT_TRACE(_module_hal_xmit_c_, _drv_warning_,
2815 ("%s: TXAGG_FRAMETAG\n", __func__));
2816 } else {
2817 RT_TRACE(_module_hal_xmit_c_, _drv_warning_,
2818 ("%s: frame_tag = 0x%x\n", __func__,
2819 pxmitframe->frame_tag));
2820
2821 ptxdesc->macid = 4; /* CAM_ID(MAC_ID) */
2822 ptxdesc->rate_id = 6; /* Rate ID */
2823 ptxdesc->seq = pattrib->seqnum;
2824 ptxdesc->userate = 1; /* driver uses rate */
2825 ptxdesc->datarate = MRateToHwRate23a(pmlmeext->tx_rate);
2826 }
2827
2828 ptxdesc->pktlen = pattrib->last_txcmdsz;
2829 ptxdesc->offset = TXDESC_SIZE + OFFSET_SZ;
2830 if (bmcst)
2831 ptxdesc->bmc = 1;
2832 ptxdesc->ls = 1;
2833 ptxdesc->fs = 1;
2834 ptxdesc->own = 1;
2835
2836 /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS. */
2837 /* (1) The sequence number of each non-Qos frame / broadcast /
2838 * multicast / mgnt frame should be controled by Hw because Fw
2839 * will also send null data which we cannot control when Fw LPS enable.
2840 * --> default enable non-Qos data sequense number.
2841 2010.06.23. by tynli. */
2842 /* (2) Enable HW SEQ control for beacon packet,
2843 * because we use Hw beacon. */
2844 /* (3) Use HW Qos SEQ to control the seq num of Ext port
2845 * non-Qos packets. */
2846 /* 2010.06.23. Added by tynli. */
2847 if (!pattrib->qos_en) {
2848 /* Hw set sequence number */
2849 ptxdesc->hwseq_en = 1; /* HWSEQ_EN */
2850 ptxdesc->hwseq_sel = 0; /* HWSEQ_SEL */
2851 }
2852}
2853
2854/*
2855 * Description:
2856 *
2857 * Parameters:
2858 * pxmitframe xmitframe
2859 * pbuf where to fill tx desc
2860 */
2861void rtl8723a_update_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf)
2862{
2863 struct tx_desc *pdesc;
2864
2865 pdesc = (struct tx_desc *)pbuf;
2866 memset(pdesc, 0, sizeof(struct tx_desc));
2867
2868 rtl8723a_fill_default_txdesc(pxmitframe, pbuf);
2869
2870 pdesc->txdw0 = cpu_to_le32(pdesc->txdw0);
2871 pdesc->txdw1 = cpu_to_le32(pdesc->txdw1);
2872 pdesc->txdw2 = cpu_to_le32(pdesc->txdw2);
2873 pdesc->txdw3 = cpu_to_le32(pdesc->txdw3);
2874 pdesc->txdw4 = cpu_to_le32(pdesc->txdw4);
2875 pdesc->txdw5 = cpu_to_le32(pdesc->txdw5);
2876 pdesc->txdw6 = cpu_to_le32(pdesc->txdw6);
2877 pdesc->txdw7 = cpu_to_le32(pdesc->txdw7);
2878 rtl8723a_cal_txdesc_chksum(pdesc);
2879}
2880
2881/*
2882 * Description: In normal chip, we should send some packet to Hw which
2883 * will be used by Fw in FW LPS mode. The function is to fill the Tx
2884 * descriptor of this packets, then
2885 */
2886/* Fw can tell Hw to send these packet derectly. */
2887/* Added by tynli. 2009.10.15. */
2888/* */
2889void rtl8723a_fill_fake_txdesc(struct rtw_adapter *padapter, u8 *pDesc,
2890 u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull)
2891{
2892 struct tx_desc *ptxdesc;
2893
2894 /* Clear all status */
2895 ptxdesc = (struct tx_desc *)pDesc;
2896 memset(pDesc, 0, TXDESC_SIZE);
2897
2898 /* offset 0 */
2899 /* own, bFirstSeg, bLastSeg; */
2900 ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
2901
2902 /* 32 bytes for TX Desc */
2903 ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) <<
2904 OFFSET_SHT) & 0x00ff0000);
2905
2906 /* Buffer size + command header */
2907 ptxdesc->txdw0 |= cpu_to_le32(BufferLen & 0x0000ffff);
2908
2909 /* offset 4 */
2910 /* Fixed queue of Mgnt queue */
2911 ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT << QSEL_SHT) & 0x00001f00);
2912
2913 /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed
2914 to error vlaue by Hw. */
2915 if (IsPsPoll) {
2916 ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR);
2917 } else {
2918 /* Hw set sequence number */
2919 ptxdesc->txdw4 |= cpu_to_le32(BIT(7));
2920 /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */
2921 ptxdesc->txdw3 |= cpu_to_le32((8 << 28));
2922 }
2923
2924 if (true == IsBTQosNull) {
2925 ptxdesc->txdw2 |= cpu_to_le32(BIT(23)); /* BT NULL */
2926 }
2927
2928 /* offset 16 */
2929 ptxdesc->txdw4 |= cpu_to_le32(BIT(8)); /* driver uses rate */
2930
2931 /* USB interface drop packet if the checksum of descriptor isn't
2932 correct. */
2933 /* Using this checksum can let hardware recovery from packet bulk
2934 out error (e.g. Cancel URC, Bulk out error.). */
2935 rtl8723a_cal_txdesc_chksum(ptxdesc);
2936}
2937
2938static void hw_var_set_opmode(struct rtw_adapter *padapter, u8 mode)
2939{
2940 u8 val8;
2941
2942 if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
2943 StopTxBeacon(padapter);
2944
2945 /* disable atim wnd */
2946 val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_ATIM;
2947 SetBcnCtrlReg23a(padapter, val8, ~val8);
2948 } else if ((mode == _HW_STATE_ADHOC_) /*|| (mode == _HW_STATE_AP_) */) {
2949 ResumeTxBeacon(padapter);
2950
2951 val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB;
2952 SetBcnCtrlReg23a(padapter, val8, ~val8);
2953 } else if (mode == _HW_STATE_AP_) {
2954#ifdef CONFIG_8723AU_BT_COEXIST
2955 /* add NULL Data and BT NULL Data Packets to FW RSVD Page */
2956 rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(padapter);
2957#endif
2958
2959 ResumeTxBeacon(padapter);
2960
2961 val8 = DIS_TSF_UDT | DIS_BCNQ_SUB;
2962 SetBcnCtrlReg23a(padapter, val8, ~val8);
2963
2964 /* Set RCR */
2965 /* rtw_write32(padapter, REG_RCR, 0x70002a8e);
2966 CBSSID_DATA must set to 0 */
2967 /* CBSSID_DATA must set to 0 */
2968 rtw_write32(padapter, REG_RCR, 0x7000228e);
2969 /* enable to rx data frame */
2970 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
2971 /* enable to rx ps-poll */
2972 rtw_write16(padapter, REG_RXFLTMAP1, 0x0400);
2973
2974 /* Beacon Control related register for first time */
2975 rtw_write8(padapter, REG_BCNDMATIM, 0x02); /* 2ms */
2976 rtw_write8(padapter, REG_DRVERLYINT, 0x05); /* 5ms */
2977 rtw_write8(padapter, REG_ATIMWND, 0x0a); /* 10ms for port0 */
2978 rtw_write16(padapter, REG_BCNTCFG, 0x00);
2979 rtw_write16(padapter, REG_TBTT_PROHIBIT, 0xff04);
2980 /* +32767 (~32ms) */
2981 rtw_write16(padapter, REG_TSFTR_SYN_OFFSET, 0x7fff);
2982
2983 /* reset TSF */
2984 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
2985
2986 /* enable BCN Function */
2987 /* don't enable update TSF (due to TSF update when
2988 beacon/probe rsp are received) */
2989 val8 = DIS_TSF_UDT | EN_BCN_FUNCTION |
2990 EN_TXBCN_RPT | DIS_BCNQ_SUB;
2991 SetBcnCtrlReg23a(padapter, val8, ~val8);
2992 }
2993
2994 val8 = rtw_read8(padapter, MSR);
2995 val8 = (val8 & 0xC) | mode;
2996 rtw_write8(padapter, MSR, val8);
2997}
2998
2999static void hw_var_set_macaddr(struct rtw_adapter *padapter, u8 *val)
3000{
3001 u8 idx = 0;
3002 u32 reg_macid;
3003
3004 reg_macid = REG_MACID;
3005
3006 for (idx = 0; idx < 6; idx++)
3007 rtw_write8(padapter, (reg_macid + idx), val[idx]);
3008}
3009
3010static void hw_var_set_bssid(struct rtw_adapter *padapter, u8 *val)
3011{
3012 u8 idx = 0;
3013 u32 reg_bssid;
3014
3015 reg_bssid = REG_BSSID;
3016
3017 for (idx = 0; idx < 6; idx++)
3018 rtw_write8(padapter, (reg_bssid + idx), val[idx]);
3019}
3020
3021static void hw_var_set_correct_tsf(struct rtw_adapter *padapter)
3022{
3023 u64 tsf;
3024 u32 reg_tsftr;
3025 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3026 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
3027
3028 /* tsf = pmlmeext->TSFValue - ((u32)pmlmeext->TSFValue %
3029 (pmlmeinfo->bcn_interval*1024)) - 1024; us */
3030 tsf = pmlmeext->TSFValue -
3031 rtw_modular6423a(pmlmeext->TSFValue,
3032 (pmlmeinfo->bcn_interval * 1024)) - 1024; /* us */
3033
3034 if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
3035 ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
3036 /* pHalData->RegTxPause |= STOP_BCNQ;BIT(6) */
3037 /* rtw_write8(padapter, REG_TXPAUSE,
3038 (rtw_read8(Adapter, REG_TXPAUSE)|BIT(6))); */
3039 StopTxBeacon(padapter);
3040 }
3041
3042 reg_tsftr = REG_TSFTR;
3043
3044 /* disable related TSF function */
3045 SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION);
3046
3047 rtw_write32(padapter, reg_tsftr, tsf);
3048 rtw_write32(padapter, reg_tsftr + 4, tsf >> 32);
3049
3050 /* enable related TSF function */
3051 SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION, 0);
3052
3053 if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
3054 ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE))
3055 ResumeTxBeacon(padapter);
3056}
3057
3058static void hw_var_set_mlme_disconnect(struct rtw_adapter *padapter)
3059{
3060 /* reject all data frames */
3061 rtw_write16(padapter, REG_RXFLTMAP2, 0);
3062
3063 /* reset TSF */
3064 rtw_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
3065
3066 /* disable update TSF */
3067 SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0);
3068}
3069
3070static void hw_var_set_mlme_join(struct rtw_adapter *padapter, u8 type)
3071{
3072 u8 RetryLimit = 0x30;
3073
3074 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
3075 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3076
3077 if (type == 0) { /* prepare to join */
3078 u32 v32;
3079
3080 /* enable to rx data frame.Accept all data frame */
3081 /* rtw_write32(padapter, REG_RCR,
3082 rtw_read32(padapter, REG_RCR)|RCR_ADF); */
3083 rtw_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
3084
3085 v32 = rtw_read32(padapter, REG_RCR);
3086 v32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;
3087 rtw_write32(padapter, REG_RCR, v32);
3088
3089 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
3090 RetryLimit =
3091 (pHalData->CustomerID == RT_CID_CCX) ? 7 : 48;
3092 else /* Ad-hoc Mode */
3093 RetryLimit = 0x7;
3094 } else if (type == 1) { /* joinbss_event callback when join res < 0 */
3095 /* config RCR to receive different BSSID & not to
3096 receive data frame during linking */
3097 rtw_write16(padapter, REG_RXFLTMAP2, 0);
3098 } else if (type == 2) { /* sta add event callback */
3099 /* enable update TSF */
3100 SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT);
3101
3102 if (check_fwstate(pmlmepriv,
3103 WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
3104 /* fixed beacon issue for 8191su........... */
3105 rtw_write8(padapter, 0x542, 0x02);
3106 RetryLimit = 0x7;
3107 }
3108 }
3109
3110 rtw_write16(padapter, REG_RL,
3111 RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit <<
3112 RETRY_LIMIT_LONG_SHIFT);
3113
3114#ifdef CONFIG_8723AU_BT_COEXIST
3115 switch (type) {
3116 case 0:
3117 /* prepare to join */
3118 BT_WifiAssociateNotify(padapter, true);
3119 break;
3120 case 1:
3121 /* joinbss_event callback when join res < 0 */
3122 BT_WifiAssociateNotify(padapter, false);
3123 break;
3124 case 2:
3125 /* sta add event callback */
3126/* BT_WifiMediaStatusNotify(padapter, RT_MEDIA_CONNECT); */
3127 break;
3128 }
3129#endif
3130}
3131
3132void SetHwReg8723A(struct rtw_adapter *padapter, u8 variable, u8 *val)
3133{
3134 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
3135 u32 *val32 = (u32 *)val;
3136
3137 switch (variable) {
3138 case HW_VAR_MEDIA_STATUS:
3139 rtl8723a_set_media_status(padapter, *val);
3140 break;
3141
3142 case HW_VAR_MEDIA_STATUS1:
3143 rtl8723a_set_media_status1(padapter, *val);
3144 break;
3145
3146 case HW_VAR_SET_OPMODE:
3147 hw_var_set_opmode(padapter, *val);
3148 break;
3149
3150 case HW_VAR_MAC_ADDR:
3151 hw_var_set_macaddr(padapter, val);
3152 break;
3153
3154 case HW_VAR_BSSID:
3155 hw_var_set_bssid(padapter, val);
3156 break;
3157
3158 case HW_VAR_BASIC_RATE:
3159 HalSetBrateCfg23a(padapter, val);
3160 break;
3161
3162 case HW_VAR_TXPAUSE:
3163 rtl8723a_set_tx_pause(padapter, *val);
3164 break;
3165
3166 case HW_VAR_BCN_FUNC:
3167 rtl8723a_set_bcn_func(padapter, *val);
3168 break;
3169
3170 case HW_VAR_CORRECT_TSF:
3171 hw_var_set_correct_tsf(padapter);
3172 break;
3173
3174 case HW_VAR_CHECK_BSSID:
3175 rtl8723a_check_bssid(padapter, *val);
3176 break;
3177
3178 case HW_VAR_MLME_DISCONNECT:
3179 hw_var_set_mlme_disconnect(padapter);
3180 break;
3181
3182 case HW_VAR_MLME_SITESURVEY:
3183 rtl8723a_mlme_sitesurvey(padapter, *val);
3184 break;
3185
3186 case HW_VAR_MLME_JOIN:
3187 hw_var_set_mlme_join(padapter, *val);
3188 break;
3189
3190 case HW_VAR_ON_RCR_AM:
3191 rtl8723a_on_rcr_am(padapter);
3192 break;
3193
3194 case HW_VAR_OFF_RCR_AM:
3195 rtl8723a_off_rcr_am(padapter);
3196 break;
3197
3198 case HW_VAR_BEACON_INTERVAL:
3199 rtl8723a_set_beacon_interval(padapter, *((u16 *) val));
3200 break;
3201
3202 case HW_VAR_SLOT_TIME:
3203 rtl8723a_set_slot_time(padapter, *val);
3204 break;
3205
3206 case HW_VAR_RESP_SIFS:
3207 rtl8723a_set_resp_sifs(padapter, val[0], val[1],
3208 val[2], val[3]);
3209 break;
3210
3211 case HW_VAR_ACK_PREAMBLE:
3212 rtl8723a_ack_preamble(padapter, *val);
3213 break;
3214
3215 case HW_VAR_SEC_CFG:
3216 rtl8723a_set_sec_cfg(padapter, *val);
3217 break;
3218
3219 case HW_VAR_DM_FLAG:
3220 rtl8723a_odm_support_ability_write(padapter, *val32);
3221 break;
3222 case HW_VAR_DM_FUNC_OP:
3223 rtl8723a_odm_support_ability_backup(padapter, *val);
3224 break;
3225 case HW_VAR_DM_FUNC_SET:
3226 rtl8723a_odm_support_ability_set(padapter, *val32);
3227 break;
3228
3229 case HW_VAR_DM_FUNC_CLR:
3230 rtl8723a_odm_support_ability_clr(padapter, *val32);
3231 break;
3232
3233 case HW_VAR_CAM_EMPTY_ENTRY:
3234 rtl8723a_cam_empty_entry(padapter, *val);
3235 break;
3236
3237 case HW_VAR_CAM_INVALID_ALL:
3238 rtl8723a_cam_invalid_all(padapter);
3239 break;
3240
3241 case HW_VAR_CAM_WRITE:
3242 rtl8723a_cam_write(padapter, val32[0], val32[1]);
3243 break;
3244
3245 case HW_VAR_AC_PARAM_VO:
3246 rtl8723a_set_ac_param_vo(padapter, *val32);
3247 break;
3248
3249 case HW_VAR_AC_PARAM_VI:
3250 rtl8723a_set_ac_param_vi(padapter, *val32);
3251 break;
3252
3253 case HW_VAR_AC_PARAM_BE:
3254 rtl8723a_set_ac_param_be(padapter, *val32);
3255 break;
3256
3257 case HW_VAR_AC_PARAM_BK:
3258 rtl8723a_set_ac_param_bk(padapter, *val32);
3259 break;
3260
3261 case HW_VAR_ACM_CTRL:
3262 rtl8723a_set_acm_ctrl(padapter, *val);
3263 break;
3264
3265 case HW_VAR_AMPDU_MIN_SPACE:
3266 rtl8723a_set_ampdu_min_space(padapter, *val);
3267 break;
3268
3269 case HW_VAR_AMPDU_FACTOR:
3270 rtl8723a_set_ampdu_factor(padapter, *val);
3271 break;
3272
3273 case HW_VAR_RXDMA_AGG_PG_TH:
3274 rtl8723a_set_rxdma_agg_pg_th(padapter, *val);
3275 break;
3276
3277 case HW_VAR_H2C_FW_PWRMODE:
3278 rtl8723a_set_FwPwrMode_cmd(padapter, *val);
3279 break;
3280
3281 case HW_VAR_H2C_FW_JOINBSSRPT:
3282 rtl8723a_set_FwJoinBssReport_cmd(padapter, *val);
3283 break;
3284
3285#ifdef CONFIG_8723AU_P2P
3286 case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:
3287 rtl8723a_set_p2p_ps_offload_cmd(padapter, *val);
3288 break;
3289#endif /* CONFIG_8723AU_P2P */
3290
3291 case HW_VAR_INITIAL_GAIN:
3292 rtl8723a_set_initial_gain(padapter, *val32);
3293 break;
3294 case HW_VAR_EFUSE_BYTES:
3295 pHalData->EfuseUsedBytes = *((u16 *) val);
3296 break;
3297 case HW_VAR_EFUSE_BT_BYTES:
3298 pHalData->BTEfuseUsedBytes = *((u16 *) val);
3299 break;
3300 case HW_VAR_FIFO_CLEARN_UP:
3301 rtl8723a_fifo_cleanup(padapter);
3302 break;
3303 case HW_VAR_CHECK_TXBUF:
3304 break;
3305 case HW_VAR_APFM_ON_MAC:
3306 rtl8723a_set_apfm_on_mac(padapter, *val);
3307 break;
3308
3309 case HW_VAR_NAV_UPPER:
3310 rtl8723a_set_nav_upper(padapter, *val32);
3311 break;
3312 case HW_VAR_BCN_VALID:
3313 rtl8723a_bcn_valid(padapter);
3314 break;
3315 default:
3316 break;
3317 }
3318
3319}
3320
3321void GetHwReg8723A(struct rtw_adapter *padapter, u8 variable, u8 *val)
3322{
3323 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
3324
3325 switch (variable) {
3326 case HW_VAR_BASIC_RATE:
3327 *((u16 *) val) = pHalData->BasicRateSet;
3328 break;
3329
3330 case HW_VAR_TXPAUSE:
3331 *val = rtw_read8(padapter, REG_TXPAUSE);
3332 break;
3333
3334 case HW_VAR_BCN_VALID:
3335 /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */
3336 val[0] = (BIT0 & rtw_read8(padapter, REG_TDECTRL + 2)) ? true :
3337 false;
3338 break;
3339
3340 case HW_VAR_RF_TYPE:
3341 *val = pHalData->rf_type;
3342 break;
3343
3344 case HW_VAR_DM_FLAG:
3345 {
3346 struct dm_odm_t *podmpriv = &pHalData->odmpriv;
3347 *((u32 *) val) = podmpriv->SupportAbility;
3348 }
3349 break;
3350
3351 case HW_VAR_FWLPS_RF_ON:
3352 {
3353 /* When we halt NIC, we should check if FW LPS is leave. */
3354 u32 valRCR;
3355
3356 if ((padapter->bSurpriseRemoved == true) ||
3357 (padapter->pwrctrlpriv.rf_pwrstate == rf_off)) {
3358 /* If it is in HW/SW Radio OFF or IPS state, we do
3359 not check Fw LPS Leave, because Fw is unload. */
3360 *val = true;
3361 } else {
3362 valRCR = rtw_read32(padapter, REG_RCR);
3363 valRCR &= 0x00070000;
3364 if (valRCR)
3365 *val = false;
3366 else
3367 *val = true;
3368 }
3369 }
3370 break;
3371 case HW_VAR_EFUSE_BYTES:
3372 *((u16 *) val) = pHalData->EfuseUsedBytes;
3373 break;
3374
3375 case HW_VAR_EFUSE_BT_BYTES:
3376 *((u16 *) val) = pHalData->BTEfuseUsedBytes;
3377 break;
3378
3379 case HW_VAR_APFM_ON_MAC:
3380 *val = pHalData->bMacPwrCtrlOn;
3381 break;
3382 case HW_VAR_CHK_HI_QUEUE_EMPTY:
3383 *val =
3384 ((rtw_read32(padapter, REG_HGQ_INFORMATION) & 0x0000ff00) ==
3385 0) ? true : false;
3386 break;
3387 }
3388}
3389
3390#ifdef CONFIG_8723AU_BT_COEXIST
3391
3392void rtl8723a_SingleDualAntennaDetection(struct rtw_adapter *padapter)
3393{
3394 struct hal_data_8723a *pHalData;
3395 struct dm_odm_t *pDM_Odm;
3396 struct sw_ant_sw *pDM_SWAT_Table;
3397 u8 i;
3398
3399 pHalData = GET_HAL_DATA(padapter);
3400 pDM_Odm = &pHalData->odmpriv;
3401 pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table;
3402
3403 /* */
3404 /* <Roger_Notes> RTL8723A Single and Dual antenna dynamic detection
3405 mechanism when RF power state is on. */
3406 /* We should take power tracking, IQK, LCK, RCK RF read/write
3407 operation into consideration. */
3408 /* 2011.12.15. */
3409 /* */
3410 if (!pHalData->bAntennaDetected) {
3411 u8 btAntNum = BT_GetPGAntNum(padapter);
3412
3413 /* Set default antenna B status */
3414 if (btAntNum == Ant_x2)
3415 pDM_SWAT_Table->ANTB_ON = true;
3416 else if (btAntNum == Ant_x1)
3417 pDM_SWAT_Table->ANTB_ON = false;
3418 else
3419 pDM_SWAT_Table->ANTB_ON = true;
3420
3421 if (pHalData->CustomerID != RT_CID_TOSHIBA) {
3422 for (i = 0; i < MAX_ANTENNA_DETECTION_CNT; i++) {
3423 if (ODM_SingleDualAntennaDetection
3424 (&pHalData->odmpriv, ANTTESTALL) == true)
3425 break;
3426 }
3427
3428 /* Set default antenna number for BT coexistence */
3429 if (btAntNum == Ant_x2)
3430 BT_SetBtCoexCurrAntNum(padapter,
3431 pDM_SWAT_Table->
3432 ANTB_ON ? 2 : 1);
3433 }
3434 pHalData->bAntennaDetected = true;
3435 }
3436}
3437#endif /* CONFIG_8723AU_BT_COEXIST */
3438
3439void rtl8723a_clone_haldata(struct rtw_adapter *dst_adapter,
3440 struct rtw_adapter *src_adapter)
3441{
3442 memcpy(dst_adapter->HalData, src_adapter->HalData,
3443 dst_adapter->hal_data_sz);
3444}
3445
3446void rtl8723a_start_thread(struct rtw_adapter *padapter)
3447{
3448}
3449
3450void rtl8723a_stop_thread(struct rtw_adapter *padapter)
3451{
3452}
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c b/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c
new file mode 100644
index 000000000000..8400e6e2fca8
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c
@@ -0,0 +1,1162 @@
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 ******************************************************************************/
15#define _RTL8723A_PHYCFG_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19
20#include <rtl8723a_hal.h>
21
22/*---------------------------Define Local Constant---------------------------*/
23/* Channel switch:The size of command tables for switch channel*/
24#define MAX_PRECMD_CNT 16
25#define MAX_RFDEPENDCMD_CNT 16
26#define MAX_POSTCMD_CNT 16
27
28#define MAX_DOZE_WAITING_TIMES_9x 64
29
30/*---------------------------Define Local Constant---------------------------*/
31
32/*------------------------Define global variable-----------------------------*/
33
34/*------------------------Define local variable------------------------------*/
35
36/*--------------------Define export function prototype-----------------------*/
37/* Please refer to header file */
38/*--------------------Define export function prototype-----------------------*/
39
40/*----------------------------Function Body----------------------------------*/
41/* */
42/* 1. BB register R/W API */
43/* */
44
45/**
46* Function: phy_CalculateBitShift
47*
48* OverView: Get shifted position of the BitMask
49*
50* Input:
51* u32 BitMask,
52*
53* Output: none
54* Return: u32 Return the shift bit bit position of the mask
55*/
56static u32 phy_CalculateBitShift(u32 BitMask)
57{
58 u32 i;
59
60 for (i = 0; i <= 31; i++) {
61 if (((BitMask>>i) & 0x1) == 1)
62 break;
63 }
64
65 return i;
66}
67
68/**
69* Function: PHY_QueryBBReg
70*
71* OverView: Read "sepcific bits" from BB register
72*
73* Input:
74* struct rtw_adapter * Adapter,
75* u32 RegAddr, Target address to be readback
76* u32 BitMask Target bit position in the
77* target address to be readback
78* Output:
79* None
80* Return:
81* u32 Data The readback register value
82* Note:
83* This function is equal to "GetRegSetting" in PHY programming guide
84*/
85u32
86PHY_QueryBBReg(struct rtw_adapter *Adapter, u32 RegAddr, u32 BitMask)
87{
88 u32 ReturnValue = 0, OriginalValue, BitShift;
89
90 OriginalValue = rtw_read32(Adapter, RegAddr);
91 BitShift = phy_CalculateBitShift(BitMask);
92 ReturnValue = (OriginalValue & BitMask) >> BitShift;
93 return ReturnValue;
94}
95
96/**
97* Function: PHY_SetBBReg
98*
99* OverView: Write "Specific bits" to BB register (page 8~)
100*
101* Input:
102* struct rtw_adapter * Adapter,
103* u32 RegAddr, Target address to be modified
104* u32 BitMask Target bit position in the
105* target address to be modified
106* u32 Data The new register value in the
107* target bit position of the
108* target address
109*
110* Output:
111* None
112* Return:
113* None
114* Note:
115* This function is equal to "PutRegSetting" in PHY programming guide
116*/
117
118void
119PHY_SetBBReg(struct rtw_adapter *Adapter, u32 RegAddr, u32 BitMask, u32 Data)
120{
121 u32 OriginalValue, BitShift;
122
123 /* RT_TRACE(COMP_RF, DBG_TRACE, ("--->PHY_SetBBReg(): RegAddr(%#lx), BitMask(%#lx), Data(%#lx)\n", RegAddr, BitMask, Data)); */
124
125 if (BitMask != bMaskDWord) {/* if not "double word" write */
126 OriginalValue = rtw_read32(Adapter, RegAddr);
127 BitShift = phy_CalculateBitShift(BitMask);
128 Data = ((OriginalValue & (~BitMask)) | (Data << BitShift));
129 }
130
131 rtw_write32(Adapter, RegAddr, Data);
132
133 /* RTPRINT(FPHY, PHY_BBW, ("BBW MASK = 0x%lx Addr[0x%lx]= 0x%lx\n", BitMask, RegAddr, Data)); */
134 /* RT_TRACE(COMP_RF, DBG_TRACE, ("<---PHY_SetBBReg(): RegAddr(%#lx), BitMask(%#lx), Data(%#lx)\n", RegAddr, BitMask, Data)); */
135}
136
137/* */
138/* 2. RF register R/W API */
139/* */
140
141/**
142* Function: phy_RFSerialRead
143*
144* OverView: Read regster from RF chips
145*
146* Input:
147* struct rtw_adapter * Adapter,
148* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D
149* u32 Offset, The target address to be read
150*
151* Output: None
152* Return: u32 reback value
153* Note: Threre are three types of serial operations:
154* 1. Software serial write
155* 2. Hardware LSSI-Low Speed Serial Interface
156* 3. Hardware HSSI-High speed
157* serial write. Driver need to implement (1) and (2).
158* This function is equal to the combination of RF_ReadReg() and
159* RFLSSIRead()
160*/
161static u32
162phy_RFSerialRead(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath,
163 u32 Offset)
164{
165 u32 retValue = 0;
166 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
167 struct bb_reg_define *pPhyReg = &pHalData->PHYRegDef[eRFPath];
168 u32 NewOffset;
169 u32 tmplong, tmplong2;
170 u8 RfPiEnable = 0;
171 /* */
172 /* Make sure RF register offset is correct */
173 /* */
174 Offset &= 0x3f;
175
176 /* */
177 /* Switch page for 8256 RF IC */
178 /* */
179 NewOffset = Offset;
180
181 /* 2009/06/17 MH We can not execute IO for power save or
182 other accident mode. */
183 /* if (RT_CANNOT_IO(Adapter)) */
184 /* */
185 /* RTPRINT(FPHY, PHY_RFR, ("phy_RFSerialRead return all one\n")); */
186 /* return 0xFFFFFFFF; */
187 /* */
188
189 /* For 92S LSSI Read RFLSSIRead */
190 /* For RF A/B write 0x824/82c(does not work in the future) */
191 /* We must use 0x824 for RF A and B to execute read trigger */
192 tmplong = PHY_QueryBBReg(Adapter, rFPGA0_XA_HSSIParameter2, bMaskDWord);
193 if (eRFPath == RF_PATH_A)
194 tmplong2 = tmplong;
195 else
196 tmplong2 = PHY_QueryBBReg(Adapter, pPhyReg->rfHSSIPara2,
197 bMaskDWord);
198
199 tmplong2 = (tmplong2 & ~bLSSIReadAddress) |
200 (NewOffset << 23) | bLSSIReadEdge; /* T65 RF */
201
202 PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2,
203 bMaskDWord, tmplong & (~bLSSIReadEdge));
204 udelay(10);/* PlatformStallExecution(10); */
205
206 PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, bMaskDWord, tmplong2);
207 udelay(100);/* PlatformStallExecution(100); */
208
209 PHY_SetBBReg(Adapter, rFPGA0_XA_HSSIParameter2, bMaskDWord,
210 tmplong | bLSSIReadEdge);
211 udelay(10);/* PlatformStallExecution(10); */
212
213 if (eRFPath == RF_PATH_A)
214 RfPiEnable = (u8)PHY_QueryBBReg(Adapter,
215 rFPGA0_XA_HSSIParameter1, BIT8);
216 else if (eRFPath == RF_PATH_B)
217 RfPiEnable = (u8)PHY_QueryBBReg(Adapter,
218 rFPGA0_XB_HSSIParameter1, BIT8);
219
220 if (RfPiEnable) {
221 /* Read from BBreg8b8, 12 bits for 8190, 20bits for T65 RF */
222 retValue = PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBackPi,
223 bLSSIReadBackData);
224 /* DBG_8723A("Readback from RF-PI : 0x%x\n", retValue); */
225 } else {
226 /* Read from BBreg8a0, 12 bits for 8190, 20 bits for T65 RF */
227 retValue = PHY_QueryBBReg(Adapter, pPhyReg->rfLSSIReadBack,
228 bLSSIReadBackData);
229 /* DBG_8723A("Readback from RF-SI : 0x%x\n", retValue); */
230 }
231 /* DBG_8723A("RFR-%d Addr[0x%x]= 0x%x\n", eRFPath, pPhyReg->rfLSSIReadBack, retValue); */
232
233 return retValue;
234}
235
236/**
237* Function: phy_RFSerialWrite
238*
239* OverView: Write data to RF register (page 8~)
240*
241* Input:
242* struct rtw_adapter * Adapter,
243* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D
244* u32 Offset, The target address to be read
245* u32 Data The new register Data in the target
246* bit position of the target to be read
247*
248* Output:
249* None
250* Return:
251* None
252* Note:
253* Threre are three types of serial operations:
254* 1. Software serial write
255* 2. Hardware LSSI-Low Speed Serial Interface
256* 3. Hardware HSSI-High speed
257* serial write. Driver need to implement (1) and (2).
258* This function is equal to the combination of RF_ReadReg() and
259* RFLSSIRead()
260*
261* Note: For RF8256 only
262* The total count of RTL8256(Zebra4) register is around 36 bit it only employs
263* 4-bit RF address. RTL8256 uses "register mode control bit"
264* (Reg00[12], Reg00[10]) to access register address bigger than 0xf.
265* See "Appendix-4 in PHY Configuration programming guide" for more details.
266* Thus, we define a sub-finction for RTL8526 register address conversion
267* ===========================================================
268* Register Mode: RegCTL[1] RegCTL[0] Note
269* (Reg00[12]) (Reg00[10])
270* ===========================================================
271* Reg_Mode0 0 x Reg 0 ~15(0x0 ~ 0xf)
272* ------------------------------------------------------------------
273* Reg_Mode1 1 0 Reg 16 ~30(0x1 ~ 0xf)
274* ------------------------------------------------------------------
275* Reg_Mode2 1 1 Reg 31 ~ 45(0x1 ~ 0xf)
276* ------------------------------------------------------------------
277*
278* 2008/09/02 MH Add 92S RF definition
279*/
280static void
281phy_RFSerialWrite(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath,
282 u32 Offset, u32 Data)
283{
284 u32 DataAndAddr = 0;
285 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
286 struct bb_reg_define *pPhyReg = &pHalData->PHYRegDef[eRFPath];
287 u32 NewOffset;
288
289 /* 2009/06/17 MH We can not execute IO for power save or
290 other accident mode. */
291 /* if (RT_CANNOT_IO(Adapter)) */
292 /* */
293 /* RTPRINT(FPHY, PHY_RFW, ("phy_RFSerialWrite stop\n")); */
294 /* return; */
295 /* */
296
297 Offset &= 0x3f;
298
299 /* */
300 /* Shadow Update */
301 /* */
302 /* PHY_RFShadowWrite(Adapter, eRFPath, Offset, Data); */
303
304 /* */
305 /* Switch page for 8256 RF IC */
306 /* */
307 NewOffset = Offset;
308
309 /* */
310 /* Put write addr in [5:0] and write data in [31:16] */
311 /* */
312 /* DataAndAddr = (Data<<16) | (NewOffset&0x3f); */
313 /* T65 RF */
314 DataAndAddr = ((NewOffset<<20) | (Data&0x000fffff)) & 0x0fffffff;
315
316 /* */
317 /* Write Operation */
318 /* */
319 PHY_SetBBReg(Adapter, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
320 /* RTPRINT(FPHY, PHY_RFW, ("RFW-%d Addr[0x%lx]= 0x%lx\n", eRFPath, pPhyReg->rf3wireOffset, DataAndAddr)); */
321
322}
323
324/**
325* Function: PHY_QueryRFReg
326*
327* OverView: Query "Specific bits" to RF register (page 8~)
328*
329* Input:
330* struct rtw_adapter * Adapter,
331* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D
332* u32 RegAddr, The target address to be read
333* u32BitMask The target bit position in the target
334* address to be read
335*
336* Output:
337* None
338* Return:
339* u32 Readback value
340* Note:
341* This function is equal to "GetRFRegSetting" in PHY programming guide
342*/
343u32
344PHY_QueryRFReg(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath,
345 u32 RegAddr, u32 BitMask)
346{
347 u32 Original_Value, Readback_Value, BitShift;
348 /* struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); */
349 /* u8 RFWaitCounter = 0; */
350 /* _irqL irqL; */
351
352 Original_Value = phy_RFSerialRead(Adapter, eRFPath, RegAddr);
353
354 BitShift = phy_CalculateBitShift(BitMask);
355 Readback_Value = (Original_Value & BitMask) >> BitShift;
356
357 return Readback_Value;
358}
359
360/**
361* Function: PHY_SetRFReg
362*
363* OverView: Write "Specific bits" to RF register (page 8~)
364*
365* Input:
366* struct rtw_adapter * Adapter,
367* enum RF_RADIO_PATH eRFPath, Radio path of A/B/C/D
368* u32 RegAddr, The target address to be modified
369* u32 BitMask The target bit position in the target
370* address to be modified
371* u32 Data The new register Data in the target
372* bit position of the target address
373*
374* Output:
375* None
376* Return:
377* None
378* Note: This function is equal to "PutRFRegSetting" in PHY programming guide
379*/
380void
381PHY_SetRFReg(struct rtw_adapter *Adapter, enum RF_RADIO_PATH eRFPath,
382 u32 RegAddr, u32 BitMask, u32 Data)
383{
384 /* struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); */
385 /* u8 RFWaitCounter = 0; */
386 u32 Original_Value, BitShift;
387
388 /* RF data is 12 bits only */
389 if (BitMask != bRFRegOffsetMask) {
390 Original_Value = phy_RFSerialRead(Adapter, eRFPath, RegAddr);
391 BitShift = phy_CalculateBitShift(BitMask);
392 Data = ((Original_Value & (~BitMask)) | (Data << BitShift));
393 }
394
395 phy_RFSerialWrite(Adapter, eRFPath, RegAddr, Data);
396}
397
398/* 3. Initial MAC/BB/RF config by reading MAC/BB/RF txt. */
399
400/*-----------------------------------------------------------------------------
401 * Function: PHY_MACConfig8723A
402 *
403 * Overview: Condig MAC by header file or parameter file.
404 *
405 * Input: NONE
406 *
407 * Output: NONE
408 *
409 * Return: NONE
410 *
411 * Revised History:
412 * When Who Remark
413 * 08/12/2008 MHC Create Version 0.
414 *
415 *---------------------------------------------------------------------------*/
416s32 PHY_MACConfig8723A(struct rtw_adapter *Adapter)
417{
418 int rtStatus = _SUCCESS;
419 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
420 s8 *pszMACRegFile;
421 s8 sz8723MACRegFile[] = RTL8723_PHY_MACREG;
422 bool is92C = IS_92C_SERIAL(pHalData->VersionID);
423
424 pszMACRegFile = sz8723MACRegFile;
425
426 /* */
427 /* Config MAC */
428 /* */
429 if (HAL_STATUS_FAILURE ==
430 ODM_ConfigMACWithHeaderFile23a(&pHalData->odmpriv))
431 rtStatus = _FAIL;
432
433 /* 2010.07.13 AMPDU aggregation number 9 */
434 /* rtw_write16(Adapter, REG_MAX_AGGR_NUM, MAX_AGGR_NUM); */
435 rtw_write8(Adapter, REG_MAX_AGGR_NUM, 0x0A); /* By tynli. 2010.11.18. */
436 if (is92C && (BOARD_USB_DONGLE == pHalData->BoardType))
437 rtw_write8(Adapter, 0x40, 0x04);
438
439 return rtStatus;
440}
441
442/**
443* Function: phy_InitBBRFRegisterDefinition
444*
445* OverView: Initialize Register definition offset for Radio Path A/B/C/D
446*
447* Input:
448* struct rtw_adapter * Adapter,
449*
450* Output: None
451* Return: None
452* Note:
453* The initialization value is constant and it should never be changes
454*/
455static void
456phy_InitBBRFRegisterDefinition(struct rtw_adapter *Adapter)
457{
458 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
459
460 /* RF Interface Sowrtware Control */
461 /* 16 LSBs if read 32-bit from 0x870 */
462 pHalData->PHYRegDef[RF_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW;
463 /* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */
464 pHalData->PHYRegDef[RF_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW;
465
466 /* RF Interface Readback Value */
467 /* 16 LSBs if read 32-bit from 0x8E0 */
468 pHalData->PHYRegDef[RF_PATH_A].rfintfi = rFPGA0_XAB_RFInterfaceRB;
469 /* 16 MSBs if read 32-bit from 0x8E0 (16-bit for 0x8E2) */
470 pHalData->PHYRegDef[RF_PATH_B].rfintfi = rFPGA0_XAB_RFInterfaceRB;
471
472 /* RF Interface Output (and Enable) */
473 /* 16 LSBs if read 32-bit from 0x860 */
474 pHalData->PHYRegDef[RF_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE;
475 /* 16 LSBs if read 32-bit from 0x864 */
476 pHalData->PHYRegDef[RF_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE;
477
478 /* RF Interface (Output and) Enable */
479 /* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */
480 pHalData->PHYRegDef[RF_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE;
481 /* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */
482 pHalData->PHYRegDef[RF_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE;
483
484 /* Addr of LSSI. Wirte RF register by driver */
485 pHalData->PHYRegDef[RF_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter;
486 pHalData->PHYRegDef[RF_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter;
487
488 /* RF parameter */
489 /* BB Band Select */
490 pHalData->PHYRegDef[RF_PATH_A].rfLSSI_Select = rFPGA0_XAB_RFParameter;
491 pHalData->PHYRegDef[RF_PATH_B].rfLSSI_Select = rFPGA0_XAB_RFParameter;
492
493 /* Tx AGC Gain Stage (same for all path. Should we remove this?) */
494 pHalData->PHYRegDef[RF_PATH_A].rfTxGainStage = rFPGA0_TxGainStage;
495 pHalData->PHYRegDef[RF_PATH_B].rfTxGainStage = rFPGA0_TxGainStage;
496
497 /* Tranceiver A~D HSSI Parameter-1 */
498 /* wire control parameter1 */
499 pHalData->PHYRegDef[RF_PATH_A].rfHSSIPara1 = rFPGA0_XA_HSSIParameter1;
500 /* wire control parameter1 */
501 pHalData->PHYRegDef[RF_PATH_B].rfHSSIPara1 = rFPGA0_XB_HSSIParameter1;
502
503 /* Tranceiver A~D HSSI Parameter-2 */
504 /* wire control parameter2 */
505 pHalData->PHYRegDef[RF_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2;
506 /* wire control parameter2 */
507 pHalData->PHYRegDef[RF_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2;
508
509 /* RF switch Control */
510 pHalData->PHYRegDef[RF_PATH_A].rfSwitchControl =
511 rFPGA0_XAB_SwitchControl; /* TR/Ant switch control */
512 pHalData->PHYRegDef[RF_PATH_B].rfSwitchControl =
513 rFPGA0_XAB_SwitchControl;
514
515 /* AGC control 1 */
516 pHalData->PHYRegDef[RF_PATH_A].rfAGCControl1 = rOFDM0_XAAGCCore1;
517 pHalData->PHYRegDef[RF_PATH_B].rfAGCControl1 = rOFDM0_XBAGCCore1;
518
519 /* AGC control 2 */
520 pHalData->PHYRegDef[RF_PATH_A].rfAGCControl2 = rOFDM0_XAAGCCore2;
521 pHalData->PHYRegDef[RF_PATH_B].rfAGCControl2 = rOFDM0_XBAGCCore2;
522
523 /* RX AFE control 1 */
524 pHalData->PHYRegDef[RF_PATH_A].rfRxIQImbalance = rOFDM0_XARxIQImbalance;
525 pHalData->PHYRegDef[RF_PATH_B].rfRxIQImbalance = rOFDM0_XBRxIQImbalance;
526
527 /* RX AFE control 1 */
528 pHalData->PHYRegDef[RF_PATH_A].rfRxAFE = rOFDM0_XARxAFE;
529 pHalData->PHYRegDef[RF_PATH_B].rfRxAFE = rOFDM0_XBRxAFE;
530
531 /* Tx AFE control 1 */
532 pHalData->PHYRegDef[RF_PATH_A].rfTxIQImbalance = rOFDM0_XATxIQImbalance;
533 pHalData->PHYRegDef[RF_PATH_B].rfTxIQImbalance = rOFDM0_XBTxIQImbalance;
534
535 /* Tx AFE control 2 */
536 pHalData->PHYRegDef[RF_PATH_A].rfTxAFE = rOFDM0_XATxAFE;
537 pHalData->PHYRegDef[RF_PATH_B].rfTxAFE = rOFDM0_XBTxAFE;
538
539 /* Tranceiver LSSI Readback SI mode */
540 pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack;
541 pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack;
542
543 /* Tranceiver LSSI Readback PI mode */
544 pHalData->PHYRegDef[RF_PATH_A].rfLSSIReadBackPi =
545 TransceiverA_HSPI_Readback;
546 pHalData->PHYRegDef[RF_PATH_B].rfLSSIReadBackPi =
547 TransceiverB_HSPI_Readback;
548}
549
550/* The following is for High Power PA */
551static void
552storePwrIndexDiffRateOffset(struct rtw_adapter *Adapter, u32 RegAddr,
553 u32 BitMask, u32 Data)
554{
555 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
556
557 if (RegAddr == rTxAGC_A_Rate18_06) {
558 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][0] = Data;
559 /* RT_TRACE(COMP_INIT, DBG_TRACE,
560 ("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%lx\n",
561 pHalData->pwrGroupCnt, */
562 /* pHalData->MCSTxPowerLevelOriginalOffset[
563 pHalData->pwrGroupCnt][0])); */
564 }
565 if (RegAddr == rTxAGC_A_Rate54_24) {
566 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][1] = Data;
567 /* RT_TRACE(COMP_INIT, DBG_TRACE,
568 ("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%lx\n",
569 pHalData->pwrGroupCnt, */
570 /* pHalData->MCSTxPowerLevelOriginalOffset[
571 pHalData->pwrGroupCnt][1])); */
572 }
573 if (RegAddr == rTxAGC_A_CCK1_Mcs32) {
574 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][6] = Data;
575 /* RT_TRACE(COMP_INIT, DBG_TRACE,
576 ("MCSTxPowerLevelOriginalOffset[%d][6] = 0x%lx\n",
577 pHalData->pwrGroupCnt, */
578 /* pHalData->MCSTxPowerLevelOriginalOffset[
579 pHalData->pwrGroupCnt][6])); */
580 }
581 if (RegAddr == rTxAGC_B_CCK11_A_CCK2_11 && BitMask == 0xffffff00) {
582 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][7] = Data;
583 /* RT_TRACE(COMP_INIT, DBG_TRACE,
584 ("MCSTxPowerLevelOriginalOffset[%d][7] = 0x%lx\n",
585 pHalData->pwrGroupCnt, */
586 /* pHalData->MCSTxPowerLevelOriginalOffset[
587 pHalData->pwrGroupCnt][7])); */
588 }
589 if (RegAddr == rTxAGC_A_Mcs03_Mcs00) {
590 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][2] = Data;
591 /* RT_TRACE(COMP_INIT, DBG_TRACE,
592 ("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%lx\n",
593 pHalData->pwrGroupCnt, */
594 /* pHalData->MCSTxPowerLevelOriginalOffset[
595 pHalData->pwrGroupCnt][2])); */
596 }
597 if (RegAddr == rTxAGC_A_Mcs07_Mcs04) {
598 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][3] = Data;
599 /* RT_TRACE(COMP_INIT, DBG_TRACE,
600 ("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%lx\n",
601 pHalData->pwrGroupCnt, */
602 /* pHalData->MCSTxPowerLevelOriginalOffset[
603 pHalData->pwrGroupCnt][3])); */
604 }
605 if (RegAddr == rTxAGC_A_Mcs11_Mcs08) {
606 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][4] = Data;
607 /* RT_TRACE(COMP_INIT, DBG_TRACE,
608 ("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%lx\n",
609 pHalData->pwrGroupCnt, */
610 /* pHalData->MCSTxPowerLevelOriginalOffset[
611 pHalData->pwrGroupCnt][4])); */
612 }
613 if (RegAddr == rTxAGC_A_Mcs15_Mcs12) {
614 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][5] = Data;
615 /* RT_TRACE(COMP_INIT, DBG_TRACE,
616 ("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%lx\n",
617 pHalData->pwrGroupCnt, */
618 /* pHalData->MCSTxPowerLevelOriginalOffset[
619 pHalData->pwrGroupCnt][5])); */
620 }
621 if (RegAddr == rTxAGC_B_Rate18_06) {
622 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][8] = Data;
623 /* RT_TRACE(COMP_INIT, DBG_TRACE,
624 ("MCSTxPowerLevelOriginalOffset[%d][8] = 0x%lx\n",
625 pHalData->pwrGroupCnt, */
626 /* pHalData->MCSTxPowerLevelOriginalOffset[
627 pHalData->pwrGroupCnt][8])); */
628 }
629 if (RegAddr == rTxAGC_B_Rate54_24) {
630 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][9] = Data;
631 /* RT_TRACE(COMP_INIT, DBG_TRACE,
632 ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%lx\n",
633 pHalData->pwrGroupCnt, */
634 /* pHalData->MCSTxPowerLevelOriginalOffset[
635 pHalData->pwrGroupCnt][9])); */
636 }
637 if (RegAddr == rTxAGC_B_CCK1_55_Mcs32) {
638 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][14] = Data;
639 /* RT_TRACE(COMP_INIT, DBG_TRACE,
640 ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%lx\n",
641 pHalData->pwrGroupCnt, */
642 /* pHalData->MCSTxPowerLevelOriginalOffset[
643 pHalData->pwrGroupCnt][14])); */
644 }
645 if (RegAddr == rTxAGC_B_CCK11_A_CCK2_11 && BitMask == 0x000000ff) {
646 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][15] = Data;
647 /* RT_TRACE(COMP_INIT, DBG_TRACE,
648 ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%lx\n",
649 pHalData->pwrGroupCnt, */
650 /* pHalData->MCSTxPowerLevelOriginalOffset[
651 pHalData->pwrGroupCnt][15])); */
652 }
653 if (RegAddr == rTxAGC_B_Mcs03_Mcs00) {
654 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][10] = Data;
655 /* RT_TRACE(COMP_INIT, DBG_TRACE,
656 ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%lx\n",
657 pHalData->pwrGroupCnt, */
658 /* pHalData->MCSTxPowerLevelOriginalOffset[
659 pHalData->pwrGroupCnt][10])); */
660 }
661 if (RegAddr == rTxAGC_B_Mcs07_Mcs04) {
662 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][11] = Data;
663 /* RT_TRACE(COMP_INIT, DBG_TRACE,
664 ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%lx\n",
665 pHalData->pwrGroupCnt, */
666 /* pHalData->MCSTxPowerLevelOriginalOffset[
667 pHalData->pwrGroupCnt][11])); */
668 }
669 if (RegAddr == rTxAGC_B_Mcs11_Mcs08) {
670 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][12] = Data;
671 /* RT_TRACE(COMP_INIT, DBG_TRACE,
672 ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%lx\n",
673 pHalData->pwrGroupCnt, */
674 /* pHalData->MCSTxPowerLevelOriginalOffset[
675 pHalData->pwrGroupCnt][12])); */
676 }
677 if (RegAddr == rTxAGC_B_Mcs15_Mcs12) {
678 pHalData->MCSTxPowerLevelOriginalOffset[pHalData->pwrGroupCnt][13] = Data;
679 /* RT_TRACE(COMP_INIT, DBG_TRACE,
680 ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%lx\n",
681 pHalData->pwrGroupCnt, */
682 /* pHalData->MCSTxPowerLevelOriginalOffset[
683 pHalData->pwrGroupCnt][13])); */
684 pHalData->pwrGroupCnt++;
685 }
686}
687
688/*-----------------------------------------------------------------------------
689 * Function: phy_ConfigBBWithPgHeaderFile
690 *
691 * Overview: Config PHY_REG_PG array
692 *
693 * Input: NONE
694 *
695 * Output: NONE
696 *
697 * Return: NONE
698 *
699 * Revised History:
700 * When Who Remark
701 * 11/06/2008 MHC Add later!!!!!!.. Please modify for new files!!!!
702 * 11/10/2008 tynli Modify to mew files.
703 *---------------------------------------------------------------------------*/
704static int
705phy_ConfigBBWithPgHeaderFile(struct rtw_adapter *Adapter, u8 ConfigType)
706{
707 int i;
708 u32 *Rtl819XPHY_REGArray_Table_PG;
709 u16 PHY_REGArrayPGLen;
710
711 PHY_REGArrayPGLen = Rtl8723_PHY_REG_Array_PGLength;
712 Rtl819XPHY_REGArray_Table_PG = (u32 *)Rtl8723_PHY_REG_Array_PG;
713
714 if (ConfigType == BaseBand_Config_PHY_REG) {
715 for (i = 0; i < PHY_REGArrayPGLen; i = i + 3) {
716 storePwrIndexDiffRateOffset(Adapter,
717 Rtl819XPHY_REGArray_Table_PG[i],
718 Rtl819XPHY_REGArray_Table_PG[i+1],
719 Rtl819XPHY_REGArray_Table_PG[i+2]);
720 }
721 }
722
723 return _SUCCESS;
724} /* phy_ConfigBBWithPgHeaderFile */
725
726static void
727phy_BB8192C_Config_1T(struct rtw_adapter *Adapter)
728{
729 /* for path - B */
730 PHY_SetBBReg(Adapter, rFPGA0_TxInfo, 0x3, 0x2);
731 PHY_SetBBReg(Adapter, rFPGA1_TxInfo, 0x300033, 0x200022);
732
733 /* 20100519 Joseph: Add for 1T2R config. Suggested by Kevin,
734 Jenyu and Yunan. */
735 PHY_SetBBReg(Adapter, rCCK0_AFESetting, bMaskByte3, 0x45);
736 PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, bMaskByte0, 0x23);
737 /* B path first AGC */
738 PHY_SetBBReg(Adapter, rOFDM0_AGCParameter1, 0x30, 0x1);
739
740 PHY_SetBBReg(Adapter, 0xe74, 0x0c000000, 0x2);
741 PHY_SetBBReg(Adapter, 0xe78, 0x0c000000, 0x2);
742 PHY_SetBBReg(Adapter, 0xe7c, 0x0c000000, 0x2);
743 PHY_SetBBReg(Adapter, 0xe80, 0x0c000000, 0x2);
744 PHY_SetBBReg(Adapter, 0xe88, 0x0c000000, 0x2);
745}
746
747static int
748phy_BB8723a_Config_ParaFile(struct rtw_adapter *Adapter)
749{
750 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(Adapter);
751 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
752 int rtStatus = _SUCCESS;
753
754 u8 sz8723BBRegFile[] = RTL8723_PHY_REG;
755 u8 sz8723AGCTableFile[] = RTL8723_AGC_TAB;
756 u8 sz8723BBRegPgFile[] = RTL8723_PHY_REG_PG;
757 u8 sz8723BBRegMpFile[] = RTL8723_PHY_REG_MP;
758
759 u8 *pszBBRegFile = NULL, *pszAGCTableFile = NULL;
760 u8 *pszBBRegPgFile = NULL, *pszBBRegMpFile = NULL;
761
762 /* RT_TRACE(COMP_INIT, DBG_TRACE, ("==>phy_BB8192S_Config_ParaFile\n")); */
763
764 pszBBRegFile = sz8723BBRegFile ;
765 pszAGCTableFile = sz8723AGCTableFile;
766 pszBBRegPgFile = sz8723BBRegPgFile;
767 pszBBRegMpFile = sz8723BBRegMpFile;
768
769 /* */
770 /* 1. Read PHY_REG.TXT BB INIT!! */
771 /* We will seperate as 88C / 92C according to chip version */
772 /* */
773 if (HAL_STATUS_FAILURE == ODM_ConfigBBWithHeaderFile23a(&pHalData->odmpriv,
774 CONFIG_BB_PHY_REG))
775 rtStatus = _FAIL;
776 if (rtStatus != _SUCCESS)
777 goto phy_BB8190_Config_ParaFile_Fail;
778
779 /* */
780 /* 20100318 Joseph: Config 2T2R to 1T2R if necessary. */
781 /* */
782 if (pHalData->rf_type == RF_1T2R) {
783 phy_BB8192C_Config_1T(Adapter);
784 DBG_8723A("phy_BB8723a_Config_ParaFile():Config to 1T!!\n");
785 }
786
787 /* */
788 /* 2. If EEPROM or EFUSE autoload OK, We must config by
789 PHY_REG_PG.txt */
790 /* */
791 if (pEEPROM->bautoload_fail_flag == false) {
792 pHalData->pwrGroupCnt = 0;
793
794 rtStatus = phy_ConfigBBWithPgHeaderFile(Adapter,
795 BaseBand_Config_PHY_REG);
796 }
797
798 if (rtStatus != _SUCCESS)
799 goto phy_BB8190_Config_ParaFile_Fail;
800
801 /* */
802 /* 3. BB AGC table Initialization */
803 /* */
804 if (HAL_STATUS_FAILURE == ODM_ConfigBBWithHeaderFile23a(&pHalData->odmpriv,
805 CONFIG_BB_AGC_TAB))
806 rtStatus = _FAIL;
807
808phy_BB8190_Config_ParaFile_Fail:
809
810 return rtStatus;
811}
812
813int
814PHY_BBConfig8723A(struct rtw_adapter *Adapter)
815{
816 int rtStatus = _SUCCESS;
817 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
818 u8 TmpU1B = 0;
819 u8 CrystalCap;
820
821 phy_InitBBRFRegisterDefinition(Adapter);
822
823 /* Suggested by Scott. tynli_test. 2010.12.30. */
824 /* 1. 0x28[1] = 1 */
825 TmpU1B = rtw_read8(Adapter, REG_AFE_PLL_CTRL);
826 udelay(2);
827 rtw_write8(Adapter, REG_AFE_PLL_CTRL, (TmpU1B|BIT1));
828 udelay(2);
829
830 /* 2. 0x29[7:0] = 0xFF */
831 rtw_write8(Adapter, REG_AFE_PLL_CTRL+1, 0xff);
832 udelay(2);
833
834 /* 3. 0x02[1:0] = 2b'11 */
835 TmpU1B = rtw_read8(Adapter, REG_SYS_FUNC_EN);
836 rtw_write8(Adapter, REG_SYS_FUNC_EN,
837 (TmpU1B | FEN_BB_GLB_RSTn | FEN_BBRSTB));
838
839 /* 4. 0x25[6] = 0 */
840 TmpU1B = rtw_read8(Adapter, REG_AFE_XTAL_CTRL + 1);
841 rtw_write8(Adapter, REG_AFE_XTAL_CTRL+1, (TmpU1B & (~BIT6)));
842
843 /* 5. 0x24[20] = 0 Advised by SD3 Alex Wang. 2011.02.09. */
844 TmpU1B = rtw_read8(Adapter, REG_AFE_XTAL_CTRL+2);
845 rtw_write8(Adapter, REG_AFE_XTAL_CTRL+2, (TmpU1B & (~BIT4)));
846
847 /* 6. 0x1f[7:0] = 0x07 */
848 rtw_write8(Adapter, REG_RF_CTRL, 0x07);
849
850 /* */
851 /* Config BB and AGC */
852 /* */
853 rtStatus = phy_BB8723a_Config_ParaFile(Adapter);
854
855/* only for B-cut */
856 if (pHalData->EEPROMVersion >= 0x01) {
857 CrystalCap = pHalData->CrystalCap & 0x3F;
858 PHY_SetBBReg(Adapter, REG_MAC_PHY_CTRL, 0xFFF000,
859 (CrystalCap | (CrystalCap << 6)));
860 }
861
862 PHY_SetBBReg(Adapter, REG_LDOA15_CTRL, bMaskDWord, 0x01572505);
863 return rtStatus;
864}
865
866int
867PHY_RFConfig8723A(struct rtw_adapter *Adapter)
868{
869 int rtStatus = _SUCCESS;
870
871 /* */
872 /* RF config */
873 /* */
874 rtStatus = PHY_RF6052_Config8723A(Adapter);
875 return rtStatus;
876}
877
878static void getTxPowerIndex(struct rtw_adapter *Adapter,
879 u8 channel, u8 *cckPowerLevel, u8 *ofdmPowerLevel)
880{
881 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
882 u8 index = (channel - 1);
883 /* 1. CCK */
884 cckPowerLevel[RF_PATH_A] = pHalData->TxPwrLevelCck[RF_PATH_A][index];
885 cckPowerLevel[RF_PATH_B] = pHalData->TxPwrLevelCck[RF_PATH_B][index];
886
887 /* 2. OFDM for 1S or 2S */
888 if (GET_RF_TYPE(Adapter) == RF_1T2R || GET_RF_TYPE(Adapter) == RF_1T1R) {
889 /* Read HT 40 OFDM TX power */
890 ofdmPowerLevel[RF_PATH_A] =
891 pHalData->TxPwrLevelHT40_1S[RF_PATH_A][index];
892 ofdmPowerLevel[RF_PATH_B] =
893 pHalData->TxPwrLevelHT40_1S[RF_PATH_B][index];
894 } else if (GET_RF_TYPE(Adapter) == RF_2T2R) {
895 /* Read HT 40 OFDM TX power */
896 ofdmPowerLevel[RF_PATH_A] =
897 pHalData->TxPwrLevelHT40_2S[RF_PATH_A][index];
898 ofdmPowerLevel[RF_PATH_B] =
899 pHalData->TxPwrLevelHT40_2S[RF_PATH_B][index];
900 }
901}
902
903static void ccxPowerIndexCheck(struct rtw_adapter *Adapter, u8 channel,
904 u8 *cckPowerLevel, u8 *ofdmPowerLevel)
905{
906}
907
908/*-----------------------------------------------------------------------------
909 * Function: SetTxPowerLevel8723A()
910 *
911 * Overview: This function is export to "HalCommon" moudule
912 * We must consider RF path later!!!!!!!
913 *
914 * Input: struct rtw_adapter * Adapter
915 * u8 channel
916 *
917 * Output: NONE
918 *
919 * Return: NONE
920 *
921 *---------------------------------------------------------------------------*/
922void PHY_SetTxPowerLevel8723A(struct rtw_adapter *Adapter, u8 channel)
923{
924 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
925 u8 cckPowerLevel[2], ofdmPowerLevel[2]; /* [0]:RF-A, [1]:RF-B */
926
927 if (pHalData->bTXPowerDataReadFromEEPORM == false)
928 return;
929
930 getTxPowerIndex(Adapter, channel, &cckPowerLevel[0],
931 &ofdmPowerLevel[0]);
932
933 ccxPowerIndexCheck(Adapter, channel, &cckPowerLevel[0],
934 &ofdmPowerLevel[0]);
935
936 rtl823a_phy_rf6052setccktxpower(Adapter, &cckPowerLevel[0]);
937 rtl8723a_PHY_RF6052SetOFDMTxPower(Adapter, &ofdmPowerLevel[0], channel);
938}
939
940/*-----------------------------------------------------------------------------
941 * Function: PHY_SetBWMode23aCallback8192C()
942 *
943 * Overview: Timer callback function for SetSetBWMode23a
944 *
945 * Input: PRT_TIMER pTimer
946 *
947 * Output: NONE
948 *
949 * Return: NONE
950 *
951 * Note:
952 * (1) We do not take j mode into consideration now
953 * (2) Will two workitem of "switch channel" and
954 * "switch channel bandwidth" run concurrently?
955 *---------------------------------------------------------------------------*/
956static void
957_PHY_SetBWMode23a92C(struct rtw_adapter *Adapter)
958{
959 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
960 u8 regBwOpMode;
961 u8 regRRSR_RSC;
962
963 if (pHalData->rf_chip == RF_PSEUDO_11N)
964 return;
965
966 /* There is no 40MHz mode in RF_8225. */
967 if (pHalData->rf_chip == RF_8225)
968 return;
969
970 if (Adapter->bDriverStopped)
971 return;
972
973 /* 3 */
974 /* 3<1>Set MAC register */
975 /* 3 */
976
977 regBwOpMode = rtw_read8(Adapter, REG_BWOPMODE);
978 regRRSR_RSC = rtw_read8(Adapter, REG_RRSR+2);
979
980 switch (pHalData->CurrentChannelBW) {
981 case HT_CHANNEL_WIDTH_20:
982 regBwOpMode |= BW_OPMODE_20MHZ;
983 rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode);
984 break;
985 case HT_CHANNEL_WIDTH_40:
986 regBwOpMode &= ~BW_OPMODE_20MHZ;
987 rtw_write8(Adapter, REG_BWOPMODE, regBwOpMode);
988 regRRSR_RSC = (regRRSR_RSC & 0x90) |
989 (pHalData->nCur40MhzPrimeSC << 5);
990 rtw_write8(Adapter, REG_RRSR+2, regRRSR_RSC);
991 break;
992
993 default:
994 break;
995 }
996
997 /* 3 */
998 /* 3<2>Set PHY related register */
999 /* 3 */
1000 switch (pHalData->CurrentChannelBW) {
1001 /* 20 MHz channel*/
1002 case HT_CHANNEL_WIDTH_20:
1003 PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x0);
1004 PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x0);
1005 PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter2, BIT10, 1);
1006
1007 break;
1008
1009 /* 40 MHz channel*/
1010 case HT_CHANNEL_WIDTH_40:
1011 PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bRFMOD, 0x1);
1012 PHY_SetBBReg(Adapter, rFPGA1_RFMOD, bRFMOD, 0x1);
1013
1014 /* Set Control channel to upper or lower. These settings
1015 are required only for 40MHz */
1016 PHY_SetBBReg(Adapter, rCCK0_System, bCCKSideBand,
1017 (pHalData->nCur40MhzPrimeSC >> 1));
1018 PHY_SetBBReg(Adapter, rOFDM1_LSTF, 0xC00,
1019 pHalData->nCur40MhzPrimeSC);
1020 PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter2, BIT10, 0);
1021
1022 PHY_SetBBReg(Adapter, 0x818, (BIT26 | BIT27),
1023 (pHalData->nCur40MhzPrimeSC ==
1024 HAL_PRIME_CHNL_OFFSET_LOWER) ? 2:1);
1025 break;
1026
1027 default:
1028 /*RT_TRACE(COMP_DBG, DBG_LOUD,
1029 ("PHY_SetBWMode23aCallback8192C(): unknown Bandwidth: %#X\n" \
1030 , pHalData->CurrentChannelBW));*/
1031 break;
1032 }
1033 /* Skip over setting of J-mode in BB register here. Default value
1034 is "None J mode". Emily 20070315 */
1035
1036 /* Added it for 20/40 mhz switch time evaluation by guangan 070531 */
1037 /* NowL = PlatformEFIORead4Byte(Adapter, TSFR); */
1038 /* NowH = PlatformEFIORead4Byte(Adapter, TSFR+4); */
1039 /* EndTime = ((u64)NowH << 32) + NowL; */
1040 /* RT_TRACE(COMP_SCAN, DBG_LOUD, ("SetBWMode23aCallback8190Pci: time
1041 of SetBWMode23a = %I64d us!\n", (EndTime - BeginTime))); */
1042
1043 /* 3<3>Set RF related register */
1044 switch (pHalData->rf_chip) {
1045 case RF_8225:
1046 /* PHY_SetRF8225Bandwidth(Adapter,
1047 pHalData->CurrentChannelBW); */
1048 break;
1049
1050 case RF_8256:
1051 /* Please implement this function in Hal8190PciPhy8256.c */
1052 /* PHY_SetRF8256Bandwidth(Adapter,
1053 pHalData->CurrentChannelBW); */
1054 break;
1055
1056 case RF_8258:
1057 /* Please implement this function in Hal8190PciPhy8258.c */
1058 /* PHY_SetRF8258Bandwidth(); */
1059 break;
1060
1061 case RF_PSEUDO_11N:
1062 /* Do Nothing */
1063 break;
1064
1065 case RF_6052:
1066 rtl8723a_phy_rf6052set_bw(Adapter, pHalData->CurrentChannelBW);
1067 break;
1068
1069 default:
1070 /* RT_ASSERT(false, ("Unknown RFChipID: %d\n",
1071 pHalData->RFChipID)); */
1072 break;
1073 }
1074
1075 /* pHalData->SetBWMode23aInProgress = false; */
1076
1077 /* RT_TRACE(COMP_SCAN, DBG_LOUD,
1078 ("<== PHY_SetBWMode23aCallback8192C() \n")); */
1079}
1080
1081 /*-----------------------------------------------------------------------------
1082 * Function: SetBWMode23a8190Pci()
1083 *
1084 * Overview: This function is export to "HalCommon" moudule
1085 *
1086 * Input: struct rtw_adapter * Adapter
1087 * enum ht_channel_width Bandwidth 20M or 40M
1088 *
1089 * Output: NONE
1090 *
1091 * Return: NONE
1092 *
1093 * Note: We do not take j mode into consideration now
1094 *---------------------------------------------------------------------------*/
1095void
1096PHY_SetBWMode23a8723A(struct rtw_adapter *Adapter,
1097 enum ht_channel_width Bandwidth, unsigned char Offset)
1098{
1099 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1100 enum ht_channel_width tmpBW = pHalData->CurrentChannelBW;
1101
1102 pHalData->CurrentChannelBW = Bandwidth;
1103
1104 pHalData->nCur40MhzPrimeSC = Offset;
1105
1106 if ((!Adapter->bDriverStopped) && (!Adapter->bSurpriseRemoved))
1107 _PHY_SetBWMode23a92C(Adapter);
1108 else
1109 pHalData->CurrentChannelBW = tmpBW;
1110}
1111
1112static void _PHY_SwChnl8723A(struct rtw_adapter *Adapter, u8 channel)
1113{
1114 u8 eRFPath;
1115 u32 param1, param2;
1116 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1117
1118 if (Adapter->bNotifyChannelChange)
1119 DBG_8723A("[%s] ch = %d\n", __FUNCTION__, channel);
1120
1121 /* s1. pre common command - CmdID_SetTxPowerLevel */
1122 PHY_SetTxPowerLevel8723A(Adapter, channel);
1123
1124 /* s2. RF dependent command - CmdID_RF_WriteReg,
1125 param1 = RF_CHNLBW, param2 = channel */
1126 param1 = RF_CHNLBW;
1127 param2 = channel;
1128 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) {
1129 pHalData->RfRegChnlVal[eRFPath] =
1130 (pHalData->RfRegChnlVal[eRFPath] & 0xfffffc00) | param2;
1131 PHY_SetRFReg(Adapter, (enum RF_RADIO_PATH)eRFPath, param1,
1132 bRFRegOffsetMask, pHalData->RfRegChnlVal[eRFPath]);
1133 }
1134
1135 /* s3. post common command - CmdID_End, None */
1136}
1137
1138void PHY_SwChnl8723A(struct rtw_adapter *Adapter, u8 channel)
1139{
1140 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1141 u8 tmpchannel = pHalData->CurrentChannel;
1142 bool result = true;
1143
1144 if (pHalData->rf_chip == RF_PSEUDO_11N) {
1145 /* return immediately if it is peudo-phy */
1146 return;
1147 }
1148
1149 if (channel == 0)
1150 channel = 1;
1151
1152 pHalData->CurrentChannel = channel;
1153
1154 if ((!Adapter->bDriverStopped) && (!Adapter->bSurpriseRemoved)) {
1155 _PHY_SwChnl8723A(Adapter, channel);
1156
1157 if (!result)
1158 pHalData->CurrentChannel = tmpchannel;
1159 } else {
1160 pHalData->CurrentChannel = tmpchannel;
1161 }
1162}
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c b/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c
new file mode 100644
index 000000000000..ed39c18c3f84
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_rf6052.c
@@ -0,0 +1,507 @@
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 ******************************************************************************/
15/******************************************************************************
16 *
17 *
18 * Module: rtl8192c_rf6052.c (Source C File)
19 *
20 * Note: Provide RF 6052 series relative API.
21 *
22 * Function:
23 *
24 * Export:
25 *
26 * Abbrev:
27 *
28 * History:
29 * Data Who Remark
30 *
31 * 09/25/2008 MHC Create initial version.
32 * 11/05/2008 MHC Add API for tw power setting.
33 *
34 *
35******************************************************************************/
36
37#define _RTL8723A_RF6052_C_
38
39#include <osdep_service.h>
40#include <drv_types.h>
41
42#include <rtl8723a_hal.h>
43
44/*---------------------------Define Local Constant---------------------------*/
45/* Define local structure for debug!!!!! */
46struct rf_shadow_compare_map {
47 /* Shadow register value */
48 u32 Value;
49 /* Compare or not flag */
50 u8 Compare;
51 /* Record If it had ever modified unpredicted */
52 u8 ErrorOrNot;
53 /* Recorver Flag */
54 u8 Recorver;
55 /* */
56 u8 Driver_Write;
57};
58
59/*-----------------------------------------------------------------------------
60 * Function: PHY_RF6052SetBandwidth()
61 *
62 * Overview: This function is called by SetBWMode23aCallback8190Pci() only
63 *
64 * Input: struct rtw_adapter * Adapter
65 * WIRELESS_BANDWIDTH_E Bandwidth 20M or 40M
66 *
67 * Output: NONE
68 *
69 * Return: NONE
70 *
71 * Note: For RF type 0222D
72 *---------------------------------------------------------------------------*/
73void rtl8723a_phy_rf6052set_bw(
74 struct rtw_adapter *Adapter,
75 enum ht_channel_width Bandwidth) /* 20M or 40M */
76{
77 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
78
79 switch (Bandwidth) {
80 case HT_CHANNEL_WIDTH_20:
81 pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff) | 0x0400);
82 PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
83 break;
84 case HT_CHANNEL_WIDTH_40:
85 pHalData->RfRegChnlVal[0] = ((pHalData->RfRegChnlVal[0] & 0xfffff3ff));
86 PHY_SetRFReg(Adapter, RF_PATH_A, RF_CHNLBW, bRFRegOffsetMask, pHalData->RfRegChnlVal[0]);
87 break;
88 default:
89 break;
90 }
91}
92
93/*-----------------------------------------------------------------------------
94 * Function: PHY_RF6052SetCckTxPower
95 *
96 * Overview:
97 *
98 * Input: NONE
99 *
100 * Output: NONE
101 *
102 * Return: NONE
103 *
104 * Revised History:
105 * When Who Remark
106 * 11/05/2008 MHC Simulate 8192series..
107 *
108 *---------------------------------------------------------------------------*/
109
110void rtl823a_phy_rf6052setccktxpower(struct rtw_adapter *Adapter, u8 *pPowerlevel)
111{
112 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
113 struct dm_priv *pdmpriv = &pHalData->dmpriv;
114 struct mlme_ext_priv *pmlmeext = &Adapter->mlmeextpriv;
115 u32 TxAGC[2] = {0, 0}, tmpval = 0;
116 bool TurboScanOff = false;
117 u8 idx1, idx2;
118 u8 *ptr;
119
120 /* According to SD3 eechou's suggestion, we need to disable turbo scan for RU. */
121 /* Otherwise, external PA will be broken if power index > 0x20. */
122 if (pHalData->EEPROMRegulatory != 0 || pHalData->ExternalPA)
123 TurboScanOff = true;
124
125 if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
126 TxAGC[RF_PATH_A] = 0x3f3f3f3f;
127 TxAGC[RF_PATH_B] = 0x3f3f3f3f;
128
129 TurboScanOff = true;/* disable turbo scan */
130
131 if (TurboScanOff) {
132 for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
133 TxAGC[idx1] =
134 pPowerlevel[idx1] | (pPowerlevel[idx1]<<8) |
135 (pPowerlevel[idx1]<<16) | (pPowerlevel[idx1]<<24);
136 /* 2010/10/18 MH For external PA module. We need to limit power index to be less than 0x20. */
137 if (TxAGC[idx1] > 0x20 && pHalData->ExternalPA)
138 TxAGC[idx1] = 0x20;
139 }
140 }
141 } else {
142/* 20100427 Joseph: Driver dynamic Tx power shall not affect Tx power. It shall be determined by power training mechanism. */
143/* Currently, we cannot fully disable driver dynamic tx power mechanism because it is referenced by BT coexist mechanism. */
144/* In the future, two mechanism shall be separated from each other and maintained independantly. Thanks for Lanhsin's reminder. */
145 if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) {
146 TxAGC[RF_PATH_A] = 0x10101010;
147 TxAGC[RF_PATH_B] = 0x10101010;
148 } else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2) {
149 TxAGC[RF_PATH_A] = 0x00000000;
150 TxAGC[RF_PATH_B] = 0x00000000;
151 } else {
152 for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
153 TxAGC[idx1] =
154 pPowerlevel[idx1] | (pPowerlevel[idx1]<<8) |
155 (pPowerlevel[idx1]<<16) | (pPowerlevel[idx1]<<24);
156 }
157
158 if (pHalData->EEPROMRegulatory == 0) {
159 tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][6]) +
160 (pHalData->MCSTxPowerLevelOriginalOffset[0][7]<<8);
161 TxAGC[RF_PATH_A] += tmpval;
162
163 tmpval = (pHalData->MCSTxPowerLevelOriginalOffset[0][14]) +
164 (pHalData->MCSTxPowerLevelOriginalOffset[0][15]<<24);
165 TxAGC[RF_PATH_B] += tmpval;
166 }
167 }
168 }
169
170 for (idx1 = RF_PATH_A; idx1 <= RF_PATH_B; idx1++) {
171 ptr = (u8 *)(&TxAGC[idx1]);
172 for (idx2 = 0; idx2 < 4; idx2++) {
173 if (*ptr > RF6052_MAX_TX_PWR)
174 *ptr = RF6052_MAX_TX_PWR;
175 ptr++;
176 }
177 }
178
179 /* rf-A cck tx power */
180 tmpval = TxAGC[RF_PATH_A]&0xff;
181 PHY_SetBBReg(Adapter, rTxAGC_A_CCK1_Mcs32, bMaskByte1, tmpval);
182 tmpval = TxAGC[RF_PATH_A]>>8;
183 PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
184
185 /* rf-B cck tx power */
186 tmpval = TxAGC[RF_PATH_B]>>24;
187 PHY_SetBBReg(Adapter, rTxAGC_B_CCK11_A_CCK2_11, bMaskByte0, tmpval);
188 tmpval = TxAGC[RF_PATH_B]&0x00ffffff;
189 PHY_SetBBReg(Adapter, rTxAGC_B_CCK1_55_Mcs32, 0xffffff00, tmpval);
190} /* PHY_RF6052SetCckTxPower */
191
192/* powerbase0 for OFDM rates */
193/* powerbase1 for HT MCS rates */
194static void getPowerBase(
195 struct rtw_adapter *Adapter,
196 u8 *pPowerLevel,
197 u8 Channel,
198 u32 *OfdmBase,
199 u32 *MCSBase
200 )
201{
202 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
203 u32 powerBase0, powerBase1;
204 u8 Legacy_pwrdiff = 0;
205 s8 HT20_pwrdiff = 0;
206 u8 i, powerlevel[2];
207
208 for (i = 0; i < 2; i++) {
209 powerlevel[i] = pPowerLevel[i];
210 Legacy_pwrdiff = pHalData->TxPwrLegacyHtDiff[i][Channel-1];
211 powerBase0 = powerlevel[i] + Legacy_pwrdiff;
212
213 powerBase0 = (powerBase0<<24) | (powerBase0<<16) | (powerBase0<<8) | powerBase0;
214 *(OfdmBase+i) = powerBase0;
215 }
216
217 for (i = 0; i < 2; i++) {
218 /* Check HT20 to HT40 diff */
219 if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20) {
220 HT20_pwrdiff = pHalData->TxPwrHt20Diff[i][Channel-1];
221 powerlevel[i] += HT20_pwrdiff;
222 }
223 powerBase1 = powerlevel[i];
224 powerBase1 = (powerBase1<<24) | (powerBase1<<16) | (powerBase1<<8) | powerBase1;
225 *(MCSBase+i) = powerBase1;
226 }
227}
228
229static void getTxPowerWriteValByRegulatory(
230 struct rtw_adapter *Adapter,
231 u8 Channel,
232 u8 index,
233 u32 *powerBase0,
234 u32 *powerBase1,
235 u32 *pOutWriteVal
236 )
237{
238 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
239 struct dm_priv *pdmpriv = &pHalData->dmpriv;
240 u8 i, chnlGroup = 0, pwr_diff_limit[4];
241 u32 writeVal, customer_limit, rf;
242
243 /* Index 0 & 1 = legacy OFDM, 2-5 = HT_MCS rate */
244 for (rf = 0; rf < 2; rf++) {
245 switch (pHalData->EEPROMRegulatory) {
246 case 0: /* Realtek better performance */
247 /* increase power diff defined by Realtek for large power */
248 chnlGroup = 0;
249 writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf?8:0)] +
250 ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
251 break;
252 case 1: /* Realtek regulatory */
253 /* increase power diff defined by Realtek for regulatory */
254 if (pHalData->pwrGroupCnt == 1)
255 chnlGroup = 0;
256 if (pHalData->pwrGroupCnt >= 3) {
257 if (Channel <= 3)
258 chnlGroup = 0;
259 else if (Channel >= 4 && Channel <= 9)
260 chnlGroup = 1;
261 else if (Channel > 9)
262 chnlGroup = 2;
263
264 if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
265 chnlGroup++;
266 else
267 chnlGroup += 4;
268 }
269 writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf?8:0)] +
270 ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
271 break;
272 case 2: /* Better regulatory */
273 /* don't increase any power diff */
274 writeVal = ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
275 break;
276 case 3: /* Customer defined power diff. */
277 chnlGroup = 0;
278
279 for (i = 0; i < 4; i++) {
280 pwr_diff_limit[i] = (u8)((pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index +
281 (rf ? 8 : 0)]&(0x7f << (i*8))) >> (i*8));
282 if (pHalData->CurrentChannelBW == HT_CHANNEL_WIDTH_40) {
283 if (pwr_diff_limit[i] > pHalData->PwrGroupHT40[rf][Channel-1])
284 pwr_diff_limit[i] = pHalData->PwrGroupHT40[rf][Channel-1];
285 } else {
286 if (pwr_diff_limit[i] > pHalData->PwrGroupHT20[rf][Channel-1])
287 pwr_diff_limit[i] = pHalData->PwrGroupHT20[rf][Channel-1];
288 }
289 }
290 customer_limit = (pwr_diff_limit[3]<<24) | (pwr_diff_limit[2]<<16) |
291 (pwr_diff_limit[1]<<8) | (pwr_diff_limit[0]);
292 writeVal = customer_limit + ((index<2)?powerBase0[rf]:powerBase1[rf]);
293 break;
294 default:
295 chnlGroup = 0;
296 writeVal = pHalData->MCSTxPowerLevelOriginalOffset[chnlGroup][index+(rf?8:0)] +
297 ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
298 break;
299 }
300
301/* 20100427 Joseph: Driver dynamic Tx power shall not affect Tx power. It shall be determined by power training mechanism. */
302/* Currently, we cannot fully disable driver dynamic tx power mechanism because it is referenced by BT coexist mechanism. */
303/* In the future, two mechanism shall be separated from each other and maintained independantly. Thanks for Lanhsin's reminder. */
304
305 if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1)
306 writeVal = 0x14141414;
307 else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2)
308 writeVal = 0x00000000;
309
310 /* 20100628 Joseph: High power mode for BT-Coexist mechanism. */
311 /* This mechanism is only applied when Driver-Highpower-Mechanism is OFF. */
312 if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_BT1)
313 writeVal = writeVal - 0x06060606;
314 else if (pdmpriv->DynamicTxHighPowerLvl == TxHighPwrLevel_BT2)
315 writeVal = writeVal;
316 *(pOutWriteVal+rf) = writeVal;
317 }
318}
319
320static void writeOFDMPowerReg(struct rtw_adapter *Adapter, u8 index, u32 *pValue)
321{
322 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
323 u16 RegOffset_A[6] = {
324 rTxAGC_A_Rate18_06, rTxAGC_A_Rate54_24,
325 rTxAGC_A_Mcs03_Mcs00, rTxAGC_A_Mcs07_Mcs04,
326 rTxAGC_A_Mcs11_Mcs08, rTxAGC_A_Mcs15_Mcs12
327 };
328 u16 RegOffset_B[6] = {
329 rTxAGC_B_Rate18_06, rTxAGC_B_Rate54_24,
330 rTxAGC_B_Mcs03_Mcs00, rTxAGC_B_Mcs07_Mcs04,
331 rTxAGC_B_Mcs11_Mcs08, rTxAGC_B_Mcs15_Mcs12
332 };
333 u8 i, rf, pwr_val[4];
334 u32 writeVal;
335 u16 RegOffset;
336
337 for (rf = 0; rf < 2; rf++) {
338 writeVal = pValue[rf];
339 for (i = 0; i < 4; i++) {
340 pwr_val[i] = (u8)((writeVal & (0x7f<<(i*8)))>>(i*8));
341 if (pwr_val[i] > RF6052_MAX_TX_PWR)
342 pwr_val[i] = RF6052_MAX_TX_PWR;
343 }
344 writeVal = (pwr_val[3]<<24) | (pwr_val[2]<<16) |
345 (pwr_val[1]<<8) | pwr_val[0];
346
347 if (rf == 0)
348 RegOffset = RegOffset_A[index];
349 else
350 RegOffset = RegOffset_B[index];
351
352 PHY_SetBBReg(Adapter, RegOffset, bMaskDWord, writeVal);
353
354 /* 201005115 Joseph: Set Tx Power diff for Tx power training mechanism. */
355 if (((pHalData->rf_type == RF_2T2R) &&
356 (RegOffset == rTxAGC_A_Mcs15_Mcs12 ||
357 RegOffset == rTxAGC_B_Mcs15_Mcs12)) ||
358 ((pHalData->rf_type != RF_2T2R) &&
359 (RegOffset == rTxAGC_A_Mcs07_Mcs04 ||
360 RegOffset == rTxAGC_B_Mcs07_Mcs04))) {
361 writeVal = pwr_val[3];
362 if (RegOffset == rTxAGC_A_Mcs15_Mcs12 || RegOffset == rTxAGC_A_Mcs07_Mcs04)
363 RegOffset = 0xc90;
364 if (RegOffset == rTxAGC_B_Mcs15_Mcs12 || RegOffset == rTxAGC_B_Mcs07_Mcs04)
365 RegOffset = 0xc98;
366 for (i = 0; i < 3; i++) {
367 if (i != 2)
368 writeVal = (writeVal > 8) ? (writeVal-8) : 0;
369 else
370 writeVal = (writeVal > 6) ? (writeVal-6) : 0;
371 rtw_write8(Adapter, (u32)(RegOffset+i), (u8)writeVal);
372 }
373 }
374 }
375}
376/*-----------------------------------------------------------------------------
377 * Function: PHY_RF6052SetOFDMTxPower
378 *
379 * Overview: For legacy and HY OFDM, we must read EEPROM TX power index for
380 * different channel and read original value in TX power register area from
381 * 0xe00. We increase offset and original value to be correct tx pwr.
382 *
383 * Input: NONE
384 *
385 * Output: NONE
386 *
387 * Return: NONE
388 *
389 * Revised History:
390 * When Who Remark
391 * 11/05/2008 MHC Simulate 8192 series method.
392 * 01/06/2009 MHC 1. Prevent Path B tx power overflow or underflow dure to
393 * A/B pwr difference or legacy/HT pwr diff.
394 * 2. We concern with path B legacy/HT OFDM difference.
395 * 01/22/2009 MHC Support new EPRO format from SD3.
396 *
397 *---------------------------------------------------------------------------*/
398void rtl8723a_PHY_RF6052SetOFDMTxPower(struct rtw_adapter *Adapter, u8 *pPowerLevel, u8 Channel)
399{
400 u32 writeVal[2], powerBase0[2], powerBase1[2];
401 u8 index = 0;
402
403 getPowerBase(Adapter, pPowerLevel, Channel, &powerBase0[0], &powerBase1[0]);
404
405 for (index = 0; index < 6; index++) {
406 getTxPowerWriteValByRegulatory(Adapter, Channel, index,
407 &powerBase0[0], &powerBase1[0], &writeVal[0]);
408
409 writeOFDMPowerReg(Adapter, index, &writeVal[0]);
410 }
411}
412
413static int phy_RF6052_Config_ParaFile(struct rtw_adapter *Adapter)
414{
415 u32 u4RegValue = 0;
416 u8 eRFPath;
417 struct bb_reg_define *pPhyReg;
418 int rtStatus = _SUCCESS;
419 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
420 static char sz8723RadioAFile[] = RTL8723_PHY_RADIO_A;
421 static char sz8723RadioBFile[] = RTL8723_PHY_RADIO_B;
422 char *pszRadioAFile, *pszRadioBFile;
423
424 pszRadioAFile = sz8723RadioAFile;
425 pszRadioBFile = sz8723RadioBFile;
426
427 /* 3----------------------------------------------------------------- */
428 /* 3 <2> Initialize RF */
429 /* 3----------------------------------------------------------------- */
430 for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) {
431
432 pPhyReg = &pHalData->PHYRegDef[eRFPath];
433
434 /*----Store original RFENV control type----*/
435 switch (eRFPath) {
436 case RF_PATH_A:
437 u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV);
438 break;
439 case RF_PATH_B:
440 u4RegValue = PHY_QueryBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV<<16);
441 break;
442 }
443
444 /*----Set RF_ENV enable----*/
445 PHY_SetBBReg(Adapter, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
446 udelay(1);/* PlatformStallExecution(1); */
447
448 /*----Set RF_ENV output high----*/
449 PHY_SetBBReg(Adapter, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
450 udelay(1);/* PlatformStallExecution(1); */
451
452 /* Set bit number of Address and Data for RF register */
453 PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); /* Set 1 to 4 bits for 8255 */
454 udelay(1);/* PlatformStallExecution(1); */
455
456 PHY_SetBBReg(Adapter, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); /* Set 0 to 12 bits for 8255 */
457 udelay(1);/* PlatformStallExecution(1); */
458
459 /*----Initialize RF fom connfiguration file----*/
460 switch (eRFPath) {
461 case RF_PATH_A:
462 if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile23a(&pHalData->odmpriv, (enum RF_RADIO_PATH)eRFPath, (enum RF_RADIO_PATH)eRFPath))
463 rtStatus = _FAIL;
464 break;
465 case RF_PATH_B:
466 if (HAL_STATUS_FAILURE == ODM_ConfigRFWithHeaderFile23a(&pHalData->odmpriv, (enum RF_RADIO_PATH)eRFPath, (enum RF_RADIO_PATH)eRFPath))
467 rtStatus = _FAIL;
468 break;
469 }
470
471 /*----Restore RFENV control type----*/;
472 switch (eRFPath) {
473 case RF_PATH_A:
474 PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
475 break;
476 case RF_PATH_B:
477 PHY_SetBBReg(Adapter, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue);
478 break;
479 }
480
481 if (rtStatus != _SUCCESS) {
482 /* RT_TRACE(COMP_FPGA, DBG_LOUD, ("phy_RF6052_Config_ParaFile():Radio[%d] Fail!!", eRFPath)); */
483 goto phy_RF6052_Config_ParaFile_Fail;
484 }
485 }
486phy_RF6052_Config_ParaFile_Fail:
487 return rtStatus;
488}
489
490int PHY_RF6052_Config8723A(struct rtw_adapter *Adapter)
491{
492 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
493 int rtStatus = _SUCCESS;
494
495 /* Initialize general global value */
496 /* TODO: Extend RF_PATH_C and RF_PATH_D in the future */
497 if (pHalData->rf_type == RF_1T1R)
498 pHalData->NumTotalRFPath = 1;
499 else
500 pHalData->NumTotalRFPath = 2;
501
502 /* Config BB and RF */
503 rtStatus = phy_RF6052_Config_ParaFile(Adapter);
504 return rtStatus;
505}
506
507/* End of HalRf6052.c */
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_rxdesc.c b/drivers/staging/rtl8723au/hal/rtl8723a_rxdesc.c
new file mode 100644
index 000000000000..81b5efe649fa
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_rxdesc.c
@@ -0,0 +1,69 @@
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 ******************************************************************************/
15#define _RTL8723A_REDESC_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <rtl8723a_hal.h>
20
21static void process_rssi(struct rtw_adapter *padapter,
22 struct recv_frame *prframe)
23{
24 struct rx_pkt_attrib *pattrib = &prframe->attrib;
25 struct signal_stat *signal_stat = &padapter->recvpriv.signal_strength_data;
26
27 if (signal_stat->update_req) {
28 signal_stat->total_num = 0;
29 signal_stat->total_val = 0;
30 signal_stat->update_req = 0;
31 }
32
33 signal_stat->total_num++;
34 signal_stat->total_val += pattrib->phy_info.SignalStrength;
35 signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
36}
37
38static void process_link_qual(struct rtw_adapter *padapter,
39 struct recv_frame *prframe)
40{
41 struct rx_pkt_attrib *pattrib;
42 struct signal_stat *signal_stat;
43
44 if (prframe == NULL || padapter == NULL)
45 return;
46
47 pattrib = &prframe->attrib;
48 signal_stat = &padapter->recvpriv.signal_qual_data;
49
50 if (signal_stat->update_req) {
51 signal_stat->total_num = 0;
52 signal_stat->total_val = 0;
53 signal_stat->update_req = 0;
54 }
55
56 signal_stat->total_num++;
57 signal_stat->total_val += pattrib->phy_info.SignalQuality;
58 signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
59}
60
61/* void rtl8723a_process_phy_info(struct rtw_adapter *padapter, union recv_frame *prframe) */
62void rtl8723a_process_phy_info(struct rtw_adapter *padapter, void *prframe)
63{
64 struct recv_frame *precvframe = prframe;
65 /* Check RSSI */
66 process_rssi(padapter, precvframe);
67 /* Check EVM */
68 process_link_qual(padapter, precvframe);
69}
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_sreset.c b/drivers/staging/rtl8723au/hal/rtl8723a_sreset.c
new file mode 100644
index 000000000000..c0218e734b9e
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_sreset.c
@@ -0,0 +1,73 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _RTL8723A_SRESET_C_
16
17#include <rtl8723a_sreset.h>
18#include <rtl8723a_hal.h>
19
20void rtl8723a_sreset_xmit_status_check(struct rtw_adapter *padapter)
21{
22 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
23 struct sreset_priv *psrtpriv = &pHalData->srestpriv;
24
25 unsigned long current_time;
26 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
27 unsigned int diff_time;
28 u32 txdma_status;
29
30 txdma_status = rtw_read32(padapter, REG_TXDMA_STATUS);
31 if (txdma_status != 0) {
32 DBG_8723A("%s REG_TXDMA_STATUS:0x%08x\n", __func__, txdma_status);
33 rtw_hal_sreset_reset23a(padapter);
34 }
35
36 current_time = jiffies;
37
38 if (0 == pxmitpriv->free_xmitbuf_cnt || 0 == pxmitpriv->free_xmit_extbuf_cnt) {
39
40 diff_time = jiffies_to_msecs(jiffies - psrtpriv->last_tx_time);
41
42 if (diff_time > 2000) {
43 if (psrtpriv->last_tx_complete_time == 0) {
44 psrtpriv->last_tx_complete_time = current_time;
45 } else {
46 diff_time = jiffies_to_msecs(jiffies - psrtpriv->last_tx_complete_time);
47 if (diff_time > 4000) {
48 /* padapter->Wifi_Error_Status = WIFI_TX_HANG; */
49 DBG_8723A("%s tx hang\n", __func__);
50 rtw_hal_sreset_reset23a(padapter);
51 }
52 }
53 }
54 }
55
56 if (psrtpriv->dbg_trigger_point == SRESET_TGP_XMIT_STATUS) {
57 psrtpriv->dbg_trigger_point = SRESET_TGP_NULL;
58 rtw_hal_sreset_reset23a(padapter);
59 return;
60 }
61}
62
63void rtl8723a_sreset_linked_status_check(struct rtw_adapter *padapter)
64{
65 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
66 struct sreset_priv *psrtpriv = &pHalData->srestpriv;
67
68 if (psrtpriv->dbg_trigger_point == SRESET_TGP_LINK_STATUS) {
69 psrtpriv->dbg_trigger_point = SRESET_TGP_NULL;
70 rtw_hal_sreset_reset23a(padapter);
71 return;
72 }
73}
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_xmit.c b/drivers/staging/rtl8723au/hal/rtl8723a_xmit.c
new file mode 100644
index 000000000000..d7612ccc47e9
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_xmit.c
@@ -0,0 +1,52 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _RTL8723A_XMIT_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <rtl8723a_hal.h>
20
21void dump_txrpt_ccx_8723a(void *buf)
22{
23 struct txrpt_ccx_8723a *txrpt_ccx = buf;
24
25 DBG_8723A("%s:\n"
26 "tag1:%u, rsvd:%u, int_bt:%u, int_tri:%u, int_ccx:%u\n"
27 "mac_id:%u, pkt_drop:%u, pkt_ok:%u, bmc:%u\n"
28 "retry_cnt:%u, lifetime_over:%u, retry_over:%u\n"
29 "ccx_qtime:%u\n"
30 "final_data_rate:0x%02x\n"
31 "qsel:%u, sw:0x%03x\n"
32 , __func__
33 , txrpt_ccx->tag1, txrpt_ccx->rsvd, txrpt_ccx->int_bt, txrpt_ccx->int_tri, txrpt_ccx->int_ccx
34 , txrpt_ccx->mac_id, txrpt_ccx->pkt_drop, txrpt_ccx->pkt_ok, txrpt_ccx->bmc
35 , txrpt_ccx->retry_cnt, txrpt_ccx->lifetime_over, txrpt_ccx->retry_over
36 , txrpt_ccx_qtime_8723a(txrpt_ccx)
37 , txrpt_ccx->final_data_rate
38 , txrpt_ccx->qsel, txrpt_ccx_sw_8723a(txrpt_ccx)
39 );
40}
41
42void handle_txrpt_ccx_8723a(struct rtw_adapter *adapter, void *buf)
43{
44 struct txrpt_ccx_8723a *txrpt_ccx = buf;
45
46 if (txrpt_ccx->int_ccx) {
47 if (txrpt_ccx->pkt_ok)
48 rtw_ack_tx_done23a(&adapter->xmitpriv, RTW_SCTX_DONE_SUCCESS);
49 else
50 rtw_ack_tx_done23a(&adapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL);
51 }
52}
diff --git a/drivers/staging/rtl8723au/hal/rtl8723au_led.c b/drivers/staging/rtl8723au/hal/rtl8723au_led.c
new file mode 100644
index 000000000000..4d5c909487f8
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/rtl8723au_led.c
@@ -0,0 +1,113 @@
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 ******************************************************************************/
15
16#include "drv_types.h"
17#include "rtl8723a_hal.h"
18#include "rtl8723a_led.h"
19
20/* */
21/* LED object. */
22/* */
23
24/* */
25/* Prototype of protected function. */
26/* */
27
28/* */
29/* LED_819xUsb routines. */
30/* */
31
32/* Description: */
33/* Turn on LED according to LedPin specified. */
34void SwLedOn23a(struct rtw_adapter *padapter, struct led_8723a *pLed)
35{
36 u8 LedCfg = 0;
37
38 if ((padapter->bSurpriseRemoved == true) || (padapter->bDriverStopped == true))
39 return;
40 switch (pLed->LedPin) {
41 case LED_PIN_GPIO0:
42 break;
43 case LED_PIN_LED0:
44 rtw_write8(padapter, REG_LEDCFG0, (LedCfg&0xf0)|BIT5|BIT6); /* SW control led0 on. */
45 break;
46 case LED_PIN_LED1:
47 rtw_write8(padapter, REG_LEDCFG1, (LedCfg&0x00)|BIT6); /* SW control led1 on. */
48 break;
49 case LED_PIN_LED2:
50 LedCfg = rtw_read8(padapter, REG_LEDCFG2);
51 rtw_write8(padapter, REG_LEDCFG2, (LedCfg&0x80)|BIT5); /* SW control led1 on. */
52 break;
53 default:
54 break;
55 }
56 pLed->bLedOn = true;
57}
58
59/* Description: */
60/* Turn off LED according to LedPin specified. */
61void SwLedOff23a(struct rtw_adapter *padapter, struct led_8723a *pLed)
62{
63 u8 LedCfg = 0;
64 /* struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter); */
65
66 if ((padapter->bSurpriseRemoved) || (padapter->bDriverStopped))
67 goto exit;
68
69 switch (pLed->LedPin) {
70 case LED_PIN_GPIO0:
71 break;
72 case LED_PIN_LED0:
73 rtw_write8(padapter, REG_LEDCFG0, (LedCfg&0xf0)|BIT5|BIT6); /* SW control led0 on. */
74 break;
75 case LED_PIN_LED1:
76 rtw_write8(padapter, REG_LEDCFG1, (LedCfg&0x00)|BIT5|BIT6); /* SW control led1 on. */
77 break;
78 case LED_PIN_LED2:
79 LedCfg = rtw_read8(padapter, REG_LEDCFG2);
80 rtw_write8(padapter, REG_LEDCFG2, (LedCfg&0x80)|BIT3|BIT5); /* SW control led1 on. */
81 break;
82 default:
83 break;
84 }
85exit:
86 pLed->bLedOn = false;
87}
88
89/* Interface to manipulate LED objects. */
90
91/* Description: */
92/* Initialize all LED_871x objects. */
93void
94rtl8723au_InitSwLeds(struct rtw_adapter *padapter)
95{
96 struct led_priv *pledpriv = &padapter->ledpriv;
97
98 pledpriv->LedControlHandler = LedControl871x23a;
99 /* 8723as-vau wifi used led2 */
100 InitLed871x23a(padapter, &pledpriv->SwLed0, LED_PIN_LED2);
101
102/* InitLed871x23a(padapter,&pledpriv->SwLed1, LED_PIN_LED2); */
103}
104
105/* Description: */
106/* DeInitialize all LED_819xUsb objects. */
107void
108rtl8723au_DeInitSwLeds(struct rtw_adapter *padapter)
109{
110 struct led_priv *ledpriv = &padapter->ledpriv;
111
112 DeInitLed871x23a(&ledpriv->SwLed0);
113}
diff --git a/drivers/staging/rtl8723au/hal/rtl8723au_recv.c b/drivers/staging/rtl8723au/hal/rtl8723au_recv.c
new file mode 100644
index 000000000000..213d1936109d
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/rtl8723au_recv.c
@@ -0,0 +1,247 @@
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 ******************************************************************************/
15#define _RTL8192CU_RECV_C_
16#include <osdep_service.h>
17#include <drv_types.h>
18#include <recv_osdep.h>
19#include <mlme_osdep.h>
20#include <linux/ip.h>
21#include <linux/if_ether.h>
22#include <ethernet.h>
23#include <usb_ops.h>
24#include <wifi.h>
25#include <rtl8723a_hal.h>
26
27void rtl8723au_init_recvbuf(struct rtw_adapter *padapter,
28 struct recv_buf *precvbuf)
29{
30}
31
32int rtl8723au_init_recv_priv(struct rtw_adapter *padapter)
33{
34 struct recv_priv *precvpriv = &padapter->recvpriv;
35 int i, size, res = _SUCCESS;
36 struct recv_buf *precvbuf;
37 unsigned long tmpaddr;
38 unsigned long alignment;
39 struct sk_buff *pskb;
40
41 tasklet_init(&precvpriv->recv_tasklet,
42 (void(*)(unsigned long))rtl8723au_recv_tasklet,
43 (unsigned long)padapter);
44
45 precvpriv->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
46 if (!precvpriv->int_in_urb)
47 DBG_8723A("alloc_urb for interrupt in endpoint fail !!!!\n");
48 precvpriv->int_in_buf = kzalloc(USB_INTR_CONTENT_LENGTH, GFP_KERNEL);
49 if (!precvpriv->int_in_buf)
50 DBG_8723A("alloc_mem for interrupt in endpoint fail !!!!\n");
51
52 /* init recv_buf */
53 _rtw_init_queue23a(&precvpriv->free_recv_buf_queue);
54
55 size = NR_RECVBUFF * sizeof(struct recv_buf);
56 precvpriv->precv_buf = kzalloc(size, GFP_KERNEL);
57 if (!precvpriv->precv_buf) {
58 res = _FAIL;
59 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
60 ("alloc recv_buf fail!\n"));
61 goto exit;
62 }
63
64 precvbuf = (struct recv_buf *)precvpriv->precv_buf;
65
66 for (i = 0; i < NR_RECVBUFF; i++) {
67 INIT_LIST_HEAD(&precvbuf->list);
68
69 res = rtw_os_recvbuf_resource_alloc23a(padapter, precvbuf);
70 if (res == _FAIL)
71 break;
72
73 precvbuf->adapter = padapter;
74
75 precvbuf++;
76 }
77
78 precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
79
80 skb_queue_head_init(&precvpriv->rx_skb_queue);
81 skb_queue_head_init(&precvpriv->free_recv_skb_queue);
82
83 for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) {
84 size = MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ;
85 pskb = __netdev_alloc_skb(padapter->pnetdev, size, GFP_KERNEL);
86
87 if (pskb) {
88 pskb->dev = padapter->pnetdev;
89
90 tmpaddr = (unsigned long)pskb->data;
91 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
92 skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
93
94 skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
95 }
96
97 pskb = NULL;
98 }
99
100exit:
101 return res;
102}
103
104void rtl8723au_free_recv_priv(struct rtw_adapter *padapter)
105{
106 int i;
107 struct recv_buf *precvbuf;
108 struct recv_priv *precvpriv = &padapter->recvpriv;
109
110 precvbuf = (struct recv_buf *)precvpriv->precv_buf;
111
112 for (i = 0; i < NR_RECVBUFF; i++) {
113 rtw_os_recvbuf_resource_free23a(padapter, precvbuf);
114 precvbuf++;
115 }
116
117 kfree(precvpriv->precv_buf);
118
119 usb_free_urb(precvpriv->int_in_urb);
120 kfree(precvpriv->int_in_buf);
121
122 if (skb_queue_len(&precvpriv->rx_skb_queue))
123 DBG_8723A(KERN_WARNING "rx_skb_queue not empty\n");
124
125 skb_queue_purge(&precvpriv->rx_skb_queue);
126
127 if (skb_queue_len(&precvpriv->free_recv_skb_queue)) {
128 DBG_8723A(KERN_WARNING "free_recv_skb_queue not empty, %d\n",
129 skb_queue_len(&precvpriv->free_recv_skb_queue));
130 }
131
132 skb_queue_purge(&precvpriv->free_recv_skb_queue);
133}
134
135void update_recvframe_attrib(struct recv_frame *precvframe,
136 struct recv_stat *prxstat)
137{
138 struct rx_pkt_attrib *pattrib;
139 struct recv_stat report;
140 struct rxreport_8723a *prxreport;
141
142 report.rxdw0 = le32_to_cpu(prxstat->rxdw0);
143 report.rxdw1 = le32_to_cpu(prxstat->rxdw1);
144 report.rxdw2 = le32_to_cpu(prxstat->rxdw2);
145 report.rxdw3 = le32_to_cpu(prxstat->rxdw3);
146 report.rxdw4 = le32_to_cpu(prxstat->rxdw4);
147 report.rxdw5 = le32_to_cpu(prxstat->rxdw5);
148
149 prxreport = (struct rxreport_8723a *)&report;
150
151 pattrib = &precvframe->attrib;
152 memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
153
154 /* update rx report to recv_frame attribute */
155 pattrib->pkt_len = (u16)prxreport->pktlen;
156 pattrib->drvinfo_sz = (u8)(prxreport->drvinfosize << 3);
157 pattrib->physt = (u8)prxreport->physt;
158
159 pattrib->crc_err = (u8)prxreport->crc32;
160 pattrib->icv_err = (u8)prxreport->icverr;
161
162 pattrib->bdecrypted = (u8)(prxreport->swdec ? 0 : 1);
163 pattrib->encrypt = (u8)prxreport->security;
164
165 pattrib->qos = (u8)prxreport->qos;
166 pattrib->priority = (u8)prxreport->tid;
167
168 pattrib->amsdu = (u8)prxreport->amsdu;
169
170 pattrib->seq_num = (u16)prxreport->seq;
171 pattrib->frag_num = (u8)prxreport->frag;
172 pattrib->mfrag = (u8)prxreport->mf;
173 pattrib->mdata = (u8)prxreport->md;
174
175 pattrib->mcs_rate = (u8)prxreport->rxmcs;
176 pattrib->rxht = (u8)prxreport->rxht;
177}
178
179void update_recvframe_phyinfo(struct recv_frame *precvframe,
180 struct phy_stat *pphy_status)
181{
182 struct rtw_adapter *padapter = precvframe->adapter;
183 struct rx_pkt_attrib *pattrib = &precvframe->attrib;
184 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
185 struct odm_phy_info *pPHYInfo = (struct odm_phy_info *)(&pattrib->phy_info);
186 struct odm_packet_info pkt_info;
187 u8 *sa = NULL, *da;
188 struct sta_priv *pstapriv;
189 struct sta_info *psta;
190 struct sk_buff *skb = precvframe->pkt;
191 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
192 u8 *wlanhdr = skb->data;
193
194 pkt_info.bPacketMatchBSSID = false;
195 pkt_info.bPacketToSelf = false;
196 pkt_info.bPacketBeacon = false;
197
198 pkt_info.bPacketMatchBSSID =
199 (!ieee80211_is_ctl(hdr->frame_control) &&
200 !pattrib->icv_err &&
201 !pattrib->crc_err &&
202 !memcmp(get_hdr_bssid(wlanhdr),
203 get_bssid(&padapter->mlmepriv), ETH_ALEN));
204
205 da = ieee80211_get_DA(hdr);
206 pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID &&
207 (!memcmp(da, myid(&padapter->eeprompriv), ETH_ALEN));
208
209 pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID &&
210 ieee80211_is_beacon(hdr->frame_control);
211
212 pkt_info.StationID = 0xFF;
213 if (pkt_info.bPacketBeacon) {
214 if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == true)
215 sa = padapter->mlmepriv.cur_network.network.MacAddress;
216 /* to do Ad-hoc */
217 } else {
218 sa = ieee80211_get_SA(hdr);
219 }
220
221 pstapriv = &padapter->stapriv;
222 psta = rtw_get_stainfo23a(pstapriv, sa);
223 if (psta) {
224 pkt_info.StationID = psta->mac_id;
225 /* printk("%s ==> StationID(%d)\n", __FUNCTION__, pkt_info.StationID); */
226 }
227 pkt_info.Rate = pattrib->mcs_rate;
228
229 ODM_PhyStatusQuery23a(&pHalData->odmpriv, pPHYInfo,
230 (u8 *)pphy_status, &pkt_info);
231 precvframe->psta = NULL;
232 if (pkt_info.bPacketMatchBSSID &&
233 (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)) {
234 if (psta) {
235 precvframe->psta = psta;
236 rtl8723a_process_phy_info(padapter, precvframe);
237 }
238 } else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon) {
239 if (check_fwstate(&padapter->mlmepriv,
240 WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) ==
241 true) {
242 if (psta)
243 precvframe->psta = psta;
244 }
245 rtl8723a_process_phy_info(padapter, precvframe);
246 }
247}
diff --git a/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c b/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c
new file mode 100644
index 000000000000..2af2e3ee1abc
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c
@@ -0,0 +1,548 @@
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 ******************************************************************************/
15#define _RTL8192C_XMIT_C_
16#include <osdep_service.h>
17#include <drv_types.h>
18#include <wifi.h>
19#include <osdep_intf.h>
20#include <usb_ops.h>
21/* include <rtl8192c_hal.h> */
22#include <rtl8723a_hal.h>
23
24s32 rtl8723au_init_xmit_priv(struct rtw_adapter *padapter)
25{
26 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
27
28 tasklet_init(&pxmitpriv->xmit_tasklet,
29 (void(*)(unsigned long))rtl8723au_xmit_tasklet,
30 (unsigned long)padapter);
31 return _SUCCESS;
32}
33
34void rtl8723au_free_xmit_priv(struct rtw_adapter *padapter)
35{
36}
37
38static void do_queue_select(struct rtw_adapter *padapter, struct pkt_attrib *pattrib)
39{
40 u8 qsel;
41
42 qsel = pattrib->priority;
43 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
44 ("### do_queue_select priority =%d , qsel = %d\n",
45 pattrib->priority, qsel));
46
47 pattrib->qsel = qsel;
48}
49
50static int urb_zero_packet_chk(struct rtw_adapter *padapter, int sz)
51{
52 int blnSetTxDescOffset;
53 struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
54
55 if (pdvobj->ishighspeed) {
56 if (((sz + TXDESC_SIZE) % 512) == 0)
57 blnSetTxDescOffset = 1;
58 else
59 blnSetTxDescOffset = 0;
60 } else {
61 if (((sz + TXDESC_SIZE) % 64) == 0)
62 blnSetTxDescOffset = 1;
63 else
64 blnSetTxDescOffset = 0;
65 }
66 return blnSetTxDescOffset;
67}
68
69static void rtl8192cu_cal_txdesc_chksum(struct tx_desc *ptxdesc)
70{
71 u16 *usPtr = (u16 *)ptxdesc;
72 u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */
73 u32 index;
74 u16 checksum = 0;
75
76 /* Clear first */
77 ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
78
79 for (index = 0 ; index < count ; index++)
80 checksum = checksum ^ le16_to_cpu(*(usPtr + index));
81
82 ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff&checksum);
83}
84
85static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc)
86{
87 if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
88 switch (pattrib->encrypt) {
89 /* SEC_TYPE */
90 case _WEP40_:
91 case _WEP104_:
92 ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000);
93 break;
94 case _TKIP_:
95 case _TKIP_WTMIC_:
96 /* ptxdesc->txdw1 |= cpu_to_le32((0x02<<22)&0x00c00000); */
97 ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000);
98 break;
99 case _AES_:
100 ptxdesc->txdw1 |= cpu_to_le32((0x03<<22)&0x00c00000);
101 break;
102 case _NO_PRIVACY_:
103 default:
104 break;
105 }
106 }
107}
108
109static void fill_txdesc_vcs(struct pkt_attrib *pattrib, u32 *pdw)
110{
111 /* DBG_8723A("cvs_mode =%d\n", pattrib->vcs_mode); */
112
113 switch (pattrib->vcs_mode) {
114 case RTS_CTS:
115 *pdw |= cpu_to_le32(BIT(12));
116 break;
117 case CTS_TO_SELF:
118 *pdw |= cpu_to_le32(BIT(11));
119 break;
120 case NONE_VCS:
121 default:
122 break;
123 }
124
125 if (pattrib->vcs_mode) {
126 *pdw |= cpu_to_le32(BIT(13));
127
128 /* Set RTS BW */
129 if (pattrib->ht_en) {
130 *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(27)) : 0;
131
132 if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
133 *pdw |= cpu_to_le32((0x01<<28)&0x30000000);
134 else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
135 *pdw |= cpu_to_le32((0x02<<28)&0x30000000);
136 else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
137 *pdw |= 0;
138 else
139 *pdw |= cpu_to_le32((0x03<<28)&0x30000000);
140 }
141 }
142}
143
144static void fill_txdesc_phy(struct pkt_attrib *pattrib, u32 *pdw)
145{
146 if (pattrib->ht_en) {
147 *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0;
148
149 if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
150 *pdw |= cpu_to_le32((0x01<<20)&0x003f0000);
151 else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
152 *pdw |= cpu_to_le32((0x02<<20)&0x003f0000);
153 else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
154 *pdw |= 0;
155 else
156 *pdw |= cpu_to_le32((0x03<<20)&0x003f0000);
157 }
158}
159
160static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bagg_pkt)
161{
162 int pull = 0;
163 uint qsel;
164 struct rtw_adapter *padapter = pxmitframe->padapter;
165 struct pkt_attrib *pattrib = &pxmitframe->attrib;
166 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
167 struct dm_priv *pdmpriv = &pHalData->dmpriv;
168 struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
169 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
170 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
171 int bmcst = is_multicast_ether_addr(pattrib->ra);
172
173 if ((!bagg_pkt) && (urb_zero_packet_chk(padapter, sz) == 0)) {
174 ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ);
175 pull = 1;
176 pxmitframe->pkt_offset--;
177 }
178
179 memset(ptxdesc, 0, sizeof(struct tx_desc));
180
181 if ((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) {
182 /* offset 4 */
183 ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f);
184
185 qsel = (uint)(pattrib->qsel & 0x0000001f);
186 ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
187
188 ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000);
189
190 fill_txdesc_sectype(pattrib, ptxdesc);
191
192 if (pattrib->ampdu_en)
193 ptxdesc->txdw1 |= cpu_to_le32(BIT(5));/* AGG EN */
194 else
195 ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */
196
197 /* offset 8 */
198
199 /* offset 12 */
200 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
201
202 /* offset 16 , offset 20 */
203 if (pattrib->qos_en)
204 ptxdesc->txdw4 |= cpu_to_le32(BIT(6));/* QoS */
205
206 if ((pattrib->ether_type != 0x888e) &&
207 (pattrib->ether_type != 0x0806) &&
208 (pattrib->dhcp_pkt != 1)) {
209 /* Non EAP & ARP & DHCP type data packet */
210
211 fill_txdesc_vcs(pattrib, &ptxdesc->txdw4);
212 fill_txdesc_phy(pattrib, &ptxdesc->txdw4);
213
214 ptxdesc->txdw4 |= cpu_to_le32(0x00000008);/* RTS Rate = 24M */
215 ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/* */
216
217 /* use REG_INIDATA_RATE_SEL value */
218 ptxdesc->txdw5 |= cpu_to_le32(pdmpriv->INIDATA_RATE[pattrib->mac_id]);
219 } else {
220 /* EAP data packet and ARP packet. */
221 /* Use the 1M data rate to send the EAP/ARP packet. */
222 /* This will maybe make the handshake smooth. */
223
224 ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */
225
226 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
227
228 if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
229 ptxdesc->txdw4 |= cpu_to_le32(BIT(24));/* DATA_SHORT */
230
231 ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
232 }
233 } else if ((pxmitframe->frame_tag&0x0f) == MGNT_FRAMETAG) {
234 /* offset 4 */
235 ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f);
236
237 qsel = (uint)(pattrib->qsel&0x0000001f);
238 ptxdesc->txdw1 |= cpu_to_le32((qsel<<QSEL_SHT)&0x00001f00);
239
240 ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000);
241
242 /* offset 8 */
243 /* CCX-TXRPT ack for xmit mgmt frames. */
244 if (pxmitframe->ack_report)
245 ptxdesc->txdw2 |= cpu_to_le32(BIT(19));
246
247 /* offset 12 */
248 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
249
250 /* offset 16 */
251 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
252
253 /* offset 20 */
254 ptxdesc->txdw5 |= cpu_to_le32(BIT(17));/* retry limit enable */
255 ptxdesc->txdw5 |= cpu_to_le32(0x00180000);/* retry limit = 6 */
256
257 ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
258 } else if ((pxmitframe->frame_tag&0x0f) == TXAGG_FRAMETAG) {
259 DBG_8723A("pxmitframe->frame_tag == TXAGG_FRAMETAG\n");
260 } else {
261 DBG_8723A("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag);
262
263 /* offset 4 */
264 ptxdesc->txdw1 |= cpu_to_le32((4)&0x1f);/* CAM_ID(MAC_ID) */
265
266 ptxdesc->txdw1 |= cpu_to_le32((6<<16) & 0x000f0000);/* raid */
267
268 /* offset 8 */
269
270 /* offset 12 */
271 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
272
273 /* offset 16 */
274 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
275
276 /* offset 20 */
277 ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
278 }
279
280 /* (1) The sequence number of each non-Qos frame / broadcast / multicast / */
281 /* mgnt frame should be controled by Hw because Fw will also send null data */
282 /* which we cannot control when Fw LPS enable. */
283 /* --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */
284 /* (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */
285 /* (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */
286 if (!pattrib->qos_en) {
287 /* Hw set sequence number */
288 ptxdesc->txdw4 |= cpu_to_le32(BIT(7));
289 /* set bit3 to 1. */
290 ptxdesc->txdw3 |= cpu_to_le32((8 << 28));
291 }
292
293 /* offset 0 */
294 ptxdesc->txdw0 |= cpu_to_le32(sz&0x0000ffff);
295 ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
296 ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);/* 32 bytes for TX Desc */
297
298 if (bmcst)
299 ptxdesc->txdw0 |= cpu_to_le32(BIT(24));
300
301 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("offset0-txdesc = 0x%x\n", ptxdesc->txdw0));
302
303 /* offset 4 */
304 /* pkt_offset, unit:8 bytes padding */
305 if (pxmitframe->pkt_offset > 0)
306 ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000);
307
308 rtl8192cu_cal_txdesc_chksum(ptxdesc);
309 return pull;
310}
311
312static s32 rtw_dump_xframe(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
313{
314 s32 ret = _SUCCESS;
315 s32 inner_ret = _SUCCESS;
316 int t, sz, w_sz, pull = 0;
317 u8 *mem_addr;
318 u32 ff_hwaddr;
319 struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
320 struct pkt_attrib *pattrib = &pxmitframe->attrib;
321 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
322
323 if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
324 (pxmitframe->attrib.ether_type != 0x0806) &&
325 (pxmitframe->attrib.ether_type != 0x888e) &&
326 (pxmitframe->attrib.dhcp_pkt != 1))
327 rtw_issue_addbareq_cmd23a(padapter, pxmitframe);
328
329 mem_addr = pxmitframe->buf_addr;
330
331 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_dump_xframe()\n"));
332
333 for (t = 0; t < pattrib->nr_frags; t++) {
334 if (inner_ret != _SUCCESS && ret == _SUCCESS)
335 ret = _FAIL;
336
337 if (t != (pattrib->nr_frags - 1)) {
338 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
339 ("pattrib->nr_frags =%d\n", pattrib->nr_frags));
340
341 sz = pxmitpriv->frag_len;
342 sz = sz - 4 - pattrib->icv_len;
343 } else {
344 /* no frag */
345 sz = pattrib->last_txcmdsz;
346 }
347
348 pull = update_txdesc(pxmitframe, mem_addr, sz, false);
349
350 if (pull) {
351 mem_addr += PACKET_OFFSET_SZ; /* pull txdesc head */
352
353 pxmitframe->buf_addr = mem_addr;
354
355 w_sz = sz + TXDESC_SIZE;
356 } else {
357 w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ;
358 }
359
360 ff_hwaddr = rtw_get_ff_hwaddr23a(pxmitframe);
361 inner_ret = rtw_write_port(padapter, ff_hwaddr, w_sz, pxmitbuf);
362 rtw_count_tx_stats23a(padapter, pxmitframe, sz);
363
364 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
365 ("rtw_write_port, w_sz =%d\n", w_sz));
366
367 mem_addr += w_sz;
368
369 mem_addr = PTR_ALIGN(mem_addr, 4);
370 }
371
372 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
373
374 if (ret != _SUCCESS)
375 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);
376
377 return ret;
378}
379
380s32 rtl8723au_xmitframe_complete(struct rtw_adapter *padapter,
381 struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
382{
383 struct hw_xmit *phwxmits;
384 struct xmit_frame *pxmitframe;
385 int hwentry;
386 int res = _SUCCESS, xcnt = 0;
387
388 phwxmits = pxmitpriv->hwxmits;
389 hwentry = pxmitpriv->hwxmit_entry;
390
391 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("xmitframe_complete()\n"));
392
393 if (pxmitbuf == NULL) {
394 pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv);
395 if (!pxmitbuf)
396 return false;
397 }
398 pxmitframe = rtw_dequeue_xframe23a(pxmitpriv, phwxmits, hwentry);
399
400 if (pxmitframe) {
401 pxmitframe->pxmitbuf = pxmitbuf;
402
403 pxmitframe->buf_addr = pxmitbuf->pbuf;
404
405 pxmitbuf->priv_data = pxmitframe;
406
407 if ((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) {
408 if (pxmitframe->attrib.priority <= 15)/* TID0~15 */
409 res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe);
410
411 rtw_os_xmit_complete23a(padapter, pxmitframe);/* always return ndis_packet after rtw_xmitframe_coalesce23a */
412 }
413
414 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("xmitframe_complete(): rtw_dump_xframe\n"));
415
416 if (res == _SUCCESS) {
417 rtw_dump_xframe(padapter, pxmitframe);
418 } else {
419 rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
420 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
421 }
422 xcnt++;
423 } else {
424 rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
425 return false;
426 }
427 return true;
428}
429
430static s32 xmitframe_direct(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
431{
432 s32 res = _SUCCESS;
433
434 res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe);
435 if (res == _SUCCESS)
436 rtw_dump_xframe(padapter, pxmitframe);
437 return res;
438}
439
440/*
441 * Return
442 * true dump packet directly
443 * false enqueue packet
444 */
445static s32 pre_xmitframe(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
446{
447 s32 res;
448 struct xmit_buf *pxmitbuf = NULL;
449 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
450 struct pkt_attrib *pattrib = &pxmitframe->attrib;
451 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
452
453 do_queue_select(padapter, pattrib);
454 spin_lock_bh(&pxmitpriv->lock);
455
456#ifdef CONFIG_8723AU_AP_MODE
457 if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) {
458 struct sta_info *psta;
459 struct sta_priv *pstapriv = &padapter->stapriv;
460
461 spin_unlock_bh(&pxmitpriv->lock);
462
463 if (pattrib->psta)
464 psta = pattrib->psta;
465 else
466 psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
467
468 if (psta) {
469 if (psta->sleepq_len > (NR_XMITFRAME>>3))
470 wakeup_sta_to_xmit23a(padapter, psta);
471 }
472
473 return false;
474 }
475#endif
476
477 if (rtw_txframes_sta_ac_pending23a(padapter, pattrib) > 0)
478 goto enqueue;
479
480 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true)
481 goto enqueue;
482
483 pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv);
484 if (pxmitbuf == NULL)
485 goto enqueue;
486
487 spin_unlock_bh(&pxmitpriv->lock);
488
489 pxmitframe->pxmitbuf = pxmitbuf;
490 pxmitframe->buf_addr = pxmitbuf->pbuf;
491 pxmitbuf->priv_data = pxmitframe;
492
493 if (xmitframe_direct(padapter, pxmitframe) != _SUCCESS) {
494 rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
495 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
496 }
497 return true;
498
499enqueue:
500 res = rtw_xmitframe_enqueue23a(padapter, pxmitframe);
501 spin_unlock_bh(&pxmitpriv->lock);
502
503 if (res != _SUCCESS) {
504 RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
505 ("pre_xmitframe: enqueue xmitframe fail\n"));
506 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
507
508 /* Trick, make the statistics correct */
509 pxmitpriv->tx_pkts--;
510 pxmitpriv->tx_drop++;
511 return true;
512 }
513 return false;
514}
515
516s32 rtl8723au_mgnt_xmit(struct rtw_adapter *padapter, struct xmit_frame *pmgntframe)
517{
518 return rtw_dump_xframe(padapter, pmgntframe);
519}
520
521/*
522 * Return
523 * true dump packet directly ok
524 * false temporary can't transmit packets to hardware
525 */
526s32 rtl8723au_hal_xmit(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
527{
528 return pre_xmitframe(padapter, pxmitframe);
529}
530
531s32 rtl8723au_hal_xmitframe_enqueue(struct rtw_adapter *padapter,
532 struct xmit_frame *pxmitframe)
533{
534 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
535 s32 err;
536
537 err = rtw_xmitframe_enqueue23a(padapter, pxmitframe);
538 if (err != _SUCCESS) {
539 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
540
541 /* Trick, make the statistics correct */
542 pxmitpriv->tx_pkts--;
543 pxmitpriv->tx_drop++;
544 } else {
545 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
546 }
547 return err;
548}
diff --git a/drivers/staging/rtl8723au/hal/usb_halinit.c b/drivers/staging/rtl8723au/hal/usb_halinit.c
new file mode 100644
index 000000000000..e206829d50fa
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/usb_halinit.c
@@ -0,0 +1,1834 @@
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 ******************************************************************************/
15#define _HCI_HAL_INIT_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <rtw_efuse.h>
20
21#include <HalPwrSeqCmd.h>
22#include <Hal8723PwrSeq.h>
23#include <rtl8723a_hal.h>
24#include <rtl8723a_led.h>
25#include <linux/ieee80211.h>
26
27#include <usb_ops.h>
28#include <usb_hal.h>
29#include <usb_osintf.h>
30
31static void
32_ConfigChipOutEP(struct rtw_adapter *pAdapter, u8 NumOutPipe)
33{
34 u8 value8;
35 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
36
37 pHalData->OutEpQueueSel = 0;
38 pHalData->OutEpNumber = 0;
39
40 /* Normal and High queue */
41 value8 = rtw_read8(pAdapter, (REG_NORMAL_SIE_EP + 1));
42
43 if (value8 & USB_NORMAL_SIE_EP_MASK) {
44 pHalData->OutEpQueueSel |= TX_SELE_HQ;
45 pHalData->OutEpNumber++;
46 }
47
48 if ((value8 >> USB_NORMAL_SIE_EP_SHIFT) & USB_NORMAL_SIE_EP_MASK) {
49 pHalData->OutEpQueueSel |= TX_SELE_NQ;
50 pHalData->OutEpNumber++;
51 }
52
53 /* Low queue */
54 value8 = rtw_read8(pAdapter, (REG_NORMAL_SIE_EP + 2));
55 if (value8 & USB_NORMAL_SIE_EP_MASK) {
56 pHalData->OutEpQueueSel |= TX_SELE_LQ;
57 pHalData->OutEpNumber++;
58 }
59
60 /* TODO: Error recovery for this case */
61 /* RT_ASSERT((NumOutPipe == pHalData->OutEpNumber),
62 ("Out EP number isn't match! %d(Descriptor) != %d (SIE reg)\n",
63 (u32)NumOutPipe, (u32)pHalData->OutEpNumber)); */
64}
65
66static bool rtl8723au_set_queue_pipe_mapping(struct rtw_adapter *pAdapter,
67 u8 NumInPipe, u8 NumOutPipe)
68{
69 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
70 bool result = false;
71
72 _ConfigChipOutEP(pAdapter, NumOutPipe);
73
74 /* Normal chip with one IN and one OUT doesn't have interrupt IN EP. */
75 if (pHalData->OutEpNumber == 1) {
76 if (NumInPipe != 1)
77 return result;
78 }
79
80 result = Hal_MappingOutPipe23a(pAdapter, NumOutPipe);
81
82 return result;
83}
84
85static void rtl8723au_interface_configure(struct rtw_adapter *padapter)
86{
87 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
88 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
89
90 if (pdvobjpriv->ishighspeed == true) {
91 /* 512 bytes */
92 pHalData->UsbBulkOutSize = USB_HIGH_SPEED_BULK_SIZE;
93 } else {
94 /* 64 bytes */
95 pHalData->UsbBulkOutSize = USB_FULL_SPEED_BULK_SIZE;
96 }
97
98 pHalData->interfaceIndex = pdvobjpriv->InterfaceNumber;
99
100 rtl8723au_set_queue_pipe_mapping(padapter,
101 pdvobjpriv->RtNumInPipes,
102 pdvobjpriv->RtNumOutPipes);
103}
104
105static u8 _InitPowerOn(struct rtw_adapter *padapter)
106{
107 u8 status = _SUCCESS;
108 u16 value16 = 0;
109 u8 value8 = 0;
110
111 /* RSV_CTRL 0x1C[7:0] = 0x00
112 unlock ISO/CLK/Power control register */
113 rtw_write8(padapter, REG_RSV_CTRL, 0x0);
114
115 /* HW Power on sequence */
116 if (!HalPwrSeqCmdParsing23a(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
117 PWR_INTF_USB_MSK, rtl8723AU_card_enable_flow))
118 return _FAIL;
119
120 /* 0x04[19] = 1, suggest by Jackie 2011.05.09, reset 8051 */
121 value8 = rtw_read8(padapter, REG_APS_FSMCO+2);
122 rtw_write8(padapter, REG_APS_FSMCO + 2, (value8 | BIT3));
123
124 /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */
125 /* Set CR bit10 to enable 32k calibration. Suggested by SD1 Gimmy.
126 Added by tynli. 2011.08.31. */
127 value16 = rtw_read16(padapter, REG_CR);
128 value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN |
129 PROTOCOL_EN | SCHEDULE_EN | MACTXEN | MACRXEN |
130 ENSEC | CALTMR_EN);
131 rtw_write16(padapter, REG_CR, value16);
132
133 /* for Efuse PG, suggest by Jackie 2011.11.23 */
134 PHY_SetBBReg(padapter, REG_EFUSE_CTRL, BIT28|BIT29|BIT30, 0x06);
135
136 return status;
137}
138
139/* Shall USB interface init this? */
140static void _InitInterrupt(struct rtw_adapter *Adapter)
141{
142 u32 value32;
143
144 /* HISR - turn all on */
145 value32 = 0xFFFFFFFF;
146 rtw_write32(Adapter, REG_HISR, value32);
147
148 /* HIMR - turn all on */
149 rtw_write32(Adapter, REG_HIMR, value32);
150}
151
152static void _InitQueueReservedPage(struct rtw_adapter *Adapter)
153{
154 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
155 struct registry_priv *pregistrypriv = &Adapter->registrypriv;
156 u32 numHQ = 0;
157 u32 numLQ = 0;
158 u32 numNQ = 0;
159 u32 numPubQ;
160 u32 value32;
161 u8 value8;
162 bool bWiFiConfig = pregistrypriv->wifi_spec;
163 /* u32 txQPageNum, txQPageUnit, txQRemainPage; */
164
165 { /* for WMM */
166 /* RT_ASSERT((outEPNum>= 2), ("for WMM , number of out-ep "
167 "must more than or equal to 2!\n")); */
168
169 numPubQ = bWiFiConfig ?
170 WMM_NORMAL_PAGE_NUM_PUBQ : NORMAL_PAGE_NUM_PUBQ;
171
172 if (pHalData->OutEpQueueSel & TX_SELE_HQ) {
173 numHQ = bWiFiConfig ?
174 WMM_NORMAL_PAGE_NUM_HPQ : NORMAL_PAGE_NUM_HPQ;
175 }
176
177 if (pHalData->OutEpQueueSel & TX_SELE_LQ) {
178 numLQ = bWiFiConfig ?
179 WMM_NORMAL_PAGE_NUM_LPQ : NORMAL_PAGE_NUM_LPQ;
180 }
181 /* NOTE: This step shall be proceed before
182 writting REG_RQPN. */
183 if (pHalData->OutEpQueueSel & TX_SELE_NQ) {
184 numNQ = bWiFiConfig ?
185 WMM_NORMAL_PAGE_NUM_NPQ : NORMAL_PAGE_NUM_NPQ;
186 }
187 value8 = (u8)_NPQ(numNQ);
188 rtw_write8(Adapter, REG_RQPN_NPQ, value8);
189 }
190
191 /* TX DMA */
192 value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN;
193 rtw_write32(Adapter, REG_RQPN, value32);
194}
195
196static void _InitTxBufferBoundary(struct rtw_adapter *Adapter)
197{
198 struct registry_priv *pregistrypriv = &Adapter->registrypriv;
199
200 u8 txpktbuf_bndy;
201
202 if (!pregistrypriv->wifi_spec)
203 txpktbuf_bndy = TX_PAGE_BOUNDARY;
204 else /* for WMM */
205 txpktbuf_bndy = WMM_NORMAL_TX_PAGE_BOUNDARY;
206
207 rtw_write8(Adapter, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
208 rtw_write8(Adapter, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
209 rtw_write8(Adapter, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy);
210 rtw_write8(Adapter, REG_TRXFF_BNDY, txpktbuf_bndy);
211 rtw_write8(Adapter, REG_TDECTRL+1, txpktbuf_bndy);
212}
213
214static void _InitPageBoundary(struct rtw_adapter *Adapter)
215{
216 /* RX Page Boundary */
217 /* srand(static_cast<unsigned int>(time(NULL))); */
218 u16 rxff_bndy = 0x27FF;/* rand() % 1) ? 0x27FF : 0x23FF; */
219
220 rtw_write16(Adapter, (REG_TRXFF_BNDY + 2), rxff_bndy);
221
222 /* TODO: ?? shall we set tx boundary? */
223}
224
225static void
226_InitNormalChipRegPriority(struct rtw_adapter *Adapter, u16 beQ, u16 bkQ,
227 u16 viQ, u16 voQ, u16 mgtQ, u16 hiQ)
228{
229 u16 value16 = rtw_read16(Adapter, REG_TRXDMA_CTRL) & 0x7;
230
231 value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) |
232 _TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) |
233 _TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ);
234
235 rtw_write16(Adapter, REG_TRXDMA_CTRL, value16);
236}
237
238static void _InitNormalChipOneOutEpPriority(struct rtw_adapter *Adapter)
239{
240 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
241 u16 value = 0;
242
243 switch (pHalData->OutEpQueueSel) {
244 case TX_SELE_HQ:
245 value = QUEUE_HIGH;
246 break;
247 case TX_SELE_LQ:
248 value = QUEUE_LOW;
249 break;
250 case TX_SELE_NQ:
251 value = QUEUE_NORMAL;
252 break;
253 default:
254 /* RT_ASSERT(false, ("Shall not reach here!\n")); */
255 break;
256 }
257
258 _InitNormalChipRegPriority(Adapter, value, value, value,
259 value, value, value);
260}
261
262static void _InitNormalChipTwoOutEpPriority(struct rtw_adapter *Adapter)
263{
264 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
265 struct registry_priv *pregistrypriv = &Adapter->registrypriv;
266 u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
267 u16 valueHi = 0;
268 u16 valueLow = 0;
269
270 switch (pHalData->OutEpQueueSel) {
271 case (TX_SELE_HQ | TX_SELE_LQ):
272 valueHi = QUEUE_HIGH;
273 valueLow = QUEUE_LOW;
274 break;
275 case (TX_SELE_NQ | TX_SELE_LQ):
276 valueHi = QUEUE_NORMAL;
277 valueLow = QUEUE_LOW;
278 break;
279 case (TX_SELE_HQ | TX_SELE_NQ):
280 valueHi = QUEUE_HIGH;
281 valueLow = QUEUE_NORMAL;
282 break;
283 default:
284 /* RT_ASSERT(false, ("Shall not reach here!\n")); */
285 break;
286 }
287
288 if (!pregistrypriv->wifi_spec) {
289 beQ = valueLow;
290 bkQ = valueLow;
291 viQ = valueHi;
292 voQ = valueHi;
293 mgtQ = valueHi;
294 hiQ = valueHi;
295 } else {/* for WMM , CONFIG_OUT_EP_WIFI_MODE */
296 beQ = valueLow;
297 bkQ = valueHi;
298 viQ = valueHi;
299 voQ = valueLow;
300 mgtQ = valueHi;
301 hiQ = valueHi;
302 }
303
304 _InitNormalChipRegPriority(Adapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
305}
306
307static void _InitNormalChipThreeOutEpPriority(struct rtw_adapter *Adapter)
308{
309 struct registry_priv *pregistrypriv = &Adapter->registrypriv;
310 u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
311
312 if (!pregistrypriv->wifi_spec) {/* typical setting */
313 beQ = QUEUE_LOW;
314 bkQ = QUEUE_LOW;
315 viQ = QUEUE_NORMAL;
316 voQ = QUEUE_HIGH;
317 mgtQ = QUEUE_HIGH;
318 hiQ = QUEUE_HIGH;
319 } else {/* for WMM */
320 beQ = QUEUE_LOW;
321 bkQ = QUEUE_NORMAL;
322 viQ = QUEUE_NORMAL;
323 voQ = QUEUE_HIGH;
324 mgtQ = QUEUE_HIGH;
325 hiQ = QUEUE_HIGH;
326 }
327 _InitNormalChipRegPriority(Adapter, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
328}
329
330static void _InitNormalChipQueuePriority(struct rtw_adapter *Adapter)
331{
332 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
333
334 switch (pHalData->OutEpNumber) {
335 case 1:
336 _InitNormalChipOneOutEpPriority(Adapter);
337 break;
338 case 2:
339 _InitNormalChipTwoOutEpPriority(Adapter);
340 break;
341 case 3:
342 _InitNormalChipThreeOutEpPriority(Adapter);
343 break;
344 default:
345 /* RT_ASSERT(false, ("Shall not reach here!\n")); */
346 break;
347 }
348}
349
350static void _InitQueuePriority(struct rtw_adapter *Adapter)
351{
352 _InitNormalChipQueuePriority(Adapter);
353}
354
355static void _InitNetworkType(struct rtw_adapter *Adapter)
356{
357 u32 value32;
358
359 value32 = rtw_read32(Adapter, REG_CR);
360
361 /* TODO: use the other function to set network type */
362 value32 = (value32 & ~MASK_NETTYPE) | _NETTYPE(NT_LINK_AP);
363 rtw_write32(Adapter, REG_CR, value32);
364}
365
366static void _InitTransferPageSize(struct rtw_adapter *Adapter)
367{
368 /* Tx page size is always 128. */
369
370 u8 value8;
371 value8 = _PSRX(PBP_128) | _PSTX(PBP_128);
372 rtw_write8(Adapter, REG_PBP, value8);
373}
374
375static void _InitDriverInfoSize(struct rtw_adapter *Adapter, u8 drvInfoSize)
376{
377 rtw_write8(Adapter, REG_RX_DRVINFO_SZ, drvInfoSize);
378}
379
380static void _InitWMACSetting(struct rtw_adapter *Adapter)
381{
382 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
383
384 /* don't turn on AAP, it will allow all packets to driver */
385 pHalData->ReceiveConfig = RCR_APM | RCR_AM | RCR_AB | RCR_CBSSID_DATA |
386 RCR_CBSSID_BCN | RCR_APP_ICV | RCR_AMF |
387 RCR_HTC_LOC_CTRL | RCR_APP_MIC |
388 RCR_APP_PHYSTS;
389
390 /* some REG_RCR will be modified later by
391 phy_ConfigMACWithHeaderFile() */
392 rtw_write32(Adapter, REG_RCR, pHalData->ReceiveConfig);
393
394 /* Accept all multicast address */
395 rtw_write32(Adapter, REG_MAR, 0xFFFFFFFF);
396 rtw_write32(Adapter, REG_MAR + 4, 0xFFFFFFFF);
397
398 /* Accept all data frames */
399 /* value16 = 0xFFFF; */
400 /* rtw_write16(Adapter, REG_RXFLTMAP2, value16); */
401
402 /* 2010.09.08 hpfan */
403 /* Since ADF is removed from RCR, ps-poll will not be indicate
404 to driver, */
405 /* RxFilterMap should mask ps-poll to gurantee AP mode can
406 rx ps-poll. */
407 /* value16 = 0x400; */
408 /* rtw_write16(Adapter, REG_RXFLTMAP1, value16); */
409
410 /* Accept all management frames */
411 /* value16 = 0xFFFF; */
412 /* rtw_write16(Adapter, REG_RXFLTMAP0, value16); */
413
414 /* enable RX_SHIFT bits */
415 /* rtw_write8(Adapter, REG_TRXDMA_CTRL, rtw_read8(Adapter,
416 REG_TRXDMA_CTRL)|BIT(1)); */
417}
418
419static void _InitAdaptiveCtrl(struct rtw_adapter *Adapter)
420{
421 u16 value16;
422 u32 value32;
423
424 /* Response Rate Set */
425 value32 = rtw_read32(Adapter, REG_RRSR);
426 value32 &= ~RATE_BITMAP_ALL;
427 value32 |= RATE_RRSR_CCK_ONLY_1M;
428 rtw_write32(Adapter, REG_RRSR, value32);
429
430 /* CF-END Threshold */
431 /* m_spIoBase->rtw_write8(REG_CFEND_TH, 0x1); */
432
433 /* SIFS (used in NAV) */
434 value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10);
435 rtw_write16(Adapter, REG_SPEC_SIFS, value16);
436
437 /* Retry Limit */
438 value16 = _LRL(0x30) | _SRL(0x30);
439 rtw_write16(Adapter, REG_RL, value16);
440}
441
442static void _InitRateFallback(struct rtw_adapter *Adapter)
443{
444 /* Set Data Auto Rate Fallback Retry Count register. */
445 rtw_write32(Adapter, REG_DARFRC, 0x00000000);
446 rtw_write32(Adapter, REG_DARFRC+4, 0x10080404);
447 rtw_write32(Adapter, REG_RARFRC, 0x04030201);
448 rtw_write32(Adapter, REG_RARFRC+4, 0x08070605);
449}
450
451static void _InitEDCA(struct rtw_adapter *Adapter)
452{
453 /* Set Spec SIFS (used in NAV) */
454 rtw_write16(Adapter, REG_SPEC_SIFS, 0x100a);
455 rtw_write16(Adapter, REG_MAC_SPEC_SIFS, 0x100a);
456
457 /* Set SIFS for CCK */
458 rtw_write16(Adapter, REG_SIFS_CTX, 0x100a);
459
460 /* Set SIFS for OFDM */
461 rtw_write16(Adapter, REG_SIFS_TRX, 0x100a);
462
463 /* TXOP */
464 rtw_write32(Adapter, REG_EDCA_BE_PARAM, 0x005EA42B);
465 rtw_write32(Adapter, REG_EDCA_BK_PARAM, 0x0000A44F);
466 rtw_write32(Adapter, REG_EDCA_VI_PARAM, 0x005EA324);
467 rtw_write32(Adapter, REG_EDCA_VO_PARAM, 0x002FA226);
468}
469
470static void _InitHWLed(struct rtw_adapter *Adapter)
471{
472 struct led_priv *pledpriv = &Adapter->ledpriv;
473
474 if (pledpriv->LedStrategy != HW_LED)
475 return;
476
477/* HW led control */
478/* to do .... */
479/* must consider cases of antenna diversity/ commbo card/solo card/mini card */
480}
481
482static void _InitRDGSetting(struct rtw_adapter *Adapter)
483{
484 rtw_write8(Adapter, REG_RD_CTRL, 0xFF);
485 rtw_write16(Adapter, REG_RD_NAV_NXT, 0x200);
486 rtw_write8(Adapter, REG_RD_RESP_PKT_TH, 0x05);
487}
488
489static void _InitRetryFunction(struct rtw_adapter *Adapter)
490{
491 u8 value8;
492
493 value8 = rtw_read8(Adapter, REG_FWHW_TXQ_CTRL);
494 value8 |= EN_AMPDU_RTY_NEW;
495 rtw_write8(Adapter, REG_FWHW_TXQ_CTRL, value8);
496
497 /* Set ACK timeout */
498 rtw_write8(Adapter, REG_ACKTO, 0x40);
499}
500
501/*-----------------------------------------------------------------------------
502 * Function: usb_AggSettingTxUpdate()
503 *
504 * Overview: Seperate TX/RX parameters update independent for TP
505 * detection and dynamic TX/RX aggreagtion parameters update.
506 *
507 * Input: struct rtw_adapter *
508 *
509 * Output/Return: NONE
510 *
511 * Revised History:
512 * When Who Remark
513 * 12/10/2010 MHC Seperate to smaller function.
514 *
515 *---------------------------------------------------------------------------*/
516static void usb_AggSettingTxUpdate(struct rtw_adapter *Adapter)
517{
518} /* usb_AggSettingTxUpdate */
519
520/*-----------------------------------------------------------------------------
521 * Function: usb_AggSettingRxUpdate()
522 *
523 * Overview: Seperate TX/RX parameters update independent for TP
524 * detection and dynamic TX/RX aggreagtion parameters update.
525 *
526 * Input: struct rtw_adapter *
527 *
528 * Output/Return: NONE
529 *
530 * Revised History:
531 * When Who Remark
532 * 12/10/2010 MHC Seperate to smaller function.
533 *
534 *---------------------------------------------------------------------------*/
535static void usb_AggSettingRxUpdate(struct rtw_adapter *Adapter)
536{
537} /* usb_AggSettingRxUpdate */
538
539static void InitUsbAggregationSetting(struct rtw_adapter *Adapter)
540{
541 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
542
543 /* Tx aggregation setting */
544 usb_AggSettingTxUpdate(Adapter);
545
546 /* Rx aggregation setting */
547 usb_AggSettingRxUpdate(Adapter);
548
549 /* 201/12/10 MH Add for USB agg mode dynamic switch. */
550 pHalData->UsbRxHighSpeedMode = false;
551}
552
553static void _InitOperationMode(struct rtw_adapter *Adapter)
554{
555}
556
557static void _InitRFType(struct rtw_adapter *Adapter)
558{
559 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
560 bool is92CU = IS_92C_SERIAL(pHalData->VersionID);
561
562 pHalData->rf_chip = RF_6052;
563
564 if (is92CU == false) {
565 pHalData->rf_type = RF_1T1R;
566 DBG_8723A("Set RF Chip ID to RF_6052 and RF type to 1T1R.\n");
567 return;
568 }
569
570 /* TODO: Consider that EEPROM set 92CU to 1T1R later. */
571 /* Force to overwrite setting according to chip version. Ignore
572 EEPROM setting. */
573 /* pHalData->RF_Type = is92CU ? RF_2T2R : RF_1T1R; */
574 MSG_8723A("Set RF Chip ID to RF_6052 and RF type to %d.\n",
575 pHalData->rf_type);
576}
577
578/* Set CCK and OFDM Block "ON" */
579static void _BBTurnOnBlock(struct rtw_adapter *Adapter)
580{
581 PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bCCKEn, 0x1);
582 PHY_SetBBReg(Adapter, rFPGA0_RFMOD, bOFDMEn, 0x1);
583}
584
585#define MgntActSet_RF_State(...)
586static void _RfPowerSave(struct rtw_adapter *padapter)
587{
588}
589
590enum {
591 Antenna_Lfet = 1,
592 Antenna_Right = 2,
593};
594
595enum rt_rf_power_state RfOnOffDetect23a(struct rtw_adapter *pAdapter)
596{
597 /* struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter); */
598 u8 val8;
599 enum rt_rf_power_state rfpowerstate = rf_off;
600
601 if (pAdapter->pwrctrlpriv.bHWPowerdown) {
602 val8 = rtw_read8(pAdapter, REG_HSISR);
603 DBG_8723A("pwrdown, 0x5c(BIT7) =%02x\n", val8);
604 rfpowerstate = (val8 & BIT7) ? rf_off : rf_on;
605 } else { /* rf on/off */
606 rtw_write8(pAdapter, REG_MAC_PINMUX_CFG,
607 rtw_read8(pAdapter, REG_MAC_PINMUX_CFG) & ~BIT3);
608 val8 = rtw_read8(pAdapter, REG_GPIO_IO_SEL);
609 DBG_8723A("GPIO_IN =%02x\n", val8);
610 rfpowerstate = (val8 & BIT3) ? rf_on : rf_off;
611 }
612 return rfpowerstate;
613} /* HalDetectPwrDownMode */
614
615void _ps_open_RF23a(struct rtw_adapter *padapter);
616
617static u32 rtl8723au_hal_init(struct rtw_adapter *Adapter)
618{
619 u8 val8 = 0;
620 u32 boundary, status = _SUCCESS;
621 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
622 struct pwrctrl_priv *pwrctrlpriv = &Adapter->pwrctrlpriv;
623 struct registry_priv *pregistrypriv = &Adapter->registrypriv;
624 u32 NavUpper = WiFiNavUpperUs;
625
626 unsigned long init_start_time = jiffies;
627
628#define HAL_INIT_PROFILE_TAG(stage) do {} while (0)
629
630 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BEGIN);
631 if (Adapter->pwrctrlpriv.bkeepfwalive) {
632 _ps_open_RF23a(Adapter);
633
634 if (pHalData->bIQKInitialized) {
635 rtl8723a_phy_iq_calibrate(Adapter, true);
636 } else {
637 rtl8723a_phy_iq_calibrate(Adapter, false);
638 pHalData->bIQKInitialized = true;
639 }
640 rtl8723a_odm_check_tx_power_tracking(Adapter);
641 rtl8723a_phy_lc_calibrate(Adapter);
642
643 goto exit;
644 }
645
646 /* Check if MAC has already power on. by tynli. 2011.05.27. */
647 val8 = rtw_read8(Adapter, REG_CR);
648 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
649 ("%s: REG_CR 0x100 = 0x%02x\n", __func__, val8));
650 /* Fix 92DU-VC S3 hang with the reason is that secondary mac is not
651 initialized. */
652 /* 0x100 value of first mac is 0xEA while 0x100 value of secondary
653 is 0x00 */
654 if (val8 == 0xEA) {
655 pHalData->bMACFuncEnable = false;
656 } else {
657 pHalData->bMACFuncEnable = true;
658 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
659 ("%s: MAC has already power on\n", __func__));
660 }
661
662 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PW_ON);
663 status = _InitPowerOn(Adapter);
664 if (status == _FAIL) {
665 RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
666 ("Failed to init power on!\n"));
667 goto exit;
668 }
669
670 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_LLTT);
671 if (!pregistrypriv->wifi_spec) {
672 boundary = TX_PAGE_BOUNDARY;
673 } else {
674 /* for WMM */
675 boundary = WMM_NORMAL_TX_PAGE_BOUNDARY;
676 }
677
678 if (!pHalData->bMACFuncEnable) {
679 status = InitLLTTable23a(Adapter, boundary);
680 if (status == _FAIL) {
681 RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
682 ("Failed to init LLT table\n"));
683 goto exit;
684 }
685 }
686
687 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC01);
688 if (pHalData->bRDGEnable)
689 _InitRDGSetting(Adapter);
690
691 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_DOWNLOAD_FW);
692 status = rtl8723a_FirmwareDownload(Adapter);
693 if (status != _SUCCESS) {
694 Adapter->bFWReady = false;
695 pHalData->fw_ractrl = false;
696 DBG_8723A("fw download fail!\n");
697 goto exit;
698 } else {
699 Adapter->bFWReady = true;
700 pHalData->fw_ractrl = true;
701 DBG_8723A("fw download ok!\n");
702 }
703
704 rtl8723a_InitializeFirmwareVars(Adapter);
705
706 if (pwrctrlpriv->reg_rfoff == true) {
707 pwrctrlpriv->rf_pwrstate = rf_off;
708 }
709
710 /* 2010/08/09 MH We need to check if we need to turnon or off RF after detecting */
711 /* HW GPIO pin. Before PHY_RFConfig8192C. */
712 /* HalDetectPwrDownMode(Adapter); */
713 /* 2010/08/26 MH If Efuse does not support sective suspend then disable the function. */
714 /* HalDetectSelectiveSuspendMode(Adapter); */
715
716 /* Set RF type for BB/RF configuration */
717 _InitRFType(Adapter);/* _ReadRFType() */
718
719 /* Save target channel */
720 /* <Roger_Notes> Current Channel will be updated again later. */
721 pHalData->CurrentChannel = 6;/* default set to 6 */
722
723 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MAC);
724 status = PHY_MACConfig8723A(Adapter);
725 if (status == _FAIL) {
726 DBG_8723A("PHY_MACConfig8723A fault !!\n");
727 goto exit;
728 }
729
730 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BB);
731 /* */
732 /* d. Initialize BB related configurations. */
733 /* */
734 status = PHY_BBConfig8723A(Adapter);
735 if (status == _FAIL) {
736 DBG_8723A("PHY_BBConfig8723A fault !!\n");
737 goto exit;
738 }
739
740 /* Add for tx power by rate fine tune. We need to call the function after BB config. */
741 /* Because the tx power by rate table is inited in BB config. */
742
743 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_RF);
744 status = PHY_RFConfig8723A(Adapter);
745 if (status == _FAIL) {
746 DBG_8723A("PHY_RFConfig8723A fault !!\n");
747 goto exit;
748 }
749
750 /* reducing 80M spur */
751 PHY_SetBBReg(Adapter, RF_T_METER, bMaskDWord, 0x0381808d);
752 PHY_SetBBReg(Adapter, RF_SYN_G4, bMaskDWord, 0xf2ffff83);
753 PHY_SetBBReg(Adapter, RF_SYN_G4, bMaskDWord, 0xf2ffff82);
754 PHY_SetBBReg(Adapter, RF_SYN_G4, bMaskDWord, 0xf2ffff83);
755
756 /* RFSW Control */
757 PHY_SetBBReg(Adapter, rFPGA0_TxInfo, bMaskDWord, 0x00000003); /* 0x804[14]= 0 */
758 PHY_SetBBReg(Adapter, rFPGA0_XAB_RFInterfaceSW, bMaskDWord, 0x07000760); /* 0x870[6:5]= b'11 */
759 PHY_SetBBReg(Adapter, rFPGA0_XA_RFInterfaceOE, bMaskDWord, 0x66F60210); /* 0x860[6:5]= b'00 */
760
761 RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("%s: 0x870 = value 0x%x\n", __func__, PHY_QueryBBReg(Adapter, 0x870, bMaskDWord)));
762
763 /* */
764 /* Joseph Note: Keep RfRegChnlVal for later use. */
765 /* */
766 pHalData->RfRegChnlVal[0] = PHY_QueryRFReg(Adapter, (enum RF_RADIO_PATH)0, RF_CHNLBW, bRFRegOffsetMask);
767 pHalData->RfRegChnlVal[1] = PHY_QueryRFReg(Adapter, (enum RF_RADIO_PATH)1, RF_CHNLBW, bRFRegOffsetMask);
768
769 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC02);
770 if (!pHalData->bMACFuncEnable) {
771 _InitQueueReservedPage(Adapter);
772 _InitTxBufferBoundary(Adapter);
773 }
774 _InitQueuePriority(Adapter);
775 _InitPageBoundary(Adapter);
776 _InitTransferPageSize(Adapter);
777
778 /* Get Rx PHY status in order to report RSSI and others. */
779 _InitDriverInfoSize(Adapter, DRVINFO_SZ);
780
781 _InitInterrupt(Adapter);
782 hal_init_macaddr23a(Adapter);/* set mac_address */
783 _InitNetworkType(Adapter);/* set msr */
784 _InitWMACSetting(Adapter);
785 _InitAdaptiveCtrl(Adapter);
786 _InitEDCA(Adapter);
787 _InitRateFallback(Adapter);
788 _InitRetryFunction(Adapter);
789 InitUsbAggregationSetting(Adapter);
790 _InitOperationMode(Adapter);/* todo */
791 rtl8723a_InitBeaconParameters(Adapter);
792
793 _InitHWLed(Adapter);
794
795 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_TURN_ON_BLOCK);
796 _BBTurnOnBlock(Adapter);
797 /* NicIFSetMacAddress(padapter, padapter->PermanentAddress); */
798
799 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_SECURITY);
800 invalidate_cam_all23a(Adapter);
801
802 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC11);
803 /* 2010/12/17 MH We need to set TX power according to EFUSE content at first. */
804 PHY_SetTxPowerLevel8723A(Adapter, pHalData->CurrentChannel);
805
806 rtl8723a_InitAntenna_Selection(Adapter);
807
808 /* HW SEQ CTRL */
809 /* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */
810 rtw_write8(Adapter, REG_HWSEQ_CTRL, 0xFF);
811
812 /* */
813 /* Disable BAR, suggested by Scott */
814 /* 2010.04.09 add by hpfan */
815 /* */
816 rtw_write32(Adapter, REG_BAR_MODE_CTRL, 0x0201ffff);
817
818 if (pregistrypriv->wifi_spec)
819 rtw_write16(Adapter, REG_FAST_EDCA_CTRL, 0);
820
821 /* Move by Neo for USB SS from above setp */
822 _RfPowerSave(Adapter);
823
824 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_IQK);
825 /* 2010/08/26 MH Merge from 8192CE. */
826 /* sherry masked that it has been done in _RfPowerSave */
827 /* 20110927 */
828 /* recovery for 8192cu and 9723Au 20111017 */
829 if (pwrctrlpriv->rf_pwrstate == rf_on) {
830 if (pHalData->bIQKInitialized) {
831 rtl8723a_phy_iq_calibrate(Adapter, true);
832 } else {
833 rtl8723a_phy_iq_calibrate(Adapter, false);
834 pHalData->bIQKInitialized = true;
835 }
836
837 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_PW_TRACK);
838 rtl8723a_odm_check_tx_power_tracking(Adapter);
839
840 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_LCK);
841 rtl8723a_phy_lc_calibrate(Adapter);
842
843#ifdef CONFIG_8723AU_BT_COEXIST
844 rtl8723a_SingleDualAntennaDetection(Adapter);
845#endif
846 }
847
848 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC21);
849 /* fixed USB interface interference issue */
850 rtw_write8(Adapter, 0xfe40, 0xe0);
851 rtw_write8(Adapter, 0xfe41, 0x8d);
852 rtw_write8(Adapter, 0xfe42, 0x80);
853 rtw_write32(Adapter, 0x20c, 0xfd0320);
854 /* Solve too many protocol error on USB bus */
855 if (!IS_81xxC_VENDOR_UMC_A_CUT(pHalData->VersionID)) {
856 /* 0xE6 = 0x94 */
857 rtw_write8(Adapter, 0xFE40, 0xE6);
858 rtw_write8(Adapter, 0xFE41, 0x94);
859 rtw_write8(Adapter, 0xFE42, 0x80);
860
861 /* 0xE0 = 0x19 */
862 rtw_write8(Adapter, 0xFE40, 0xE0);
863 rtw_write8(Adapter, 0xFE41, 0x19);
864 rtw_write8(Adapter, 0xFE42, 0x80);
865
866 /* 0xE5 = 0x91 */
867 rtw_write8(Adapter, 0xFE40, 0xE5);
868 rtw_write8(Adapter, 0xFE41, 0x91);
869 rtw_write8(Adapter, 0xFE42, 0x80);
870
871 /* 0xE2 = 0x81 */
872 rtw_write8(Adapter, 0xFE40, 0xE2);
873 rtw_write8(Adapter, 0xFE41, 0x81);
874 rtw_write8(Adapter, 0xFE42, 0x80);
875
876 }
877
878/* HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_PABIAS); */
879/* _InitPABias(Adapter); */
880
881#ifdef CONFIG_8723AU_BT_COEXIST
882 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_BT_COEXIST);
883 /* Init BT hw config. */
884 BT_InitHwConfig(Adapter);
885#endif
886
887 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_INIT_HAL_DM);
888 rtl8723a_InitHalDm(Adapter);
889
890 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_MISC31);
891 rtw_hal_set_hwreg23a(Adapter, HW_VAR_NAV_UPPER, (u8 *)&NavUpper);
892
893 /* 2011/03/09 MH debug only, UMC-B cut pass 2500 S5 test, but we need to fin root cause. */
894 if (((rtw_read32(Adapter, rFPGA0_RFMOD) & 0xFF000000) != 0x83000000)) {
895 PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT(24), 1);
896 RT_TRACE(_module_hci_hal_init_c_, _drv_err_, ("%s: IQK fail recorver\n", __func__));
897 }
898
899 /* ack for xmit mgmt frames. */
900 rtw_write32(Adapter, REG_FWHW_TXQ_CTRL, rtw_read32(Adapter, REG_FWHW_TXQ_CTRL)|BIT(12));
901
902exit:
903 HAL_INIT_PROFILE_TAG(HAL_INIT_STAGES_END);
904
905 DBG_8723A("%s in %dms\n", __func__,
906 jiffies_to_msecs(jiffies - init_start_time));
907 return status;
908}
909
910static void phy_SsPwrSwitch92CU(struct rtw_adapter *Adapter,
911 enum rt_rf_power_state eRFPowerState,
912 int bRegSSPwrLvl)
913{
914 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
915 u8 value8;
916 u8 bytetmp;
917
918 switch (eRFPowerState) {
919 case rf_on:
920 if (bRegSSPwrLvl == 1) {
921 /* 1. Enable MAC Clock. Can not be enabled now. */
922 /* WriteXBYTE(REG_SYS_CLKR+1,
923 ReadXBYTE(REG_SYS_CLKR+1) | BIT(3)); */
924
925 /* 2. Force PWM, Enable SPS18_LDO_Marco_Block */
926 rtw_write8(Adapter, REG_SPS0_CTRL,
927 rtw_read8(Adapter, REG_SPS0_CTRL) |
928 (BIT0|BIT3));
929
930 /* 3. restore BB, AFE control register. */
931 /* RF */
932 if (pHalData->rf_type == RF_2T2R)
933 PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
934 0x380038, 1);
935 else
936 PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
937 0x38, 1);
938 PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf0, 1);
939 PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT1, 0);
940
941 /* AFE */
942 if (pHalData->rf_type == RF_2T2R)
943 PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
944 0x63DB25A0);
945 else if (pHalData->rf_type == RF_1T1R)
946 PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
947 0x631B25A0);
948
949 /* 4. issue 3-wire command that RF set to Rx idle
950 mode. This is used to re-write the RX idle mode. */
951 /* We can only prvide a usual value instead and then
952 HW will modify the value by itself. */
953 PHY_SetRFReg(Adapter, RF_PATH_A, 0,
954 bRFRegOffsetMask, 0x32D95);
955 if (pHalData->rf_type == RF_2T2R) {
956 PHY_SetRFReg(Adapter, RF_PATH_B, 0,
957 bRFRegOffsetMask, 0x32D95);
958 }
959 } else { /* Level 2 or others. */
960 /* h. AFE_PLL_CTRL 0x28[7:0] = 0x80
961 disable AFE PLL */
962 rtw_write8(Adapter, REG_AFE_PLL_CTRL, 0x81);
963
964 /* i. AFE_XTAL_CTRL 0x24[15:0] = 0x880F
965 gated AFE DIG_CLOCK */
966 rtw_write16(Adapter, REG_AFE_XTAL_CTRL, 0x800F);
967 mdelay(1);
968
969 /* 2. Force PWM, Enable SPS18_LDO_Marco_Block */
970 rtw_write8(Adapter, REG_SPS0_CTRL,
971 rtw_read8(Adapter, REG_SPS0_CTRL) |
972 (BIT0|BIT3));
973
974 /* 3. restore BB, AFE control register. */
975 /* RF */
976 if (pHalData->rf_type == RF_2T2R)
977 PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
978 0x380038, 1);
979 else
980 PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
981 0x38, 1);
982 PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf0, 1);
983 PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT1, 0);
984
985 /* AFE */
986 if (pHalData->rf_type == RF_2T2R)
987 PHY_SetBBReg(Adapter, rRx_Wait_CCA,
988 bMaskDWord, 0x63DB25A0);
989 else if (pHalData->rf_type == RF_1T1R)
990 PHY_SetBBReg(Adapter, rRx_Wait_CCA,
991 bMaskDWord, 0x631B25A0);
992
993 /* 4. issue 3-wire command that RF set to Rx idle
994 mode. This is used to re-write the RX idle mode. */
995 /* We can only prvide a usual value instead and
996 then HW will modify the value by itself. */
997 PHY_SetRFReg(Adapter, RF_PATH_A, 0,
998 bRFRegOffsetMask, 0x32D95);
999 if (pHalData->rf_type == RF_2T2R) {
1000 PHY_SetRFReg(Adapter, RF_PATH_B, 0,
1001 bRFRegOffsetMask, 0x32D95);
1002 }
1003
1004 /* 5. gated MAC Clock */
1005 bytetmp = rtw_read8(Adapter, REG_APSD_CTRL);
1006 rtw_write8(Adapter, REG_APSD_CTRL, bytetmp & ~BIT6);
1007
1008 mdelay(10);
1009
1010 /* Set BB reset at first */
1011 rtw_write8(Adapter, REG_SYS_FUNC_EN, 0x17); /* 0x16 */
1012
1013 /* Enable TX */
1014 rtw_write8(Adapter, REG_TXPAUSE, 0x0);
1015 }
1016 break;
1017 case rf_sleep:
1018 case rf_off:
1019 value8 = rtw_read8(Adapter, REG_SPS0_CTRL) ;
1020 if (IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID))
1021 value8 &= ~(BIT0);
1022 else
1023 value8 &= ~(BIT0|BIT3);
1024 if (bRegSSPwrLvl == 1) {
1025 RT_TRACE(_module_hal_init_c_, _drv_err_, ("SS LVL1\n"));
1026 /* Disable RF and BB only for SelectSuspend. */
1027
1028 /* 1. Set BB/RF to shutdown. */
1029 /* (1) Reg878[5:3]= 0 RF rx_code for
1030 preamble power saving */
1031 /* (2)Reg878[21:19]= 0 Turn off RF-B */
1032 /* (3) RegC04[7:4]= 0 Turn off all paths
1033 for packet detection */
1034 /* (4) Reg800[1] = 1 enable preamble power
1035 saving */
1036 Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF0] =
1037 PHY_QueryBBReg(Adapter, rFPGA0_XAB_RFParameter,
1038 bMaskDWord);
1039 Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF1] =
1040 PHY_QueryBBReg(Adapter, rOFDM0_TRxPathEnable,
1041 bMaskDWord);
1042 Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF2] =
1043 PHY_QueryBBReg(Adapter, rFPGA0_RFMOD,
1044 bMaskDWord);
1045 if (pHalData->rf_type == RF_2T2R) {
1046 PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
1047 0x380038, 0);
1048 } else if (pHalData->rf_type == RF_1T1R) {
1049 PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
1050 0x38, 0);
1051 }
1052 PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf0, 0);
1053 PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT1, 1);
1054
1055 /* 2 .AFE control register to power down. bit[30:22] */
1056 Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_AFE0] =
1057 PHY_QueryBBReg(Adapter, rRx_Wait_CCA,
1058 bMaskDWord);
1059 if (pHalData->rf_type == RF_2T2R)
1060 PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
1061 0x00DB25A0);
1062 else if (pHalData->rf_type == RF_1T1R)
1063 PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
1064 0x001B25A0);
1065
1066 /* 3. issue 3-wire command that RF set to power down.*/
1067 PHY_SetRFReg(Adapter, RF_PATH_A, 0, bRFRegOffsetMask, 0);
1068 if (pHalData->rf_type == RF_2T2R)
1069 PHY_SetRFReg(Adapter, RF_PATH_B, 0,
1070 bRFRegOffsetMask, 0);
1071
1072 /* 4. Force PFM , disable SPS18_LDO_Marco_Block */
1073 rtw_write8(Adapter, REG_SPS0_CTRL, value8);
1074 } else { /* Level 2 or others. */
1075 RT_TRACE(_module_hal_init_c_, _drv_err_, ("SS LVL2\n"));
1076 {
1077 u8 eRFPath = RF_PATH_A, value8 = 0;
1078 rtw_write8(Adapter, REG_TXPAUSE, 0xFF);
1079 PHY_SetRFReg(Adapter,
1080 (enum RF_RADIO_PATH)eRFPath,
1081 0x0, bMaskByte0, 0x0);
1082 value8 |= APSDOFF;
1083 /* 0x40 */
1084 rtw_write8(Adapter, REG_APSD_CTRL, value8);
1085
1086 /* After switch APSD, we need to delay
1087 for stability */
1088 mdelay(10);
1089
1090 /* Set BB reset at first */
1091 value8 = 0 ;
1092 value8 |= (FEN_USBD | FEN_USBA |
1093 FEN_BB_GLB_RSTn);
1094 /* 0x16 */
1095 rtw_write8(Adapter, REG_SYS_FUNC_EN, value8);
1096 }
1097
1098 /* Disable RF and BB only for SelectSuspend. */
1099
1100 /* 1. Set BB/RF to shutdown. */
1101 /* (1) Reg878[5:3]= 0 RF rx_code for
1102 preamble power saving */
1103 /* (2)Reg878[21:19]= 0 Turn off RF-B */
1104 /* (3) RegC04[7:4]= 0 Turn off all paths for
1105 packet detection */
1106 /* (4) Reg800[1] = 1 enable preamble power
1107 saving */
1108 Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF0] =
1109 PHY_QueryBBReg(Adapter, rFPGA0_XAB_RFParameter,
1110 bMaskDWord);
1111 Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF1] =
1112 PHY_QueryBBReg(Adapter, rOFDM0_TRxPathEnable,
1113 bMaskDWord);
1114 Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_RF2] =
1115 PHY_QueryBBReg(Adapter, rFPGA0_RFMOD,
1116 bMaskDWord);
1117 if (pHalData->rf_type == RF_2T2R)
1118 PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
1119 0x380038, 0);
1120 else if (pHalData->rf_type == RF_1T1R)
1121 PHY_SetBBReg(Adapter, rFPGA0_XAB_RFParameter,
1122 0x38, 0);
1123 PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf0, 0);
1124 PHY_SetBBReg(Adapter, rFPGA0_RFMOD, BIT1, 1);
1125
1126 /* 2 .AFE control register to power down. bit[30:22] */
1127 Adapter->pwrctrlpriv.PS_BBRegBackup[PSBBREG_AFE0] =
1128 PHY_QueryBBReg(Adapter, rRx_Wait_CCA,
1129 bMaskDWord);
1130 if (pHalData->rf_type == RF_2T2R)
1131 PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
1132 0x00DB25A0);
1133 else if (pHalData->rf_type == RF_1T1R)
1134 PHY_SetBBReg(Adapter, rRx_Wait_CCA, bMaskDWord,
1135 0x001B25A0);
1136
1137 /* 3. issue 3-wire command that RF set to power down. */
1138 PHY_SetRFReg(Adapter, RF_PATH_A, 0, bRFRegOffsetMask, 0);
1139 if (pHalData->rf_type == RF_2T2R)
1140 PHY_SetRFReg(Adapter, RF_PATH_B, 0,
1141 bRFRegOffsetMask, 0);
1142
1143 /* 4. Force PFM , disable SPS18_LDO_Marco_Block */
1144 rtw_write8(Adapter, REG_SPS0_CTRL, value8);
1145
1146 /* 2010/10/13 MH/Isaachsu exchange sequence. */
1147 /* h. AFE_PLL_CTRL 0x28[7:0] = 0x80
1148 disable AFE PLL */
1149 rtw_write8(Adapter, REG_AFE_PLL_CTRL, 0x80);
1150 mdelay(1);
1151
1152 /* i. AFE_XTAL_CTRL 0x24[15:0] = 0x880F
1153 gated AFE DIG_CLOCK */
1154 rtw_write16(Adapter, REG_AFE_XTAL_CTRL, 0xA80F);
1155 }
1156 break;
1157 default:
1158 break;
1159 }
1160
1161} /* phy_PowerSwitch92CU */
1162
1163void _ps_open_RF23a(struct rtw_adapter *padapter)
1164{
1165 /* here call with bRegSSPwrLvl 1, bRegSSPwrLvl 2 needs to be verified */
1166 phy_SsPwrSwitch92CU(padapter, rf_on, 1);
1167}
1168
1169static void CardDisableRTL8723U(struct rtw_adapter *Adapter)
1170{
1171 u8 u1bTmp;
1172
1173 DBG_8723A("CardDisableRTL8723U\n");
1174 /* USB-MF Card Disable Flow */
1175 /* 1. Run LPS WL RFOFF flow */
1176 HalPwrSeqCmdParsing23a(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
1177 PWR_INTF_USB_MSK, rtl8723AU_enter_lps_flow);
1178
1179 /* 2. 0x1F[7:0] = 0 turn off RF */
1180 rtw_write8(Adapter, REG_RF_CTRL, 0x00);
1181
1182 /* ==== Reset digital sequence ====== */
1183 if ((rtw_read8(Adapter, REG_MCUFWDL)&BIT7) &&
1184 Adapter->bFWReady) /* 8051 RAM code */
1185 rtl8723a_FirmwareSelfReset(Adapter);
1186
1187 /* Reset MCU. Suggested by Filen. 2011.01.26. by tynli. */
1188 u1bTmp = rtw_read8(Adapter, REG_SYS_FUNC_EN+1);
1189 rtw_write8(Adapter, REG_SYS_FUNC_EN+1, (u1bTmp & (~BIT2)));
1190
1191 /* g. MCUFWDL 0x80[1:0]= 0 reset MCU ready status */
1192 rtw_write8(Adapter, REG_MCUFWDL, 0x00);
1193
1194 /* ==== Reset digital sequence end ====== */
1195 /* Card disable power action flow */
1196 HalPwrSeqCmdParsing23a(Adapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK,
1197 PWR_INTF_USB_MSK,
1198 rtl8723AU_card_disable_flow);
1199
1200 /* Reset MCU IO Wrapper, added by Roger, 2011.08.30. */
1201 u1bTmp = rtw_read8(Adapter, REG_RSV_CTRL + 1);
1202 rtw_write8(Adapter, REG_RSV_CTRL+1, (u1bTmp & (~BIT0)));
1203 u1bTmp = rtw_read8(Adapter, REG_RSV_CTRL + 1);
1204 rtw_write8(Adapter, REG_RSV_CTRL+1, u1bTmp | BIT0);
1205
1206 /* 7. RSV_CTRL 0x1C[7:0] = 0x0E lock ISO/CLK/Power control register */
1207 rtw_write8(Adapter, REG_RSV_CTRL, 0x0e);
1208}
1209
1210static u32 rtl8723au_hal_deinit(struct rtw_adapter *padapter)
1211{
1212 DBG_8723A("==> %s\n", __func__);
1213
1214#ifdef CONFIG_8723AU_BT_COEXIST
1215 BT_HaltProcess(padapter);
1216#endif
1217 /* 2011/02/18 To Fix RU LNA power leakage problem. We need to
1218 execute below below in Adapter init and halt sequence.
1219 According to EEchou's opinion, we can enable the ability for all */
1220 /* IC. Accord to johnny's opinion, only RU need the support. */
1221 CardDisableRTL8723U(padapter);
1222
1223 return _SUCCESS;
1224}
1225
1226static unsigned int rtl8723au_inirp_init(struct rtw_adapter *Adapter)
1227{
1228 u8 i;
1229 struct recv_buf *precvbuf;
1230 uint status;
1231 struct intf_hdl *pintfhdl = &Adapter->iopriv.intf;
1232 struct recv_priv *precvpriv = &Adapter->recvpriv;
1233 u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
1234 struct recv_buf *rbuf);
1235 u32 (*_read_interrupt)(struct intf_hdl *pintfhdl, u32 addr);
1236 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1237
1238 _read_port = pintfhdl->io_ops._read_port;
1239
1240 status = _SUCCESS;
1241
1242 RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("===> usb_inirp_init\n"));
1243
1244 precvpriv->ff_hwaddr = RECV_BULK_IN_ADDR;
1245
1246 /* issue Rx irp to receive data */
1247 precvbuf = (struct recv_buf *)precvpriv->precv_buf;
1248 for (i = 0; i < NR_RECVBUFF; i++) {
1249 if (_read_port(pintfhdl, precvpriv->ff_hwaddr, 0, precvbuf) ==
1250 false) {
1251 RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
1252 ("usb_rx_init: usb_read_port error\n"));
1253 status = _FAIL;
1254 goto exit;
1255 }
1256 precvbuf++;
1257 precvpriv->free_recv_buf_queue_cnt--;
1258 }
1259 _read_interrupt = pintfhdl->io_ops._read_interrupt;
1260 if (_read_interrupt(pintfhdl, RECV_INT_IN_ADDR) == false) {
1261 RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
1262 ("usb_rx_init: usb_read_interrupt error\n"));
1263 status = _FAIL;
1264 }
1265 pHalData->IntrMask[0] = rtw_read32(Adapter, REG_USB_HIMR);
1266 MSG_8723A("pHalData->IntrMask = 0x%04x\n", pHalData->IntrMask[0]);
1267 pHalData->IntrMask[0] |= UHIMR_C2HCMD|UHIMR_CPWM;
1268 rtw_write32(Adapter, REG_USB_HIMR, pHalData->IntrMask[0]);
1269exit:
1270 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
1271 ("<=== usb_inirp_init\n"));
1272 return status;
1273}
1274
1275static unsigned int rtl8723au_inirp_deinit(struct rtw_adapter *Adapter)
1276{
1277 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1278
1279 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
1280 ("\n ===> usb_rx_deinit\n"));
1281 rtw_read_port_cancel(Adapter);
1282 pHalData->IntrMask[0] = rtw_read32(Adapter, REG_USB_HIMR);
1283 MSG_8723A("%s pHalData->IntrMask = 0x%04x\n", __func__,
1284 pHalData->IntrMask[0]);
1285 pHalData->IntrMask[0] = 0x0;
1286 rtw_write32(Adapter, REG_USB_HIMR, pHalData->IntrMask[0]);
1287 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
1288 ("\n <=== usb_rx_deinit\n"));
1289 return _SUCCESS;
1290}
1291
1292static void _ReadBoardType(struct rtw_adapter *Adapter, u8 *PROMContent,
1293 bool AutoloadFail)
1294{
1295 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1296 u8 boardType = BOARD_USB_DONGLE;
1297
1298 if (AutoloadFail) {
1299 if (IS_8723_SERIES(pHalData->VersionID))
1300 pHalData->rf_type = RF_1T1R;
1301 else
1302 pHalData->rf_type = RF_2T2R;
1303 pHalData->BoardType = boardType;
1304 return;
1305 }
1306
1307 boardType = PROMContent[EEPROM_NORMAL_BoardType];
1308 boardType &= BOARD_TYPE_NORMAL_MASK;/* bit[7:5] */
1309 boardType >>= 5;
1310
1311 pHalData->BoardType = boardType;
1312 MSG_8723A("_ReadBoardType(%x)\n", pHalData->BoardType);
1313
1314 if (boardType == BOARD_USB_High_PA)
1315 pHalData->ExternalPA = 1;
1316}
1317
1318static void _ReadLEDSetting(struct rtw_adapter *Adapter, u8 *PROMContent,
1319 bool AutoloadFail)
1320{
1321 struct led_priv *pledpriv = &Adapter->ledpriv;
1322
1323 pledpriv->LedStrategy = HW_LED;
1324}
1325
1326static void Hal_EfuseParsePIDVID_8723AU(struct rtw_adapter *pAdapter,
1327 u8 *hwinfo, bool AutoLoadFail)
1328{
1329 struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
1330
1331 if (AutoLoadFail) {
1332 pHalData->EEPROMVID = 0;
1333 pHalData->EEPROMPID = 0;
1334 } else {
1335 /* VID, PID */
1336 pHalData->EEPROMVID =
1337 le16_to_cpu(*(u16 *)&hwinfo[EEPROM_VID_8723AU]);
1338 pHalData->EEPROMPID =
1339 le16_to_cpu(*(u16 *)&hwinfo[EEPROM_PID_8723AU]);
1340 }
1341
1342 MSG_8723A("EEPROM VID = 0x%4x\n", pHalData->EEPROMVID);
1343 MSG_8723A("EEPROM PID = 0x%4x\n", pHalData->EEPROMPID);
1344}
1345
1346static void Hal_EfuseParseMACAddr_8723AU(struct rtw_adapter *padapter,
1347 u8 *hwinfo, bool AutoLoadFail)
1348{
1349 u16 i;
1350 u8 sMacAddr[ETH_ALEN] = {0x00, 0xE0, 0x4C, 0x87, 0x23, 0x00};
1351 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
1352
1353 if (AutoLoadFail) {
1354 for (i = 0; i < 6; i++)
1355 pEEPROM->mac_addr[i] = sMacAddr[i];
1356 } else {
1357 /* Read Permanent MAC address */
1358 memcpy(pEEPROM->mac_addr, &hwinfo[EEPROM_MAC_ADDR_8723AU],
1359 ETH_ALEN);
1360 }
1361
1362 RT_TRACE(_module_hci_hal_init_c_, _drv_notice_,
1363 ("Hal_EfuseParseMACAddr_8723AU: Permanent Address =%02x:%02x:"
1364 "%02x:%02x:%02x:%02x\n",
1365 pEEPROM->mac_addr[0], pEEPROM->mac_addr[1],
1366 pEEPROM->mac_addr[2], pEEPROM->mac_addr[3],
1367 pEEPROM->mac_addr[4], pEEPROM->mac_addr[5]));
1368}
1369
1370static void readAdapterInfo(struct rtw_adapter *padapter)
1371{
1372 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
1373 /* struct hal_data_8723a * pHalData = GET_HAL_DATA(padapter); */
1374 u8 hwinfo[HWSET_MAX_SIZE];
1375
1376 Hal_InitPGData(padapter, hwinfo);
1377 Hal_EfuseParseIDCode(padapter, hwinfo);
1378 Hal_EfuseParsePIDVID_8723AU(padapter, hwinfo,
1379 pEEPROM->bautoload_fail_flag);
1380 Hal_EfuseParseEEPROMVer(padapter, hwinfo,
1381 pEEPROM->bautoload_fail_flag);
1382 Hal_EfuseParseMACAddr_8723AU(padapter, hwinfo,
1383 pEEPROM->bautoload_fail_flag);
1384 Hal_EfuseParsetxpowerinfo_8723A(padapter, hwinfo,
1385 pEEPROM->bautoload_fail_flag);
1386 _ReadBoardType(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
1387 Hal_EfuseParseBTCoexistInfo_8723A(padapter, hwinfo,
1388 pEEPROM->bautoload_fail_flag);
1389
1390 rtl8723a_EfuseParseChnlPlan(padapter, hwinfo,
1391 pEEPROM->bautoload_fail_flag);
1392 Hal_EfuseParseThermalMeter_8723A(padapter, hwinfo,
1393 pEEPROM->bautoload_fail_flag);
1394 _ReadLEDSetting(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
1395/* _ReadRFSetting(Adapter, PROMContent, pEEPROM->bautoload_fail_flag); */
1396/* _ReadPSSetting(Adapter, PROMContent, pEEPROM->bautoload_fail_flag); */
1397 Hal_EfuseParseAntennaDiversity(padapter, hwinfo,
1398 pEEPROM->bautoload_fail_flag);
1399
1400 Hal_EfuseParseEEPROMVer(padapter, hwinfo, pEEPROM->bautoload_fail_flag);
1401 Hal_EfuseParseCustomerID(padapter, hwinfo,
1402 pEEPROM->bautoload_fail_flag);
1403 Hal_EfuseParseRateIndicationOption(padapter, hwinfo,
1404 pEEPROM->bautoload_fail_flag);
1405 Hal_EfuseParseXtal_8723A(padapter, hwinfo,
1406 pEEPROM->bautoload_fail_flag);
1407 /* */
1408 /* The following part initialize some vars by PG info. */
1409 /* */
1410 Hal_InitChannelPlan23a(padapter);
1411
1412 /* hal_CustomizedBehavior_8723U(Adapter); */
1413
1414/* Adapter->bDongle = (PROMContent[EEPROM_EASY_REPLACEMENT] == 1)? 0: 1; */
1415 DBG_8723A("%s(): REPLACEMENT = %x\n", __func__, padapter->bDongle);
1416}
1417
1418static void _ReadPROMContent(struct rtw_adapter *Adapter)
1419{
1420 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(Adapter);
1421 u8 eeValue;
1422
1423 eeValue = rtw_read8(Adapter, REG_9346CR);
1424 /* To check system boot selection. */
1425 pEEPROM->EepromOrEfuse = (eeValue & BOOT_FROM_EEPROM) ? true : false;
1426 pEEPROM->bautoload_fail_flag = (eeValue & EEPROM_EN) ? false : true;
1427
1428 DBG_8723A("Boot from %s, Autoload %s !\n",
1429 (pEEPROM->EepromOrEfuse ? "EEPROM" : "EFUSE"),
1430 (pEEPROM->bautoload_fail_flag ? "Fail" : "OK"));
1431
1432 readAdapterInfo(Adapter);
1433}
1434
1435static void _ReadRFType(struct rtw_adapter *Adapter)
1436{
1437 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1438
1439 pHalData->rf_chip = RF_6052;
1440}
1441
1442static void _ReadSilmComboMode(struct rtw_adapter *Adapter)
1443{
1444 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1445
1446 pHalData->SlimComboDbg = false; /* Default is not debug mode. */
1447}
1448
1449/* */
1450/* Description: */
1451/* We should set Efuse cell selection to WiFi cell in default. */
1452/* */
1453/* Assumption: */
1454/* PASSIVE_LEVEL */
1455/* */
1456/* Added by Roger, 2010.11.23. */
1457/* */
1458static void hal_EfuseCellSel(struct rtw_adapter *Adapter)
1459{
1460 u32 value32;
1461
1462 value32 = rtw_read32(Adapter, EFUSE_TEST);
1463 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
1464 rtw_write32(Adapter, EFUSE_TEST, value32);
1465}
1466
1467static int _ReadAdapterInfo8723AU(struct rtw_adapter *Adapter)
1468{
1469 /* struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); */
1470 unsigned long start = jiffies;
1471
1472 MSG_8723A("====> _ReadAdapterInfo8723AU\n");
1473
1474 hal_EfuseCellSel(Adapter);
1475
1476 _ReadRFType(Adapter);/* rf_chip -> _InitRFType() */
1477 _ReadPROMContent(Adapter);
1478
1479 /* 2010/10/25 MH THe function must be called after
1480 borad_type & IC-Version recognize. */
1481 _ReadSilmComboMode(Adapter);
1482
1483 /* MSG_8723A("%s()(done), rf_chip = 0x%x, rf_type = 0x%x\n",
1484 __func__, pHalData->rf_chip, pHalData->rf_type); */
1485
1486 MSG_8723A("<==== _ReadAdapterInfo8723AU in %d ms\n",
1487 jiffies_to_msecs(jiffies - start));
1488
1489 return _SUCCESS;
1490}
1491
1492static void ReadAdapterInfo8723AU(struct rtw_adapter *Adapter)
1493{
1494 /* Read EEPROM size before call any EEPROM function */
1495 Adapter->EepromAddressSize = GetEEPROMSize8723A(Adapter);
1496
1497 _ReadAdapterInfo8723AU(Adapter);
1498}
1499
1500#define GPIO_DEBUG_PORT_NUM 0
1501static void rtl8723au_trigger_gpio_0(struct rtw_adapter *padapter)
1502{
1503 u32 gpioctrl;
1504 DBG_8723A("==> trigger_gpio_0...\n");
1505 rtw_write16_async(padapter, REG_GPIO_PIN_CTRL, 0);
1506 rtw_write8_async(padapter, REG_GPIO_PIN_CTRL+2, 0xFF);
1507 gpioctrl = (BIT(GPIO_DEBUG_PORT_NUM) << 24)|
1508 (BIT(GPIO_DEBUG_PORT_NUM) << 16);
1509 rtw_write32_async(padapter, REG_GPIO_PIN_CTRL, gpioctrl);
1510 gpioctrl |= (BIT(GPIO_DEBUG_PORT_NUM)<<8);
1511 rtw_write32_async(padapter, REG_GPIO_PIN_CTRL, gpioctrl);
1512 DBG_8723A("<=== trigger_gpio_0...\n");
1513}
1514
1515/*
1516 * If variable not handled here,
1517 * some variables will be processed in SetHwReg8723A()
1518 */
1519static void SetHwReg8723AU(struct rtw_adapter *Adapter, u8 variable, u8 *val)
1520{
1521 switch (variable) {
1522 case HW_VAR_RXDMA_AGG_PG_TH:
1523 break;
1524 case HW_VAR_SET_RPWM:
1525 rtl8723a_set_rpwm(Adapter, *val);
1526 break;
1527 case HW_VAR_TRIGGER_GPIO_0:
1528 rtl8723au_trigger_gpio_0(Adapter);
1529 break;
1530 default:
1531 SetHwReg8723A(Adapter, variable, val);
1532 break;
1533 }
1534
1535}
1536
1537/*
1538 * If variable not handled here,
1539 * some variables will be processed in GetHwReg8723A()
1540 */
1541static void GetHwReg8723AU(struct rtw_adapter *Adapter, u8 variable, u8 *val)
1542{
1543 GetHwReg8723A(Adapter, variable, val);
1544}
1545
1546/* */
1547/* Description: */
1548/* Query setting of specified variable. */
1549/* */
1550static u8 GetHalDefVar8192CUsb(struct rtw_adapter *Adapter,
1551 enum hal_def_variable eVariable, void *pValue)
1552{
1553 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1554 u8 bResult = _SUCCESS;
1555
1556 switch (eVariable) {
1557 case HAL_DEF_UNDERCORATEDSMOOTHEDPWDB:
1558 *((int *)pValue) = pHalData->dmpriv.UndecoratedSmoothedPWDB;
1559 break;
1560 case HAL_DEF_IS_SUPPORT_ANT_DIV:
1561 break;
1562 case HAL_DEF_CURRENT_ANTENNA:
1563 break;
1564 case HAL_DEF_DRVINFO_SZ:
1565 *((u32 *)pValue) = DRVINFO_SZ;
1566 break;
1567 case HAL_DEF_MAX_RECVBUF_SZ:
1568 *((u32 *)pValue) = MAX_RECVBUF_SZ;
1569 break;
1570 case HAL_DEF_RX_PACKET_OFFSET:
1571 *((u32 *)pValue) = RXDESC_SIZE + DRVINFO_SZ;
1572 break;
1573 case HAL_DEF_DBG_DUMP_RXPKT:
1574 *((u8 *)pValue) = pHalData->bDumpRxPkt;
1575 break;
1576 case HAL_DEF_DBG_DM_FUNC:
1577 *((u32 *)pValue) = pHalData->odmpriv.SupportAbility;
1578 break;
1579 case HW_VAR_MAX_RX_AMPDU_FACTOR:
1580 *((u32 *)pValue) = IEEE80211_HT_MAX_AMPDU_64K;
1581 break;
1582 case HW_DEF_ODM_DBG_FLAG:
1583 {
1584 struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
1585 printk("pDM_Odm->DebugComponents = 0x%llx\n",
1586 pDM_Odm->DebugComponents);
1587 }
1588 break;
1589 default:
1590 /* RT_TRACE(COMP_INIT, DBG_WARNING, ("GetHalDefVar8192CUsb(): "
1591 "Unkown variable: %d!\n", eVariable)); */
1592 bResult = _FAIL;
1593 break;
1594 }
1595
1596 return bResult;
1597}
1598
1599/* Change default setting of specified variable. */
1600static u8 SetHalDefVar8192CUsb(struct rtw_adapter *Adapter,
1601 enum hal_def_variable eVariable, void *pValue)
1602{
1603 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
1604 u8 bResult = _SUCCESS;
1605
1606 switch (eVariable) {
1607 case HAL_DEF_DBG_DUMP_RXPKT:
1608 pHalData->bDumpRxPkt = *((u8 *)pValue);
1609 break;
1610 case HAL_DEF_DBG_DM_FUNC:
1611 {
1612 u8 dm_func = *((u8 *)pValue);
1613 struct dm_priv *pdmpriv = &pHalData->dmpriv;
1614 struct dm_odm_t *podmpriv = &pHalData->odmpriv;
1615
1616 if (dm_func == 0) { /* disable all dynamic func */
1617 podmpriv->SupportAbility = DYNAMIC_FUNC_DISABLE;
1618 DBG_8723A("==> Disable all dynamic function...\n");
1619 } else if (dm_func == 1) {/* disable DIG */
1620 podmpriv->SupportAbility &= (~DYNAMIC_BB_DIG);
1621 DBG_8723A("==> Disable DIG...\n");
1622 } else if (dm_func == 2) {/* disable High power */
1623 podmpriv->SupportAbility &= (~DYNAMIC_BB_DYNAMIC_TXPWR);
1624 } else if (dm_func == 3) {/* disable tx power tracking */
1625 podmpriv->SupportAbility &= (~DYNAMIC_RF_CALIBRATION);
1626 DBG_8723A("==> Disable tx power tracking...\n");
1627 } else if (dm_func == 4) {/* disable BT coexistence */
1628 pdmpriv->DMFlag &= (~DYNAMIC_FUNC_BT);
1629 } else if (dm_func == 5) {/* disable antenna diversity */
1630 podmpriv->SupportAbility &= (~DYNAMIC_BB_ANT_DIV);
1631 } else if (dm_func == 6) {/* turn on all dynamic func */
1632 if (!(podmpriv->SupportAbility & DYNAMIC_BB_DIG)) {
1633 struct dig_t *pDigTable =
1634 &podmpriv->DM_DigTable;
1635 pDigTable->CurIGValue = rtw_read8(Adapter, 0xc50);
1636 }
1637 pdmpriv->DMFlag |= DYNAMIC_FUNC_BT;
1638 podmpriv->SupportAbility = DYNAMIC_ALL_FUNC_ENABLE;
1639 DBG_8723A("==> Turn on all dynamic function...\n");
1640 }
1641 }
1642 break;
1643 case HW_DEF_FA_CNT_DUMP:
1644 {
1645 u8 bRSSIDump = *((u8 *)pValue);
1646 struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
1647 if (bRSSIDump)
1648 pDM_Odm->DebugComponents = ODM_COMP_DIG|ODM_COMP_FA_CNT;
1649 else
1650 pDM_Odm->DebugComponents = 0;
1651 }
1652 break;
1653 case HW_DEF_ODM_DBG_FLAG:
1654 {
1655 u64 DebugComponents = *((u64 *)pValue);
1656 struct dm_odm_t *pDM_Odm = &pHalData->odmpriv;
1657 pDM_Odm->DebugComponents = DebugComponents;
1658 }
1659 break;
1660 default:
1661 /* RT_TRACE(COMP_INIT, DBG_TRACE, ("SetHalDefVar819xUsb(): "
1662 "Unkown variable: %d!\n", eVariable)); */
1663 bResult = _FAIL;
1664 break;
1665 }
1666
1667 return bResult;
1668}
1669
1670static void UpdateHalRAMask8192CUsb(struct rtw_adapter *padapter,
1671 u32 mac_id, u8 rssi_level)
1672{
1673 u8 init_rate = 0;
1674 u8 networkType, raid;
1675 u32 mask, rate_bitmap;
1676 u8 shortGIrate = false;
1677 int supportRateNum = 0;
1678 struct sta_info *psta;
1679 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1680 struct dm_priv *pdmpriv = &pHalData->dmpriv;
1681 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1682 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1683 struct wlan_bssid_ex *cur_network = &pmlmeinfo->network;
1684
1685 if (mac_id >= NUM_STA) /* CAM_SIZE */
1686 return;
1687
1688 psta = pmlmeinfo->FW_sta_info[mac_id].psta;
1689 if (psta == NULL)
1690 return;
1691
1692 switch (mac_id) {
1693 case 0:/* for infra mode */
1694 supportRateNum =
1695 rtw_get_rateset_len23a(cur_network->SupportedRates);
1696 networkType = judge_network_type23a(padapter,
1697 cur_network->SupportedRates,
1698 supportRateNum) & 0xf;
1699 /* pmlmeext->cur_wireless_mode = networkType; */
1700 raid = networktype_to_raid23a(networkType);
1701
1702 mask = update_supported_rate23a(cur_network->SupportedRates,
1703 supportRateNum);
1704 mask |= (pmlmeinfo->HT_enable) ?
1705 update_MSC_rate23a(&pmlmeinfo->HT_caps) : 0;
1706
1707 if (support_short_GI23a(padapter, &pmlmeinfo->HT_caps))
1708 shortGIrate = true;
1709 break;
1710
1711 case 1:/* for broadcast/multicast */
1712 supportRateNum = rtw_get_rateset_len23a(
1713 pmlmeinfo->FW_sta_info[mac_id].SupportedRates);
1714 if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
1715 networkType = WIRELESS_11B;
1716 else
1717 networkType = WIRELESS_11G;
1718 raid = networktype_to_raid23a(networkType);
1719
1720 mask = update_basic_rate23a(cur_network->SupportedRates,
1721 supportRateNum);
1722 break;
1723
1724 default: /* for each sta in IBSS */
1725 supportRateNum = rtw_get_rateset_len23a(
1726 pmlmeinfo->FW_sta_info[mac_id].SupportedRates);
1727 networkType = judge_network_type23a(padapter,
1728 pmlmeinfo->FW_sta_info[mac_id].SupportedRates,
1729 supportRateNum) & 0xf;
1730 /* pmlmeext->cur_wireless_mode = networkType; */
1731 raid = networktype_to_raid23a(networkType);
1732
1733 mask = update_supported_rate23a(cur_network->SupportedRates,
1734 supportRateNum);
1735
1736 /* todo: support HT in IBSS */
1737 break;
1738 }
1739
1740 /* mask &= 0x0fffffff; */
1741 rate_bitmap = 0x0fffffff;
1742 rate_bitmap = ODM_Get_Rate_Bitmap23a(&pHalData->odmpriv,
1743 mac_id, mask, rssi_level);
1744 printk(KERN_DEBUG "%s => mac_id:%d, networkType:0x%02x, "
1745 "mask:0x%08x\n\t ==> rssi_level:%d, rate_bitmap:0x%08x\n",
1746 __func__,
1747 mac_id, networkType, mask, rssi_level, rate_bitmap);
1748
1749 mask &= rate_bitmap;
1750 mask |= ((raid<<28)&0xf0000000);
1751
1752 init_rate = get_highest_rate_idx23a(mask)&0x3f;
1753
1754 if (pHalData->fw_ractrl == true) {
1755 u8 arg = 0;
1756
1757 /* arg = (cam_idx-4)&0x1f;MACID */
1758 arg = mac_id&0x1f;/* MACID */
1759
1760 arg |= BIT(7);
1761
1762 if (shortGIrate == true)
1763 arg |= BIT(5);
1764
1765 DBG_8723A("update raid entry, mask = 0x%x, arg = 0x%x\n",
1766 mask, arg);
1767
1768 rtl8723a_set_raid_cmd(padapter, mask, arg);
1769 } else {
1770 if (shortGIrate == true)
1771 init_rate |= BIT(6);
1772
1773 rtw_write8(padapter, (REG_INIDATA_RATE_SEL+mac_id), init_rate);
1774 }
1775
1776 /* set ra_id */
1777 psta->raid = raid;
1778 psta->init_rate = init_rate;
1779
1780 /* set correct initial date rate for each mac_id */
1781 pdmpriv->INIDATA_RATE[mac_id] = init_rate;
1782}
1783
1784static void rtl8723au_init_default_value(struct rtw_adapter *padapter)
1785{
1786 rtl8723a_init_default_value(padapter);
1787}
1788
1789static u8 rtl8192cu_ps_func(struct rtw_adapter *Adapter,
1790 enum hal_intf_ps_func efunc_id, u8 *val)
1791{
1792 return true;
1793}
1794
1795int rtl8723au_set_hal_ops(struct rtw_adapter *padapter)
1796{
1797 struct hal_ops *pHalFunc = &padapter->HalFunc;
1798
1799 padapter->HalData = kzalloc(sizeof(struct hal_data_8723a), GFP_KERNEL);
1800 if (!padapter->HalData) {
1801 DBG_8723A("cannot alloc memory for HAL DATA\n");
1802 return -ENOMEM;
1803 }
1804 padapter->hal_data_sz = sizeof(struct hal_data_8723a);
1805
1806 pHalFunc->hal_init = &rtl8723au_hal_init;
1807 pHalFunc->hal_deinit = &rtl8723au_hal_deinit;
1808
1809 pHalFunc->inirp_init = &rtl8723au_inirp_init;
1810 pHalFunc->inirp_deinit = &rtl8723au_inirp_deinit;
1811
1812 pHalFunc->init_xmit_priv = &rtl8723au_init_xmit_priv;
1813 pHalFunc->free_xmit_priv = &rtl8723au_free_xmit_priv;
1814
1815 pHalFunc->init_recv_priv = &rtl8723au_init_recv_priv;
1816 pHalFunc->free_recv_priv = &rtl8723au_free_recv_priv;
1817 pHalFunc->InitSwLeds = NULL;
1818 pHalFunc->DeInitSwLeds = NULL;
1819
1820 pHalFunc->init_default_value = &rtl8723au_init_default_value;
1821 pHalFunc->intf_chip_configure = &rtl8723au_interface_configure;
1822 pHalFunc->read_adapter_info = &ReadAdapterInfo8723AU;
1823 pHalFunc->SetHwRegHandler = &SetHwReg8723AU;
1824 pHalFunc->GetHwRegHandler = &GetHwReg8723AU;
1825 pHalFunc->GetHalDefVarHandler = &GetHalDefVar8192CUsb;
1826 pHalFunc->SetHalDefVarHandler = &SetHalDefVar8192CUsb;
1827 pHalFunc->UpdateRAMaskHandler = &UpdateHalRAMask8192CUsb;
1828 pHalFunc->hal_xmit = &rtl8723au_hal_xmit;
1829 pHalFunc->mgnt_xmit = &rtl8723au_mgnt_xmit;
1830 pHalFunc->hal_xmitframe_enqueue = &rtl8723au_hal_xmitframe_enqueue;
1831 pHalFunc->interface_ps_func = &rtl8192cu_ps_func;
1832 rtl8723a_set_hal_ops(pHalFunc);
1833 return 0;
1834}
diff --git a/drivers/staging/rtl8723au/hal/usb_ops_linux.c b/drivers/staging/rtl8723au/hal/usb_ops_linux.c
new file mode 100644
index 000000000000..0311cdf77ff1
--- /dev/null
+++ b/drivers/staging/rtl8723au/hal/usb_ops_linux.c
@@ -0,0 +1,848 @@
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 ******************************************************************************/
15#define _HCI_OPS_OS_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <osdep_intf.h>
20#include <usb_ops.h>
21#include <recv_osdep.h>
22#include <rtl8723a_hal.h>
23#include <rtl8723a_recv.h>
24
25static int usbctrl_vendorreq(struct intf_hdl *pintfhdl, u8 request, u16 value, u16 index, void *pdata, u16 len, u8 requesttype)
26{
27 struct rtw_adapter *padapter = pintfhdl->padapter ;
28 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
29 struct usb_device *udev = pdvobjpriv->pusbdev;
30
31 unsigned int pipe;
32 int status = 0;
33 u8 reqtype;
34 u8 *pIo_buf;
35 int vendorreq_times = 0;
36
37 if ((padapter->bSurpriseRemoved) || (padapter->pwrctrlpriv.pnp_bstop_trx)) {
38 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
39 ("usbctrl_vendorreq:(padapter->bSurpriseRemoved||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
40 status = -EPERM;
41 goto exit;
42 }
43
44 if (len > MAX_VENDOR_REQ_CMD_SIZE) {
45 DBG_8723A("[%s] Buffer len error , vendor request failed\n", __FUNCTION__);
46 status = -EINVAL;
47 goto exit;
48 }
49
50 mutex_lock(&pdvobjpriv->usb_vendor_req_mutex);
51
52 /* Acquire IO memory for vendorreq */
53 pIo_buf = pdvobjpriv->usb_vendor_req_buf;
54
55 if (pIo_buf == NULL) {
56 DBG_8723A("[%s] pIo_buf == NULL \n", __FUNCTION__);
57 status = -ENOMEM;
58 goto release_mutex;
59 }
60
61 while (++vendorreq_times <= MAX_USBCTRL_VENDORREQ_TIMES) {
62 memset(pIo_buf, 0, len);
63
64 if (requesttype == 0x01) {
65 pipe = usb_rcvctrlpipe(udev, 0);/* read_in */
66 reqtype = REALTEK_USB_VENQT_READ;
67 } else {
68 pipe = usb_sndctrlpipe(udev, 0);/* write_out */
69 reqtype = REALTEK_USB_VENQT_WRITE;
70 memcpy(pIo_buf, pdata, len);
71 }
72
73 status = rtw_usb_control_msg(udev, pipe, request, reqtype,
74 value, index, pIo_buf, len,
75 RTW_USB_CONTROL_MSG_TIMEOUT);
76
77 if (status == len) { /* Success this control transfer. */
78 rtw_reset_continual_urb_error(pdvobjpriv);
79 if (requesttype == 0x01) {
80 /* For Control read transfer, we have to copy
81 * the read data from pIo_buf to pdata.
82 */
83 memcpy(pdata, pIo_buf, len);
84 }
85 } else { /* error cases */
86 DBG_8723A("reg 0x%x, usb %s %u fail, status:%d value ="
87 " 0x%x, vendorreq_times:%d\n",
88 value, (requesttype == 0x01) ? "read" : "write",
89 len, status, *(u32 *)pdata, vendorreq_times);
90
91 if (status < 0) {
92 if (status == (-ESHUTDOWN) || status == -ENODEV) {
93 padapter->bSurpriseRemoved = true;
94 } else {
95 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
96 pHalData->srestpriv.Wifi_Error_Status = USB_VEN_REQ_CMD_FAIL;
97 }
98 } else { /* status != len && status >= 0 */
99 if (status > 0) {
100 if (requesttype == 0x01) {
101 /* For Control read transfer, we have to copy
102 * the read data from pIo_buf to pdata.
103 */
104 memcpy(pdata, pIo_buf, len);
105 }
106 }
107 }
108
109 if (rtw_inc_and_chk_continual_urb_error(pdvobjpriv)) {
110 padapter->bSurpriseRemoved = true;
111 break;
112 }
113
114 }
115
116 /* firmware download is checksumed, don't retry */
117 if ((value >= FW_8723A_START_ADDRESS && value <= FW_8723A_END_ADDRESS) || status == len)
118 break;
119 }
120
121release_mutex:
122 mutex_unlock(&pdvobjpriv->usb_vendor_req_mutex);
123exit:
124 return status;
125}
126
127static u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
128{
129 u8 request;
130 u8 requesttype;
131 u16 wvalue;
132 u16 index;
133 u16 len;
134 u8 data = 0;
135
136 request = 0x05;
137 requesttype = 0x01;/* read_in */
138 index = 0;/* n/a */
139
140 wvalue = (u16)(addr&0x0000ffff);
141 len = 1;
142
143 usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
144
145 return data;
146}
147
148static u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
149{
150 u8 request;
151 u8 requesttype;
152 u16 wvalue;
153 u16 index;
154 u16 len;
155 u16 data = 0;
156
157 request = 0x05;
158 requesttype = 0x01;/* read_in */
159 index = 0;/* n/a */
160
161 wvalue = (u16)(addr&0x0000ffff);
162 len = 2;
163
164 usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
165
166 return data;
167}
168
169static u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
170{
171 u8 request;
172 u8 requesttype;
173 u16 wvalue;
174 u16 index;
175 u16 len;
176 u32 data = 0;
177
178 request = 0x05;
179 requesttype = 0x01;/* read_in */
180 index = 0;/* n/a */
181
182 wvalue = (u16)(addr&0x0000ffff);
183 len = 4;
184
185 usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
186
187 return data;
188}
189
190static int usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
191{
192 u8 request;
193 u8 requesttype;
194 u16 wvalue;
195 u16 index;
196 u16 len;
197 u8 data;
198 int ret;
199
200 request = 0x05;
201 requesttype = 0x00;/* write_out */
202 index = 0;/* n/a */
203
204 wvalue = (u16)(addr&0x0000ffff);
205 len = 1;
206
207 data = val;
208
209 ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
210
211 return ret;
212}
213
214static int usb_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
215{
216 u8 request;
217 u8 requesttype;
218 u16 wvalue;
219 u16 index;
220 u16 len;
221 u16 data;
222 int ret;
223
224 request = 0x05;
225 requesttype = 0x00;/* write_out */
226 index = 0;/* n/a */
227
228 wvalue = (u16)(addr&0x0000ffff);
229 len = 2;
230
231 data = val;
232
233 ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
234 return ret;
235}
236
237static int usb_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
238{
239 u8 request;
240 u8 requesttype;
241 u16 wvalue;
242 u16 index;
243 u16 len;
244 u32 data;
245 int ret;
246
247 request = 0x05;
248 requesttype = 0x00;/* write_out */
249 index = 0;/* n/a */
250
251 wvalue = (u16)(addr&0x0000ffff);
252 len = 4;
253 data = val;
254
255 ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, &data, len, requesttype);
256
257 return ret;
258}
259
260static int usb_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata)
261{
262 u8 request;
263 u8 requesttype;
264 u16 wvalue;
265 u16 index;
266 u16 len;
267 u8 buf[VENDOR_CMD_MAX_DATA_LEN] = {0};
268 int ret;
269
270 request = 0x05;
271 requesttype = 0x00;/* write_out */
272 index = 0;/* n/a */
273
274 wvalue = (u16)(addr&0x0000ffff);
275 len = length;
276 memcpy(buf, pdata, len);
277
278 ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, buf, len, requesttype);
279
280 return ret;
281}
282
283/*
284 * Description:
285 * Recognize the interrupt content by reading the interrupt
286 * register or content and masking interrupt mask (IMR)
287 * if it is our NIC's interrupt. After recognizing, we may clear
288 * the all interrupts (ISR).
289 * Arguments:
290 * [in] Adapter -
291 * The adapter context.
292 * [in] pContent -
293 * Under PCI interface, this field is ignord.
294 * Under USB interface, the content is the interrupt
295 * content pointer.
296 * Under SDIO interface, this is the interrupt type which
297 * is Local interrupt or system interrupt.
298 * [in] ContentLen -
299 * The length in byte of pContent.
300 * Return:
301 * If any interrupt matches the mask (IMR), return true, and
302 * return false otherwise.
303 */
304static bool
305InterruptRecognized8723AU(struct rtw_adapter *Adapter, void *pContent,
306 u32 ContentLen)
307{
308 struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
309 u8 *buffer = (u8 *)pContent;
310 struct reportpwrstate_parm report;
311
312 memcpy(&pHalData->IntArray[0], &buffer[USB_INTR_CONTENT_HISR_OFFSET],
313 4);
314 pHalData->IntArray[0] &= pHalData->IntrMask[0];
315
316 /* For HISR extension. Added by tynli. 2009.10.07. */
317 memcpy(&pHalData->IntArray[1],
318 &buffer[USB_INTR_CONTENT_HISRE_OFFSET], 4);
319 pHalData->IntArray[1] &= pHalData->IntrMask[1];
320
321 /* We sholud remove this function later because DDK suggest
322 * not to executing too many operations in MPISR */
323
324 memcpy(&report.state, &buffer[USB_INTR_CPWM_OFFSET], 1);
325
326 return ((pHalData->IntArray[0])&pHalData->IntrMask[0]) != 0 ||
327 ((pHalData->IntArray[1])&pHalData->IntrMask[1]) != 0;
328}
329
330static void usb_read_interrupt_complete(struct urb *purb, struct pt_regs *regs)
331{
332 int err;
333 struct rtw_adapter *padapter = (struct rtw_adapter *)purb->context;
334
335 if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
336 padapter->bReadPortCancel) {
337 DBG_8723A("%s() RX Warning! bDriverStopped(%d) OR "
338 "bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
339 __FUNCTION__, padapter->bDriverStopped,
340 padapter->bSurpriseRemoved,
341 padapter->bReadPortCancel);
342 return;
343 }
344
345 if (purb->status == 0) {
346 struct c2h_evt_hdr *c2h_evt;
347
348 c2h_evt = (struct c2h_evt_hdr *)purb->transfer_buffer;
349
350 if (purb->actual_length > USB_INTR_CONTENT_LENGTH) {
351 DBG_8723A("usb_read_interrupt_complete: purb->actual_"
352 "length > USB_INTR_CONTENT_LENGTH\n");
353 goto urb_submit;
354 }
355
356 InterruptRecognized8723AU(padapter, purb->transfer_buffer,
357 purb->actual_length);
358
359 if (c2h_evt_exist(c2h_evt)) {
360 if (c2h_id_filter_ccx_8723a(c2h_evt->id)) {
361 /* Handle CCX report here */
362 handle_txrpt_ccx_8723a(padapter, (void *)(c2h_evt->payload));
363 /* Replace with special pointer to
364 trigger c2h_evt_clear23a */
365 if (rtw_cbuf_push23a(padapter->evtpriv.c2h_queue,
366 (void *)&padapter->evtpriv) !=
367 _SUCCESS)
368 DBG_8723A("%s rtw_cbuf_push23a fail\n",
369 __func__);
370 schedule_work(&padapter->evtpriv.c2h_wk);
371 } else if ((c2h_evt = (struct c2h_evt_hdr *)
372 kmalloc(16, GFP_ATOMIC))) {
373 memcpy(c2h_evt, purb->transfer_buffer, 16);
374 if (rtw_cbuf_push23a(padapter->evtpriv.c2h_queue,
375 (void *)c2h_evt) != _SUCCESS)
376 DBG_8723A("%s rtw_cbuf_push23a fail\n",
377 __func__);
378 schedule_work(&padapter->evtpriv.c2h_wk);
379 } else {
380 /* Error handling for malloc fail */
381 if (rtw_cbuf_push23a(padapter->evtpriv.c2h_queue,
382 (void *)NULL) != _SUCCESS)
383 DBG_8723A("%s rtw_cbuf_push23a fail\n",
384 __func__);
385 schedule_work(&padapter->evtpriv.c2h_wk);
386 }
387 }
388
389urb_submit:
390 err = usb_submit_urb(purb, GFP_ATOMIC);
391 if (err && (err != -EPERM)) {
392 DBG_8723A("cannot submit interrupt in-token(err = "
393 "0x%08x), urb_status = %d\n",
394 err, purb->status);
395 }
396 } else {
397 DBG_8723A("###=> usb_read_interrupt_complete => urb "
398 "status(%d)\n", purb->status);
399
400 switch (purb->status) {
401 case -EINVAL:
402 case -EPIPE:
403 case -ENODEV:
404 case -ESHUTDOWN:
405 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
406 ("usb_read_port_complete:bSurpriseRemoved ="
407 "true\n"));
408 /* Fall Through here */
409 case -ENOENT:
410 padapter->bDriverStopped = true;
411 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
412 ("usb_read_port_complete:bDriverStopped ="
413 "true\n"));
414 break;
415 case -EPROTO:
416 break;
417 case -EINPROGRESS:
418 DBG_8723A("ERROR: URB IS IN PROGRESS!/n");
419 break;
420 default:
421 break;
422 }
423 }
424}
425
426static u32 usb_read_interrupt(struct intf_hdl *pintfhdl, u32 addr)
427{
428 int err;
429 unsigned int pipe;
430 u32 ret = _SUCCESS;
431 struct rtw_adapter *adapter = pintfhdl->padapter;
432 struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);
433 struct recv_priv *precvpriv = &adapter->recvpriv;
434 struct usb_device *pusbd = pdvobj->pusbdev;
435
436 /* translate DMA FIFO addr to pipehandle */
437 pipe = ffaddr2pipehdl23a(pdvobj, addr);
438
439 usb_fill_int_urb(precvpriv->int_in_urb, pusbd, pipe,
440 precvpriv->int_in_buf, USB_INTR_CONTENT_LENGTH,
441 usb_read_interrupt_complete, adapter, 1);
442
443 err = usb_submit_urb(precvpriv->int_in_urb, GFP_ATOMIC);
444 if (err && (err != -EPERM)) {
445 DBG_8723A("cannot submit interrupt in-token(err = 0x%08x),"
446 "urb_status = %d\n", err,
447 precvpriv->int_in_urb->status);
448 ret = _FAIL;
449 }
450
451 return ret;
452}
453
454static int recvbuf2recvframe(struct rtw_adapter *padapter, struct sk_buff *pskb)
455{
456 u8 *pbuf;
457 u8 shift_sz = 0;
458 u16 pkt_cnt;
459 u32 pkt_offset, skb_len, alloc_sz;
460 s32 transfer_len;
461 struct recv_stat *prxstat;
462 struct phy_stat *pphy_info = NULL;
463 struct sk_buff *pkt_copy = NULL;
464 struct recv_frame *precvframe = NULL;
465 struct rx_pkt_attrib *pattrib = NULL;
466 struct recv_priv *precvpriv = &padapter->recvpriv;
467 struct rtw_queue *pfree_recv_queue = &precvpriv->free_recv_queue;
468
469 transfer_len = (s32)pskb->len;
470 pbuf = pskb->data;
471
472 prxstat = (struct recv_stat *)pbuf;
473 pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
474
475 do {
476 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
477 ("recvbuf2recvframe: rxdesc = offsset 0:0x%08x, "
478 "4:0x%08x, 8:0x%08x, C:0x%08x\n", prxstat->rxdw0,
479 prxstat->rxdw1, prxstat->rxdw2, prxstat->rxdw4));
480
481 prxstat = (struct recv_stat *)pbuf;
482
483 precvframe = rtw_alloc_recvframe23a(pfree_recv_queue);
484 if (!precvframe) {
485 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
486 ("recvbuf2recvframe: precvframe == NULL\n"));
487 DBG_8723A("%s()-%d: rtw_alloc_recvframe23a() failed! RX "
488 "Drop!\n", __FUNCTION__, __LINE__);
489 goto _exit_recvbuf2recvframe;
490 }
491
492 INIT_LIST_HEAD(&precvframe->list);
493
494 update_recvframe_attrib(precvframe, prxstat);
495
496 pattrib = &precvframe->attrib;
497
498 if (pattrib->crc_err) {
499 DBG_8723A("%s()-%d: RX Warning! rx CRC ERROR !!\n",
500 __FUNCTION__, __LINE__);
501 rtw_free_recvframe23a(precvframe, pfree_recv_queue);
502 goto _exit_recvbuf2recvframe;
503 }
504
505 pkt_offset = RXDESC_SIZE + pattrib->drvinfo_sz +
506 pattrib->shift_sz + pattrib->pkt_len;
507
508 if ((pattrib->pkt_len <= 0) || (pkt_offset > transfer_len)) {
509 RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
510 ("recvbuf2recvframe: pkt_len<= 0\n"));
511 DBG_8723A("%s()-%d: RX Warning!\n",
512 __FUNCTION__, __LINE__);
513 rtw_free_recvframe23a(precvframe, pfree_recv_queue);
514 goto _exit_recvbuf2recvframe;
515 }
516
517 /* Modified by Albert 20101213 */
518 /* For 8 bytes IP header alignment. */
519 /* Qos data, wireless lan header length is 26 */
520 if (pattrib->qos) {
521 shift_sz = 6;
522 } else {
523 shift_sz = 0;
524 }
525
526 skb_len = pattrib->pkt_len;
527
528 /* for first fragment packet, driver need allocate
529 * 1536+drvinfo_sz+RXDESC_SIZE to defrag packet.
530 * modify alloc_sz for recvive crc error packet
531 * by thomas 2011-06-02 */
532 if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
533 /* alloc_sz = 1664; 1664 is 128 alignment. */
534 if (skb_len <= 1650)
535 alloc_sz = 1664;
536 else
537 alloc_sz = skb_len + 14;
538 } else {
539 alloc_sz = skb_len;
540 /* 6 is for IP header 8 bytes alignment in QoS packet case. */
541 /* 8 is for skb->data 4 bytes alignment. */
542 alloc_sz += 14;
543 }
544
545 pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz);
546 if (pkt_copy) {
547 pkt_copy->dev = padapter->pnetdev;
548 precvframe->pkt = pkt_copy;
549 skb_reserve(pkt_copy, 8 - ((unsigned long)(pkt_copy->data) & 7));/* force pkt_copy->data at 8-byte alignment address */
550 /*force ip_hdr at 8-byte alignment address according to shift_sz. */
551 skb_reserve(pkt_copy, shift_sz);
552 memcpy(pkt_copy->data, (pbuf + pattrib->shift_sz + pattrib->drvinfo_sz + RXDESC_SIZE), skb_len);
553 skb_put(pkt_copy, skb_len);
554 } else {
555 if ((pattrib->mfrag == 1) && (pattrib->frag_num == 0)) {
556 DBG_8723A("recvbuf2recvframe: alloc_skb fail, "
557 "drop frag frame \n");
558 rtw_free_recvframe23a(precvframe,
559 pfree_recv_queue);
560 goto _exit_recvbuf2recvframe;
561 }
562
563 precvframe->pkt = skb_clone(pskb, GFP_ATOMIC);
564 if (!precvframe->pkt) {
565 DBG_8723A("recvbuf2recvframe: skb_clone "
566 "fail\n");
567 rtw_free_recvframe23a(precvframe,
568 pfree_recv_queue);
569 goto _exit_recvbuf2recvframe;
570 }
571 }
572
573 if (pattrib->physt) {
574 pphy_info = (struct phy_stat *)(pbuf + RXDESC_OFFSET);
575 update_recvframe_phyinfo(precvframe, pphy_info);
576 }
577
578 if (rtw_recv_entry23a(precvframe) != _SUCCESS)
579 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
580 ("recvbuf2recvframe: rtw_recv_entry23a"
581 "(precvframe) != _SUCCESS\n"));
582
583 pkt_cnt--;
584 transfer_len -= pkt_offset;
585 pbuf += pkt_offset;
586 precvframe = NULL;
587 pkt_copy = NULL;
588
589 if (transfer_len > 0 && pkt_cnt == 0)
590 pkt_cnt = (le32_to_cpu(prxstat->rxdw2)>>16) & 0xff;
591
592 } while ((transfer_len > 0) && (pkt_cnt > 0));
593
594_exit_recvbuf2recvframe:
595
596 return _SUCCESS;
597}
598
599void rtl8723au_recv_tasklet(void *priv)
600{
601 struct sk_buff *pskb;
602 struct rtw_adapter *padapter = (struct rtw_adapter *)priv;
603 struct recv_priv *precvpriv = &padapter->recvpriv;
604
605 while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
606 if ((padapter->bDriverStopped) ||
607 (padapter->bSurpriseRemoved)) {
608 DBG_8723A("recv_tasklet => bDriverStopped or "
609 "bSurpriseRemoved \n");
610 dev_kfree_skb_any(pskb);
611 break;
612 }
613
614 recvbuf2recvframe(padapter, pskb);
615 skb_reset_tail_pointer(pskb);
616
617 pskb->len = 0;
618
619 skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
620 }
621}
622
623static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs)
624{
625 struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
626 struct rtw_adapter *padapter = (struct rtw_adapter *)precvbuf->adapter;
627 struct recv_priv *precvpriv = &padapter->recvpriv;
628 struct hal_data_8723a *pHalData;
629
630 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
631 ("usb_read_port_complete!!!\n"));
632
633 precvpriv->rx_pending_cnt--;
634
635 if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
636 padapter->bReadPortCancel) {
637 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
638 ("usb_read_port_complete:bDriverStopped(%d) OR "
639 "bSurpriseRemoved(%d)\n", padapter->bDriverStopped,
640 padapter->bSurpriseRemoved));
641
642 DBG_8723A("%s()-%d: RX Warning! bDriverStopped(%d) OR "
643 "bSurpriseRemoved(%d) bReadPortCancel(%d)\n",
644 __FUNCTION__, __LINE__, padapter->bDriverStopped,
645 padapter->bSurpriseRemoved, padapter->bReadPortCancel);
646 return;
647 }
648
649 if (purb->status == 0) {
650 if ((purb->actual_length > MAX_RECVBUF_SZ) ||
651 (purb->actual_length < RXDESC_SIZE)) {
652 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
653 ("usb_read_port_complete: (purb->actual_"
654 "length > MAX_RECVBUF_SZ) || (purb->actual_"
655 "length < RXDESC_SIZE)\n"));
656 rtw_read_port(padapter, precvpriv->ff_hwaddr, 0,
657 precvbuf);
658 DBG_8723A("%s()-%d: RX Warning!\n",
659 __FUNCTION__, __LINE__);
660 } else {
661 rtw_reset_continual_urb_error(
662 adapter_to_dvobj(padapter));
663
664 skb_put(precvbuf->pskb, purb->actual_length);
665 skb_queue_tail(&precvpriv->rx_skb_queue,
666 precvbuf->pskb);
667
668 if (skb_queue_len(&precvpriv->rx_skb_queue) <= 1)
669 tasklet_schedule(&precvpriv->recv_tasklet);
670
671 precvbuf->pskb = NULL;
672 rtw_read_port(padapter, precvpriv->ff_hwaddr, 0,
673 precvbuf);
674 }
675 } else {
676 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
677 ("usb_read_port_complete : purb->status(%d) != 0 \n",
678 purb->status));
679 skb_put(precvbuf->pskb, purb->actual_length);
680 precvbuf->pskb = NULL;
681
682 DBG_8723A("###=> usb_read_port_complete => urb status(%d)\n",
683 purb->status);
684
685 if (rtw_inc_and_chk_continual_urb_error(
686 adapter_to_dvobj(padapter))) {
687 padapter->bSurpriseRemoved = true;
688 }
689
690 switch (purb->status) {
691 case -EINVAL:
692 case -EPIPE:
693 case -ENODEV:
694 case -ESHUTDOWN:
695 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
696 ("usb_read_port_complete:bSurprise"
697 "Removed = true\n"));
698 /* Intentional fall through here */
699 case -ENOENT:
700 padapter->bDriverStopped = true;
701 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
702 ("usb_read_port_complete:"
703 "bDriverStopped = true\n"));
704 break;
705 case -EPROTO:
706 case -EOVERFLOW:
707 pHalData = GET_HAL_DATA(padapter);
708 pHalData->srestpriv.Wifi_Error_Status =
709 USB_READ_PORT_FAIL;
710 rtw_read_port(padapter, precvpriv->ff_hwaddr,
711 0, precvbuf);
712 break;
713 case -EINPROGRESS:
714 DBG_8723A("ERROR: URB IS IN PROGRESS!/n");
715 break;
716 default:
717 break;
718 }
719
720 }
721}
722
723static u32 usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
724 struct recv_buf *precvbuf)
725{
726 int err;
727 unsigned int pipe;
728 unsigned long tmpaddr = 0;
729 unsigned long alignment = 0;
730 u32 ret = _SUCCESS;
731 struct urb *purb = NULL;
732 struct rtw_adapter *adapter = pintfhdl->padapter;
733 struct dvobj_priv *pdvobj = adapter_to_dvobj(adapter);
734 struct recv_priv *precvpriv = &adapter->recvpriv;
735 struct usb_device *pusbd = pdvobj->pusbdev;
736
737 if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
738 adapter->pwrctrlpriv.pnp_bstop_trx) {
739 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
740 ("usb_read_port:(padapter->bDriverStopped ||"
741 "padapter->bSurpriseRemoved ||adapter->"
742 "pwrctrlpriv.pnp_bstop_trx)!!!\n"));
743 return _FAIL;
744 }
745
746 if (!precvbuf) {
747 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
748 ("usb_read_port:precvbuf == NULL\n"));
749 return _FAIL;
750 }
751
752 if (!precvbuf->pskb)
753 precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
754
755 rtl8723au_init_recvbuf(adapter, precvbuf);
756
757 /* re-assign for linux based on skb */
758 if (!precvbuf->pskb) {
759 precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev, MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
760 if (precvbuf->pskb == NULL) {
761 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("init_recvbuf(): alloc_skb fail!\n"));
762 return _FAIL;
763 }
764
765 tmpaddr = (unsigned long)precvbuf->pskb->data;
766 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
767 skb_reserve(precvbuf->pskb, (RECVBUFF_ALIGN_SZ - alignment));
768 }
769
770 precvpriv->rx_pending_cnt++;
771
772 purb = precvbuf->purb;
773
774 /* translate DMA FIFO addr to pipehandle */
775 pipe = ffaddr2pipehdl23a(pdvobj, addr);
776
777 usb_fill_bulk_urb(purb, pusbd, pipe, precvbuf->pskb->data,
778 MAX_RECVBUF_SZ, usb_read_port_complete,
779 precvbuf);/* context is precvbuf */
780
781 err = usb_submit_urb(purb, GFP_ATOMIC);
782 if ((err) && (err != -EPERM)) {
783 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
784 ("cannot submit rx in-token(err = 0x%.8x), URB_STATUS "
785 "= 0x%.8x", err, purb->status));
786 DBG_8723A("cannot submit rx in-token(err = 0x%08x), urb_status "
787 "= %d\n", err, purb->status);
788 ret = _FAIL;
789 }
790 return ret;
791}
792
793void rtl8723au_xmit_tasklet(void *priv)
794{
795 int ret = false;
796 struct rtw_adapter *padapter = (struct rtw_adapter *)priv;
797 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
798
799 if (check_fwstate(&padapter->mlmepriv, _FW_UNDER_SURVEY))
800 return;
801
802 while (1) {
803 if ((padapter->bDriverStopped) ||
804 (padapter->bSurpriseRemoved) ||
805 (padapter->bWritePortCancel)) {
806 DBG_8723A("xmit_tasklet => bDriverStopped or "
807 "bSurpriseRemoved or bWritePortCancel\n");
808 break;
809 }
810
811 ret = rtl8723au_xmitframe_complete(padapter, pxmitpriv, NULL);
812
813 if (!ret)
814 break;
815 }
816}
817
818void rtl8723au_set_intf_ops(struct _io_ops *pops)
819{
820
821 memset((u8 *)pops, 0, sizeof(struct _io_ops));
822
823 pops->_read8 = &usb_read8;
824 pops->_read16 = &usb_read16;
825 pops->_read32 = &usb_read32;
826 pops->_read_mem = &usb_read_mem23a;
827 pops->_read_port = &usb_read_port;
828
829 pops->_write8 = &usb_write8;
830 pops->_write16 = &usb_write16;
831 pops->_write32 = &usb_write32;
832 pops->_writeN = &usb_writeN;
833
834 pops->_write_mem = &usb_write_mem23a;
835 pops->_write_port = &usb_write_port23a;
836
837 pops->_read_port_cancel = &usb_read_port_cancel23a;
838 pops->_write_port_cancel = &usb_write_port23a_cancel;
839
840 pops->_read_interrupt = &usb_read_interrupt;
841}
842
843void rtl8723au_set_hw_type(struct rtw_adapter *padapter)
844{
845 padapter->chip_type = RTL8723A;
846 padapter->HardwareType = HARDWARE_TYPE_RTL8723AU;
847 DBG_8723A("CHIP TYPE: RTL8723A\n");
848}
diff --git a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h b/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h
new file mode 100644
index 000000000000..4b7f3479c0a9
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h
@@ -0,0 +1,230 @@
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 *
15 ******************************************************************************/
16#ifndef __INC_HAL8723PHYCFG_H__
17#define __INC_HAL8723PHYCFG_H__
18
19/*--------------------------Define Parameters-------------------------------*/
20#define LOOP_LIMIT 5
21#define MAX_STALL_TIME 50 /* us */
22#define AntennaDiversityValue 0x80
23#define MAX_TXPWR_IDX_NMODE_92S 63
24#define Reset_Cnt_Limit 3
25
26
27#define MAX_AGGR_NUM 0x0909
28
29/*--------------------------Define Parameters-------------------------------*/
30
31
32/*------------------------------Define structure----------------------------*/
33enum swchnlcmdid {
34 CmdID_End,
35 CmdID_SetTxPowerLevel,
36 CmdID_BBRegWrite10,
37 CmdID_WritePortUlong,
38 CmdID_WritePortUshort,
39 CmdID_WritePortUchar,
40 CmdID_RF_WriteReg,
41};
42
43
44/* 1. Switch channel related */
45struct swchnlcmd {
46 enum swchnlcmdid CmdID;
47 u32 Para1;
48 u32 Para2;
49 u32 msDelay;
50};
51
52enum HW90_BLOCK {
53 HW90_BLOCK_MAC = 0,
54 HW90_BLOCK_PHY0 = 1,
55 HW90_BLOCK_PHY1 = 2,
56 HW90_BLOCK_RF = 3,
57 HW90_BLOCK_MAXIMUM = 4, /* Never use this */
58};
59
60enum RF_RADIO_PATH {
61 RF_PATH_A = 0, /* Radio Path A */
62 RF_PATH_B = 1, /* Radio Path B */
63 RF_PATH_MAX /* Max RF number 90 support */
64};
65
66#define CHANNEL_MAX_NUMBER 14 /* 14 is the max channel number */
67#define CHANNEL_GROUP_MAX 3 /* ch1~3, ch4~9, ch10~14 total three groups */
68
69enum WIRELESS_MODE {
70 WIRELESS_MODE_UNKNOWN = 0x00,
71 WIRELESS_MODE_A = BIT2,
72 WIRELESS_MODE_B = BIT0,
73 WIRELESS_MODE_G = BIT1,
74 WIRELESS_MODE_AUTO = BIT5,
75 WIRELESS_MODE_N_24G = BIT3,
76 WIRELESS_MODE_N_5G = BIT4,
77 WIRELESS_MODE_AC = BIT6
78};
79
80enum baseband_config_type {
81 BaseBand_Config_PHY_REG = 0, /* Radio Path A */
82 BaseBand_Config_AGC_TAB = 1, /* Radio Path B */
83};
84
85enum ra_offset_area {
86 RA_OFFSET_LEGACY_OFDM1,
87 RA_OFFSET_LEGACY_OFDM2,
88 RA_OFFSET_HT_OFDM1,
89 RA_OFFSET_HT_OFDM2,
90 RA_OFFSET_HT_OFDM3,
91 RA_OFFSET_HT_OFDM4,
92 RA_OFFSET_HT_CCK,
93};
94
95
96/* BB/RF related */
97enum rf_type_8190p {
98 RF_TYPE_MIN, /* 0 */
99 RF_8225 = 1, /* 1 11b/g RF for verification only */
100 RF_8256 = 2, /* 2 11b/g/n */
101 RF_8258 = 3, /* 3 11a/b/g/n RF */
102 RF_6052 = 4, /* 4 11b/g/n RF */
103 RF_PSEUDO_11N = 5, /* 5, It is a temporality RF. */
104};
105
106struct bb_reg_define {
107 u32 rfintfs; /* set software control: */
108 /* 0x870~0x877[8 bytes] */
109 u32 rfintfi; /* readback data: */
110 /* 0x8e0~0x8e7[8 bytes] */
111 u32 rfintfo; /* output data: */
112 /* 0x860~0x86f [16 bytes] */
113 u32 rfintfe; /* output enable: */
114 /* 0x860~0x86f [16 bytes] */
115 u32 rf3wireOffset; /* LSSI data: */
116 /* 0x840~0x84f [16 bytes] */
117 u32 rfLSSI_Select; /* BB Band Select: */
118 /* 0x878~0x87f [8 bytes] */
119 u32 rfTxGainStage; /* Tx gain stage: */
120 /* 0x80c~0x80f [4 bytes] */
121 u32 rfHSSIPara1; /* wire parameter control1 : */
122 /* 0x820~0x823, 0x828~0x82b, 0x830~0x833, 0x838~0x83b [16 bytes] */
123 u32 rfHSSIPara2; /* wire parameter control2 : */
124 /* 0x824~0x827, 0x82c~0x82f, 0x834~0x837, 0x83c~0x83f [16 bytes] */
125 u32 rfSwitchControl; /* Tx Rx antenna control : */
126 /* 0x858~0x85f [16 bytes] */
127 u32 rfAGCControl1; /* AGC parameter control1 : */
128 /* 0xc50~0xc53, 0xc58~0xc5b, 0xc60~0xc63, 0xc68~0xc6b [16 bytes] */
129 u32 rfAGCControl2; /* AGC parameter control2 : */
130 /* 0xc54~0xc57, 0xc5c~0xc5f, 0xc64~0xc67, 0xc6c~0xc6f [16 bytes] */
131 u32 rfRxIQImbalance; /* OFDM Rx IQ imbalance matrix : */
132 /* 0xc14~0xc17, 0xc1c~0xc1f, 0xc24~0xc27, 0xc2c~0xc2f [16 bytes] */
133 u32 rfRxAFE; /* Rx IQ DC ofset and Rx digital filter, Rx DC notch filter : */
134 /* 0xc10~0xc13, 0xc18~0xc1b, 0xc20~0xc23, 0xc28~0xc2b [16 bytes] */
135 u32 rfTxIQImbalance; /* OFDM Tx IQ imbalance matrix */
136 /* 0xc80~0xc83, 0xc88~0xc8b, 0xc90~0xc93, 0xc98~0xc9b [16 bytes] */
137 u32 rfTxAFE; /* Tx IQ DC Offset and Tx DFIR type */
138 /* 0xc84~0xc87, 0xc8c~0xc8f, 0xc94~0xc97, 0xc9c~0xc9f [16 bytes] */
139 u32 rfLSSIReadBack; /* LSSI RF readback data SI mode */
140 /* 0x8a0~0x8af [16 bytes] */
141 u32 rfLSSIReadBackPi; /* LSSI RF readback data PI mode 0x8b8-8bc for Path A and B */
142};
143
144struct r_antenna_sel_ofdm {
145 u32 r_tx_antenna:4;
146 u32 r_ant_l:4;
147 u32 r_ant_non_ht:4;
148 u32 r_ant_ht1:4;
149 u32 r_ant_ht2:4;
150 u32 r_ant_ht_s1:4;
151 u32 r_ant_non_ht_s1:4;
152 u32 OFDM_TXSC:2;
153 u32 Reserved:2;
154};
155
156struct r_antenna_sel_cck {
157 u8 r_cckrx_enable_2:2;
158 u8 r_cckrx_enable:2;
159 u8 r_ccktx_enable:4;
160};
161
162/*------------------------------Define structure----------------------------*/
163
164
165/*------------------------Export global variable----------------------------*/
166/*------------------------Export global variable----------------------------*/
167
168
169/*------------------------Export Macro Definition---------------------------*/
170/*------------------------Export Macro Definition---------------------------*/
171
172
173/*--------------------------Exported Function prototype---------------------*/
174/* */
175/* BB and RF register read/write */
176/* */
177u32 PHY_QueryBBReg(struct rtw_adapter *Adapter, u32 RegAddr,
178 u32 BitMask);
179void PHY_SetBBReg(struct rtw_adapter *Adapter, u32 RegAddr,
180 u32 BitMask, u32 Data);
181u32 PHY_QueryRFReg(struct rtw_adapter *Adapter,
182 enum RF_RADIO_PATH eRFPath, u32 RegAddr,
183 u32 BitMask);
184void PHY_SetRFReg(struct rtw_adapter *Adapter,
185 enum RF_RADIO_PATH eRFPath, u32 RegAddr,
186 u32 BitMask, u32 Data);
187
188/* */
189/* BB TX Power R/W */
190/* */
191void PHY_SetTxPowerLevel8723A(struct rtw_adapter *Adapter, u8 channel);
192
193/* */
194/* Switch bandwidth for 8723A */
195/* */
196void PHY_SetBWMode23a8723A(struct rtw_adapter *pAdapter,
197 enum ht_channel_width ChnlWidth,
198 unsigned char Offset);
199
200/* */
201/* channel switch related funciton */
202/* */
203void PHY_SwChnl8723A(struct rtw_adapter *pAdapter, u8 channel);
204 /* Call after initialization */
205void ChkFwCmdIoDone(struct rtw_adapter *Adapter);
206
207/* */
208/* Modify the value of the hw register when beacon interval be changed. */
209/* */
210void
211rtl8192c_PHY_SetBeaconHwReg(struct rtw_adapter *Adapter, u16 BeaconInterval);
212
213
214void PHY_SwitchEphyParameter(struct rtw_adapter *Adapter);
215
216void PHY_EnableHostClkReq(struct rtw_adapter *Adapter);
217
218bool
219SetAntennaConfig92C(struct rtw_adapter *Adapter, u8 DefaultAnt);
220
221/*--------------------------Exported Function prototype---------------------*/
222
223#define PHY_SetMacReg PHY_SetBBReg
224
225/* MAC/BB/RF HAL config */
226int PHY_BBConfig8723A(struct rtw_adapter *Adapter);
227int PHY_RFConfig8723A(struct rtw_adapter *Adapter);
228s32 PHY_MACConfig8723A(struct rtw_adapter *padapter);
229
230#endif
diff --git a/drivers/staging/rtl8723au/include/Hal8723APhyReg.h b/drivers/staging/rtl8723au/include/Hal8723APhyReg.h
new file mode 100644
index 000000000000..759928f78d6d
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/Hal8723APhyReg.h
@@ -0,0 +1,1078 @@
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 *
15 ******************************************************************************/
16#ifndef __INC_HAL8723APHYREG_H__
17#define __INC_HAL8723APHYREG_H__
18
19/* 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF */
20/* 1. Page1(0x100) */
21#define rPMAC_Reset 0x100
22#define rPMAC_TxStart 0x104
23#define rPMAC_TxLegacySIG 0x108
24#define rPMAC_TxHTSIG1 0x10c
25#define rPMAC_TxHTSIG2 0x110
26#define rPMAC_PHYDebug 0x114
27#define rPMAC_TxPacketNum 0x118
28#define rPMAC_TxIdle 0x11c
29#define rPMAC_TxMACHeader0 0x120
30#define rPMAC_TxMACHeader1 0x124
31#define rPMAC_TxMACHeader2 0x128
32#define rPMAC_TxMACHeader3 0x12c
33#define rPMAC_TxMACHeader4 0x130
34#define rPMAC_TxMACHeader5 0x134
35#define rPMAC_TxDataType 0x138
36#define rPMAC_TxRandomSeed 0x13c
37#define rPMAC_CCKPLCPPreamble 0x140
38#define rPMAC_CCKPLCPHeader 0x144
39#define rPMAC_CCKCRC16 0x148
40#define rPMAC_OFDMRxCRC32OK 0x170
41#define rPMAC_OFDMRxCRC32Er 0x174
42#define rPMAC_OFDMRxParityEr 0x178
43#define rPMAC_OFDMRxCRC8Er 0x17c
44#define rPMAC_CCKCRxRC16Er 0x180
45#define rPMAC_CCKCRxRC32Er 0x184
46#define rPMAC_CCKCRxRC32OK 0x188
47#define rPMAC_TxStatus 0x18c
48
49/* 2. Page2(0x200) */
50/* The following two definition are only used for USB interface. */
51#define RF_BB_CMD_ADDR 0x02c0 /* RF/BB read/write command address. */
52#define RF_BB_CMD_DATA 0x02c4 /* RF/BB read/write command data. */
53
54/* 3. Page8(0x800) */
55#define rFPGA0_RFMOD 0x800 /* RF mode & CCK TxSC RF BW Setting?? */
56
57#define rFPGA0_TxInfo 0x804 /* Status report?? */
58#define rFPGA0_PSDFunction 0x808
59
60#define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */
61
62#define rFPGA0_RFTiming1 0x810 /* Useless now */
63#define rFPGA0_RFTiming2 0x814
64
65#define rFPGA0_XA_HSSIParameter1 0x820 /* RF 3 wire register */
66#define rFPGA0_XA_HSSIParameter2 0x824
67#define rFPGA0_XB_HSSIParameter1 0x828
68#define rFPGA0_XB_HSSIParameter2 0x82c
69#define rTxAGC_B_Rate18_06 0x830
70#define rTxAGC_B_Rate54_24 0x834
71#define rTxAGC_B_CCK1_55_Mcs32 0x838
72#define rTxAGC_B_Mcs03_Mcs00 0x83c
73
74#define rTxAGC_B_Mcs07_Mcs04 0x848
75#define rTxAGC_B_Mcs11_Mcs08 0x84c
76
77#define rFPGA0_XA_LSSIParameter 0x840
78#define rFPGA0_XB_LSSIParameter 0x844
79
80#define rFPGA0_RFWakeUpParameter 0x850 /* Useless now */
81#define rFPGA0_RFSleepUpParameter 0x854
82
83#define rFPGA0_XAB_SwitchControl 0x858 /* RF Channel switch */
84#define rFPGA0_XCD_SwitchControl 0x85c
85
86#define rFPGA0_XA_RFInterfaceOE 0x860 /* RF Channel switch */
87#define rFPGA0_XB_RFInterfaceOE 0x864
88
89#define rTxAGC_B_Mcs15_Mcs12 0x868
90#define rTxAGC_B_CCK11_A_CCK2_11 0x86c
91
92#define rFPGA0_XAB_RFInterfaceSW 0x870 /* RF Interface Software Control */
93#define rFPGA0_XCD_RFInterfaceSW 0x874
94
95#define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */
96#define rFPGA0_XCD_RFParameter 0x87c
97
98#define rFPGA0_AnalogParameter1 0x880 /* Crystal cap setting RF-R/W protection for parameter4?? */
99#define rFPGA0_AnalogParameter2 0x884
100#define rFPGA0_AnalogParameter3 0x888 /* Useless now */
101#define rFPGA0_AnalogParameter4 0x88c
102
103#define rFPGA0_XA_LSSIReadBack 0x8a0 /* Tranceiver LSSI Readback */
104#define rFPGA0_XB_LSSIReadBack 0x8a4
105#define rFPGA0_XC_LSSIReadBack 0x8a8
106#define rFPGA0_XD_LSSIReadBack 0x8ac
107
108#define rFPGA0_PSDReport 0x8b4 /* Useless now */
109#define TransceiverA_HSPI_Readback 0x8b8 /* Transceiver A HSPI Readback */
110#define TransceiverB_HSPI_Readback 0x8bc /* Transceiver B HSPI Readback */
111#define rFPGA0_XAB_RFInterfaceRB 0x8e0 /* Useless now RF Interface Readback Value */
112#define rFPGA0_XCD_RFInterfaceRB 0x8e4 /* Useless now */
113
114/* 4. Page9(0x900) */
115#define rFPGA1_RFMOD 0x900 /* RF mode & OFDM TxSC RF BW Setting?? */
116
117#define rFPGA1_TxBlock 0x904 /* Useless now */
118#define rFPGA1_DebugSelect 0x908 /* Useless now */
119#define rFPGA1_TxInfo 0x90c /* Useless now Status report?? */
120
121/* 5. PageA(0xA00) */
122/* Set Control channel to upper or lower. These settings are required only for 40MHz */
123#define rCCK0_System 0xa00
124
125#define rCCK0_AFESetting 0xa04 /* Disable init gain now Select RX path by RSSI */
126#define rCCK0_CCA 0xa08 /* Disable init gain now Init gain */
127
128#define rCCK0_RxAGC1 0xa0c /* AGC default value, saturation level Antenna Diversity, RX AGC, LNA Threshold, RX LNA Threshold useless now. Not the same as 90 series */
129#define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */
130
131#define rCCK0_RxHP 0xa14
132
133#define rCCK0_DSPParameter1 0xa18 /* Timing recovery & Channel estimation threshold */
134#define rCCK0_DSPParameter2 0xa1c /* SQ threshold */
135
136#define rCCK0_TxFilter1 0xa20
137#define rCCK0_TxFilter2 0xa24
138#define rCCK0_DebugPort 0xa28 /* debug port and Tx filter3 */
139#define rCCK0_FalseAlarmReport 0xa2c /* 0xa2d useless now 0xa30-a4f channel report */
140#define rCCK0_TRSSIReport 0xa50
141#define rCCK0_RxReport 0xa54 /* 0xa57 */
142#define rCCK0_FACounterLower 0xa5c /* 0xa5b */
143#define rCCK0_FACounterUpper 0xa58 /* 0xa5c */
144/* PageB(0xB00) */
145#define rPdp_AntA 0xb00
146#define rPdp_AntA_4 0xb04
147#define rConfig_Pmpd_AntA 0xb28
148#define rConfig_AntA 0xb68
149#define rConfig_AntB 0xb6c
150#define rPdp_AntB 0xb70
151#define rPdp_AntB_4 0xb74
152#define rConfig_Pmpd_AntB 0xb98
153#define rAPK 0xbd8
154
155/* 6. PageC(0xC00) */
156#define rOFDM0_LSTF 0xc00
157
158#define rOFDM0_TRxPathEnable 0xc04
159#define rOFDM0_TRMuxPar 0xc08
160#define rOFDM0_TRSWIsolation 0xc0c
161
162#define rOFDM0_XARxAFE 0xc10 /* RxIQ DC offset, Rx digital filter, DC notch filter */
163#define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imblance matrix */
164#define rOFDM0_XBRxAFE 0xc18
165#define rOFDM0_XBRxIQImbalance 0xc1c
166#define rOFDM0_XCRxAFE 0xc20
167#define rOFDM0_XCRxIQImbalance 0xc24
168#define rOFDM0_XDRxAFE 0xc28
169#define rOFDM0_XDRxIQImbalance 0xc2c
170
171#define rOFDM0_RxDetector1 0xc30 /* PD,BW & SBD DM tune init gain */
172#define rOFDM0_RxDetector2 0xc34 /* SBD & Fame Sync. */
173#define rOFDM0_RxDetector3 0xc38 /* Frame Sync. */
174#define rOFDM0_RxDetector4 0xc3c /* PD, SBD, Frame Sync & Short-GI */
175
176#define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */
177#define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */
178#define rOFDM0_CCADropThreshold 0xc48 /* CCA Drop threshold */
179#define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */
180
181#define rOFDM0_XAAGCCore1 0xc50 /* DIG */
182#define rOFDM0_XAAGCCore2 0xc54
183#define rOFDM0_XBAGCCore1 0xc58
184#define rOFDM0_XBAGCCore2 0xc5c
185#define rOFDM0_XCAGCCore1 0xc60
186#define rOFDM0_XCAGCCore2 0xc64
187#define rOFDM0_XDAGCCore1 0xc68
188#define rOFDM0_XDAGCCore2 0xc6c
189
190#define rOFDM0_AGCParameter1 0xc70
191#define rOFDM0_AGCParameter2 0xc74
192#define rOFDM0_AGCRSSITable 0xc78
193#define rOFDM0_HTSTFAGC 0xc7c
194
195#define rOFDM0_XATxIQImbalance 0xc80 /* TX PWR TRACK and DIG */
196#define rOFDM0_XATxAFE 0xc84
197#define rOFDM0_XBTxIQImbalance 0xc88
198#define rOFDM0_XBTxAFE 0xc8c
199#define rOFDM0_XCTxIQImbalance 0xc90
200#define rOFDM0_XCTxAFE 0xc94
201#define rOFDM0_XDTxIQImbalance 0xc98
202#define rOFDM0_XDTxAFE 0xc9c
203
204#define rOFDM0_RxIQExtAnta 0xca0
205#define rOFDM0_TxCoeff1 0xca4
206#define rOFDM0_TxCoeff2 0xca8
207#define rOFDM0_TxCoeff3 0xcac
208#define rOFDM0_TxCoeff4 0xcb0
209#define rOFDM0_TxCoeff5 0xcb4
210#define rOFDM0_TxCoeff6 0xcb8
211#define rOFDM0_RxHPParameter 0xce0
212#define rOFDM0_TxPseudoNoiseWgt 0xce4
213#define rOFDM0_FrameSync 0xcf0
214#define rOFDM0_DFSReport 0xcf4
215
216/* 7. PageD(0xD00) */
217#define rOFDM1_LSTF 0xd00
218#define rOFDM1_TRxPathEnable 0xd04
219
220#define rOFDM1_CFO 0xd08 /* No setting now */
221#define rOFDM1_CSI1 0xd10
222#define rOFDM1_SBD 0xd14
223#define rOFDM1_CSI2 0xd18
224#define rOFDM1_CFOTracking 0xd2c
225#define rOFDM1_TRxMesaure1 0xd34
226#define rOFDM1_IntfDet 0xd3c
227#define rOFDM1_PseudoNoiseStateAB 0xd50
228#define rOFDM1_PseudoNoiseStateCD 0xd54
229#define rOFDM1_RxPseudoNoiseWgt 0xd58
230
231#define rOFDM_PHYCounter1 0xda0 /* cca, parity fail */
232#define rOFDM_PHYCounter2 0xda4 /* rate illegal, crc8 fail */
233#define rOFDM_PHYCounter3 0xda8 /* MCS not support */
234
235#define rOFDM_ShortCFOAB 0xdac /* No setting now */
236#define rOFDM_ShortCFOCD 0xdb0
237#define rOFDM_LongCFOAB 0xdb4
238#define rOFDM_LongCFOCD 0xdb8
239#define rOFDM_TailCFOAB 0xdbc
240#define rOFDM_TailCFOCD 0xdc0
241#define rOFDM_PWMeasure1 0xdc4
242#define rOFDM_PWMeasure2 0xdc8
243#define rOFDM_BWReport 0xdcc
244#define rOFDM_AGCReport 0xdd0
245#define rOFDM_RxSNR 0xdd4
246#define rOFDM_RxEVMCSI 0xdd8
247#define rOFDM_SIGReport 0xddc
248
249
250/* 8. PageE(0xE00) */
251#define rTxAGC_A_Rate18_06 0xe00
252#define rTxAGC_A_Rate54_24 0xe04
253#define rTxAGC_A_CCK1_Mcs32 0xe08
254#define rTxAGC_A_Mcs03_Mcs00 0xe10
255#define rTxAGC_A_Mcs07_Mcs04 0xe14
256#define rTxAGC_A_Mcs11_Mcs08 0xe18
257#define rTxAGC_A_Mcs15_Mcs12 0xe1c
258
259#define rFPGA0_IQK 0xe28
260#define rTx_IQK_Tone_A 0xe30
261#define rRx_IQK_Tone_A 0xe34
262#define rTx_IQK_PI_A 0xe38
263#define rRx_IQK_PI_A 0xe3c
264
265#define rTx_IQK 0xe40
266#define rRx_IQK 0xe44
267#define rIQK_AGC_Pts 0xe48
268#define rIQK_AGC_Rsp 0xe4c
269#define rTx_IQK_Tone_B 0xe50
270#define rRx_IQK_Tone_B 0xe54
271#define rTx_IQK_PI_B 0xe58
272#define rRx_IQK_PI_B 0xe5c
273#define rIQK_AGC_Cont 0xe60
274
275#define rBlue_Tooth 0xe6c
276#define rRx_Wait_CCA 0xe70
277#define rTx_CCK_RFON 0xe74
278#define rTx_CCK_BBON 0xe78
279#define rTx_OFDM_RFON 0xe7c
280#define rTx_OFDM_BBON 0xe80
281#define rTx_To_Rx 0xe84
282#define rTx_To_Tx 0xe88
283#define rRx_CCK 0xe8c
284
285#define rTx_Power_Before_IQK_A 0xe94
286#define rTx_Power_After_IQK_A 0xe9c
287
288#define rRx_Power_Before_IQK_A 0xea0
289#define rRx_Power_Before_IQK_A_2 0xea4
290#define rRx_Power_After_IQK_A 0xea8
291#define rRx_Power_After_IQK_A_2 0xeac
292
293#define rTx_Power_Before_IQK_B 0xeb4
294#define rTx_Power_After_IQK_B 0xebc
295
296#define rRx_Power_Before_IQK_B 0xec0
297#define rRx_Power_Before_IQK_B_2 0xec4
298#define rRx_Power_After_IQK_B 0xec8
299#define rRx_Power_After_IQK_B_2 0xecc
300
301#define rRx_OFDM 0xed0
302#define rRx_Wait_RIFS 0xed4
303#define rRx_TO_Rx 0xed8
304#define rStandby 0xedc
305#define rSleep 0xee0
306#define rPMPD_ANAEN 0xeec
307
308/* 7. RF Register 0x00-0x2E (RF 8256) */
309/* RF-0222D 0x00-3F */
310/* Zebra1 */
311#define rZebra1_HSSIEnable 0x0 /* Useless now */
312#define rZebra1_TRxEnable1 0x1
313#define rZebra1_TRxEnable2 0x2
314#define rZebra1_AGC 0x4
315#define rZebra1_ChargePump 0x5
316#define rZebra1_Channel 0x7 /* RF channel switch */
317
318#define rZebra1_TxGain 0x8 /* Useless now */
319#define rZebra1_TxLPF 0x9
320#define rZebra1_RxLPF 0xb
321#define rZebra1_RxHPFCorner 0xc
322
323/* Zebra4 */
324#define rGlobalCtrl 0 /* Useless now */
325#define rRTL8256_TxLPF 19
326#define rRTL8256_RxLPF 11
327
328/* RTL8258 */
329#define rRTL8258_TxLPF 0x11 /* Useless now */
330#define rRTL8258_RxLPF 0x13
331#define rRTL8258_RSSILPF 0xa
332
333/* RL6052 Register definition */
334#define RF_AC 0x00
335#define RF_IQADJ_G1 0x01
336#define RF_IQADJ_G2 0x02
337#define RF_BS_PA_APSET_G1_G4 0x03
338#define RF_BS_PA_APSET_G5_G8 0x04
339#define RF_POW_TRSW 0x05
340#define RF_GAIN_RX 0x06
341#define RF_GAIN_TX 0x07
342#define RF_TXM_IDAC 0x08
343#define RF_IPA_G 0x09
344#define RF_TXBIAS_G 0x0A
345#define RF_TXPA_AG 0x0B
346#define RF_IPA_A 0x0C
347#define RF_TXBIAS_A 0x0D
348#define RF_BS_PA_APSET_G9_G11 0x0E
349#define RF_BS_IQGEN 0x0F
350#define RF_MODE1 0x10
351#define RF_MODE2 0x11
352#define RF_RX_AGC_HP 0x12
353#define RF_TX_AGC 0x13
354#define RF_BIAS 0x14
355#define RF_IPA 0x15
356#define RF_TXBIAS 0x16
357#define RF_POW_ABILITY 0x17
358#define RF_MODE_AG 0x18
359#define rRfChannel 0x18 /* RF channel and BW switch */
360#define RF_CHNLBW 0x18 /* RF channel and BW switch */
361#define RF_TOP 0x19
362#define RF_RX_G1 0x1A
363#define RF_RX_G2 0x1B
364#define RF_RX_BB2 0x1C
365#define RF_RX_BB1 0x1D
366#define RF_RCK1 0x1E
367#define RF_RCK2 0x1F
368#define RF_TX_G1 0x20
369#define RF_TX_G2 0x21
370#define RF_TX_G3 0x22
371#define RF_TX_BB1 0x23
372#define RF_T_METER 0x24
373#define RF_SYN_G1 0x25 /* RF TX Power control */
374#define RF_SYN_G2 0x26 /* RF TX Power control */
375#define RF_SYN_G3 0x27 /* RF TX Power control */
376#define RF_SYN_G4 0x28 /* RF TX Power control */
377#define RF_SYN_G5 0x29 /* RF TX Power control */
378#define RF_SYN_G6 0x2A /* RF TX Power control */
379#define RF_SYN_G7 0x2B /* RF TX Power control */
380#define RF_SYN_G8 0x2C /* RF TX Power control */
381
382#define RF_RCK_OS 0x30 /* RF TX PA control */
383
384#define RF_TXPA_G1 0x31 /* RF TX PA control */
385#define RF_TXPA_G2 0x32 /* RF TX PA control */
386#define RF_TXPA_G3 0x33 /* RF TX PA control */
387
388/* Bit Mask */
389/* 1. Page1(0x100) */
390#define bBBResetB 0x100 /* Useless now? */
391#define bGlobalResetB 0x200
392#define bOFDMTxStart 0x4
393#define bCCKTxStart 0x8
394#define bCRC32Debug 0x100
395#define bPMACLoopback 0x10
396#define bTxLSIG 0xffffff
397#define bOFDMTxRate 0xf
398#define bOFDMTxReserved 0x10
399#define bOFDMTxLength 0x1ffe0
400#define bOFDMTxParity 0x20000
401#define bTxHTSIG1 0xffffff
402#define bTxHTMCSRate 0x7f
403#define bTxHTBW 0x80
404#define bTxHTLength 0xffff00
405#define bTxHTSIG2 0xffffff
406#define bTxHTSmoothing 0x1
407#define bTxHTSounding 0x2
408#define bTxHTReserved 0x4
409#define bTxHTAggreation 0x8
410#define bTxHTSTBC 0x30
411#define bTxHTAdvanceCoding 0x40
412#define bTxHTShortGI 0x80
413#define bTxHTNumberHT_LTF 0x300
414#define bTxHTCRC8 0x3fc00
415#define bCounterReset 0x10000
416#define bNumOfOFDMTx 0xffff
417#define bNumOfCCKTx 0xffff0000
418#define bTxIdleInterval 0xffff
419#define bOFDMService 0xffff0000
420#define bTxMACHeader 0xffffffff
421#define bTxDataInit 0xff
422#define bTxHTMode 0x100
423#define bTxDataType 0x30000
424#define bTxRandomSeed 0xffffffff
425#define bCCKTxPreamble 0x1
426#define bCCKTxSFD 0xffff0000
427#define bCCKTxSIG 0xff
428#define bCCKTxService 0xff00
429#define bCCKLengthExt 0x8000
430#define bCCKTxLength 0xffff0000
431#define bCCKTxCRC16 0xffff
432#define bCCKTxStatus 0x1
433#define bOFDMTxStatus 0x2
434
435#define IS_BB_REG_OFFSET_92S(_Offset) \
436 ((_Offset >= 0x800) && (_Offset <= 0xfff))
437
438/* 2. Page8(0x800) */
439#define bRFMOD 0x1 /* Reg 0x800 rFPGA0_RFMOD */
440#define bJapanMode 0x2
441#define bCCKTxSC 0x30
442#define bCCKEn 0x1000000
443#define bOFDMEn 0x2000000
444
445#define bOFDMRxADCPhase 0x10000 /* Useless now */
446#define bOFDMTxDACPhase 0x40000
447#define bXATxAGC 0x3f
448
449#define bAntennaSelect 0x0300
450
451#define bXBTxAGC 0xf00 /* Reg 80c rFPGA0_TxGainStage */
452#define bXCTxAGC 0xf000
453#define bXDTxAGC 0xf0000
454
455#define bPAStart 0xf0000000 /* Useless now */
456#define bTRStart 0x00f00000
457#define bRFStart 0x0000f000
458#define bBBStart 0x000000f0
459#define bBBCCKStart 0x0000000f
460#define bPAEnd 0xf /* Reg0x814 */
461#define bTREnd 0x0f000000
462#define bRFEnd 0x000f0000
463#define bCCAMask 0x000000f0 /* T2R */
464#define bR2RCCAMask 0x00000f00
465#define bHSSI_R2TDelay 0xf8000000
466#define bHSSI_T2RDelay 0xf80000
467#define bContTxHSSI 0x400 /* chane gain at continue Tx */
468#define bIGFromCCK 0x200
469#define bAGCAddress 0x3f
470#define bRxHPTx 0x7000
471#define bRxHPT2R 0x38000
472#define bRxHPCCKIni 0xc0000
473#define bAGCTxCode 0xc00000
474#define bAGCRxCode 0x300000
475
476#define b3WireDataLength 0x800 /* Reg 0x820~84f rFPGA0_XA_HSSIParameter1 */
477#define b3WireAddressLength 0x400
478
479#define b3WireRFPowerDown 0x1 /* Useless now */
480/* define bHWSISelect 0x8 */
481#define b5GPAPEPolarity 0x40000000
482#define b2GPAPEPolarity 0x80000000
483#define bRFSW_TxDefaultAnt 0x3
484#define bRFSW_TxOptionAnt 0x30
485#define bRFSW_RxDefaultAnt 0x300
486#define bRFSW_RxOptionAnt 0x3000
487#define bRFSI_3WireData 0x1
488#define bRFSI_3WireClock 0x2
489#define bRFSI_3WireLoad 0x4
490#define bRFSI_3WireRW 0x8
491#define bRFSI_3Wire 0xf
492
493#define bRFSI_RFENV 0x10 /* Reg 0x870 rFPGA0_XAB_RFInterfaceSW */
494
495#define bRFSI_TRSW 0x20 /* Useless now */
496#define bRFSI_TRSWB 0x40
497#define bRFSI_ANTSW 0x100
498#define bRFSI_ANTSWB 0x200
499#define bRFSI_PAPE 0x400
500#define bRFSI_PAPE5G 0x800
501#define bBandSelect 0x1
502#define bHTSIG2_GI 0x80
503#define bHTSIG2_Smoothing 0x01
504#define bHTSIG2_Sounding 0x02
505#define bHTSIG2_Aggreaton 0x08
506#define bHTSIG2_STBC 0x30
507#define bHTSIG2_AdvCoding 0x40
508#define bHTSIG2_NumOfHTLTF 0x300
509#define bHTSIG2_CRC8 0x3fc
510#define bHTSIG1_MCS 0x7f
511#define bHTSIG1_BandWidth 0x80
512#define bHTSIG1_HTLength 0xffff
513#define bLSIG_Rate 0xf
514#define bLSIG_Reserved 0x10
515#define bLSIG_Length 0x1fffe
516#define bLSIG_Parity 0x20
517#define bCCKRxPhase 0x4
518
519#define bLSSIReadAddress 0x7f800000 /* T65 RF */
520
521#define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */
522
523#define bLSSIReadBackData 0xfffff /* T65 RF */
524
525#define bLSSIReadOKFlag 0x1000 /* Useless now */
526#define bCCKSampleRate 0x8 /* 0: 44MHz, 1:88MHz */
527#define bRegulator0Standby 0x1
528#define bRegulatorPLLStandby 0x2
529#define bRegulator1Standby 0x4
530#define bPLLPowerUp 0x8
531#define bDPLLPowerUp 0x10
532#define bDA10PowerUp 0x20
533#define bAD7PowerUp 0x200
534#define bDA6PowerUp 0x2000
535#define bXtalPowerUp 0x4000
536#define b40MDClkPowerUP 0x8000
537#define bDA6DebugMode 0x20000
538#define bDA6Swing 0x380000
539
540#define bADClkPhase 0x4000000 /* Reg 0x880 rFPGA0_AnalogParameter1 20/40 CCK support switch 40/80 BB MHZ */
541
542#define b80MClkDelay 0x18000000 /* Useless */
543#define bAFEWatchDogEnable 0x20000000
544
545#define bXtalCap01 0xc0000000 /* Reg 0x884 rFPGA0_AnalogParameter2 Crystal cap */
546#define bXtalCap23 0x3
547#define bXtalCap92x 0x0f000000
548#define bXtalCap 0x0f000000
549
550#define bIntDifClkEnable 0x400 /* Useless */
551#define bExtSigClkEnable 0x800
552#define bBandgapMbiasPowerUp 0x10000
553#define bAD11SHGain 0xc0000
554#define bAD11InputRange 0x700000
555#define bAD11OPCurrent 0x3800000
556#define bIPathLoopback 0x4000000
557#define bQPathLoopback 0x8000000
558#define bAFELoopback 0x10000000
559#define bDA10Swing 0x7e0
560#define bDA10Reverse 0x800
561#define bDAClkSource 0x1000
562#define bAD7InputRange 0x6000
563#define bAD7Gain 0x38000
564#define bAD7OutputCMMode 0x40000
565#define bAD7InputCMMode 0x380000
566#define bAD7Current 0xc00000
567#define bRegulatorAdjust 0x7000000
568#define bAD11PowerUpAtTx 0x1
569#define bDA10PSAtTx 0x10
570#define bAD11PowerUpAtRx 0x100
571#define bDA10PSAtRx 0x1000
572#define bCCKRxAGCFormat 0x200
573#define bPSDFFTSamplepPoint 0xc000
574#define bPSDAverageNum 0x3000
575#define bIQPathControl 0xc00
576#define bPSDFreq 0x3ff
577#define bPSDAntennaPath 0x30
578#define bPSDIQSwitch 0x40
579#define bPSDRxTrigger 0x400000
580#define bPSDTxTrigger 0x80000000
581#define bPSDSineToneScale 0x7f000000
582#define bPSDReport 0xffff
583
584/* 3. Page9(0x900) */
585#define bOFDMTxSC 0x30000000 /* Useless */
586#define bCCKTxOn 0x1
587#define bOFDMTxOn 0x2
588#define bDebugPage 0xfff /* reset debug page and also HWord, LWord */
589#define bDebugItem 0xff /* reset debug page and LWord */
590#define bAntL 0x10
591#define bAntNonHT 0x100
592#define bAntHT1 0x1000
593#define bAntHT2 0x10000
594#define bAntHT1S1 0x100000
595#define bAntNonHTS1 0x1000000
596
597/* 4. PageA(0xA00) */
598#define bCCKBBMode 0x3 /* Useless */
599#define bCCKTxPowerSaving 0x80
600#define bCCKRxPowerSaving 0x40
601
602#define bCCKSideBand 0x10 /* Reg 0xa00 rCCK0_System 20/40 switch */
603
604#define bCCKScramble 0x8 /* Useless */
605#define bCCKAntDiversity 0x8000
606#define bCCKCarrierRecovery 0x4000
607#define bCCKTxRate 0x3000
608#define bCCKDCCancel 0x0800
609#define bCCKISICancel 0x0400
610#define bCCKMatchFilter 0x0200
611#define bCCKEqualizer 0x0100
612#define bCCKPreambleDetect 0x800000
613#define bCCKFastFalseCCA 0x400000
614#define bCCKChEstStart 0x300000
615#define bCCKCCACount 0x080000
616#define bCCKcs_lim 0x070000
617#define bCCKBistMode 0x80000000
618#define bCCKCCAMask 0x40000000
619#define bCCKTxDACPhase 0x4
620#define bCCKRxADCPhase 0x20000000 /* r_rx_clk */
621#define bCCKr_cp_mode0 0x0100
622#define bCCKTxDCOffset 0xf0
623#define bCCKRxDCOffset 0xf
624#define bCCKCCAMode 0xc000
625#define bCCKFalseCS_lim 0x3f00
626#define bCCKCS_ratio 0xc00000
627#define bCCKCorgBit_sel 0x300000
628#define bCCKPD_lim 0x0f0000
629#define bCCKNewCCA 0x80000000
630#define bCCKRxHPofIG 0x8000
631#define bCCKRxIG 0x7f00
632#define bCCKLNAPolarity 0x800000
633#define bCCKRx1stGain 0x7f0000
634#define bCCKRFExtend 0x20000000 /* CCK Rx Iinital gain polarity */
635#define bCCKRxAGCSatLevel 0x1f000000
636#define bCCKRxAGCSatCount 0xe0
637#define bCCKRxRFSettle 0x1f /* AGCsamp_dly */
638#define bCCKFixedRxAGC 0x8000
639/* define bCCKRxAGCFormat 0x4000 remove to HSSI register 0x824 */
640#define bCCKAntennaPolarity 0x2000
641#define bCCKTxFilterType 0x0c00
642#define bCCKRxAGCReportType 0x0300
643#define bCCKRxDAGCEn 0x80000000
644#define bCCKRxDAGCPeriod 0x20000000
645#define bCCKRxDAGCSatLevel 0x1f000000
646#define bCCKTimingRecovery 0x800000
647#define bCCKTxC0 0x3f0000
648#define bCCKTxC1 0x3f000000
649#define bCCKTxC2 0x3f
650#define bCCKTxC3 0x3f00
651#define bCCKTxC4 0x3f0000
652#define bCCKTxC5 0x3f000000
653#define bCCKTxC6 0x3f
654#define bCCKTxC7 0x3f00
655#define bCCKDebugPort 0xff0000
656#define bCCKDACDebug 0x0f000000
657#define bCCKFalseAlarmEnable 0x8000
658#define bCCKFalseAlarmRead 0x4000
659#define bCCKTRSSI 0x7f
660#define bCCKRxAGCReport 0xfe
661#define bCCKRxReport_AntSel 0x80000000
662#define bCCKRxReport_MFOff 0x40000000
663#define bCCKRxRxReport_SQLoss 0x20000000
664#define bCCKRxReport_Pktloss 0x10000000
665#define bCCKRxReport_Lockedbit 0x08000000
666#define bCCKRxReport_RateError 0x04000000
667#define bCCKRxReport_RxRate 0x03000000
668#define bCCKRxFACounterLower 0xff
669#define bCCKRxFACounterUpper 0xff000000
670#define bCCKRxHPAGCStart 0xe000
671#define bCCKRxHPAGCFinal 0x1c00
672#define bCCKRxFalseAlarmEnable 0x8000
673#define bCCKFACounterFreeze 0x4000
674#define bCCKTxPathSel 0x10000000
675#define bCCKDefaultRxPath 0xc000000
676#define bCCKOptionRxPath 0x3000000
677
678/* 5. PageC(0xC00) */
679#define bNumOfSTF 0x3 /* Useless */
680#define bShift_L 0xc0
681#define bGI_TH 0xc
682#define bRxPathA 0x1
683#define bRxPathB 0x2
684#define bRxPathC 0x4
685#define bRxPathD 0x8
686#define bTxPathA 0x1
687#define bTxPathB 0x2
688#define bTxPathC 0x4
689#define bTxPathD 0x8
690#define bTRSSIFreq 0x200
691#define bADCBackoff 0x3000
692#define bDFIRBackoff 0xc000
693#define bTRSSILatchPhase 0x10000
694#define bRxIDCOffset 0xff
695#define bRxQDCOffset 0xff00
696#define bRxDFIRMode 0x1800000
697#define bRxDCNFType 0xe000000
698#define bRXIQImb_A 0x3ff
699#define bRXIQImb_B 0xfc00
700#define bRXIQImb_C 0x3f0000
701#define bRXIQImb_D 0xffc00000
702#define bDC_dc_Notch 0x60000
703#define bRxNBINotch 0x1f000000
704#define bPD_TH 0xf
705#define bPD_TH_Opt2 0xc000
706#define bPWED_TH 0x700
707#define bIfMF_Win_L 0x800
708#define bPD_Option 0x1000
709#define bMF_Win_L 0xe000
710#define bBW_Search_L 0x30000
711#define bwin_enh_L 0xc0000
712#define bBW_TH 0x700000
713#define bED_TH2 0x3800000
714#define bBW_option 0x4000000
715#define bRatio_TH 0x18000000
716#define bWindow_L 0xe0000000
717#define bSBD_Option 0x1
718#define bFrame_TH 0x1c
719#define bFS_Option 0x60
720#define bDC_Slope_check 0x80
721#define bFGuard_Counter_DC_L 0xe00
722#define bFrame_Weight_Short 0x7000
723#define bSub_Tune 0xe00000
724#define bFrame_DC_Length 0xe000000
725#define bSBD_start_offset 0x30000000
726#define bFrame_TH_2 0x7
727#define bFrame_GI2_TH 0x38
728#define bGI2_Sync_en 0x40
729#define bSarch_Short_Early 0x300
730#define bSarch_Short_Late 0xc00
731#define bSarch_GI2_Late 0x70000
732#define bCFOAntSum 0x1
733#define bCFOAcc 0x2
734#define bCFOStartOffset 0xc
735#define bCFOLookBack 0x70
736#define bCFOSumWeight 0x80
737#define bDAGCEnable 0x10000
738#define bTXIQImb_A 0x3ff
739#define bTXIQImb_B 0xfc00
740#define bTXIQImb_C 0x3f0000
741#define bTXIQImb_D 0xffc00000
742#define bTxIDCOffset 0xff
743#define bTxQDCOffset 0xff00
744#define bTxDFIRMode 0x10000
745#define bTxPesudoNoiseOn 0x4000000
746#define bTxPesudoNoise_A 0xff
747#define bTxPesudoNoise_B 0xff00
748#define bTxPesudoNoise_C 0xff0000
749#define bTxPesudoNoise_D 0xff000000
750#define bCCADropOption 0x20000
751#define bCCADropThres 0xfff00000
752#define bEDCCA_H 0xf
753#define bEDCCA_L 0xf0
754#define bLambda_ED 0x300
755#define bRxInitialGain 0x7f
756#define bRxAntDivEn 0x80
757#define bRxAGCAddressForLNA 0x7f00
758#define bRxHighPowerFlow 0x8000
759#define bRxAGCFreezeThres 0xc0000
760#define bRxFreezeStep_AGC1 0x300000
761#define bRxFreezeStep_AGC2 0xc00000
762#define bRxFreezeStep_AGC3 0x3000000
763#define bRxFreezeStep_AGC0 0xc000000
764#define bRxRssi_Cmp_En 0x10000000
765#define bRxQuickAGCEn 0x20000000
766#define bRxAGCFreezeThresMode 0x40000000
767#define bRxOverFlowCheckType 0x80000000
768#define bRxAGCShift 0x7f
769#define bTRSW_Tri_Only 0x80
770#define bPowerThres 0x300
771#define bRxAGCEn 0x1
772#define bRxAGCTogetherEn 0x2
773#define bRxAGCMin 0x4
774#define bRxHP_Ini 0x7
775#define bRxHP_TRLNA 0x70
776#define bRxHP_RSSI 0x700
777#define bRxHP_BBP1 0x7000
778#define bRxHP_BBP2 0x70000
779#define bRxHP_BBP3 0x700000
780#define bRSSI_H 0x7f0000 /* the threshold for high power */
781#define bRSSI_Gen 0x7f000000 /* the threshold for ant diversity */
782#define bRxSettle_TRSW 0x7
783#define bRxSettle_LNA 0x38
784#define bRxSettle_RSSI 0x1c0
785#define bRxSettle_BBP 0xe00
786#define bRxSettle_RxHP 0x7000
787#define bRxSettle_AntSW_RSSI 0x38000
788#define bRxSettle_AntSW 0xc0000
789#define bRxProcessTime_DAGC 0x300000
790#define bRxSettle_HSSI 0x400000
791#define bRxProcessTime_BBPPW 0x800000
792#define bRxAntennaPowerShift 0x3000000
793#define bRSSITableSelect 0xc000000
794#define bRxHP_Final 0x7000000
795#define bRxHTSettle_BBP 0x7
796#define bRxHTSettle_HSSI 0x8
797#define bRxHTSettle_RxHP 0x70
798#define bRxHTSettle_BBPPW 0x80
799#define bRxHTSettle_Idle 0x300
800#define bRxHTSettle_Reserved 0x1c00
801#define bRxHTRxHPEn 0x8000
802#define bRxHTAGCFreezeThres 0x30000
803#define bRxHTAGCTogetherEn 0x40000
804#define bRxHTAGCMin 0x80000
805#define bRxHTAGCEn 0x100000
806#define bRxHTDAGCEn 0x200000
807#define bRxHTRxHP_BBP 0x1c00000
808#define bRxHTRxHP_Final 0xe0000000
809#define bRxPWRatioTH 0x3
810#define bRxPWRatioEn 0x4
811#define bRxMFHold 0x3800
812#define bRxPD_Delay_TH1 0x38
813#define bRxPD_Delay_TH2 0x1c0
814#define bRxPD_DC_COUNT_MAX 0x600
815/* define bRxMF_Hold 0x3800 */
816#define bRxPD_Delay_TH 0x8000
817#define bRxProcess_Delay 0xf0000
818#define bRxSearchrange_GI2_Early 0x700000
819#define bRxFrame_Guard_Counter_L 0x3800000
820#define bRxSGI_Guard_L 0xc000000
821#define bRxSGI_Search_L 0x30000000
822#define bRxSGI_TH 0xc0000000
823#define bDFSCnt0 0xff
824#define bDFSCnt1 0xff00
825#define bDFSFlag 0xf0000
826#define bMFWeightSum 0x300000
827#define bMinIdxTH 0x7f000000
828#define bDAFormat 0x40000
829#define bTxChEmuEnable 0x01000000
830#define bTRSWIsolation_A 0x7f
831#define bTRSWIsolation_B 0x7f00
832#define bTRSWIsolation_C 0x7f0000
833#define bTRSWIsolation_D 0x7f000000
834#define bExtLNAGain 0x7c00
835
836/* 6. PageE(0xE00) */
837#define bSTBCEn 0x4 /* Useless */
838#define bAntennaMapping 0x10
839#define bNss 0x20
840#define bCFOAntSumD 0x200
841#define bPHYCounterReset 0x8000000
842#define bCFOReportGet 0x4000000
843#define bOFDMContinueTx 0x10000000
844#define bOFDMSingleCarrier 0x20000000
845#define bOFDMSingleTone 0x40000000
846/* define bRxPath1 0x01 */
847/* define bRxPath2 0x02 */
848/* define bRxPath3 0x04 */
849/* define bRxPath4 0x08 */
850/* define bTxPath1 0x10 */
851/* define bTxPath2 0x20 */
852#define bHTDetect 0x100
853#define bCFOEn 0x10000
854#define bCFOValue 0xfff00000
855#define bSigTone_Re 0x3f
856#define bSigTone_Im 0x7f00
857#define bCounter_CCA 0xffff
858#define bCounter_ParityFail 0xffff0000
859#define bCounter_RateIllegal 0xffff
860#define bCounter_CRC8Fail 0xffff0000
861#define bCounter_MCSNoSupport 0xffff
862#define bCounter_FastSync 0xffff
863#define bShortCFO 0xfff
864#define bShortCFOTLength 12 /* total */
865#define bShortCFOFLength 11 /* fraction */
866#define bLongCFO 0x7ff
867#define bLongCFOTLength 11
868#define bLongCFOFLength 11
869#define bTailCFO 0x1fff
870#define bTailCFOTLength 13
871#define bTailCFOFLength 12
872#define bmax_en_pwdB 0xffff
873#define bCC_power_dB 0xffff0000
874#define bnoise_pwdB 0xffff
875#define bPowerMeasTLength 10
876#define bPowerMeasFLength 3
877#define bRx_HT_BW 0x1
878#define bRxSC 0x6
879#define bRx_HT 0x8
880#define bNB_intf_det_on 0x1
881#define bIntf_win_len_cfg 0x30
882#define bNB_Intf_TH_cfg 0x1c0
883#define bRFGain 0x3f
884#define bTableSel 0x40
885#define bTRSW 0x80
886#define bRxSNR_A 0xff
887#define bRxSNR_B 0xff00
888#define bRxSNR_C 0xff0000
889#define bRxSNR_D 0xff000000
890#define bSNREVMTLength 8
891#define bSNREVMFLength 1
892#define bCSI1st 0xff
893#define bCSI2nd 0xff00
894#define bRxEVM1st 0xff0000
895#define bRxEVM2nd 0xff000000
896#define bSIGEVM 0xff
897#define bPWDB 0xff00
898#define bSGIEN 0x10000
899
900#define bSFactorQAM1 0xf /* Useless */
901#define bSFactorQAM2 0xf0
902#define bSFactorQAM3 0xf00
903#define bSFactorQAM4 0xf000
904#define bSFactorQAM5 0xf0000
905#define bSFactorQAM6 0xf0000
906#define bSFactorQAM7 0xf00000
907#define bSFactorQAM8 0xf000000
908#define bSFactorQAM9 0xf0000000
909#define bCSIScheme 0x100000
910
911#define bNoiseLvlTopSet 0x3 /* Useless */
912#define bChSmooth 0x4
913#define bChSmoothCfg1 0x38
914#define bChSmoothCfg2 0x1c0
915#define bChSmoothCfg3 0xe00
916#define bChSmoothCfg4 0x7000
917#define bMRCMode 0x800000
918#define bTHEVMCfg 0x7000000
919
920#define bLoopFitType 0x1 /* Useless */
921#define bUpdCFO 0x40
922#define bUpdCFOOffData 0x80
923#define bAdvUpdCFO 0x100
924#define bAdvTimeCtrl 0x800
925#define bUpdClko 0x1000
926#define bFC 0x6000
927#define bTrackingMode 0x8000
928#define bPhCmpEnable 0x10000
929#define bUpdClkoLTF 0x20000
930#define bComChCFO 0x40000
931#define bCSIEstiMode 0x80000
932#define bAdvUpdEqz 0x100000
933#define bUChCfg 0x7000000
934#define bUpdEqz 0x8000000
935
936/* Rx Pseduo noise */
937#define bRxPesudoNoiseOn 0x20000000 /* Useless */
938#define bRxPesudoNoise_A 0xff
939#define bRxPesudoNoise_B 0xff00
940#define bRxPesudoNoise_C 0xff0000
941#define bRxPesudoNoise_D 0xff000000
942#define bPesudoNoiseState_A 0xffff
943#define bPesudoNoiseState_B 0xffff0000
944#define bPesudoNoiseState_C 0xffff
945#define bPesudoNoiseState_D 0xffff0000
946
947/* 7. RF Register */
948/* Zebra1 */
949#define bZebra1_HSSIEnable 0x8 /* Useless */
950#define bZebra1_TRxControl 0xc00
951#define bZebra1_TRxGainSetting 0x07f
952#define bZebra1_RxCorner 0xc00
953#define bZebra1_TxChargePump 0x38
954#define bZebra1_RxChargePump 0x7
955#define bZebra1_ChannelNum 0xf80
956#define bZebra1_TxLPFBW 0x400
957#define bZebra1_RxLPFBW 0x600
958
959/* Zebra4 */
960#define bRTL8256RegModeCtrl1 0x100 /* Useless */
961#define bRTL8256RegModeCtrl0 0x40
962#define bRTL8256_TxLPFBW 0x18
963#define bRTL8256_RxLPFBW 0x600
964
965/* RTL8258 */
966#define bRTL8258_TxLPFBW 0xc /* Useless */
967#define bRTL8258_RxLPFBW 0xc00
968#define bRTL8258_RSSILPFBW 0xc0
969
970
971/* Other Definition */
972
973/* byte endable for sb_write */
974#define bByte0 0x1 /* Useless */
975#define bByte1 0x2
976#define bByte2 0x4
977#define bByte3 0x8
978#define bWord0 0x3
979#define bWord1 0xc
980#define bDWord 0xf
981
982/* for PutRegsetting & GetRegSetting BitMask */
983#define bMaskByte0 0xff /* Reg 0xc50 rOFDM0_XAAGCCore~0xC6f */
984#define bMaskByte1 0xff00
985#define bMaskByte2 0xff0000
986#define bMaskByte3 0xff000000
987#define bMaskHWord 0xffff0000
988#define bMaskLWord 0x0000ffff
989#define bMaskDWord 0xffffffff
990#define bMask12Bits 0xfff
991#define bMaskH4Bits 0xf0000000
992#define bMaskOFDM_D 0xffc00000
993#define bMaskCCK 0x3f3f3f3f
994
995/* for PutRFRegsetting & GetRFRegSetting BitMask */
996#define bRFRegOffsetMask 0xfffff
997
998#define bDisable 0x0
999
1000#define LeftAntenna 0x0 /* Useless */
1001#define RightAntenna 0x1
1002
1003#define tCheckTxStatus 500 /* 500ms Useless */
1004#define tUpdateRxCounter 100 /* 100ms */
1005
1006#define rateCCK 0 /* Useless */
1007#define rateOFDM 1
1008#define rateHT 2
1009
1010/* define Register-End */
1011#define bPMAC_End 0x1ff /* Useless */
1012#define bFPGAPHY0_End 0x8ff
1013#define bFPGAPHY1_End 0x9ff
1014#define bCCKPHY0_End 0xaff
1015#define bOFDMPHY0_End 0xcff
1016#define bOFDMPHY1_End 0xdff
1017
1018/* define max debug item in each debug page */
1019/* define bMaxItem_FPGA_PHY0 0x9 */
1020/* define bMaxItem_FPGA_PHY1 0x3 */
1021/* define bMaxItem_PHY_11B 0x16 */
1022/* define bMaxItem_OFDM_PHY0 0x29 */
1023/* define bMaxItem_OFDM_PHY1 0x0 */
1024
1025#define bPMACControl 0x0 /* Useless */
1026#define bWMACControl 0x1
1027#define bWNICControl 0x2
1028
1029#define PathA 0x0 /* Useless */
1030#define PathB 0x1
1031#define PathC 0x2
1032#define PathD 0x3
1033
1034/* PageB(0xB00) */
1035#define rPdp_AntA 0xb00
1036#define rPdp_AntA_4 0xb04
1037#define rPdp_AntA_8 0xb08
1038#define rPdp_AntA_C 0xb0c
1039#define rPdp_AntA_18 0xb18
1040#define rPdp_AntA_1C 0xb1c
1041#define rPdp_AntA_20 0xb20
1042#define rPdp_AntA_24 0xb24
1043
1044#define rConfig_Pmpd_AntA 0xb28
1045#define rConfig_ram64x16 0xb2c
1046
1047#define rBndA 0xb30
1048#define rHssiPar 0xb34
1049
1050#define rConfig_AntA 0xb68
1051#define rConfig_AntB 0xb6c
1052
1053#define rPdp_AntB 0xb70
1054#define rPdp_AntB_4 0xb74
1055#define rPdp_AntB_8 0xb78
1056#define rPdp_AntB_C 0xb7c
1057#define rPdp_AntB_10 0xb80
1058#define rPdp_AntB_14 0xb84
1059#define rPdp_AntB_18 0xb88
1060#define rPdp_AntB_1C 0xb8c
1061#define rPdp_AntB_20 0xb90
1062#define rPdp_AntB_24 0xb94
1063
1064#define rConfig_Pmpd_AntB 0xb98
1065
1066#define rBndB 0xba0
1067
1068#define rAPK 0xbd8
1069#define rPm_Rx0_AntA 0xbdc
1070#define rPm_Rx1_AntA 0xbe0
1071#define rPm_Rx2_AntA 0xbe4
1072#define rPm_Rx3_AntA 0xbe8
1073#define rPm_Rx0_AntB 0xbec
1074#define rPm_Rx1_AntB 0xbf0
1075#define rPm_Rx2_AntB 0xbf4
1076#define rPm_Rx3_AntB 0xbf8
1077
1078#endif
diff --git a/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h b/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h
new file mode 100644
index 000000000000..7f3bdea6a55e
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h
@@ -0,0 +1,150 @@
1#ifndef __HAL8723PWRSEQ_H__
2#define __HAL8723PWRSEQ_H__
3/*
4 Check document WM-20110607-Paul-RTL8723A_Power_Architecture-R02.vsd
5 There are 6 HW Power States:
6 0: POFF--Power Off
7 1: PDN--Power Down
8 2: CARDEMU--Card Emulation
9 3: ACT--Active Mode
10 4: LPS--Low Power State
11 5: SUS--Suspend
12
13 The transision from different states are defined below
14 TRANS_CARDEMU_TO_ACT
15 TRANS_ACT_TO_CARDEMU
16 TRANS_CARDEMU_TO_SUS
17 TRANS_SUS_TO_CARDEMU
18 TRANS_CARDEMU_TO_PDN
19 TRANS_ACT_TO_LPS
20 TRANS_LPS_TO_ACT
21
22 TRANS_END
23*/
24#include "HalPwrSeqCmd.h"
25#include "rtl8723a_spec.h"
26
27#define RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS 15
28#define RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS 15
29#define RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS 15
30#define RTL8723A_TRANS_SUS_TO_CARDEMU_STEPS 15
31#define RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS 15
32#define RTL8723A_TRANS_PDN_TO_CARDEMU_STEPS 15
33#define RTL8723A_TRANS_ACT_TO_LPS_STEPS 15
34#define RTL8723A_TRANS_LPS_TO_ACT_STEPS 15
35#define RTL8723A_TRANS_END_STEPS 1
36
37
38/* format
39 * { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here
40 */
41#define RTL8723A_TRANS_CARDEMU_TO_ACT \
42 {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0}, /*0x20[0] = 1b'1 enable LDOA12 MACRO block for all interface*/ \
43 {0x0067, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0}, /*0x67[0] = 0 to disable BT_GPS_SEL pins*/ \
44 {0x0001, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 1, PWRSEQ_DELAY_MS},/*Delay 1ms*/ \
45 {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT5, 0}, /*0x00[5] = 1b'0 release analog Ips to digital , 1:isolation*/ \
46 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT2, 0},/* disable SW LPS 0x04[10]= 0*/ \
47 {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT1, BIT1},/* wait till 0x04[17] = 1 power ready*/ \
48 {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0},/* release WLON reset 0x04[16]= 1*/ \
49 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0},/* disable HWPDN 0x04[15]= 0*/ \
50 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT4|BIT3), 0},/* disable WL suspend*/ \
51 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0},/* polling until return 0*/ \
52 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT0, 0},/**/ \
53 {0x004E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 1},/*0x4C[23] = 0x4E[7] = 1, switch DPDT_SEL_P output from WL BB */\
54
55#define RTL8723A_TRANS_ACT_TO_CARDEMU \
56 {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0},/*0x1F[7:0] = 0 turn off RF*/ \
57 {0x004E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0},/*0x4C[23] = 0x4E[7] = 0, switch DPDT_SEL_P output from register 0x65[2] */\
58 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1}, /*0x04[9] = 1 turn off MAC by HW state machine*/ \
59 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT1, 0}, /*wait till 0x04[9] = 0 polling until return 0 to disable*/ \
60 {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT5, BIT5}, /*0x00[5] = 1b'1 analog Ips to digital , 1:isolation*/ \
61 {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0}, /*0x20[0] = 1b'0 disable LDOA12 MACRO block*/ \
62
63
64#define RTL8723A_TRANS_CARDEMU_TO_SUS \
65 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4|BIT3, (BIT4|BIT3)}, /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \
66 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, BIT3}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \
67 {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4}, /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \
68 {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07[7:0] = 0x20 SDIO SOP option to disable BG/MB/ACK/SWR*/ \
69 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, BIT3|BIT4}, /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \
70 {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, BIT0}, /*Set SDIO suspend local register*/ \
71 {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, 0}, /*wait power state to suspend*/
72
73#define RTL8723A_TRANS_SUS_TO_CARDEMU \
74 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3 | BIT7, 0}, /*clear suspend enable and power down enable*/ \
75 {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, 0}, /*Set SDIO suspend local register*/ \
76 {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, BIT1}, /*wait power state to suspend*/\
77 {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0}, /*0x23[4] = 1b'0 12H LDO enter normal mode*/ \
78 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, 0}, /*0x04[12:11] = 2b'01enable WL suspend*/
79
80#define RTL8723A_TRANS_CARDEMU_TO_CARDDIS \
81 {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07 = 0x20 , SOP option to disable BG/MB*/ \
82 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, BIT3}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \
83 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT2, BIT2}, /*0x04[10] = 1, enable SW LPS*/ \
84 {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 1}, /*0x48[16] = 1 to enable GPIO9 as EXT WAKEUP*/ \
85 {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4}, /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \
86 {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, BIT0}, /*Set SDIO suspend local register*/ \
87 {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, 0}, /*wait power state to suspend*/
88
89#define RTL8723A_TRANS_CARDDIS_TO_CARDEMU \
90 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3 | BIT7, 0}, /*clear suspend enable and power down enable*/ \
91 {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, 0}, /*Set SDIO suspend local register*/ \
92 {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, BIT1}, /*wait power state to suspend*/\
93 {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0}, /*0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/ \
94 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, 0}, /*0x04[12:11] = 2b'01enable WL suspend*/\
95 {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0}, /*0x23[4] = 1b'0 12H LDO enter normal mode*/ \
96 {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0},/*PCIe DMA start*/
97
98
99#define RTL8723A_TRANS_CARDEMU_TO_PDN \
100 {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4}, /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \
101 {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK|PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07[7:0] = 0x20 SOP option to disable BG/MB/ACK/SWR*/ \
102 {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0},/* 0x04[16] = 0*/\
103 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, BIT7},/* 0x04[15] = 1*/
104
105#define RTL8723A_TRANS_PDN_TO_CARDEMU \
106 {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0},/* 0x04[15] = 0*/
107
108#define RTL8723A_TRANS_ACT_TO_LPS \
109 {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF},/*PCIe DMA stop*/ \
110 {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF},/*Tx Pause*/ \
111 {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \
112 {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \
113 {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \
114 {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \
115 {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0},/*CCK and OFDM are disabled, and clock are gated*/ \
116 {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US},/*Delay 1us*/ \
117 {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0},/*Whole BB is reset*/ \
118 {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x03},/*Reset MAC TRX*/ \
119 {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0},/*check if removed later*/ \
120 {0x0093, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00},/*When driver enter Sus/ Disable, enable LOP for BT*/ \
121 {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT5, BIT5},/*Respond TxOK to scheduler*/
122
123#define RTL8723A_TRANS_LPS_TO_ACT \
124 {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84}, /*SDIO RPWM*/\
125 {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*USB RPWM*/\
126 {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*PCIe RPWM*/\
127 {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/\
128 {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0}, /*. 0x08[4] = 0 switch TSF to 40M*/\
129 {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT7, 0}, /*Polling 0x109[7]= 0 TSF in 40M*/\
130 {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT6|BIT7, 0}, /*. 0x29[7:6] = 2b'00 enable BB clock*/\
131 {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1}, /*. 0x101[1] = 1*/\
132 {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, /*. 0x100[7:0] = 0xFF enable WMAC TRX*/\
133 {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1|BIT0, BIT1|BIT0}, /*. 0x02[1:0] = 2b'11 enable BB macro*/\
134 {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, /*. 0x522 = 0*/
135
136#define RTL8723A_TRANS_END \
137 {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, 0, PWR_CMD_END, 0, 0},
138
139
140extern struct wlan_pwr_cfg rtl8723AU_power_on_flow[RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS];
141extern struct wlan_pwr_cfg rtl8723AU_radio_off_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_END_STEPS];
142extern struct wlan_pwr_cfg rtl8723AU_card_disable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS];
143extern struct wlan_pwr_cfg rtl8723AU_card_enable_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS];
144extern struct wlan_pwr_cfg rtl8723AU_suspend_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS];
145extern struct wlan_pwr_cfg rtl8723AU_resume_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS+RTL8723A_TRANS_END_STEPS];
146extern struct wlan_pwr_cfg rtl8723AU_hwpdn_flow[RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS+RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS+RTL8723A_TRANS_END_STEPS];
147extern struct wlan_pwr_cfg rtl8723AU_enter_lps_flow[RTL8723A_TRANS_ACT_TO_LPS_STEPS+RTL8723A_TRANS_END_STEPS];
148extern struct wlan_pwr_cfg rtl8723AU_leave_lps_flow[RTL8723A_TRANS_LPS_TO_ACT_STEPS+RTL8723A_TRANS_END_STEPS];
149
150#endif
diff --git a/drivers/staging/rtl8723au/include/Hal8723UHWImg_CE.h b/drivers/staging/rtl8723au/include/Hal8723UHWImg_CE.h
new file mode 100644
index 000000000000..bbeaab48057a
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/Hal8723UHWImg_CE.h
@@ -0,0 +1,29 @@
1#ifndef __INC_HAL8723U_FW_IMG_H
2#define __INC_HAL8723U_FW_IMG_H
3
4/*Created on 2013/01/14, 15:51*/
5
6/* FW v16 enable usb interrupt */
7#define Rtl8723UImgArrayLength 22172
8extern u8 Rtl8723UFwImgArray[Rtl8723UImgArrayLength];
9#define Rtl8723UBTImgArrayLength 1
10extern u8 Rtl8723UFwBTImgArray[Rtl8723UBTImgArrayLength];
11
12#define Rtl8723UUMCBCutImgArrayWithBTLength 24118
13#define Rtl8723UUMCBCutImgArrayWithoutBTLength 19200
14
15extern u8 Rtl8723UFwUMCBCutImgArrayWithBT[Rtl8723UUMCBCutImgArrayWithBTLength];
16extern u8 Rtl8723UFwUMCBCutImgArrayWithoutBT[Rtl8723UUMCBCutImgArrayWithoutBTLength];
17
18#define Rtl8723SUMCBCutMPImgArrayLength 24174
19extern const u8 Rtl8723SFwUMCBCutMPImgArray[Rtl8723SUMCBCutMPImgArrayLength];
20
21#define Rtl8723EBTImgArrayLength 15276
22extern u8 Rtl8723EFwBTImgArray[Rtl8723EBTImgArrayLength] ;
23
24#define Rtl8723UPHY_REG_Array_PGLength 336
25extern u32 Rtl8723UPHY_REG_Array_PG[Rtl8723UPHY_REG_Array_PGLength];
26#define Rtl8723UMACPHY_Array_PGLength 1
27extern u32 Rtl8723UMACPHY_Array_PG[Rtl8723UMACPHY_Array_PGLength];
28
29#endif /* ifndef __INC_HAL8723U_FW_IMG_H */
diff --git a/drivers/staging/rtl8723au/include/HalDMOutSrc8723A.h b/drivers/staging/rtl8723au/include/HalDMOutSrc8723A.h
new file mode 100644
index 000000000000..d7651f7a665b
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/HalDMOutSrc8723A.h
@@ -0,0 +1,64 @@
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 *
15 ******************************************************************************/
16#ifndef __RTL8723A_ODM_H__
17#define __RTL8723A_ODM_H__
18/* */
19
20#define RSSI_CCK 0
21#define RSSI_OFDM 1
22#define RSSI_DEFAULT 2
23
24#define IQK_MAC_REG_NUM 4
25#define IQK_ADDA_REG_NUM 16
26#define IQK_BB_REG_NUM 9
27#define HP_THERMAL_NUM 8
28
29
30/* */
31/* structure and define */
32/* */
33
34
35
36
37/*------------------------Export global variable----------------------------*/
38/*------------------------Export global variable----------------------------*/
39/*------------------------Export Marco Definition---------------------------*/
40/* define DM_MultiSTA_InitGainChangeNotify(Event) {DM_DigTable.CurMultiSTAConnectState = Event;} */
41
42
43/* */
44/* function prototype */
45/* */
46
47/* */
48/* IQ calibrate */
49/* */
50void rtl8723a_phy_iq_calibrate(struct rtw_adapter *pAdapter, bool bReCovery);
51
52/* */
53/* LC calibrate */
54/* */
55void rtl8723a_phy_lc_calibrate(struct rtw_adapter *pAdapter);
56
57/* */
58/* AP calibrate */
59/* */
60void rtl8723a_phy_ap_calibrate(struct rtw_adapter *pAdapter, char delta);
61
62void rtl8723a_odm_check_tx_power_tracking(struct rtw_adapter *Adapter);
63
64#endif
diff --git a/drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h b/drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h
new file mode 100644
index 000000000000..e99833cc7929
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/HalHWImg8723A_BB.h
@@ -0,0 +1,44 @@
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*
15******************************************************************************/
16
17#ifndef __INC_BB_8723A_HW_IMG_H
18#define __INC_BB_8723A_HW_IMG_H
19
20/******************************************************************************
21* AGC_TAB_1T.TXT
22******************************************************************************/
23
24void ODM_ReadAndConfig_AGC_TAB_1T_8723A(struct dm_odm_t *pDM_Odm);
25
26/******************************************************************************
27* PHY_REG_1T.TXT
28******************************************************************************/
29
30void ODM_ReadAndConfig_PHY_REG_1T_8723A(struct dm_odm_t *pDM_Odm);
31
32/******************************************************************************
33* PHY_REG_MP.TXT
34******************************************************************************/
35
36void ODM_ReadAndConfig_PHY_REG_MP_8723A(struct dm_odm_t *pDM_Odm);
37
38/******************************************************************************
39* PHY_REG_PG.TXT
40******************************************************************************/
41
42void ODM_ReadAndConfig_PHY_REG_PG_8723A(struct dm_odm_t *pDM_Odm);
43
44#endif /* end of HWIMG_SUPPORT */
diff --git a/drivers/staging/rtl8723au/include/HalHWImg8723A_FW.h b/drivers/staging/rtl8723au/include/HalHWImg8723A_FW.h
new file mode 100644
index 000000000000..7ee363b99b49
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/HalHWImg8723A_FW.h
@@ -0,0 +1,28 @@
1/******************************************************************************
2*
3* Copyright(c) 2007 - 2012 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*
15******************************************************************************/
16
17#ifndef __INC_FW_8723A_HW_IMG_H
18#define __INC_FW_8723A_HW_IMG_H
19
20
21/******************************************************************************
22* rtl8723fw_B.TXT
23******************************************************************************/
24
25void ODM_ReadFirmware_8723A_rtl8723fw_B(struct dm_odm_t *pDM_Odm,
26 u8 *pFirmware, u32 *pFirmwareSize);
27
28#endif /* end of HWIMG_SUPPORT */
diff --git a/drivers/staging/rtl8723au/include/HalHWImg8723A_MAC.h b/drivers/staging/rtl8723au/include/HalHWImg8723A_MAC.h
new file mode 100644
index 000000000000..201be1f87292
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/HalHWImg8723A_MAC.h
@@ -0,0 +1,26 @@
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*
15******************************************************************************/
16
17#ifndef __INC_MAC_8723A_HW_IMG_H
18#define __INC_MAC_8723A_HW_IMG_H
19
20/******************************************************************************
21* MAC_REG.TXT
22******************************************************************************/
23
24void ODM_ReadAndConfig_MAC_REG_8723A(struct dm_odm_t *pDM_Odm);
25
26#endif /* end of HWIMG_SUPPORT */
diff --git a/drivers/staging/rtl8723au/include/HalHWImg8723A_RF.h b/drivers/staging/rtl8723au/include/HalHWImg8723A_RF.h
new file mode 100644
index 000000000000..c9af1c375339
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/HalHWImg8723A_RF.h
@@ -0,0 +1,25 @@
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******************************************************************************/
15
16#ifndef __INC_RF_8723A_HW_IMG_H
17#define __INC_RF_8723A_HW_IMG_H
18
19/******************************************************************************
20* RadioA_1T.TXT
21******************************************************************************/
22
23void ODM_ReadAndConfig_RadioA_1T_8723A(struct dm_odm_t *pDM_Odm);
24
25#endif /* end of HWIMG_SUPPORT */
diff --git a/drivers/staging/rtl8723au/include/HalPwrSeqCmd.h b/drivers/staging/rtl8723au/include/HalPwrSeqCmd.h
new file mode 100644
index 000000000000..12e03a36f2d3
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/HalPwrSeqCmd.h
@@ -0,0 +1,130 @@
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 *
15 ******************************************************************************/
16#ifndef __HALPWRSEQCMD_H__
17#define __HALPWRSEQCMD_H__
18
19#include <drv_types.h>
20
21/*---------------------------------------------*/
22/*---------------------------------------------*/
23#define PWR_CMD_READ 0x00
24 /* offset: the read register offset */
25 /* msk: the mask of the read value */
26 /* value: N/A, left by 0 */
27 /* note: dirver shall implement this function by read & msk */
28
29#define PWR_CMD_WRITE 0x01
30 /* offset: the read register offset */
31 /* msk: the mask of the write bits */
32 /* value: write value */
33 /* note: driver shall implement this cmd by read & msk after write */
34
35#define PWR_CMD_POLLING 0x02
36 /* offset: the read register offset */
37 /* msk: the mask of the polled value */
38 /* value: the value to be polled, masked by the msd field. */
39 /* note: driver shall implement this cmd by */
40 /* do{ */
41 /* if( (Read(offset) & msk) == (value & msk) ) */
42 /* break; */
43 /* } while(not timeout); */
44
45#define PWR_CMD_DELAY 0x03
46 /* offset: the value to delay */
47 /* msk: N/A */
48 /* value: the unit of delay, 0: us, 1: ms */
49
50#define PWR_CMD_END 0x04
51 /* offset: N/A */
52 /* msk: N/A */
53 /* value: N/A */
54
55/*---------------------------------------------*/
56/* 3 The value of base: 4 bits */
57/*---------------------------------------------*/
58 /* define the base address of each block */
59#define PWR_BASEADDR_MAC 0x00
60#define PWR_BASEADDR_USB 0x01
61#define PWR_BASEADDR_PCIE 0x02
62#define PWR_BASEADDR_SDIO 0x03
63
64/*---------------------------------------------*/
65/* 3 The value of interface_msk: 4 bits */
66/*---------------------------------------------*/
67#define PWR_INTF_SDIO_MSK BIT(0)
68#define PWR_INTF_USB_MSK BIT(1)
69#define PWR_INTF_PCI_MSK BIT(2)
70#define PWR_INTF_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3))
71
72/*---------------------------------------------*/
73/* 3 The value of fab_msk: 4 bits */
74/*---------------------------------------------*/
75#define PWR_FAB_TSMC_MSK BIT(0)
76#define PWR_FAB_UMC_MSK BIT(1)
77#define PWR_FAB_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3))
78
79/*---------------------------------------------*/
80/* 3 The value of cut_msk: 8 bits */
81/*---------------------------------------------*/
82#define PWR_CUT_TESTCHIP_MSK BIT(0)
83#define PWR_CUT_A_MSK BIT(1)
84#define PWR_CUT_B_MSK BIT(2)
85#define PWR_CUT_C_MSK BIT(3)
86#define PWR_CUT_D_MSK BIT(4)
87#define PWR_CUT_E_MSK BIT(5)
88#define PWR_CUT_F_MSK BIT(6)
89#define PWR_CUT_G_MSK BIT(7)
90#define PWR_CUT_ALL_MSK 0xFF
91
92
93enum pwrseq_delay_unit {
94 PWRSEQ_DELAY_US,
95 PWRSEQ_DELAY_MS,
96};
97
98struct wlan_pwr_cfg {
99 u16 offset;
100 u8 cut_msk;
101 u8 fab_msk:4;
102 u8 interface_msk:4;
103 u8 base:4;
104 u8 cmd:4;
105 u8 msk;
106 u8 value;
107};
108
109
110#define GET_PWR_CFG_OFFSET(__PWR_CMD) __PWR_CMD.offset
111#define GET_PWR_CFG_CUT_MASK(__PWR_CMD) __PWR_CMD.cut_msk
112#define GET_PWR_CFG_FAB_MASK(__PWR_CMD) __PWR_CMD.fab_msk
113#define GET_PWR_CFG_INTF_MASK(__PWR_CMD) __PWR_CMD.interface_msk
114#define GET_PWR_CFG_BASE(__PWR_CMD) __PWR_CMD.base
115#define GET_PWR_CFG_CMD(__PWR_CMD) __PWR_CMD.cmd
116#define GET_PWR_CFG_MASK(__PWR_CMD) __PWR_CMD.msk
117#define GET_PWR_CFG_VALUE(__PWR_CMD) __PWR_CMD.value
118
119
120/* */
121/* Prototype of protected function. */
122/* */
123u8 HalPwrSeqCmdParsing23a(
124 struct rtw_adapter *padapter,
125 u8 CutVersion,
126 u8 FabVersion,
127 u8 InterfaceType,
128 struct wlan_pwr_cfg PwrCfgCmd[]);
129
130#endif
diff --git a/drivers/staging/rtl8723au/include/HalVerDef.h b/drivers/staging/rtl8723au/include/HalVerDef.h
new file mode 100644
index 000000000000..607b71f6e1e4
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/HalVerDef.h
@@ -0,0 +1,136 @@
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 ******************************************************************************/
15#ifndef __HAL_VERSION_DEF_H__
16#define __HAL_VERSION_DEF_H__
17
18enum hal_ic_type {
19 CHIP_8192S = 0,
20 CHIP_8188C = 1,
21 CHIP_8192C = 2,
22 CHIP_8192D = 3,
23 CHIP_8723A = 4,
24 CHIP_8188E = 5,
25 CHIP_8881A = 6,
26 CHIP_8812A = 7,
27 CHIP_8821A = 8,
28 CHIP_8723B = 9,
29 CHIP_8192E = 10,
30};
31
32enum hal_chip_type {
33 TEST_CHIP = 0,
34 NORMAL_CHIP = 1,
35 FPGA = 2,
36};
37
38enum hal_cut_version {
39 A_CUT_VERSION = 0,
40 B_CUT_VERSION = 1,
41 C_CUT_VERSION = 2,
42 D_CUT_VERSION = 3,
43 E_CUT_VERSION = 4,
44 F_CUT_VERSION = 5,
45 G_CUT_VERSION = 6,
46};
47
48/* HAL_Manufacturer */
49enum hal_vendor {
50 CHIP_VENDOR_TSMC = 0,
51 CHIP_VENDOR_UMC = 1,
52};
53
54enum hal_rf_type {
55 RF_TYPE_1T1R = 0,
56 RF_TYPE_1T2R = 1,
57 RF_TYPE_2T2R = 2,
58 RF_TYPE_2T3R = 3,
59 RF_TYPE_2T4R = 4,
60 RF_TYPE_3T3R = 5,
61 RF_TYPE_3T4R = 6,
62 RF_TYPE_4T4R = 7,
63};
64
65struct hal_version {
66 enum hal_ic_type ICType;
67 enum hal_chip_type ChipType;
68 enum hal_cut_version CUTVersion;
69 enum hal_vendor VendorType;
70 enum hal_rf_type RFType;
71 u8 ROMVer;
72};
73
74/* Get element */
75#define GET_CVID_IC_TYPE(version) ((version).ICType)
76#define GET_CVID_CHIP_TYPE(version) ((version).ChipType)
77#define GET_CVID_RF_TYPE(version) ((version).RFType)
78#define GET_CVID_MANUFACTUER(version) ((version).VendorType)
79#define GET_CVID_CUT_VERSION(version) ((version).CUTVersion)
80#define GET_CVID_ROM_VERSION(version) (((version).ROMVer) & ROM_VERSION_MASK)
81
82/* Common Macro. -- */
83
84#define IS_81XXC(version) \
85 (((GET_CVID_IC_TYPE(version) == CHIP_8192C) || \
86 (GET_CVID_IC_TYPE(version) == CHIP_8188C)) ? true : false)
87#define IS_8723_SERIES(version) \
88 ((GET_CVID_IC_TYPE(version) == CHIP_8723A) ? true : false)
89
90#define IS_TEST_CHIP(version) \
91 ((GET_CVID_CHIP_TYPE(version) == TEST_CHIP) ? true : false)
92#define IS_NORMAL_CHIP(version) \
93 ((GET_CVID_CHIP_TYPE(version) == NORMAL_CHIP) ? true : false)
94
95#define IS_A_CUT(version) \
96 ((GET_CVID_CUT_VERSION(version) == A_CUT_VERSION) ? true : false)
97#define IS_B_CUT(version) \
98 ((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? true : false)
99#define IS_C_CUT(version) \
100 ((GET_CVID_CUT_VERSION(version) == C_CUT_VERSION) ? true : false)
101#define IS_D_CUT(version) \
102 ((GET_CVID_CUT_VERSION(version) == D_CUT_VERSION) ? true : false)
103#define IS_E_CUT(version) \
104 ((GET_CVID_CUT_VERSION(version) == E_CUT_VERSION) ? true : false)
105
106#define IS_CHIP_VENDOR_TSMC(version) \
107 ((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_TSMC) ? true : false)
108#define IS_CHIP_VENDOR_UMC(version) \
109 ((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_UMC) ? true : false)
110
111#define IS_1T1R(version) \
112 ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T1R) ? true : false)
113#define IS_1T2R(version) \
114 ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R) ? true : false)
115#define IS_2T2R(version) \
116 ((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R) ? true : false)
117
118/* Chip version Macro. -- */
119
120#define IS_92C_SERIAL(version) \
121 ((IS_81XXC(version) && IS_2T2R(version)) ? true : false)
122#define IS_81xxC_VENDOR_UMC_A_CUT(version) \
123 (IS_81XXC(version)?(IS_CHIP_VENDOR_UMC(version) ? \
124 (IS_A_CUT(version) ? true : false) : false) : false)
125#define IS_81xxC_VENDOR_UMC_B_CUT(version) \
126 (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \
127 (IS_B_CUT(version) ? true : false) : false): false)
128#define IS_81xxC_VENDOR_UMC_C_CUT(version) \
129 (IS_81XXC(version)?(IS_CHIP_VENDOR_UMC(version) ? \
130 (IS_C_CUT(version) ? true : false) : false) : false)
131#define IS_8723A_A_CUT(version) \
132 ((IS_8723_SERIES(version)) ? (IS_A_CUT(version) ? true : false) : false)
133#define IS_8723A_B_CUT(version) \
134 ((IS_8723_SERIES(version)) ? (IS_B_CUT(version) ? true : false) : false)
135
136#endif
diff --git a/drivers/staging/rtl8723au/include/cmd_osdep.h b/drivers/staging/rtl8723au/include/cmd_osdep.h
new file mode 100644
index 000000000000..4866bee04054
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/cmd_osdep.h
@@ -0,0 +1,26 @@
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 ******************************************************************************/
15#ifndef __CMD_OSDEP_H_
16#define __CMD_OSDEP_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21int _rtw_init_evt_priv23a(struct evt_priv *pevtpriv);
22void _rtw_free_evt_priv23a(struct evt_priv *pevtpriv);
23void _rtw_free_cmd_priv23a(struct cmd_priv *pcmdpriv);
24int _rtw_enqueue_cmd23a(struct rtw_queue *queue, struct cmd_obj *obj);
25
26#endif
diff --git a/drivers/staging/rtl8723au/include/drv_types.h b/drivers/staging/rtl8723au/include/drv_types.h
new file mode 100644
index 000000000000..53eecea48cec
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/drv_types.h
@@ -0,0 +1,360 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15/*-----------------------------------------------------------------------------
16
17 For type defines and data structure defines
18
19------------------------------------------------------------------------------*/
20
21
22#ifndef __DRV_TYPES_H__
23#define __DRV_TYPES_H__
24
25#include <osdep_service.h>
26#include <wlan_bssdef.h>
27
28
29enum _NIC_VERSION {
30 RTL8711_NIC,
31 RTL8712_NIC,
32 RTL8713_NIC,
33 RTL8716_NIC
34
35};
36
37
38#include <rtw_ht.h>
39
40#include <rtw_cmd.h>
41#include <wlan_bssdef.h>
42#include <rtw_xmit.h>
43#include <rtw_recv.h>
44#include <hal_intf.h>
45#include <hal_com.h>
46#include <rtw_qos.h>
47#include <rtw_security.h>
48#include <rtw_pwrctrl.h>
49#include <rtw_io.h>
50#include <rtw_eeprom.h>
51#include <sta_info.h>
52#include <rtw_mlme.h>
53#include <rtw_debug.h>
54#include <rtw_rf.h>
55#include <rtw_event.h>
56#include <rtw_led.h>
57#include <rtw_mlme_ext.h>
58#include <rtw_p2p.h>
59#include <rtw_ap.h>
60
61#include "ioctl_cfg80211.h"
62
63#define SPEC_DEV_ID_NONE BIT(0)
64#define SPEC_DEV_ID_DISABLE_HT BIT(1)
65#define SPEC_DEV_ID_ENABLE_PS BIT(2)
66#define SPEC_DEV_ID_RF_CONFIG_1T1R BIT(3)
67#define SPEC_DEV_ID_RF_CONFIG_2T2R BIT(4)
68#define SPEC_DEV_ID_ASSIGN_IFNAME BIT(5)
69
70struct specific_device_id {
71 u32 flags;
72
73 u16 idVendor;
74 u16 idProduct;
75
76};
77
78struct registry_priv {
79 u8 chip_version;
80 u8 rfintfs;
81 struct cfg80211_ssid ssid;
82 u8 channel;/* ad-hoc support requirement */
83 u8 wireless_mode;/* A, B, G, auto */
84 u8 scan_mode;/* active, passive */
85 u8 preamble;/* long, short, auto */
86 u8 vrtl_carrier_sense;/* Enable, Disable, Auto */
87 u8 vcs_type;/* RTS/CTS, CTS-to-self */
88 u16 rts_thresh;
89 u16 frag_thresh;
90 u8 adhoc_tx_pwr;
91 u8 soft_ap;
92 u8 power_mgnt;
93 u8 ips_mode;
94 u8 smart_ps;
95 u8 long_retry_lmt;
96 u8 short_retry_lmt;
97 u16 busy_thresh;
98 u8 ack_policy;
99 u8 software_encrypt;
100 u8 software_decrypt;
101 u8 acm_method;
102 /* UAPSD */
103 u8 wmm_enable;
104 u8 uapsd_enable;
105
106 struct wlan_bssid_ex dev_network;
107
108 u8 ht_enable;
109 u8 cbw40_enable;
110 u8 ampdu_enable;/* for tx */
111 u8 rx_stbc;
112 u8 ampdu_amsdu;/* A-MPDU Supports A-MSDU is permitted */
113 u8 lowrate_two_xmit;
114
115 u8 rf_config;
116 u8 low_power;
117
118 u8 wifi_spec;/* !turbo_mode */
119
120 u8 channel_plan;
121#ifdef CONFIG_8723AU_BT_COEXIST
122 u8 btcoex;
123 u8 bt_iso;
124 u8 bt_sco;
125 u8 bt_ampdu;
126#endif
127 bool bAcceptAddbaReq;
128
129 u8 antdiv_cfg;
130 u8 antdiv_type;
131
132 u8 usbss_enable;/* 0:disable,1:enable */
133 u8 hwpdn_mode;/* 0:disable,1:enable,2:decide by EFUSE config */
134 u8 hwpwrp_detect;/* 0:disable,1:enable */
135
136 u8 hw_wps_pbc;/* 0:disable,1:enable */
137
138 u8 max_roaming_times; /* max number driver will try to roaming */
139
140 u8 enable80211d;
141
142 u8 ifname[16];
143 u8 if2name[16];
144
145 u8 notch_filter;
146
147 u8 regulatory_tid;
148};
149
150
151#define MAX_CONTINUAL_URB_ERR 4
152
153#define GET_PRIMARY_ADAPTER(padapter) \
154 (((struct rtw_adapter *)padapter)->dvobj->if1)
155
156enum _IFACE_ID {
157 IFACE_ID0, /* maping to PRIMARY_ADAPTER */
158 IFACE_ID1, /* maping to SECONDARY_ADAPTER */
159 IFACE_ID2,
160 IFACE_ID3,
161 IFACE_ID_MAX,
162};
163
164struct dvobj_priv {
165 struct rtw_adapter *if1; /* PRIMARY_ADAPTER */
166 struct rtw_adapter *if2; /* SECONDARY_ADAPTER */
167
168 /* for local/global synchronization */
169 struct mutex hw_init_mutex;
170 struct mutex h2c_fwcmd_mutex;
171 struct mutex setch_mutex;
172 struct mutex setbw_mutex;
173
174 unsigned char oper_channel; /* saved chan info when set chan bw */
175 unsigned char oper_bwmode;
176 unsigned char oper_ch_offset;/* PRIME_CHNL_OFFSET */
177
178 struct rtw_adapter *padapters[IFACE_ID_MAX];
179 u8 iface_nums; /* total number of ifaces used runtime */
180
181 /* For 92D, DMDP have 2 interface. */
182 u8 InterfaceNumber;
183 u8 NumInterfaces;
184
185 /* In /Out Pipe information */
186 int RtInPipe[2];
187 int RtOutPipe[3];
188 u8 Queue2Pipe[HW_QUEUE_ENTRY];/* for out pipe mapping */
189
190 u8 irq_alloc;
191
192/*-------- below is for USB INTERFACE --------*/
193
194 u8 nr_endpoint;
195 u8 ishighspeed;
196 u8 RtNumInPipes;
197 u8 RtNumOutPipes;
198 int ep_num[5]; /* endpoint number */
199
200 int RegUsbSS;
201
202 struct semaphore usb_suspend_sema;
203
204 struct mutex usb_vendor_req_mutex;
205
206 u8 *usb_alloc_vendor_req_buf;
207 u8 *usb_vendor_req_buf;
208
209 struct usb_interface *pusbintf;
210 struct usb_device *pusbdev;
211 atomic_t continual_urb_error;
212
213/*-------- below is for PCIE INTERFACE --------*/
214
215};
216
217static inline struct device *dvobj_to_dev(struct dvobj_priv *dvobj)
218{
219 /* todo: get interface type from dvobj and the return the dev accordingly */
220 return &dvobj->pusbintf->dev;
221}
222
223enum _IFACE_TYPE {
224 IFACE_PORT0, /* mapping to port0 for C/D series chips */
225 IFACE_PORT1, /* mapping to port1 for C/D series chip */
226 MAX_IFACE_PORT,
227};
228
229enum _ADAPTER_TYPE {
230 PRIMARY_ADAPTER,
231 SECONDARY_ADAPTER,
232 MAX_ADAPTER,
233};
234
235struct rtw_adapter {
236 int pid[3];/* process id from UI, 0:wps, 1:hostapd, 2:dhcpcd */
237 int bDongle;/* build-in module or external dongle */
238 u16 chip_type;
239 u16 HardwareType;
240
241 struct dvobj_priv *dvobj;
242 struct mlme_priv mlmepriv;
243 struct mlme_ext_priv mlmeextpriv;
244 struct cmd_priv cmdpriv;
245 struct evt_priv evtpriv;
246 /* struct io_queue *pio_queue; */
247 struct io_priv iopriv;
248 struct xmit_priv xmitpriv;
249 struct recv_priv recvpriv;
250 struct sta_priv stapriv;
251 struct security_priv securitypriv;
252 struct registry_priv registrypriv;
253 struct pwrctrl_priv pwrctrlpriv;
254 struct eeprom_priv eeprompriv;
255 struct led_priv ledpriv;
256
257#ifdef CONFIG_8723AU_AP_MODE
258 struct hostapd_priv *phostapdpriv;
259#endif
260
261 struct cfg80211_wifidirect_info cfg80211_wdinfo;
262 u32 setband;
263 struct wifidirect_info wdinfo;
264
265#ifdef CONFIG_8723AU_P2P
266 struct wifi_display_info wfd_info;
267#endif /* CONFIG_8723AU_P2P */
268
269 void *HalData;
270 u32 hal_data_sz;
271 struct hal_ops HalFunc;
272
273 s32 bDriverStopped;
274 s32 bSurpriseRemoved;
275 s32 bCardDisableWOHSM;
276
277 u32 IsrContent;
278 u32 ImrContent;
279
280 u8 EepromAddressSize;
281 u8 hw_init_completed;
282 u8 bDriverIsGoingToUnload;
283 u8 init_adpt_in_progress;
284 u8 bHaltInProgress;
285
286 void *cmdThread;
287 void *evtThread;
288 void *xmitThread;
289 void *recvThread;
290
291 void (*intf_start)(struct rtw_adapter *adapter);
292 void (*intf_stop)(struct rtw_adapter *adapter);
293
294 struct net_device *pnetdev;
295
296 /* used by rtw_rereg_nd_name related function */
297 struct rereg_nd_name_data {
298 struct net_device *old_pnetdev;
299 char old_ifname[IFNAMSIZ];
300 u8 old_ips_mode;
301 u8 old_bRegUseLed;
302 } rereg_nd_name_priv;
303
304 int bup;
305 struct net_device_stats stats;
306 struct iw_statistics iwstats;
307 struct proc_dir_entry *dir_dev;/* for proc directory */
308
309 struct wireless_dev *rtw_wdev;
310 int net_closed;
311
312 u8 bFWReady;
313 u8 bBTFWReady;
314 u8 bReadPortCancel;
315 u8 bWritePortCancel;
316 u8 bRxRSSIDisplay;
317 /* The driver will show the desired chan nor when this flag is 1. */
318 u8 bNotifyChannelChange;
319#ifdef CONFIG_8723AU_P2P
320 /* driver will show current P2P status when the application reads it*/
321 u8 bShowGetP2PState;
322#endif
323 struct rtw_adapter *pbuddy_adapter;
324
325 /* extend to support multi interface */
326 /* IFACE_ID0 is equals to PRIMARY_ADAPTER */
327 /* IFACE_ID1 is equals to SECONDARY_ADAPTER */
328 u8 iface_id;
329
330#ifdef CONFIG_BR_EXT
331 _lock br_ext_lock;
332 /* unsigned int macclone_completed; */
333 struct nat25_network_db_entry *nethash[NAT25_HASH_SIZE];
334 int pppoe_connection_in_progress;
335 unsigned char pppoe_addr[MACADDRLEN];
336 unsigned char scdb_mac[MACADDRLEN];
337 unsigned char scdb_ip[4];
338 struct nat25_network_db_entry *scdb_entry;
339 unsigned char br_mac[MACADDRLEN];
340 unsigned char br_ip[4];
341
342 struct br_ext_info ethBrExtInfo;
343#endif /* CONFIG_BR_EXT */
344
345 u8 fix_rate;
346
347 unsigned char in_cta_test;
348
349};
350
351#define adapter_to_dvobj(adapter) (adapter->dvobj)
352
353int rtw_handle_dualmac23a(struct rtw_adapter *adapter, bool init);
354
355static inline u8 *myid(struct eeprom_priv *peepriv)
356{
357 return peepriv->mac_addr;
358}
359
360#endif /* __DRV_TYPES_H__ */
diff --git a/drivers/staging/rtl8723au/include/ethernet.h b/drivers/staging/rtl8723au/include/ethernet.h
new file mode 100644
index 000000000000..39fc6df88188
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/ethernet.h
@@ -0,0 +1,22 @@
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 *
15 ******************************************************************************/
16/*! \file */
17#ifndef __INC_ETHERNET_H
18#define __INC_ETHERNET_H
19
20#define LLC_HEADER_SIZE 6 /* LLC Header Length */
21
22#endif /* #ifndef __INC_ETHERNET_H */
diff --git a/drivers/staging/rtl8723au/include/hal_com.h b/drivers/staging/rtl8723au/include/hal_com.h
new file mode 100644
index 000000000000..20f983cfc2b7
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/hal_com.h
@@ -0,0 +1,211 @@
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 ******************************************************************************/
15#ifndef __HAL_COMMON_H__
16#define __HAL_COMMON_H__
17
18/* */
19/* Rate Definition */
20/* */
21/* CCK */
22#define RATR_1M 0x00000001
23#define RATR_2M 0x00000002
24#define RATR_55M 0x00000004
25#define RATR_11M 0x00000008
26/* OFDM */
27#define RATR_6M 0x00000010
28#define RATR_9M 0x00000020
29#define RATR_12M 0x00000040
30#define RATR_18M 0x00000080
31#define RATR_24M 0x00000100
32#define RATR_36M 0x00000200
33#define RATR_48M 0x00000400
34#define RATR_54M 0x00000800
35/* MCS 1 Spatial Stream */
36#define RATR_MCS0 0x00001000
37#define RATR_MCS1 0x00002000
38#define RATR_MCS2 0x00004000
39#define RATR_MCS3 0x00008000
40#define RATR_MCS4 0x00010000
41#define RATR_MCS5 0x00020000
42#define RATR_MCS6 0x00040000
43#define RATR_MCS7 0x00080000
44/* MCS 2 Spatial Stream */
45#define RATR_MCS8 0x00100000
46#define RATR_MCS9 0x00200000
47#define RATR_MCS10 0x00400000
48#define RATR_MCS11 0x00800000
49#define RATR_MCS12 0x01000000
50#define RATR_MCS13 0x02000000
51#define RATR_MCS14 0x04000000
52#define RATR_MCS15 0x08000000
53
54/* CCK */
55#define RATE_1M BIT(0)
56#define RATE_2M BIT(1)
57#define RATE_5_5M BIT(2)
58#define RATE_11M BIT(3)
59/* OFDM */
60#define RATE_6M BIT(4)
61#define RATE_9M BIT(5)
62#define RATE_12M BIT(6)
63#define RATE_18M BIT(7)
64#define RATE_24M BIT(8)
65#define RATE_36M BIT(9)
66#define RATE_48M BIT(10)
67#define RATE_54M BIT(11)
68/* MCS 1 Spatial Stream */
69#define RATE_MCS0 BIT(12)
70#define RATE_MCS1 BIT(13)
71#define RATE_MCS2 BIT(14)
72#define RATE_MCS3 BIT(15)
73#define RATE_MCS4 BIT(16)
74#define RATE_MCS5 BIT(17)
75#define RATE_MCS6 BIT(18)
76#define RATE_MCS7 BIT(19)
77/* MCS 2 Spatial Stream */
78#define RATE_MCS8 BIT(20)
79#define RATE_MCS9 BIT(21)
80#define RATE_MCS10 BIT(22)
81#define RATE_MCS11 BIT(23)
82#define RATE_MCS12 BIT(24)
83#define RATE_MCS13 BIT(25)
84#define RATE_MCS14 BIT(26)
85#define RATE_MCS15 BIT(27)
86
87/* ALL CCK Rate */
88#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M)
89#define RATE_ALL_OFDM_AG \
90 (RATR_6M | RATR_9M | RATR_12M | RATR_18M | RATR_24M| \
91 RATR_36M|RATR_48M|RATR_54M)
92#define RATE_ALL_OFDM_1SS \
93 (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | RATR_MCS3 | \
94 RATR_MCS4 | RATR_MCS5 | RATR_MCS6 | RATR_MCS7)
95#define RATE_ALL_OFDM_2SS \
96 (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | RATR_MCS11| \
97 RATR_MCS12 | RATR_MCS13 | RATR_MCS14 | RATR_MCS15)
98
99/*------------------------------ Tx Desc definition Macro ------------------------*/
100/* pragma mark -- Tx Desc related definition. -- */
101/* */
102/* */
103/* Rate */
104/* */
105/* CCK Rates, TxHT = 0 */
106#define DESC_RATE1M 0x00
107#define DESC_RATE2M 0x01
108#define DESC_RATE5_5M 0x02
109#define DESC_RATE11M 0x03
110
111/* OFDM Rates, TxHT = 0 */
112#define DESC_RATE6M 0x04
113#define DESC_RATE9M 0x05
114#define DESC_RATE12M 0x06
115#define DESC_RATE18M 0x07
116#define DESC_RATE24M 0x08
117#define DESC_RATE36M 0x09
118#define DESC_RATE48M 0x0a
119#define DESC_RATE54M 0x0b
120
121/* MCS Rates, TxHT = 1 */
122#define DESC_RATEMCS0 0x0c
123#define DESC_RATEMCS1 0x0d
124#define DESC_RATEMCS2 0x0e
125#define DESC_RATEMCS3 0x0f
126#define DESC_RATEMCS4 0x10
127#define DESC_RATEMCS5 0x11
128#define DESC_RATEMCS6 0x12
129#define DESC_RATEMCS7 0x13
130#define DESC_RATEMCS8 0x14
131#define DESC_RATEMCS9 0x15
132#define DESC_RATEMCS10 0x16
133#define DESC_RATEMCS11 0x17
134#define DESC_RATEMCS12 0x18
135#define DESC_RATEMCS13 0x19
136#define DESC_RATEMCS14 0x1a
137#define DESC_RATEMCS15 0x1b
138#define DESC_RATEMCS15_SG 0x1c
139#define DESC_RATEMCS32 0x20
140
141#define REG_P2P_CTWIN 0x0572 /* 1 Byte long (in unit of TU) */
142#define REG_NOA_DESC_SEL 0x05CF
143#define REG_NOA_DESC_DURATION 0x05E0
144#define REG_NOA_DESC_INTERVAL 0x05E4
145#define REG_NOA_DESC_START 0x05E8
146#define REG_NOA_DESC_COUNT 0x05EC
147
148#include "HalVerDef.h"
149void dump_chip_info23a(struct hal_version ChipVersion);
150
151
152u8 /* return the final channel plan decision */
153hal_com_get_channel_plan23a(
154 struct rtw_adapter *padapter,
155 u8 hw_channel_plan, /* channel plan from HW (efuse/eeprom) */
156 u8 sw_channel_plan, /* channel plan from SW (registry/module param) */
157 u8 def_channel_plan, /* channel plan used when the former two is invalid */
158 bool AutoLoadFail
159 );
160
161u8 MRateToHwRate23a(u8 rate);
162
163void HalSetBrateCfg23a(struct rtw_adapter *padapter, u8 *mBratesOS);
164
165bool
166Hal_MappingOutPipe23a(struct rtw_adapter *pAdapter, u8 NumOutPipe);
167
168void hal_init_macaddr23a(struct rtw_adapter *adapter);
169
170void c2h_evt_clear23a(struct rtw_adapter *adapter);
171s32 c2h_evt_read23a(struct rtw_adapter *adapter, u8 *buf);
172
173void rtl8723a_set_ampdu_min_space(struct rtw_adapter *padapter, u8 MinSpacingToSet);
174void rtl8723a_set_ampdu_factor(struct rtw_adapter *padapter, u8 FactorToSet);
175void rtl8723a_set_acm_ctrl(struct rtw_adapter *padapter, u8 ctrl);
176void rtl8723a_set_media_status(struct rtw_adapter *padapter, u8 status);
177void rtl8723a_set_media_status1(struct rtw_adapter *padapter, u8 status);
178void rtl8723a_set_bcn_func(struct rtw_adapter *padapter, u8 val);
179void rtl8723a_check_bssid(struct rtw_adapter *padapter, u8 val);
180void rtl8723a_mlme_sitesurvey(struct rtw_adapter *padapter, u8 flag);
181void rtl8723a_on_rcr_am(struct rtw_adapter *padapter);
182void rtl8723a_off_rcr_am(struct rtw_adapter *padapter);
183void rtl8723a_set_slot_time(struct rtw_adapter *padapter, u8 slottime);
184void rtl8723a_ack_preamble(struct rtw_adapter *padapter, u8 bShortPreamble);
185void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec);
186void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex);
187void rtl8723a_cam_invalid_all(struct rtw_adapter *padapter);
188void rtl8723a_cam_write(struct rtw_adapter *padapter, u32 val1, u32 val2);
189void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter);
190void rtl8723a_set_apfm_on_mac(struct rtw_adapter *padapter, u8 val);
191void rtl8723a_bcn_valid(struct rtw_adapter *padapter);
192void rtl8723a_set_tx_pause(struct rtw_adapter *padapter, u8 pause);
193void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval);
194void rtl8723a_set_resp_sifs(struct rtw_adapter *padapter,
195 u8 r2t1, u8 r2t2, u8 t2t1, u8 t2t2);
196void rtl8723a_set_ac_param_vo(struct rtw_adapter *padapter, u32 vo);
197void rtl8723a_set_ac_param_vi(struct rtw_adapter *padapter, u32 vi);
198void rtl8723a_set_ac_param_be(struct rtw_adapter *padapter, u32 be);
199void rtl8723a_set_ac_param_bk(struct rtw_adapter *padapter, u32 bk);
200void rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter *padapter, u8 val);
201void rtl8723a_set_nav_upper(struct rtw_adapter *padapter, u32 usNavUpper);
202void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain);
203
204void rtl8723a_odm_support_ability_write(struct rtw_adapter *padapter, u32 val);
205void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter, u8 val);
206void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val);
207void rtl8723a_odm_support_ability_clr(struct rtw_adapter *padapter, u32 val);
208
209void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val);
210
211#endif /* __HAL_COMMON_H__ */
diff --git a/drivers/staging/rtl8723au/include/hal_intf.h b/drivers/staging/rtl8723au/include/hal_intf.h
new file mode 100644
index 000000000000..d183f4ba1ecb
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/hal_intf.h
@@ -0,0 +1,392 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#ifndef __HAL_INTF_H__
16#define __HAL_INTF_H__
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21enum RTL871X_HCI_TYPE {
22 RTW_PCIE = BIT0,
23 RTW_USB = BIT1,
24 RTW_SDIO = BIT2,
25 RTW_GSPI = BIT3,
26};
27
28enum _CHIP_TYPE {
29 NULL_CHIP_TYPE,
30 RTL8712_8188S_8191S_8192S,
31 RTL8188C_8192C,
32 RTL8192D,
33 RTL8723A,
34 RTL8188E,
35 MAX_CHIP_TYPE
36};
37
38enum HW_VARIABLES {
39 HW_VAR_MEDIA_STATUS,
40 HW_VAR_MEDIA_STATUS1,
41 HW_VAR_SET_OPMODE,
42 HW_VAR_MAC_ADDR,
43 HW_VAR_BSSID,
44 HW_VAR_INIT_RTS_RATE,
45 HW_VAR_BASIC_RATE,
46 HW_VAR_TXPAUSE,
47 HW_VAR_BCN_FUNC,
48 HW_VAR_CORRECT_TSF,
49 HW_VAR_CHECK_BSSID,
50 HW_VAR_MLME_DISCONNECT,
51 HW_VAR_MLME_SITESURVEY,
52 HW_VAR_MLME_JOIN,
53 HW_VAR_ON_RCR_AM,
54 HW_VAR_OFF_RCR_AM,
55 HW_VAR_BEACON_INTERVAL,
56 HW_VAR_SLOT_TIME,
57 HW_VAR_RESP_SIFS,
58 HW_VAR_ACK_PREAMBLE,
59 HW_VAR_SEC_CFG,
60 HW_VAR_BCN_VALID,
61 HW_VAR_RF_TYPE,
62 HW_VAR_DM_FLAG,
63 HW_VAR_DM_FUNC_OP,
64 HW_VAR_DM_FUNC_SET,
65 HW_VAR_DM_FUNC_CLR,
66 HW_VAR_CAM_EMPTY_ENTRY,
67 HW_VAR_CAM_INVALID_ALL,
68 HW_VAR_CAM_WRITE,
69 HW_VAR_CAM_READ,
70 HW_VAR_AC_PARAM_VO,
71 HW_VAR_AC_PARAM_VI,
72 HW_VAR_AC_PARAM_BE,
73 HW_VAR_AC_PARAM_BK,
74 HW_VAR_ACM_CTRL,
75 HW_VAR_AMPDU_MIN_SPACE,
76 HW_VAR_AMPDU_FACTOR,
77 HW_VAR_RXDMA_AGG_PG_TH,
78 HW_VAR_SET_RPWM,
79 HW_VAR_H2C_FW_PWRMODE,
80 HW_VAR_H2C_FW_JOINBSSRPT,
81 HW_VAR_FWLPS_RF_ON,
82 HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
83 HW_VAR_TDLS_WRCR,
84 HW_VAR_TDLS_INIT_CH_SEN,
85 HW_VAR_TDLS_RS_RCR,
86 HW_VAR_TDLS_DONE_CH_SEN,
87 HW_VAR_INITIAL_GAIN,
88 HW_VAR_TRIGGER_GPIO_0,
89 HW_VAR_BT_SET_COEXIST,
90 HW_VAR_BT_ISSUE_DELBA,
91 HW_VAR_CURRENT_ANTENNA,
92 HW_VAR_ANTENNA_DIVERSITY_LINK,
93 HW_VAR_ANTENNA_DIVERSITY_SELECT,
94 HW_VAR_SWITCH_EPHY_WoWLAN,
95 HW_VAR_EFUSE_BYTES,
96 HW_VAR_EFUSE_BT_BYTES,
97 HW_VAR_FIFO_CLEARN_UP,
98 HW_VAR_CHECK_TXBUF,
99 HW_VAR_APFM_ON_MAC, /* Auto FSM to Turn On, include clock, isolation, power control for MAC only */
100 /* The valid upper nav range for the HW updating, if the true value is larger than the upper range, the HW won't update it. */
101 /* Unit in microsecond. 0 means disable this function. */
102 HW_VAR_NAV_UPPER,
103 HW_VAR_RPT_TIMER_SETTING,
104 HW_VAR_TX_RPT_MAX_MACID,
105 HW_VAR_H2C_MEDIA_STATUS_RPT,
106 HW_VAR_CHK_HI_QUEUE_EMPTY,
107 HW_VAR_READ_LLT_TAB,
108};
109
110enum hal_def_variable {
111 HAL_DEF_UNDERCORATEDSMOOTHEDPWDB,
112 HAL_DEF_IS_SUPPORT_ANT_DIV,
113 HAL_DEF_CURRENT_ANTENNA,
114 HAL_DEF_DRVINFO_SZ,
115 HAL_DEF_MAX_RECVBUF_SZ,
116 HAL_DEF_RX_PACKET_OFFSET,
117 HAL_DEF_DBG_DUMP_RXPKT,/* for dbg */
118 HAL_DEF_DBG_DM_FUNC,/* for dbg */
119 HAL_DEF_RA_DECISION_RATE,
120 HAL_DEF_RA_SGI,
121 HAL_DEF_PT_PWR_STATUS,
122 HW_VAR_MAX_RX_AMPDU_FACTOR,
123 HW_DEF_RA_INFO_DUMP,
124 HAL_DEF_DBG_DUMP_TXPKT,
125 HW_DEF_FA_CNT_DUMP,
126 HW_DEF_ODM_DBG_FLAG,
127};
128
129enum hal_odm_variable {
130 HAL_ODM_STA_INFO,
131 HAL_ODM_P2P_STATE,
132 HAL_ODM_WIFI_DISPLAY_STATE,
133};
134
135enum hal_intf_ps_func {
136 HAL_USB_SELECT_SUSPEND,
137 HAL_MAX_ID,
138};
139
140struct hal_ops {
141 u32 (*hal_power_on)(struct rtw_adapter *padapter);
142 u32 (*hal_init)(struct rtw_adapter *padapter);
143 u32 (*hal_deinit)(struct rtw_adapter *padapter);
144
145 void (*free_hal_data)(struct rtw_adapter *padapter);
146
147 u32 (*inirp_init)(struct rtw_adapter *padapter);
148 u32 (*inirp_deinit)(struct rtw_adapter *padapter);
149
150 s32 (*init_xmit_priv)(struct rtw_adapter *padapter);
151 void (*free_xmit_priv)(struct rtw_adapter *padapter);
152
153 s32 (*init_recv_priv)(struct rtw_adapter *padapter);
154 void (*free_recv_priv)(struct rtw_adapter *padapter);
155
156 void (*InitSwLeds)(struct rtw_adapter *padapter);
157 void (*DeInitSwLeds)(struct rtw_adapter *padapter);
158
159 void (*dm_init)(struct rtw_adapter *padapter);
160 void (*dm_deinit)(struct rtw_adapter *padapter);
161 void (*read_chip_version)(struct rtw_adapter *padapter);
162
163 void (*init_default_value)(struct rtw_adapter *padapter);
164
165 void (*intf_chip_configure)(struct rtw_adapter *padapter);
166
167 void (*read_adapter_info)(struct rtw_adapter *padapter);
168
169 void (*enable_interrupt)(struct rtw_adapter *padapter);
170 void (*disable_interrupt)(struct rtw_adapter *padapter);
171 s32 (*interrupt_handler)(struct rtw_adapter *padapter);
172 void (*set_bwmode_handler)(struct rtw_adapter *padapter,
173 enum ht_channel_width Bandwidth, u8 Offset);
174 void (*set_channel_handler)(struct rtw_adapter *padapter, u8 channel);
175
176 void (*hal_dm_watchdog)(struct rtw_adapter *padapter);
177
178 void (*SetHwRegHandler)(struct rtw_adapter *padapter,
179 u8 variable, u8 *val);
180 void (*GetHwRegHandler)(struct rtw_adapter *padapter,
181 u8 variable, u8 *val);
182
183 u8 (*GetHalDefVarHandler)(struct rtw_adapter *padapter,
184 enum hal_def_variable eVariable,
185 void *pValue);
186 u8 (*SetHalDefVarHandler)(struct rtw_adapter *padapter,
187 enum hal_def_variable eVariable,
188 void *pValue);
189
190 void (*GetHalODMVarHandler)(struct rtw_adapter *padapter,
191 enum hal_odm_variable eVariable,
192 void *pValue1, bool bSet);
193 void (*SetHalODMVarHandler)(struct rtw_adapter *padapter,
194 enum hal_odm_variable eVariable,
195 void *pValue1, bool bSet);
196
197 void (*UpdateRAMaskHandler)(struct rtw_adapter *padapter,
198 u32 mac_id, u8 rssi_level);
199 void (*SetBeaconRelatedRegistersHandler)(struct rtw_adapter *padapter);
200
201 void (*Add_RateATid)(struct rtw_adapter *padapter, u32 bitmap,
202 u8 arg, u8 rssi_level);
203 void (*run_thread)(struct rtw_adapter *padapter);
204 void (*cancel_thread)(struct rtw_adapter *padapter);
205
206 u8 (*interface_ps_func)(struct rtw_adapter *padapter,
207 enum hal_intf_ps_func efunc_id, u8 *val);
208
209 s32 (*hal_xmit)(struct rtw_adapter *padapter,
210 struct xmit_frame *pxmitframe);
211 s32 (*mgnt_xmit)(struct rtw_adapter *padapter,
212 struct xmit_frame *pmgntframe);
213 s32 (*hal_xmitframe_enqueue)(struct rtw_adapter *padapter,
214 struct xmit_frame *pxmitframe);
215
216 u32 (*read_bbreg)(struct rtw_adapter *padapter, u32 RegAddr,
217 u32 BitMask);
218 void (*write_bbreg)(struct rtw_adapter *padapter, u32 RegAddr,
219 u32 BitMask, u32 Data);
220 u32 (*read_rfreg)(struct rtw_adapter *padapter, u32 eRFPath,
221 u32 RegAddr, u32 BitMask);
222 void (*write_rfreg)(struct rtw_adapter *padapter, u32 eRFPath,
223 u32 RegAddr, u32 BitMask, u32 Data);
224
225 void (*EfusePowerSwitch)(struct rtw_adapter *padapter, u8 bWrite,
226 u8 PwrState);
227 void (*ReadEFuse)(struct rtw_adapter *padapter, u8 efuseType,
228 u16 _offset, u16 _size_byte, u8 *pbuf);
229 void (*EFUSEGetEfuseDefinition)(struct rtw_adapter *padapter,
230 u8 efuseType, u8 type, void *pOut);
231 u16 (*EfuseGetCurrentSize)(struct rtw_adapter *padapter, u8 efuseType);
232 int (*Efuse_PgPacketRead23a)(struct rtw_adapter *padapter,
233 u8 offset, u8 *data);
234 int (*Efuse_PgPacketWrite23a)(struct rtw_adapter *padapter,
235 u8 offset, u8 word_en, u8 *data);
236 u8 (*Efuse_WordEnableDataWrite23a)(struct rtw_adapter *padapter,
237 u16 efuse_addr, u8 word_en,
238 u8 *data);
239 bool (*Efuse_PgPacketWrite23a_BT)(struct rtw_adapter *padapter,
240 u8 offset, u8 word_en, u8 *data);
241
242 void (*sreset_init_value23a)(struct rtw_adapter *padapter);
243 void (*sreset_reset_value23a)(struct rtw_adapter *padapter);
244 void (*silentreset)(struct rtw_adapter *padapter);
245 void (*sreset_xmit_status_check)(struct rtw_adapter *padapter);
246 void (*sreset_linked_status_check) (struct rtw_adapter *padapter);
247 u8 (*sreset_get_wifi_status23a)(struct rtw_adapter *padapter);
248 bool (*sreset_inprogress)(struct rtw_adapter *padapter);
249
250 void (*hal_notch_filter)(struct rtw_adapter *adapter, bool enable);
251 void (*hal_reset_security_engine)(struct rtw_adapter *adapter);
252 s32 (*c2h_handler)(struct rtw_adapter *padapter, struct c2h_evt_hdr *c2h_evt);
253 c2h_id_filter c2h_id_filter_ccx;
254};
255
256enum rt_eeprom_type {
257 EEPROM_93C46,
258 EEPROM_93C56,
259 EEPROM_BOOT_EFUSE,
260};
261
262
263
264#define RF_CHANGE_BY_INIT 0
265#define RF_CHANGE_BY_IPS BIT28
266#define RF_CHANGE_BY_PS BIT29
267#define RF_CHANGE_BY_HW BIT30
268#define RF_CHANGE_BY_SW BIT31
269
270enum hardware_type {
271 HARDWARE_TYPE_RTL8180,
272 HARDWARE_TYPE_RTL8185,
273 HARDWARE_TYPE_RTL8187,
274 HARDWARE_TYPE_RTL8188,
275 HARDWARE_TYPE_RTL8190P,
276 HARDWARE_TYPE_RTL8192E,
277 HARDWARE_TYPE_RTL819xU,
278 HARDWARE_TYPE_RTL8192SE,
279 HARDWARE_TYPE_RTL8192SU,
280 HARDWARE_TYPE_RTL8192CE,
281 HARDWARE_TYPE_RTL8192CU,
282 HARDWARE_TYPE_RTL8192DE,
283 HARDWARE_TYPE_RTL8192DU,
284 HARDWARE_TYPE_RTL8723AE,
285 HARDWARE_TYPE_RTL8723AU,
286 HARDWARE_TYPE_RTL8723AS,
287 HARDWARE_TYPE_RTL8188EE,
288 HARDWARE_TYPE_RTL8188EU,
289 HARDWARE_TYPE_RTL8188ES,
290 HARDWARE_TYPE_MAX,
291};
292
293#define GET_EEPROM_EFUSE_PRIV(adapter) (&adapter->eeprompriv)
294#define is_boot_from_eeprom(adapter) (adapter->eeprompriv.EepromOrEfuse)
295
296extern int rtw_ht_enable23A;
297extern int rtw_cbw40_enable23A;
298extern int rtw_ampdu_enable23A;/* for enable tx_ampdu */
299
300void rtw_hal_def_value_init23a(struct rtw_adapter *padapter);
301int pm_netdev_open23a(struct net_device *pnetdev, u8 bnormal);
302int rtw_resume_process23a(struct rtw_adapter *padapter);
303
304void rtw_hal_free_data23a(struct rtw_adapter *padapter);
305
306void rtw_hal_dm_init23a(struct rtw_adapter *padapter);
307void rtw_hal_dm_deinit23a(struct rtw_adapter *padapter);
308void rtw_hal_sw_led_init23a(struct rtw_adapter *padapter);
309void rtw_hal_sw_led_deinit23a(struct rtw_adapter *padapter);
310
311u32 rtw_hal_power_on23a(struct rtw_adapter *padapter);
312uint rtw_hal_init23a(struct rtw_adapter *padapter);
313uint rtw_hal_deinit23a(struct rtw_adapter *padapter);
314void rtw_hal_stop(struct rtw_adapter *padapter);
315void rtw_hal_set_hwreg23a(struct rtw_adapter *padapter, u8 variable, u8 *val);
316void rtw23a_hal_get_hwreg(struct rtw_adapter *padapter, u8 variable, u8 *val);
317
318void rtw_hal_chip_configure23a(struct rtw_adapter *padapter);
319void rtw_hal_read_chip_info23a(struct rtw_adapter *padapter);
320void rtw_hal_read_chip_version23a(struct rtw_adapter *padapter);
321
322u8 rtw_hal_set_def_var23a(struct rtw_adapter *padapter,
323 enum hal_def_variable eVariable,
324 void *pValue);
325u8 rtw_hal_get_def_var23a(struct rtw_adapter *padapter,
326 enum hal_def_variable eVariable,
327 void *pValue);
328
329void rtw_hal_set_odm_var23a(struct rtw_adapter *padapter,
330 enum hal_odm_variable eVariable,
331 void *pValue1, bool bSet);
332void rtw_hal_get_odm_var23a(struct rtw_adapter *padapter,
333 enum hal_odm_variable eVariable,
334 void *pValue1, bool bSet);
335
336void rtw_hal_enable_interrupt23a(struct rtw_adapter *padapter);
337void rtw_hal_disable_interrupt23a(struct rtw_adapter *padapter);
338
339u32 rtw_hal_inirp_init23a(struct rtw_adapter *padapter);
340u32 rtw_hal_inirp_deinit23a(struct rtw_adapter *padapter);
341
342u8 rtw_hal_intf_ps_func23a(struct rtw_adapter *padapter,
343 enum hal_intf_ps_func efunc_id, u8 *val);
344
345s32 rtw_hal_xmit23aframe_enqueue(struct rtw_adapter *padapter,
346 struct xmit_frame *pxmitframe);
347s32 rtw_hal_xmit23a(struct rtw_adapter *padapter,
348 struct xmit_frame *pxmitframe);
349s32 rtw_hal_mgnt_xmit23a(struct rtw_adapter *padapter,
350 struct xmit_frame *pmgntframe);
351
352s32 rtw_hal_init23a_xmit_priv(struct rtw_adapter *padapter);
353void rtw_hal_free_xmit_priv23a(struct rtw_adapter *padapter);
354
355s32 rtw_hal_init23a_recv_priv(struct rtw_adapter *padapter);
356void rtw_hal_free_recv_priv23a(struct rtw_adapter *padapter);
357
358void rtw_hal_update_ra_mask23a(struct sta_info *psta, u8 rssi_level);
359void rtw_hal_add_ra_tid23a(struct rtw_adapter *padapter, u32 bitmap, u8 arg, u8 rssi_level);
360void rtw_hal_clone_data(struct rtw_adapter *dst_padapter, struct rtw_adapter *src_padapter);
361void rtw_hal_start_thread23a(struct rtw_adapter *padapter);
362void rtw_hal_stop_thread23a(struct rtw_adapter *padapter);
363
364void rtw_hal_bcn_related_reg_setting23a(struct rtw_adapter *padapter);
365
366u32 rtw_hal_read_bbreg23a(struct rtw_adapter *padapter, u32 RegAddr, u32 BitMask);
367void rtw_hal_write_bbreg23a(struct rtw_adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data);
368u32 rtw_hal_read_rfreg23a(struct rtw_adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask);
369void rtw_hal_write_rfreg23a(struct rtw_adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask, u32 Data);
370
371s32 rtw_hal_interrupt_handler23a(struct rtw_adapter *padapter);
372
373void rtw_hal_set_bwmode23a(struct rtw_adapter *padapter,
374 enum ht_channel_width Bandwidth, u8 Offset);
375void rtw_hal_set_chan23a(struct rtw_adapter *padapter, u8 channel);
376void rtw_hal_dm_watchdog23a(struct rtw_adapter *padapter);
377
378void rtw_hal_sreset_init23a(struct rtw_adapter *padapter);
379void rtw_hal_sreset_reset23a(struct rtw_adapter *padapter);
380void rtw_hal_sreset_reset23a_value23a(struct rtw_adapter *padapter);
381void rtw_hal_sreset_xmit_status_check23a(struct rtw_adapter *padapter);
382void rtw_hal_sreset_linked_status_check23a (struct rtw_adapter *padapter);
383u8 rtw_hal_sreset_get_wifi_status23a(struct rtw_adapter *padapter);
384bool rtw_hal_sreset_inprogress(struct rtw_adapter *padapter);
385
386void rtw_hal_notch_filter23a(struct rtw_adapter *adapter, bool enable);
387void rtw_hal_reset_security_engine23a(struct rtw_adapter *adapter);
388
389s32 rtw_hal_c2h_handler23a(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt);
390c2h_id_filter rtw_hal_c2h_id_filter_ccx23a(struct rtw_adapter *adapter);
391
392#endif /* __HAL_INTF_H__ */
diff --git a/drivers/staging/rtl8723au/include/ieee80211.h b/drivers/staging/rtl8723au/include/ieee80211.h
new file mode 100644
index 000000000000..28e4ab239fb9
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/ieee80211.h
@@ -0,0 +1,603 @@
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 ******************************************************************************/
15#ifndef __IEEE80211_H
16#define __IEEE80211_H
17
18#include <osdep_service.h>
19#include <drv_types.h>
20#include "linux/ieee80211.h"
21#include "wifi.h"
22
23#include <linux/wireless.h>
24
25#if (WIRELESS_EXT < 22)
26#error "Obsolete pre 2007 wireless extensions are not supported"
27#endif
28
29
30#define MGMT_QUEUE_NUM 5
31
32#ifdef CONFIG_8723AU_AP_MODE
33
34/* STA flags */
35#define WLAN_STA_AUTH BIT(0)
36#define WLAN_STA_ASSOC BIT(1)
37#define WLAN_STA_PS BIT(2)
38#define WLAN_STA_TIM BIT(3)
39#define WLAN_STA_PERM BIT(4)
40#define WLAN_STA_AUTHORIZED BIT(5)
41#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */
42#define WLAN_STA_SHORT_PREAMBLE BIT(7)
43#define WLAN_STA_PREAUTH BIT(8)
44#define WLAN_STA_WME BIT(9)
45#define WLAN_STA_MFP BIT(10)
46#define WLAN_STA_HT BIT(11)
47#define WLAN_STA_WPS BIT(12)
48#define WLAN_STA_MAYBE_WPS BIT(13)
49#define WLAN_STA_NONERP BIT(31)
50
51#endif
52
53#define IEEE_CMD_SET_WPA_PARAM 1
54#define IEEE_CMD_SET_WPA_IE 2
55#define IEEE_CMD_SET_ENCRYPTION 3
56
57#define IEEE_CRYPT_ALG_NAME_LEN 16
58
59#define WPA_CIPHER_NONE BIT(0)
60#define WPA_CIPHER_WEP40 BIT(1)
61#define WPA_CIPHER_WEP104 BIT(2)
62#define WPA_CIPHER_TKIP BIT(3)
63#define WPA_CIPHER_CCMP BIT(4)
64
65
66
67#define WPA_SELECTOR_LEN 4
68extern u8 RTW_WPA_OUI23A_TYPE[] ;
69extern u16 RTW_WPA_VERSION23A ;
70extern u8 WPA_AUTH_KEY_MGMT_NONE23A[];
71extern u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X23A[];
72extern u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[];
73extern u8 WPA_CIPHER_SUITE_NONE23A[];
74extern u8 WPA_CIPHER_SUITE_WEP4023A[];
75extern u8 WPA_CIPHER_SUITE_TKIP23A[];
76extern u8 WPA_CIPHER_SUITE_WRAP23A[];
77extern u8 WPA_CIPHER_SUITE_CCMP23A[];
78extern u8 WPA_CIPHER_SUITE_WEP10423A[];
79
80
81#define RSN_HEADER_LEN 4
82#define RSN_SELECTOR_LEN 4
83
84extern u16 RSN_VERSION_BSD23A;
85extern u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X23A[];
86extern u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X23A[];
87extern u8 RSN_CIPHER_SUITE_NONE23A[];
88extern u8 RSN_CIPHER_SUITE_WEP4023A[];
89extern u8 RSN_CIPHER_SUITE_TKIP23A[];
90extern u8 RSN_CIPHER_SUITE_WRAP23A[];
91extern u8 RSN_CIPHER_SUITE_CCMP23A[];
92extern u8 RSN_CIPHER_SUITE_WEP10423A[];
93
94enum ratr_table_mode {
95 RATR_INX_WIRELESS_NGB = 0, /* BGN 40 Mhz 2SS 1SS */
96 RATR_INX_WIRELESS_NG = 1, /* GN or N */
97 RATR_INX_WIRELESS_NB = 2, /* BGN 20 Mhz 2SS 1SS or BN */
98 RATR_INX_WIRELESS_N = 3,
99 RATR_INX_WIRELESS_GB = 4,
100 RATR_INX_WIRELESS_G = 5,
101 RATR_INX_WIRELESS_B = 6,
102 RATR_INX_WIRELESS_MC = 7,
103 RATR_INX_WIRELESS_AC_N = 8,
104};
105
106enum NETWORK_TYPE
107{
108 WIRELESS_INVALID = 0,
109 /* Sub-Element */
110 WIRELESS_11B = BIT(0), /* tx: cck only , rx: cck only, hw: cck */
111 WIRELESS_11G = BIT(1), /* tx: ofdm only, rx: ofdm & cck, hw: cck & ofdm */
112 WIRELESS_11A = BIT(2), /* tx: ofdm only, rx: ofdm only, hw: ofdm only */
113 WIRELESS_11_24N = BIT(3), /* tx: MCS only, rx: MCS & cck, hw: MCS & cck */
114 WIRELESS_11_5N = BIT(4), /* tx: MCS only, rx: MCS & ofdm, hw: ofdm only */
115 /* WIRELESS_AUTO = BIT(5), */
116 WIRELESS_AC = BIT(6),
117
118 /* Combination */
119 WIRELESS_11BG = (WIRELESS_11B|WIRELESS_11G), /* tx: cck & ofdm, rx: cck & ofdm & MCS, hw: cck & ofdm */
120 WIRELESS_11G_24N = (WIRELESS_11G|WIRELESS_11_24N), /* tx: ofdm & MCS, rx: ofdm & cck & MCS, hw: cck & ofdm */
121 WIRELESS_11A_5N = (WIRELESS_11A|WIRELESS_11_5N), /* tx: ofdm & MCS, rx: ofdm & MCS, hw: ofdm only */
122 WIRELESS_11BG_24N = (WIRELESS_11B|WIRELESS_11G|WIRELESS_11_24N), /* tx: ofdm & cck & MCS, rx: ofdm & cck & MCS, hw: ofdm & cck */
123 WIRELESS_11AGN = (WIRELESS_11A|WIRELESS_11G|WIRELESS_11_24N|WIRELESS_11_5N), /* tx: ofdm & MCS, rx: ofdm & MCS, hw: ofdm only */
124 WIRELESS_11ABGN = (WIRELESS_11A|WIRELESS_11B|WIRELESS_11G|WIRELESS_11_24N|WIRELESS_11_5N),
125};
126
127#define SUPPORTED_24G_NETTYPE_MSK (WIRELESS_11B | WIRELESS_11G | WIRELESS_11_24N)
128#define SUPPORTED_5G_NETTYPE_MSK (WIRELESS_11A | WIRELESS_11_5N)
129
130#define IsSupported24G(NetType) ((NetType) & SUPPORTED_24G_NETTYPE_MSK ? true : false)
131#define IsSupported5G(NetType) ((NetType) & SUPPORTED_5G_NETTYPE_MSK ? true : false)
132
133#define IsEnableHWCCK(NetType) IsSupported24G(NetType)
134#define IsEnableHWOFDM(NetType) ((NetType) & (WIRELESS_11G|WIRELESS_11_24N|SUPPORTED_5G_NETTYPE_MSK) ? true : false)
135
136#define IsSupportedRxCCK(NetType) IsEnableHWCCK(NetType)
137#define IsSupportedRxOFDM(NetType) IsEnableHWOFDM(NetType)
138#define IsSupportedRxMCS(NetType) IsEnableHWOFDM(NetType)
139
140#define IsSupportedTxCCK(NetType) ((NetType) & (WIRELESS_11B) ? true : false)
141#define IsSupportedTxOFDM(NetType) ((NetType) & (WIRELESS_11G|WIRELESS_11A) ? true : false)
142#define IsSupportedTxMCS(NetType) ((NetType) & (WIRELESS_11_24N|WIRELESS_11_5N) ? true : false)
143
144
145struct ieee_param {
146 u32 cmd;
147 u8 sta_addr[ETH_ALEN];
148 union {
149 struct {
150 u8 name;
151 u32 value;
152 } wpa_param;
153 struct {
154 u32 len;
155 u8 reserved[32];
156 u8 data[0];
157 } wpa_ie;
158 struct{
159 int command;
160 int reason_code;
161 } mlme;
162 struct {
163 u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
164 u8 set_tx;
165 u32 err;
166 u8 idx;
167 u8 seq[8]; /* sequence counter (set: RX, get: TX) */
168 u16 key_len;
169 u8 key[0];
170 } crypt;
171#ifdef CONFIG_8723AU_AP_MODE
172 struct {
173 u16 aid;
174 u16 capability;
175 int flags;
176 u8 tx_supp_rates[16];
177 struct ieee80211_ht_cap ht_cap;
178 } add_sta;
179 struct {
180 u8 reserved[2];/* for set max_num_sta */
181 u8 buf[0];
182 } bcn_ie;
183#endif
184
185 } u;
186};
187
188
189#define MIN_FRAG_THRESHOLD 256U
190#define MAX_FRAG_THRESHOLD 2346U
191
192/* QoS,QOS */
193#define NORMAL_ACK 0
194#define NO_ACK 1
195#define NON_EXPLICIT_ACK 2
196#define BLOCK_ACK 3
197
198/* IEEE 802.11 defines */
199
200#define P80211_OUI_LEN 3
201
202struct ieee80211_snap_hdr {
203
204 u8 dsap; /* always 0xAA */
205 u8 ssap; /* always 0xAA */
206 u8 ctrl; /* always 0x03 */
207 u8 oui[P80211_OUI_LEN]; /* organizational universal id */
208
209} __attribute__ ((packed));
210
211
212#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
213
214#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE)
215#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)
216
217#define WLAN_QC_GET_TID(qc) ((qc) & 0x0f)
218
219#define WLAN_GET_SEQ_FRAG(seq) ((seq) & RTW_IEEE80211_SCTL_FRAG)
220#define WLAN_GET_SEQ_SEQ(seq) ((seq) & RTW_IEEE80211_SCTL_SEQ)
221
222
223#define WLAN_REASON_JOIN_WRONG_CHANNEL 65534
224#define WLAN_REASON_EXPIRATION_CHK 65535
225
226
227
228#define IEEE80211_STATMASK_SIGNAL (1<<0)
229#define IEEE80211_STATMASK_RSSI (1<<1)
230#define IEEE80211_STATMASK_NOISE (1<<2)
231#define IEEE80211_STATMASK_RATE (1<<3)
232#define IEEE80211_STATMASK_WEMASK 0x7
233
234
235#define IEEE80211_CCK_MODULATION (1<<0)
236#define IEEE80211_OFDM_MODULATION (1<<1)
237
238#define IEEE80211_24GHZ_BAND (1<<0)
239#define IEEE80211_52GHZ_BAND (1<<1)
240
241#define IEEE80211_CCK_RATE_LEN 4
242#define IEEE80211_NUM_OFDM_RATESLEN 8
243
244
245#define IEEE80211_CCK_RATE_1MB 0x02
246#define IEEE80211_CCK_RATE_2MB 0x04
247#define IEEE80211_CCK_RATE_5MB 0x0B
248#define IEEE80211_CCK_RATE_11MB 0x16
249#define IEEE80211_OFDM_RATE_LEN 8
250#define IEEE80211_OFDM_RATE_6MB 0x0C
251#define IEEE80211_OFDM_RATE_9MB 0x12
252#define IEEE80211_OFDM_RATE_12MB 0x18
253#define IEEE80211_OFDM_RATE_18MB 0x24
254#define IEEE80211_OFDM_RATE_24MB 0x30
255#define IEEE80211_OFDM_RATE_36MB 0x48
256#define IEEE80211_OFDM_RATE_48MB 0x60
257#define IEEE80211_OFDM_RATE_54MB 0x6C
258#define IEEE80211_BASIC_RATE_MASK 0x80
259
260#define IEEE80211_CCK_RATE_1MB_MASK (1<<0)
261#define IEEE80211_CCK_RATE_2MB_MASK (1<<1)
262#define IEEE80211_CCK_RATE_5MB_MASK (1<<2)
263#define IEEE80211_CCK_RATE_11MB_MASK (1<<3)
264#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4)
265#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5)
266#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6)
267#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7)
268#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8)
269#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9)
270#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10)
271#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11)
272
273#define IEEE80211_CCK_RATES_MASK 0x0000000F
274#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \
275 IEEE80211_CCK_RATE_2MB_MASK)
276#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \
277 IEEE80211_CCK_RATE_5MB_MASK | \
278 IEEE80211_CCK_RATE_11MB_MASK)
279
280#define IEEE80211_OFDM_RATES_MASK 0x00000FF0
281#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \
282 IEEE80211_OFDM_RATE_12MB_MASK | \
283 IEEE80211_OFDM_RATE_24MB_MASK)
284#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \
285 IEEE80211_OFDM_RATE_9MB_MASK | \
286 IEEE80211_OFDM_RATE_18MB_MASK | \
287 IEEE80211_OFDM_RATE_36MB_MASK | \
288 IEEE80211_OFDM_RATE_48MB_MASK | \
289 IEEE80211_OFDM_RATE_54MB_MASK)
290#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \
291 IEEE80211_CCK_DEFAULT_RATES_MASK)
292
293#define IEEE80211_NUM_OFDM_RATES 8
294#define IEEE80211_NUM_CCK_RATES 4
295#define IEEE80211_OFDM_SHIFT_MASK_A 4
296
297#define WEP_KEYS 4
298#define WEP_KEY_LEN 13
299
300
301
302/*
303
304 802.11 data frame from AP
305
306 ,-------------------------------------------------------------------.
307Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
308 |------|------|---------|---------|---------|------|---------|------|
309Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs |
310 | | tion | (BSSID) | | | ence | data | |
311 `-------------------------------------------------------------------'
312
313Total: 28-2340 bytes
314
315*/
316
317struct ieee80211_header_data {
318 u16 frame_ctl;
319 u16 duration_id;
320 u8 addr1[6];
321 u8 addr2[6];
322 u8 addr3[6];
323 u16 seq_ctrl;
324};
325
326struct ieee80211_info_element_hdr {
327 u8 id;
328 u8 len;
329} __attribute__ ((packed));
330
331struct ieee80211_info_element {
332 u8 id;
333 u8 len;
334 u8 data[0];
335} __attribute__ ((packed));
336
337
338struct ieee80211_txb {
339 u8 nr_frags;
340 u8 encrypted;
341 u16 reserved;
342 u16 frag_size;
343 u16 payload_size;
344 struct sk_buff *fragments[0];
345};
346
347
348/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs
349 * only use 8, and then use extended rates for the remaining supported
350 * rates. Other APs, however, stick all of their supported rates on the
351 * main rates information element... */
352#define MAX_RATES_LENGTH ((u8)12)
353#define MAX_RATES_EX_LENGTH ((u8)16)
354#define MAX_CHANNEL_NUMBER 161
355
356#define MAX_WPA_IE_LEN (256)
357#define MAX_WPS_IE_LEN (512)
358#define MAX_P2P_IE_LEN (256)
359#define MAX_WFD_IE_LEN (128)
360
361#define IW_ESSID_MAX_SIZE 32
362
363/*
364join_res:
365-1: authentication fail
366-2: association fail
367> 0: TID
368*/
369
370#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
371#define DEFAULT_FTS 2346
372#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
373#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
374
375#define CFG_IEEE80211_RESERVE_FCS (1<<0)
376#define CFG_IEEE80211_COMPUTE_FCS (1<<1)
377
378#define MAXTID 16
379
380#define IEEE_A (1<<0)
381#define IEEE_B (1<<1)
382#define IEEE_G (1<<2)
383#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G)
384
385/* Baron move to ieee80211.c */
386int ieee80211_is_empty_essid23a(const char *essid, int essid_len);
387
388enum _PUBLIC_ACTION{
389 ACT_PUBLIC_BSSCOEXIST = 0, /* 20/40 BSS Coexistence */
390 ACT_PUBLIC_DSE_ENABLE = 1,
391 ACT_PUBLIC_DSE_DEENABLE = 2,
392 ACT_PUBLIC_DSE_REG_LOCATION = 3,
393 ACT_PUBLIC_EXT_CHL_SWITCH = 4,
394 ACT_PUBLIC_DSE_MSR_REQ = 5,
395 ACT_PUBLIC_DSE_MSR_RPRT = 6,
396 ACT_PUBLIC_MP = 7, /* Measurement Pilot */
397 ACT_PUBLIC_DSE_PWR_CONSTRAINT = 8,
398 ACT_PUBLIC_VENDOR = 9, /* for WIFI_DIRECT */
399 ACT_PUBLIC_GAS_INITIAL_REQ = 10,
400 ACT_PUBLIC_GAS_INITIAL_RSP = 11,
401 ACT_PUBLIC_GAS_COMEBACK_REQ = 12,
402 ACT_PUBLIC_GAS_COMEBACK_RSP = 13,
403 ACT_PUBLIC_TDLS_DISCOVERY_RSP = 14,
404 ACT_PUBLIC_LOCATION_TRACK = 15,
405 ACT_PUBLIC_MAX
406};
407
408#define WME_OUI_TYPE 2
409#define WME_OUI_SUBTYPE_INFORMATION_ELEMENT 0
410#define WME_OUI_SUBTYPE_PARAMETER_ELEMENT 1
411#define WME_OUI_SUBTYPE_TSPEC_ELEMENT 2
412#define WME_VERSION 1
413
414
415#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
416
417#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */
418
419/* Represent channel details, subset of ieee80211_channel */
420struct rtw_ieee80211_channel {
421 /* enum ieee80211_band band; */
422 /* u16 center_freq; */
423 u16 hw_value;
424 u32 flags;
425 /* int max_antenna_gain; */
426 /* int max_power; */
427 /* int max_reg_power; */
428 /* bool beacon_found; */
429 /* u32 orig_flags; */
430 /* int orig_mag; */
431 /* int orig_mpwr; */
432};
433
434#define CHAN_FMT \
435 /*"band:%d, "*/ \
436 /*"center_freq:%u, "*/ \
437 "hw_value:%u, " \
438 "flags:0x%08x" \
439 /*"max_antenna_gain:%d\n"*/ \
440 /*"max_power:%d\n"*/ \
441 /*"max_reg_power:%d\n"*/ \
442 /*"beacon_found:%u\n"*/ \
443 /*"orig_flags:0x%08x\n"*/ \
444 /*"orig_mag:%d\n"*/ \
445 /*"orig_mpwr:%d\n"*/
446
447#define CHAN_ARG(channel) \
448 /*(channel)->band*/ \
449 /*, (channel)->center_freq*/ \
450 (channel)->hw_value \
451 , (channel)->flags \
452 /*, (channel)->max_antenna_gain*/ \
453 /*, (channel)->max_power*/ \
454 /*, (channel)->max_reg_power*/ \
455 /*, (channel)->beacon_found*/ \
456 /*, (channel)->orig_flags*/ \
457 /*, (channel)->orig_mag*/ \
458 /*, (channel)->orig_mpwr*/ \
459
460/* Parsed Information Elements */
461struct rtw_ieee802_11_elems {
462 u8 *ssid;
463 u8 ssid_len;
464 u8 *supp_rates;
465 u8 supp_rates_len;
466 u8 *fh_params;
467 u8 fh_params_len;
468 u8 *ds_params;
469 u8 ds_params_len;
470 u8 *cf_params;
471 u8 cf_params_len;
472 u8 *tim;
473 u8 tim_len;
474 u8 *ibss_params;
475 u8 ibss_params_len;
476 u8 *challenge;
477 u8 challenge_len;
478 u8 *erp_info;
479 u8 erp_info_len;
480 u8 *ext_supp_rates;
481 u8 ext_supp_rates_len;
482 u8 *wpa_ie;
483 u8 wpa_ie_len;
484 u8 *rsn_ie;
485 u8 rsn_ie_len;
486 u8 *wme;
487 u8 wme_len;
488 u8 *wme_tspec;
489 u8 wme_tspec_len;
490 u8 *wps_ie;
491 u8 wps_ie_len;
492 u8 *power_cap;
493 u8 power_cap_len;
494 u8 *supp_channels;
495 u8 supp_channels_len;
496 u8 *mdie;
497 u8 mdie_len;
498 u8 *ftie;
499 u8 ftie_len;
500 u8 *timeout_int;
501 u8 timeout_int_len;
502 u8 *ht_capabilities;
503 u8 ht_capabilities_len;
504 u8 *ht_operation;
505 u8 ht_operation_len;
506 u8 *vendor_ht_cap;
507 u8 vendor_ht_cap_len;
508};
509
510enum parse_res {
511 ParseOK = 0,
512 ParseUnknown = 1,
513 ParseFailed = -1
514};
515
516enum parse_res rtw_ieee802_11_parse_elems23a(u8 *start, uint len,
517 struct rtw_ieee802_11_elems *elems,
518 int show_errors);
519
520u8 *rtw_set_fixed_ie23a(unsigned char *pbuf, unsigned int len, unsigned char *source, unsigned int *frlen);
521u8 *rtw_set_ie23a(u8 *pbuf, int index, uint len, u8 *source, uint *frlen);
522
523enum secondary_ch_offset {
524 SCN = 0, /* no secondary channel */
525 SCA = 1, /* secondary channel above */
526 SCB = 3, /* secondary channel below */
527};
528u8 secondary_ch_offset_to_hal_ch_offset23a(u8 ch_offset);
529u8 hal_ch_offset_to_secondary_ch_offset23a(u8 ch_offset);
530u8 *rtw_set_ie23a_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, u8 new_ch, u8 ch_switch_cnt);
531u8 *rtw_set_ie23a_secondary_ch_offset(u8 *buf, u32 *buf_len, u8 secondary_ch_offset);
532u8 *rtw_set_ie23a_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl, u8 flags, u16 reason, u16 precedence);
533
534u8 *rtw_get_ie23a(u8*pbuf, int index, int *len, int limit);
535u8 *rtw_get_ie23a_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, uint *ielen);
536int rtw_ies_remove_ie23a(u8 *ies, uint *ies_len, uint offset, u8 eid, u8 *oui, u8 oui_len);
537
538void rtw_set_supported_rate23a(u8* SupportedRates, uint mode) ;
539
540unsigned char *rtw_get_wpa_ie23a(unsigned char *pie, int *wpa_ie_len, int limit);
541unsigned char *rtw_get_wpa2_ie23a(unsigned char *pie, int *rsn_ie_len, int limit);
542int rtw_get_wpa_cipher_suite23a(u8 *s);
543int rtw_get_wpa2_cipher_suite23a(u8 *s);
544int rtw_parse_wpa_ie23a(u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x);
545int rtw_parse_wpa2_ie23a(u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x);
546
547int rtw_get_sec_ie23a(u8 *in_ie,uint in_len,u8 *rsn_ie,u16 *rsn_len,u8 *wpa_ie,u16 *wpa_len);
548
549u8 rtw_is_wps_ie23a(u8 *ie_ptr, uint *wps_ielen);
550u8 *rtw_get_wps_ie23a(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen);
551u8 *rtw_get_wps_attr23a(u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_attr, u32 *len_attr);
552u8 *rtw_get_wps_attr_content23a(u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_content, uint *len_content);
553
554/**
555 * for_each_ie - iterate over continuous IEs
556 * @ie:
557 * @buf:
558 * @buf_len:
559 */
560#define for_each_ie(ie, buf, buf_len) \
561 for (ie = (void*)buf; (((u8*)ie) - ((u8*)buf) + 1) < buf_len; ie = (void*)(((u8*)ie) + *(((u8*)ie)+1) + 2))
562
563void dump_ies23a(u8 *buf, u32 buf_len);
564void dump_wps_ie23a(u8 *ie, u32 ie_len);
565
566#ifdef CONFIG_8723AU_P2P
567void dump_p2p_ie23a(u8 *ie, u32 ie_len);
568u8 *rtw_get_p2p_ie23a(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen);
569u8 *rtw_get_p2p_attr23a(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id ,u8 *buf_attr, u32 *len_attr);
570u8 *rtw_get_p2p_attr23a_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id ,u8 *buf_content, uint *len_content);
571u32 rtw_set_p2p_attr_content23a(u8 *pbuf, u8 attr_id, u16 attr_len, u8 *pdata_attr);
572void rtw_wlan_bssid_ex_remove_p2p_attr23a(struct wlan_bssid_ex *bss_ex, u8 attr_id);
573#endif
574
575#ifdef CONFIG_8723AU_P2P
576int rtw_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen);
577int rtw_get_wfd_attr_content(u8 *wfd_ie, uint wfd_ielen, u8 target_attr_id ,u8 *attr_content, uint *attr_contentlen);
578#endif /* CONFIG_8723AU_P2P */
579
580uint rtw_get_rateset_len23a(u8 *rateset);
581
582struct registry_priv;
583int rtw_generate_ie23a(struct registry_priv *pregistrypriv);
584
585
586int rtw_get_bit_value_from_ieee_value23a(u8 val);
587
588uint rtw_is_cckrates_included23a(u8 *rate);
589
590uint rtw_is_cckratesonly_included23a(u8 *rate);
591
592int rtw_check_network_type23a(unsigned char *rate, int ratelen, int channel);
593
594void rtw_get_bcn_info23a(struct wlan_network *pnetwork);
595
596void rtw_macaddr_cfg23a(u8 *mac_addr);
597
598u16 rtw_mcs_rate23a(u8 rf_type, u8 bw_40MHz, u8 short_GI_20, u8 short_GI_40, unsigned char * MCS_rate);
599
600int rtw_action_frame_parse23a(const u8 *frame, u32 frame_len, u8* category, u8 *action);
601const char *action_public_str23a(u8 action);
602
603#endif /* IEEE80211_H */
diff --git a/drivers/staging/rtl8723au/include/ioctl_cfg80211.h b/drivers/staging/rtl8723au/include/ioctl_cfg80211.h
new file mode 100644
index 000000000000..0eb9036d7250
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/ioctl_cfg80211.h
@@ -0,0 +1,119 @@
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 ******************************************************************************/
15#ifndef __IOCTL_CFG80211_H__
16#define __IOCTL_CFG80211_H__
17
18struct rtw_wdev_invit_info {
19 u8 token;
20 u8 flags;
21 u8 status;
22 u8 req_op_ch;
23 u8 rsp_op_ch;
24};
25
26#define rtw_wdev_invit_info_init(invit_info) \
27 do { \
28 (invit_info)->token = 0; \
29 (invit_info)->flags = 0x00; \
30 (invit_info)->status = 0xff; \
31 (invit_info)->req_op_ch = 0; \
32 (invit_info)->rsp_op_ch = 0; \
33 } while (0)
34
35struct rtw_wdev_priv {
36 struct wireless_dev *rtw_wdev;
37
38 struct rtw_adapter *padapter;
39
40 struct cfg80211_scan_request *scan_request;
41 spinlock_t scan_req_lock;
42
43 struct net_device *pmon_ndev;/* for monitor interface */
44 char ifname_mon[IFNAMSIZ + 1]; /* name for monitor interface */
45
46 u8 p2p_enabled;
47
48 u8 provdisc_req_issued;
49
50 struct rtw_wdev_invit_info invit_info;
51
52 bool block;
53 bool power_mgmt;
54};
55
56#define wdev_to_priv(w) ((struct rtw_wdev_priv *)(wdev_priv(w)))
57
58#define wiphy_to_adapter(x) \
59 (struct rtw_adapter *)(((struct rtw_wdev_priv *) \
60 wiphy_priv(x))->padapter)
61
62#define wiphy_to_wdev(x) \
63 (struct wireless_dev *)(((struct rtw_wdev_priv *) \
64 wiphy_priv(x))->rtw_wdev)
65
66int rtw_wdev_alloc(struct rtw_adapter *padapter, struct device *dev);
67void rtw_wdev_free(struct wireless_dev *wdev);
68void rtw_wdev_unregister(struct wireless_dev *wdev);
69
70void rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter);
71
72void rtw_cfg80211_surveydone_event_callback(struct rtw_adapter *padapter);
73
74void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter);
75void rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter);
76void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
77 bool aborted);
78
79#ifdef CONFIG_8723AU_AP_MODE
80void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter,
81 u8 *pmgmt_frame, uint frame_len);
82void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter,
83 unsigned char *da, unsigned short reason);
84#endif /* CONFIG_8723AU_AP_MODE */
85
86void rtw_cfg80211_issue_p2p_provision_request23a(struct rtw_adapter *padapter,
87 const u8 *buf, size_t len);
88void rtw_cfg80211_rx_p2p_action_public(struct rtw_adapter *padapter,
89 u8 *pmgmt_frame, uint frame_len);
90void rtw_cfg80211_rx_action_p2p(struct rtw_adapter *padapter,
91 u8 *pmgmt_frame, uint frame_len);
92void rtw_cfg80211_rx_action(struct rtw_adapter *adapter, u8 *frame,
93 uint frame_len, const char*msg);
94
95int rtw_cfg80211_set_mgnt_wpsp2pie(struct net_device *net, char *buf, int len,
96 int type);
97
98bool rtw_cfg80211_pwr_mgmt(struct rtw_adapter *adapter);
99
100#define rtw_cfg80211_rx_mgmt(adapter, freq, sig_dbm, buf, len, gfp) \
101 cfg80211_rx_mgmt((adapter)->rtw_wdev, freq, sig_dbm, buf, len, 0, gfp)
102
103#define rtw_cfg80211_send_rx_assoc(adapter, bss, buf, len) \
104 cfg80211_send_rx_assoc((adapter)->pnetdev, bss, buf, len)
105
106#define rtw_cfg80211_mgmt_tx_status(adapter, cookie, buf, len, ack, gfp) \
107 cfg80211_mgmt_tx_status((adapter)->rtw_wdev, cookie, buf, \
108 len, ack, gfp)
109
110#define rtw_cfg80211_ready_on_channel(adapter, cookie, chan, \
111 channel_type, duration, gfp) \
112 cfg80211_ready_on_channel((adapter)->rtw_wdev, cookie, chan, \
113 duration, gfp)
114#define rtw_cfg80211_remain_on_channel_expired(adapter, cookie, chan, \
115 chan_type, gfp) \
116 cfg80211_remain_on_channel_expired((adapter)->rtw_wdev, \
117 cookie, chan, gfp)
118
119#endif /* __IOCTL_CFG80211_H__ */
diff --git a/drivers/staging/rtl8723au/include/mlme_osdep.h b/drivers/staging/rtl8723au/include/mlme_osdep.h
new file mode 100644
index 000000000000..b7132a9a1378
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/mlme_osdep.h
@@ -0,0 +1,28 @@
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 ******************************************************************************/
15#ifndef __MLME_OSDEP_H_
16#define __MLME_OSDEP_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21void rtw_os_indicate_disconnect23a(struct rtw_adapter *adapter);
22void rtw_os_indicate_connect23a(struct rtw_adapter *adapter);
23void rtw_os_indicate_scan_done23a(struct rtw_adapter *padapter, bool aborted);
24void rtw_report_sec_ie23a(struct rtw_adapter *adapter, u8 authmode, u8 *sec_ie);
25
26void rtw_reset_securitypriv23a(struct rtw_adapter *adapter);
27
28#endif /* _MLME_OSDEP_H_ */
diff --git a/drivers/staging/rtl8723au/include/mp_custom_oid.h b/drivers/staging/rtl8723au/include/mp_custom_oid.h
new file mode 100644
index 000000000000..da197cf678a1
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/mp_custom_oid.h
@@ -0,0 +1,342 @@
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 ******************************************************************************/
15#ifndef __CUSTOM_OID_H
16#define __CUSTOM_OID_H
17
18/* 0xFF818000 - 0xFF81802F RTL8180 Mass Production Kit */
19/* 0xFF818500 - 0xFF81850F RTL8185 Setup Utility */
20/* 0xFF818580 - 0xFF81858F RTL8185 Phy Status Utility */
21
22/* For Production Kit with Agilent Equipments */
23/* in order to make our custom oids hopefully somewhat unique */
24/* we will use 0xFF (indicating implementation specific OID) */
25/* 81(first byte of non zero Realtek unique identifier) */
26/* 80 (second byte of non zero Realtek unique identifier) */
27/* XX (the custom OID number - providing 255 possible custom oids) */
28
29#define OID_RT_PRO_RESET_DUT 0xFF818000
30#define OID_RT_PRO_SET_DATA_RATE 0xFF818001
31#define OID_RT_PRO_START_TEST 0xFF818002
32#define OID_RT_PRO_STOP_TEST 0xFF818003
33#define OID_RT_PRO_SET_PREAMBLE 0xFF818004
34#define OID_RT_PRO_SET_SCRAMBLER 0xFF818005
35#define OID_RT_PRO_SET_FILTER_BB 0xFF818006
36#define OID_RT_PRO_SET_MANUAL_DIVERSITY_BB 0xFF818007
37#define OID_RT_PRO_SET_CHANNEL_DIRECT_CALL 0xFF818008
38#define OID_RT_PRO_SET_SLEEP_MODE_DIRECT_CALL 0xFF818009
39#define OID_RT_PRO_SET_WAKE_MODE_DIRECT_CALL 0xFF81800A
40
41#define OID_RT_PRO_SET_TX_ANTENNA_BB 0xFF81800D
42#define OID_RT_PRO_SET_ANTENNA_BB 0xFF81800E
43#define OID_RT_PRO_SET_CR_SCRAMBLER 0xFF81800F
44#define OID_RT_PRO_SET_CR_NEW_FILTER 0xFF818010
45#define OID_RT_PRO_SET_TX_POWER_CONTROL 0xFF818011
46#define OID_RT_PRO_SET_CR_TX_CONFIG 0xFF818012
47#define OID_RT_PRO_GET_TX_POWER_CONTROL 0xFF818013
48#define OID_RT_PRO_GET_CR_SIGNAL_QUALITY 0xFF818014
49#define OID_RT_PRO_SET_CR_SETPOINT 0xFF818015
50#define OID_RT_PRO_SET_INTEGRATOR 0xFF818016
51#define OID_RT_PRO_SET_SIGNAL_QUALITY 0xFF818017
52#define OID_RT_PRO_GET_INTEGRATOR 0xFF818018
53#define OID_RT_PRO_GET_SIGNAL_QUALITY 0xFF818019
54#define OID_RT_PRO_QUERY_EEPROM_TYPE 0xFF81801A
55#define OID_RT_PRO_WRITE_MAC_ADDRESS 0xFF81801B
56#define OID_RT_PRO_READ_MAC_ADDRESS 0xFF81801C
57#define OID_RT_PRO_WRITE_CIS_DATA 0xFF81801D
58#define OID_RT_PRO_READ_CIS_DATA 0xFF81801E
59#define OID_RT_PRO_WRITE_POWER_CONTROL 0xFF81801F
60#define OID_RT_PRO_READ_POWER_CONTROL 0xFF818020
61#define OID_RT_PRO_WRITE_EEPROM 0xFF818021
62#define OID_RT_PRO_READ_EEPROM 0xFF818022
63#define OID_RT_PRO_RESET_TX_PACKET_SENT 0xFF818023
64#define OID_RT_PRO_QUERY_TX_PACKET_SENT 0xFF818024
65#define OID_RT_PRO_RESET_RX_PACKET_RECEIVED 0xFF818025
66#define OID_RT_PRO_QUERY_RX_PACKET_RECEIVED 0xFF818026
67#define OID_RT_PRO_QUERY_RX_PACKET_CRC32_ERROR 0xFF818027
68#define OID_RT_PRO_QUERY_CURRENT_ADDRESS 0xFF818028
69#define OID_RT_PRO_QUERY_PERMANENT_ADDRESS 0xFF818029
70#define OID_RT_PRO_SET_PHILIPS_RF_PARAMETERS 0xFF81802A
71#define OID_RT_PRO_RECEIVE_PACKET 0xFF81802C
72/* added by Owen on 04/08/03 for Cameo's request */
73#define OID_RT_PRO_WRITE_EEPROM_BYTE 0xFF81802D
74#define OID_RT_PRO_READ_EEPROM_BYTE 0xFF81802E
75#define OID_RT_PRO_SET_MODULATION 0xFF81802F
76/* */
77
78#define OID_RT_DRIVER_OPTION 0xFF818080
79#define OID_RT_RF_OFF 0xFF818081
80#define OID_RT_AUTH_STATUS 0xFF818082
81
82/* */
83#define OID_RT_PRO_SET_CONTINUOUS_TX 0xFF81800B
84#define OID_RT_PRO_SET_SINGLE_CARRIER_TX 0xFF81800C
85#define OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX 0xFF81802B
86#define OID_RT_PRO_SET_SINGLE_TONE_TX 0xFF818043
87/* */
88
89
90/* by Owen for RTL8185 Phy Status Report Utility */
91#define OID_RT_UTILITYfalse_ALARM_COUNTERS 0xFF818580
92#define OID_RT_UTILITY_SELECT_DEBUG_MODE 0xFF818581
93#define OID_RT_UTILITY_SELECT_SUBCARRIER_NUMBER 0xFF818582
94#define OID_RT_UTILITY_GET_RSSI_STATUS 0xFF818583
95#define OID_RT_UTILITY_GET_FRAME_DETECTION_STATUS 0xFF818584
96#define OID_RT_UTILITY_GET_AGC_AND_FREQUENCY_OFFSET_ESTIMATION_STATUS 0xFF818585
97#define OID_RT_UTILITY_GET_CHANNEL_ESTIMATION_STATUS 0xFF818586
98
99/* by Owen on 03/09/19-03/09/22 for RTL8185 */
100#define OID_RT_WIRELESS_MODE 0xFF818500
101#define OID_RT_SUPPORTED_RATES 0xFF818501
102#define OID_RT_DESIRED_RATES 0xFF818502
103#define OID_RT_WIRELESS_MODE_STARTING_ADHOC 0xFF818503
104/* */
105
106#define OID_RT_GET_CONNECT_STATE 0xFF030001
107#define OID_RT_RESCAN 0xFF030002
108#define OID_RT_SET_KEY_LENGTH 0xFF030003
109#define OID_RT_SET_DEFAULT_KEY_ID 0xFF030004
110
111#define OID_RT_SET_CHANNEL 0xFF010182
112#define OID_RT_SET_SNIFFER_MODE 0xFF010183
113#define OID_RT_GET_SIGNAL_QUALITY 0xFF010184
114#define OID_RT_GET_SMALL_PACKET_CRC 0xFF010185
115#define OID_RT_GET_MIDDLE_PACKET_CRC 0xFF010186
116#define OID_RT_GET_LARGE_PACKET_CRC 0xFF010187
117#define OID_RT_GET_TX_RETRY 0xFF010188
118#define OID_RT_GET_RX_RETRY 0xFF010189
119#define OID_RT_PRO_SET_FW_DIG_STATE 0xFF01018A/* S */
120#define OID_RT_PRO_SET_FW_RA_STATE 0xFF01018B/* S */
121
122#define OID_RT_GET_RX_TOTAL_PACKET 0xFF010190
123#define OID_RT_GET_TX_BEACON_OK 0xFF010191
124#define OID_RT_GET_TX_BEACON_ERR 0xFF010192
125#define OID_RT_GET_RX_ICV_ERR 0xFF010193
126#define OID_RT_SET_ENCRYPTION_ALGORITHM 0xFF010194
127#define OID_RT_SET_NO_AUTO_RESCAN 0xFF010195
128#define OID_RT_GET_PREAMBLE_MODE 0xFF010196
129#define OID_RT_GET_DRIVER_UP_DELTA_TIME 0xFF010197
130#define OID_RT_GET_AP_IP 0xFF010198
131#define OID_RT_GET_CHANNELPLAN 0xFF010199
132#define OID_RT_SET_PREAMBLE_MODE 0xFF01019A
133#define OID_RT_SET_BCN_INTVL 0xFF01019B
134#define OID_RT_GET_RF_VENDER 0xFF01019C
135#define OID_RT_DEDICATE_PROBE 0xFF01019D
136#define OID_RT_PRO_RX_FILTER_PATTERN 0xFF01019E
137
138#define OID_RT_GET_DCST_CURRENT_THRESHOLD 0xFF01019F
139
140#define OID_RT_GET_CCA_ERR 0xFF0101A0
141#define OID_RT_GET_CCA_UPGRADE_THRESHOLD 0xFF0101A1
142#define OID_RT_GET_CCA_FALLBACK_THRESHOLD 0xFF0101A2
143
144#define OID_RT_GET_CCA_UPGRADE_EVALUATE_TIMES 0xFF0101A3
145#define OID_RT_GET_CCA_FALLBACK_EVALUATE_TIMES 0xFF0101A4
146
147/* by Owen on 03/31/03 for Cameo's request */
148#define OID_RT_SET_RATE_ADAPTIVE 0xFF0101A5
149/* */
150#define OID_RT_GET_DCST_EVALUATE_PERIOD 0xFF0101A5
151#define OID_RT_GET_DCST_TIME_UNIT_INDEX 0xFF0101A6
152#define OID_RT_GET_TOTAL_TX_BYTES 0xFF0101A7
153#define OID_RT_GET_TOTAL_RX_BYTES 0xFF0101A8
154#define OID_RT_CURRENT_TX_POWER_LEVEL 0xFF0101A9
155#define OID_RT_GET_ENC_KEY_MISMATCH_COUNT 0xFF0101AA
156#define OID_RT_GET_ENC_KEY_MATCH_COUNT 0xFF0101AB
157#define OID_RT_GET_CHANNEL 0xFF0101AC
158
159#define OID_RT_SET_CHANNELPLAN 0xFF0101AD
160#define OID_RT_GET_HARDWARE_RADIO_OFF 0xFF0101AE
161#define OID_RT_CHANNELPLAN_BY_COUNTRY 0xFF0101AF
162#define OID_RT_SCAN_AVAILABLE_BSSID 0xFF0101B0
163#define OID_RT_GET_HARDWARE_VERSION 0xFF0101B1
164#define OID_RT_GET_IS_ROAMING 0xFF0101B2
165#define OID_RT_GET_IS_PRIVACY 0xFF0101B3
166#define OID_RT_GET_KEY_MISMATCH 0xFF0101B4
167#define OID_RT_SET_RSSI_ROAM_TRAFFIC_TH 0xFF0101B5
168#define OID_RT_SET_RSSI_ROAM_SIGNAL_TH 0xFF0101B6
169#define OID_RT_RESET_LOG 0xFF0101B7
170#define OID_RT_GET_LOG 0xFF0101B8
171#define OID_RT_SET_INDICATE_HIDDEN_AP 0xFF0101B9
172#define OID_RT_GET_HEADER_FAIL 0xFF0101BA
173#define OID_RT_SUPPORTED_WIRELESS_MODE 0xFF0101BB
174#define OID_RT_GET_CHANNEL_LIST 0xFF0101BC
175#define OID_RT_GET_SCAN_IN_PROGRESS 0xFF0101BD
176#define OID_RT_GET_TX_INFO 0xFF0101BE
177#define OID_RT_RF_READ_WRITE_OFFSET 0xFF0101BF
178#define OID_RT_RF_READ_WRITE 0xFF0101C0
179
180/* For Netgear request. 2005.01.13, by rcnjko. */
181#define OID_RT_FORCED_DATA_RATE 0xFF0101C1
182#define OID_RT_WIRELESS_MODE_FOR_SCAN_LIST 0xFF0101C2
183/* For Netgear request. 2005.02.17, by rcnjko. */
184#define OID_RT_GET_BSS_WIRELESS_MODE 0xFF0101C3
185/* For AZ project. 2005.06.27, by rcnjko. */
186#define OID_RT_SCAN_WITH_MAGIC_PACKET 0xFF0101C4
187
188/* Vincent 8185MP */
189#define OID_RT_PRO_RX_FILTER 0xFF0111C0
190
191/* Andy TEST */
192/* define OID_RT_PRO_WRITE_REGISTRY 0xFF0111C1 */
193/* define OID_RT_PRO_READ_REGISTRY 0xFF0111C2 */
194#define OID_CE_USB_WRITE_REGISTRY 0xFF0111C1
195#define OID_CE_USB_READ_REGISTRY 0xFF0111C2
196
197
198#define OID_RT_PRO_SET_INITIAL_GAIN 0xFF0111C3
199#define OID_RT_PRO_SET_BB_RF_STANDBY_MODE 0xFF0111C4
200#define OID_RT_PRO_SET_BB_RF_SHUTDOWN_MODE 0xFF0111C5
201#define OID_RT_PRO_SET_TX_CHARGE_PUMP 0xFF0111C6
202#define OID_RT_PRO_SET_RX_CHARGE_PUMP 0xFF0111C7
203#define OID_RT_PRO_RF_WRITE_REGISTRY 0xFF0111C8
204#define OID_RT_PRO_RF_READ_REGISTRY 0xFF0111C9
205#define OID_RT_PRO_QUERY_RF_TYPE 0xFF0111CA
206
207/* AP OID */
208#define OID_RT_AP_GET_ASSOCIATED_STATION_LIST 0xFF010300
209#define OID_RT_AP_GET_CURRENT_TIME_STAMP 0xFF010301
210#define OID_RT_AP_SWITCH_INTO_AP_MODE 0xFF010302
211#define OID_RT_AP_SET_DTIM_PERIOD 0xFF010303
212#define OID_RT_AP_SUPPORTED 0xFF010304 /* Determine if driver supports AP mode. 2004.08.27, by rcnjko. */
213#define OID_RT_AP_SET_PASSPHRASE 0xFF010305 /* Set WPA-PSK passphrase into authenticator. 2005.07.08, byrcnjko. */
214
215/* 8187MP. 2004.09.06, by rcnjko. */
216#define OID_RT_PRO8187_WI_POLL 0xFF818780
217#define OID_RT_PRO_WRITE_BB_REG 0xFF818781
218#define OID_RT_PRO_READ_BB_REG 0xFF818782
219#define OID_RT_PRO_WRITE_RF_REG 0xFF818783
220#define OID_RT_PRO_READ_RF_REG 0xFF818784
221
222/* Meeting House. added by Annie, 2005-07-20. */
223#define OID_RT_MH_VENDER_ID 0xFFEDC100
224
225/* 8711 MP OID added 20051230. */
226#define OID_RT_PRO8711_JOIN_BSS 0xFF871100/* S */
227
228#define OID_RT_PRO_READ_REGISTER 0xFF871101 /* Q */
229#define OID_RT_PRO_WRITE_REGISTER 0xFF871102 /* S */
230
231#define OID_RT_PRO_BURST_READ_REGISTER 0xFF871103 /* Q */
232#define OID_RT_PRO_BURST_WRITE_REGISTER 0xFF871104 /* S */
233
234#define OID_RT_PRO_WRITE_TXCMD 0xFF871105 /* S */
235
236#define OID_RT_PRO_READ16_EEPROM 0xFF871106 /* Q */
237#define OID_RT_PRO_WRITE16_EEPROM 0xFF871107 /* S */
238
239#define OID_RT_PRO_H2C_SET_COMMAND 0xFF871108 /* S */
240#define OID_RT_PRO_H2C_QUERY_RESULT 0xFF871109 /* Q */
241
242#define OID_RT_PRO8711_WI_POLL 0xFF87110A /* Q */
243#define OID_RT_PRO8711_PKT_LOSS 0xFF87110B /* Q */
244#define OID_RT_RD_ATTRIB_MEM 0xFF87110C/* Q */
245#define OID_RT_WR_ATTRIB_MEM 0xFF87110D/* S */
246
247
248/* Method 2 for H2C/C2H */
249#define OID_RT_PRO_H2C_CMD_MODE 0xFF871110 /* S */
250#define OID_RT_PRO_H2C_CMD_RSP_MODE 0xFF871111 /* Q */
251#define OID_RT_PRO_H2C_CMD_EVENT_MODE 0xFF871112 /* S */
252#define OID_RT_PRO_WAIT_C2H_EVENT 0xFF871113 /* Q */
253#define OID_RT_PRO_RW_ACCESS_PROTOCOL_TEST 0xFF871114/* Q */
254
255#define OID_RT_PRO_SCSI_ACCESS_TEST 0xFF871115 /* Q, S */
256
257#define OID_RT_PRO_SCSI_TCPIPOFFLOAD_OUT 0xFF871116 /* S */
258#define OID_RT_PRO_SCSI_TCPIPOFFLOAD_IN 0xFF871117 /* Q,S */
259#define OID_RT_RRO_RX_PKT_VIA_IOCTRL 0xFF871118 /* Q */
260#define OID_RT_RRO_RX_PKTARRAY_VIA_IOCTRL 0xFF871119 /* Q */
261
262#define OID_RT_RPO_SET_PWRMGT_TEST 0xFF87111A /* S */
263#define OID_RT_PRO_QRY_PWRMGT_TEST 0XFF87111B /* Q */
264#define OID_RT_RPO_ASYNC_RWIO_TEST 0xFF87111C /* S */
265#define OID_RT_RPO_ASYNC_RWIO_POLL 0xFF87111D /* Q */
266#define OID_RT_PRO_SET_RF_INTFS 0xFF87111E /* S */
267#define OID_RT_POLL_RX_STATUS 0xFF87111F /* Q */
268
269#define OID_RT_PRO_CFG_DEBUG_MESSAGE 0xFF871120 /* Q,S */
270#define OID_RT_PRO_SET_DATA_RATE_EX 0xFF871121/* S */
271#define OID_RT_PRO_SET_BASIC_RATE 0xFF871122/* S */
272#define OID_RT_PRO_READ_TSSI 0xFF871123/* S */
273#define OID_RT_PRO_SET_POWER_TRACKING 0xFF871124/* S */
274
275
276#define OID_RT_PRO_QRY_PWRSTATE 0xFF871150 /* Q */
277#define OID_RT_PRO_SET_PWRSTATE 0xFF871151 /* S */
278
279/* Method 2 , using workitem */
280#define OID_RT_SET_READ_REG 0xFF871181 /* S */
281#define OID_RT_SET_WRITE_REG 0xFF871182 /* S */
282#define OID_RT_SET_BURST_READ_REG 0xFF871183 /* S */
283#define OID_RT_SET_BURST_WRITE_REG 0xFF871184 /* S */
284#define OID_RT_SET_WRITE_TXCMD 0xFF871185 /* S */
285#define OID_RT_SET_READ16_EEPROM 0xFF871186 /* S */
286#define OID_RT_SET_WRITE16_EEPROM 0xFF871187 /* S */
287#define OID_RT_QRY_POLL_WKITEM 0xFF871188 /* Q */
288
289/* For SDIO INTERFACE only */
290#define OID_RT_PRO_SYNCPAGERW_SRAM 0xFF8711A0 /* Q, S */
291#define OID_RT_PRO_871X_DRV_EXT 0xFF8711A1
292
293/* For USB INTERFACE only */
294#define OID_RT_PRO_USB_VENDOR_REQ 0xFF8711B0 /* Q, S */
295#define OID_RT_PRO_SCSI_AUTO_TEST 0xFF8711B1 /* S */
296#define OID_RT_PRO_USB_MAC_AC_FIFO_WRITE 0xFF8711B2 /* S */
297#define OID_RT_PRO_USB_MAC_RX_FIFO_READ 0xFF8711B3 /* Q */
298#define OID_RT_PRO_USB_MAC_RX_FIFO_POLLING 0xFF8711B4 /* Q */
299
300#define OID_RT_PRO_H2C_SET_RATE_TABLE 0xFF8711FB /* S */
301#define OID_RT_PRO_H2C_GET_RATE_TABLE 0xFF8711FC /* S */
302#define OID_RT_PRO_H2C_C2H_LBK_TEST 0xFF8711FE
303
304#define OID_RT_PRO_ENCRYPTION_CTRL 0xFF871200 /* Q, S */
305#define OID_RT_PRO_ADD_STA_INFO 0xFF871201 /* S */
306#define OID_RT_PRO_DELE_STA_INFO 0xFF871202 /* S */
307#define OID_RT_PRO_QUERY_DR_VARIABLE 0xFF871203 /* Q */
308
309#define OID_RT_PRO_RX_PACKET_TYPE 0xFF871204 /* Q, S */
310
311#define OID_RT_PRO_READ_EFUSE 0xFF871205 /* Q */
312#define OID_RT_PRO_WRITE_EFUSE 0xFF871206 /* S */
313#define OID_RT_PRO_RW_EFUSE_PGPKT 0xFF871207 /* Q, S */
314#define OID_RT_GET_EFUSE_CURRENT_SIZE 0xFF871208 /* Q */
315
316#define OID_RT_SET_BANDWIDTH 0xFF871209 /* S */
317#define OID_RT_SET_CRYSTAL_CAP 0xFF87120A /* S */
318
319#define OID_RT_SET_RX_PACKET_TYPE 0xFF87120B /* S */
320
321#define OID_RT_GET_EFUSE_MAX_SIZE 0xFF87120C /* Q */
322
323#define OID_RT_PRO_SET_TX_AGC_OFFSET 0xFF87120D /* S */
324
325#define OID_RT_PRO_SET_PKT_TEST_MODE 0xFF87120E /* S */
326
327#define OID_RT_PRO_FOR_EVM_TEST_SETTING 0xFF87120F /* S */
328
329#define OID_RT_PRO_GET_THERMAL_METER 0xFF871210 /* Q */
330
331#define OID_RT_RESET_PHY_RX_PACKET_COUNT 0xFF871211 /* S */
332#define OID_RT_GET_PHY_RX_PACKET_RECEIVED 0xFF871212 /* Q */
333#define OID_RT_GET_PHY_RX_PACKET_CRC32_ERROR 0xFF871213 /* Q */
334
335#define OID_RT_SET_POWER_DOWN 0xFF871214 /* S */
336
337#define OID_RT_GET_POWER_MODE 0xFF871215 /* Q */
338
339#define OID_RT_PRO_EFUSE 0xFF871216 /* Q, S */
340#define OID_RT_PRO_EFUSE_MAP 0xFF871217 /* Q, S */
341
342#endif /* ifndef __CUSTOM_OID_H */
diff --git a/drivers/staging/rtl8723au/include/odm.h b/drivers/staging/rtl8723au/include/odm.h
new file mode 100644
index 000000000000..dfedfbb48fc2
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/odm.h
@@ -0,0 +1,1205 @@
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 ******************************************************************************/
15
16
17#ifndef __HALDMOUTSRC_H__
18#define __HALDMOUTSRC_H__
19
20/* */
21/* Definition */
22/* */
23/* */
24/* 2011/09/22 MH Define all team supprt ability. */
25/* */
26
27/* */
28/* 2011/09/22 MH Define for all teams. Please Define the constan in your precomp header. */
29/* */
30/* define DM_ODM_SUPPORT_AP 0 */
31/* define DM_ODM_SUPPORT_ADSL 0 */
32/* define DM_ODM_SUPPORT_CE 0 */
33/* define DM_ODM_SUPPORT_MP 1 */
34
35#define TP_MODE 0
36#define RSSI_MODE 1
37#define TRAFFIC_LOW 0
38#define TRAFFIC_HIGH 1
39
40
41/* */
42/* 3 Tx Power Tracking */
43/* 3============================================================ */
44#define DPK_DELTA_MAPPING_NUM 13
45#define index_mapping_HP_NUM 15
46
47
48/* */
49/* 3 PSD Handler */
50/* 3============================================================ */
51
52#define AFH_PSD 1 /* 0:normal PSD scan, 1: only do 20 pts PSD */
53#define MODE_40M 0 /* 0:20M, 1:40M */
54#define PSD_TH2 3
55#define PSD_CHMIN 20 /* Minimum channel number for BT AFH */
56#define SIR_STEP_SIZE 3
57#define Smooth_Size_1 5
58#define Smooth_TH_1 3
59#define Smooth_Size_2 10
60#define Smooth_TH_2 4
61#define Smooth_Size_3 20
62#define Smooth_TH_3 4
63#define Smooth_Step_Size 5
64#define Adaptive_SIR 1
65#define PSD_RESCAN 4
66#define PSD_SCAN_INTERVAL 700 /* ms */
67
68/* 8723A High Power IGI Setting */
69#define DM_DIG_HIGH_PWR_IGI_LOWER_BOUND 0x22
70#define DM_DIG_Gmode_HIGH_PWR_IGI_LOWER_BOUND 0x28
71#define DM_DIG_HIGH_PWR_THRESHOLD 0x3a
72
73/* LPS define */
74#define DM_DIG_FA_TH0_LPS 4 /* 4 in lps */
75#define DM_DIG_FA_TH1_LPS 15 /* 15 lps */
76#define DM_DIG_FA_TH2_LPS 30 /* 30 lps */
77#define RSSI_OFFSET_DIG 0x05;
78
79/* ANT Test */
80#define ANTTESTALL 0x00 /* Ant A or B will be Testing */
81#define ANTTESTA 0x01 /* Ant A will be Testing */
82#define ANTTESTB 0x02 /* Ant B will be testing */
83
84
85/* */
86/* structure and define */
87/* */
88
89/* */
90/* 2011/09/20 MH Add for AP/ADSLpseudo DM structuer requirement. */
91/* We need to remove to other position??? */
92/* */
93struct rtl8723a_priv {
94 u8 temp;
95};
96
97
98struct dig_t {
99 u8 Dig_Enable_Flag;
100 u8 Dig_Ext_Port_Stage;
101
102 int RssiLowThresh;
103 int RssiHighThresh;
104
105 u32 FALowThresh;
106 u32 FAHighThresh;
107
108 u8 CurSTAConnectState;
109 u8 PreSTAConnectState;
110 u8 CurMultiSTAConnectState;
111
112 u8 PreIGValue;
113 u8 CurIGValue;
114 u8 BackupIGValue;
115
116 s8 BackoffVal;
117 s8 BackoffVal_range_max;
118 s8 BackoffVal_range_min;
119 u8 rx_gain_range_max;
120 u8 rx_gain_range_min;
121 u8 Rssi_val_min;
122
123 u8 PreCCK_CCAThres;
124 u8 CurCCK_CCAThres;
125 u8 PreCCKPDState;
126 u8 CurCCKPDState;
127
128 u8 LargeFAHit;
129 u8 ForbiddenIGI;
130 u32 Recover_cnt;
131
132 u8 DIG_Dynamic_MIN_0;
133 u8 DIG_Dynamic_MIN_1;
134 bool bMediaConnect_0;
135 bool bMediaConnect_1;
136
137 u32 AntDiv_RSSI_max;
138 u32 RSSI_max;
139};
140
141struct dynamic_pwr_sav {
142 u8 PreCCAState;
143 u8 CurCCAState;
144
145 u8 PreRFState;
146 u8 CurRFState;
147
148 int Rssi_val_min;
149
150 u8 initialize;
151 u32 Reg874,RegC70,Reg85C,RegA74;
152};
153
154struct false_alarm_stats {
155 u32 Cnt_Parity_Fail;
156 u32 Cnt_Rate_Illegal;
157 u32 Cnt_Crc8_fail;
158 u32 Cnt_Mcs_fail;
159 u32 Cnt_Ofdm_fail;
160 u32 Cnt_Cck_fail;
161 u32 Cnt_all;
162 u32 Cnt_Fast_Fsync;
163 u32 Cnt_SB_Search_fail;
164 u32 Cnt_OFDM_CCA;
165 u32 Cnt_CCK_CCA;
166 u32 Cnt_CCA_all;
167 u32 Cnt_BW_USC; /* Gary */
168 u32 Cnt_BW_LSC; /* Gary */
169};
170
171struct pri_cca {
172 u8 PriCCA_flag;
173 u8 intf_flag;
174 u8 intf_type;
175 u8 DupRTS_flag;
176 u8 Monitor_flag;
177};
178
179struct rx_hp {
180 u8 RXHP_flag;
181 u8 PSD_func_trigger;
182 u8 PSD_bitmap_RXHP[80];
183 u8 Pre_IGI;
184 u8 Cur_IGI;
185 u8 Pre_pw_th;
186 u8 Cur_pw_th;
187 bool First_time_enter;
188 bool RXHP_enable;
189 u8 TP_Mode;
190 struct timer_list PSDTimer;
191};
192
193#define ASSOCIATE_ENTRY_NUM 32 /* Max size of AsocEntry[]. */
194#define ODM_ASSOCIATE_ENTRY_NUM ASSOCIATE_ENTRY_NUM
195
196/* This indicates two different the steps. */
197/* In SWAW_STEP_PEAK, driver needs to switch antenna and listen to the signal on the air. */
198/* In SWAW_STEP_DETERMINE, driver just compares the signal captured in SWAW_STEP_PEAK */
199/* with original RSSI to determine if it is necessary to switch antenna. */
200#define SWAW_STEP_PEAK 0
201#define SWAW_STEP_DETERMINE 1
202
203#define TP_MODE 0
204#define RSSI_MODE 1
205#define TRAFFIC_LOW 0
206#define TRAFFIC_HIGH 1
207
208struct sw_ant_sw {
209 u8 try_flag;
210 s32 PreRSSI;
211 u8 CurAntenna;
212 u8 PreAntenna;
213 u8 RSSI_Trying;
214 u8 TestMode;
215 u8 bTriggerAntennaSwitch;
216 u8 SelectAntennaMap;
217 u8 RSSI_target;
218
219 /* Before link Antenna Switch check */
220 u8 SWAS_NoLink_State;
221 u32 SWAS_NoLink_BK_Reg860;
222 bool ANTA_ON; /* To indicate Ant A is or not */
223 bool ANTB_ON; /* To indicate Ant B is on or not */
224
225 s32 RSSI_sum_A;
226 s32 RSSI_sum_B;
227 s32 RSSI_cnt_A;
228 s32 RSSI_cnt_B;
229
230 u64 lastTxOkCnt;
231 u64 lastRxOkCnt;
232 u64 TXByteCnt_A;
233 u64 TXByteCnt_B;
234 u64 RXByteCnt_A;
235 u64 RXByteCnt_B;
236 u8 TrafficLoad;
237 struct timer_list SwAntennaSwitchTimer;
238};
239
240struct edca_turbo {
241 bool bCurrentTurboEDCA;
242 bool bIsCurRDLState;
243 u32 prv_traffic_idx; /* edca turbo */
244
245};
246
247struct odm_rate_adapt {
248 u8 Type; /* DM_Type_ByFW/DM_Type_ByDriver */
249 u8 HighRSSIThresh; /* if RSSI > HighRSSIThresh => RATRState is DM_RATR_STA_HIGH */
250 u8 LowRSSIThresh; /* if RSSI <= LowRSSIThresh => RATRState is DM_RATR_STA_LOW */
251 u8 RATRState; /* Current RSSI level, DM_RATR_STA_HIGH/DM_RATR_STA_MIDDLE/DM_RATR_STA_LOW */
252 u32 LastRATR; /* RATR Register Content */
253};
254
255#define IQK_MAC_REG_NUM 4
256#define IQK_ADDA_REG_NUM 16
257#define IQK_BB_REG_NUM_MAX 10
258#define IQK_BB_REG_NUM 9
259#define HP_THERMAL_NUM 8
260
261#define AVG_THERMAL_NUM 8
262#define IQK_Matrix_REG_NUM 8
263#define IQK_Matrix_Settings_NUM 1+24+21
264
265#define DM_Type_ByFW 0
266#define DM_Type_ByDriver 1
267
268/* Declare for common info */
269
270struct odm_phy_info {
271 u8 RxPWDBAll;
272 u8 SignalQuality; /* in 0-100 index. */
273 u8 RxMIMOSignalQuality[RF_PATH_MAX]; /* EVM */
274 u8 RxMIMOSignalStrength[RF_PATH_MAX];/* in 0~100 index */
275 s8 RxPower; /* in dBm Translate from PWdB */
276 s8 RecvSignalPower;/* Real power in dBm for this packet, no beautification and aggregation. Keep this raw info to be used for the other procedures. */
277 u8 BTRxRSSIPercentage;
278 u8 SignalStrength; /* in 0-100 index. */
279 u8 RxPwr[RF_PATH_MAX];/* per-path's pwdb */
280 u8 RxSNR[RF_PATH_MAX];/* per-path's SNR */
281};
282
283
284struct odm_phy_dbg_info {
285 /* ODM Write,debug info */
286 s8 RxSNRdB[RF_PATH_MAX];
287 u64 NumQryPhyStatus;
288 u64 NumQryPhyStatusCCK;
289 u64 NumQryPhyStatusOFDM;
290 /* Others */
291 s32 RxEVM[RF_PATH_MAX];
292
293};
294
295struct odm_packet_info {
296 u8 Rate;
297 u8 StationID;
298 bool bPacketMatchBSSID;
299 bool bPacketToSelf;
300 bool bPacketBeacon;
301};
302
303struct odm_mac_info {
304 u8 test;
305
306};
307
308
309enum {
310 /* BB Team */
311 ODM_DIG = 0x00000001,
312 ODM_HIGH_POWER = 0x00000002,
313 ODM_CCK_CCA_TH = 0x00000004,
314 ODM_FA_STATISTICS = 0x00000008,
315 ODM_RAMASK = 0x00000010,
316 ODM_RSSI_MONITOR = 0x00000020,
317 ODM_SW_ANTDIV = 0x00000040,
318 ODM_HW_ANTDIV = 0x00000080,
319 ODM_BB_PWRSV = 0x00000100,
320 ODM_2TPATHDIV = 0x00000200,
321 ODM_1TPATHDIV = 0x00000400,
322 ODM_PSD2AFH = 0x00000800
323};
324
325/* */
326/* 2011/20/20 MH For MP driver RT_WLAN_STA = struct sta_info */
327/* Please declare below ODM relative info in your STA info structure. */
328/* */
329struct odm_sta_info {
330 /* Driver Write */
331 bool bUsed; /* record the sta status link or not? */
332 u8 IOTPeer; /* Enum value. HT_IOT_PEER_E */
333
334 /* ODM Write */
335 /* 1 PHY_STATUS_INFO */
336 u8 RSSI_Path[4]; /* */
337 u8 RSSI_Ave;
338 u8 RXEVM[4];
339 u8 RXSNR[4];
340
341 /* ODM Write */
342 /* 1 TX_INFO (may changed by IC) */
343
344 /* */
345 /* Please use compile flag to disable the structure for other IC except 88E. */
346 /* Move To lower layer. */
347 /* */
348 /* ODM Write Wilson will handle this part(said by Luke.Lee) */
349};
350
351/* */
352/* 2011/10/20 MH Define Common info enum for all team. */
353/* */
354
355enum odm_cmninfo {
356 /* Fixed value: */
357 /* */
358
359 ODM_CMNINFO_PLATFORM = 0,
360 ODM_CMNINFO_ABILITY, /* enum odm_ability */
361 ODM_CMNINFO_INTERFACE, /* enum odm_interface_def */
362 ODM_CMNINFO_MP_TEST_CHIP,
363 ODM_CMNINFO_IC_TYPE, /* enum odm_ic_type_def */
364 ODM_CMNINFO_CUT_VER, /* enum odm_cut_version */
365 ODM_CMNINFO_FAB_VER, /* enum odm_fab_version */
366 ODM_CMNINFO_RF_TYPE, /* enum rf_path_def or enum odm_rf_type? */
367 ODM_CMNINFO_BOARD_TYPE, /* enum odm_board_type */
368 ODM_CMNINFO_EXT_LNA, /* true */
369 ODM_CMNINFO_EXT_PA,
370 ODM_CMNINFO_EXT_TRSW,
371 ODM_CMNINFO_PATCH_ID, /* CUSTOMER ID */
372 ODM_CMNINFO_BINHCT_TEST,
373 ODM_CMNINFO_BWIFI_TEST,
374 ODM_CMNINFO_SMART_CONCURRENT,
375
376
377 /* */
378 /* Dynamic value: */
379 /* */
380 ODM_CMNINFO_MAC_PHY_MODE, /* enum odm_mac_phy_mode */
381 ODM_CMNINFO_TX_UNI,
382 ODM_CMNINFO_RX_UNI,
383 ODM_CMNINFO_WM_MODE, /* enum odm_wireless_mode */
384 ODM_CMNINFO_BAND, /* enum odm_band_type */
385 ODM_CMNINFO_SEC_CHNL_OFFSET, /* enum odm_sec_chnl_offset */
386 ODM_CMNINFO_SEC_MODE, /* enum odm_security */
387 ODM_CMNINFO_BW, /* enum odm_band_width */
388 ODM_CMNINFO_CHNL,
389
390 ODM_CMNINFO_DMSP_GET_VALUE,
391 ODM_CMNINFO_BUDDY_ADAPTOR,
392 ODM_CMNINFO_DMSP_IS_MASTER,
393 ODM_CMNINFO_SCAN,
394 ODM_CMNINFO_POWER_SAVING,
395 ODM_CMNINFO_ONE_PATH_CCA, /* enum odm_cca_path */
396 ODM_CMNINFO_DRV_STOP,
397 ODM_CMNINFO_PNP_IN,
398 ODM_CMNINFO_INIT_ON,
399 ODM_CMNINFO_ANT_TEST,
400 ODM_CMNINFO_NET_CLOSED,
401 ODM_CMNINFO_MP_MODE,
402
403 ODM_CMNINFO_WIFI_DIRECT,
404 ODM_CMNINFO_WIFI_DISPLAY,
405 ODM_CMNINFO_LINK,
406 ODM_CMNINFO_RSSI_MIN,
407 ODM_CMNINFO_DBG_COMP, /* u64 */
408 ODM_CMNINFO_DBG_LEVEL, /* u32 */
409 ODM_CMNINFO_RA_THRESHOLD_HIGH, /* u8 */
410 ODM_CMNINFO_RA_THRESHOLD_LOW, /* u8 */
411 ODM_CMNINFO_RF_ANTENNA_TYPE, /* u8 */
412 ODM_CMNINFO_BT_DISABLED,
413 ODM_CMNINFO_BT_OPERATION,
414 ODM_CMNINFO_BT_DIG,
415 ODM_CMNINFO_BT_BUSY, /* Check Bt is using or not */
416 ODM_CMNINFO_BT_DISABLE_EDCA,
417
418 /* */
419 /* Dynamic ptr array hook itms. */
420 /* */
421 ODM_CMNINFO_STA_STATUS,
422 ODM_CMNINFO_PHY_STATUS,
423 ODM_CMNINFO_MAC_STATUS,
424
425 ODM_CMNINFO_MAX,
426};
427
428/* Define ODM support ability. ODM_CMNINFO_ABILITY */
429enum {
430 /* BB ODM section BIT 0-15 */
431 ODM_BB_DIG = BIT0,
432 ODM_BB_RA_MASK = BIT1,
433 ODM_BB_DYNAMIC_TXPWR = BIT2,
434 ODM_BB_FA_CNT = BIT3,
435 ODM_BB_RSSI_MONITOR = BIT4,
436 ODM_BB_CCK_PD = BIT5,
437 ODM_BB_ANT_DIV = BIT6,
438 ODM_BB_PWR_SAVE = BIT7,
439 ODM_BB_PWR_TRAIN = BIT8,
440 ODM_BB_RATE_ADAPTIVE = BIT9,
441 ODM_BB_PATH_DIV = BIT10,
442 ODM_BB_PSD = BIT11,
443 ODM_BB_RXHP = BIT12,
444
445 /* MAC DM section BIT 16-23 */
446 ODM_MAC_EDCA_TURBO = BIT16,
447 ODM_MAC_EARLY_MODE = BIT17,
448
449 /* RF ODM section BIT 24-31 */
450 ODM_RF_TX_PWR_TRACK = BIT24,
451 ODM_RF_RX_GAIN_TRACK = BIT25,
452 ODM_RF_CALIBRATION = BIT26,
453
454};
455
456/* ODM_CMNINFO_INTERFACE */
457enum odm_interface_def {
458 ODM_ITRF_PCIE = 0x1,
459 ODM_ITRF_USB = 0x2,
460 ODM_ITRF_SDIO = 0x4,
461 ODM_ITRF_ALL = 0x7,
462};
463
464/* ODM_CMNINFO_IC_TYPE */
465enum odm_ic_type_def {
466 ODM_RTL8192S = BIT0,
467 ODM_RTL8192C = BIT1,
468 ODM_RTL8192D = BIT2,
469 ODM_RTL8723A = BIT3,
470 ODM_RTL8188E = BIT4,
471 ODM_RTL8812 = BIT5,
472 ODM_RTL8821 = BIT6,
473};
474
475#define ODM_IC_11N_SERIES \
476 (ODM_RTL8192S|ODM_RTL8192C|ODM_RTL8192D|ODM_RTL8723A|ODM_RTL8188E)
477#define ODM_IC_11AC_SERIES (ODM_RTL8812)
478
479/* ODM_CMNINFO_CUT_VER */
480enum odm_cut_version {
481 ODM_CUT_A = 1,
482 ODM_CUT_B = 2,
483 ODM_CUT_C = 3,
484 ODM_CUT_D = 4,
485 ODM_CUT_E = 5,
486 ODM_CUT_F = 6,
487 ODM_CUT_TEST = 7,
488};
489
490/* ODM_CMNINFO_FAB_VER */
491enum odm_fab_version {
492 ODM_TSMC = 0,
493 ODM_UMC = 1,
494};
495
496/* ODM_CMNINFO_RF_TYPE */
497/* For example 1T2R (A+AB = BIT0|BIT4|BIT5) */
498enum rf_path_def {
499 ODM_RF_TX_A = BIT0,
500 ODM_RF_TX_B = BIT1,
501 ODM_RF_TX_C = BIT2,
502 ODM_RF_TX_D = BIT3,
503 ODM_RF_RX_A = BIT4,
504 ODM_RF_RX_B = BIT5,
505 ODM_RF_RX_C = BIT6,
506 ODM_RF_RX_D = BIT7,
507};
508
509
510enum odm_rf_type {
511 ODM_1T1R = 0,
512 ODM_1T2R = 1,
513 ODM_2T2R = 2,
514 ODM_2T3R = 3,
515 ODM_2T4R = 4,
516 ODM_3T3R = 5,
517 ODM_3T4R = 6,
518 ODM_4T4R = 7,
519};
520
521/* ODM Dynamic common info value definition */
522
523enum odm_mac_phy_mode {
524 ODM_SMSP = 0,
525 ODM_DMSP = 1,
526 ODM_DMDP = 2,
527};
528
529
530enum odm_bt_coexist {
531 ODM_BT_BUSY = 1,
532 ODM_BT_ON = 2,
533 ODM_BT_OFF = 3,
534 ODM_BT_NONE = 4,
535};
536
537/* ODM_CMNINFO_OP_MODE */
538enum odm_operation_mode {
539 ODM_NO_LINK = BIT0,
540 ODM_LINK = BIT1,
541 ODM_SCAN = BIT2,
542 ODM_POWERSAVE = BIT3,
543 ODM_AP_MODE = BIT4,
544 ODM_CLIENT_MODE = BIT5,
545 ODM_AD_HOC = BIT6,
546 ODM_WIFI_DIRECT = BIT7,
547 ODM_WIFI_DISPLAY = BIT8,
548};
549
550/* ODM_CMNINFO_WM_MODE */
551enum odm_wireless_mode {
552 ODM_WM_UNKNOW = 0x0,
553 ODM_WM_B = BIT0,
554 ODM_WM_G = BIT1,
555 ODM_WM_A = BIT2,
556 ODM_WM_N24G = BIT3,
557 ODM_WM_N5G = BIT4,
558 ODM_WM_AUTO = BIT5,
559 ODM_WM_AC = BIT6,
560};
561
562/* ODM_CMNINFO_BAND */
563enum odm_band_type {
564 ODM_BAND_2_4G = BIT0,
565 ODM_BAND_5G = BIT1,
566
567};
568
569/* ODM_CMNINFO_SEC_CHNL_OFFSET */
570enum odm_sec_chnl_offset {
571 ODM_DONT_CARE = 0,
572 ODM_BELOW = 1,
573 ODM_ABOVE = 2
574};
575
576/* ODM_CMNINFO_SEC_MODE */
577enum odm_security {
578 ODM_SEC_OPEN = 0,
579 ODM_SEC_WEP40 = 1,
580 ODM_SEC_TKIP = 2,
581 ODM_SEC_RESERVE = 3,
582 ODM_SEC_AESCCMP = 4,
583 ODM_SEC_WEP104 = 5,
584 ODM_WEP_WPA_MIXED = 6, /* WEP + WPA */
585 ODM_SEC_SMS4 = 7,
586};
587
588/* ODM_CMNINFO_BW */
589enum odm_band_width {
590 ODM_BW20M = 0,
591 ODM_BW40M = 1,
592 ODM_BW80M = 2,
593 ODM_BW160M = 3,
594 ODM_BW10M = 4,
595};
596
597/* ODM_CMNINFO_CHNL */
598
599/* ODM_CMNINFO_BOARD_TYPE */
600enum odm_board_type {
601 ODM_BOARD_NORMAL = 0,
602 ODM_BOARD_HIGHPWR = 1,
603 ODM_BOARD_MINICARD = 2,
604 ODM_BOARD_SLIM = 3,
605 ODM_BOARD_COMBO = 4,
606
607};
608
609/* ODM_CMNINFO_ONE_PATH_CCA */
610enum odm_cca_path {
611 ODM_CCA_2R = 0,
612 ODM_CCA_1R_A = 1,
613 ODM_CCA_1R_B = 2,
614};
615
616struct odm_ra_info {
617 u8 RateID;
618 u32 RateMask;
619 u32 RAUseRate;
620 u8 RateSGI;
621 u8 RssiStaRA;
622 u8 PreRssiStaRA;
623 u8 SGIEnable;
624 u8 DecisionRate;
625 u8 PreRate;
626 u8 HighestRate;
627 u8 LowestRate;
628 u32 NscUp;
629 u32 NscDown;
630 u16 RTY[5];
631 u32 TOTAL;
632 u16 DROP;
633 u8 Active;
634 u16 RptTime;
635 u8 RAWaitingCounter;
636 u8 RAPendingCounter;
637 u8 PTActive; /* on or off */
638 u8 PTTryState; /* 0 trying state, 1 for decision state */
639 u8 PTStage; /* 0~6 */
640 u8 PTStopCount; /* Stop PT counter */
641 u8 PTPreRate; /* if rate change do PT */
642 u8 PTPreRssi; /* if RSSI change 5% do PT */
643 u8 PTModeSS; /* decide whitch rate should do PT */
644 u8 RAstage; /* StageRA, decide how many times RA will be done between PT */
645 u8 PTSmoothFactor;
646};
647
648struct iqk_matrix_regs_set {
649 bool bIQKDone;
650 s32 Value[1][IQK_Matrix_REG_NUM];
651};
652
653struct odm_rf_cal_t {
654 /* for tx power tracking */
655
656 u32 RegA24; /* for TempCCK */
657 s32 RegE94;
658 s32 RegE9C;
659 s32 RegEB4;
660 s32 RegEBC;
661
662 /* u8 bTXPowerTracking; */
663 u8 TXPowercount;
664 bool bTXPowerTrackingInit;
665 bool bTXPowerTracking;
666 u8 TxPowerTrackControl; /* for mp mode, turn off txpwrtracking as default */
667 u8 TM_Trigger;
668 u8 InternalPA5G[2]; /* pathA / pathB */
669
670 u8 ThermalMeter[2]; /* ThermalMeter, index 0 for RFIC0, and 1 for RFIC1 */
671 u8 ThermalValue;
672 u8 ThermalValue_LCK;
673 u8 ThermalValue_IQK;
674 u8 ThermalValue_DPK;
675 u8 ThermalValue_AVG[AVG_THERMAL_NUM];
676 u8 ThermalValue_AVG_index;
677 u8 ThermalValue_RxGain;
678 u8 ThermalValue_Crystal;
679 u8 ThermalValue_DPKstore;
680 u8 ThermalValue_DPKtrack;
681 bool TxPowerTrackingInProgress;
682 bool bDPKenable;
683
684 bool bReloadtxpowerindex;
685 u8 bRfPiEnable;
686 u32 TXPowerTrackingCallbackCnt; /* cosa add for debug */
687
688 u8 bCCKinCH14;
689 u8 CCK_index;
690 u8 OFDM_index[2];
691 bool bDoneTxpower;
692
693 u8 ThermalValue_HP[HP_THERMAL_NUM];
694 u8 ThermalValue_HP_index;
695 struct iqk_matrix_regs_set IQKMatrixRegSetting[IQK_Matrix_Settings_NUM];
696
697 u8 Delta_IQK;
698 u8 Delta_LCK;
699
700 /* for IQK */
701 u32 RegC04;
702 u32 Reg874;
703 u32 RegC08;
704 u32 RegB68;
705 u32 RegB6C;
706 u32 Reg870;
707 u32 Reg860;
708 u32 Reg864;
709
710 bool bIQKInitialized;
711 bool bLCKInProgress;
712 bool bAntennaDetected;
713 u32 ADDA_backup[IQK_ADDA_REG_NUM];
714 u32 IQK_MAC_backup[IQK_MAC_REG_NUM];
715 u32 IQK_BB_backup_recover[9];
716 u32 IQK_BB_backup[IQK_BB_REG_NUM];
717
718 /* for APK */
719 u32 APKoutput[2][2]; /* path A/B; output1_1a/output1_2a */
720 u8 bAPKdone;
721 u8 bAPKThermalMeterIgnore;
722 u8 bDPdone;
723 u8 bDPPathAOK;
724 u8 bDPPathBOK;
725};
726
727/* ODM Dynamic common info value definition */
728struct odm_fat_t {
729 u8 Bssid[6];
730 u8 antsel_rx_keep_0;
731 u8 antsel_rx_keep_1;
732 u8 antsel_rx_keep_2;
733 u32 antSumRSSI[7];
734 u32 antRSSIcnt[7];
735 u32 antAveRSSI[7];
736 u8 FAT_State;
737 u32 TrainIdx;
738 u8 antsel_a[ODM_ASSOCIATE_ENTRY_NUM];
739 u8 antsel_b[ODM_ASSOCIATE_ENTRY_NUM];
740 u8 antsel_c[ODM_ASSOCIATE_ENTRY_NUM];
741 u32 MainAnt_Sum[ODM_ASSOCIATE_ENTRY_NUM];
742 u32 AuxAnt_Sum[ODM_ASSOCIATE_ENTRY_NUM];
743 u32 MainAnt_Cnt[ODM_ASSOCIATE_ENTRY_NUM];
744 u32 AuxAnt_Cnt[ODM_ASSOCIATE_ENTRY_NUM];
745 u8 RxIdleAnt;
746 bool bBecomeLinked;
747};
748
749enum fat_state {
750 FAT_NORMAL_STATE = 0,
751 FAT_TRAINING_STATE = 1,
752};
753
754enum ant_dif_type {
755 NO_ANTDIV = 0xFF,
756 CG_TRX_HW_ANTDIV = 0x01,
757 CGCS_RX_HW_ANTDIV = 0x02,
758 FIXED_HW_ANTDIV = 0x03,
759 CG_TRX_SMART_ANTDIV = 0x04,
760 CGCS_RX_SW_ANTDIV = 0x05,
761};
762
763/* 2011/09/22 MH Copy from SD4 defined structure. We use to support PHY DM integration. */
764struct dm_odm_t {
765 /* struct timer_list FastAntTrainingTimer; */
766 /* */
767 /* Add for different team use temporarily */
768 /* */
769 struct rtw_adapter *Adapter; /* For CE/NIC team */
770 struct rtl8723a_priv *priv; /* For AP/ADSL team */
771 /* WHen you use Adapter or priv pointer, you must make sure the pointer is ready. */
772 bool odm_ready;
773
774 struct rtl8723a_priv fake_priv;
775
776 u64 DebugComponents;
777 u32 DebugLevel;
778
779/* ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */
780 bool bCckHighPower;
781 u8 RFPathRxEnable; /* ODM_CMNINFO_RFPATH_ENABLE */
782 u8 ControlChannel;
783/* ODM HANDLE, DRIVER NEEDS NOT TO HOOK------ */
784
785/* 1 COMMON INFORMATION */
786
787 /* Init Value */
788/* HOOK BEFORE REG INIT----------- */
789 /* ODM Support Ability DIG/RATR/TX_PWR_TRACK/ ¡K¡K = 1/2/3/¡K */
790 u32 SupportAbility;
791 /* ODM PCIE/USB/SDIO/GSPI = 0/1/2/3 */
792 u8 SupportInterface;
793 /* ODM composite or independent. Bit oriented/ 92C+92D+ .... or any other type = 1/2/3/... */
794 u32 SupportICType;
795 /* Cut Version TestChip/A-cut/B-cut... = 0/1/2/3/... */
796 u8 CutVersion;
797 /* Fab Version TSMC/UMC = 0/1 */
798 u8 FabVersion;
799 /* RF Type 4T4R/3T3R/2T2R/1T2R/1T1R/... */
800 u8 RFType;
801 /* Board Type Normal/HighPower/MiniCard/SLIM/Combo/... = 0/1/2/3/4/... */
802 u8 BoardType;
803 /* with external LNA NO/Yes = 0/1 */
804 u8 ExtLNA;
805 /* with external PA NO/Yes = 0/1 */
806 u8 ExtPA;
807 /* with external TRSW NO/Yes = 0/1 */
808 u8 ExtTRSW;
809 u8 PatchID; /* Customer ID */
810 bool bInHctTest;
811 bool bWIFITest;
812
813 bool bDualMacSmartConcurrent;
814 u32 BK_SupportAbility;
815 u8 AntDivType;
816/* HOOK BEFORE REG INIT----------- */
817
818 /* */
819 /* Dynamic Value */
820 /* */
821/* POINTER REFERENCE----------- */
822
823 u8 u8_temp;
824 bool bool_temp;
825 struct rtw_adapter *PADAPTER_temp;
826
827 /* MAC PHY Mode SMSP/DMSP/DMDP = 0/1/2 */
828 u8 *pMacPhyMode;
829 /* TX Unicast byte count */
830 u64 *pNumTxBytesUnicast;
831 /* RX Unicast byte count */
832 u64 *pNumRxBytesUnicast;
833 /* Wireless mode B/G/A/N = BIT0/BIT1/BIT2/BIT3 */
834 u8 *pWirelessMode; /* enum odm_wireless_mode */
835 /* Frequence band 2.4G/5G = 0/1 */
836 u8 *pBandType;
837 /* Secondary channel offset don't_care/below/above = 0/1/2 */
838 u8 *pSecChOffset;
839 /* Security mode Open/WEP/AES/TKIP = 0/1/2/3 */
840 u8 *pSecurity;
841 /* BW info 20M/40M/80M = 0/1/2 */
842 u8 *pBandWidth;
843 /* Central channel location Ch1/Ch2/.... */
844 u8 *pChannel; /* central channel number */
845 /* Common info for 92D DMSP */
846
847 bool *pbGetValueFromOtherMac;
848 struct rtw_adapter **pBuddyAdapter;
849 bool *pbMasterOfDMSP; /* MAC0: master, MAC1: slave */
850 /* Common info for Status */
851 bool *pbScanInProcess;
852 bool *pbPowerSaving;
853 /* CCA Path 2-path/path-A/path-B = 0/1/2; using enum odm_cca_path. */
854 u8 *pOnePathCCA;
855 /* pMgntInfo->AntennaTest */
856 u8 *pAntennaTest;
857 bool *pbNet_closed;
858/* POINTER REFERENCE----------- */
859 /* */
860/* CALL BY VALUE------------- */
861 bool bWIFI_Direct;
862 bool bWIFI_Display;
863 bool bLinked;
864 u8 RSSI_Min;
865 u8 InterfaceIndex; /* Add for 92D dual MAC: 0--Mac0 1--Mac1 */
866 bool bIsMPChip;
867 bool bOneEntryOnly;
868 /* Common info for BTDM */
869 bool bBtDisabled; /* BT is disabled */
870 bool bBtHsOperation; /* BT HS mode is under progress */
871 u8 btHsDigVal; /* use BT rssi to decide the DIG value */
872 bool bBtDisableEdcaTurbo; /* Under some condition, don't enable the EDCA Turbo */
873 bool bBtBusy; /* BT is busy. */
874/* CALL BY VALUE------------- */
875
876 /* 2 Define STA info. */
877 /* _ODM_STA_INFO */
878 /* 2012/01/12 MH For MP, we need to reduce one array pointer for default port.?? */
879 struct sta_info * pODM_StaInfo[ODM_ASSOCIATE_ENTRY_NUM];
880
881 /* */
882 /* 2012/02/14 MH Add to share 88E ra with other SW team. */
883 /* We need to colelct all support abilit to a proper area. */
884 /* */
885 bool RaSupport88E;
886
887 /* Define ........... */
888
889 /* Latest packet phy info (ODM write) */
890 struct odm_phy_dbg_info PhyDbgInfo;
891 /* PHY_INFO_88E PhyInfo; */
892
893 /* Latest packet phy info (ODM write) */
894 struct odm_mac_info *pMacInfo;
895 /* MAC_INFO_88E MacInfo; */
896
897 /* Different Team independt structure?? */
898
899 /* */
900 /* TX_RTP_CMN TX_retrpo; */
901 /* TX_RTP_88E TX_retrpo; */
902 /* TX_RTP_8195 TX_retrpo; */
903
904 /* */
905 /* ODM Structure */
906 /* */
907 struct odm_fat_t DM_FatTable;
908 struct dig_t DM_DigTable;
909 struct dynamic_pwr_sav DM_PSTable;
910 struct pri_cca DM_PriCCA;
911 struct rx_hp DM_RXHP_Table;
912 struct false_alarm_stats FalseAlmCnt;
913 struct false_alarm_stats FlaseAlmCntBuddyAdapter;
914 struct sw_ant_sw DM_SWAT_Table;
915 bool RSSI_test;
916
917 struct edca_turbo DM_EDCA_Table;
918 u32 WMMEDCA_BE;
919 /* Copy from SD4 structure */
920 /* */
921 /* ================================================== */
922 /* */
923
924 /* common */
925 bool *pbDriverStopped;
926 bool *pbDriverIsGoingToPnpSetPowerSleep;
927 bool *pinit_adpt_in_progress;
928
929 /* PSD */
930 bool bUserAssignLevel;
931 struct timer_list PSDTimer;
932 u8 RSSI_BT; /* come from BT */
933 bool bPSDinProcess;
934 bool bDMInitialGainEnable;
935
936 /* for rate adaptive, in fact, 88c/92c fw will handle this */
937 u8 bUseRAMask;
938
939 struct odm_rate_adapt RateAdaptive;
940
941
942 struct odm_rf_cal_t RFCalibrateInfo;
943
944 /* */
945 /* TX power tracking */
946 /* */
947 u8 BbSwingIdxOfdm;
948 u8 BbSwingIdxOfdmCurrent;
949 u8 BbSwingIdxOfdmBase;
950 bool BbSwingFlagOfdm;
951 u8 BbSwingIdxCck;
952 u8 BbSwingIdxCckCurrent;
953 u8 BbSwingIdxCckBase;
954 bool BbSwingFlagCck;
955 /* */
956 /* ODM system resource. */
957 /* */
958
959 /* ODM relative time. */
960 struct timer_list PathDivSwitchTimer;
961 /* 2011.09.27 add for Path Diversity */
962 struct timer_list CCKPathDiversityTimer;
963 struct timer_list FastAntTrainingTimer;
964
965 /* ODM relative workitem. */
966}; /* DM_Dynamic_Mechanism_Structure */
967
968enum odm_rf_content {
969 odm_radioa_txt = 0x1000,
970 odm_radiob_txt = 0x1001,
971 odm_radioc_txt = 0x1002,
972 odm_radiod_txt = 0x1003
973};
974
975enum odm_bb_config_type {
976 CONFIG_BB_PHY_REG,
977 CONFIG_BB_AGC_TAB,
978 CONFIG_BB_AGC_TAB_2G,
979 CONFIG_BB_AGC_TAB_5G,
980 CONFIG_BB_PHY_REG_PG,
981};
982
983/* Status code */
984enum rt_status {
985 RT_STATUS_SUCCESS,
986 RT_STATUS_FAILURE,
987 RT_STATUS_PENDING,
988 RT_STATUS_RESOURCE,
989 RT_STATUS_INVALID_CONTEXT,
990 RT_STATUS_INVALID_PARAMETER,
991 RT_STATUS_NOT_SUPPORT,
992 RT_STATUS_OS_API_FAILED,
993};
994
995/* include "odm_function.h" */
996
997/* 3=========================================================== */
998/* 3 DIG */
999/* 3=========================================================== */
1000
1001enum dm_dig_op {
1002 DIG_TYPE_THRESH_HIGH = 0,
1003 DIG_TYPE_THRESH_LOW = 1,
1004 DIG_TYPE_BACKOFF = 2,
1005 DIG_TYPE_RX_GAIN_MIN = 3,
1006 DIG_TYPE_RX_GAIN_MAX = 4,
1007 DIG_TYPE_ENABLE = 5,
1008 DIG_TYPE_DISABLE = 6,
1009 DIG_OP_TYPE_MAX
1010};
1011
1012#define DM_DIG_THRESH_HIGH 40
1013#define DM_DIG_THRESH_LOW 35
1014
1015#define DM_SCAN_RSSI_TH 0x14 /* scan return issue for LC */
1016
1017
1018#define DM_FALSEALARM_THRESH_LOW 400
1019#define DM_FALSEALARM_THRESH_HIGH 1000
1020
1021#define DM_DIG_MAX_NIC 0x4e
1022#define DM_DIG_MIN_NIC 0x1e
1023
1024#define DM_DIG_MAX_AP 0x32
1025#define DM_DIG_MIN_AP 0x20
1026
1027#define DM_DIG_MAX_NIC_HP 0x46
1028#define DM_DIG_MIN_NIC_HP 0x2e
1029
1030#define DM_DIG_MAX_AP_HP 0x42
1031#define DM_DIG_MIN_AP_HP 0x30
1032
1033/* vivi 92c&92d has different definition, 20110504 */
1034/* this is for 92c */
1035#define DM_DIG_FA_TH0 0x200
1036#define DM_DIG_FA_TH1 0x300
1037#define DM_DIG_FA_TH2 0x400
1038/* this is for 92d */
1039#define DM_DIG_FA_TH0_92D 0x100
1040#define DM_DIG_FA_TH1_92D 0x400
1041#define DM_DIG_FA_TH2_92D 0x600
1042
1043#define DM_DIG_BACKOFF_MAX 12
1044#define DM_DIG_BACKOFF_MIN -4
1045#define DM_DIG_BACKOFF_DEFAULT 10
1046
1047/* 3=========================================================== */
1048/* 3 AGC RX High Power Mode */
1049/* 3=========================================================== */
1050#define LNA_Low_Gain_1 0x64
1051#define LNA_Low_Gain_2 0x5A
1052#define LNA_Low_Gain_3 0x58
1053
1054#define FA_RXHP_TH1 5000
1055#define FA_RXHP_TH2 1500
1056#define FA_RXHP_TH3 800
1057#define FA_RXHP_TH4 600
1058#define FA_RXHP_TH5 500
1059
1060/* 3=========================================================== */
1061/* 3 EDCA */
1062/* 3=========================================================== */
1063
1064/* 3=========================================================== */
1065/* 3 Dynamic Tx Power */
1066/* 3=========================================================== */
1067/* Dynamic Tx Power Control Threshold */
1068#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74
1069#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67
1070#define TX_POWER_NEAR_FIELD_THRESH_AP 0x3F
1071
1072#define TxHighPwrLevel_Normal 0
1073#define TxHighPwrLevel_Level1 1
1074#define TxHighPwrLevel_Level2 2
1075#define TxHighPwrLevel_BT1 3
1076#define TxHighPwrLevel_BT2 4
1077#define TxHighPwrLevel_15 5
1078#define TxHighPwrLevel_35 6
1079#define TxHighPwrLevel_50 7
1080#define TxHighPwrLevel_70 8
1081#define TxHighPwrLevel_100 9
1082
1083/* 3=========================================================== */
1084/* 3 Rate Adaptive */
1085/* 3=========================================================== */
1086#define DM_RATR_STA_INIT 0
1087#define DM_RATR_STA_HIGH 1
1088#define DM_RATR_STA_MIDDLE 2
1089#define DM_RATR_STA_LOW 3
1090
1091/* 3=========================================================== */
1092/* 3 BB Power Save */
1093/* 3=========================================================== */
1094
1095
1096enum dm_1r_cca {
1097 CCA_1R =0,
1098 CCA_2R = 1,
1099 CCA_MAX = 2,
1100};
1101
1102enum dm_rf_def {
1103 RF_Save =0,
1104 RF_Normal = 1,
1105 RF_MAX = 2,
1106};
1107
1108/* 3=========================================================== */
1109/* 3 Antenna Diversity */
1110/* 3=========================================================== */
1111enum dm_swas {
1112 Antenna_A = 1,
1113 Antenna_B = 2,
1114 Antenna_MAX = 3,
1115};
1116
1117/* Maximal number of antenna detection mechanism needs to perform, added by Roger, 2011.12.28. */
1118#define MAX_ANTENNA_DETECTION_CNT 10
1119
1120/* */
1121/* Extern Global Variables. */
1122/* */
1123#define OFDM_TABLE_SIZE_92C 37
1124#define OFDM_TABLE_SIZE_92D 43
1125#define CCK_TABLE_SIZE 33
1126
1127extern u32 OFDMSwingTable23A[OFDM_TABLE_SIZE_92D];
1128extern u8 CCKSwingTable_Ch1_Ch1323A[CCK_TABLE_SIZE][8];
1129extern u8 CCKSwingTable_Ch1423A [CCK_TABLE_SIZE][8];
1130
1131
1132
1133/* */
1134/* check Sta pointer valid or not */
1135/* */
1136#define IS_STA_VALID(pSta) (pSta)
1137/* 20100514 Joseph: Add definition for antenna switching test after link. */
1138/* This indicates two different the steps. */
1139/* In SWAW_STEP_PEAK, driver needs to switch antenna and listen to the signal on the air. */
1140/* In SWAW_STEP_DETERMINE, driver just compares the signal captured in SWAW_STEP_PEAK */
1141/* with original RSSI to determine if it is necessary to switch antenna. */
1142#define SWAW_STEP_PEAK 0
1143#define SWAW_STEP_DETERMINE 1
1144
1145void ODM_Write_DIG23a(struct dm_odm_t *pDM_Odm, u8 CurrentIGI);
1146void ODM_Write_CCK_CCA_Thres23a(struct dm_odm_t *pDM_Odm, u8 CurCCK_CCAThres);
1147
1148void ODM_SetAntenna(struct dm_odm_t *pDM_Odm, u8 Antenna);
1149
1150
1151#define dm_RF_Saving ODM_RF_Saving23a
1152void ODM_RF_Saving23a(struct dm_odm_t *pDM_Odm, u8 bForceInNormal);
1153
1154#define SwAntDivRestAfterLink ODM_SwAntDivRestAfterLink
1155void ODM_SwAntDivRestAfterLink(struct dm_odm_t *pDM_Odm);
1156
1157#define dm_CheckTXPowerTracking ODM_TXPowerTrackingCheck23a
1158void ODM_TXPowerTrackingCheck23a(struct dm_odm_t *pDM_Odm);
1159
1160bool ODM_RAStateCheck23a(struct dm_odm_t *pDM_Odm, s32 RSSI, bool bForceUpdate,
1161 u8 *pRATRState);
1162
1163
1164#define dm_SWAW_RSSI_Check ODM_SwAntDivChkPerPktRssi
1165void ODM_SwAntDivChkPerPktRssi(struct dm_odm_t *pDM_Odm, u8 StationID,
1166 struct odm_phy_info *pPhyInfo);
1167
1168u32 ConvertTo_dB23a(u32 Value);
1169
1170u32 GetPSDData(struct dm_odm_t *pDM_Odm, unsigned int point, u8 initial_gain_psd);
1171
1172void odm_DIG23abyRSSI_LPS(struct dm_odm_t *pDM_Odm);
1173
1174u32 ODM_Get_Rate_Bitmap23a(struct dm_odm_t *pDM_Odm, u32 macid, u32 ra_mask, u8 rssi_level);
1175
1176
1177void ODM23a_DMInit(struct dm_odm_t *pDM_Odm);
1178
1179void ODM_DMWatchdog23a(struct dm_odm_t *pDM_Odm); /* For common use in the future */
1180
1181void ODM_CmnInfoInit23a(struct dm_odm_t *pDM_Odm, enum odm_cmninfo CmnInfo, u32 Value);
1182
1183void ODM23a_CmnInfoHook(struct dm_odm_t *pDM_Odm, enum odm_cmninfo CmnInfo, void *pValue);
1184
1185void ODM_CmnInfoPtrArrayHook23a(struct dm_odm_t *pDM_Odm, enum odm_cmninfo CmnInfo, u16 Index, void *pValue);
1186
1187void ODM_CmnInfoUpdate23a(struct dm_odm_t *pDM_Odm, u32 CmnInfo, u64 Value);
1188
1189void ODM_InitAllTimers(struct dm_odm_t *pDM_Odm);
1190
1191void ODM_CancelAllTimers(struct dm_odm_t *pDM_Odm);
1192
1193void ODM_ReleaseAllTimers(struct dm_odm_t *pDM_Odm);
1194
1195void ODM_ResetIQKResult(struct dm_odm_t *pDM_Odm);
1196
1197void ODM_AntselStatistics_88C(struct dm_odm_t *pDM_Odm, u8 MacId, u32 PWDBAll, bool isCCKrate);
1198
1199void ODM_SingleDualAntennaDefaultSetting(struct dm_odm_t *pDM_Odm);
1200
1201bool ODM_SingleDualAntennaDetection(struct dm_odm_t *pDM_Odm, u8 mode);
1202
1203void odm_dtc(struct dm_odm_t *pDM_Odm);
1204
1205#endif
diff --git a/drivers/staging/rtl8723au/include/odm_HWConfig.h b/drivers/staging/rtl8723au/include/odm_HWConfig.h
new file mode 100644
index 000000000000..147855c96ad4
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/odm_HWConfig.h
@@ -0,0 +1,174 @@
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 ******************************************************************************/
15
16
17#ifndef __HALHWOUTSRC_H__
18#define __HALHWOUTSRC_H__
19
20#include <Hal8723APhyCfg.h>
21
22/* */
23/* Definition */
24/* */
25/* */
26/* */
27/* CCK Rates, TxHT = 0 */
28#define DESC92C_RATE1M 0x00
29#define DESC92C_RATE2M 0x01
30#define DESC92C_RATE5_5M 0x02
31#define DESC92C_RATE11M 0x03
32
33/* OFDM Rates, TxHT = 0 */
34#define DESC92C_RATE6M 0x04
35#define DESC92C_RATE9M 0x05
36#define DESC92C_RATE12M 0x06
37#define DESC92C_RATE18M 0x07
38#define DESC92C_RATE24M 0x08
39#define DESC92C_RATE36M 0x09
40#define DESC92C_RATE48M 0x0a
41#define DESC92C_RATE54M 0x0b
42
43/* MCS Rates, TxHT = 1 */
44#define DESC92C_RATEMCS0 0x0c
45#define DESC92C_RATEMCS1 0x0d
46#define DESC92C_RATEMCS2 0x0e
47#define DESC92C_RATEMCS3 0x0f
48#define DESC92C_RATEMCS4 0x10
49#define DESC92C_RATEMCS5 0x11
50#define DESC92C_RATEMCS6 0x12
51#define DESC92C_RATEMCS7 0x13
52#define DESC92C_RATEMCS8 0x14
53#define DESC92C_RATEMCS9 0x15
54#define DESC92C_RATEMCS10 0x16
55#define DESC92C_RATEMCS11 0x17
56#define DESC92C_RATEMCS12 0x18
57#define DESC92C_RATEMCS13 0x19
58#define DESC92C_RATEMCS14 0x1a
59#define DESC92C_RATEMCS15 0x1b
60#define DESC92C_RATEMCS15_SG 0x1c
61#define DESC92C_RATEMCS32 0x20
62
63
64/* */
65/* structure and define */
66/* */
67
68struct phy_rx_agc_info {
69 #ifdef __LITTLE_ENDIAN
70 u8 gain:7,trsw:1;
71 #else
72 u8 trsw:1,gain:7;
73 #endif
74};
75
76struct phy_status_rpt {
77 struct phy_rx_agc_info path_agc[RF_PATH_MAX];
78 u8 ch_corr[RF_PATH_MAX];
79 u8 cck_sig_qual_ofdm_pwdb_all;
80 u8 cck_agc_rpt_ofdm_cfosho_a;
81 u8 cck_rpt_b_ofdm_cfosho_b;
82 u8 rsvd_1;/* ch_corr_msb; */
83 u8 noise_power_db_msb;
84 u8 path_cfotail[RF_PATH_MAX];
85 u8 pcts_mask[RF_PATH_MAX];
86 s8 stream_rxevm[RF_PATH_MAX];
87 u8 path_rxsnr[RF_PATH_MAX];
88 u8 noise_power_db_lsb;
89 u8 rsvd_2[3];
90 u8 stream_csi[RF_PATH_MAX];
91 u8 stream_target_csi[RF_PATH_MAX];
92 s8 sig_evm;
93 u8 rsvd_3;
94
95#ifdef __LITTLE_ENDIAN
96 u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */
97 u8 sgi_en:1;
98 u8 rxsc:2;
99 u8 idle_long:1;
100 u8 r_ant_train_en:1;
101 u8 ant_sel_b:1;
102 u8 ant_sel:1;
103#else /* _BIG_ENDIAN_ */
104 u8 ant_sel:1;
105 u8 ant_sel_b:1;
106 u8 r_ant_train_en:1;
107 u8 idle_long:1;
108 u8 rxsc:2;
109 u8 sgi_en:1;
110 u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */
111#endif
112};
113
114
115struct phy_status_rpt_8195 {
116 struct phy_rx_agc_info path_agc[2];
117 u8 ch_num[2];
118 u8 cck_sig_qual_ofdm_pwdb_all;
119 u8 cck_agc_rpt_ofdm_cfosho_a;
120 u8 cck_bb_pwr_ofdm_cfosho_b;
121 u8 cck_rx_path; /* CCK_RX_PATH [3:0] (with regA07[3:0] definition) */
122 u8 rsvd_1;
123 u8 path_cfotail[2];
124 u8 pcts_mask[2];
125 s8 stream_rxevm[2];
126 u8 path_rxsnr[2];
127 u8 rsvd_2[2];
128 u8 stream_snr[2];
129 u8 stream_csi[2];
130 u8 rsvd_3[2];
131 s8 sig_evm;
132 u8 rsvd_4;
133#ifdef __LITTLE_ENDIAN
134 u8 antidx_anta:3;
135 u8 antidx_antb:3;
136 u8 rsvd_5:2;
137#else /* _BIG_ENDIAN_ */
138 u8 rsvd_5:2;
139 u8 antidx_antb:3;
140 u8 antidx_anta:3;
141#endif
142};
143
144
145void odm_Init_RSSIForDM23a(struct dm_odm_t *pDM_Odm);
146
147void
148ODM_PhyStatusQuery23a(
149 struct dm_odm_t *pDM_Odm,
150 struct odm_phy_info *pPhyInfo,
151 u8 * pPhyStatus,
152 struct odm_packet_info *pPktinfo
153 );
154
155void ODM_MacStatusQuery23a(struct dm_odm_t *pDM_Odm,
156 u8 *pMacStatus,
157 u8 MacID,
158 bool bPacketMatchBSSID,
159 bool bPacketToSelf,
160 bool bPacketBeacon
161);
162
163enum hal_status ODM_ConfigRFWithHeaderFile23a(struct dm_odm_t *pDM_Odm,
164 enum RF_RADIO_PATH Content,
165 enum RF_RADIO_PATH eRFPath
166);
167
168enum hal_status ODM_ConfigBBWithHeaderFile23a(struct dm_odm_t *pDM_Odm,
169 enum odm_bb_config_type ConfigType
170);
171
172enum hal_status ODM_ConfigMACWithHeaderFile23a(struct dm_odm_t *pDM_Odm);
173
174#endif
diff --git a/drivers/staging/rtl8723au/include/odm_RegConfig8723A.h b/drivers/staging/rtl8723au/include/odm_RegConfig8723A.h
new file mode 100644
index 000000000000..4ea579b2e8bd
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/odm_RegConfig8723A.h
@@ -0,0 +1,34 @@
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 ******************************************************************************/
15#ifndef __INC_ODM_REGCONFIG_H_8723A
16#define __INC_ODM_REGCONFIG_H_8723A
17
18void odm_ConfigRFReg_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Data,
19 enum RF_RADIO_PATH RF_PATH, u32 RegAddr);
20
21void odm_ConfigRF_RadioA_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Data);
22
23void odm_ConfigRF_RadioB_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Data);
24
25void odm_ConfigMAC_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u8 Data);
26
27void odm_ConfigBB_AGC_8723A(struct dm_odm_t *pDM_Odm, u32 Addr,
28 u32 Bitmask, u32 Data);
29
30void odm_ConfigBB_PHY_REG_PG_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Bitmask, u32 Data);
31
32void odm_ConfigBB_PHY_8723A(struct dm_odm_t *pDM_Odm, u32 Addr, u32 Bitmask, u32 Data);
33
34#endif /* end of SUPPORT */
diff --git a/drivers/staging/rtl8723au/include/odm_RegDefine11AC.h b/drivers/staging/rtl8723au/include/odm_RegDefine11AC.h
new file mode 100644
index 000000000000..77b7acec5ea8
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/odm_RegDefine11AC.h
@@ -0,0 +1,49 @@
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 ******************************************************************************/
15
16#ifndef __ODM_REGDEFINE11AC_H__
17#define __ODM_REGDEFINE11AC_H__
18
19/* 2 RF REG LIST */
20
21
22
23/* 2 BB REG LIST */
24/* PAGE 8 */
25/* PAGE 9 */
26#define ODM_REG_OFDM_FA_RST_11AC 0x9A4
27/* PAGE A */
28#define ODM_REG_CCK_CCA_11AC 0xA0A
29#define ODM_REG_CCK_FA_RST_11AC 0xA2C
30#define ODM_REG_CCK_FA_11AC 0xA5C
31/* PAGE C */
32#define ODM_REG_IGI_A_11AC 0xC50
33/* PAGE E */
34#define ODM_REG_IGI_B_11AC 0xE50
35/* PAGE F */
36#define ODM_REG_OFDM_FA_11AC 0xF48
37
38
39/* 2 MAC REG LIST */
40
41
42
43
44/* DIG Related */
45#define ODM_BIT_IGI_11AC 0xFFFFFFFF
46
47
48
49#endif
diff --git a/drivers/staging/rtl8723au/include/odm_RegDefine11N.h b/drivers/staging/rtl8723au/include/odm_RegDefine11N.h
new file mode 100644
index 000000000000..27782154f502
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/odm_RegDefine11N.h
@@ -0,0 +1,165 @@
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 ******************************************************************************/
15
16#ifndef __ODM_REGDEFINE11N_H__
17#define __ODM_REGDEFINE11N_H__
18
19
20/* 2 RF REG LIST */
21#define ODM_REG_RF_MODE_11N 0x00
22#define ODM_REG_RF_0B_11N 0x0B
23#define ODM_REG_CHNBW_11N 0x18
24#define ODM_REG_T_METER_11N 0x24
25#define ODM_REG_RF_25_11N 0x25
26#define ODM_REG_RF_26_11N 0x26
27#define ODM_REG_RF_27_11N 0x27
28#define ODM_REG_RF_2B_11N 0x2B
29#define ODM_REG_RF_2C_11N 0x2C
30#define ODM_REG_RXRF_A3_11N 0x3C
31#define ODM_REG_T_METER_92D_11N 0x42
32#define ODM_REG_T_METER_88E_11N 0x42
33
34
35
36/* 2 BB REG LIST */
37/* PAGE 8 */
38#define ODM_REG_BB_CTRL_11N 0x800
39#define ODM_REG_RF_PIN_11N 0x804
40#define ODM_REG_PSD_CTRL_11N 0x808
41#define ODM_REG_TX_ANT_CTRL_11N 0x80C
42#define ODM_REG_BB_PWR_SAV5_11N 0x818
43#define ODM_REG_CCK_RPT_FORMAT_11N 0x824
44#define ODM_REG_RX_DEFUALT_A_11N 0x858
45#define ODM_REG_RX_DEFUALT_B_11N 0x85A
46#define ODM_REG_BB_PWR_SAV3_11N 0x85C
47#define ODM_REG_ANTSEL_CTRL_11N 0x860
48#define ODM_REG_RX_ANT_CTRL_11N 0x864
49#define ODM_REG_PIN_CTRL_11N 0x870
50#define ODM_REG_BB_PWR_SAV1_11N 0x874
51#define ODM_REG_ANTSEL_PATH_11N 0x878
52#define ODM_REG_BB_3WIRE_11N 0x88C
53#define ODM_REG_SC_CNT_11N 0x8C4
54#define ODM_REG_PSD_DATA_11N 0x8B4
55/* PAGE 9 */
56#define ODM_REG_ANT_MAPPING1_11N 0x914
57#define ODM_REG_ANT_MAPPING2_11N 0x918
58/* PAGE A */
59#define ODM_REG_CCK_ANTDIV_PARA1_11N 0xA00
60#define ODM_REG_CCK_CCA_11N 0xA0A
61#define ODM_REG_CCK_ANTDIV_PARA2_11N 0xA0C
62#define ODM_REG_CCK_ANTDIV_PARA3_11N 0xA10
63#define ODM_REG_CCK_ANTDIV_PARA4_11N 0xA14
64#define ODM_REG_CCK_FILTER_PARA1_11N 0xA22
65#define ODM_REG_CCK_FILTER_PARA2_11N 0xA23
66#define ODM_REG_CCK_FILTER_PARA3_11N 0xA24
67#define ODM_REG_CCK_FILTER_PARA4_11N 0xA25
68#define ODM_REG_CCK_FILTER_PARA5_11N 0xA26
69#define ODM_REG_CCK_FILTER_PARA6_11N 0xA27
70#define ODM_REG_CCK_FILTER_PARA7_11N 0xA28
71#define ODM_REG_CCK_FILTER_PARA8_11N 0xA29
72#define ODM_REG_CCK_FA_RST_11N 0xA2C
73#define ODM_REG_CCK_FA_MSB_11N 0xA58
74#define ODM_REG_CCK_FA_LSB_11N 0xA5C
75#define ODM_REG_CCK_CCA_CNT_11N 0xA60
76#define ODM_REG_BB_PWR_SAV4_11N 0xA74
77/* PAGE B */
78#define ODM_REG_LNA_SWITCH_11N 0xB2C
79#define ODM_REG_PATH_SWITCH_11N 0xB30
80#define ODM_REG_RSSI_CTRL_11N 0xB38
81#define ODM_REG_CONFIG_ANTA_11N 0xB68
82#define ODM_REG_RSSI_BT_11N 0xB9C
83/* PAGE C */
84#define ODM_REG_OFDM_FA_HOLDC_11N 0xC00
85#define ODM_REG_RX_PATH_11N 0xC04
86#define ODM_REG_TRMUX_11N 0xC08
87#define ODM_REG_OFDM_FA_RSTC_11N 0xC0C
88#define ODM_REG_RXIQI_MATRIX_11N 0xC14
89#define ODM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C
90#define ODM_REG_IGI_A_11N 0xC50
91#define ODM_REG_ANTDIV_PARA2_11N 0xC54
92#define ODM_REG_IGI_B_11N 0xC58
93#define ODM_REG_ANTDIV_PARA3_11N 0xC5C
94#define ODM_REG_BB_PWR_SAV2_11N 0xC70
95#define ODM_REG_RX_OFF_11N 0xC7C
96#define ODM_REG_TXIQK_MATRIXA_11N 0xC80
97#define ODM_REG_TXIQK_MATRIXB_11N 0xC88
98#define ODM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94
99#define ODM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C
100#define ODM_REG_RXIQK_MATRIX_LSB_11N 0xCA0
101#define ODM_REG_ANTDIV_PARA1_11N 0xCA4
102#define ODM_REG_OFDM_FA_TYPE1_11N 0xCF0
103/* PAGE D */
104#define ODM_REG_OFDM_FA_RSTD_11N 0xD00
105#define ODM_REG_OFDM_FA_TYPE2_11N 0xDA0
106#define ODM_REG_OFDM_FA_TYPE3_11N 0xDA4
107#define ODM_REG_OFDM_FA_TYPE4_11N 0xDA8
108/* PAGE E */
109#define ODM_REG_TXAGC_A_6_18_11N 0xE00
110#define ODM_REG_TXAGC_A_24_54_11N 0xE04
111#define ODM_REG_TXAGC_A_1_MCS32_11N 0xE08
112#define ODM_REG_TXAGC_A_MCS0_3_11N 0xE10
113#define ODM_REG_TXAGC_A_MCS4_7_11N 0xE14
114#define ODM_REG_TXAGC_A_MCS8_11_11N 0xE18
115#define ODM_REG_TXAGC_A_MCS12_15_11N 0xE1C
116#define ODM_REG_FPGA0_IQK_11N 0xE28
117#define ODM_REG_TXIQK_TONE_A_11N 0xE30
118#define ODM_REG_RXIQK_TONE_A_11N 0xE34
119#define ODM_REG_TXIQK_PI_A_11N 0xE38
120#define ODM_REG_RXIQK_PI_A_11N 0xE3C
121#define ODM_REG_TXIQK_11N 0xE40
122#define ODM_REG_RXIQK_11N 0xE44
123#define ODM_REG_IQK_AGC_PTS_11N 0xE48
124#define ODM_REG_IQK_AGC_RSP_11N 0xE4C
125#define ODM_REG_BLUETOOTH_11N 0xE6C
126#define ODM_REG_RX_WAIT_CCA_11N 0xE70
127#define ODM_REG_TX_CCK_RFON_11N 0xE74
128#define ODM_REG_TX_CCK_BBON_11N 0xE78
129#define ODM_REG_OFDM_RFON_11N 0xE7C
130#define ODM_REG_OFDM_BBON_11N 0xE80
131#define ODM_REG_TX2RX_11N 0xE84
132#define ODM_REG_TX2TX_11N 0xE88
133#define ODM_REG_RX_CCK_11N 0xE8C
134#define ODM_REG_RX_OFDM_11N 0xED0
135#define ODM_REG_RX_WAIT_RIFS_11N 0xED4
136#define ODM_REG_RX2RX_11N 0xED8
137#define ODM_REG_STANDBY_11N 0xEDC
138#define ODM_REG_SLEEP_11N 0xEE0
139#define ODM_REG_PMPD_ANAEN_11N 0xEEC
140
141
142
143
144
145
146
147/* 2 MAC REG LIST */
148#define ODM_REG_BB_RST_11N 0x02
149#define ODM_REG_ANTSEL_PIN_11N 0x4C
150#define ODM_REG_EARLY_MODE_11N 0x4D0
151#define ODM_REG_RSSI_MONITOR_11N 0x4FE
152#define ODM_REG_EDCA_VO_11N 0x500
153#define ODM_REG_EDCA_VI_11N 0x504
154#define ODM_REG_EDCA_BE_11N 0x508
155#define ODM_REG_EDCA_BK_11N 0x50C
156#define ODM_REG_TXPAUSE_11N 0x522
157#define ODM_REG_RESP_TX_11N 0x6D8
158#define ODM_REG_ANT_TRAIN_PARA1_11N 0x7b0
159#define ODM_REG_ANT_TRAIN_PARA2_11N 0x7b4
160
161
162/* DIG Related */
163#define ODM_BIT_IGI_11N 0x0000007F
164
165#endif
diff --git a/drivers/staging/rtl8723au/include/odm_debug.h b/drivers/staging/rtl8723au/include/odm_debug.h
new file mode 100644
index 000000000000..5bc51d09e52f
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/odm_debug.h
@@ -0,0 +1,139 @@
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 ******************************************************************************/
15
16
17#ifndef __ODM_DBG_H__
18#define __ODM_DBG_H__
19
20
21/* */
22/* Define the debug levels */
23/* */
24/* 1. DBG_TRACE and DBG_LOUD are used for normal cases. */
25/* So that, they can help SW engineer to develope or trace states changed */
26/* and also help HW enginner to trace every operation to and from HW, */
27/* e.g IO, Tx, Rx. */
28/* */
29/* 2. DBG_WARNNING and DBG_SERIOUS are used for unusual or error cases, */
30/* which help us to debug SW or HW. */
31/* */
32/* */
33/* */
34/* Never used in a call to ODM_RT_TRACE()! */
35/* */
36#define ODM_DBG_OFF 1
37
38/* */
39/* Fatal bug. */
40/* For example, Tx/Rx/IO locked up, OS hangs, memory access violation, */
41/* resource allocation failed, unexpected HW behavior, HW BUG and so on. */
42/* */
43#define ODM_DBG_SERIOUS 2
44
45/* */
46/* Abnormal, rare, or unexpeted cases. */
47/* For example, IRP/Packet/OID canceled, device suprisely unremoved and so on. */
48/* */
49#define ODM_DBG_WARNING 3
50
51/* */
52/* Normal case with useful information about current SW or HW state. */
53/* For example, Tx/Rx descriptor to fill, Tx/Rx descriptor completed status, */
54/* SW protocol state change, dynamic mechanism state change and so on. */
55/* */
56#define ODM_DBG_LOUD 4
57
58/* */
59/* Normal case with detail execution flow or information. */
60/* */
61#define ODM_DBG_TRACE 5
62
63/* */
64/* Define the tracing components */
65/* */
66/* */
67/* BB Functions */
68#define ODM_COMP_DIG BIT0
69#define ODM_COMP_RA_MASK BIT1
70#define ODM_COMP_DYNAMIC_TXPWR BIT2
71#define ODM_COMP_FA_CNT BIT3
72#define ODM_COMP_RSSI_MONITOR BIT4
73#define ODM_COMP_CCK_PD BIT5
74#define ODM_COMP_ANT_DIV BIT6
75#define ODM_COMP_PWR_SAVE BIT7
76#define ODM_COMP_PWR_TRAIN BIT8
77#define ODM_COMP_RATE_ADAPTIVE BIT9
78#define ODM_COMP_PATH_DIV BIT10
79#define ODM_COMP_PSD BIT11
80#define ODM_COMP_DYNAMIC_PRICCA BIT12
81#define ODM_COMP_RXHP BIT13
82/* MAC Functions */
83#define ODM_COMP_EDCA_TURBO BIT16
84#define ODM_COMP_EARLY_MODE BIT17
85/* RF Functions */
86#define ODM_COMP_TX_PWR_TRACK BIT24
87#define ODM_COMP_RX_GAIN_TRACK BIT25
88#define ODM_COMP_CALIBRATION BIT26
89/* Common Functions */
90#define ODM_COMP_COMMON BIT30
91#define ODM_COMP_INIT BIT31
92
93/*------------------------Export Macro Definition---------------------------*/
94 #define DbgPrint printk
95 #define RT_PRINTK(fmt, args...) DbgPrint("%s(): " fmt, __func__, ## args);
96
97#ifndef ASSERT
98 #define ASSERT(expr)
99#endif
100
101#define ODM_RT_TRACE(pDM_Odm, comp, level, fmt) \
102 if(((comp) & pDM_Odm->DebugComponents) && (level <= pDM_Odm->DebugLevel)) \
103 { \
104 DbgPrint("[ODM-8723A] "); \
105 RT_PRINTK fmt; \
106 }
107
108#define ODM_RT_TRACE_F(pDM_Odm, comp, level, fmt) \
109 if(((comp) & pDM_Odm->DebugComponents) && (level <= pDM_Odm->DebugLevel)) \
110 { \
111 RT_PRINTK fmt; \
112 }
113
114#define ODM_RT_ASSERT(pDM_Odm, expr, fmt) \
115 if(!(expr)) { \
116 DbgPrint("Assertion failed! %s at ......\n", #expr); \
117 DbgPrint(" ......%s,%s,line=%d\n", __FILE__, __func__, __LINE__);\
118 RT_PRINTK fmt; \
119 ASSERT(false); \
120 }
121#define ODM_dbg_enter() { DbgPrint("==> %s\n", __func__); }
122#define ODM_dbg_exit() { DbgPrint("<== %s\n", __func__); }
123#define ODM_dbg_trace(str) { DbgPrint("%s:%s\n", __func__, str); }
124
125#define ODM_PRINT_ADDR(pDM_Odm, comp, level, title_str, ptr) \
126 if(((comp) & pDM_Odm->DebugComponents) && (level <= pDM_Odm->DebugLevel){ \
127 int __i; \
128 u8 * __ptr = (u8 *)ptr; \
129 DbgPrint("[ODM] "); \
130 DbgPrint(title_str); \
131 DbgPrint(" "); \
132 for (__i=0; __i < 6; __i++) \
133 DbgPrint("%02X%s", __ptr[__i], (__i == 5) ? "" : "-"); \
134 DbgPrint("\n"); \
135 }
136
137void ODM_InitDebugSetting23a(struct dm_odm_t *pDM_Odm);
138
139#endif /* __ODM_DBG_H__ */
diff --git a/drivers/staging/rtl8723au/include/odm_interface.h b/drivers/staging/rtl8723au/include/odm_interface.h
new file mode 100644
index 000000000000..f216b5846f92
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/odm_interface.h
@@ -0,0 +1,131 @@
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 ******************************************************************************/
15
16
17#ifndef __ODM_INTERFACE_H__
18#define __ODM_INTERFACE_H__
19
20
21
22/* */
23/* =========== Constant/Structure/Enum/... Define */
24/* */
25
26
27
28/* */
29/* =========== Macro Define */
30/* */
31
32#define _reg_all(_name) ODM_##_name
33#define _reg_ic(_name, _ic) ODM_##_name##_ic
34#define _bit_all(_name) BIT_##_name
35#define _bit_ic(_name, _ic) BIT_##_name##_ic
36
37/* _cat: implemented by Token-Pasting Operator. */
38
39/*===================================
40
41#define ODM_REG_DIG_11N 0xC50
42#define ODM_REG_DIG_11AC 0xDDD
43
44ODM_REG(DIG,_pDM_Odm)
45=====================================*/
46
47#define _reg_11N(_name) ODM_REG_##_name##_11N
48#define _reg_11AC(_name) ODM_REG_##_name##_11AC
49#define _bit_11N(_name) ODM_BIT_##_name##_11N
50#define _bit_11AC(_name) ODM_BIT_##_name##_11AC
51
52#define _cat(_name, _ic_type, _func) \
53 ( \
54 ((_ic_type) & ODM_IC_11N_SERIES)? _func##_11N(_name): \
55 _func##_11AC(_name) \
56 )
57
58/* _name: name of register or bit. */
59/* Example: "ODM_REG(R_A_AGC_CORE1, pDM_Odm)" */
60/* gets "ODM_R_A_AGC_CORE1" or "ODM_R_A_AGC_CORE1_8192C", depends on SupportICType. */
61#define ODM_REG(_name, _pDM_Odm) _cat(_name, _pDM_Odm->SupportICType, _reg)
62#define ODM_BIT(_name, _pDM_Odm) _cat(_name, _pDM_Odm->SupportICType, _bit)
63
64/* */
65/* 2012/02/17 MH For non-MP compile pass only. Linux does not support workitem. */
66/* Suggest HW team to use thread instead of workitem. Windows also support the feature. */
67/* */
68typedef void (*RT_WORKITEM_CALL_BACK)(struct work_struct *pContext);
69
70/* */
71/* =========== Extern Variable ??? It should be forbidden. */
72/* */
73
74
75/* */
76/* =========== EXtern Function Prototype */
77/* */
78
79
80u8 ODM_Read1Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr);
81
82u16 ODM_Read2Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr);
83
84u32 ODM_Read4Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr);
85
86void ODM_Write1Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr, u8 Data);
87
88void ODM_Write2Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr, u16 Data);
89
90void ODM_Write4Byte(struct dm_odm_t *pDM_Odm, u32 RegAddr, u32 Data);
91
92void ODM_SetMACReg(struct dm_odm_t *pDM_Odm, u32 RegAddr, u32 BitMask, u32 Data);
93
94u32 ODM_GetMACReg(struct dm_odm_t *pDM_Odm, u32 RegAddr, u32 BitMask);
95
96void ODM_SetBBReg(struct dm_odm_t *pDM_Odm, u32 RegAddr, u32 BitMask, u32 Data);
97
98u32 ODM_GetBBReg(struct dm_odm_t *pDM_Odm, u32 RegAddr, u32 BitMask);
99
100void ODM_SetRFReg(struct dm_odm_t *pDM_Odm, enum RF_RADIO_PATH eRFPath,
101 u32 RegAddr, u32 BitMask, u32 Data);
102
103u32 ODM_GetRFReg(struct dm_odm_t *pDM_Odm, enum RF_RADIO_PATH eRFPath,
104 u32 RegAddr, u32 BitMask);
105
106/* Memory Relative Function. */
107void ODM_AllocateMemory(struct dm_odm_t *pDM_Odm, void **pPtr, u32 length);
108void ODM_FreeMemory(struct dm_odm_t *pDM_Odm, void *pPtr, u32 length);
109
110s32 ODM_CompareMemory(struct dm_odm_t *pDM_Odm, void *pBuf1, void *pBuf2, u32 length);
111
112/* ODM MISC-spin lock relative API. */
113void ODM_AcquireSpinLock(struct dm_odm_t *pDM_Odm, enum rt_spinlock_type type);
114
115void ODM_ReleaseSpinLock(struct dm_odm_t *pDM_Odm, enum rt_spinlock_type type);
116
117/* ODM MISC-workitem relative API. */
118void ODM_InitializeWorkItem(struct dm_odm_t *pDM_Odm, void *pRtWorkItem,
119 RT_WORKITEM_CALL_BACK RtWorkItemCallback, void *pContext, const char *szID);
120
121/* ODM Timer relative API. */
122void ODM_SetTimer(struct dm_odm_t *pDM_Odm, struct timer_list *pTimer, u32 msDelay);
123
124void ODM_ReleaseTimer(struct dm_odm_t *pDM_Odm, struct timer_list *pTimer);
125
126/* ODM FW relative API. */
127u32 ODM_FillH2CCmd(u8 *pH2CBuffer, u32 H2CBufferLen, u32 CmdNum,
128 u32 *pElementID, u32 *pCmdLen, u8 **pCmbBuffer,
129 u8 *CmdStartSeq);
130
131#endif /* __ODM_INTERFACE_H__ */
diff --git a/drivers/staging/rtl8723au/include/odm_precomp.h b/drivers/staging/rtl8723au/include/odm_precomp.h
new file mode 100644
index 000000000000..f3fc2fad9884
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/odm_precomp.h
@@ -0,0 +1,54 @@
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 ******************************************************************************/
15
16#ifndef __ODM_PRECOMP_H__
17#define __ODM_PRECOMP_H__
18
19#include "odm_types.h"
20
21#define TEST_FALG___ 1
22
23/* 2 Config Flags and Structs - defined by each ODM Type */
24
25#include <osdep_service.h>
26#include <drv_types.h>
27#include <hal_intf.h>
28
29
30/* 2 Hardware Parameter Files */
31#include "Hal8723UHWImg_CE.h"
32
33
34/* 2 OutSrc Header Files */
35
36#include "odm.h"
37#include "odm_HWConfig.h"
38#include "odm_debug.h"
39#include "odm_RegDefine11AC.h"
40#include "odm_RegDefine11N.h"
41
42#include "HalDMOutSrc8723A.h" /* for IQK,LCK,Power-tracking */
43#include "rtl8723a_hal.h"
44
45#include "odm_interface.h"
46#include "odm_reg.h"
47
48#include "HalHWImg8723A_MAC.h"
49#include "HalHWImg8723A_RF.h"
50#include "HalHWImg8723A_BB.h"
51#include "HalHWImg8723A_FW.h"
52#include "odm_RegConfig8723A.h"
53
54#endif /* __ODM_PRECOMP_H__ */
diff --git a/drivers/staging/rtl8723au/include/odm_reg.h b/drivers/staging/rtl8723au/include/odm_reg.h
new file mode 100644
index 000000000000..56191e9fdcdb
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/odm_reg.h
@@ -0,0 +1,114 @@
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 ******************************************************************************/
15/* */
16/* File Name: odm_reg.h */
17/* */
18/* Description: */
19/* */
20/* This file is for general register definition. */
21/* */
22/* */
23/* */
24#ifndef __HAL_ODM_REG_H__
25#define __HAL_ODM_REG_H__
26
27/* */
28/* Register Definition */
29/* */
30
31/* MAC REG */
32#define ODM_BB_RESET 0x002
33#define ODM_DUMMY 0x4fe
34#define ODM_EDCA_VO_PARAM 0x500
35#define ODM_EDCA_VI_PARAM 0x504
36#define ODM_EDCA_BE_PARAM 0x508
37#define ODM_EDCA_BK_PARAM 0x50C
38#define ODM_TXPAUSE 0x522
39
40/* BB REG */
41#define ODM_FPGA_PHY0_PAGE8 0x800
42#define ODM_PSD_SETTING 0x808
43#define ODM_AFE_SETTING 0x818
44#define ODM_TXAGC_B_6_18 0x830
45#define ODM_TXAGC_B_24_54 0x834
46#define ODM_TXAGC_B_MCS32_5 0x838
47#define ODM_TXAGC_B_MCS0_MCS3 0x83c
48#define ODM_TXAGC_B_MCS4_MCS7 0x848
49#define ODM_TXAGC_B_MCS8_MCS11 0x84c
50#define ODM_ANALOG_REGISTER 0x85c
51#define ODM_RF_INTERFACE_OUTPUT 0x860
52#define ODM_TXAGC_B_MCS12_MCS15 0x868
53#define ODM_TXAGC_B_11_A_2_11 0x86c
54#define ODM_AD_DA_LSB_MASK 0x874
55#define ODM_ENABLE_3_WIRE 0x88c
56#define ODM_PSD_REPORT 0x8b4
57#define ODM_R_ANT_SELECT 0x90c
58#define ODM_CCK_ANT_SELECT 0xa07
59#define ODM_CCK_PD_THRESH 0xa0a
60#define ODM_CCK_RF_REG1 0xa11
61#define ODM_CCK_MATCH_FILTER 0xa20
62#define ODM_CCK_RAKE_MAC 0xa2e
63#define ODM_CCK_CNT_RESET 0xa2d
64#define ODM_CCK_TX_DIVERSITY 0xa2f
65#define ODM_CCK_FA_CNT_MSB 0xa5b
66#define ODM_CCK_FA_CNT_LSB 0xa5c
67#define ODM_CCK_NEW_FUNCTION 0xa75
68#define ODM_OFDM_PHY0_PAGE_C 0xc00
69#define ODM_OFDM_RX_ANT 0xc04
70#define ODM_R_A_RXIQI 0xc14
71#define ODM_R_A_AGC_CORE1 0xc50
72#define ODM_R_A_AGC_CORE2 0xc54
73#define ODM_R_B_AGC_CORE1 0xc58
74#define ODM_R_AGC_PAR 0xc70
75#define ODM_R_HTSTF_AGC_PAR 0xc7c
76#define ODM_TX_PWR_TRAINING_A 0xc90
77#define ODM_TX_PWR_TRAINING_B 0xc98
78#define ODM_OFDM_FA_CNT1 0xcf0
79#define ODM_OFDM_PHY0_PAGE_D 0xd00
80#define ODM_OFDM_FA_CNT2 0xda0
81#define ODM_OFDM_FA_CNT3 0xda4
82#define ODM_OFDM_FA_CNT4 0xda8
83#define ODM_TXAGC_A_6_18 0xe00
84#define ODM_TXAGC_A_24_54 0xe04
85#define ODM_TXAGC_A_1_MCS32 0xe08
86#define ODM_TXAGC_A_MCS0_MCS3 0xe10
87#define ODM_TXAGC_A_MCS4_MCS7 0xe14
88#define ODM_TXAGC_A_MCS8_MCS11 0xe18
89#define ODM_TXAGC_A_MCS12_MCS15 0xe1c
90
91/* RF REG */
92#define ODM_GAIN_SETTING 0x00
93#define ODM_CHANNEL 0x18
94
95/* Ant Detect Reg */
96#define ODM_DPDT 0x300
97
98/* PSD Init */
99#define ODM_PSDREG 0x808
100
101/* 92D Path Div */
102#define PATHDIV_REG 0xB30
103#define PATHDIV_TRI 0xBA0
104
105
106/* */
107/* Bitmap Definition */
108/* */
109
110#define BIT_FA_RESET BIT0
111
112
113
114#endif
diff --git a/drivers/staging/rtl8723au/include/odm_types.h b/drivers/staging/rtl8723au/include/odm_types.h
new file mode 100644
index 000000000000..a866769ea178
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/odm_types.h
@@ -0,0 +1,36 @@
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 ******************************************************************************/
15#ifndef __ODM_TYPES_H__
16#define __ODM_TYPES_H__
17
18/* Define Different SW team support */
19
20enum hal_status {
21 HAL_STATUS_SUCCESS,
22 HAL_STATUS_FAILURE,
23};
24
25enum rt_spinlock_type {
26 RT_TEMP =1,
27};
28
29#define SET_TX_DESC_ANTSEL_A_88E(__pTxDesc, __Value) \
30 SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 24, 1, __Value)
31#define SET_TX_DESC_ANTSEL_B_88E(__pTxDesc, __Value) \
32 SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 25, 1, __Value)
33#define SET_TX_DESC_ANTSEL_C_88E(__pTxDesc, __Value) \
34 SET_BITS_TO_LE_4BYTE(__pTxDesc+28, 29, 1, __Value)
35
36#endif /* __ODM_TYPES_H__ */
diff --git a/drivers/staging/rtl8723au/include/osdep_intf.h b/drivers/staging/rtl8723au/include/osdep_intf.h
new file mode 100644
index 000000000000..b603cf532900
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/osdep_intf.h
@@ -0,0 +1,46 @@
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 ******************************************************************************/
15
16#ifndef __OSDEP_INTF_H_
17#define __OSDEP_INTF_H_
18
19#include <osdep_service.h>
20#include <drv_types.h>
21
22int rtw_hw_suspend23a(struct rtw_adapter *padapter);
23int rtw_hw_resume23a(struct rtw_adapter *padapter);
24
25u8 rtw_init_drv_sw23a(struct rtw_adapter *padapter);
26u8 rtw_free_drv_sw23a(struct rtw_adapter *padapter);
27u8 rtw_reset_drv_sw23a(struct rtw_adapter *padapter);
28
29u32 rtw_start_drv_threads23a(struct rtw_adapter *padapter);
30void rtw_stop_drv_threads23a (struct rtw_adapter *padapter);
31void rtw_cancel_all_timer23a(struct rtw_adapter *padapter);
32
33int rtw_init_netdev23a_name23a(struct net_device *pnetdev, const char *ifname);
34struct net_device *rtw_init_netdev23a(struct rtw_adapter *padapter);
35
36u16 rtw_recv_select_queue23a(struct sk_buff *skb);
37
38void rtw_ips_dev_unload23a(struct rtw_adapter *padapter);
39
40int rtw_ips_pwr_up23a(struct rtw_adapter *padapter);
41void rtw_ips_pwr_down23a(struct rtw_adapter *padapter);
42
43int rtw_drv_register_netdev(struct rtw_adapter *padapter);
44void rtw_ndev_destructor(struct net_device *ndev);
45
46#endif /* _OSDEP_INTF_H_ */
diff --git a/drivers/staging/rtl8723au/include/osdep_service.h b/drivers/staging/rtl8723au/include/osdep_service.h
new file mode 100644
index 000000000000..039bc7285ed0
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/osdep_service.h
@@ -0,0 +1,207 @@
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 ******************************************************************************/
15#ifndef __OSDEP_SERVICE_H_
16#define __OSDEP_SERVICE_H_
17
18#define _FAIL 0
19#define _SUCCESS 1
20#define RTW_RX_HANDLED 2
21
22#include <linux/version.h>
23#include <linux/spinlock.h>
24#include <linux/compiler.h>
25#include <linux/kernel.h>
26#include <linux/errno.h>
27#include <linux/init.h>
28#include <linux/slab.h>
29#include <linux/module.h>
30#include <linux/kref.h>
31#include <linux/netdevice.h>
32#include <linux/skbuff.h>
33#include <linux/circ_buf.h>
34#include <asm/uaccess.h>
35#include <asm/byteorder.h>
36#include <asm/atomic.h>
37#include <asm/io.h>
38#include <linux/semaphore.h>
39#include <linux/sem.h>
40#include <linux/sched.h>
41#include <linux/etherdevice.h>
42#include <linux/wireless.h>
43#include <net/iw_handler.h>
44#include <linux/if_arp.h>
45#include <linux/rtnetlink.h>
46#include <linux/delay.h>
47#include <linux/proc_fs.h> /* Necessary because we use the proc fs */
48#include <linux/interrupt.h> /* for struct tasklet_struct */
49#include <linux/ip.h>
50#include <linux/kthread.h>
51
52
53/* #include <linux/ieee80211.h> */
54#include <net/ieee80211_radiotap.h>
55#include <net/cfg80211.h>
56#include <linux/usb.h>
57#include <linux/usb/ch9.h>
58
59struct rtw_adapter;
60struct c2h_evt_hdr;
61
62typedef s32 (*c2h_id_filter)(u8 id);
63
64struct rtw_queue {
65 struct list_head queue;
66 spinlock_t lock;
67};
68
69static inline struct list_head *get_list_head(struct rtw_queue *queue)
70{
71 return (&queue->queue);
72}
73
74static inline int rtw_netif_queue_stopped(struct net_device *pnetdev)
75{
76 return (netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 0)) &&
77 netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 1)) &&
78 netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 2)) &&
79 netif_tx_queue_stopped(netdev_get_tx_queue(pnetdev, 3)) );
80}
81
82#ifndef BIT
83#define BIT(x) ( 1 << (x))
84#endif
85static inline u32 CHKBIT(u32 x)
86{
87 WARN_ON(x >= 32);
88 if (x >= 32)
89 return 0;
90 return BIT(x);
91}
92
93#define BIT0 0x00000001
94#define BIT1 0x00000002
95#define BIT2 0x00000004
96#define BIT3 0x00000008
97#define BIT4 0x00000010
98#define BIT5 0x00000020
99#define BIT6 0x00000040
100#define BIT7 0x00000080
101#define BIT8 0x00000100
102#define BIT9 0x00000200
103#define BIT10 0x00000400
104#define BIT11 0x00000800
105#define BIT12 0x00001000
106#define BIT13 0x00002000
107#define BIT14 0x00004000
108#define BIT15 0x00008000
109#define BIT16 0x00010000
110#define BIT17 0x00020000
111#define BIT18 0x00040000
112#define BIT19 0x00080000
113#define BIT20 0x00100000
114#define BIT21 0x00200000
115#define BIT22 0x00400000
116#define BIT23 0x00800000
117#define BIT24 0x01000000
118#define BIT25 0x02000000
119#define BIT26 0x04000000
120#define BIT27 0x08000000
121#define BIT28 0x10000000
122#define BIT29 0x20000000
123#define BIT30 0x40000000
124#define BIT31 0x80000000
125#define BIT32 0x0100000000
126#define BIT33 0x0200000000
127#define BIT34 0x0400000000
128#define BIT35 0x0800000000
129#define BIT36 0x1000000000
130
131int RTW_STATUS_CODE23a(int error_code);
132
133u8* _rtw_vmalloc(u32 sz);
134u8* _rtw_zvmalloc(u32 sz);
135void _rtw_vmfree(u8 *pbuf, u32 sz);
136#define rtw_vmalloc(sz) _rtw_vmalloc((sz))
137#define rtw_zvmalloc(sz) _rtw_zvmalloc((sz))
138#define rtw_vmfree(pbuf, sz) _rtw_vmfree((pbuf), (sz))
139
140extern unsigned char REALTEK_96B_IE23A[];
141extern unsigned char MCS_rate_2R23A[16];
142extern unsigned char RTW_WPA_OUI23A[];
143extern unsigned char WPA_TKIP_CIPHER23A[4];
144extern unsigned char RSN_TKIP_CIPHER23A[4];
145
146extern unsigned char MCS_rate_2R23A[16];
147extern unsigned char MCS_rate_1R23A[16];
148
149void _rtw_init_queue23a(struct rtw_queue *pqueue);
150u32 _rtw_queue_empty23a(struct rtw_queue *pqueue);
151
152static inline u32 bitshift(u32 bitmask)
153{
154 u32 i;
155
156 for (i = 0; i <= 31; i++)
157 if (((bitmask>>i) & 0x1) == 1) break;
158
159 return i;
160}
161
162void rtw_suspend_lock_init(void);
163void rtw_suspend_lock_uninit(void);
164void rtw_lock_suspend(void);
165void rtw_unlock_suspend(void);
166
167
168#define NDEV_FMT "%s"
169#define NDEV_ARG(ndev) ndev->name
170#define ADPT_FMT "%s"
171#define ADPT_ARG(adapter) adapter->pnetdev->name
172#define FUNC_NDEV_FMT "%s(%s)"
173#define FUNC_NDEV_ARG(ndev) __func__, ndev->name
174#define FUNC_ADPT_FMT "%s(%s)"
175#define FUNC_ADPT_ARG(adapter) __func__, adapter->pnetdev->name
176
177#define rtw_signal_process(pid, sig) kill_pid(find_vpid((pid)),(sig), 1)
178
179u64 rtw_modular6423a(u64 x, u64 y);
180u64 rtw_division6423a(u64 x, u64 y);
181
182
183/* Macros for handling unaligned memory accesses */
184
185#define RTW_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \
186 ((u32) (a)[2]))
187
188
189struct rtw_cbuf {
190 u32 write;
191 u32 read;
192 u32 size;
193 void *bufs[0];
194};
195
196bool rtw_cbuf_full23a(struct rtw_cbuf *cbuf);
197bool rtw_cbuf_empty23a(struct rtw_cbuf *cbuf);
198bool rtw_cbuf_push23a(struct rtw_cbuf *cbuf, void *buf);
199void *rtw_cbuf_pop23a(struct rtw_cbuf *cbuf);
200struct rtw_cbuf *rtw_cbuf_alloc23a(u32 size);
201void rtw_cbuf_free(struct rtw_cbuf *cbuf);
202int rtw_change_ifname(struct rtw_adapter *padapter, const char *ifname);
203s32 c2h_evt_hdl(struct rtw_adapter *adapter, struct c2h_evt_hdr *c2h_evt, c2h_id_filter filter);
204void indicate_wx_scan_complete_event(struct rtw_adapter *padapter);
205u8 rtw_do_join23a(struct rtw_adapter *padapter);
206
207#endif
diff --git a/drivers/staging/rtl8723au/include/recv_osdep.h b/drivers/staging/rtl8723au/include/recv_osdep.h
new file mode 100644
index 000000000000..15c94b6168bf
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/recv_osdep.h
@@ -0,0 +1,45 @@
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 ******************************************************************************/
15#ifndef __RECV_OSDEP_H_
16#define __RECV_OSDEP_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21int _rtw_init_recv_priv23a(struct recv_priv *precvpriv, struct rtw_adapter *padapter);
22void _rtw_free_recv_priv23a (struct recv_priv *precvpriv);
23
24int rtw_recv_entry23a(struct recv_frame *precv_frame);
25int rtw_recv_indicatepkt23a(struct rtw_adapter *adapter, struct recv_frame *precv_frame);
26void rtw_recv_returnpacket(struct net_device *cnxt, struct sk_buff *preturnedpkt);
27
28void rtw_hostapd_mlme_rx23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
29void rtw_handle_tkip_mic_err23a(struct rtw_adapter *padapter, u8 bgroup);
30
31int rtw_init_recv_priv(struct recv_priv *precvpriv, struct rtw_adapter *padapter);
32void rtw_free_recv_priv (struct recv_priv *precvpriv);
33
34int rtw_os_recv_resource_init(struct recv_priv *precvpriv, struct rtw_adapter *padapter);
35int rtw_os_recv_resource_alloc23a(struct rtw_adapter *padapter, struct recv_frame *precvframe);
36void rtw_os_recv_resource_free(struct recv_priv *precvpriv);
37
38int rtw_os_recvbuf_resource_alloc23a(struct rtw_adapter *padapter, struct recv_buf *precvbuf);
39int rtw_os_recvbuf_resource_free23a(struct rtw_adapter *padapter, struct recv_buf *precvbuf);
40
41void rtw_os_read_port23a(struct rtw_adapter *padapter, struct recv_buf *precvbuf);
42
43void rtw_init_recv_timer23a(struct recv_reorder_ctrl *preorder_ctrl);
44
45#endif
diff --git a/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h b/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h
new file mode 100644
index 000000000000..6d1edc6ef84d
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h
@@ -0,0 +1,1672 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#ifndef __RTL8723A_BT_COEXIST_H__
16#define __RTL8723A_BT_COEXIST_H__
17
18#include <drv_types.h>
19#include "odm_precomp.h"
20
21
22#define __BT_C__ 1
23#define __BT_HANDLEPACKET_C__ 1
24#define __BT_HCI_C__ 1
25#define __HALBTC87231ANT_C__ 1
26#define __HALBTC87232ANT_C__ 1
27#define __HALBTC8723_C__ 1
28#define __HALBTCCSR1ANT_C__ 1
29#define __HALBTCCSR2ANT_C__ 1
30#define __HALBTCOEXIST_C__ 1
31#define __HALBT_C__ 1
32
33#ifdef __BT_C__ /* COMMON/BT.h */
34
35/* HEADER/PlatformDef.h */
36enum rt_media_status {
37 RT_MEDIA_DISCONNECT = 0,
38 RT_MEDIA_CONNECT = 1
39};
40
41/* ===== Below this line is sync from SD7 driver COMMON/BT.h ===== */
42
43#define BT_TMP_BUF_SIZE 100
44
45void BT_SignalCompensation(struct rtw_adapter *padapter,
46 u8 *rssi_wifi, u8 *rssi_bt);
47void BT_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType);
48void BT_WifiAssociateNotify(struct rtw_adapter *padapter, u8 action);
49void BT_WifiMediaStatusNotify(struct rtw_adapter *padapter,
50 enum rt_media_status mstatus);
51void BT_SpecialPacketNotify(struct rtw_adapter * padapter);
52void BT_HaltProcess(struct rtw_adapter * padapter);
53void BT_LpsLeave(struct rtw_adapter * padapter);
54
55
56#define BT_HsConnectionEstablished(Adapter) false
57/* ===== End of sync from SD7 driver COMMON/BT.h ===== */
58#endif /* __BT_C__ */
59
60#ifdef __BT_HCI_C__ /* COMMON/bt_hci.h */
61
62/* HEADER/SecurityType.h */
63#define TKIP_ENC_KEY_POS 32 /* KEK_LEN+KEK_LEN) */
64#define MAXRSNIELEN 256
65
66/* COMMON/Protocol802_11.h */
67/* */
68/* 802.11 Management frame Status Code field */
69/* */
70struct octet_string {
71 u8 *Octet;
72 u16 Length;
73};
74
75
76/* AES_CCMP specific */
77enum {
78 AESCCMP_BLK_SIZE = 16, /* # octets in an AES block */
79 AESCCMP_MAX_PACKET = 4*512, /* largest packet size */
80 AESCCMP_N_RESERVED = 0, /* reserved nonce octet value */
81 AESCCMP_A_DATA = 0x40, /* the Adata bit in the flags */
82 AESCCMP_M_SHIFT = 3, /* how much to shift the 3-bit M field */
83 AESCCMP_L_SHIFT = 0, /* how much to shift the 3-bit L field */
84 AESCCMP_L_SIZE = 2, /* size of the l(m) length field (in octets) */
85 AESCCMP_OFFSET_SC = 22,
86 AESCCMP_OFFSET_DURATION = 4,
87 AESCCMP_OFFSET_A2 = 10,
88 AESCCMP_OFFSET_A4 = 24,
89 AESCCMP_QC_TID_MASK = 0x0f,
90 AESCCMP_BLK_SIZE_TOTAL = 16*16, /* Added by Annie for CKIP AES MIC BSOD, 2006-08-17. */
91 /* 16*8 < 4*60 Resove to 16*16 */
92};
93
94/* Key Length */
95#define PMK_LEN 32
96#define PTK_LEN_TKIP 64
97#define GTK_LEN 32
98#define KEY_NONCE_LEN 32
99
100
101/* COMMON/Dot11d.h */
102struct chnl_txpower_triple {
103 u8 FirstChnl;
104 u8 NumChnls;
105 s8 MaxTxPowerInDbm;
106};
107
108
109/* ===== Below this line is sync from SD7 driver COMMON/bt_hci.h ===== */
110/* The following is for BT 3.0 + HS HCI COMMAND ERRORS CODES */
111
112#define Max80211PALPDUSize 1492
113#define Max80211AMPASSOCLen 672
114#define MinGUserPrio 4
115#define MaxGUserPrio 7
116#define BEUserPrio0 0
117#define BEUserPrio1 3
118#define Max80211BeaconPeriod 2000
119#define ShortRangeModePowerMax 4
120
121#define BT_Default_Chnl 10
122#define ACLDataHeaderLen 4
123
124#define BTTotalDataBlockNum 0x100
125#define BTLocalBufNum 0x200
126#define BTMaxDataBlockLen 0x800
127#define BTTOTALBANDWIDTH 0x7530
128#define BTMAXBANDGUBANDWIDTH 0x4e20
129#define TmpLocalBufSize 0x100
130#define BTSynDataPacketLength 0xff
131/* */
132
133#define BTMaxAuthCount 5
134#define BTMaxAsocCount 5
135
136#define MAX_LOGICAL_LINK_NUM 2 /* temporarily define */
137#define MAX_BT_ASOC_ENTRY_NUM 2 /* temporarily define */
138
139#define INVALID_PL_HANDLE 0xff
140#define INVALID_ENTRY_NUM 0xff
141/* */
142
143#define CAM_BT_START_INDEX (HALF_CAM_ENTRY - 4) /* MAX_BT_ASOC_ENTRY_NUM : 4 !!! */
144#define BT_HWCAM_STAR CAM_BT_START_INDEX /* We used HALF_CAM_ENTRY ~ HALF_CAM_ENTRY -MAX_BT_ASOC_ENTRY_NUM */
145
146enum hci_status {
147 HCI_STATUS_SUCCESS = 0x00, /* Success */
148 HCI_STATUS_UNKNOW_HCI_CMD = 0x01, /* Unknown HCI Command */
149 HCI_STATUS_UNKNOW_CONNECT_ID = 0X02, /* Unknown Connection Identifier */
150 HCI_STATUS_HW_FAIL = 0X03, /* Hardware Failure */
151 HCI_STATUS_PAGE_TIMEOUT = 0X04, /* Page Timeout */
152 HCI_STATUS_AUTH_FAIL = 0X05, /* Authentication Failure */
153 HCI_STATUS_PIN_OR_KEY_MISSING = 0X06, /* PIN or Key Missing */
154 HCI_STATUS_MEM_CAP_EXCEED = 0X07, /* Memory Capacity Exceeded */
155 HCI_STATUS_CONNECT_TIMEOUT = 0X08, /* Connection Timeout */
156 HCI_STATUS_CONNECT_LIMIT = 0X09, /* Connection Limit Exceeded */
157 HCI_STATUS_SYN_CONNECT_LIMIT = 0X0a, /* Synchronous Connection Limit To A Device Exceeded */
158 HCI_STATUS_ACL_CONNECT_EXISTS = 0X0b, /* ACL Connection Already Exists */
159 HCI_STATUS_CMD_DISALLOW = 0X0c, /* Command Disallowed */
160 HCI_STATUS_CONNECT_RJT_LIMIT_RESOURCE = 0X0d, /* Connection Rejected due to Limited Resources */
161 HCI_STATUS_CONNECT_RJT_SEC_REASON = 0X0e, /* Connection Rejected Due To Security Reasons */
162 HCI_STATUS_CONNECT_RJT_UNACCEPT_BD_ADDR = 0X0f, /* Connection Rejected due to Unacceptable BD_ADDR */
163 HCI_STATUS_CONNECT_ACCEPT_TIMEOUT = 0X10, /* Connection Accept Timeout Exceeded */
164 HCI_STATUS_UNSUPPORT_FEATURE_PARA_VALUE = 0X11, /* Unsupported Feature or Parameter Value */
165 HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE = 0X12, /* Invalid HCI Command Parameters */
166 HCI_STATUS_REMOTE_USER_TERMINATE_CONNECT = 0X13, /* Remote User Terminated Connection */
167 HCI_STATUS_REMOTE_DEV_TERMINATE_LOW_RESOURCE = 0X14, /* Remote Device Terminated Connection due to Low Resources */
168 HCI_STATUS_REMOTE_DEV_TERMINATE_CONNECT_POWER_OFF = 0X15, /* Remote Device Terminated Connection due to Power Off */
169 HCI_STATUS_CONNECT_TERMINATE_LOCAL_HOST = 0X16, /* Connection Terminated By Local Host */
170 HCI_STATUS_REPEATE_ATTEMPT = 0X17, /* Repeated Attempts */
171 HCI_STATUS_PAIR_NOT_ALLOW = 0X18, /* Pairing Not Allowed */
172 HCI_STATUS_UNKNOW_LMP_PDU = 0X19, /* Unknown LMP PDU */
173 HCI_STATUS_UNSUPPORT_REMOTE_LMP_FEATURE = 0X1a, /* Unsupported Remote Feature / Unsupported LMP Feature */
174 HCI_STATUS_SOC_OFFSET_REJECT = 0X1b, /* SCO Offset Rejected */
175 HCI_STATUS_SOC_INTERVAL_REJECT = 0X1c, /* SCO Interval Rejected */
176 HCI_STATUS_SOC_AIR_MODE_REJECT = 0X1d,/* SCO Air Mode Rejected */
177 HCI_STATUS_INVALID_LMP_PARA = 0X1e, /* Invalid LMP Parameters */
178 HCI_STATUS_UNSPECIFIC_ERROR = 0X1f, /* Unspecified Error */
179 HCI_STATUS_UNSUPPORT_LMP_PARA_VALUE = 0X20, /* Unsupported LMP Parameter Value */
180 HCI_STATUS_ROLE_CHANGE_NOT_ALLOW = 0X21, /* Role Change Not Allowed */
181 HCI_STATUS_LMP_RESPONSE_TIMEOUT = 0X22, /* LMP Response Timeout */
182 HCI_STATUS_LMP_ERROR_TRANSACTION_COLLISION = 0X23, /* LMP Error Transaction Collision */
183 HCI_STATUS_LMP_PDU_NOT_ALLOW = 0X24, /* LMP PDU Not Allowed */
184 HCI_STATUS_ENCRYPTION_MODE_NOT_ALLOW = 0X25, /* Encryption Mode Not Acceptable */
185 HCI_STATUS_LINK_KEY_CAN_NOT_CHANGE = 0X26, /* Link Key Can Not be Changed */
186 HCI_STATUS_REQUEST_QOS_NOT_SUPPORT = 0X27, /* Requested QoS Not Supported */
187 HCI_STATUS_INSTANT_PASSED = 0X28, /* Instant Passed */
188 HCI_STATUS_PAIRING_UNIT_KEY_NOT_SUPPORT = 0X29, /* Pairing With Unit Key Not Supported */
189 HCI_STATUS_DIFFERENT_TRANSACTION_COLLISION = 0X2a, /* Different Transaction Collision */
190 HCI_STATUS_RESERVE_1 = 0X2b, /* Reserved */
191 HCI_STATUS_QOS_UNACCEPT_PARA = 0X2c, /* QoS Unacceptable Parameter */
192 HCI_STATUS_QOS_REJECT = 0X2d, /* QoS Rejected */
193 HCI_STATUS_CHNL_CLASSIFICATION_NOT_SUPPORT = 0X2e, /* Channel Classification Not Supported */
194 HCI_STATUS_INSUFFICIENT_SECURITY = 0X2f, /* Insufficient Security */
195 HCI_STATUS_PARA_OUT_OF_RANGE = 0x30, /* Parameter Out Of Mandatory Range */
196 HCI_STATUS_RESERVE_2 = 0X31, /* Reserved */
197 HCI_STATUS_ROLE_SWITCH_PENDING = 0X32, /* Role Switch Pending */
198 HCI_STATUS_RESERVE_3 = 0X33, /* Reserved */
199 HCI_STATUS_RESERVE_SOLT_VIOLATION = 0X34, /* Reserved Slot Violation */
200 HCI_STATUS_ROLE_SWITCH_FAIL = 0X35, /* Role Switch Failed */
201 HCI_STATUS_EXTEND_INQUIRY_RSP_TOO_LARGE = 0X36, /* Extended Inquiry Response Too Large */
202 HCI_STATUS_SEC_SIMPLE_PAIRING_NOT_SUPPORT = 0X37, /* Secure Simple Pairing Not Supported By Host. */
203 HCI_STATUS_HOST_BUSY_PAIRING = 0X38, /* Host Busy - Pairing */
204 HCI_STATUS_CONNECT_REJ_NOT_SUIT_CHNL_FOUND = 0X39, /* Connection Rejected due to No Suitable Channel Found */
205 HCI_STATUS_CONTROLLER_BUSY = 0X3a /* CONTROLLER BUSY */
206};
207
208/* */
209/* The following is for BT 3.0 + HS HCI COMMAND */
210/* */
211
212/* bit 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
213/* | OCF | OGF | */
214/* */
215
216/* OGF 0x01 */
217#define LINK_CONTROL_COMMANDS 0x01
218enum link_control_commands {
219 HCI_INQUIRY = 0x0001,
220 HCI_INQUIRY_CANCEL = 0x0002,
221 HCI_PERIODIC_INQUIRY_MODE = 0x0003,
222 HCI_EXIT_PERIODIC_INQUIRY_MODE = 0x0004,
223 HCI_CREATE_CONNECTION = 0x0005,
224 HCI_DISCONNECT = 0x0006,
225 HCI_CREATE_CONNECTION_CANCEL = 0x0008,
226 HCI_ACCEPT_CONNECTIONREQUEST = 0x0009,
227 HCI_REJECT_CONNECTION_REQUEST = 0x000a,
228 HCI_LINK_KEY_REQUEST_REPLY = 0x000b,
229 HCI_LINK_KEY_REQUEST_NEGATIVE_REPLY = 0x000c,
230 HCI_PIN_CODE_REQUEST_REPLY = 0x000d,
231 HCI_PIN_CODE_REQUEST_NEGATIVE_REPLY = 0x000e,
232 HCI_CHANGE_CONNECTION_PACKET_TYPE = 0x000f,
233 HCI_AUTHENTICATION_REQUESTED = 0x0011,
234 HCI_SET_CONNECTION_ENCRYPTION = 0x0013,
235 HCI_CHANGE_CONNECTION_LINK_KEY = 0x0015,
236 HCI_MASTER_LINK_KEY = 0x0017,
237 HCI_REMOTE_NAME_REQUEST = 0x0019,
238 HCI_REMOTE_NAME_REQUEST_CANCEL = 0x001a,
239 HCI_READ_REMOTE_SUPPORTED_FEATURES = 0x001b,
240 HCI_READ_REMOTE_EXTENDED_FEATURES = 0x001c,
241 HCI_READ_REMOTE_VERSION_INFORMATION = 0x001d,
242 HCI_READ_CLOCK_OFFSET = 0x001f,
243 HCI_READ_LMP_HANDLE = 0x0020,
244 HCI_SETUP_SYNCHRONOUS_CONNECTION = 0x0028,
245 HCI_ACCEPT_SYNCHRONOUS_CONNECTION_REQUEST = 0x0029,
246 HCI_REJECT_SYNCHRONOUS_CONNECTION_REQUEST = 0x002a,
247 HCI_IO_CAPABILITY_REQUEST_REPLY = 0x002b,
248 HCI_USER_CONFIRMATION_REQUEST_REPLY = 0x002c,
249 HCI_USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY = 0x002d,
250 HCI_USER_PASSKEY_REQUEST_REPLY = 0x002e,
251 HCI_USER_PASSKEY_REQUESTNEGATIVE_REPLY = 0x002f,
252 HCI_REMOTE_OOB_DATA_REQUEST_REPLY = 0x0030,
253 HCI_REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY = 0x0033,
254 HCI_IO_CAPABILITY_REQUEST_NEGATIVE_REPLY = 0x0034,
255 HCI_CREATE_PHYSICAL_LINK = 0x0035,
256 HCI_ACCEPT_PHYSICAL_LINK = 0x0036,
257 HCI_DISCONNECT_PHYSICAL_LINK = 0x0037,
258 HCI_CREATE_LOGICAL_LINK = 0x0038,
259 HCI_ACCEPT_LOGICAL_LINK = 0x0039,
260 HCI_DISCONNECT_LOGICAL_LINK = 0x003a,
261 HCI_LOGICAL_LINK_CANCEL = 0x003b,
262 HCI_FLOW_SPEC_MODIFY = 0x003c
263};
264
265/* OGF 0x02 */
266#define HOLD_MODE_COMMAND 0x02
267enum hold_mode_command {
268 HCI_HOLD_MODE = 0x0001,
269 HCI_SNIFF_MODE = 0x0002,
270 HCI_EXIT_SNIFF_MODE = 0x0003,
271 HCI_PARK_STATE = 0x0005,
272 HCI_EXIT_PARK_STATE = 0x0006,
273 HCI_QOS_SETUP = 0x0007,
274 HCI_ROLE_DISCOVERY = 0x0009,
275 HCI_SWITCH_ROLE = 0x000b,
276 HCI_READ_LINK_POLICY_SETTINGS = 0x000c,
277 HCI_WRITE_LINK_POLICY_SETTINGS = 0x000d,
278 HCI_READ_DEFAULT_LINK_POLICY_SETTINGS = 0x000e,
279 HCI_WRITE_DEFAULT_LINK_POLICY_SETTINGS = 0x000f,
280 HCI_FLOW_SPECIFICATION = 0x0010,
281 HCI_SNIFF_SUBRATING = 0x0011
282};
283
284/* OGF 0x03 */
285#define OGF_SET_EVENT_MASK_COMMAND 0x03
286enum set_event_mask_command {
287 HCI_SET_EVENT_MASK = 0x0001,
288 HCI_RESET = 0x0003,
289 HCI_SET_EVENT_FILTER = 0x0005,
290 HCI_FLUSH = 0x0008,
291 HCI_READ_PIN_TYPE = 0x0009,
292 HCI_WRITE_PIN_TYPE = 0x000a,
293 HCI_CREATE_NEW_UNIT_KEY = 0x000b,
294 HCI_READ_STORED_LINK_KEY = 0x000d,
295 HCI_WRITE_STORED_LINK_KEY = 0x0011,
296 HCI_DELETE_STORED_LINK_KEY = 0x0012,
297 HCI_WRITE_LOCAL_NAME = 0x0013,
298 HCI_READ_LOCAL_NAME = 0x0014,
299 HCI_READ_CONNECTION_ACCEPT_TIMEOUT = 0x0015,
300 HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT = 0x0016,
301 HCI_READ_PAGE_TIMEOUT = 0x0017,
302 HCI_WRITE_PAGE_TIMEOUT = 0x0018,
303 HCI_READ_SCAN_ENABLE = 0x0019,
304 HCI_WRITE_SCAN_ENABLE = 0x001a,
305 HCI_READ_PAGE_SCAN_ACTIVITY = 0x001b,
306 HCI_WRITE_PAGE_SCAN_ACTIVITY = 0x001c,
307 HCI_READ_INQUIRY_SCAN_ACTIVITY = 0x001d,
308 HCI_WRITE_INQUIRY_SCAN_ACTIVITY = 0x001e,
309 HCI_READ_AUTHENTICATION_ENABLE = 0x001f,
310 HCI_WRITE_AUTHENTICATION_ENABLE = 0x0020,
311 HCI_READ_CLASS_OF_DEVICE = 0x0023,
312 HCI_WRITE_CLASS_OF_DEVICE = 0x0024,
313 HCI_READ_VOICE_SETTING = 0x0025,
314 HCI_WRITE_VOICE_SETTING = 0x0026,
315 HCI_READ_AUTOMATIC_FLUSH_TIMEOUT = 0x0027,
316 HCI_WRITE_AUTOMATIC_FLUSH_TIMEOUT = 0x0028,
317 HCI_READ_NUM_BROADCAST_RETRANSMISSIONS = 0x0029,
318 HCI_WRITE_NUM_BROADCAST_RETRANSMISSIONS = 0x002a,
319 HCI_READ_HOLD_MODE_ACTIVITY = 0x002b,
320 HCI_WRITE_HOLD_MODE_ACTIVITY = 0x002c,
321 HCI_READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE = 0x002e,
322 HCI_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE = 0x002f,
323 HCI_SET_CONTROLLER_TO_HOST_FLOW_CONTROL = 0x0031,
324 HCI_HOST_BUFFER_SIZE = 0x0033,
325 HCI_HOST_NUMBER_OF_COMPLETED_PACKETS = 0x0035,
326 HCI_READ_LINK_SUPERVISION_TIMEOUT = 0x0036,
327 HCI_WRITE_LINK_SUPERVISION_TIMEOUT = 0x0037,
328 HCI_READ_NUMBER_OF_SUPPORTED_IAC = 0x0038,
329 HCI_READ_CURRENT_IAC_LAP = 0x0039,
330 HCI_WRITE_CURRENT_IAC_LAP = 0x003a,
331 HCI_READ_PAGE_SCAN_MODE = 0x003d,
332 HCI_WRITE_PAGE_SCAN_MODE = 0x003e,
333 HCI_SET_AFH_HOST_CHANNEL_CLASSIFICATION = 0x003f,
334 HCI_READ_INQUIRY_SCAN_TYPE = 0x0042,
335 HCI_WRITE_INQUIRY_SCAN_TYPE = 0x0043,
336 HCI_READ_INQUIRY_MODE = 0x0044,
337 HCI_WRITE_INQUIRY_MODE = 0x0045,
338 HCI_READ_PAGE_SCAN_TYPE = 0x0046,
339 HCI_WRITE_PAGE_SCAN_TYPE = 0x0047,
340 HCI_READ_AFH_CHANNEL_ASSESSMENT_MODE = 0x0048,
341 HCI_WRITE_AFH_CHANNEL_ASSESSMENT_MODE = 0x0049,
342 HCI_READ_EXTENDED_INQUIRY_RESPONSE = 0x0051,
343 HCI_WRITE_EXTENDED_INQUIRY_RESPONSE = 0x0052,
344 HCI_REFRESH_ENCRYPTION_KEY = 0x0053,
345 HCI_READ_SIMPLE_PAIRING_MODE = 0x0055,
346 HCI_WRITE_SIMPLE_PAIRING_MODE = 0x0056,
347 HCI_READ_LOCAL_OOB_DATA = 0x0057,
348 HCI_READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL = 0x0058,
349 HCI_WRITE_INQUIRY_TRANSMIT_POWER_LEVEL = 0x0059,
350 HCI_READ_DEFAULT_ERRONEOUS_DATA_REPORTING = 0x005a,
351 HCI_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING = 0x005b,
352 HCI_ENHANCED_FLUSH = 0x005f,
353 HCI_SEND_KEYPRESS_NOTIFICATION = 0x0060,
354 HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT = 0x0061,
355 HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT = 0x0062,
356 HCI_SET_EVENT_MASK_PAGE_2 = 0x0063,
357 HCI_READ_LOCATION_DATA = 0x0064,
358 HCI_WRITE_LOCATION_DATA = 0x0065,
359 HCI_READ_FLOW_CONTROL_MODE = 0x0066,
360 HCI_WRITE_FLOW_CONTROL_MODE = 0x0067,
361 HCI_READ_ENHANCE_TRANSMIT_POWER_LEVEL = 0x0068,
362 HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT = 0x0069,
363 HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT = 0x006a,
364 HCI_SHORT_RANGE_MODE = 0x006b
365};
366
367/* OGF 0x04 */
368#define OGF_INFORMATIONAL_PARAMETERS 0x04
369enum informational_params {
370 HCI_READ_LOCAL_VERSION_INFORMATION = 0x0001,
371 HCI_READ_LOCAL_SUPPORTED_COMMANDS = 0x0002,
372 HCI_READ_LOCAL_SUPPORTED_FEATURES = 0x0003,
373 HCI_READ_LOCAL_EXTENDED_FEATURES = 0x0004,
374 HCI_READ_BUFFER_SIZE = 0x0005,
375 HCI_READ_BD_ADDR = 0x0009,
376 HCI_READ_DATA_BLOCK_SIZE = 0x000a
377};
378
379/* OGF 0x05 */
380#define OGF_STATUS_PARAMETERS 0x05
381enum status_params {
382 HCI_READ_FAILED_CONTACT_COUNTER = 0x0001,
383 HCI_RESET_FAILED_CONTACT_COUNTER = 0x0002,
384 HCI_READ_LINK_QUALITY = 0x0003,
385 HCI_READ_RSSI = 0x0005,
386 HCI_READ_AFH_CHANNEL_MAP = 0x0006,
387 HCI_READ_CLOCK = 0x0007,
388 HCI_READ_ENCRYPTION_KEY_SIZE = 0x0008,
389 HCI_READ_LOCAL_AMP_INFO = 0x0009,
390 HCI_READ_LOCAL_AMP_ASSOC = 0x000a,
391 HCI_WRITE_REMOTE_AMP_ASSOC = 0x000b
392};
393
394/* OGF 0x06 */
395#define OGF_TESTING_COMMANDS 0x06
396enum testing_commands {
397 HCI_READ_LOOPBACK_MODE = 0x0001,
398 HCI_WRITE_LOOPBACK_MODE = 0x0002,
399 HCI_ENABLE_DEVICE_UNDER_TEST_MODE = 0x0003,
400 HCI_WRITE_SIMPLE_PAIRING_DEBUG_MODE = 0x0004,
401 HCI_ENABLE_AMP_RECEIVER_REPORTS = 0x0007,
402 HCI_AMP_TEST_END = 0x0008,
403 HCI_AMP_TEST_COMMAND = 0x0009
404};
405
406/* OGF 0x3f */
407#define OGF_EXTENSION 0X3f
408enum hci_extension_commands {
409 HCI_SET_ACL_LINK_DATA_FLOW_MODE = 0x0010,
410 HCI_SET_ACL_LINK_STATUS = 0x0020,
411 HCI_SET_SCO_LINK_STATUS = 0x0030,
412 HCI_SET_RSSI_VALUE = 0x0040,
413 HCI_SET_CURRENT_BLUETOOTH_STATUS = 0x0041,
414
415 /* The following is for RTK8723 */
416 HCI_EXTENSION_VERSION_NOTIFY = 0x0100,
417 HCI_LINK_STATUS_NOTIFY = 0x0101,
418 HCI_BT_OPERATION_NOTIFY = 0x0102,
419 HCI_ENABLE_WIFI_SCAN_NOTIFY = 0x0103,
420
421
422 /* The following is for IVT */
423 HCI_WIFI_CURRENT_CHANNEL = 0x0300,
424 HCI_WIFI_CURRENT_BANDWIDTH = 0x0301,
425 HCI_WIFI_CONNECTION_STATUS = 0x0302,
426};
427
428enum bt_spec {
429 BT_SPEC_1_0_b = 0x00,
430 BT_SPEC_1_1 = 0x01,
431 BT_SPEC_1_2 = 0x02,
432 BT_SPEC_2_0_EDR = 0x03,
433 BT_SPEC_2_1_EDR = 0x04,
434 BT_SPEC_3_0_HS = 0x05,
435 BT_SPEC_4_0 = 0x06
436};
437
438/* The following is for BT 3.0 + HS EVENTS */
439enum hci_event {
440 HCI_EVENT_INQUIRY_COMPLETE = 0x01,
441 HCI_EVENT_INQUIRY_RESULT = 0x02,
442 HCI_EVENT_CONNECTION_COMPLETE = 0x03,
443 HCI_EVENT_CONNECTION_REQUEST = 0x04,
444 HCI_EVENT_DISCONNECTION_COMPLETE = 0x05,
445 HCI_EVENT_AUTHENTICATION_COMPLETE = 0x06,
446 HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE = 0x07,
447 HCI_EVENT_ENCRYPTION_CHANGE = 0x08,
448 HCI_EVENT_CHANGE_LINK_KEY_COMPLETE = 0x09,
449 HCI_EVENT_MASTER_LINK_KEY_COMPLETE = 0x0a,
450 HCI_EVENT_READ_REMOTE_SUPPORT_FEATURES_COMPLETE = 0x0b,
451 HCI_EVENT_READ_REMOTE_VER_INFO_COMPLETE = 0x0c,
452 HCI_EVENT_QOS_SETUP_COMPLETE = 0x0d,
453 HCI_EVENT_COMMAND_COMPLETE = 0x0e,
454 HCI_EVENT_COMMAND_STATUS = 0x0f,
455 HCI_EVENT_HARDWARE_ERROR = 0x10,
456 HCI_EVENT_FLUSH_OCCRUED = 0x11,
457 HCI_EVENT_ROLE_CHANGE = 0x12,
458 HCI_EVENT_NUMBER_OF_COMPLETE_PACKETS = 0x13,
459 HCI_EVENT_MODE_CHANGE = 0x14,
460 HCI_EVENT_RETURN_LINK_KEYS = 0x15,
461 HCI_EVENT_PIN_CODE_REQUEST = 0x16,
462 HCI_EVENT_LINK_KEY_REQUEST = 0x17,
463 HCI_EVENT_LINK_KEY_NOTIFICATION = 0x18,
464 HCI_EVENT_LOOPBACK_COMMAND = 0x19,
465 HCI_EVENT_DATA_BUFFER_OVERFLOW = 0x1a,
466 HCI_EVENT_MAX_SLOTS_CHANGE = 0x1b,
467 HCI_EVENT_READ_CLOCK_OFFSET_COMPLETE = 0x1c,
468 HCI_EVENT_CONNECT_PACKET_TYPE_CHANGE = 0x1d,
469 HCI_EVENT_QOS_VIOLATION = 0x1e,
470 HCI_EVENT_PAGE_SCAN_REPETITION_MODE_CHANGE = 0x20,
471 HCI_EVENT_FLOW_SEPC_COMPLETE = 0x21,
472 HCI_EVENT_INQUIRY_RESULT_WITH_RSSI = 0x22,
473 HCI_EVENT_READ_REMOTE_EXT_FEATURES_COMPLETE = 0x23,
474 HCI_EVENT_SYNC_CONNECT_COMPLETE = 0x2c,
475 HCI_EVENT_SYNC_CONNECT_CHANGE = 0x2d,
476 HCI_EVENT_SNIFFER_SUBRATING = 0x2e,
477 HCI_EVENT_EXTENTED_INQUIRY_RESULT = 0x2f,
478 HCI_EVENT_ENCRYPTION_KEY_REFLASH_COMPLETE = 0x30,
479 HCI_EVENT_IO_CAPIBILITY_COMPLETE = 0x31,
480 HCI_EVENT_IO_CAPIBILITY_RESPONSE = 0x32,
481 HCI_EVENT_USER_CONFIRMTION_REQUEST = 0x33,
482 HCI_EVENT_USER_PASSKEY_REQUEST = 0x34,
483 HCI_EVENT_REMOTE_OOB_DATA_REQUEST = 0x35,
484 HCI_EVENT_SIMPLE_PAIRING_COMPLETE = 0x36,
485 HCI_EVENT_LINK_SUPERVISION_TIMEOUT_CHANGE = 0x38,
486 HCI_EVENT_ENHANCED_FLUSH_COMPLETE = 0x39,
487 HCI_EVENT_USER_PASSKEY_NOTIFICATION = 0x3b,
488 HCI_EVENT_KEYPRESS_NOTIFICATION = 0x3c,
489 HCI_EVENT_REMOTE_HOST_SUPPORT_FEATURES_NOTIFICATION = 0x3d,
490 HCI_EVENT_PHY_LINK_COMPLETE = 0x40,
491 HCI_EVENT_CHANNEL_SELECT = 0x41,
492 HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE = 0x42,
493 HCI_EVENT_PHY_LINK_LOSS_EARLY_WARNING = 0x43,
494 HCI_EVENT_PHY_LINK_RECOVER = 0x44,
495 HCI_EVENT_LOGICAL_LINK_COMPLETE = 0x45,
496 HCI_EVENT_DISCONNECT_LOGICAL_LINK_COMPLETE = 0x46,
497 HCI_EVENT_FLOW_SPEC_MODIFY_COMPLETE = 0x47,
498 HCI_EVENT_NUM_OF_COMPLETE_DATA_BLOCKS = 0x48,
499 HCI_EVENT_AMP_START_TEST = 0x49,
500 HCI_EVENT_AMP_TEST_END = 0x4a,
501 HCI_EVENT_AMP_RECEIVER_REPORT = 0x4b,
502 HCI_EVENT_SHORT_RANGE_MODE_CHANGE_COMPLETE = 0x4c,
503 HCI_EVENT_AMP_STATUS_CHANGE = 0x4d,
504 HCI_EVENT_EXTENSION_RTK = 0xfe,
505 HCI_EVENT_EXTENSION_MOTO = 0xff,
506};
507
508enum hci_extension_event_moto {
509 HCI_EVENT_GET_BT_RSSI = 0x01,
510};
511
512enum hci_extension_event {
513 HCI_EVENT_EXT_WIFI_SCAN_NOTIFY = 0x01,
514};
515
516enum hci_event_mask_page_2 {
517 EMP2_HCI_EVENT_PHY_LINK_COMPLETE = 0x0000000000000001,
518 EMP2_HCI_EVENT_CHANNEL_SELECT = 0x0000000000000002,
519 EMP2_HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE = 0x0000000000000004,
520 EMP2_HCI_EVENT_PHY_LINK_LOSS_EARLY_WARNING = 0x0000000000000008,
521 EMP2_HCI_EVENT_PHY_LINK_RECOVER = 0x0000000000000010,
522 EMP2_HCI_EVENT_LOGICAL_LINK_COMPLETE = 0x0000000000000020,
523 EMP2_HCI_EVENT_DISCONNECT_LOGICAL_LINK_COMPLETE = 0x0000000000000040,
524 EMP2_HCI_EVENT_FLOW_SPEC_MODIFY_COMPLETE = 0x0000000000000080,
525 EMP2_HCI_EVENT_NUM_OF_COMPLETE_DATA_BLOCKS = 0x0000000000000100,
526 EMP2_HCI_EVENT_AMP_START_TEST = 0x0000000000000200,
527 EMP2_HCI_EVENT_AMP_TEST_END = 0x0000000000000400,
528 EMP2_HCI_EVENT_AMP_RECEIVER_REPORT = 0x0000000000000800,
529 EMP2_HCI_EVENT_SHORT_RANGE_MODE_CHANGE_COMPLETE = 0x0000000000001000,
530 EMP2_HCI_EVENT_AMP_STATUS_CHANGE = 0x0000000000002000,
531};
532
533enum hci_state_machine {
534 HCI_STATE_STARTING = 0x01,
535 HCI_STATE_CONNECTING = 0x02,
536 HCI_STATE_AUTHENTICATING = 0x04,
537 HCI_STATE_CONNECTED = 0x08,
538 HCI_STATE_DISCONNECTING = 0x10,
539 HCI_STATE_DISCONNECTED = 0x20
540};
541
542enum amp_assoc_structure_type {
543 AMP_MAC_ADDR = 0x01,
544 AMP_PREFERRED_CHANNEL_LIST = 0x02,
545 AMP_CONNECTED_CHANNEL = 0x03,
546 AMP_80211_PAL_CAP_LIST = 0x04,
547 AMP_80211_PAL_VISION = 0x05,
548 AMP_RESERVED_FOR_TESTING = 0x33
549};
550
551enum amp_btap_type {
552 AMP_BTAP_NONE,
553 AMP_BTAP_CREATOR,
554 AMP_BTAP_JOINER
555};
556
557enum hci_state_with_cmd {
558 STATE_CMD_CREATE_PHY_LINK,
559 STATE_CMD_ACCEPT_PHY_LINK,
560 STATE_CMD_DISCONNECT_PHY_LINK,
561 STATE_CMD_CONNECT_ACCEPT_TIMEOUT,
562 STATE_CMD_MAC_START_COMPLETE,
563 STATE_CMD_MAC_START_FAILED,
564 STATE_CMD_MAC_CONNECT_COMPLETE,
565 STATE_CMD_MAC_CONNECT_FAILED,
566 STATE_CMD_MAC_DISCONNECT_INDICATE,
567 STATE_CMD_MAC_CONNECT_CANCEL_INDICATE,
568 STATE_CMD_4WAY_FAILED,
569 STATE_CMD_4WAY_SUCCESSED,
570 STATE_CMD_ENTER_STATE,
571 STATE_CMD_NO_SUCH_CMD,
572};
573
574enum hci_service_type {
575 SERVICE_NO_TRAFFIC,
576 SERVICE_BEST_EFFORT,
577 SERVICE_GUARANTEE
578};
579
580enum hci_traffic_mode {
581 TRAFFIC_MODE_BEST_EFFORT = 0x00,
582 TRAFFIC_MODE_GUARANTEED_LATENCY = 0x01,
583 TRAFFIC_MODE_GUARANTEED_BANDWIDTH = 0x02,
584 TRAFFIC_MODE_GUARANTEED_LATENCY_AND_BANDWIDTH = 0x03
585};
586
587#define HCIOPCODE(_OCF, _OGF) (_OGF<<10|_OCF)
588#define HCIOPCODELOW(_OCF, _OGF) (u8)(HCIOPCODE(_OCF, _OGF)&0x00ff)
589#define HCIOPCODEHIGHT(_OCF, _OGF) (u8)(HCIOPCODE(_OCF, _OGF)>>8)
590
591#define TWOBYTE_HIGHTBYTE(_DATA) (u8)(_DATA>>8)
592#define TWOBYTE_LOWBYTE(_DATA) (u8)(_DATA)
593
594enum amp_status {
595 AMP_STATUS_AVA_PHY_PWR_DWN = 0x0,
596 AMP_STATUS_BT_USE_ONLY = 0x1,
597 AMP_STATUS_NO_CAPACITY_FOR_BT = 0x2,
598 AMP_STATUS_LOW_CAPACITY_FOR_BT = 0x3,
599 AMP_STATUS_MEDIUM_CAPACITY_FOR_BT = 0x4,
600 AMP_STATUS_HIGH_CAPACITY_FOR_BT = 0x5,
601 AMP_STATUS_FULL_CAPACITY_FOR_BT = 0x6
602};
603
604enum bt_wpa_msg_type {
605 Type_BT_4way1st = 0,
606 Type_BT_4way2nd = 1,
607 Type_BT_4way3rd = 2,
608 Type_BT_4way4th = 3,
609 Type_BT_unknow = 4
610};
611
612enum bt_connect_type {
613 BT_CONNECT_AUTH_REQ = 0x00,
614 BT_CONNECT_AUTH_RSP = 0x01,
615 BT_CONNECT_ASOC_REQ = 0x02,
616 BT_CONNECT_ASOC_RSP = 0x03,
617 BT_DISCONNECT = 0x04
618};
619
620enum bt_ll_service_type {
621 BT_LL_BE = 0x01,
622 BT_LL_GU = 0x02
623};
624
625enum bt_ll_flowspec {
626 BT_TX_BE_FS, /* TX best effort flowspec */
627 BT_RX_BE_FS, /* RX best effort flowspec */
628 BT_TX_GU_FS, /* TX guaranteed latency flowspec */
629 BT_RX_GU_FS, /* RX guaranteed latency flowspec */
630 BT_TX_BE_AGG_FS, /* TX aggregated best effort flowspec */
631 BT_RX_BE_AGG_FS, /* RX aggregated best effort flowspec */
632 BT_TX_GU_BW_FS, /* TX guaranteed bandwidth flowspec */
633 BT_RX_GU_BW_FS, /* RX guaranteed bandwidth flowspec */
634 BT_TX_GU_LARGE_FS, /* TX guaranteed latency flowspec, for testing only */
635 BT_RX_GU_LARGE_FS, /* RX guaranteed latency flowspec, for testing only */
636};
637
638enum bt_traffic_mode {
639 BT_MOTOR_EXT_BE = 0x00, /* Best Effort. Default. for HCRP, PAN, SDP, RFCOMM-based profiles like FTP, OPP, SPP, DUN, etc. */
640 BT_MOTOR_EXT_GUL = 0x01, /* Guaranteed Latency. This type of traffic is used e.g. for HID and AVRCP. */
641 BT_MOTOR_EXT_GUB = 0X02, /* Guaranteed Bandwidth. */
642 BT_MOTOR_EXT_GULB = 0X03 /* Guaranteed Latency and Bandwidth. for A2DP and VDP. */
643};
644
645enum bt_traffic_mode_profile {
646 BT_PROFILE_NONE,
647 BT_PROFILE_A2DP,
648 BT_PROFILE_PAN,
649 BT_PROFILE_HID,
650 BT_PROFILE_SCO
651};
652
653enum bt_link_role {
654 BT_LINK_MASTER = 0,
655 BT_LINK_SLAVE = 1
656};
657
658enum bt_state_wpa_auth {
659 STATE_WPA_AUTH_UNINITIALIZED,
660 STATE_WPA_AUTH_WAIT_PACKET_1, /* Join */
661 STATE_WPA_AUTH_WAIT_PACKET_2, /* Creat */
662 STATE_WPA_AUTH_WAIT_PACKET_3,
663 STATE_WPA_AUTH_WAIT_PACKET_4,
664 STATE_WPA_AUTH_SUCCESSED
665};
666
667#define BT_WPA_AUTH_TIMEOUT_PERIOD 1000
668#define BTMaxWPAAuthReTransmitCoun 5
669
670#define MAX_AMP_ASSOC_FRAG_LEN 248
671#define TOTAL_ALLOCIATE_ASSOC_LEN 1000
672
673struct hci_flow_spec {
674 u8 Identifier;
675 u8 ServiceType;
676 u16 MaximumSDUSize;
677 u32 SDUInterArrivalTime;
678 u32 AccessLatency;
679 u32 FlushTimeout;
680};
681
682struct hci_log_link_cmd_data {
683 u8 BtPhyLinkhandle;
684 u16 BtLogLinkhandle;
685 u8 BtTxFlowSpecID;
686 struct hci_flow_spec Tx_Flow_Spec;
687 struct hci_flow_spec Rx_Flow_Spec;
688 u32 TxPacketCount;
689 u32 BestEffortFlushTimeout;
690
691 u8 bLLCompleteEventIsSet;
692
693 u8 bLLCancelCMDIsSetandComplete;
694};
695
696struct hci_phy_link_cmd_data {
697 /* Physical_Link_Handle */
698 u8 BtPhyLinkhandle;
699
700 u16 LinkSuperversionTimeout;
701
702 /* u16 SuperTimeOutCnt; */
703
704 /* Dedicated_AMP_Key_Length */
705 u8 BtAMPKeyLen;
706 /* Dedicated_AMP_Key_Type */
707 u8 BtAMPKeyType;
708 /* Dedicated_AMP_Key */
709 u8 BtAMPKey[PMK_LEN];
710};
711
712struct amp_assoc_structure {
713 /* TYPE ID */
714 u8 TypeID;
715 /* Length */
716 u16 Length;
717 /* Value */
718 u8 Data[1];
719};
720
721struct amp_pref_chnl_regulatory {
722 u8 reXId;
723 u8 regulatoryClass;
724 u8 coverageClass;
725};
726
727struct amp_assoc_cmd_data {
728 /* Physical_Link_Handle */
729 u8 BtPhyLinkhandle;
730 /* Length_So_Far */
731 u16 LenSoFar;
732
733 u16 MaxRemoteASSOCLen;
734 /* AMP_ASSOC_Remaining_Length */
735 u16 AMPAssocRemLen;
736 /* AMP_ASSOC_fragment */
737 void *AMPAssocfragment;
738};
739
740struct hci_link_info {
741 u16 ConnectHandle;
742 u8 IncomingTrafficMode;
743 u8 OutgoingTrafficMode;
744 u8 BTProfile;
745 u8 BTCoreSpec;
746 s8 BT_RSSI;
747 u8 TrafficProfile;
748 u8 linkRole;
749};
750
751struct hci_ext_config {
752 struct hci_link_info linkInfo[MAX_BT_ASOC_ENTRY_NUM];
753 u8 btOperationCode;
754 u16 CurrentConnectHandle;
755 u8 CurrentIncomingTrafficMode;
756 u8 CurrentOutgoingTrafficMode;
757 s8 MIN_BT_RSSI;
758 u8 NumberOfHandle;
759 u8 NumberOfSCO;
760 u8 CurrentBTStatus;
761 u16 HCIExtensionVer;
762
763 /* Bt coexist related */
764 u8 btProfileCase;
765 u8 btProfileAction;
766 u8 bManualControl;
767 u8 bBTBusy;
768 u8 bBTA2DPBusy;
769 u8 bEnableWifiScanNotify;
770
771 u8 bHoldForBtOperation;
772 u32 bHoldPeriodCnt;
773};
774
775struct hci_acl_packet_data {
776 u16 ACLDataPacketLen;
777 u8 SyncDataPacketLen;
778 u16 TotalNumACLDataPackets;
779 u16 TotalSyncNumDataPackets;
780};
781
782struct hci_phy_link_bss_info {
783 u16 bdCap; /* capability information */
784};
785
786struct packet_irp_hcicmd_data {
787 u16 OCF:10;
788 u16 OGF:6;
789 u8 Length;
790 u8 Data[20];
791};
792
793struct bt_asoc_entry {
794 u8 bUsed;
795 u8 mAssoc;
796 u8 b4waySuccess;
797 u8 Bssid[6];
798 struct hci_phy_link_cmd_data PhyLinkCmdData;
799
800 struct hci_log_link_cmd_data LogLinkCmdData[MAX_LOGICAL_LINK_NUM];
801
802 struct hci_acl_packet_data ACLPacketsData;
803
804 struct amp_assoc_cmd_data AmpAsocCmdData;
805 struct octet_string BTSsid;
806 u8 BTSsidBuf[33];
807
808 enum hci_status PhyLinkDisconnectReason;
809
810 u8 bSendSupervisionPacket;
811 /* u8 CurrentSuervisionPacketSendNum; */
812 /* u8 LastSuervisionPacketSendNum; */
813 u32 NoRxPktCnt;
814 /* Is Creator or Joiner */
815 enum amp_btap_type AMPRole;
816
817 /* BT current state */
818 u8 BtCurrentState;
819 /* BT next state */
820 u8 BtNextState;
821
822 u8 bNeedPhysLinkCompleteEvent;
823
824 enum hci_status PhysLinkCompleteStatus;
825
826 u8 BTRemoteMACAddr[6];
827
828 u32 BTCapability;
829
830 u8 SyncDataPacketLen;
831
832 u16 TotalSyncNumDataPackets;
833 u16 TotalNumACLDataPackets;
834
835 u8 ShortRangeMode;
836
837 u8 PTK[PTK_LEN_TKIP];
838 u8 GTK[GTK_LEN];
839 u8 ANonce[KEY_NONCE_LEN];
840 u8 SNonce[KEY_NONCE_LEN];
841 u64 KeyReplayCounter;
842 u8 WPAAuthReplayCount;
843 u8 AESKeyBuf[AESCCMP_BLK_SIZE_TOTAL];
844 u8 PMK[PMK_LEN];
845 enum bt_state_wpa_auth BTWPAAuthState;
846 s32 UndecoratedSmoothedPWDB;
847
848 /* Add for HW security !! */
849 u8 HwCAMIndex; /* Cam index */
850 u8 bPeerQosSta;
851
852 u32 rxSuvpPktCnt;
853};
854
855struct bt_traffic_statistics {
856 u8 bTxBusyTraffic;
857 u8 bRxBusyTraffic;
858 u8 bIdle;
859 u32 TxPktCntInPeriod;
860 u32 RxPktCntInPeriod;
861 u64 TxPktLenInPeriod;
862 u64 RxPktLenInPeriod;
863};
864
865struct bt_mgnt {
866 u8 bBTConnectInProgress;
867 u8 bLogLinkInProgress;
868 u8 bPhyLinkInProgress;
869 u8 bPhyLinkInProgressStartLL;
870 u8 BtCurrentPhyLinkhandle;
871 u16 BtCurrentLogLinkhandle;
872 u8 CurrentConnectEntryNum;
873 u8 DisconnectEntryNum;
874 u8 CurrentBTConnectionCnt;
875 enum bt_connect_type BTCurrentConnectType;
876 enum bt_connect_type BTReceiveConnectPkt;
877 u8 BTAuthCount;
878 u8 BTAsocCount;
879 u8 bStartSendSupervisionPkt;
880 u8 BtOperationOn;
881 u8 BTNeedAMPStatusChg;
882 u8 JoinerNeedSendAuth;
883 struct hci_phy_link_bss_info bssDesc;
884 struct hci_ext_config ExtConfig;
885 u8 bNeedNotifyAMPNoCap;
886 u8 bCreateSpportQos;
887 u8 bSupportProfile;
888 u8 BTChannel;
889 u8 CheckChnlIsSuit;
890 u8 bBtScan;
891 u8 btLogoTest;
892};
893
894struct bt_hci_dgb_info {
895 u32 hciCmdCnt;
896 u32 hciCmdCntUnknown;
897 u32 hciCmdCntCreatePhyLink;
898 u32 hciCmdCntAcceptPhyLink;
899 u32 hciCmdCntDisconnectPhyLink;
900 u32 hciCmdPhyLinkStatus;
901 u32 hciCmdCntCreateLogLink;
902 u32 hciCmdCntAcceptLogLink;
903 u32 hciCmdCntDisconnectLogLink;
904 u32 hciCmdCntReadLocalAmpAssoc;
905 u32 hciCmdCntWriteRemoteAmpAssoc;
906 u32 hciCmdCntSetAclLinkStatus;
907 u32 hciCmdCntSetScoLinkStatus;
908 u32 hciCmdCntExtensionVersionNotify;
909 u32 hciCmdCntLinkStatusNotify;
910};
911
912struct bt_irp_dgb_info {
913 u32 irpMJCreate;
914 /* Io Control */
915 u32 irpIoControl;
916 u32 irpIoCtrlHciCmd;
917 u32 irpIoCtrlHciEvent;
918 u32 irpIoCtrlHciTxData;
919 u32 irpIoCtrlHciRxData;
920 u32 irpIoCtrlUnknown;
921
922 u32 irpIoCtrlHciTxData1s;
923};
924
925struct bt_packet_dgb_info {
926 u32 btPktTxProbReq;
927 u32 btPktRxProbReq;
928 u32 btPktRxProbReqFail;
929 u32 btPktTxProbRsp;
930 u32 btPktRxProbRsp;
931 u32 btPktTxAuth;
932 u32 btPktRxAuth;
933 u32 btPktRxAuthButDrop;
934 u32 btPktTxAssocReq;
935 u32 btPktRxAssocReq;
936 u32 btPktRxAssocReqButDrop;
937 u32 btPktTxAssocRsp;
938 u32 btPktRxAssocRsp;
939 u32 btPktTxDisassoc;
940 u32 btPktRxDisassoc;
941 u32 btPktRxDeauth;
942 u32 btPktTx4way1st;
943 u32 btPktRx4way1st;
944 u32 btPktTx4way2nd;
945 u32 btPktRx4way2nd;
946 u32 btPktTx4way3rd;
947 u32 btPktRx4way3rd;
948 u32 btPktTx4way4th;
949 u32 btPktRx4way4th;
950 u32 btPktTxLinkSuperReq;
951 u32 btPktRxLinkSuperReq;
952 u32 btPktTxLinkSuperRsp;
953 u32 btPktRxLinkSuperRsp;
954 u32 btPktTxData;
955 u32 btPktRxData;
956};
957
958struct bt_dgb {
959 u8 dbgCtrl;
960 u32 dbgProfile;
961 struct bt_hci_dgb_info dbgHciInfo;
962 struct bt_irp_dgb_info dbgIrpInfo;
963 struct bt_packet_dgb_info dbgBtPkt;
964};
965
966struct bt_hci_info {
967 /* 802.11 Pal version specifier */
968 u8 BTPalVersion;
969 u16 BTPalCompanyID;
970 u16 BTPalsubversion;
971
972 /* Connected channel list */
973 u16 BTConnectChnlListLen;
974 u8 BTConnectChnllist[64];
975
976 /* Fail contact counter */
977 u16 FailContactCount;
978
979 /* Event mask */
980 u64 BTEventMask;
981 u64 BTEventMaskPage2;
982
983 /* timeout var */
984 u16 ConnAcceptTimeout;
985 u16 LogicalAcceptTimeout;
986 u16 PageTimeout;
987
988 u8 LocationDomainAware;
989 u16 LocationDomain;
990 u8 LocationDomainOptions;
991 u8 LocationOptions;
992
993 u8 FlowControlMode;
994
995 /* Preferred channel list */
996 u16 BtPreChnlListLen;
997 u8 BTPreChnllist[64];
998
999 u16 enFlush_LLH; /* enhanced flush handle */
1000 u16 FLTO_LLH; /* enhanced flush handle */
1001
1002 /* */
1003 /* Test command only. */
1004 u8 bInTestMode;
1005 u8 bTestIsEnd;
1006 u8 bTestNeedReport;
1007 u8 TestScenario;
1008 u8 TestReportInterval;
1009 u8 TestCtrType;
1010 u32 TestEventType;
1011 u16 TestNumOfFrame;
1012 u16 TestNumOfErrFrame;
1013 u16 TestNumOfBits;
1014 u16 TestNumOfErrBits;
1015 /* */
1016};
1017
1018struct bt_traffic {
1019 /* Add for check replay data */
1020 u8 LastRxUniFragNum;
1021 u16 LastRxUniSeqNum;
1022
1023 /* s32 EntryMaxUndecoratedSmoothedPWDB; */
1024 /* s32 EntryMinUndecoratedSmoothedPWDB; */
1025
1026 struct bt_traffic_statistics Bt30TrafficStatistics;
1027};
1028
1029#define RT_WORK_ITEM struct work_struct
1030
1031struct bt_security {
1032 /* WPA auth state
1033 * May need to remove to BTSecInfo ...
1034 * enum bt_state_wpa_auth BTWPAAuthState;
1035 */
1036 struct octet_string RSNIE;
1037 u8 RSNIEBuf[MAXRSNIELEN];
1038 u8 bRegNoEncrypt;
1039 u8 bUsedHwEncrypt;
1040};
1041
1042struct bt_30info {
1043 struct rtw_adapter *padapter;
1044 struct bt_asoc_entry BtAsocEntry[MAX_BT_ASOC_ENTRY_NUM];
1045 struct bt_mgnt BtMgnt;
1046 struct bt_dgb BtDbg;
1047 struct bt_hci_info BtHciInfo;
1048 struct bt_traffic BtTraffic;
1049 struct bt_security BtSec;
1050 RT_WORK_ITEM HCICmdWorkItem;
1051 struct timer_list BTHCICmdTimer;
1052 RT_WORK_ITEM BTPsDisableWorkItem;
1053 RT_WORK_ITEM BTConnectWorkItem;
1054 struct timer_list BTHCIDiscardAclDataTimer;
1055 struct timer_list BTHCIJoinTimeoutTimer;
1056 struct timer_list BTTestSendPacketTimer;
1057 struct timer_list BTDisconnectPhyLinkTimer;
1058 struct timer_list BTBeaconTimer;
1059 u8 BTBeaconTmrOn;
1060
1061 struct timer_list BTPsDisableTimer;
1062
1063 void * pBtChnlList;
1064};
1065
1066struct packet_irp_acl_data {
1067 u16 Handle:12;
1068 u16 PB_Flag:2;
1069 u16 BC_Flag:2;
1070 u16 Length;
1071 u8 Data[1];
1072};
1073
1074struct packet_irp_hcievent_data {
1075 u8 EventCode;
1076 u8 Length;
1077 u8 Data[20];
1078};
1079
1080struct common_triple {
1081 u8 byte_1st;
1082 u8 byte_2nd;
1083 u8 byte_3rd;
1084};
1085
1086#define COUNTRY_STR_LEN 3 /* country string len = 3 */
1087
1088#define LOCAL_PMK 0
1089
1090enum hci_wifi_connect_status {
1091 HCI_WIFI_NOT_CONNECTED = 0x0,
1092 HCI_WIFI_CONNECTED = 0x1,
1093 HCI_WIFI_CONNECT_IN_PROGRESS = 0x2,
1094};
1095
1096enum hci_ext_bp_operation {
1097 HCI_BT_OP_NONE = 0x0,
1098 HCI_BT_OP_INQUIRY_START = 0x1,
1099 HCI_BT_OP_INQUIRY_FINISH = 0x2,
1100 HCI_BT_OP_PAGING_START = 0x3,
1101 HCI_BT_OP_PAGING_SUCCESS = 0x4,
1102 HCI_BT_OP_PAGING_UNSUCCESS = 0x5,
1103 HCI_BT_OP_PAIRING_START = 0x6,
1104 HCI_BT_OP_PAIRING_FINISH = 0x7,
1105 HCI_BT_OP_BT_DEV_ENABLE = 0x8,
1106 HCI_BT_OP_BT_DEV_DISABLE = 0x9,
1107 HCI_BT_OP_MAX
1108};
1109
1110/* Function proto type */
1111struct btdata_entry {
1112 struct list_head List;
1113 void *pDataBlock;
1114};
1115
1116#define BTHCI_SM_WITH_INFO(_Adapter, _StateToEnter, _StateCmd, _EntryNum) \
1117{ \
1118 RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state change] caused by ""%s"", line =%d\n", __FUNCTION__, __LINE__)); \
1119 BTHCI_StateMachine(_Adapter, _StateToEnter, _StateCmd, _EntryNum);\
1120}
1121
1122void BTHCI_EventParse(struct rtw_adapter * padapter, void *pEvntData, u32 dataLen);
1123#define BT_EventParse BTHCI_EventParse
1124u8 BTHCI_HsConnectionEstablished(struct rtw_adapter * padapter);
1125void BTHCI_UpdateBTProfileRTKToMoto(struct rtw_adapter * padapter);
1126void BTHCI_WifiScanNotify(struct rtw_adapter * padapter, u8 scanType);
1127void BTHCI_StateMachine(struct rtw_adapter * padapter, u8 StateToEnter, enum hci_state_with_cmd StateCmd, u8 EntryNum);
1128void BTHCI_DisconnectPeer(struct rtw_adapter * padapter, u8 EntryNum);
1129void BTHCI_EventNumOfCompletedDataBlocks(struct rtw_adapter * padapter);
1130void BTHCI_EventAMPStatusChange(struct rtw_adapter * padapter, u8 AMP_Status);
1131void BTHCI_DisconnectAll(struct rtw_adapter * padapter);
1132enum hci_status BTHCI_HandleHCICMD(struct rtw_adapter * padapter, struct packet_irp_hcicmd_data *pHciCmd);
1133
1134/* ===== End of sync from SD7 driver COMMON/bt_hci.h ===== */
1135#endif /* __BT_HCI_C__ */
1136
1137#ifdef __HALBTC87231ANT_C__ /* HAL/BTCoexist/HalBtc87231Ant.h */
1138/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.h ===== */
1139#define GET_BT_INFO(padapter) (&GET_HAL_DATA(padapter)->BtInfo)
1140
1141#define BTC_FOR_SCAN_START 1
1142#define BTC_FOR_SCAN_FINISH 0
1143
1144#define BT_TXRX_CNT_THRES_1 1200
1145#define BT_TXRX_CNT_THRES_2 1400
1146#define BT_TXRX_CNT_THRES_3 3000
1147#define BT_TXRX_CNT_LEVEL_0 0 /* < 1200 */
1148#define BT_TXRX_CNT_LEVEL_1 1 /* >= 1200 && < 1400 */
1149#define BT_TXRX_CNT_LEVEL_2 2 /* >= 1400 */
1150#define BT_TXRX_CNT_LEVEL_3 3 /* >= 3000 */
1151
1152enum bt_state_1ant {
1153 BT_INFO_STATE_DISABLED = 0,
1154 BT_INFO_STATE_NO_CONNECTION = 1,
1155 BT_INFO_STATE_CONNECT_IDLE = 2,
1156 BT_INFO_STATE_INQ_OR_PAG = 3,
1157 BT_INFO_STATE_ACL_ONLY_BUSY = 4,
1158 BT_INFO_STATE_SCO_ONLY_BUSY = 5,
1159 BT_INFO_STATE_ACL_SCO_BUSY = 6,
1160 BT_INFO_STATE_ACL_INQ_OR_PAG = 7,
1161 BT_INFO_STATE_MAX = 8
1162};
1163
1164struct btdm_8723a_1ant {
1165 u8 prePsTdma;
1166 u8 curPsTdma;
1167 u8 psTdmaDuAdjType;
1168 u8 bPrePsTdmaOn;
1169 u8 bCurPsTdmaOn;
1170 u8 preWifiPara;
1171 u8 curWifiPara;
1172 u8 preCoexWifiCon;
1173 u8 curCoexWifiCon;
1174 u8 wifiRssiThresh;
1175
1176 u32 psTdmaMonitorCnt;
1177 u32 psTdmaGlobalCnt;
1178
1179 /* DurationAdjust For SCO */
1180 u32 psTdmaMonitorCntForSCO;
1181 u8 psTdmaDuAdjTypeForSCO;
1182 u8 RSSI_WiFi_Last;
1183 u8 RSSI_BT_Last;
1184
1185 u8 bWiFiHalt;
1186 u8 bRAChanged;
1187};
1188
1189void BTDM_1AntSignalCompensation(struct rtw_adapter * padapter, u8 *rssi_wifi, u8 *rssi_bt);
1190void BTDM_1AntForDhcp(struct rtw_adapter * padapter);
1191void BTDM_1AntBtCoexist8723A(struct rtw_adapter * padapter);
1192
1193/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.h ===== */
1194#endif /* __HALBTC87231ANT_C__ */
1195
1196#ifdef __HALBTC87232ANT_C__ /* HAL/BTCoexist/HalBtc87232Ant.h */
1197/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.h ===== */
1198enum bt_2ant_bt_status {
1199 BT_2ANT_BT_STATUS_IDLE = 0x0,
1200 BT_2ANT_BT_STATUS_CONNECTED_IDLE = 0x1,
1201 BT_2ANT_BT_STATUS_NON_IDLE = 0x2,
1202 BT_2ANT_BT_STATUS_MAX
1203};
1204
1205enum bt_2ant_coex_algo {
1206 BT_2ANT_COEX_ALGO_UNDEFINED = 0x0,
1207 BT_2ANT_COEX_ALGO_SCO = 0x1,
1208 BT_2ANT_COEX_ALGO_HID = 0x2,
1209 BT_2ANT_COEX_ALGO_A2DP = 0x3,
1210 BT_2ANT_COEX_ALGO_PANEDR = 0x4,
1211 BT_2ANT_COEX_ALGO_PANHS = 0x5,
1212 BT_2ANT_COEX_ALGO_PANEDR_A2DP = 0x6,
1213 BT_2ANT_COEX_ALGO_PANEDR_HID = 0x7,
1214 BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x8,
1215 BT_2ANT_COEX_ALGO_HID_A2DP = 0x9,
1216 BT_2ANT_COEX_ALGO_HID_A2DP_PANHS = 0xA,
1217 BT_2ANT_COEX_ALGO_MAX = 0xB,
1218};
1219
1220struct btdm_8723a_2ant {
1221 u8 bPreDecBtPwr;
1222 u8 bCurDecBtPwr;
1223
1224 u8 preWlanActHi;
1225 u8 curWlanActHi;
1226 u8 preWlanActLo;
1227 u8 curWlanActLo;
1228
1229 u8 preFwDacSwingLvl;
1230 u8 curFwDacSwingLvl;
1231
1232 u8 bPreRfRxLpfShrink;
1233 u8 bCurRfRxLpfShrink;
1234
1235 u8 bPreLowPenaltyRa;
1236 u8 bCurLowPenaltyRa;
1237
1238 u8 preBtRetryIndex;
1239 u8 curBtRetryIndex;
1240
1241 u8 bPreDacSwingOn;
1242 u32 preDacSwingLvl;
1243 u8 bCurDacSwingOn;
1244 u32 curDacSwingLvl;
1245
1246 u8 bPreAdcBackOff;
1247 u8 bCurAdcBackOff;
1248
1249 u8 bPreAgcTableEn;
1250 u8 bCurAgcTableEn;
1251
1252 u32 preVal0x6c0;
1253 u32 curVal0x6c0;
1254 u32 preVal0x6c8;
1255 u32 curVal0x6c8;
1256 u8 preVal0x6cc;
1257 u8 curVal0x6cc;
1258
1259 u8 bCurIgnoreWlanAct;
1260 u8 bPreIgnoreWlanAct;
1261
1262 u8 prePsTdma;
1263 u8 curPsTdma;
1264 u8 psTdmaDuAdjType;
1265 u8 bPrePsTdmaOn;
1266 u8 bCurPsTdmaOn;
1267
1268 u8 preAlgorithm;
1269 u8 curAlgorithm;
1270 u8 bResetTdmaAdjust;
1271
1272 u8 btStatus;
1273};
1274
1275void BTDM_2AntBtCoexist8723A(struct rtw_adapter * padapter);
1276/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.h ===== */
1277#endif /* __HALBTC87232ANT_C__ */
1278
1279#ifdef __HALBTC8723_C__ /* HAL/BTCoexist/HalBtc8723.h */
1280/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc8723.h ===== */
1281
1282#define BT_Q_PKT_OFF 0
1283#define BT_Q_PKT_ON 1
1284
1285#define BT_TX_PWR_OFF 0
1286#define BT_TX_PWR_ON 1
1287
1288/* TDMA mode definition */
1289#define TDMA_2ANT 0
1290#define TDMA_1ANT 1
1291#define TDMA_NAV_OFF 0
1292#define TDMA_NAV_ON 1
1293#define TDMA_DAC_SWING_OFF 0
1294#define TDMA_DAC_SWING_ON 1
1295
1296#define BT_RSSI_LEVEL_H 0
1297#define BT_RSSI_LEVEL_M 1
1298#define BT_RSSI_LEVEL_L 2
1299
1300/* PTA mode related definition */
1301#define BT_PTA_MODE_OFF 0
1302#define BT_PTA_MODE_ON 1
1303
1304/* Penalty Tx Rate Adaptive */
1305#define BT_TX_RATE_ADAPTIVE_NORMAL 0
1306#define BT_TX_RATE_ADAPTIVE_LOW_PENALTY 1
1307
1308/* RF Corner */
1309#define BT_RF_RX_LPF_CORNER_RESUME 0
1310#define BT_RF_RX_LPF_CORNER_SHRINK 1
1311
1312#define BT_INFO_ACL BIT(0)
1313#define BT_INFO_SCO BIT(1)
1314#define BT_INFO_INQ_PAG BIT(2)
1315#define BT_INFO_ACL_BUSY BIT(3)
1316#define BT_INFO_SCO_BUSY BIT(4)
1317#define BT_INFO_HID BIT(5)
1318#define BT_INFO_A2DP BIT(6)
1319#define BT_INFO_FTP BIT(7)
1320
1321
1322
1323struct bt_coexist_8723a {
1324 u32 highPriorityTx;
1325 u32 highPriorityRx;
1326 u32 lowPriorityTx;
1327 u32 lowPriorityRx;
1328 u8 btRssi;
1329 u8 TotalAntNum;
1330 u8 bC2hBtInfoSupport;
1331 u8 c2hBtInfo;
1332 u8 c2hBtInfoOriginal;
1333 u8 prec2hBtInfo; /* for 1Ant */
1334 u8 bC2hBtInquiryPage;
1335 unsigned long btInqPageStartTime; /* for 2Ant */
1336 u8 c2hBtProfile; /* for 1Ant */
1337 u8 btRetryCnt;
1338 u8 btInfoExt;
1339 u8 bC2hBtInfoReqSent;
1340 u8 bForceFwBtInfo;
1341 u8 bForceA2dpSink;
1342 struct btdm_8723a_2ant btdm2Ant;
1343 struct btdm_8723a_1ant btdm1Ant;
1344};
1345
1346void BTDM_SetFwChnlInfo(struct rtw_adapter * padapter, enum rt_media_status mstatus);
1347u8 BTDM_IsWifiConnectionExist(struct rtw_adapter * padapter);
1348void BTDM_SetFw3a(struct rtw_adapter * padapter, u8 byte1, u8 byte2, u8 byte3, u8 byte4, u8 byte5);
1349void BTDM_QueryBtInformation(struct rtw_adapter * padapter);
1350void BTDM_SetSwRfRxLpfCorner(struct rtw_adapter * padapter, u8 type);
1351void BTDM_SetSwPenaltyTxRateAdaptive(struct rtw_adapter * padapter, u8 raType);
1352void BTDM_SetFwDecBtPwr(struct rtw_adapter * padapter, u8 bDecBtPwr);
1353u8 BTDM_BtProfileSupport(struct rtw_adapter * padapter);
1354void BTDM_LpsLeave(struct rtw_adapter * padapter);
1355u8 BTDM_1Ant8723A(struct rtw_adapter * padapter);
1356#define BT_1Ant BTDM_1Ant8723A
1357
1358/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc8723.h ===== */
1359#endif /* __HALBTC8723_C__ */
1360
1361#ifdef __HALBTCCSR1ANT_C__ /* HAL/BTCoexist/HalBtcCsr1Ant.h */
1362/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.h ===== */
1363
1364enum BT_A2DP_INDEX{
1365 BT_A2DP_INDEX0 = 0, /* 32, 12; the most critical for BT */
1366 BT_A2DP_INDEX1, /* 12, 24 */
1367 BT_A2DP_INDEX2, /* 0, 0 */
1368 BT_A2DP_INDEX_MAX
1369};
1370
1371#define BT_A2DP_STATE_NOT_ENTERED 0
1372#define BT_A2DP_STATE_DETECTING 1
1373#define BT_A2DP_STATE_DETECTED 2
1374
1375#define BTDM_ANT_BT_IDLE 0
1376#define BTDM_ANT_WIFI 1
1377#define BTDM_ANT_BT 2
1378
1379
1380void BTDM_SingleAnt(struct rtw_adapter * padapter, u8 bSingleAntOn, u8 bInterruptOn, u8 bMultiNAVOn);
1381void BTDM_CheckBTIdleChange1Ant(struct rtw_adapter * padapter);
1382
1383/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.h ===== */
1384#endif /* __HALBTCCSR1ANT_C__ */
1385
1386#ifdef __HALBTCCSR2ANT_C__ /* HAL/BTCoexist/HalBtcCsr2Ant.h */
1387/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.h ===== */
1388
1389/* */
1390/* For old core stack before v251 */
1391/* */
1392#define BT_RSSI_STATE_NORMAL_POWER BIT0
1393#define BT_RSSI_STATE_AMDPU_OFF BIT1
1394#define BT_RSSI_STATE_SPECIAL_LOW BIT2
1395#define BT_RSSI_STATE_BG_EDCA_LOW BIT3
1396#define BT_RSSI_STATE_TXPOWER_LOW BIT4
1397
1398#define BT_DACSWING_OFF 0
1399#define BT_DACSWING_M4 1
1400#define BT_DACSWING_M7 2
1401#define BT_DACSWING_M10 3
1402
1403void BTDM_DiminishWiFi(struct rtw_adapter * Adapter, u8 bDACOn, u8 bInterruptOn, u8 DACSwingLevel, u8 bNAVOn);
1404
1405/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.h ===== */
1406#endif /* __HALBTCCSR2ANT_C__ */
1407
1408#ifdef __HALBTCOEXIST_C__ /* HAL/BTCoexist/HalBtCoexist.h */
1409
1410/* HEADER/TypeDef.h */
1411#define MAX_FW_SUPPORT_MACID_NUM 64
1412
1413/* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtCoexist.h ===== */
1414
1415#define FW_VER_BT_REG 62
1416#define FW_VER_BT_REG1 74
1417#define REG_BT_ACTIVE 0x444
1418#define REG_BT_STATE 0x448
1419#define REG_BT_POLLING1 0x44c
1420#define REG_BT_POLLING 0x700
1421
1422#define REG_BT_ACTIVE_OLD 0x488
1423#define REG_BT_STATE_OLD 0x48c
1424#define REG_BT_POLLING_OLD 0x490
1425
1426/* The reg define is for 8723 */
1427#define REG_HIGH_PRIORITY_TXRX 0x770
1428#define REG_LOW_PRIORITY_TXRX 0x774
1429
1430#define BT_FW_COEX_THRESH_TOL 6
1431#define BT_FW_COEX_THRESH_20 20
1432#define BT_FW_COEX_THRESH_23 23
1433#define BT_FW_COEX_THRESH_25 25
1434#define BT_FW_COEX_THRESH_30 30
1435#define BT_FW_COEX_THRESH_35 35
1436#define BT_FW_COEX_THRESH_40 40
1437#define BT_FW_COEX_THRESH_45 45
1438#define BT_FW_COEX_THRESH_47 47
1439#define BT_FW_COEX_THRESH_50 50
1440#define BT_FW_COEX_THRESH_55 55
1441#define BT_FW_COEX_THRESH_65 65
1442
1443#define BT_COEX_STATE_BT30 BIT(0)
1444#define BT_COEX_STATE_WIFI_HT20 BIT(1)
1445#define BT_COEX_STATE_WIFI_HT40 BIT(2)
1446#define BT_COEX_STATE_WIFI_LEGACY BIT(3)
1447
1448#define BT_COEX_STATE_WIFI_RSSI_LOW BIT(4)
1449#define BT_COEX_STATE_WIFI_RSSI_MEDIUM BIT(5)
1450#define BT_COEX_STATE_WIFI_RSSI_HIGH BIT(6)
1451#define BT_COEX_STATE_DEC_BT_POWER BIT(7)
1452
1453#define BT_COEX_STATE_WIFI_IDLE BIT(8)
1454#define BT_COEX_STATE_WIFI_UPLINK BIT(9)
1455#define BT_COEX_STATE_WIFI_DOWNLINK BIT(10)
1456
1457#define BT_COEX_STATE_BT_INQ_PAGE BIT(11)
1458#define BT_COEX_STATE_BT_IDLE BIT(12)
1459#define BT_COEX_STATE_BT_UPLINK BIT(13)
1460#define BT_COEX_STATE_BT_DOWNLINK BIT(14)
1461/* */
1462/* Todo: Remove these definitions */
1463#define BT_COEX_STATE_BT_PAN_IDLE BIT(15)
1464#define BT_COEX_STATE_BT_PAN_UPLINK BIT(16)
1465#define BT_COEX_STATE_BT_PAN_DOWNLINK BIT(17)
1466#define BT_COEX_STATE_BT_A2DP_IDLE BIT(18)
1467/* */
1468#define BT_COEX_STATE_BT_RSSI_LOW BIT(19)
1469
1470#define BT_COEX_STATE_PROFILE_HID BIT(20)
1471#define BT_COEX_STATE_PROFILE_A2DP BIT(21)
1472#define BT_COEX_STATE_PROFILE_PAN BIT(22)
1473#define BT_COEX_STATE_PROFILE_SCO BIT(23)
1474
1475#define BT_COEX_STATE_WIFI_RSSI_1_LOW BIT(24)
1476#define BT_COEX_STATE_WIFI_RSSI_1_MEDIUM BIT(25)
1477#define BT_COEX_STATE_WIFI_RSSI_1_HIGH BIT(26)
1478
1479#define BT_COEX_STATE_WIFI_RSSI_BEACON_LOW BIT(27)
1480#define BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM BIT(28)
1481#define BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH BIT(29)
1482
1483
1484#define BT_COEX_STATE_BTINFO_COMMON BIT30
1485#define BT_COEX_STATE_BTINFO_B_HID_SCOESCO BIT31
1486#define BT_COEX_STATE_BTINFO_B_FTP_A2DP BIT32
1487
1488#define BT_COEX_STATE_BT_CNT_LEVEL_0 BIT33
1489#define BT_COEX_STATE_BT_CNT_LEVEL_1 BIT34
1490#define BT_COEX_STATE_BT_CNT_LEVEL_2 BIT35
1491#define BT_COEX_STATE_BT_CNT_LEVEL_3 BIT36
1492
1493#define BT_RSSI_STATE_HIGH 0
1494#define BT_RSSI_STATE_MEDIUM 1
1495#define BT_RSSI_STATE_LOW 2
1496#define BT_RSSI_STATE_STAY_HIGH 3
1497#define BT_RSSI_STATE_STAY_MEDIUM 4
1498#define BT_RSSI_STATE_STAY_LOW 5
1499
1500#define BT_AGCTABLE_OFF 0
1501#define BT_AGCTABLE_ON 1
1502
1503#define BT_BB_BACKOFF_OFF 0
1504#define BT_BB_BACKOFF_ON 1
1505
1506#define BT_FW_NAV_OFF 0
1507#define BT_FW_NAV_ON 1
1508
1509#define BT_COEX_MECH_NONE 0
1510#define BT_COEX_MECH_SCO 1
1511#define BT_COEX_MECH_HID 2
1512#define BT_COEX_MECH_A2DP 3
1513#define BT_COEX_MECH_PAN 4
1514#define BT_COEX_MECH_HID_A2DP 5
1515#define BT_COEX_MECH_HID_PAN 6
1516#define BT_COEX_MECH_PAN_A2DP 7
1517#define BT_COEX_MECH_HID_SCO_ESCO 8
1518#define BT_COEX_MECH_FTP_A2DP 9
1519#define BT_COEX_MECH_COMMON 10
1520#define BT_COEX_MECH_MAX 11
1521/* BT Dbg Ctrl */
1522#define BT_DBG_PROFILE_NONE 0
1523#define BT_DBG_PROFILE_SCO 1
1524#define BT_DBG_PROFILE_HID 2
1525#define BT_DBG_PROFILE_A2DP 3
1526#define BT_DBG_PROFILE_PAN 4
1527#define BT_DBG_PROFILE_HID_A2DP 5
1528#define BT_DBG_PROFILE_HID_PAN 6
1529#define BT_DBG_PROFILE_PAN_A2DP 7
1530#define BT_DBG_PROFILE_MAX 9
1531
1532struct bt_coexist_str {
1533 u8 BluetoothCoexist;
1534 u8 BT_Ant_Num;
1535 u8 BT_CoexistType;
1536 u8 BT_Ant_isolation; /* 0:good, 1:bad */
1537 u8 bt_radiosharedtype;
1538 u32 Ratio_Tx;
1539 u32 Ratio_PRI;
1540 u8 bInitlized;
1541 u32 BtRfRegOrigin1E;
1542 u32 BtRfRegOrigin1F;
1543 u8 bBTBusyTraffic;
1544 u8 bBTTrafficModeSet;
1545 u8 bBTNonTrafficModeSet;
1546 struct bt_traffic_statistics BT21TrafficStatistics;
1547 u64 CurrentState;
1548 u64 PreviousState;
1549 u8 preRssiState;
1550 u8 preRssiState1;
1551 u8 preRssiStateBeacon;
1552 u8 bFWCoexistAllOff;
1553 u8 bSWCoexistAllOff;
1554 u8 bHWCoexistAllOff;
1555 u8 bBalanceOn;
1556 u8 bSingleAntOn;
1557 u8 bInterruptOn;
1558 u8 bMultiNAVOn;
1559 u8 PreWLANActH;
1560 u8 PreWLANActL;
1561 u8 WLANActH;
1562 u8 WLANActL;
1563 u8 A2DPState;
1564 u8 AntennaState;
1565 u32 lastBtEdca;
1566 u16 last_aggr_num;
1567 u8 bEDCAInitialized;
1568 u8 exec_cnt;
1569 u8 b8723aAgcTableOn;
1570 u8 b92DAgcTableOn;
1571 struct bt_coexist_8723a halCoex8723;
1572 u8 btActiveZeroCnt;
1573 u8 bCurBtDisabled;
1574 u8 bPreBtDisabled;
1575 u8 bNeedToRoamForBtDisableEnable;
1576 u8 fw3aVal[5];
1577};
1578
1579void BTDM_CheckAntSelMode(struct rtw_adapter * padapter);
1580void BTDM_FwC2hBtRssi(struct rtw_adapter * padapter, u8 *tmpBuf);
1581#define BT_FwC2hBtRssi BTDM_FwC2hBtRssi
1582void BTDM_FwC2hBtInfo(struct rtw_adapter * padapter, u8 *tmpBuf, u8 length);
1583#define BT_FwC2hBtInfo BTDM_FwC2hBtInfo
1584void BTDM_DisplayBtCoexInfo(struct rtw_adapter * padapter);
1585#define BT_DisplayBtCoexInfo BTDM_DisplayBtCoexInfo
1586void BTDM_RejectAPAggregatedPacket(struct rtw_adapter * padapter, u8 bReject);
1587u8 BTDM_IsHT40(struct rtw_adapter * padapter);
1588u8 BTDM_Legacy(struct rtw_adapter * padapter);
1589void BTDM_CheckWiFiState(struct rtw_adapter * padapter);
1590s32 BTDM_GetRxSS(struct rtw_adapter * padapter);
1591u8 BTDM_CheckCoexBcnRssiState(struct rtw_adapter * padapter, u8 levelNum, u8 RssiThresh, u8 RssiThresh1);
1592u8 BTDM_CheckCoexRSSIState1(struct rtw_adapter * padapter, u8 levelNum, u8 RssiThresh, u8 RssiThresh1);
1593u8 BTDM_CheckCoexRSSIState(struct rtw_adapter * padapter, u8 levelNum, u8 RssiThresh, u8 RssiThresh1);
1594u8 BTDM_DisableEDCATurbo(struct rtw_adapter * padapter);
1595#define BT_DisableEDCATurbo BTDM_DisableEDCATurbo
1596void BTDM_Balance(struct rtw_adapter * padapter, u8 bBalanceOn, u8 ms0, u8 ms1);
1597void BTDM_AGCTable(struct rtw_adapter * padapter, u8 type);
1598void BTDM_BBBackOffLevel(struct rtw_adapter * padapter, u8 type);
1599void BTDM_FWCoexAllOff(struct rtw_adapter * padapter);
1600void BTDM_SWCoexAllOff(struct rtw_adapter * padapter);
1601void BTDM_HWCoexAllOff(struct rtw_adapter * padapter);
1602void BTDM_CoexAllOff(struct rtw_adapter * padapter);
1603void BTDM_TurnOffBtCoexistBeforeEnterIPS(struct rtw_adapter * padapter);
1604void BTDM_SignalCompensation(struct rtw_adapter * padapter, u8 *rssi_wifi, u8 *rssi_bt);
1605void BTDM_Coexist(struct rtw_adapter * padapter);
1606#define BT_CoexistMechanism BTDM_Coexist
1607void BTDM_UpdateCoexState(struct rtw_adapter * padapter);
1608u8 BTDM_IsSameCoexistState(struct rtw_adapter * padapter);
1609void BTDM_PWDBMonitor(struct rtw_adapter * padapter);
1610u8 BTDM_IsBTBusy(struct rtw_adapter * padapter);
1611#define BT_IsBtBusy BTDM_IsBTBusy
1612u8 BTDM_IsWifiBusy(struct rtw_adapter * padapter);
1613u8 BTDM_IsCoexistStateChanged(struct rtw_adapter * padapter);
1614u8 BTDM_IsWifiUplink(struct rtw_adapter * padapter);
1615u8 BTDM_IsWifiDownlink(struct rtw_adapter * padapter);
1616u8 BTDM_IsBTHSMode(struct rtw_adapter * padapter);
1617u8 BTDM_IsBTUplink(struct rtw_adapter * padapter);
1618u8 BTDM_IsBTDownlink(struct rtw_adapter * padapter);
1619void BTDM_AdjustForBtOperation(struct rtw_adapter * padapter);
1620void BTDM_ForHalt(struct rtw_adapter * padapter);
1621void BTDM_WifiScanNotify(struct rtw_adapter * padapter, u8 scanType);
1622void BTDM_WifiAssociateNotify(struct rtw_adapter * padapter, u8 action);
1623void BTDM_MediaStatusNotify(struct rtw_adapter * padapter, enum rt_media_status mstatus);
1624void BTDM_ForDhcp(struct rtw_adapter * padapter);
1625void BTDM_ResetActionProfileState(struct rtw_adapter * padapter);
1626void BTDM_SetBtCoexCurrAntNum(struct rtw_adapter * padapter, u8 antNum);
1627#define BT_SetBtCoexCurrAntNum BTDM_SetBtCoexCurrAntNum
1628u8 BTDM_IsActionSCO(struct rtw_adapter * padapter);
1629u8 BTDM_IsActionHID(struct rtw_adapter * padapter);
1630u8 BTDM_IsActionA2DP(struct rtw_adapter * padapter);
1631u8 BTDM_IsActionPAN(struct rtw_adapter * padapter);
1632u8 BTDM_IsActionHIDA2DP(struct rtw_adapter * padapter);
1633u8 BTDM_IsActionHIDPAN(struct rtw_adapter * padapter);
1634u8 BTDM_IsActionPANA2DP(struct rtw_adapter * padapter);
1635u8 BTDM_IsBtDisabled(struct rtw_adapter * padapter);
1636#define BT_IsBtDisabled BTDM_IsBtDisabled
1637u32 BTDM_BtTxRxCounterH(struct rtw_adapter * padapter);
1638u32 BTDM_BtTxRxCounterL(struct rtw_adapter * padapter);
1639
1640/* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtCoexist.h ===== */
1641#endif /* __HALBTCOEXIST_C__ */
1642
1643#ifdef __HALBT_C__ /* HAL/HalBT.h */
1644/* ===== Below this line is sync from SD7 driver HAL/HalBT.h ===== */
1645
1646#define RTS_CTS_NO_LEN_LIMIT 0
1647
1648u8 HALBT_GetPGAntNum(struct rtw_adapter * padapter);
1649#define BT_GetPGAntNum HALBT_GetPGAntNum
1650void HALBT_SetKey(struct rtw_adapter * padapter, u8 EntryNum);
1651void HALBT_RemoveKey(struct rtw_adapter * padapter, u8 EntryNum);
1652void HALBT_InitBTVars8723A(struct rtw_adapter * padapter);
1653#define HALBT_InitHalVars HALBT_InitBTVars8723A
1654#define BT_InitHalVars HALBT_InitHalVars
1655u8 HALBT_IsBTExist(struct rtw_adapter * padapter);
1656#define BT_IsBtExist HALBT_IsBTExist
1657u8 HALBT_BTChipType(struct rtw_adapter * padapter);
1658void HALBT_InitHwConfig(struct rtw_adapter * padapter);
1659#define BT_InitHwConfig HALBT_InitHwConfig
1660void HALBT_SetRtsCtsNoLenLimit(struct rtw_adapter * padapter);
1661
1662/* ===== End of sync from SD7 driver HAL/HalBT.c ===== */
1663#endif /* __HALBT_C__ */
1664
1665#define _bt_dbg_off_ 0
1666#define _bt_dbg_on_ 1
1667
1668extern u32 BTCoexDbgLevel;
1669
1670
1671
1672#endif /* __RTL8723A_BT_COEXIST_H__ */
diff --git a/drivers/staging/rtl8723au/include/rtl8723a_cmd.h b/drivers/staging/rtl8723au/include/rtl8723a_cmd.h
new file mode 100644
index 000000000000..8fccbfc3a45c
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtl8723a_cmd.h
@@ -0,0 +1,160 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#ifndef __RTL8723A_CMD_H__
16#define __RTL8723A_CMD_H__
17
18
19#define H2C_BT_FW_PATCH_LEN 3
20#define H2C_BT_PWR_FORCE_LEN 3
21
22enum cmd_msg_element_id
23{
24 NONE_CMDMSG_EID,
25 AP_OFFLOAD_EID = 0,
26 SET_PWRMODE_EID = 1,
27 JOINBSS_RPT_EID = 2,
28 RSVD_PAGE_EID = 3,
29 RSSI_4_EID = 4,
30 RSSI_SETTING_EID = 5,
31 MACID_CONFIG_EID = 6,
32 MACID_PS_MODE_EID = 7,
33 P2P_PS_OFFLOAD_EID = 8,
34 SELECTIVE_SUSPEND_ROF_CMD = 9,
35 BT_QUEUE_PKT_EID = 17,
36 BT_ANT_TDMA_EID = 20,
37 BT_2ANT_HID_EID = 21,
38 P2P_PS_CTW_CMD_EID = 32,
39 FORCE_BT_TX_PWR_EID = 33,
40 SET_TDMA_WLAN_ACT_TIME_EID = 34,
41 SET_BT_TX_RETRY_INDEX_EID = 35,
42 HID_PROFILE_ENABLE_EID = 36,
43 BT_IGNORE_WLAN_ACT_EID = 37,
44 BT_PTA_MANAGER_UPDATE_ENABLE_EID = 38,
45 DAC_SWING_VALUE_EID = 41,
46 TRADITIONAL_TDMA_EN_EID = 51,
47 H2C_BT_FW_PATCH = 54,
48 B_TYPE_TDMA_EID = 58,
49 SCAN_EN_EID = 59,
50 LOWPWR_LPS_EID = 71,
51 H2C_RESET_TSF = 75,
52 MAX_CMDMSG_EID
53};
54
55struct cmd_msg_parm {
56 u8 eid; /* element id */
57 u8 sz; /* sz */
58 u8 buf[6];
59};
60
61struct setpwrmode_parm {
62 u8 Mode;
63 u8 SmartPS;
64 u8 AwakeInterval; /* unit: beacon interval */
65 u8 bAllQueueUAPSD;
66
67#define SETPM_LOWRXBCN BIT(0)
68#define SETPM_AUTOANTSWITCH BIT(1)
69#define SETPM_PSALLOWBTHIGHPRI BIT(2)
70 u8 BcnAntMode;
71} __packed;
72
73struct H2C_SS_RFOFF_PARAM{
74 u8 ROFOn; /* 1: on, 0:off */
75 u16 gpio_period; /* unit: 1024 us */
76}__attribute__ ((packed));
77
78
79struct joinbssrpt_parm {
80 u8 OpMode; /* enum rt_media_status */
81};
82
83struct rsvdpage_loc {
84 u8 LocProbeRsp;
85 u8 LocPsPoll;
86 u8 LocNullData;
87 u8 LocQosNull;
88 u8 LocBTQosNull;
89};
90
91struct P2P_PS_Offload_t {
92 u8 Offload_En:1;
93 u8 role:1; /* 1: Owner, 0: Client */
94 u8 CTWindow_En:1;
95 u8 NoA0_En:1;
96 u8 NoA1_En:1;
97 u8 AllStaSleep:1; /* Only valid in Owner */
98 u8 discovery:1;
99 u8 rsvd:1;
100};
101
102struct P2P_PS_CTWPeriod_t {
103 u8 CTWPeriod; /* TU */
104};
105
106#define B_TDMA_EN BIT(0)
107#define B_TDMA_FIXANTINBT BIT(1)
108#define B_TDMA_TXPSPOLL BIT(2)
109#define B_TDMA_VAL870 BIT(3)
110#define B_TDMA_AUTOWAKEUP BIT(4)
111#define B_TDMA_NOPS BIT(5)
112#define B_TDMA_WLANHIGHPRI BIT(6)
113
114struct b_type_tdma_parm {
115 u8 option;
116
117 u8 TBTTOnPeriod;
118 u8 MedPeriod;
119 u8 rsvd30;
120} __packed;
121
122struct scan_en_parm {
123 u8 En;
124} __packed;
125
126/* BT_PWR */
127#define SET_H2CCMD_BT_PWR_IDX(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE_8BIT(__pH2CCmd, 0, 8, __Value)
128
129/* BT_FW_PATCH */
130#define SET_H2CCMD_BT_FW_PATCH_ENABLE(__pH2CCmd, __Value) SET_BITS_TO_LE_4BYTE(__pH2CCmd, 0, 8, __Value) /* SET_BITS_TO_LE_1BYTE(__pH2CCmd, 0, 8, __Value) */
131#define SET_H2CCMD_BT_FW_PATCH_SIZE(__pH2CCmd, __Value) SET_BITS_TO_LE_4BYTE(__pH2CCmd, 8, 16, __Value) /* SET_BITS_TO_LE_2BYTE((__pH2CCmd)+1, 0, 16, __Value) */
132
133struct lowpwr_lps_parm{
134 u8 bcn_count:4;
135 u8 tb_bcn_threshold:3;
136 u8 enable:1;
137 u8 bcn_interval;
138 u8 drop_threshold;
139 u8 max_early_period;
140 u8 max_bcn_timeout_period;
141} __packed;
142
143
144/* host message to firmware cmd */
145void rtl8723a_set_FwPwrMode_cmd(struct rtw_adapter * padapter, u8 Mode);
146void rtl8723a_set_FwJoinBssReport_cmd(struct rtw_adapter * padapter, u8 mstatus);
147#ifdef CONFIG_8723AU_BT_COEXIST
148void rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(struct rtw_adapter * padapter);
149#endif
150u8 rtl8723a_set_rssi_cmd(struct rtw_adapter * padapter, u8 *param);
151u8 rtl8723a_set_raid_cmd(struct rtw_adapter * padapter, u32 mask, u8 arg);
152void rtl8723a_add_rateatid(struct rtw_adapter * padapter, u32 bitmap, u8 arg, u8 rssi_level);
153
154#ifdef CONFIG_8723AU_P2P
155void rtl8723a_set_p2p_ps_offload_cmd(struct rtw_adapter * padapter, u8 p2p_ps_state);
156#endif /* CONFIG_8723AU_P2P */
157
158void CheckFwRsvdPageContent23a(struct rtw_adapter *padapter);
159
160#endif
diff --git a/drivers/staging/rtl8723au/include/rtl8723a_dm.h b/drivers/staging/rtl8723au/include/rtl8723a_dm.h
new file mode 100644
index 000000000000..47e887f5bb26
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtl8723a_dm.h
@@ -0,0 +1,144 @@
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 ******************************************************************************/
15#ifndef __RTL8723A_DM_H__
16#define __RTL8723A_DM_H__
17/* */
18/* Description: */
19/* */
20/* This file is for 8723A dynamic mechanism only */
21/* */
22/* */
23/* */
24#define DYNAMIC_FUNC_BT BIT(0)
25
26enum{
27 UP_LINK,
28 DOWN_LINK,
29};
30/* */
31/* structure and define */
32/* */
33
34/* duplicate code,will move to ODM ######### */
35#define IQK_MAC_REG_NUM 4
36#define IQK_ADDA_REG_NUM 16
37#define IQK_BB_REG_NUM 9
38#define HP_THERMAL_NUM 8
39/* duplicate code,will move to ODM ######### */
40struct dm_priv
41{
42 u8 DM_Type;
43 u8 DMFlag;
44 u8 InitDMFlag;
45 u32 InitODMFlag;
46
47 /* Upper and Lower Signal threshold for Rate Adaptive*/
48 int UndecoratedSmoothedPWDB;
49 int UndecoratedSmoothedCCK;
50 int EntryMinUndecoratedSmoothedPWDB;
51 int EntryMaxUndecoratedSmoothedPWDB;
52 int MinUndecoratedPWDBForDM;
53 int LastMinUndecoratedPWDBForDM;
54
55 s32 UndecoratedSmoothedBeacon;
56 #ifdef CONFIG_8723AU_BT_COEXIST
57 s32 BT_EntryMinUndecoratedSmoothedPWDB;
58 s32 BT_EntryMaxUndecoratedSmoothedPWDB;
59 #endif
60
61 /* for High Power */
62 u8 bDynamicTxPowerEnable;
63 u8 LastDTPLvl;
64 u8 DynamicTxHighPowerLvl;/* Add by Jacken Tx Power Control for Near/Far Range 2008/03/06 */
65
66 /* for tx power tracking */
67 u8 bTXPowerTracking;
68 u8 TXPowercount;
69 u8 bTXPowerTrackingInit;
70 u8 TxPowerTrackControl; /* for mp mode, turn off txpwrtracking as default */
71 u8 TM_Trigger;
72
73 u8 ThermalMeter[2]; /* ThermalMeter, index 0 for RFIC0, and 1 for RFIC1 */
74 u8 ThermalValue;
75 u8 ThermalValue_LCK;
76 u8 ThermalValue_IQK;
77 u8 ThermalValue_DPK;
78
79 u8 bRfPiEnable;
80
81 /* for APK */
82 u32 APKoutput[2][2]; /* path A/B; output1_1a/output1_2a */
83 u8 bAPKdone;
84 u8 bAPKThermalMeterIgnore;
85 u8 bDPdone;
86 u8 bDPPathAOK;
87 u8 bDPPathBOK;
88
89 /* for IQK */
90 u32 RegC04;
91 u32 Reg874;
92 u32 RegC08;
93 u32 RegB68;
94 u32 RegB6C;
95 u32 Reg870;
96 u32 Reg860;
97 u32 Reg864;
98 u32 ADDA_backup[IQK_ADDA_REG_NUM];
99 u32 IQK_MAC_backup[IQK_MAC_REG_NUM];
100 u32 IQK_BB_backup_recover[9];
101 u32 IQK_BB_backup[IQK_BB_REG_NUM];
102 u8 PowerIndex_backup[6];
103
104 u8 bCCKinCH14;
105
106 u8 CCK_index;
107 u8 OFDM_index[2];
108
109 u8 bDoneTxpower;
110 u8 CCK_index_HP;
111 u8 OFDM_index_HP[2];
112 u8 ThermalValue_HP[HP_THERMAL_NUM];
113 u8 ThermalValue_HP_index;
114
115 /* for TxPwrTracking */
116 s32 RegE94;
117 s32 RegE9C;
118 s32 RegEB4;
119 s32 RegEBC;
120
121 u32 TXPowerTrackingCallbackCnt; /* cosa add for debug */
122
123 u32 prv_traffic_idx; /* edca turbo */
124
125 s32 OFDM_Pkt_Cnt;
126 u8 RSSI_Select;
127/* u8 DIG_Dynamic_MIN ; */
128/* duplicate code,will move to ODM ######### */
129 /* Add for Reading Initial Data Rate SEL Register 0x484 during watchdog. Using for fill tx desc. 2011.3.21 by Thomas */
130 u8 INIDATA_RATE[32];
131};
132
133
134/* */
135/* function prototype */
136/* */
137
138void rtl8723a_init_dm_priv(struct rtw_adapter *padapter);
139void rtl8723a_deinit_dm_priv(struct rtw_adapter *padapter);
140
141void rtl8723a_InitHalDm(struct rtw_adapter *padapter);
142void rtl8723a_HalDmWatchDog(struct rtw_adapter *padapter);
143
144#endif
diff --git a/drivers/staging/rtl8723au/include/rtl8723a_hal.h b/drivers/staging/rtl8723au/include/rtl8723a_hal.h
new file mode 100644
index 000000000000..c20248bab717
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtl8723a_hal.h
@@ -0,0 +1,575 @@
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 ******************************************************************************/
15#ifndef __RTL8723A_HAL_H__
16#define __RTL8723A_HAL_H__
17
18#include "rtl8723a_spec.h"
19#include "rtl8723a_pg.h"
20#include "Hal8723APhyReg.h"
21#include "Hal8723APhyCfg.h"
22#include "rtl8723a_rf.h"
23#ifdef CONFIG_8723AU_BT_COEXIST
24#include "rtl8723a_bt-coexist.h"
25#endif
26#include "rtl8723a_dm.h"
27#include "rtl8723a_recv.h"
28#include "rtl8723a_xmit.h"
29#include "rtl8723a_cmd.h"
30#include "rtl8723a_sreset.h"
31#include "rtw_efuse.h"
32
33#include "odm_precomp.h"
34
35
36/* 2TODO: We should define 8192S firmware related macro settings here!! */
37#define RTL819X_DEFAULT_RF_TYPE RF_1T2R
38#define RTL819X_TOTAL_RF_PATH 2
39
40/* TODO: The following need to check!! */
41#define RTL8723_FW_UMC_IMG "rtl8192CU\\rtl8723fw.bin"
42#define RTL8723_FW_UMC_B_IMG "rtl8192CU\\rtl8723fw_B.bin"
43#define RTL8723_PHY_REG "rtl8723S\\PHY_REG_1T.txt"
44#define RTL8723_PHY_RADIO_A "rtl8723S\\radio_a_1T.txt"
45#define RTL8723_PHY_RADIO_B "rtl8723S\\radio_b_1T.txt"
46#define RTL8723_AGC_TAB "rtl8723S\\AGC_TAB_1T.txt"
47#define RTL8723_PHY_MACREG "rtl8723S\\MAC_REG.txt"
48#define RTL8723_PHY_REG_PG "rtl8723S\\PHY_REG_PG.txt"
49#define RTL8723_PHY_REG_MP "rtl8723S\\PHY_REG_MP.txt"
50
51/* */
52/* RTL8723S From header */
53/* */
54
55/* Fw Array */
56#define Rtl8723_FwImageArray Rtl8723UFwImgArray
57#define Rtl8723_FwUMCBCutImageArrayWithBT Rtl8723UFwUMCBCutImgArrayWithBT
58#define Rtl8723_FwUMCBCutImageArrayWithoutBT Rtl8723UFwUMCBCutImgArrayWithoutBT
59
60#define Rtl8723_ImgArrayLength Rtl8723UImgArrayLength
61#define Rtl8723_UMCBCutImgArrayWithBTLength Rtl8723UUMCBCutImgArrayWithBTLength
62#define Rtl8723_UMCBCutImgArrayWithoutBTLength Rtl8723UUMCBCutImgArrayWithoutBTLength
63
64#define Rtl8723_PHY_REG_Array_PG Rtl8723UPHY_REG_Array_PG
65#define Rtl8723_PHY_REG_Array_PGLength Rtl8723UPHY_REG_Array_PGLength
66
67#define Rtl8723_FwUMCBCutMPImageArray Rtl8723SFwUMCBCutMPImgAr
68#define Rtl8723_UMCBCutMPImgArrayLength Rtl8723SUMCBCutMPImgArrayLength
69
70#define DRVINFO_SZ 4 /* unit is 8bytes */
71#define PageNum_128(_Len) (u32)(((_Len)>>7) + ((_Len)&0x7F ? 1:0))
72
73#define FW_8723A_SIZE 0x8000
74#define FW_8723A_START_ADDRESS 0x1000
75#define FW_8723A_END_ADDRESS 0x1FFF /* 0x5FFF */
76
77#define MAX_PAGE_SIZE 4096 /* @ page : 4k bytes */
78
79#define IS_FW_HEADER_EXIST(_pFwHdr) ((le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x92C0 ||\
80 (le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x88C0 ||\
81 (le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x2300)
82
83/* */
84/* This structure must be cared byte-ordering */
85/* */
86/* Added by tynli. 2009.12.04. */
87struct rt_8723a_firmware_hdr {
88 /* 8-byte alinment required */
89
90 /* LONG WORD 0 ---- */
91 u16 Signature; /* 92C0: test chip; 92C, 88C0: test chip; 88C1: MP A-cut; 92C1: MP A-cut */
92 u8 Category; /* AP/NIC and USB/PCI */
93 u8 Function; /* Reserved for different FW function indcation, for further use when driver needs to download different FW in different conditions */
94 u16 Version; /* FW Version */
95 u8 Subversion; /* FW Subversion, default 0x00 */
96 u16 Rsvd1;
97
98
99 /* LONG WORD 1 ---- */
100 u8 Month; /* Release time Month field */
101 u8 Date; /* Release time Date field */
102 u8 Hour; /* Release time Hour field */
103 u8 Minute; /* Release time Minute field */
104 u16 RamCodeSize; /* The size of RAM code */
105 u16 Rsvd2;
106
107 /* LONG WORD 2 ---- */
108 u32 SvnIdx; /* The SVN entry index */
109 u32 Rsvd3;
110
111 /* LONG WORD 3 ---- */
112 u32 Rsvd4;
113 u32 Rsvd5;
114};
115
116#define DRIVER_EARLY_INT_TIME 0x05
117#define BCN_DMA_ATIME_INT_TIME 0x02
118
119
120/* BK, BE, VI, VO, HCCA, MANAGEMENT, COMMAND, HIGH, BEACON. */
121#define MAX_TX_QUEUE 9
122
123#define TX_SELE_HQ BIT(0) /* High Queue */
124#define TX_SELE_LQ BIT(1) /* Low Queue */
125#define TX_SELE_NQ BIT(2) /* Normal Queue */
126
127/* Note: We will divide number of page equally for each queue other than public queue! */
128#define TX_TOTAL_PAGE_NUMBER 0xF8
129#define TX_PAGE_BOUNDARY (TX_TOTAL_PAGE_NUMBER + 1)
130
131/* For Normal Chip Setting */
132/* (HPQ + LPQ + NPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */
133#define NORMAL_PAGE_NUM_PUBQ 0xE7
134#define NORMAL_PAGE_NUM_HPQ 0x0C
135#define NORMAL_PAGE_NUM_LPQ 0x02
136#define NORMAL_PAGE_NUM_NPQ 0x02
137
138/* For Test Chip Setting */
139/* (HPQ + LPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */
140#define TEST_PAGE_NUM_PUBQ 0x7E
141
142/* For Test Chip Setting */
143#define WMM_TEST_TX_TOTAL_PAGE_NUMBER 0xF5
144#define WMM_TEST_TX_PAGE_BOUNDARY (WMM_TEST_TX_TOTAL_PAGE_NUMBER + 1) /* F6 */
145
146#define WMM_TEST_PAGE_NUM_PUBQ 0xA3
147#define WMM_TEST_PAGE_NUM_HPQ 0x29
148#define WMM_TEST_PAGE_NUM_LPQ 0x29
149
150/* Note: For Normal Chip Setting, modify later */
151#define WMM_NORMAL_TX_TOTAL_PAGE_NUMBER 0xF5
152#define WMM_NORMAL_TX_PAGE_BOUNDARY (WMM_TEST_TX_TOTAL_PAGE_NUMBER + 1) /* F6 */
153
154#define WMM_NORMAL_PAGE_NUM_PUBQ 0xB0
155#define WMM_NORMAL_PAGE_NUM_HPQ 0x29
156#define WMM_NORMAL_PAGE_NUM_LPQ 0x1C
157#define WMM_NORMAL_PAGE_NUM_NPQ 0x1C
158
159
160/* */
161/* Chip specific */
162/* */
163#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3)
164#define CHIP_BONDING_92C_1T2R 0x1
165#define CHIP_BONDING_88C_USB_MCARD 0x2
166#define CHIP_BONDING_88C_USB_HP 0x1
167
168#include "HalVerDef.h"
169#include "hal_com.h"
170
171/* */
172/* Channel Plan */
173/* */
174enum ChannelPlan
175{
176 CHPL_FCC = 0,
177 CHPL_IC = 1,
178 CHPL_ETSI = 2,
179 CHPL_SPAIN = 3,
180 CHPL_FRANCE = 4,
181 CHPL_MKK = 5,
182 CHPL_MKK1 = 6,
183 CHPL_ISRAEL = 7,
184 CHPL_TELEC = 8,
185 CHPL_GLOBAL = 9,
186 CHPL_WORLD = 10,
187};
188
189#define EFUSE_REAL_CONTENT_LEN 512
190#define EFUSE_MAP_LEN 128
191#define EFUSE_MAX_SECTION 16
192#define EFUSE_IC_ID_OFFSET 506 /* For some inferiority IC purpose. added by Roger, 2009.09.02. */
193#define AVAILABLE_EFUSE_ADDR(addr) (addr < EFUSE_REAL_CONTENT_LEN)
194/* */
195/* <Roger_Notes> */
196/* To prevent out of boundary programming case, */
197/* leave 1byte and program full section */
198/* 9bytes + 1byt + 5bytes and pre 1byte. */
199/* For worst case: */
200/* | 1byte|----8bytes----|1byte|--5bytes--| */
201/* | | Reserved(14bytes) | */
202/* */
203
204/* PG data exclude header, dummy 6 bytes frome CP test and reserved 1byte. */
205#define EFUSE_OOB_PROTECT_BYTES 15
206
207#define EFUSE_REAL_CONTENT_LEN_8723A 512
208#define EFUSE_MAP_LEN_8723A 256
209#define EFUSE_MAX_SECTION_8723A 32
210
211/* */
212/* EFUSE for BT definition */
213/* */
214#define EFUSE_BT_REAL_BANK_CONTENT_LEN 512
215#define EFUSE_BT_REAL_CONTENT_LEN 1536 /* 512*3 */
216#define EFUSE_BT_MAP_LEN 1024 /* 1k bytes */
217#define EFUSE_BT_MAX_SECTION 128 /* 1024/8 */
218
219#define EFUSE_PROTECT_BYTES_BANK 16
220
221/* */
222/* <Roger_Notes> For RTL8723 WiFi/BT/GPS multi-function configuration. 2010.10.06. */
223/* */
224enum RT_MULTI_FUNC {
225 RT_MULTI_FUNC_NONE = 0x00,
226 RT_MULTI_FUNC_WIFI = 0x01,
227 RT_MULTI_FUNC_BT = 0x02,
228 RT_MULTI_FUNC_GPS = 0x04,
229};
230
231/* */
232/* <Roger_Notes> For RTL8723 WiFi PDn/GPIO polarity control configuration. 2010.10.08. */
233/* */
234enum RT_POLARITY_CTL {
235 RT_POLARITY_LOW_ACT = 0,
236 RT_POLARITY_HIGH_ACT = 1,
237};
238
239/* For RTL8723 regulator mode. by tynli. 2011.01.14. */
240enum RT_REGULATOR_MODE {
241 RT_SWITCHING_REGULATOR = 0,
242 RT_LDO_REGULATOR = 1,
243};
244
245/* Description: Determine the types of C2H events that are the same in driver and Fw. */
246/* Fisrt constructed by tynli. 2009.10.09. */
247enum {
248 C2H_DBG = 0,
249 C2H_TSF = 1,
250 C2H_AP_RPT_RSP = 2,
251 C2H_CCX_TX_RPT = 3, /* The FW notify the report of the specific tx packet. */
252 C2H_BT_RSSI = 4,
253 C2H_BT_OP_MODE = 5,
254 C2H_EXT_RA_RPT = 6,
255 C2H_HW_INFO_EXCH = 10,
256 C2H_C2H_H2C_TEST = 11,
257 C2H_BT_INFO = 12,
258 C2H_BT_MP_INFO = 15,
259 MAX_C2HEVENT
260};
261
262struct hal_data_8723a {
263 struct hal_version VersionID;
264 enum rt_customer_id CustomerID;
265
266 u16 FirmwareVersion;
267 u16 FirmwareVersionRev;
268 u16 FirmwareSubVersion;
269 u16 FirmwareSignature;
270
271 /* current WIFI_PHY values */
272 u32 ReceiveConfig;
273 enum WIRELESS_MODE CurrentWirelessMode;
274 enum ht_channel_width CurrentChannelBW;
275 u8 CurrentChannel;
276 u8 nCur40MhzPrimeSC;/* Control channel sub-carrier */
277
278 u16 BasicRateSet;
279
280 /* rf_ctrl */
281 u8 rf_chip;
282 u8 rf_type;
283 u8 NumTotalRFPath;
284
285 u8 BoardType;
286 u8 CrystalCap;
287 /* */
288 /* EEPROM setting. */
289 /* */
290 u8 EEPROMVersion;
291 u16 EEPROMVID;
292 u16 EEPROMPID;
293 u16 EEPROMSVID;
294 u16 EEPROMSDID;
295 u8 EEPROMCustomerID;
296 u8 EEPROMSubCustomerID;
297 u8 EEPROMRegulatory;
298 u8 EEPROMThermalMeter;
299 u8 EEPROMBluetoothCoexist;
300 u8 EEPROMBluetoothType;
301 u8 EEPROMBluetoothAntNum;
302 u8 EEPROMBluetoothAntIsolation;
303 u8 EEPROMBluetoothRadioShared;
304
305 u8 bTXPowerDataReadFromEEPORM;
306 u8 bAPKThermalMeterIgnore;
307
308 u8 bIQKInitialized;
309 u8 bAntennaDetected;
310
311 u8 TxPwrLevelCck[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
312 u8 TxPwrLevelHT40_1S[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; /* For HT 40MHZ pwr */
313 u8 TxPwrLevelHT40_2S[RF_PATH_MAX][CHANNEL_MAX_NUMBER]; /* For HT 40MHZ pwr */
314 u8 TxPwrHt20Diff[RF_PATH_MAX][CHANNEL_MAX_NUMBER];/* HT 20<->40 Pwr diff */
315 u8 TxPwrLegacyHtDiff[RF_PATH_MAX][CHANNEL_MAX_NUMBER];/* For HT<->legacy pwr diff */
316 /* For power group */
317 u8 PwrGroupHT20[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
318 u8 PwrGroupHT40[RF_PATH_MAX][CHANNEL_MAX_NUMBER];
319
320 u8 LegacyHTTxPowerDiff;/* Legacy to HT rate power diff */
321
322 /* Read/write are allow for following hardware information variables */
323 u8 framesync;
324 u32 framesyncC34;
325 u8 framesyncMonitor;
326 u8 DefaultInitialGain[4];
327 u8 pwrGroupCnt;
328 u32 MCSTxPowerLevelOriginalOffset[7][16];
329 u32 CCKTxPowerLevelOriginalOffset;
330
331 u32 AntennaTxPath; /* Antenna path Tx */
332 u32 AntennaRxPath; /* Antenna path Rx */
333 u8 ExternalPA;
334
335 u8 bLedOpenDrain; /* Support Open-drain arrangement for controlling the LED. Added by Roger, 2009.10.16. */
336
337 u8 b1x1RecvCombine; /* for 1T1R receive combining */
338
339 /* For EDCA Turbo mode */
340
341 u32 AcParam_BE; /* Original parameter for BE, use for EDCA turbo. */
342
343 /* vivi, for tx power tracking, 20080407 */
344 /* u16 TSSI_13dBm; */
345 /* u32 Pwr_Track; */
346 /* The current Tx Power Level */
347 u8 CurrentCckTxPwrIdx;
348 u8 CurrentOfdm24GTxPwrIdx;
349
350 struct bb_reg_define PHYRegDef[4]; /* Radio A/B/C/D */
351
352 bool bRFPathRxEnable[4]; /* We support 4 RF path now. */
353
354 u32 RfRegChnlVal[2];
355
356 u8 bCckHighPower;
357
358 /* RDG enable */
359 bool bRDGEnable;
360
361 /* for host message to fw */
362 u8 LastHMEBoxNum;
363
364 u8 fw_ractrl;
365 u8 RegTxPause;
366 /* Beacon function related global variable. */
367 u32 RegBcnCtrlVal;
368 u8 RegFwHwTxQCtrl;
369 u8 RegReg542;
370
371 struct dm_priv dmpriv;
372 struct dm_odm_t odmpriv;
373 struct sreset_priv srestpriv;
374
375#ifdef CONFIG_8723AU_BT_COEXIST
376 u8 bBTMode;
377 /* BT only. */
378 struct bt_30info BtInfo;
379 /* For bluetooth co-existance */
380 struct bt_coexist_str bt_coexist;
381#endif
382
383 u8 bDumpRxPkt;/* for debug */
384 u8 FwRsvdPageStartOffset; /* 2010.06.23. Added by tynli. Reserve page start offset except beacon in TxQ. */
385
386 /* 2010/08/09 MH Add CU power down mode. */
387 u8 pwrdown;
388
389 /* Add for dual MAC 0--Mac0 1--Mac1 */
390 u32 interfaceIndex;
391
392 u8 OutEpQueueSel;
393 u8 OutEpNumber;
394
395 /* 2010/12/10 MH Add for USB aggreation mode dynamic shceme. */
396 bool UsbRxHighSpeedMode;
397
398 /* 2010/11/22 MH Add for slim combo debug mode selective. */
399 /* This is used for fix the drawback of CU TSMC-A/UMC-A cut. HW auto suspend ability. Close BT clock. */
400 bool SlimComboDbg;
401
402 /* */
403 /* Add For EEPROM Efuse switch and Efuse Shadow map Setting */
404 /* */
405 u8 EepromOrEfuse;
406 u16 EfuseUsedBytes;
407 u16 BTEfuseUsedBytes;
408
409 /* Interrupt relatd register information. */
410 u32 SysIntrStatus;
411 u32 SysIntrMask;
412
413 /* */
414 /* 2011/02/23 MH Add for 8723 mylti function definition. The define should be moved to an */
415 /* independent file in the future. */
416 /* */
417 /* 8723-----------------------------------------*/
418 enum RT_MULTI_FUNC MultiFunc; /* For multi-function consideration. */
419 enum RT_POLARITY_CTL PolarityCtl; /* For Wifi PDn Polarity control. */
420 enum RT_REGULATOR_MODE RegulatorMode; /* switching regulator or LDO */
421 /* 8723-----------------------------------------
422 * 2011/02/23 MH Add for 8723 mylti function definition. The define should be moved to an */
423 /* independent file in the future. */
424
425 bool bMACFuncEnable;
426
427#ifdef CONFIG_8723AU_P2P
428 struct P2P_PS_Offload_t p2p_ps_offload;
429#endif
430
431
432 /* */
433 /* For USB Interface HAL related */
434 /* */
435 u32 UsbBulkOutSize;
436
437 /* Interrupt related register information. */
438 u32 IntArray[2];
439 u32 IntrMask[2];
440
441 /* */
442 /* For SDIO Interface HAL related */
443 /* */
444
445 /* Auto FSM to Turn On, include clock, isolation, power control for MAC only */
446 u8 bMacPwrCtrlOn;
447
448};
449
450#define GET_HAL_DATA(__pAdapter) ((struct hal_data_8723a *)((__pAdapter)->HalData))
451#define GET_RF_TYPE(priv) (GET_HAL_DATA(priv)->rf_type)
452
453#define INCLUDE_MULTI_FUNC_BT(_Adapter) (GET_HAL_DATA(_Adapter)->MultiFunc & RT_MULTI_FUNC_BT)
454#define INCLUDE_MULTI_FUNC_GPS(_Adapter) (GET_HAL_DATA(_Adapter)->MultiFunc & RT_MULTI_FUNC_GPS)
455
456struct rxreport_8723a {
457 u32 pktlen:14;
458 u32 crc32:1;
459 u32 icverr:1;
460 u32 drvinfosize:4;
461 u32 security:3;
462 u32 qos:1;
463 u32 shift:2;
464 u32 physt:1;
465 u32 swdec:1;
466 u32 ls:1;
467 u32 fs:1;
468 u32 eor:1;
469 u32 own:1;
470
471 u32 macid:5;
472 u32 tid:4;
473 u32 hwrsvd:4;
474 u32 amsdu:1;
475 u32 paggr:1;
476 u32 faggr:1;
477 u32 a1fit:4;
478 u32 a2fit:4;
479 u32 pam:1;
480 u32 pwr:1;
481 u32 md:1;
482 u32 mf:1;
483 u32 type:2;
484 u32 mc:1;
485 u32 bc:1;
486
487 u32 seq:12;
488 u32 frag:4;
489 u32 nextpktlen:14;
490 u32 nextind:1;
491 u32 rsvd0831:1;
492
493 u32 rxmcs:6;
494 u32 rxht:1;
495 u32 gf:1;
496 u32 splcp:1;
497 u32 bw:1;
498 u32 htc:1;
499 u32 eosp:1;
500 u32 bssidfit:2;
501 u32 rsvd1214:16;
502 u32 unicastwake:1;
503 u32 magicwake:1;
504
505 u32 pattern0match:1;
506 u32 pattern1match:1;
507 u32 pattern2match:1;
508 u32 pattern3match:1;
509 u32 pattern4match:1;
510 u32 pattern5match:1;
511 u32 pattern6match:1;
512 u32 pattern7match:1;
513 u32 pattern8match:1;
514 u32 pattern9match:1;
515 u32 patternamatch:1;
516 u32 patternbmatch:1;
517 u32 patterncmatch:1;
518 u32 rsvd1613:19;
519
520 u32 tsfl;
521
522 u32 bassn:12;
523 u32 bavld:1;
524 u32 rsvd2413:19;
525};
526
527/* rtl8723a_hal_init.c */
528s32 rtl8723a_FirmwareDownload(struct rtw_adapter *padapter);
529void rtl8723a_FirmwareSelfReset(struct rtw_adapter *padapter);
530void rtl8723a_InitializeFirmwareVars(struct rtw_adapter *padapter);
531
532void rtl8723a_InitAntenna_Selection(struct rtw_adapter *padapter);
533void rtl8723a_DeinitAntenna_Selection(struct rtw_adapter *padapter);
534void rtl8723a_CheckAntenna_Selection(struct rtw_adapter *padapter);
535void rtl8723a_init_default_value(struct rtw_adapter *padapter);
536
537s32 InitLLTTable23a(struct rtw_adapter *padapter, u32 boundary);
538
539s32 CardDisableHWSM(struct rtw_adapter *padapter, u8 resetMCU);
540s32 CardDisableWithoutHWSM(struct rtw_adapter *padapter);
541
542/* EFuse */
543u8 GetEEPROMSize8723A(struct rtw_adapter *padapter);
544void Hal_InitPGData(struct rtw_adapter *padapter, u8 *PROMContent);
545void Hal_EfuseParseIDCode(struct rtw_adapter *padapter, u8 *hwinfo);
546void Hal_EfuseParsetxpowerinfo_8723A(struct rtw_adapter *padapter, u8 *PROMContent, bool AutoLoadFail);
547void Hal_EfuseParseBTCoexistInfo_8723A(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail);
548void Hal_EfuseParseEEPROMVer(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail);
549void rtl8723a_EfuseParseChnlPlan(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail);
550void Hal_EfuseParseCustomerID(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail);
551void Hal_EfuseParseAntennaDiversity(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail);
552void Hal_EfuseParseRateIndicationOption(struct rtw_adapter *padapter, u8 *hwinfo, bool AutoLoadFail);
553void Hal_EfuseParseXtal_8723A(struct rtw_adapter *pAdapter, u8 *hwinfo, u8 AutoLoadFail);
554void Hal_EfuseParseThermalMeter_8723A(struct rtw_adapter *padapter, u8 *hwinfo, u8 AutoLoadFail);
555
556void Hal_InitChannelPlan23a(struct rtw_adapter *padapter);
557
558void rtl8723a_set_hal_ops(struct hal_ops *pHalFunc);
559void SetHwReg8723A(struct rtw_adapter *padapter, u8 variable, u8 *val);
560void GetHwReg8723A(struct rtw_adapter *padapter, u8 variable, u8 *val);
561#ifdef CONFIG_8723AU_BT_COEXIST
562void rtl8723a_SingleDualAntennaDetection(struct rtw_adapter *padapter);
563#endif
564
565/* register */
566void SetBcnCtrlReg23a(struct rtw_adapter *padapter, u8 SetBits, u8 ClearBits);
567void rtl8723a_InitBeaconParameters(struct rtw_adapter *padapter);
568
569void rtl8723a_clone_haldata(struct rtw_adapter *dst_adapter, struct rtw_adapter *src_adapter);
570void rtl8723a_start_thread(struct rtw_adapter *padapter);
571void rtl8723a_stop_thread(struct rtw_adapter *padapter);
572
573s32 c2h_id_filter_ccx_8723a(u8 id);
574
575#endif
diff --git a/drivers/staging/rtl8723au/include/rtl8723a_led.h b/drivers/staging/rtl8723au/include/rtl8723a_led.h
new file mode 100644
index 000000000000..1623d186feb4
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtl8723a_led.h
@@ -0,0 +1,30 @@
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 ******************************************************************************/
15#ifndef __RTL8723A_LED_H__
16#define __RTL8723A_LED_H__
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21
22/* */
23/* Interface to manipulate LED objects. */
24/* */
25void rtl8723au_InitSwLeds(struct rtw_adapter *padapter);
26void rtl8723au_DeInitSwLeds(struct rtw_adapter *padapter);
27void SwLedOn23a(struct rtw_adapter *padapter, struct led_8723a * pLed);
28void SwLedOff23a(struct rtw_adapter *padapter, struct led_8723a * pLed);
29
30#endif
diff --git a/drivers/staging/rtl8723au/include/rtl8723a_pg.h b/drivers/staging/rtl8723au/include/rtl8723a_pg.h
new file mode 100644
index 000000000000..5c2ec448e568
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtl8723a_pg.h
@@ -0,0 +1,98 @@
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 ******************************************************************************/
15#ifndef __RTL8723A_PG_H__
16#define __RTL8723A_PG_H__
17
18/* EEPROM/Efuse PG Offset for 8723E/8723U/8723S */
19#define EEPROM_CCK_TX_PWR_INX_8723A 0x10
20#define EEPROM_HT40_1S_TX_PWR_INX_8723A 0x16
21#define EEPROM_HT20_TX_PWR_INX_DIFF_8723A 0x1C
22#define EEPROM_OFDM_TX_PWR_INX_DIFF_8723A 0x1F
23#define EEPROM_HT40_MAX_PWR_OFFSET_8723A 0x22
24#define EEPROM_HT20_MAX_PWR_OFFSET_8723A 0x25
25
26#define EEPROM_ChannelPlan_8723A 0x28
27#define EEPROM_TSSI_A_8723A 0x29
28#define EEPROM_THERMAL_METER_8723A 0x2A
29#define RF_OPTION1_8723A 0x2B
30#define RF_OPTION2_8723A 0x2C
31#define RF_OPTION3_8723A 0x2D
32#define RF_OPTION4_8723A 0x2E
33#define EEPROM_VERSION_8723A 0x30
34#define EEPROM_CustomID_8723A 0x31
35#define EEPROM_SubCustomID_8723A 0x32
36#define EEPROM_XTAL_K_8723A 0x33
37#define EEPROM_Chipset_8723A 0x34
38
39/* RTL8723AE */
40#define EEPROM_VID_8723AE 0x49
41#define EEPROM_DID_8723AE 0x4B
42#define EEPROM_SVID_8723AE 0x4D
43#define EEPROM_SMID_8723AE 0x4F
44#define EEPROM_MAC_ADDR_8723AE 0x67
45
46/* RTL8723AU */
47#define EEPROM_MAC_ADDR_8723AU 0xC6
48#define EEPROM_VID_8723AU 0xB7
49#define EEPROM_PID_8723AU 0xB9
50
51/* RTL8723AS */
52#define EEPROM_MAC_ADDR_8723AS 0xAA
53
54/* EEPROM/Efuse Value Type */
55#define EETYPE_TX_PWR 0x0
56
57/* EEPROM/Efuse Default Value */
58#define EEPROM_Default_CrystalCap_8723A 0x20
59
60
61/* EEPROM/EFUSE data structure definition. */
62#define MAX_CHNL_GROUP 3+9
63
64struct txpowerinfo {
65 u8 CCKIndex[RF_PATH_MAX][MAX_CHNL_GROUP];
66 u8 HT40_1SIndex[RF_PATH_MAX][MAX_CHNL_GROUP];
67 u8 HT40_2SIndexDiff[RF_PATH_MAX][MAX_CHNL_GROUP];
68 u8 HT20IndexDiff[RF_PATH_MAX][MAX_CHNL_GROUP];
69 u8 OFDMIndexDiff[RF_PATH_MAX][MAX_CHNL_GROUP];
70 u8 HT40MaxOffset[RF_PATH_MAX][MAX_CHNL_GROUP];
71 u8 HT20MaxOffset[RF_PATH_MAX][MAX_CHNL_GROUP];
72 u8 TSSI_A[3];
73 u8 TSSI_B[3];
74 u8 TSSI_A_5G[3]; /* 5GL/5GM/5GH */
75 u8 TSSI_B_5G[3];
76};
77
78enum bt_ant_num {
79 Ant_x2 = 0,
80 Ant_x1 = 1
81};
82
83enum bt_cotype {
84 BT_2Wire = 0,
85 BT_ISSC_3Wire = 1,
86 BT_Accel = 2,
87 BT_CSR_BC4 = 3,
88 BT_CSR_BC8 = 4,
89 BT_RTL8756 = 5,
90 BT_RTL8723A = 6
91};
92
93enum bt_radioshared {
94 BT_Radio_Shared = 0,
95 BT_Radio_Individual = 1,
96};
97
98#endif
diff --git a/drivers/staging/rtl8723au/include/rtl8723a_recv.h b/drivers/staging/rtl8723au/include/rtl8723a_recv.h
new file mode 100644
index 000000000000..6bf6904f4d48
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtl8723a_recv.h
@@ -0,0 +1,70 @@
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 ******************************************************************************/
15#ifndef __RTL8723A_RECV_H__
16#define __RTL8723A_RECV_H__
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21#define NR_RECVBUFF (4)
22
23#define NR_PREALLOC_RECV_SKB (8)
24
25#define RECV_BLK_SZ 512
26#define RECV_BLK_CNT 16
27#define RECV_BLK_TH RECV_BLK_CNT
28
29#define MAX_RECVBUF_SZ (15360) /* 15k < 16k */
30
31#define RECV_BULK_IN_ADDR 0x80
32#define RECV_INT_IN_ADDR 0x81
33
34#define PHY_RSSI_SLID_WIN_MAX 100
35#define PHY_LINKQUALITY_SLID_WIN_MAX 20
36
37
38struct phy_stat
39{
40 unsigned int phydw0;
41 unsigned int phydw1;
42 unsigned int phydw2;
43 unsigned int phydw3;
44 unsigned int phydw4;
45 unsigned int phydw5;
46 unsigned int phydw6;
47 unsigned int phydw7;
48};
49
50/* Rx smooth factor */
51#define Rx_Smooth_Factor (20)
52
53struct interrupt_msg_format {
54 unsigned int C2H_MSG0;
55 unsigned int C2H_MSG1;
56 unsigned int C2H_MSG2;
57 unsigned int C2H_MSG3;
58 unsigned int HISR; /* from HISR Reg0x124, read to clear */
59 unsigned int HISRE;/* from HISRE Reg0x12c, read to clear */
60 unsigned int MSG_EX;
61};
62
63void rtl8723au_init_recvbuf(struct rtw_adapter *padapter, struct recv_buf *precvbuf);
64int rtl8723au_init_recv_priv(struct rtw_adapter * padapter);
65void rtl8723au_free_recv_priv(struct rtw_adapter * padapter);
66void rtl8723a_process_phy_info(struct rtw_adapter *padapter, void *prframe);
67void update_recvframe_attrib(struct recv_frame *precvframe, struct recv_stat *prxstat);
68void update_recvframe_phyinfo(struct recv_frame *precvframe, struct phy_stat *pphy_info);
69
70#endif
diff --git a/drivers/staging/rtl8723au/include/rtl8723a_rf.h b/drivers/staging/rtl8723au/include/rtl8723a_rf.h
new file mode 100644
index 000000000000..166a45fe47b1
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtl8723a_rf.h
@@ -0,0 +1,58 @@
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 ******************************************************************************/
15#ifndef __RTL8723A_RF_H__
16#define __RTL8723A_RF_H__
17
18/*--------------------------Define Parameters-------------------------------*/
19
20/* */
21/* For RF 6052 Series */
22/* */
23#define RF6052_MAX_TX_PWR 0x3F
24#define RF6052_MAX_REG 0x3F
25#define RF6052_MAX_PATH 2
26/*--------------------------Define Parameters-------------------------------*/
27
28
29/*------------------------------Define structure----------------------------*/
30
31/*------------------------------Define structure----------------------------*/
32
33
34/*------------------------Export global variable----------------------------*/
35/*------------------------Export global variable----------------------------*/
36
37/*------------------------Export Marco Definition---------------------------*/
38
39/*------------------------Export Marco Definition---------------------------*/
40
41
42/*--------------------------Exported Function prototype---------------------*/
43
44/* */
45/* RF RL6052 Series API */
46/* */
47void rtl8723a_phy_rf6052set_bw(struct rtw_adapter *Adapter,
48 enum ht_channel_width Bandwidth);
49void rtl823a_phy_rf6052setccktxpower(struct rtw_adapter *Adapter,
50 u8* pPowerlevel);
51void rtl8723a_PHY_RF6052SetOFDMTxPower(struct rtw_adapter *Adapter,
52 u8* pPowerLevel, u8 Channel);
53
54/*--------------------------Exported Function prototype---------------------*/
55
56int PHY_RF6052_Config8723A(struct rtw_adapter *Adapter);
57
58#endif
diff --git a/drivers/staging/rtl8723au/include/rtl8723a_spec.h b/drivers/staging/rtl8723au/include/rtl8723a_spec.h
new file mode 100644
index 000000000000..3595c27907d0
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtl8723a_spec.h
@@ -0,0 +1,2158 @@
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 *******************************************************************************/
15#ifndef __RTL8723A_SPEC_H__
16#define __RTL8723A_SPEC_H__
17
18/* */
19/* */
20/* 0x0000h ~ 0x00FFh System Configuration */
21/* */
22/* */
23#define REG_SYS_ISO_CTRL 0x0000
24#define REG_SYS_FUNC_EN 0x0002
25#define REG_APS_FSMCO 0x0004
26#define REG_SYS_CLKR 0x0008
27#define REG_9346CR 0x000A
28#define REG_EE_VPD 0x000C
29#define REG_AFE_MISC 0x0010
30#define REG_SPS0_CTRL 0x0011
31#define REG_SPS_OCP_CFG 0x0018
32#define REG_RSV_CTRL 0x001C
33#define REG_RF_CTRL 0x001F
34#define REG_LDOA15_CTRL 0x0020
35#define REG_LDOV12D_CTRL 0x0021
36#define REG_LDOHCI12_CTRL 0x0022
37#define REG_LPLDO_CTRL 0x0023
38#define REG_AFE_XTAL_CTRL 0x0024
39#define REG_AFE_PLL_CTRL 0x0028
40#define REG_MAC_PHY_CTRL 0x002c
41#define REG_EFUSE_CTRL 0x0030
42#define REG_EFUSE_TEST 0x0034
43#define REG_PWR_DATA 0x0038
44#define REG_CAL_TIMER 0x003C
45#define REG_ACLK_MON 0x003E
46#define REG_GPIO_MUXCFG 0x0040
47#define REG_GPIO_IO_SEL 0x0042
48#define REG_MAC_PINMUX_CFG 0x0043
49#define REG_GPIO_PIN_CTRL 0x0044
50#define REG_GPIO_INTM 0x0048
51#define REG_LEDCFG0 0x004C
52#define REG_LEDCFG1 0x004D
53#define REG_LEDCFG2 0x004E
54#define REG_LEDCFG3 0x004F
55#define REG_LEDCFG REG_LEDCFG2
56#define REG_FSIMR 0x0050
57#define REG_FSISR 0x0054
58#define REG_HSIMR 0x0058
59#define REG_HSISR 0x005c
60 /* RTL8723 WIFI/BT/GPS Multi-Function GPIO Pin Control. */
61#define REG_GPIO_PIN_CTRL_2 0x0060
62 /* RTL8723 WIFI/BT/GPS Multi-Function GPIO Select. */
63#define REG_GPIO_IO_SEL_2 0x0062
64 /* RTL8723 WIFI/BT/GPS Multi-Function control source. */
65#define REG_MULTI_FUNC_CTRL 0x0068
66#define REG_MCUFWDL 0x0080
67#define REG_HMEBOX_EXT_0 0x0088
68#define REG_HMEBOX_EXT_1 0x008A
69#define REG_HMEBOX_EXT_2 0x008C
70#define REG_HMEBOX_EXT_3 0x008E
71 /* Host suspend counter on FPGA platform */
72#define REG_HOST_SUSP_CNT 0x00BC
73 /* Efuse access protection for RTL8723 */
74#define REG_EFUSE_ACCESS 0x00CF
75#define REG_BIST_SCAN 0x00D0
76#define REG_BIST_RPT 0x00D4
77#define REG_BIST_ROM_RPT 0x00D8
78#define REG_USB_SIE_INTF 0x00E0
79#define REG_PCIE_MIO_INTF 0x00E4
80#define REG_PCIE_MIO_INTD 0x00E8
81#define REG_HPON_FSM 0x00EC
82#define REG_SYS_CFG 0x00F0
83#define REG_GPIO_OUTSTS 0x00F4 /* For RTL8723 only. */
84
85/* */
86/* */
87/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
88/* */
89/* */
90#define REG_CR 0x0100
91#define REG_PBP 0x0104
92#define REG_TRXDMA_CTRL 0x010C
93#define REG_TRXFF_BNDY 0x0114
94#define REG_TRXFF_STATUS 0x0118
95#define REG_RXFF_PTR 0x011C
96#define REG_HIMR 0x0120
97#define REG_HISR 0x0124
98#define REG_HIMRE 0x0128
99#define REG_HISRE 0x012C
100#define REG_CPWM 0x012F
101#define REG_FWIMR 0x0130
102#define REG_FWISR 0x0134
103#define REG_PKTBUF_DBG_CTRL 0x0140
104#define REG_PKTBUF_DBG_DATA_L 0x0144
105#define REG_PKTBUF_DBG_DATA_H 0x0148
106
107#define REG_TC0_CTRL 0x0150
108#define REG_TC1_CTRL 0x0154
109#define REG_TC2_CTRL 0x0158
110#define REG_TC3_CTRL 0x015C
111#define REG_TC4_CTRL 0x0160
112#define REG_TCUNIT_BASE 0x0164
113#define REG_MBIST_START 0x0174
114#define REG_MBIST_DONE 0x0178
115#define REG_MBIST_FAIL 0x017C
116#define REG_C2HEVT_MSG_NORMAL 0x01A0
117#define REG_C2HEVT_CLEAR 0x01AF
118#define REG_C2HEVT_MSG_TEST 0x01B8
119#define REG_MCUTST_1 0x01c0
120#define REG_FMETHR 0x01C8
121#define REG_HMETFR 0x01CC
122#define REG_HMEBOX_0 0x01D0
123#define REG_HMEBOX_1 0x01D4
124#define REG_HMEBOX_2 0x01D8
125#define REG_HMEBOX_3 0x01DC
126
127#define REG_LLT_INIT 0x01E0
128#define REG_BB_ACCEESS_CTRL 0x01E8
129#define REG_BB_ACCESS_DATA 0x01EC
130
131
132/* */
133/* */
134/* 0x0200h ~ 0x027Fh TXDMA Configuration */
135/* */
136/* */
137#define REG_RQPN 0x0200
138#define REG_FIFOPAGE 0x0204
139#define REG_TDECTRL 0x0208
140#define REG_TXDMA_OFFSET_CHK 0x020C
141#define REG_TXDMA_STATUS 0x0210
142#define REG_RQPN_NPQ 0x0214
143
144/* */
145/* */
146/* 0x0280h ~ 0x02FFh RXDMA Configuration */
147/* */
148/* */
149#define REG_RXDMA_AGG_PG_TH 0x0280
150#define REG_RXPKT_NUM 0x0284
151#define REG_RXDMA_STATUS 0x0288
152
153
154/* */
155/* */
156/* 0x0300h ~ 0x03FFh PCIe */
157/* */
158/* */
159#define REG_PCIE_CTRL_REG 0x0300
160#define REG_INT_MIG 0x0304 /* Interrupt Migration */
161 /* TX Beacon Descriptor Address */
162#define REG_BCNQ_DESA 0x0308
163 /* TX High Queue Descriptor Address */
164#define REG_HQ_DESA 0x0310
165 /* TX Manage Queue Descriptor Address */
166#define REG_MGQ_DESA 0x0318
167 /* TX VO Queue Descriptor Address */
168#define REG_VOQ_DESA 0x0320
169 /* TX VI Queue Descriptor Address */
170#define REG_VIQ_DESA 0x0328
171 /* TX BE Queue Descriptor Address */
172#define REG_BEQ_DESA 0x0330
173 /* TX BK Queue Descriptor Address */
174#define REG_BKQ_DESA 0x0338
175 /* RX Queue Descriptor Address */
176#define REG_RX_DESA 0x0340
177 /* Backdoor REG for Access Configuration */
178#define REG_DBI 0x0348
179 /* MDIO for Access PCIE PHY */
180#define REG_MDIO 0x0354
181 /* Debug Selection Register */
182#define REG_DBG_SEL 0x0360
183 /* PCIe RPWM */
184#define REG_PCIE_HRPWM 0x0361
185 /* PCIe CPWM */
186#define REG_PCIE_HCPWM 0x0363
187 /* UART Control */
188#define REG_UART_CTRL 0x0364
189 /* UART TX Descriptor Address */
190#define REG_UART_TX_DESA 0x0370
191 /* UART Rx Descriptor Address */
192#define REG_UART_RX_DESA 0x0378
193
194
195/* spec version 11 */
196/* */
197/* */
198/* 0x0400h ~ 0x047Fh Protocol Configuration */
199/* */
200/* */
201#define REG_VOQ_INFORMATION 0x0400
202#define REG_VIQ_INFORMATION 0x0404
203#define REG_BEQ_INFORMATION 0x0408
204#define REG_BKQ_INFORMATION 0x040C
205#define REG_MGQ_INFORMATION 0x0410
206#define REG_HGQ_INFORMATION 0x0414
207#define REG_BCNQ_INFORMATION 0x0418
208
209
210#define REG_CPU_MGQ_INFORMATION 0x041C
211#define REG_FWHW_TXQ_CTRL 0x0420
212#define REG_HWSEQ_CTRL 0x0423
213#define REG_TXPKTBUF_BCNQ_BDNY 0x0424
214#define REG_TXPKTBUF_MGQ_BDNY 0x0425
215#define REG_LIFETIME_EN 0x0426
216#define REG_MULTI_BCNQ_OFFSET 0x0427
217#define REG_SPEC_SIFS 0x0428
218#define REG_RL 0x042A
219#define REG_DARFRC 0x0430
220#define REG_RARFRC 0x0438
221#define REG_RRSR 0x0440
222#define REG_ARFR0 0x0444
223#define REG_ARFR1 0x0448
224#define REG_ARFR2 0x044C
225#define REG_ARFR3 0x0450
226#define REG_AGGLEN_LMT 0x0458
227#define REG_AMPDU_MIN_SPACE 0x045C
228#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D
229#define REG_FAST_EDCA_CTRL 0x0460
230#define REG_RD_RESP_PKT_TH 0x0463
231#define REG_INIRTS_RATE_SEL 0x0480
232#define REG_INIDATA_RATE_SEL 0x0484
233
234
235#define REG_POWER_STATUS 0x04A4
236#define REG_POWER_STAGE1 0x04B4
237#define REG_POWER_STAGE2 0x04B8
238#define REG_PKT_VO_VI_LIFE_TIME 0x04C0
239#define REG_PKT_BE_BK_LIFE_TIME 0x04C2
240#define REG_STBC_SETTING 0x04C4
241#define REG_PROT_MODE_CTRL 0x04C8
242#define REG_MAX_AGGR_NUM 0x04CA
243#define REG_RTS_MAX_AGGR_NUM 0x04CB
244#define REG_BAR_MODE_CTRL 0x04CC
245#define REG_RA_TRY_RATE_AGG_LMT 0x04CF
246#define REG_NQOS_SEQ 0x04DC
247#define REG_QOS_SEQ 0x04DE
248#define REG_NEED_CPU_HANDLE 0x04E0
249#define REG_PKT_LOSE_RPT 0x04E1
250#define REG_PTCL_ERR_STATUS 0x04E2
251#define REG_DUMMY 0x04FC
252
253
254
255/* */
256/* */
257/* 0x0500h ~ 0x05FFh EDCA Configuration */
258/* */
259/* */
260#define REG_EDCA_VO_PARAM 0x0500
261#define REG_EDCA_VI_PARAM 0x0504
262#define REG_EDCA_BE_PARAM 0x0508
263#define REG_EDCA_BK_PARAM 0x050C
264#define REG_BCNTCFG 0x0510
265#define REG_PIFS 0x0512
266#define REG_RDG_PIFS 0x0513
267#define REG_SIFS_CCK 0x0514
268#define REG_SIFS_OFDM 0x0516
269#define REG_SIFS_CTX 0x0514
270#define REG_SIFS_TRX 0x0516
271#define REG_TSFTR_SYN_OFFSET 0x0518
272#define REG_AGGR_BREAK_TIME 0x051A
273#define REG_SLOT 0x051B
274#define REG_TX_PTCL_CTRL 0x0520
275#define REG_TXPAUSE 0x0522
276#define REG_DIS_TXREQ_CLR 0x0523
277#define REG_RD_CTRL 0x0524
278#define REG_TBTT_PROHIBIT 0x0540
279#define REG_RD_NAV_NXT 0x0544
280#define REG_NAV_PROT_LEN 0x0546
281#define REG_BCN_CTRL 0x0550
282#define REG_BCN_CTRL_1 0x0551
283#define REG_MBID_NUM 0x0552
284#define REG_DUAL_TSF_RST 0x0553
285 /* The same as REG_MBSSID_BCN_SPACE */
286#define REG_BCN_INTERVAL 0x0554
287#define REG_MBSSID_BCN_SPACE 0x0554
288#define REG_DRVERLYINT 0x0558
289#define REG_BCNDMATIM 0x0559
290#define REG_ATIMWND 0x055A
291#define REG_BCN_MAX_ERR 0x055D
292#define REG_RXTSF_OFFSET_CCK 0x055E
293#define REG_RXTSF_OFFSET_OFDM 0x055F
294#define REG_TSFTR 0x0560
295#define REG_TSFTR1 0x0568
296#define REG_INIT_TSFTR 0x0564
297#define REG_ATIMWND_1 0x0570
298#define REG_PSTIMER 0x0580
299#define REG_TIMER0 0x0584
300#define REG_TIMER1 0x0588
301#define REG_ACMHWCTRL 0x05C0
302#define REG_ACMRSTCTRL 0x05C1
303#define REG_ACMAVG 0x05C2
304#define REG_VO_ADMTIME 0x05C4
305#define REG_VI_ADMTIME 0x05C6
306#define REG_BE_ADMTIME 0x05C8
307#define REG_EDCA_RANDOM_GEN 0x05CC
308#define REG_SCH_TXCMD 0x05D0
309
310/* define REG_FW_TSF_SYNC_CNT 0x04A0 */
311#define REG_FW_RESET_TSF_CNT_1 0x05FC
312#define REG_FW_RESET_TSF_CNT_0 0x05FD
313#define REG_FW_BCN_DIS_CNT 0x05FE
314
315/* */
316/* */
317/* 0x0600h ~ 0x07FFh WMAC Configuration */
318/* */
319/* */
320#define REG_APSD_CTRL 0x0600
321#define REG_BWOPMODE 0x0603
322#define REG_TCR 0x0604
323#define REG_RCR 0x0608
324#define REG_RX_PKT_LIMIT 0x060C
325#define REG_RX_DLK_TIME 0x060D
326#define REG_RX_DRVINFO_SZ 0x060F
327
328#define REG_MACID 0x0610
329#define REG_BSSID 0x0618
330#define REG_MAR 0x0620
331#define REG_MBIDCAMCFG 0x0628
332
333#define REG_USTIME_EDCA 0x0638
334#define REG_MAC_SPEC_SIFS 0x063A
335
336/* 20100719 Joseph: Hardware register definition change. (HW datasheet v54) */
337 /* [15:8]SIFS_R2T_OFDM, [7:0]SIFS_R2T_CCK */
338#define REG_R2T_SIFS 0x063C
339 /* [15:8]SIFS_T2T_OFDM, [7:0]SIFS_T2T_CCK */
340#define REG_T2T_SIFS 0x063E
341#define REG_ACKTO 0x0640
342#define REG_CTS2TO 0x0641
343#define REG_EIFS 0x0642
344
345/* WMA, BA, CCX */
346#define REG_NAV_CTRL 0x0650
347#define REG_BACAMCMD 0x0654
348#define REG_BACAMCONTENT 0x0658
349#define REG_LBDLY 0x0660
350#define REG_FWDLY 0x0661
351#define REG_RXERR_RPT 0x0664
352#define REG_WMAC_TRXPTCL_CTL 0x0668
353
354
355/* Security */
356#define REG_CAMCMD 0x0670
357#define REG_CAMWRITE 0x0674
358#define REG_CAMREAD 0x0678
359#define REG_CAMDBG 0x067C
360#define REG_SECCFG 0x0680
361
362/* Power */
363#define REG_WOW_CTRL 0x0690
364#define REG_PSSTATUS 0x0691
365#define REG_PS_RX_INFO 0x0692
366#define REG_LPNAV_CTRL 0x0694
367#define REG_WKFMCAM_CMD 0x0698
368#define REG_WKFMCAM_RWD 0x069C
369#define REG_RXFLTMAP0 0x06A0
370#define REG_RXFLTMAP1 0x06A2
371#define REG_RXFLTMAP2 0x06A4
372#define REG_BCN_PSR_RPT 0x06A8
373#define REG_CALB32K_CTRL 0x06AC
374#define REG_PKT_MON_CTRL 0x06B4
375#define REG_BT_COEX_TABLE 0x06C0
376#define REG_WMAC_RESP_TXINFO 0x06D8
377
378#define REG_MACID1 0x0700
379#define REG_BSSID1 0x0708
380
381
382/* */
383/* */
384/* 0xFE00h ~ 0xFE55h USB Configuration */
385/* */
386/* */
387#define REG_USB_INFO 0xFE17
388#define REG_USB_SPECIAL_OPTION 0xFE55
389#define REG_USB_DMA_AGG_TO 0xFE5B
390#define REG_USB_AGG_TO 0xFE5C
391#define REG_USB_AGG_TH 0xFE5D
392
393/* For test chip */
394#define REG_TEST_USB_TXQS 0xFE48
395#define REG_TEST_SIE_VID 0xFE60 /* 0xFE60~0xFE61 */
396#define REG_TEST_SIE_PID 0xFE62 /* 0xFE62~0xFE63 */
397#define REG_TEST_SIE_OPTIONAL 0xFE64
398#define REG_TEST_SIE_CHIRP_K 0xFE65
399#define REG_TEST_SIE_PHY 0xFE66 /* 0xFE66~0xFE6B */
400#define REG_TEST_SIE_MAC_ADDR 0xFE70 /* 0xFE70~0xFE75 */
401#define REG_TEST_SIE_STRING 0xFE80 /* 0xFE80~0xFEB9 */
402
403
404/* For normal chip */
405#define REG_NORMAL_SIE_VID 0xFE60 /* 0xFE60~0xFE61 */
406#define REG_NORMAL_SIE_PID 0xFE62 /* 0xFE62~0xFE63 */
407#define REG_NORMAL_SIE_OPTIONAL 0xFE64
408#define REG_NORMAL_SIE_EP 0xFE65 /* 0xFE65~0xFE67 */
409#define REG_NORMAL_SIE_PHY 0xFE68 /* 0xFE68~0xFE6B */
410#define REG_NORMAL_SIE_OPTIONAL2 0xFE6C
411#define REG_NORMAL_SIE_GPS_EP 0xFE6D /* RTL8723 only */
412#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 /* 0xFE70~0xFE75 */
413#define REG_NORMAL_SIE_STRING 0xFE80 /* 0xFE80~0xFEDF */
414
415
416/* */
417/* */
418/* Redifine 8192C register definition for compatibility */
419/* */
420/* */
421
422/* TODO: use these definition when using REG_xxx naming rule. */
423/* NOTE: DO NOT Remove these definition. Use later. */
424
425 /* System Isolation Interface Control. */
426#define SYS_ISO_CTRL REG_SYS_ISO_CTRL
427 /* System Function Enable. */
428#define SYS_FUNC_EN REG_SYS_FUNC_EN
429#define SYS_CLK REG_SYS_CLKR
430 /* 93C46/93C56 Command Register. */
431#define CR9346 REG_9346CR
432 /* E-Fuse Control. */
433#define EFUSE_CTRL REG_EFUSE_CTRL
434 /* E-Fuse Test. */
435#define EFUSE_TEST REG_EFUSE_TEST
436 /* Media Status register */
437#define MSR (REG_CR + 2)
438#define ISR REG_HISR
439 /* Timing Sync Function Timer Register. */
440#define TSFR REG_TSFTR
441
442 /* MAC ID Register, Offset 0x0050-0x0053 */
443#define MACIDR0 REG_MACID
444 /* MAC ID Register, Offset 0x0054-0x0055 */
445#define MACIDR4 (REG_MACID + 4)
446
447#define PBP REG_PBP
448
449 /* Redifine MACID register, to compatible prior ICs. */
450#define IDR0 MACIDR0
451#define IDR4 MACIDR4
452
453
454/* */
455/* 9. Security Control Registers (Offset: ) */
456/* */
457 /* IN 8190 Data Sheet is called CAMcmd */
458#define RWCAM REG_CAMCMD
459 /* Software write CAM input content */
460#define WCAMI REG_CAMWRITE
461 /* Software read/write CAM config */
462#define RCAMO REG_CAMREAD
463#define CAMDBG REG_CAMDBG
464 /* Security Configuration Register */
465#define SECR REG_SECCFG
466
467/* Unused register */
468#define UnusedRegister 0x1BF
469#define DCAM UnusedRegister
470#define PSR UnusedRegister
471#define BBAddr UnusedRegister
472#define PhyDataR UnusedRegister
473
474#define InvalidBBRFValue 0x12345678
475
476/* Min Spacing related settings. */
477#define MAX_MSS_DENSITY_2T 0x13
478#define MAX_MSS_DENSITY_1T 0x0A
479
480/* */
481/* 8192C Cmd9346CR bits (Offset 0xA, 16bit) */
482/* */
483 /* EEPROM enable when set 1 */
484#define CmdEEPROM_En BIT5
485 /* System EEPROM select, 0: boot from E-FUSE,
486 1: The EEPROM used is 9346 */
487#define CmdEERPOMSEL BIT4
488#define Cmd9346CR_9356SEL BIT4
489#define AutoLoadEEPROM (CmdEEPROM_En|CmdEERPOMSEL)
490#define AutoLoadEFUSE CmdEEPROM_En
491
492/* */
493/* 8192C GPIO MUX Configuration Register (offset 0x40, 4 byte) */
494/* */
495#define GPIOSEL_GPIO 0
496#define GPIOSEL_ENBT BIT5
497
498/* */
499/* 8192C GPIO PIN Control Register (offset 0x44, 4 byte) */
500/* */
501 /* GPIO pins input value */
502#define GPIO_IN REG_GPIO_PIN_CTRL
503 /* GPIO pins output value */
504#define GPIO_OUT (REG_GPIO_PIN_CTRL+1)
505 /* GPIO pins output enable when a bit is set to "1";
506 otherwise, input is configured. */
507#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2)
508#define GPIO_MOD (REG_GPIO_PIN_CTRL+3)
509
510/* */
511/* 8192C (MSR) Media Status Register (Offset 0x4C, 8 bits) */
512/* */
513/*
514Network Type
51500: No link
51601: Link in ad hoc network
51710: Link in infrastructure network
51811: AP mode
519Default: 00b.
520*/
521#define MSR_NOLINK 0x00
522#define MSR_ADHOC 0x01
523#define MSR_INFRA 0x02
524#define MSR_AP 0x03
525
526/* */
527/* 6. Adaptive Control Registers (Offset: 0x0160 - 0x01CF) */
528/* */
529/* */
530/* 8192C Response Rate Set Register (offset 0x181, 24bits) */
531/* */
532#define RRSR_RSC_OFFSET 21
533#define RRSR_SHORT_OFFSET 23
534#define RRSR_RSC_BW_40M 0x600000
535#define RRSR_RSC_UPSUBCHNL 0x400000
536#define RRSR_RSC_LOWSUBCHNL 0x200000
537#define RRSR_SHORT 0x800000
538#define RRSR_1M BIT0
539#define RRSR_2M BIT1
540#define RRSR_5_5M BIT2
541#define RRSR_11M BIT3
542#define RRSR_6M BIT4
543#define RRSR_9M BIT5
544#define RRSR_12M BIT6
545#define RRSR_18M BIT7
546#define RRSR_24M BIT8
547#define RRSR_36M BIT9
548#define RRSR_48M BIT10
549#define RRSR_54M BIT11
550#define RRSR_MCS0 BIT12
551#define RRSR_MCS1 BIT13
552#define RRSR_MCS2 BIT14
553#define RRSR_MCS3 BIT15
554#define RRSR_MCS4 BIT16
555#define RRSR_MCS5 BIT17
556#define RRSR_MCS6 BIT18
557#define RRSR_MCS7 BIT19
558#define BRSR_AckShortPmb BIT23
559/* CCK ACK: use Short Preamble or not */
560
561/* */
562/* 8192C BW_OPMODE bits (Offset 0x203, 8bit) */
563/* */
564#define BW_OPMODE_20MHZ BIT2
565#define BW_OPMODE_5G BIT1
566#define BW_OPMODE_11J BIT0
567
568
569/* */
570/* 8192C CAM Config Setting (offset 0x250, 1 byte) */
571/* */
572#define CAM_VALID BIT15
573#define CAM_NOTVALID 0x0000
574#define CAM_USEDK BIT5
575
576#define CAM_CONTENT_COUNT 8
577
578#define CAM_NONE 0x0
579#define CAM_WEP40 0x01
580#define CAM_TKIP 0x02
581#define CAM_AES 0x04
582#define CAM_WEP104 0x05
583
584#define TOTAL_CAM_ENTRY 32
585#define HALF_CAM_ENTRY 16
586
587#define CAM_CONFIG_USEDK true
588#define CAM_CONFIG_NO_USEDK false
589
590#define CAM_WRITE BIT16
591#define CAM_READ 0x00000000
592#define CAM_POLLINIG BIT31
593
594#define SCR_UseDK 0x01
595#define SCR_TxSecEnable 0x02
596#define SCR_RxSecEnable 0x04
597
598
599/* */
600/* 12. Host Interrupt Status Registers (Offset: 0x0300 - 0x030F) */
601/* */
602/* */
603/* 8190 IMR/ISR bits (offset 0xfd, 8bits) */
604/* */
605#define IMR8190_DISABLED 0x0
606/* IMR DW0 Bit 0-31 */
607
608#define IMR_BCNDMAINT6 BIT31 /* Beacon DMA Interrupt 6 */
609#define IMR_BCNDMAINT5 BIT30 /* Beacon DMA Interrupt 5 */
610#define IMR_BCNDMAINT4 BIT29 /* Beacon DMA Interrupt 4 */
611#define IMR_BCNDMAINT3 BIT28 /* Beacon DMA Interrupt 3 */
612#define IMR_BCNDMAINT2 BIT27 /* Beacon DMA Interrupt 2 */
613#define IMR_BCNDMAINT1 BIT26 /* Beacon DMA Interrupt 1 */
614#define IMR_BCNDOK8 BIT25 /* Beacon Queue DMA OK
615 Interrupt 8 */
616#define IMR_BCNDOK7 BIT24 /* Beacon Queue DMA OK
617 Interrupt 7 */
618#define IMR_BCNDOK6 BIT23 /* Beacon Queue DMA OK
619 Interrupt 6 */
620#define IMR_BCNDOK5 BIT22 /* Beacon Queue DMA OK
621 Interrupt 5 */
622#define IMR_BCNDOK4 BIT21 /* Beacon Queue DMA OK
623 Interrupt 4 */
624#define IMR_BCNDOK3 BIT20 /* Beacon Queue DMA OK
625 Interrupt 3 */
626#define IMR_BCNDOK2 BIT19 /* Beacon Queue DMA OK
627 Interrupt 2 */
628#define IMR_BCNDOK1 BIT18 /* Beacon Queue DMA OK
629 Interrupt 1 */
630#define IMR_TIMEOUT2 BIT17 /* Timeout interrupt 2 */
631#define IMR_TIMEOUT1 BIT16 /* Timeout interrupt 1 */
632#define IMR_TXFOVW BIT15 /* Transmit FIFO Overflow */
633#define IMR_PSTIMEOUT BIT14 /* Power save time out
634 interrupt */
635#define IMR_BcnInt BIT13 /* Beacon DMA Interrupt 0 */
636#define IMR_RXFOVW BIT12 /* Receive FIFO Overflow */
637#define IMR_RDU BIT11 /* Receive Descriptor
638 Unavailable */
639#define IMR_ATIMEND BIT10 /* For 92C,ATIM Window
640 End Interrupt */
641#define IMR_BDOK BIT9 /* Beacon Queue DMA OK
642 Interrup */
643#define IMR_HIGHDOK BIT8 /* High Queue DMA OK
644 Interrupt */
645#define IMR_TBDOK BIT7 /* Transmit Beacon OK
646 interrup */
647#define IMR_MGNTDOK BIT6 /* Management Queue DMA OK
648 Interrupt */
649#define IMR_TBDER BIT5 /* For 92C,Transmit Beacon
650 Error Interrupt */
651#define IMR_BKDOK BIT4 /* AC_BK DMA OK Interrupt */
652#define IMR_BEDOK BIT3 /* AC_BE DMA OK Interrupt */
653#define IMR_VIDOK BIT2 /* AC_VI DMA OK Interrupt */
654#define IMR_VODOK BIT1 /* AC_VO DMA Interrupt */
655#define IMR_ROK BIT0 /* Receive DMA OK Interrupt */
656
657#define IMR_RX_MASK (IMR_ROK|IMR_RDU|IMR_RXFOVW)
658#define IMR_TX_MASK (IMR_VODOK|IMR_VIDOK|IMR_BEDOK| \
659 IMR_BKDOK|IMR_MGNTDOK|IMR_HIGHDOK| \
660 IMR_BDOK)
661
662/* 13. Host Interrupt Status Extension Register (Offset: 0x012C-012Eh) */
663#define IMR_BcnInt_E BIT12
664#define IMR_TXERR BIT11
665#define IMR_RXERR BIT10
666#define IMR_C2HCMD BIT9
667#define IMR_CPWM BIT8
668/* RSVD [2-7] */
669#define IMR_OCPINT BIT1
670#define IMR_WLANOFF BIT0
671
672
673/* 8192C EEPROM/EFUSE share register definition. */
674
675/* Default Value for EEPROM or EFUSE!!! */
676#define EEPROM_Default_TSSI 0x0
677#define EEPROM_Default_TxPowerDiff 0x0
678#define EEPROM_Default_CrystalCap 0x5
679 /* Default: 2X2, RTL8192CE(QFPN68) */
680#define EEPROM_Default_BoardType 0x02
681#define EEPROM_Default_TxPower 0x1010
682#define EEPROM_Default_HT2T_TxPwr 0x10
683
684#define EEPROM_Default_LegacyHTTxPowerDiff 0x3
685#define EEPROM_Default_ThermalMeter 0x12
686
687#define EEPROM_Default_AntTxPowerDiff 0x0
688#define EEPROM_Default_TxPwDiff_CrystalCap 0x5
689#define EEPROM_Default_TxPowerLevel 0x22
690#define EEPROM_Default_HT40_2SDiff 0x0
691 /* HT20<->40 default Tx Power Index Difference */
692#define EEPROM_Default_HT20_Diff 2
693#define EEPROM_Default_LegacyHTTxPowerDiff 0x3
694#define EEPROM_Default_HT40_PwrMaxOffset 0
695#define EEPROM_Default_HT20_PwrMaxOffset 0
696
697/* For debug */
698#define EEPROM_Default_PID 0x1234
699#define EEPROM_Default_VID 0x5678
700#define EEPROM_Default_CustomerID 0xAB
701#define EEPROM_Default_SubCustomerID 0xCD
702#define EEPROM_Default_Version 0
703
704#define EEPROM_CHANNEL_PLAN_FCC 0x0
705#define EEPROM_CHANNEL_PLAN_IC 0x1
706#define EEPROM_CHANNEL_PLAN_ETSI 0x2
707#define EEPROM_CHANNEL_PLAN_SPAIN 0x3
708#define EEPROM_CHANNEL_PLAN_FRANCE 0x4
709#define EEPROM_CHANNEL_PLAN_MKK 0x5
710#define EEPROM_CHANNEL_PLAN_MKK1 0x6
711#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7
712#define EEPROM_CHANNEL_PLAN_TELEC 0x8
713#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9
714#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA
715#define EEPROM_CHANNEL_PLAN_NCC 0xB
716#define EEPROM_USB_OPTIONAL1 0xE
717#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80
718
719
720#define EEPROM_CID_DEFAULT 0x0
721#define EEPROM_CID_TOSHIBA 0x4
722 /* CCX test. By Bruce, 2009-02-25. */
723#define EEPROM_CID_CCX 0x10
724#define EEPROM_CID_QMI 0x0D
725 /* added by chiyoko for dtm, 20090108 */
726#define EEPROM_CID_WHQL 0xFE
727
728
729#define RTL_EEPROM_ID 0x8129
730
731#define SUPPORT_HW_RADIO_DETECT(pHalData) \
732 (pHalData->BoardType == BOARD_MINICARD || \
733 pHalData->BoardType == BOARD_USB_SOLO || \
734 pHalData->BoardType == BOARD_USB_COMBO)
735
736/* */
737/* EEPROM address for Test chip */
738/* */
739#define EEPROM_TEST_USB_OPT 0x0E
740#define EEPROM_TEST_CHIRP_K 0x0F
741#define EEPROM_TEST_EP_SETTING 0x0E
742#define EEPROM_TEST_USB_PHY 0x10
743
744
745/* */
746/* EEPROM address for Normal chip */
747/* */
748#define EEPROM_NORMAL_USB_OPT 0x0E
749#define EEPROM_NORMAL_CHIRP_K 0x0E /* Changed */
750#define EEPROM_NORMAL_EP_SETTING 0x0F /* Changed */
751#define EEPROM_NORMAL_USB_PHY 0x12 /* Changed */
752
753enum {
754 BOARD_USB_DONGLE = 0, /* USB dongle */
755 BOARD_USB_High_PA = 1, /* USB dongle with high power PA */
756 BOARD_MINICARD = 2, /* Minicard */
757 BOARD_USB_SOLO = 3, /* USB solo-Slim module */
758 BOARD_USB_COMBO = 4, /* USB Combo-Slim module */
759};
760
761/* Test chip and normal chip common define */
762/* */
763/* EEPROM address for both */
764/* */
765#define EEPROM_ID0 0x00
766#define EEPROM_ID1 0x01
767#define EEPROM_RTK_RSV1 0x02
768#define EEPROM_RTK_RSV2 0x03
769#define EEPROM_RTK_RSV3 0x04
770#define EEPROM_RTK_RSV4 0x05
771#define EEPROM_RTK_RSV5 0x06
772#define EEPROM_DBG_SEL 0x07
773#define EEPROM_RTK_RSV6 0x08
774#define EEPROM_VID 0x0A
775#define EEPROM_PID 0x0C
776
777#define EEPROM_MAC_ADDR 0x16
778#define EEPROM_STRING 0x1C
779#define EEPROM_SUBCUSTOMER_ID 0x59
780#define EEPROM_CCK_TX_PWR_INX 0x5A
781#define EEPROM_HT40_1S_TX_PWR_INX 0x60
782#define EEPROM_HT40_2S_TX_PWR_INX_DIFF 0x66
783#define EEPROM_HT20_TX_PWR_INX_DIFF 0x69
784#define EEPROM_OFDM_TX_PWR_INX_DIFF 0x6C
785#define EEPROM_HT40_MAX_PWR_OFFSET 0x6F
786#define EEPROM_HT20_MAX_PWR_OFFSET 0x72
787
788#define EEPROM_CHANNEL_PLAN 0x75
789#define EEPROM_TSSI_A 0x76
790#define EEPROM_TSSI_B 0x77
791#define EEPROM_THERMAL_METER 0x78
792#define EEPROM_RF_OPT1 0x79
793#define EEPROM_RF_OPT2 0x7A
794#define EEPROM_RF_OPT3 0x7B
795#define EEPROM_RF_OPT4 0x7C
796#define EEPROM_VERSION 0x7E
797#define EEPROM_CUSTOMER_ID 0x7F
798
799 /* 0x0: RTL8188SU, 0x1: RTL8191SU, 0x2: RTL8192SU, 0x3: RTL8191GU */
800#define EEPROM_BoardType 0x54
801 /* 0x5C-0x76, Tx Power index. */
802#define EEPROM_TxPwIndex 0x5C
803 /* Difference of gain index between legacy and high throughput OFDM. */
804#define EEPROM_PwDiff 0x67
805 /* CCK Tx Power */
806#define EEPROM_TxPowerCCK 0x5A
807
808/* 2009/02/09 Cosa Add for SD3 requirement */
809 /* HT20 Tx Power Index Difference */
810#define EEPROM_TX_PWR_HT20_DIFF 0x6e
811 /* HT20<->40 default Tx Power Index Difference */
812#define DEFAULT_HT20_TXPWR_DIFF 2
813 /* OFDM Tx Power Index Difference */
814#define EEPROM_TX_PWR_OFDM_DIFF 0x71
815
816 /* Power diff for channel group */
817#define EEPROM_TxPWRGroup 0x73
818 /* Check if power safety is need */
819#define EEPROM_Regulatory 0x79
820
821 /* 92cu, 0x7E[4] */
822#define EEPROM_BLUETOOTH_COEXIST 0x7E
823#define EEPROM_NORMAL_BoardType EEPROM_RF_OPT1 /* 7:5] */
824#define BOARD_TYPE_NORMAL_MASK 0xE0
825#define BOARD_TYPE_TEST_MASK 0x0F
826 /* BIT0 1 for build-in module, 0 for external dongle */
827#define EEPROM_EASY_REPLACEMENT 0x50
828/* */
829/* EPROM content definitions */
830/* */
831#define OS_LINK_SPEED BIT(5)
832
833#define BOARD_TYPE_MASK 0xF
834
835#define BT_COEXISTENCE BIT(4)
836#define BT_CO_SHIFT 4
837
838#define EP_NUMBER_MASK 0x30 /* bit 4:5 0Eh */
839#define EP_NUMBER_SHIFT 4
840
841
842#define USB_PHY_PARA_SIZE 5
843
844
845/* */
846/* EEPROM default value definitions */
847/* */
848/* Use 0xABCD instead of 0x8192 for debug */
849#define EEPROM_DEF_ID_0 0xCD /* Byte 0x00 */
850#define EEPROM_DEF_ID_1 0xAB /* Byte 0x01 */
851
852#define EEPROM_DEF_RTK_RSV_A3 0x74 /* Byte 0x03 */
853#define EEPROM_DEF_RTK_RSV_A4 0x6D /* Byte 0x04 */
854#define EEPROM_DEF_RTK_RSV_A8 0xFF /* Byte 0x08 */
855
856#define EEPROM_DEF_VID_0 0x0A /* Byte 0x0A */
857#define EEPROM_DEF_VID_1 0x0B
858
859#define EEPROM_DEF_PID_0 0x92 /* Byte 0x0C */
860#define EEPROM_DEF_PID_1 0x81
861
862
863#define EEPROM_TEST_DEF_USB_OPT 0x80 /* Byte 0x0E */
864#define EEPROM_NORMAL_DEF_USB_OPT 0x00 /* Byte 0x0E */
865
866#define EEPROM_DEF_CHIRPK 0x15 /* Byte 0x0F */
867
868#define EEPROM_DEF_USB_PHY_0 0x85 /* Byte 0x10 */
869#define EEPROM_DEF_USB_PHY_1 0x62 /* Byte 0x11 */
870#define EEPROM_DEF_USB_PHY_2 0x9E /* Byte 0x12 */
871#define EEPROM_DEF_USB_PHY_3 0x06 /* Byte 0x13 */
872
873#define EEPROM_DEF_TSSI_A 0x09 /* Byte 0x78 */
874#define EEPROM_DEF_TSSI_B 0x09 /* Byte 0x79 */
875
876
877#define EEPROM_DEF_THERMAL_METER 0x12 /* Byte 0x7A */
878
879 /* Check if power safety spec is need */
880#define RF_OPTION1 0x79
881#define RF_OPTION2 0x7A
882#define RF_OPTION3 0x7B
883#define RF_OPTION4 0x7C
884
885
886#define EEPROM_USB_SN BIT(0)
887#define EEPROM_USB_REMOTE_WAKEUP BIT(1)
888#define EEPROM_USB_DEVICE_PWR BIT(2)
889#define EEPROM_EP_NUMBER (BIT(3)|BIT(4))
890
891/*===================================================================
892=====================================================================
893Here the register defines are for 92C. When the define is as same with 92C,
894we will use the 92C's define for the consistency
895So the following defines for 92C is not entire!!!!!!
896=====================================================================
897=====================================================================*/
898/*
899Based on Datasheet V33---090401
900Register Summary
901Current IOREG MAP
9020x0000h ~ 0x00FFh System Configuration (256 Bytes)
9030x0100h ~ 0x01FFh MACTOP General Configuration (256 Bytes)
9040x0200h ~ 0x027Fh TXDMA Configuration (128 Bytes)
9050x0280h ~ 0x02FFh RXDMA Configuration (128 Bytes)
9060x0300h ~ 0x03FFh PCIE EMAC Reserved Region (256 Bytes)
9070x0400h ~ 0x04FFh Protocol Configuration (256 Bytes)
9080x0500h ~ 0x05FFh EDCA Configuration (256 Bytes)
9090x0600h ~ 0x07FFh WMAC Configuration (512 Bytes)
9100x2000h ~ 0x3FFFh 8051 FW Download Region (8196 Bytes)
911*/
912
913/* */
914/* 8192C (RCR) Receive Configuration Register (Offset 0x608, 32 bits) */
915/* */
916#define RCR_APPFCS BIT31 /* WMAC append FCS after payload*/
917#define RCR_APP_MIC BIT30
918#define RCR_APP_PHYSTS BIT28
919#define RCR_APP_ICV BIT29
920#define RCR_APP_PHYST_RXFF BIT28
921#define RCR_APP_BA_SSN BIT27 /* Accept BA SSN */
922#define RCR_ENMBID BIT24 /* Enable Multiple BssId. */
923#define RCR_LSIGEN BIT23
924#define RCR_MFBEN BIT22
925#define RCR_HTC_LOC_CTRL BIT14 /* MFC<--HTC=1 MFC-->HTC=0 */
926#define RCR_AMF BIT13 /* Accept management type frame */
927#define RCR_ACF BIT12 /* Accept control type frame */
928#define RCR_ADF BIT11 /* Accept data type frame */
929#define RCR_AICV BIT9 /* Accept ICV error packet */
930#define RCR_ACRC32 BIT8 /* Accept CRC32 error packet */
931#define RCR_CBSSID_BCN BIT7 /* Accept BSSID match packet
932 (Rx beacon, probe rsp) */
933#define RCR_CBSSID_DATA BIT6 /* Accept BSSID match packet
934 (Data) */
935#define RCR_CBSSID RCR_CBSSID_DATA /* Accept BSSID match
936 packet */
937#define RCR_APWRMGT BIT5 /* Accept power management
938 packet */
939#define RCR_ADD3 BIT4 /* Accept address 3 match
940 packet */
941#define RCR_AB BIT3 /* Accept broadcast packet */
942#define RCR_AM BIT2 /* Accept multicast packet */
943#define RCR_APM BIT1 /* Accept physical match packet */
944#define RCR_AAP BIT0 /* Accept all unicast packet */
945#define RCR_MXDMA_OFFSET 8
946#define RCR_FIFO_OFFSET 13
947
948
949
950/* */
951/* 8192c USB specific Regsiter Offset and Content definition, */
952/* 2009.08.18, added by vivi. for merge 92c and 92C into one driver */
953/* */
954/* define APS_FSMCO 0x0004 same with 92Ce */
955#define RSV_CTRL 0x001C
956#define RD_CTRL 0x0524
957
958/* */
959/* */
960/* 0xFE00h ~ 0xFE55h USB Configuration */
961/* */
962/* */
963#define REG_USB_INFO 0xFE17
964#define REG_USB_SPECIAL_OPTION 0xFE55
965#define REG_USB_DMA_AGG_TO 0xFE5B
966#define REG_USB_AGG_TO 0xFE5C
967#define REG_USB_AGG_TH 0xFE5D
968
969#define REG_USB_VID 0xFE60
970#define REG_USB_PID 0xFE62
971#define REG_USB_OPTIONAL 0xFE64
972#define REG_USB_CHIRP_K 0xFE65
973#define REG_USB_PHY 0xFE66
974#define REG_USB_MAC_ADDR 0xFE70
975
976#define REG_USB_HRPWM 0xFE58
977#define REG_USB_HCPWM 0xFE57
978
979#define InvalidBBRFValue 0x12345678
980
981/* */
982/* 8192C Regsiter Bit and Content definition */
983/* */
984/* */
985/* */
986/* 0x0000h ~ 0x00FFh System Configuration */
987/* */
988/* */
989
990/* 2 SPS0_CTRL */
991#define SW18_FPWM BIT(3)
992
993
994/* 2 SYS_ISO_CTRL */
995#define ISO_MD2PP BIT(0)
996#define ISO_UA2USB BIT(1)
997#define ISO_UD2CORE BIT(2)
998#define ISO_PA2PCIE BIT(3)
999#define ISO_PD2CORE BIT(4)
1000#define ISO_IP2MAC BIT(5)
1001#define ISO_DIOP BIT(6)
1002#define ISO_DIOE BIT(7)
1003#define ISO_EB2CORE BIT(8)
1004#define ISO_DIOR BIT(9)
1005
1006#define PWC_EV25V BIT(14)
1007#define PWC_EV12V BIT(15)
1008
1009
1010/* 2 SYS_FUNC_EN */
1011#define FEN_BBRSTB BIT(0)
1012#define FEN_BB_GLB_RSTn BIT(1)
1013#define FEN_USBA BIT(2)
1014#define FEN_UPLL BIT(3)
1015#define FEN_USBD BIT(4)
1016#define FEN_DIO_PCIE BIT(5)
1017#define FEN_PCIEA BIT(6)
1018#define FEN_PPLL BIT(7)
1019#define FEN_PCIED BIT(8)
1020#define FEN_DIOE BIT(9)
1021#define FEN_CPUEN BIT(10)
1022#define FEN_DCORE BIT(11)
1023#define FEN_ELDR BIT(12)
1024#define FEN_DIO_RF BIT(13)
1025#define FEN_HWPDN BIT(14)
1026#define FEN_MREGEN BIT(15)
1027
1028/* 2 APS_FSMCO */
1029#define PFM_LDALL BIT(0)
1030#define PFM_ALDN BIT(1)
1031#define PFM_LDKP BIT(2)
1032#define PFM_WOWL BIT(3)
1033#define EnPDN BIT(4)
1034#define PDN_PL BIT(5)
1035#define APFM_ONMAC BIT(8)
1036#define APFM_OFF BIT(9)
1037#define APFM_RSM BIT(10)
1038#define AFSM_HSUS BIT(11)
1039#define AFSM_PCIE BIT(12)
1040#define APDM_MAC BIT(13)
1041#define APDM_HOST BIT(14)
1042#define APDM_HPDN BIT(15)
1043#define RDY_MACON BIT(16)
1044#define SUS_HOST BIT(17)
1045#define ROP_ALD BIT(20)
1046#define ROP_PWR BIT(21)
1047#define ROP_SPS BIT(22)
1048#define SOP_MRST BIT(25)
1049#define SOP_FUSE BIT(26)
1050#define SOP_ABG BIT(27)
1051#define SOP_AMB BIT(28)
1052#define SOP_RCK BIT(29)
1053#define SOP_A8M BIT(30)
1054#define XOP_BTCK BIT(31)
1055
1056/* 2 SYS_CLKR */
1057#define ANAD16V_EN BIT(0)
1058#define ANA8M BIT(1)
1059#define MACSLP BIT(4)
1060#define LOADER_CLK_EN BIT(5)
1061#define _80M_SSC_DIS BIT(7)
1062#define _80M_SSC_EN_HO BIT(8)
1063#define PHY_SSC_RSTB BIT(9)
1064#define SEC_CLK_EN BIT(10)
1065#define MAC_CLK_EN BIT(11)
1066#define SYS_CLK_EN BIT(12)
1067#define RING_CLK_EN BIT(13)
1068
1069
1070/* 2 9346CR */
1071
1072
1073#define EEDO BIT(0)
1074#define EEDI BIT(1)
1075#define EESK BIT(2)
1076#define EECS BIT(3)
1077/* define EERPROMSEL BIT(4) */
1078/* define EEPROM_EN BIT(5) */
1079#define BOOT_FROM_EEPROM BIT(4)
1080#define EEPROM_EN BIT(5)
1081#define EEM0 BIT(6)
1082#define EEM1 BIT(7)
1083
1084
1085/* 2 AFE_MISC */
1086#define AFE_BGEN BIT(0)
1087#define AFE_MBEN BIT(1)
1088#define MAC_ID_EN BIT(7)
1089
1090
1091/* 2 SPS0_CTRL */
1092
1093
1094/* 2 SPS_OCP_CFG */
1095
1096
1097/* 2 RSV_CTRL */
1098#define WLOCK_ALL BIT(0)
1099#define WLOCK_00 BIT(1)
1100#define WLOCK_04 BIT(2)
1101#define WLOCK_08 BIT(3)
1102#define WLOCK_40 BIT(4)
1103#define R_DIS_PRST_0 BIT(5)
1104#define R_DIS_PRST_1 BIT(6)
1105#define LOCK_ALL_EN BIT(7)
1106
1107/* 2 RF_CTRL */
1108#define RF_EN BIT(0)
1109#define RF_RSTB BIT(1)
1110#define RF_SDMRSTB BIT(2)
1111
1112
1113
1114/* 2 LDOA15_CTRL */
1115#define LDA15_EN BIT(0)
1116#define LDA15_STBY BIT(1)
1117#define LDA15_OBUF BIT(2)
1118#define LDA15_REG_VOS BIT(3)
1119#define _LDA15_VOADJ(x) (((x) & 0x7) << 4)
1120
1121
1122
1123/* 2 LDOV12D_CTRL */
1124#define LDV12_EN BIT(0)
1125#define LDV12_SDBY BIT(1)
1126#define LPLDO_HSM BIT(2)
1127#define LPLDO_LSM_DIS BIT(3)
1128#define _LDV12_VADJ(x) (((x) & 0xF) << 4)
1129
1130
1131/* 2 AFE_XTAL_CTRL */
1132#define XTAL_EN BIT(0)
1133#define XTAL_BSEL BIT(1)
1134#define _XTAL_BOSC(x) (((x) & 0x3) << 2)
1135#define _XTAL_CADJ(x) (((x) & 0xF) << 4)
1136#define XTAL_GATE_USB BIT(8)
1137#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9)
1138#define XTAL_GATE_AFE BIT(11)
1139#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12)
1140#define XTAL_RF_GATE BIT(14)
1141#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15)
1142#define XTAL_GATE_DIG BIT(17)
1143#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18)
1144#define XTAL_BT_GATE BIT(20)
1145#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21)
1146#define _XTAL_GPIO(x) (((x) & 0x7) << 23)
1147
1148
1149#define CKDLY_AFE BIT(26)
1150#define CKDLY_USB BIT(27)
1151#define CKDLY_DIG BIT(28)
1152#define CKDLY_BT BIT(29)
1153
1154
1155/* 2 AFE_PLL_CTRL */
1156#define APLL_EN BIT(0)
1157#define APLL_320_EN BIT(1)
1158#define APLL_FREF_SEL BIT(2)
1159#define APLL_EDGE_SEL BIT(3)
1160#define APLL_WDOGB BIT(4)
1161#define APLL_LPFEN BIT(5)
1162
1163#define APLL_REF_CLK_13MHZ 0x1
1164#define APLL_REF_CLK_19_2MHZ 0x2
1165#define APLL_REF_CLK_20MHZ 0x3
1166#define APLL_REF_CLK_25MHZ 0x4
1167#define APLL_REF_CLK_26MHZ 0x5
1168#define APLL_REF_CLK_38_4MHZ 0x6
1169#define APLL_REF_CLK_40MHZ 0x7
1170
1171#define APLL_320EN BIT(14)
1172#define APLL_80EN BIT(15)
1173#define APLL_1MEN BIT(24)
1174
1175
1176/* 2 EFUSE_CTRL */
1177#define ALD_EN BIT(18)
1178#define EF_PD BIT(19)
1179#define EF_FLAG BIT(31)
1180
1181/* 2 EFUSE_TEST (For RTL8723 partially) */
1182#define EF_TRPT BIT(7)
1183 /* 00: Wifi Efuse, 01: BT Efuse0, 10: BT Efuse1, 11: BT Efuse2 */
1184#define EF_CELL_SEL (BIT(8)|BIT(9))
1185#define LDOE25_EN BIT(31)
1186#define EFUSE_SEL(x) (((x) & 0x3) << 8)
1187#define EFUSE_SEL_MASK 0x300
1188#define EFUSE_WIFI_SEL_0 0x0
1189#define EFUSE_BT_SEL_0 0x1
1190#define EFUSE_BT_SEL_1 0x2
1191#define EFUSE_BT_SEL_2 0x3
1192
1193#define EFUSE_ACCESS_ON 0x69 /* For RTL8723 only. */
1194#define EFUSE_ACCESS_OFF 0x00 /* For RTL8723 only. */
1195
1196/* 2 PWR_DATA */
1197
1198/* 2 CAL_TIMER */
1199
1200/* 2 ACLK_MON */
1201#define RSM_EN BIT(0)
1202#define Timer_EN BIT(4)
1203
1204
1205/* 2 GPIO_MUXCFG */
1206#define TRSW0EN BIT(2)
1207#define TRSW1EN BIT(3)
1208#define EROM_EN BIT(4)
1209#define EnBT BIT(5)
1210#define EnUart BIT(8)
1211#define Uart_910 BIT(9)
1212#define EnPMAC BIT(10)
1213#define SIC_SWRST BIT(11)
1214#define EnSIC BIT(12)
1215#define SIC_23 BIT(13)
1216#define EnHDP BIT(14)
1217#define SIC_LBK BIT(15)
1218
1219/* 2 GPIO_PIN_CTRL */
1220
1221/* GPIO BIT */
1222#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2)
1223
1224/* 2 GPIO_INTM */
1225
1226/* 2 LEDCFG */
1227#define LED0PL BIT(4)
1228#define LED0DIS BIT(7)
1229#define LED1DIS BIT(15)
1230#define LED1PL BIT(12)
1231
1232#define SECCAM_CLR BIT(30)
1233
1234
1235/* 2 FSIMR */
1236
1237/* 2 FSISR */
1238
1239
1240/* 2 8051FWDL */
1241/* 2 MCUFWDL */
1242#define MCUFWDL_EN BIT(0)
1243#define MCUFWDL_RDY BIT(1)
1244#define FWDL_ChkSum_rpt BIT(2)
1245#define MACINI_RDY BIT(3)
1246#define BBINI_RDY BIT(4)
1247#define RFINI_RDY BIT(5)
1248#define WINTINI_RDY BIT(6)
1249#define CPRST BIT(23)
1250
1251/* 2REG_HPON_FSM */
1252#define BOND92CE_1T2R_CFG BIT(22)
1253
1254
1255/* 2 REG_SYS_CFG */
1256#define XCLK_VLD BIT(0)
1257#define ACLK_VLD BIT(1)
1258#define UCLK_VLD BIT(2)
1259#define PCLK_VLD BIT(3)
1260#define PCIRSTB BIT(4)
1261#define V15_VLD BIT(5)
1262#define TRP_B15V_EN BIT(7)
1263#define SIC_IDLE BIT(8)
1264#define BD_MAC2 BIT(9)
1265#define BD_MAC1 BIT(10)
1266#define IC_MACPHY_MODE BIT(11)
1267#define CHIP_VER (BIT(12)|BIT(13)|BIT(14)|BIT(15))
1268#define BT_FUNC BIT(16)
1269#define VENDOR_ID BIT(19)
1270#define PAD_HWPD_IDN BIT(22)
1271#define TRP_VAUX_EN BIT(23)
1272#define TRP_BT_EN BIT(24)
1273#define BD_PKG_SEL BIT(25)
1274#define BD_HCI_SEL BIT(26)
1275#define TYPE_ID BIT(27)
1276
1277#define CHIP_VER_RTL_MASK 0xF000 /* Bit 12 ~ 15 */
1278#define CHIP_VER_RTL_SHIFT 12
1279
1280/* 2REG_GPIO_OUTSTS (For RTL8723 only) */
1281#define EFS_HCI_SEL (BIT(0)|BIT(1))
1282#define PAD_HCI_SEL (BIT(2)|BIT(3))
1283#define HCI_SEL (BIT(4)|BIT(5))
1284#define PKG_SEL_HCI BIT(6)
1285#define FEN_GPS BIT(7)
1286#define FEN_BT BIT(8)
1287#define FEN_WL BIT(9)
1288#define FEN_PCI BIT(10)
1289#define FEN_USB BIT(11)
1290#define BTRF_HWPDN_N BIT(12)
1291#define WLRF_HWPDN_N BIT(13)
1292#define PDN_BT_N BIT(14)
1293#define PDN_GPS_N BIT(15)
1294#define BT_CTL_HWPDN BIT(16)
1295#define GPS_CTL_HWPDN BIT(17)
1296#define PPHY_SUSB BIT(20)
1297#define UPHY_SUSB BIT(21)
1298#define PCI_SUSEN BIT(22)
1299#define USB_SUSEN BIT(23)
1300#define RF_RL_ID (BIT(31)|BIT(30)|BIT(29)|BIT(28))
1301
1302/* */
1303/* */
1304/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
1305/* */
1306/* */
1307
1308
1309/* 2 Function Enable Registers */
1310/* 2 CR */
1311
1312#define REG_LBMODE (REG_CR + 3)
1313
1314
1315#define HCI_TXDMA_EN BIT(0)
1316#define HCI_RXDMA_EN BIT(1)
1317#define TXDMA_EN BIT(2)
1318#define RXDMA_EN BIT(3)
1319#define PROTOCOL_EN BIT(4)
1320#define SCHEDULE_EN BIT(5)
1321#define MACTXEN BIT(6)
1322#define MACRXEN BIT(7)
1323#define ENSWBCN BIT(8)
1324#define ENSEC BIT(9)
1325
1326/* Network type */
1327#define _NETTYPE(x) (((x) & 0x3) << 16)
1328#define MASK_NETTYPE 0x30000
1329#define NT_NO_LINK 0x0
1330#define NT_LINK_AD_HOC 0x1
1331#define NT_LINK_AP 0x2
1332#define NT_AS_AP 0x3
1333
1334#define _LBMODE(x) (((x) & 0xF) << 24)
1335#define MASK_LBMODE 0xF000000
1336#define LOOPBACK_NORMAL 0x0
1337#define LOOPBACK_IMMEDIATELY 0xB
1338#define LOOPBACK_MAC_DELAY 0x3
1339#define LOOPBACK_PHY 0x1
1340#define LOOPBACK_DMA 0x7
1341
1342
1343/* 2 PBP - Page Size Register */
1344#define GET_RX_PAGE_SIZE(value) ((value) & 0xF)
1345#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4)
1346#define _PSRX_MASK 0xF
1347#define _PSTX_MASK 0xF0
1348#define _PSRX(x) (x)
1349#define _PSTX(x) ((x) << 4)
1350
1351#define PBP_64 0x0
1352#define PBP_128 0x1
1353#define PBP_256 0x2
1354#define PBP_512 0x3
1355#define PBP_1024 0x4
1356
1357
1358/* 2 TX/RXDMA */
1359#define RXDMA_ARBBW_EN BIT(0)
1360#define RXSHFT_EN BIT(1)
1361#define RXDMA_AGG_EN BIT(2)
1362#define QS_VO_QUEUE BIT(8)
1363#define QS_VI_QUEUE BIT(9)
1364#define QS_BE_QUEUE BIT(10)
1365#define QS_BK_QUEUE BIT(11)
1366#define QS_MANAGER_QUEUE BIT(12)
1367#define QS_HIGH_QUEUE BIT(13)
1368
1369#define HQSEL_VOQ BIT(0)
1370#define HQSEL_VIQ BIT(1)
1371#define HQSEL_BEQ BIT(2)
1372#define HQSEL_BKQ BIT(3)
1373#define HQSEL_MGTQ BIT(4)
1374#define HQSEL_HIQ BIT(5)
1375
1376/* For normal driver, 0x10C */
1377#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14)
1378#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12)
1379#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10)
1380#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8 )
1381#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6 )
1382#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4 )
1383
1384#define QUEUE_LOW 1
1385#define QUEUE_NORMAL 2
1386#define QUEUE_HIGH 3
1387
1388
1389
1390/* 2 TRXFF_BNDY */
1391
1392
1393/* 2 LLT_INIT */
1394#define _LLT_NO_ACTIVE 0x0
1395#define _LLT_WRITE_ACCESS 0x1
1396#define _LLT_READ_ACCESS 0x2
1397
1398#define _LLT_INIT_DATA(x) ((x) & 0xFF)
1399#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8)
1400#define _LLT_OP(x) (((x) & 0x3) << 30)
1401#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3)
1402
1403
1404/* 2 BB_ACCESS_CTRL */
1405#define BB_WRITE_READ_MASK (BIT(31) | BIT(30))
1406#define BB_WRITE_EN BIT(30)
1407#define BB_READ_EN BIT(31)
1408/* define BB_ADDR_MASK 0xFFF */
1409/* define _BB_ADDR(x) ((x) & BB_ADDR_MASK) */
1410
1411/* */
1412/* */
1413/* 0x0200h ~ 0x027Fh TXDMA Configuration */
1414/* */
1415/* */
1416/* 2 RQPN */
1417#define _HPQ(x) ((x) & 0xFF)
1418#define _LPQ(x) (((x) & 0xFF) << 8)
1419#define _PUBQ(x) (((x) & 0xFF) << 16)
1420 /* NOTE: in RQPN_NPQ register */
1421#define _NPQ(x) ((x) & 0xFF)
1422
1423
1424#define HPQ_PUBLIC_DIS BIT(24)
1425#define LPQ_PUBLIC_DIS BIT(25)
1426#define LD_RQPN BIT(31)
1427
1428
1429/* 2 TDECTRL */
1430#define BCN_VALID BIT(16)
1431#define BCN_HEAD(x) (((x) & 0xFF) << 8)
1432#define BCN_HEAD_MASK 0xFF00
1433
1434/* 2 TDECTL */
1435#define BLK_DESC_NUM_SHIFT 4
1436#define BLK_DESC_NUM_MASK 0xF
1437
1438
1439/* 2 TXDMA_OFFSET_CHK */
1440#define DROP_DATA_EN BIT(9)
1441
1442/* */
1443/* */
1444/* 0x0400h ~ 0x047Fh Protocol Configuration */
1445/* */
1446/* */
1447/* 2 FWHW_TXQ_CTRL */
1448#define EN_AMPDU_RTY_NEW BIT(7)
1449
1450/* 2 INIRTSMCS_SEL */
1451#define _INIRTSMCS_SEL(x) ((x) & 0x3F)
1452
1453
1454/* 2 SPEC SIFS */
1455#define _SPEC_SIFS_CCK(x) ((x) & 0xFF)
1456#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8)
1457
1458
1459/* 2 RRSR */
1460
1461#define RATE_REG_BITMAP_ALL 0xFFFFF
1462
1463#define _RRSC_BITMAP(x) ((x) & 0xFFFFF)
1464
1465#define _RRSR_RSC(x) (((x) & 0x3) << 21)
1466#define RRSR_RSC_RESERVED 0x0
1467#define RRSR_RSC_UPPER_SUBCHANNEL 0x1
1468#define RRSR_RSC_LOWER_SUBCHANNEL 0x2
1469#define RRSR_RSC_DUPLICATE_MODE 0x3
1470
1471
1472/* 2 ARFR */
1473#define USE_SHORT_G1 BIT(20)
1474
1475/* 2 AGGLEN_LMT_L */
1476#define _AGGLMT_MCS0(x) ((x) & 0xF)
1477#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4)
1478#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8)
1479#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12)
1480#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16)
1481#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20)
1482#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24)
1483#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28)
1484
1485
1486/* 2 RL */
1487#define RETRY_LIMIT_SHORT_SHIFT 8
1488#define RETRY_LIMIT_LONG_SHIFT 0
1489
1490
1491/* 2 DARFRC */
1492#define _DARF_RC1(x) ((x) & 0x1F)
1493#define _DARF_RC2(x) (((x) & 0x1F) << 8)
1494#define _DARF_RC3(x) (((x) & 0x1F) << 16)
1495#define _DARF_RC4(x) (((x) & 0x1F) << 24)
1496/* NOTE: shift starting from address (DARFRC + 4) */
1497#define _DARF_RC5(x) ((x) & 0x1F)
1498#define _DARF_RC6(x) (((x) & 0x1F) << 8)
1499#define _DARF_RC7(x) (((x) & 0x1F) << 16)
1500#define _DARF_RC8(x) (((x) & 0x1F) << 24)
1501
1502
1503/* 2 RARFRC */
1504#define _RARF_RC1(x) ((x) & 0x1F)
1505#define _RARF_RC2(x) (((x) & 0x1F) << 8)
1506#define _RARF_RC3(x) (((x) & 0x1F) << 16)
1507#define _RARF_RC4(x) (((x) & 0x1F) << 24)
1508/* NOTE: shift starting from address (RARFRC + 4) */
1509#define _RARF_RC5(x) ((x) & 0x1F)
1510#define _RARF_RC6(x) (((x) & 0x1F) << 8)
1511#define _RARF_RC7(x) (((x) & 0x1F) << 16)
1512#define _RARF_RC8(x) (((x) & 0x1F) << 24)
1513
1514
1515/* */
1516/* */
1517/* 0x0500h ~ 0x05FFh EDCA Configuration */
1518/* */
1519/* */
1520
1521
1522
1523/* 2 EDCA setting */
1524#define AC_PARAM_TXOP_LIMIT_OFFSET 16
1525#define AC_PARAM_ECW_MAX_OFFSET 12
1526#define AC_PARAM_ECW_MIN_OFFSET 8
1527#define AC_PARAM_AIFS_OFFSET 0
1528
1529
1530/* 2 EDCA_VO_PARAM */
1531#define _AIFS(x) (x)
1532#define _ECW_MAX_MIN(x) ((x) << 8)
1533#define _TXOP_LIMIT(x) ((x) << 16)
1534
1535
1536#define _BCNIFS(x) ((x) & 0xFF)
1537#define _BCNECW(x) (((x) & 0xF))<< 8)
1538
1539
1540#define _LRL(x) ((x) & 0x3F)
1541#define _SRL(x) (((x) & 0x3F) << 8)
1542
1543
1544/* 2 SIFS_CCK */
1545#define _SIFS_CCK_CTX(x) ((x) & 0xFF)
1546#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8);
1547
1548
1549/* 2 SIFS_OFDM */
1550#define _SIFS_OFDM_CTX(x) ((x) & 0xFF)
1551#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8);
1552
1553
1554/* 2 TBTT PROHIBIT */
1555#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8)
1556
1557
1558/* 2 REG_RD_CTRL */
1559#define DIS_EDCA_CNT_DWN BIT(11)
1560
1561
1562/* 2 BCN_CTRL */
1563#define EN_MBSSID BIT(1)
1564#define EN_TXBCN_RPT BIT(2)
1565#define EN_BCN_FUNCTION BIT(3)
1566#define DIS_TSF_UPDATE BIT(3)
1567
1568/* The same function but different bit field. */
1569#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4)
1570#define DIS_TSF_UDT0_TEST_CHIP BIT(5)
1571
1572/* 2 ACMHWCTRL */
1573#define AcmHw_HwEn BIT(0)
1574#define AcmHw_BeqEn BIT(1)
1575#define AcmHw_ViqEn BIT(2)
1576#define AcmHw_VoqEn BIT(3)
1577#define AcmHw_BeqStatus BIT(4)
1578#define AcmHw_ViqStatus BIT(5)
1579#define AcmHw_VoqStatus BIT(6)
1580
1581
1582
1583/* */
1584/* */
1585/* 0x0600h ~ 0x07FFh WMAC Configuration */
1586/* */
1587/* */
1588
1589/* 2 APSD_CTRL */
1590#define APSDOFF BIT(6)
1591#define APSDOFF_STATUS BIT(7)
1592
1593
1594/* 2 BWOPMODE */
1595#define BW_20MHZ BIT(2)
1596
1597
1598#define RATE_BITMAP_ALL 0xFFFFF
1599
1600/* Only use CCK 1M rate for ACK */
1601#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1
1602
1603/* 2 TCR */
1604#define TSFRST BIT(0)
1605#define DIS_GCLK BIT(1)
1606#define PAD_SEL BIT(2)
1607#define PWR_ST BIT(6)
1608#define PWRBIT_OW_EN BIT(7)
1609#define ACRC BIT(8)
1610#define CFENDFORM BIT(9)
1611#define ICV BIT(10)
1612
1613
1614
1615/* 2 RCR */
1616#define AAP BIT(0)
1617#define APM BIT(1)
1618#define AM BIT(2)
1619#define AB BIT(3)
1620#define ADD3 BIT(4)
1621#define APWRMGT BIT(5)
1622#define CBSSID BIT(6)
1623#define CBSSID_BCN BIT(7)
1624#define ACRC32 BIT(8)
1625#define AICV BIT(9)
1626#define ADF BIT(11)
1627#define ACF BIT(12)
1628#define AMF BIT(13)
1629#define HTC_LOC_CTRL BIT(14)
1630#define UC_DATA_EN BIT(16)
1631#define BM_DATA_EN BIT(17)
1632#define MFBEN BIT(22)
1633#define LSIGEN BIT(23)
1634#define EnMBID BIT(24)
1635#define APP_BASSN BIT(27)
1636#define APP_PHYSTS BIT(28)
1637#define APP_ICV BIT(29)
1638#define APP_MIC BIT(30)
1639#define APP_FCS BIT(31)
1640
1641/* 2 RX_PKT_LIMIT */
1642
1643/* 2 RX_DLK_TIME */
1644
1645/* 2 MBIDCAMCFG */
1646
1647
1648
1649/* 2 AMPDU_MIN_SPACE */
1650#define _MIN_SPACE(x) ((x) & 0x7)
1651#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3)
1652
1653
1654/* 2 RXERR_RPT */
1655#define RXERR_TYPE_OFDM_PPDU 0
1656#define RXERR_TYPE_OFDMfalse_ALARM 1
1657#define RXERR_TYPE_OFDM_MPDU_OK 2
1658#define RXERR_TYPE_OFDM_MPDU_FAIL 3
1659#define RXERR_TYPE_CCK_PPDU 4
1660#define RXERR_TYPE_CCKfalse_ALARM 5
1661#define RXERR_TYPE_CCK_MPDU_OK 6
1662#define RXERR_TYPE_CCK_MPDU_FAIL 7
1663#define RXERR_TYPE_HT_PPDU 8
1664#define RXERR_TYPE_HTfalse_ALARM 9
1665#define RXERR_TYPE_HT_MPDU_TOTAL 10
1666#define RXERR_TYPE_HT_MPDU_OK 11
1667#define RXERR_TYPE_HT_MPDU_FAIL 12
1668#define RXERR_TYPE_RX_FULL_DROP 15
1669
1670#define RXERR_COUNTER_MASK 0xFFFFF
1671#define RXERR_RPT_RST BIT(27)
1672#define _RXERR_RPT_SEL(type) ((type) << 28)
1673
1674
1675/* 2 SECCFG */
1676#define SCR_TxUseDK BIT(0) /* Force Tx Use Default Key */
1677#define SCR_RxUseDK BIT(1) /* Force Rx Use Default Key */
1678#define SCR_TxEncEnable BIT(2) /* Enable Tx Encryption */
1679#define SCR_RxDecEnable BIT(3) /* Enable Rx Decryption */
1680#define SCR_SKByA2 BIT(4) /* Search kEY BY A2 */
1681#define SCR_NoSKMC BIT(5) /* No Key Search Multicast */
1682
1683
1684
1685/* */
1686/* */
1687/* 0xFE00h ~ 0xFE55h USB Configuration */
1688/* */
1689/* */
1690
1691/* 2 USB Information (0xFE17) */
1692#define USB_IS_HIGH_SPEED 0
1693#define USB_IS_FULL_SPEED 1
1694#define USB_SPEED_MASK BIT(5)
1695
1696#define USB_NORMAL_SIE_EP_MASK 0xF
1697#define USB_NORMAL_SIE_EP_SHIFT 4
1698
1699#define USB_TEST_EP_MASK 0x30
1700#define USB_TEST_EP_SHIFT 4
1701
1702/* 2 Special Option */
1703#define USB_AGG_EN BIT(3)
1704
1705
1706/* 2REG_C2HEVT_CLEAR */
1707 /* Set by driver and notify FW that the driver has read the
1708 C2H command message */
1709#define C2H_EVT_HOST_CLOSE 0x00
1710 /* Set by FW indicating that FW had set the C2H command message
1711 and it's not yet read by driver. */
1712#define C2H_EVT_FW_CLOSE 0xFF
1713
1714
1715/* 2REG_MULTI_FUNC_CTRL(For RTL8723 Only) */
1716 /* Enable GPIO[9] as WiFi HW PDn source */
1717#define WL_HWPDN_EN BIT0
1718 /* WiFi HW PDn polarity control */
1719#define WL_HWPDN_SL BIT1
1720 /* WiFi function enable */
1721#define WL_FUNC_EN BIT2
1722 /* Enable GPIO[9] as WiFi RF HW PDn source */
1723#define WL_HWROF_EN BIT3
1724 /* Enable GPIO[11] as BT HW PDn source */
1725#define BT_HWPDN_EN BIT16
1726 /* BT HW PDn polarity control */
1727#define BT_HWPDN_SL BIT17
1728 /* BT function enable */
1729#define BT_FUNC_EN BIT18
1730 /* Enable GPIO[11] as BT/GPS RF HW PDn source */
1731#define BT_HWROF_EN BIT19
1732 /* Enable GPIO[10] as GPS HW PDn source */
1733#define GPS_HWPDN_EN BIT20
1734 /* GPS HW PDn polarity control */
1735#define GPS_HWPDN_SL BIT21
1736 /* GPS function enable */
1737#define GPS_FUNC_EN BIT22
1738
1739/* 3 REG_LIFECTRL_CTRL */
1740#define HAL92C_EN_PKT_LIFE_TIME_BK BIT3
1741#define HAL92C_EN_PKT_LIFE_TIME_BE BIT2
1742#define HAL92C_EN_PKT_LIFE_TIME_VI BIT1
1743#define HAL92C_EN_PKT_LIFE_TIME_VO BIT0
1744
1745#define HAL92C_MSDU_LIFE_TIME_UNIT 128 /* in us, said by Tim. */
1746
1747/* */
1748/* General definitions */
1749/* */
1750
1751#define LAST_ENTRY_OF_TX_PKT_BUFFER 255
1752
1753#define POLLING_LLT_THRESHOLD 20
1754#define POLLING_READY_TIMEOUT_COUNT 1000
1755
1756/* Min Spacing related settings. */
1757#define MAX_MSS_DENSITY_2T 0x13
1758#define MAX_MSS_DENSITY_1T 0x0A
1759
1760/* */
1761/* 8723A Regsiter offset definition */
1762/* */
1763#define HAL_8723A_NAV_UPPER_UNIT 128 /* micro-second */
1764
1765/* */
1766/* */
1767/* 0x0000h ~ 0x00FFh System Configuration */
1768/* */
1769/* */
1770#define REG_SYSON_REG_LOCK 0x001C
1771
1772
1773/* */
1774/* */
1775/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
1776/* */
1777/* */
1778#define REG_FTIMR 0x0138
1779
1780
1781/* */
1782/* */
1783/* 0x0200h ~ 0x027Fh TXDMA Configuration */
1784/* */
1785/* */
1786
1787
1788/* */
1789/* */
1790/* 0x0280h ~ 0x02FFh RXDMA Configuration */
1791/* */
1792/* */
1793
1794
1795/* */
1796/* */
1797/* 0x0300h ~ 0x03FFh PCIe */
1798/* */
1799/* */
1800
1801
1802/* */
1803/* */
1804/* 0x0400h ~ 0x047Fh Protocol Configuration */
1805/* */
1806/* */
1807#define REG_EARLY_MODE_CONTROL 0x4D0
1808
1809
1810/* */
1811/* */
1812/* 0x0500h ~ 0x05FFh EDCA Configuration */
1813/* */
1814/* */
1815
1816/* 2 BCN_CTRL */
1817#define DIS_ATIM BIT(0)
1818#define DIS_BCNQ_SUB BIT(1)
1819#define DIS_TSF_UDT BIT(4)
1820
1821
1822/* */
1823/* */
1824/* 0x0600h ~ 0x07FFh WMAC Configuration */
1825/* */
1826/* */
1827/* */
1828/* Note: */
1829/* The NAV upper value is very important to WiFi 11n 5.2.3 NAV test.
1830 * The default value is always too small, but the WiFi TestPlan test
1831 * by 25,000 microseconds of NAV through sending CTS in the air. We
1832 * must update this value greater than 25,000 microseconds to pass the
1833 * item.
1834* The offset of NAV_UPPER in 8192C Spec is incorrect, and the offset
1835* should be 0x0652. Commented by SD1 Scott. */
1836/* By Bruce, 2011-07-18. */
1837/* */
1838#define REG_NAV_UPPER 0x0652 /* unit of 128 */
1839
1840
1841/* */
1842/* 8723 Regsiter Bit and Content definition */
1843/* */
1844
1845/* */
1846/* */
1847/* 0x0000h ~ 0x00FFh System Configuration */
1848/* */
1849/* */
1850
1851/* 2 SPS0_CTRL */
1852
1853/* 2 SYS_ISO_CTRL */
1854
1855/* 2 SYS_FUNC_EN */
1856
1857/* 2 APS_FSMCO */
1858#define EN_WLON BIT(16)
1859
1860/* 2 SYS_CLKR */
1861
1862/* 2 9346CR */
1863
1864/* 2 AFE_MISC */
1865
1866/* 2 SPS0_CTRL */
1867
1868/* 2 SPS_OCP_CFG */
1869
1870/* 2 SYSON_REG_LOCK */
1871#define WLOCK_ALL BIT(0)
1872#define WLOCK_00 BIT(1)
1873#define WLOCK_04 BIT(2)
1874#define WLOCK_08 BIT(3)
1875#define WLOCK_40 BIT(4)
1876#define WLOCK_1C_B6 BIT(5)
1877#define R_DIS_PRST_1 BIT(6)
1878#define LOCK_ALL_EN BIT(7)
1879
1880/* 2 RF_CTRL */
1881
1882/* 2 LDOA15_CTRL */
1883
1884/* 2 LDOV12D_CTRL */
1885
1886/* 2 AFE_XTAL_CTRL */
1887
1888/* 2 AFE_PLL_CTRL */
1889
1890/* 2 EFUSE_CTRL */
1891
1892/* 2 EFUSE_TEST (For RTL8723 partially) */
1893
1894/* 2 PWR_DATA */
1895
1896/* 2 CAL_TIMER */
1897
1898/* 2 ACLK_MON */
1899
1900/* 2 GPIO_MUXCFG */
1901
1902/* 2 GPIO_PIN_CTRL */
1903
1904/* 2 GPIO_INTM */
1905
1906/* 2 LEDCFG */
1907
1908/* 2 FSIMR */
1909
1910/* 2 FSISR */
1911
1912/* 2 HSIMR */
1913/* 8723 Host System Interrupt Mask Register (offset 0x58, 32 byte) */
1914#define HSIMR_GPIO12_0_INT_EN BIT(0)
1915#define HSIMR_SPS_OCP_INT_EN BIT(5)
1916#define HSIMR_RON_INT_EN BIT(6)
1917#define HSIMR_PDNINT_EN BIT(7)
1918#define HSIMR_GPIO9_INT_EN BIT(25)
1919
1920/* 2 HSISR */
1921/* 8723 Host System Interrupt Status Register (offset 0x5C, 32 byte) */
1922#define HSISR_GPIO12_0_INT BIT(0)
1923#define HSISR_SPS_OCP_INT BIT(5)
1924#define HSISR_RON_INT BIT(6)
1925#define HSISR_PDNINT BIT(7)
1926#define HSISR_GPIO9_INT BIT(25)
1927
1928/* interrupt mask which needs to clear */
1929#define MASK_HSISR_CLEAR (HSISR_GPIO12_0_INT | \
1930 HSISR_SPS_OCP_INT | \
1931 HSISR_RON_INT | \
1932 HSISR_PDNINT | \
1933 HSISR_GPIO9_INT)
1934
1935/* 2 MCUFWDL */
1936#define RAM_DL_SEL BIT7 /* 1:RAM, 0:ROM */
1937
1938/* 2 HPON_FSM */
1939
1940/* 2 SYS_CFG */
1941#define RTL_ID BIT(23) /* TestChip ID,
1942 1:Test(RLE); 0:MP(RL) */
1943#define SPS_SEL BIT(24) /* 1:LDO regulator mode;
1944 0:Switching regulator mode*/
1945
1946
1947/* */
1948/* */
1949/* 0x0100h ~ 0x01FFh MACTOP General Configuration */
1950/* */
1951/* */
1952
1953/* 2 Function Enable Registers */
1954
1955/* 2 CR */
1956#define CALTMR_EN BIT(10)
1957
1958/* 2 PBP - Page Size Register */
1959
1960/* 2 TX/RXDMA */
1961
1962/* 2 TRXFF_BNDY */
1963
1964/* 2 LLT_INIT */
1965
1966/* 2 BB_ACCESS_CTRL */
1967
1968
1969/* */
1970/* */
1971/* 0x0200h ~ 0x027Fh TXDMA Configuration */
1972/* */
1973/* */
1974
1975/* 2 RQPN */
1976
1977/* 2 TDECTRL */
1978
1979/* 2 TDECTL */
1980
1981/* 2 TXDMA_OFFSET_CHK */
1982
1983
1984/* */
1985/* */
1986/* 0x0400h ~ 0x047Fh Protocol Configuration */
1987/* */
1988/* */
1989
1990/* 2 FWHW_TXQ_CTRL */
1991
1992/* 2 INIRTSMCS_SEL */
1993
1994/* 2 SPEC SIFS */
1995
1996/* 2 RRSR */
1997
1998/* 2 ARFR */
1999
2000/* 2 AGGLEN_LMT_L */
2001
2002/* 2 RL */
2003
2004/* 2 DARFRC */
2005
2006/* 2 RARFRC */
2007
2008
2009/* */
2010/* */
2011/* 0x0500h ~ 0x05FFh EDCA Configuration */
2012/* */
2013/* */
2014
2015/* 2 EDCA setting */
2016
2017/* 2 EDCA_VO_PARAM */
2018
2019/* 2 SIFS_CCK */
2020
2021/* 2 SIFS_OFDM */
2022
2023/* 2 TBTT PROHIBIT */
2024
2025/* 2 REG_RD_CTRL */
2026
2027/* 2 BCN_CTRL */
2028
2029/* 2 ACMHWCTRL */
2030
2031
2032/* */
2033/* */
2034/* 0x0600h ~ 0x07FFh WMAC Configuration */
2035/* */
2036/* */
2037
2038/* 2 APSD_CTRL */
2039
2040/* 2 BWOPMODE */
2041
2042/* 2 TCR */
2043
2044/* 2 RCR */
2045
2046/* 2 RX_PKT_LIMIT */
2047
2048/* 2 RX_DLK_TIME */
2049
2050/* 2 MBIDCAMCFG */
2051
2052/* 2 AMPDU_MIN_SPACE */
2053
2054/* 2 RXERR_RPT */
2055
2056/* 2 SECCFG */
2057
2058
2059/* */
2060/* */
2061/* 0xFE00h ~ 0xFE55h RTL8723 SDIO Configuration */
2062/* */
2063/* */
2064
2065/* I/O bus domain address mapping */
2066#define WLAN_IOREG_BASE 0x10260000
2067#define FIRMWARE_FIFO_BASE 0x10270000
2068#define TX_HIQ_BASE 0x10310000
2069#define TX_MIQ_BASE 0x10320000
2070#define TX_LOQ_BASE 0x10330000
2071#define RX_RX0FF_BASE 0x10340000
2072
2073/* SDIO host local register space mapping. */
2074#define WLAN_IOREG_MSK 0x7FFF
2075#define WLAN_FIFO_MSK 0x1FFF /* Aggregation Length[12:0] */
2076#define WLAN_RX0FF_MSK 0x0003
2077
2078#define WLAN_RX0FF_DEVICE_ID 7 /* 0b[16], 111b[15:13] */
2079#define WLAN_IOREG_DEVICE_ID 8 /* 1b[16] */
2080
2081/* 8723 EFUSE */
2082#define HWSET_MAX_SIZE 256
2083
2084
2085/* USB interrupt */
2086#define UHIMR_TIMEOUT2 BIT31
2087#define UHIMR_TIMEOUT1 BIT30
2088#define UHIMR_PSTIMEOUT BIT29
2089#define UHIMR_GTINT4 BIT28
2090#define UHIMR_GTINT3 BIT27
2091#define UHIMR_TXBCNERR BIT26
2092#define UHIMR_TXBCNOK BIT25
2093#define UHIMR_TSF_BIT32_TOGGLE BIT24
2094#define UHIMR_BCNDMAINT3 BIT23
2095#define UHIMR_BCNDMAINT2 BIT22
2096#define UHIMR_BCNDMAINT1 BIT21
2097#define UHIMR_BCNDMAINT0 BIT20
2098#define UHIMR_BCNDOK3 BIT19
2099#define UHIMR_BCNDOK2 BIT18
2100#define UHIMR_BCNDOK1 BIT17
2101#define UHIMR_BCNDOK0 BIT16
2102#define UHIMR_HSISR_IND BIT15
2103#define UHIMR_BCNDMAINT_E BIT14
2104/* RSVD BIT13 */
2105#define UHIMR_CTW_END BIT12
2106/* RSVD BIT11 */
2107#define UHIMR_C2HCMD BIT10
2108#define UHIMR_CPWM2 BIT9
2109#define UHIMR_CPWM BIT8
2110#define UHIMR_HIGHDOK BIT7 /* High Queue DMA OK
2111 Interrupt */
2112#define UHIMR_MGNTDOK BIT6 /* Management Queue DMA OK
2113 Interrupt */
2114#define UHIMR_BKDOK BIT5 /* AC_BK DMA OK Interrupt */
2115#define UHIMR_BEDOK BIT4 /* AC_BE DMA OK Interrupt */
2116#define UHIMR_VIDOK BIT3 /* AC_VI DMA OK Interrupt */
2117#define UHIMR_VODOK BIT2 /* AC_VO DMA Interrupt */
2118#define UHIMR_RDU BIT1 /* Receive Descriptor
2119 Unavailable */
2120#define UHIMR_ROK BIT0 /* Receive DMA OK Interrupt */
2121
2122/* USB Host Interrupt Status Extension bit */
2123#define UHIMR_BCNDMAINT7 BIT23
2124#define UHIMR_BCNDMAINT6 BIT22
2125#define UHIMR_BCNDMAINT5 BIT21
2126#define UHIMR_BCNDMAINT4 BIT20
2127#define UHIMR_BCNDOK7 BIT19
2128#define UHIMR_BCNDOK6 BIT18
2129#define UHIMR_BCNDOK5 BIT17
2130#define UHIMR_BCNDOK4 BIT16
2131/* bit14-15: RSVD */
2132#define UHIMR_ATIMEND_E BIT13
2133#define UHIMR_ATIMEND BIT12
2134#define UHIMR_TXERR BIT11
2135#define UHIMR_RXERR BIT10
2136#define UHIMR_TXFOVW BIT9
2137#define UHIMR_RXFOVW BIT8
2138/* bit2-7: RSVD */
2139#define UHIMR_OCPINT BIT1
2140/* bit0: RSVD */
2141
2142#define REG_USB_HIMR 0xFE38
2143#define REG_USB_HIMRE 0xFE3C
2144#define REG_USB_HISR 0xFE78
2145#define REG_USB_HISRE 0xFE7C
2146
2147#define USB_INTR_CPWM_OFFSET 16
2148#define USB_INTR_CONTENT_HISR_OFFSET 48
2149#define USB_INTR_CONTENT_HISRE_OFFSET 52
2150#define USB_INTR_CONTENT_LENGTH 56
2151#define USB_C2H_CMDID_OFFSET 0
2152#define USB_C2H_SEQ_OFFSET 1
2153#define USB_C2H_EVENT_OFFSET 2
2154/* */
2155/* General definitions */
2156/* */
2157
2158#endif
diff --git a/drivers/staging/rtl8723au/include/rtl8723a_sreset.h b/drivers/staging/rtl8723au/include/rtl8723a_sreset.h
new file mode 100644
index 000000000000..82af6a2704ed
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtl8723a_sreset.h
@@ -0,0 +1,25 @@
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 ******************************************************************************/
15#ifndef _RTL8723A_SRESET_H_
16#define _RTL8723A_SRESET_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20#include <rtw_sreset.h>
21
22void rtl8723a_sreset_xmit_status_check(struct rtw_adapter *padapter);
23void rtl8723a_sreset_linked_status_check(struct rtw_adapter *padapter);
24
25#endif
diff --git a/drivers/staging/rtl8723au/include/rtl8723a_xmit.h b/drivers/staging/rtl8723au/include/rtl8723a_xmit.h
new file mode 100644
index 000000000000..3b6fdc3a9b7b
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtl8723a_xmit.h
@@ -0,0 +1,229 @@
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 ******************************************************************************/
15#ifndef __RTL8723A_XMIT_H__
16#define __RTL8723A_XMIT_H__
17
18/* */
19/* Queue Select Value in TxDesc */
20/* */
21#define QSLT_BK 0x2/* 0x01 */
22#define QSLT_BE 0x0
23#define QSLT_VI 0x5/* 0x4 */
24#define QSLT_VO 0x7/* 0x6 */
25#define QSLT_BEACON 0x10
26#define QSLT_HIGH 0x11
27#define QSLT_MGNT 0x12
28#define QSLT_CMD 0x13
29
30/* */
31/* defined for TX DESC Operation */
32/* */
33
34#define MAX_TID (15)
35
36/* OFFSET 0 */
37#define OFFSET_SZ 0
38#define OFFSET_SHT 16
39#define BMC BIT(24)
40#define LSG BIT(26)
41#define FSG BIT(27)
42#define OWN BIT(31)
43
44
45/* OFFSET 4 */
46#define PKT_OFFSET_SZ 0
47#define BK BIT(6)
48#define QSEL_SHT 8
49#define Rate_ID_SHT 16
50#define NAVUSEHDR BIT(20)
51#define PKT_OFFSET_SHT 26
52#define HWPC BIT(31)
53
54/* OFFSET 8 */
55#define AGG_EN BIT(29)
56
57/* OFFSET 12 */
58#define SEQ_SHT 16
59
60/* OFFSET 16 */
61#define QoS BIT(6)
62#define HW_SEQ_EN BIT(7)
63#define USERATE BIT(8)
64#define DISDATAFB BIT(10)
65#define DATA_SHORT BIT(24)
66#define DATA_BW BIT(25)
67
68/* OFFSET 20 */
69#define SGI BIT(6)
70
71struct txdesc_8723a {
72 u32 pktlen:16;
73 u32 offset:8;
74 u32 bmc:1;
75 u32 htc:1;
76 u32 ls:1;
77 u32 fs:1;
78 u32 linip:1;
79 u32 noacm:1;
80 u32 gf:1;
81 u32 own:1;
82
83 u32 macid:5;
84 u32 agg_en:1;
85 u32 bk:1;
86 u32 rd_en:1;
87 u32 qsel:5;
88 u32 rd_nav_ext:1;
89 u32 lsig_txop_en:1;
90 u32 pifs:1;
91 u32 rate_id:4;
92 u32 navusehdr:1;
93 u32 en_desc_id:1;
94 u32 sectype:2;
95 u32 rsvd0424:2;
96 u32 pkt_offset:5; /* unit: 8 bytes */
97 u32 rsvd0431:1;
98
99 u32 rts_rc:6;
100 u32 data_rc:6;
101 u32 rsvd0812:2;
102 u32 bar_rty_th:2;
103 u32 rsvd0816:1;
104 u32 morefrag:1;
105 u32 raw:1;
106 u32 ccx:1;
107 u32 ampdu_density:3;
108 u32 bt_null:1;
109 u32 ant_sel_a:1;
110 u32 ant_sel_b:1;
111 u32 tx_ant_cck:2;
112 u32 tx_antl:2;
113 u32 tx_ant_ht:2;
114
115 u32 nextheadpage:8;
116 u32 tailpage:8;
117 u32 seq:12;
118 u32 cpu_handle:1;
119 u32 tag1:1;
120 u32 trigger_int:1;
121 u32 hwseq_en:1;
122
123 u32 rtsrate:5;
124 u32 ap_dcfe:1;
125 u32 hwseq_sel:2;
126 u32 userate:1;
127 u32 disrtsfb:1;
128 u32 disdatafb:1;
129 u32 cts2self:1;
130 u32 rtsen:1;
131 u32 hw_rts_en:1;
132 u32 port_id:1;
133 u32 rsvd1615:3;
134 u32 wait_dcts:1;
135 u32 cts2ap_en:1;
136 u32 data_sc:2;
137 u32 data_stbc:2;
138 u32 data_short:1;
139 u32 data_bw:1;
140 u32 rts_short:1;
141 u32 rts_bw:1;
142 u32 rts_sc:2;
143 u32 vcs_stbc:2;
144
145 u32 datarate:6;
146 u32 sgi:1;
147 u32 try_rate:1;
148 u32 data_ratefb_lmt:5;
149 u32 rts_ratefb_lmt:4;
150 u32 rty_lmt_en:1;
151 u32 data_rt_lmt:6;
152 u32 usb_txagg_num:8;
153
154 u32 txagg_a:5;
155 u32 txagg_b:5;
156 u32 use_max_len:1;
157 u32 max_agg_num:5;
158 u32 mcsg1_max_len:4;
159 u32 mcsg2_max_len:4;
160 u32 mcsg3_max_len:4;
161 u32 mcs7_sgi_max_len:4;
162
163 u32 checksum:16; /* TxBuffSize(PCIe)/CheckSum(USB) */
164 u32 mcsg4_max_len:4;
165 u32 mcsg5_max_len:4;
166 u32 mcsg6_max_len:4;
167 u32 mcs15_sgi_max_len:4;
168};
169
170#define txdesc_set_ccx_sw_8723a(txdesc, value) \
171 do { \
172 ((struct txdesc_8723a *)(txdesc))->mcsg4_max_len = (((value)>>8) & 0x0f); \
173 ((struct txdesc_8723a *)(txdesc))->mcs15_sgi_max_len= (((value)>>4) & 0x0f); \
174 ((struct txdesc_8723a *)(txdesc))->mcsg6_max_len = ((value) & 0x0f); \
175 } while (0)
176
177struct txrpt_ccx_8723a {
178 /* offset 0 */
179 u8 tag1:1;
180 u8 rsvd:4;
181 u8 int_bt:1;
182 u8 int_tri:1;
183 u8 int_ccx:1;
184
185 /* offset 1 */
186 u8 mac_id:5;
187 u8 pkt_drop:1;
188 u8 pkt_ok:1;
189 u8 bmc:1;
190
191 /* offset 2 */
192 u8 retry_cnt:6;
193 u8 lifetime_over:1;
194 u8 retry_over:1;
195
196 /* offset 3 */
197 u8 ccx_qtime0;
198 u8 ccx_qtime1;
199
200 /* offset 5 */
201 u8 final_data_rate;
202
203 /* offset 6 */
204 u8 sw1:4;
205 u8 qsel:4;
206
207 /* offset 7 */
208 u8 sw0;
209};
210
211#define txrpt_ccx_sw_8723a(txrpt_ccx) ((txrpt_ccx)->sw0 + ((txrpt_ccx)->sw1<<8))
212#define txrpt_ccx_qtime_8723a(txrpt_ccx) ((txrpt_ccx)->ccx_qtime0+((txrpt_ccx)->ccx_qtime1<<8))
213
214void dump_txrpt_ccx_8723a(void *buf);
215void handle_txrpt_ccx_8723a(struct rtw_adapter *adapter, void *buf);
216void rtl8723a_update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem);
217void rtl8723a_fill_fake_txdesc(struct rtw_adapter *padapter, u8 *pDesc, u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull);
218
219s32 rtl8723au_hal_xmitframe_enqueue(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe);
220s32 rtl8723au_xmit_buf_handler(struct rtw_adapter *padapter);
221#define hal_xmit_handler rtl8723au_xmit_buf_handler
222s32 rtl8723au_init_xmit_priv(struct rtw_adapter * padapter);
223void rtl8723au_free_xmit_priv(struct rtw_adapter * padapter);
224s32 rtl8723au_hal_xmit(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe);
225s32 rtl8723au_mgnt_xmit(struct rtw_adapter *padapter, struct xmit_frame *pmgntframe);
226s32 rtl8723au_xmitframe_complete(struct rtw_adapter *padapter, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf);
227
228
229#endif
diff --git a/drivers/staging/rtl8723au/include/rtw_ap.h b/drivers/staging/rtl8723au/include/rtw_ap.h
new file mode 100644
index 000000000000..76f82d68f633
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_ap.h
@@ -0,0 +1,55 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#ifndef __RTW_AP_H_
16#define __RTW_AP_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21
22#ifdef CONFIG_8723AU_AP_MODE
23
24/* external function */
25void rtw_indicate_sta_assoc_event23a(struct rtw_adapter *padapter, struct sta_info *psta);
26void rtw_indicate_sta_disassoc_event23a(struct rtw_adapter *padapter, struct sta_info *psta);
27
28void init_mlme_ap_info23a(struct rtw_adapter *padapter);
29void free_mlme_ap_info23a(struct rtw_adapter *padapter);
30/* void update_BCNTIM(struct rtw_adapter *padapter); */
31void rtw_add_bcn_ie(struct rtw_adapter *padapter, struct wlan_bssid_ex *pnetwork, u8 index, u8 *data, u8 len);
32void rtw_remove_bcn_ie(struct rtw_adapter *padapter, struct wlan_bssid_ex *pnetwork, u8 index);
33void update_beacon23a(struct rtw_adapter *padapter, u8 ie_id, u8 *oui, u8 tx);
34void add_RATid23a(struct rtw_adapter *padapter, struct sta_info *psta, u8 rssi_level);
35void expire_timeout_chk23a(struct rtw_adapter *padapter);
36void update_sta_info23a_apmode23a(struct rtw_adapter *padapter, struct sta_info *psta);
37int rtw_check_beacon_data23a(struct rtw_adapter *padapter, u8 *pbuf, int len);
38void rtw_ap_restore_network(struct rtw_adapter *padapter);
39void rtw_set_macaddr_acl23a(struct rtw_adapter *padapter, int mode);
40int rtw_acl_add_sta23a(struct rtw_adapter *padapter, u8 *addr);
41int rtw_acl_remove_sta23a(struct rtw_adapter *padapter, u8 *addr);
42
43void associated_clients_update23a(struct rtw_adapter *padapter, u8 updated);
44void bss_cap_update_on_sta_join23a(struct rtw_adapter *padapter, struct sta_info *psta);
45u8 bss_cap_update_on_sta_leave23a(struct rtw_adapter *padapter, struct sta_info *psta);
46void sta_info_update23a(struct rtw_adapter *padapter, struct sta_info *psta);
47void ap_sta_info_defer_update23a(struct rtw_adapter *padapter, struct sta_info *psta);
48u8 ap_free_sta23a(struct rtw_adapter *padapter, struct sta_info *psta, bool active, u16 reason);
49int rtw_sta_flush23a(struct rtw_adapter *padapter);
50int rtw_ap_inform_ch_switch23a(struct rtw_adapter *padapter, u8 new_ch, u8 ch_offset);
51void start_ap_mode23a(struct rtw_adapter *padapter);
52void stop_ap_mode23a(struct rtw_adapter *padapter);
53#endif /* end of CONFIG_8723AU_AP_MODE */
54
55#endif
diff --git a/drivers/staging/rtl8723au/include/rtw_cmd.h b/drivers/staging/rtl8723au/include/rtw_cmd.h
new file mode 100644
index 000000000000..f9caa3e35f57
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_cmd.h
@@ -0,0 +1,835 @@
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 ******************************************************************************/
15#ifndef __RTW_CMD_H_
16#define __RTW_CMD_H_
17
18#include <wlan_bssdef.h>
19#include <rtw_rf.h>
20#include <rtw_led.h>
21
22#define C2H_MEM_SZ (16*1024)
23
24#include <osdep_service.h>
25#include <ieee80211.h> /* <ieee80211/ieee80211.h> */
26
27
28#define FREE_CMDOBJ_SZ 128
29
30#define MAX_CMDSZ 1024
31#define MAX_RSPSZ 512
32#define MAX_EVTSZ 1024
33
34#define CMDBUFF_ALIGN_SZ 512
35
36struct cmd_obj {
37 struct rtw_adapter *padapter;
38 u16 cmdcode;
39 u8 res;
40 u8 *parmbuf;
41 u32 cmdsz;
42 u8 *rsp;
43 u32 rspsz;
44 /* struct semaphore cmd_sem; */
45 struct list_head list;
46};
47
48struct cmd_priv {
49 struct semaphore cmd_queue_sema;
50 /* struct semaphore cmd_done_sema; */
51 struct semaphore terminate_cmdthread_sema;
52 struct rtw_queue cmd_queue;
53 u8 cmd_seq;
54 u8 *cmd_buf; /* shall be non-paged, and 4 bytes aligned */
55 u8 *cmd_allocated_buf;
56 u8 *rsp_buf; /* shall be non-paged, and 4 bytes aligned */
57 u8 *rsp_allocated_buf;
58 u32 cmd_issued_cnt;
59 u32 cmd_done_cnt;
60 u32 rsp_cnt;
61 u8 cmdthd_running;
62 struct rtw_adapter *padapter;
63};
64
65#define C2H_QUEUE_MAX_LEN 10
66
67struct evt_priv {
68 struct work_struct c2h_wk;
69 bool c2h_wk_alive;
70 struct rtw_cbuf *c2h_queue;
71
72 atomic_t event_seq;
73 u8 *evt_buf; /* shall be non-paged, and 4 bytes aligned */
74 u8 *evt_allocated_buf;
75 u32 evt_done_cnt;
76};
77
78#define init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code) \
79do {\
80 INIT_LIST_HEAD(&pcmd->list);\
81 pcmd->cmdcode = code;\
82 pcmd->parmbuf = (u8 *)(pparm);\
83 pcmd->cmdsz = sizeof (*pparm);\
84 pcmd->rsp = NULL;\
85 pcmd->rspsz = 0;\
86} while(0)
87
88struct c2h_evt_hdr {
89 u8 id:4;
90 u8 plen:4;
91 u8 seq;
92 u8 payload[0];
93};
94
95#define c2h_evt_exist(c2h_evt) ((c2h_evt)->id || (c2h_evt)->plen)
96
97u32 rtw_enqueue_cmd23a(struct cmd_priv *pcmdpriv, struct cmd_obj *obj);
98void rtw_free_cmd_obj23a(struct cmd_obj *pcmd);
99
100int rtw_cmd_thread23a(void *context);
101
102int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv);
103void rtw_free_cmd_priv23a (struct cmd_priv *pcmdpriv);
104
105u32 rtw_init_evt_priv23a (struct evt_priv *pevtpriv);
106void rtw_free_evt_priv23a (struct evt_priv *pevtpriv);
107void rtw_cmd_clr_isr23a(struct cmd_priv *pcmdpriv);
108void rtw_evt_notify_isr(struct evt_priv *pevtpriv);
109#ifdef CONFIG_8723AU_P2P
110u8 p2p_protocol_wk_cmd23a(struct rtw_adapter*padapter, int intCmdType );
111#endif /* CONFIG_8723AU_P2P */
112
113enum rtw_drvextra_cmd_id
114{
115 NONE_WK_CID,
116 DYNAMIC_CHK_WK_CID,
117 DM_CTRL_WK_CID,
118 PBC_POLLING_WK_CID,
119 POWER_SAVING_CTRL_WK_CID,/* IPS,AUTOSuspend */
120 LPS_CTRL_WK_CID,
121 ANT_SELECT_WK_CID,
122 P2P_PS_WK_CID,
123 P2P_PROTO_WK_CID,
124 CHECK_HIQ_WK_CID,/* for softap mode, check hi queue if empty */
125 C2H_WK_CID,
126 RTP_TIMER_CFG_WK_CID,
127 MAX_WK_CID
128};
129
130enum LPS_CTRL_TYPE
131{
132 LPS_CTRL_SCAN=0,
133 LPS_CTRL_JOINBSS=1,
134 LPS_CTRL_CONNECT=2,
135 LPS_CTRL_DISCONNECT=3,
136 LPS_CTRL_SPECIAL_PACKET=4,
137 LPS_CTRL_LEAVE=5,
138};
139
140enum RFINTFS {
141 SWSI,
142 HWSI,
143 HWPI,
144};
145
146/*
147Caller Mode: Infra, Ad-HoC(C)
148
149Notes: To enter USB suspend mode
150
151Command Mode
152
153*/
154struct usb_suspend_parm {
155 u32 action;/* 1: sleep, 0:resume */
156};
157
158/*
159Caller Mode: Infra, Ad-HoC
160
161Notes: To join a known BSS.
162
163Command-Event Mode
164
165*/
166
167/*
168Caller Mode: Infra, Ad-HoC(C)
169
170Notes: To disconnect the current associated BSS
171
172Command Mode
173
174*/
175struct disconnect_parm {
176 u32 deauth_timeout_ms;
177};
178
179struct setopmode_parm {
180 u8 mode;
181 u8 rsvd[3];
182};
183
184/*
185Caller Mode: AP, Ad-HoC, Infra
186
187Notes: To ask RTL8711 performing site-survey
188
189Command-Event Mode
190
191*/
192
193#define RTW_SSID_SCAN_AMOUNT 9 /* for WEXT_CSCAN_AMOUNT 9 */
194#define RTW_CHANNEL_SCAN_AMOUNT (14+37)
195struct sitesurvey_parm {
196 int scan_mode; /* active: 1, passive: 0 */
197 u8 ssid_num;
198 u8 ch_num;
199 struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT];
200 struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
201};
202
203/*
204Caller Mode: Any
205
206Notes: To set the auth type of RTL8711. open/shared/802.1x
207
208Command Mode
209
210*/
211struct setauth_parm {
212 u8 mode; /* 0: legacy open, 1: legacy shared 2: 802.1x */
213 u8 _1x; /* 0: PSK, 1: TLS */
214 u8 rsvd[2];
215};
216
217/*
218Caller Mode: Infra
219
220a. algorithm: wep40, wep104, tkip & aes
221b. keytype: grp key/unicast key
222c. key contents
223
224when shared key ==> keyid is the camid
225when 802.1x ==> keyid [0:1] ==> grp key
226when 802.1x ==> keyid > 2 ==> unicast key
227
228*/
229struct setkey_parm {
230 u8 algorithm; /* encryption algorithm, could be none, wep40, TKIP, CCMP, wep104 */
231 u8 keyid;
232 u8 grpkey; /* 1: this is the grpkey for 802.1x. 0: this is the unicast key for 802.1x */
233 u8 set_tx; /* 1: main tx key for wep. 0: other key. */
234 u8 key[16]; /* this could be 40 or 104 */
235};
236
237/*
238When in AP or Ad-Hoc mode, this is used to
239allocate an sw/hw entry for a newly associated sta.
240
241Command
242
243when shared key ==> algorithm/keyid
244
245*/
246struct set_stakey_parm {
247 u8 addr[ETH_ALEN];
248 u8 algorithm;
249 u8 id;/* currently for erasing cam entry if algorithm == _NO_PRIVACY_ */
250 u8 key[16];
251};
252
253struct set_stakey_rsp {
254 u8 addr[ETH_ALEN];
255 u8 keyid;
256 u8 rsvd;
257};
258
259/*
260Caller Ad-Hoc/AP
261
262Command -Rsp(AID == CAMID) mode
263
264This is to force fw to add an sta_data entry per driver's request.
265
266FW will write an cam entry associated with it.
267
268*/
269struct set_assocsta_parm {
270 u8 addr[ETH_ALEN];
271};
272
273struct set_assocsta_rsp {
274 u8 cam_id;
275 u8 rsvd[3];
276};
277
278/*
279 Caller Ad-Hoc/AP
280
281 Command mode
282
283 This is to force fw to del an sta_data entry per driver's request
284
285 FW will invalidate the cam entry associated with it.
286
287*/
288struct del_assocsta_parm {
289 u8 addr[ETH_ALEN];
290};
291
292/*
293Caller Mode: AP/Ad-HoC(M)
294
295Notes: To notify fw that given staid has changed its power state
296
297Command Mode
298
299*/
300struct setstapwrstate_parm {
301 u8 staid;
302 u8 status;
303 u8 hwaddr[6];
304};
305
306/*
307Caller Mode: Any
308
309Notes: To setup the basic rate of RTL8711
310
311Command Mode
312
313*/
314struct setbasicrate_parm {
315 u8 basicrates[NumRates];
316};
317
318/*
319Caller Mode: Any
320
321Notes: To read the current basic rate
322
323Command-Rsp Mode
324
325*/
326struct getbasicrate_parm {
327 u32 rsvd;
328};
329
330struct getbasicrate_rsp {
331 u8 basicrates[NumRates];
332};
333
334/*
335Caller Mode: Any
336
337Notes: To setup the data rate of RTL8711
338
339Command Mode
340
341*/
342struct setdatarate_parm {
343 u8 mac_id;
344 u8 datarates[NumRates];
345};
346
347/*
348Caller Mode: Any
349
350Notes: To read the current data rate
351
352Command-Rsp Mode
353
354*/
355struct getdatarate_parm {
356 u32 rsvd;
357};
358
359struct getdatarate_rsp {
360 u8 datarates[NumRates];
361};
362
363
364/*
365Caller Mode: Any
366AP: AP can use the info for the contents of beacon frame
367Infra: STA can use the info when sitesurveying
368Ad-HoC(M): Like AP
369Ad-HoC(C): Like STA
370
371
372Notes: To set the phy capability of the NIC
373
374Command Mode
375
376*/
377
378struct setphyinfo_parm {
379 struct regulatory_class class_sets[NUM_REGULATORYS];
380 u8 status;
381};
382
383struct getphyinfo_parm {
384 u32 rsvd;
385};
386
387struct getphyinfo_rsp {
388 struct regulatory_class class_sets[NUM_REGULATORYS];
389 u8 status;
390};
391
392/*
393Caller Mode: Any
394
395Notes: To set the channel/modem/band
396This command will be used when channel/modem/band is changed.
397
398Command Mode
399
400*/
401struct setphy_parm {
402 u8 rfchannel;
403 u8 modem;
404};
405
406/*
407Caller Mode: Any
408
409Notes: To get the current setting of channel/modem/band
410
411Command-Rsp Mode
412
413*/
414struct getphy_parm {
415 u32 rsvd;
416};
417
418struct getphy_rsp {
419 u8 rfchannel;
420 u8 modem;
421};
422
423struct readBB_parm {
424 u8 offset;
425};
426
427struct readBB_rsp {
428 u8 value;
429};
430
431struct readTSSI_parm {
432 u8 offset;
433};
434
435struct readTSSI_rsp {
436 u8 value;
437};
438
439struct writeBB_parm {
440 u8 offset;
441 u8 value;
442};
443
444struct readRF_parm {
445 u8 offset;
446};
447
448struct readRF_rsp {
449 u32 value;
450};
451
452struct writeRF_parm {
453 u32 offset;
454 u32 value;
455};
456
457struct getrfintfs_parm {
458 u8 rfintfs;
459};
460
461struct Tx_Beacon_param
462{
463 struct wlan_bssid_ex network;
464};
465
466/* CMD param Formart for driver extra cmd handler */
467struct drvextra_cmd_parm {
468 int ec_id; /* extra cmd id */
469 int type_size; /* Can use this field as the type id or command size */
470 unsigned char *pbuf;
471};
472
473/*------------------- Below are used for RF/BB tunning ---------------------*/
474
475struct setantenna_parm {
476 u8 tx_antset;
477 u8 rx_antset;
478 u8 tx_antenna;
479 u8 rx_antenna;
480};
481
482struct enrateadaptive_parm {
483 u32 en;
484};
485
486struct settxagctbl_parm {
487 u32 txagc[MAX_RATES_LENGTH];
488};
489
490struct gettxagctbl_parm {
491 u32 rsvd;
492};
493
494struct gettxagctbl_rsp {
495 u32 txagc[MAX_RATES_LENGTH];
496};
497
498struct setagcctrl_parm {
499 u32 agcctrl; /* 0: pure hw, 1: fw */
500};
501
502struct setssup_parm {
503 u32 ss_ForceUp[MAX_RATES_LENGTH];
504};
505
506struct getssup_parm {
507 u32 rsvd;
508};
509
510struct getssup_rsp {
511 u8 ss_ForceUp[MAX_RATES_LENGTH];
512};
513
514struct setssdlevel_parm {
515 u8 ss_DLevel[MAX_RATES_LENGTH];
516};
517
518struct getssdlevel_parm {
519 u32 rsvd;
520};
521
522struct getssdlevel_rsp {
523 u8 ss_DLevel[MAX_RATES_LENGTH];
524};
525
526struct setssulevel_parm {
527 u8 ss_ULevel[MAX_RATES_LENGTH];
528};
529
530struct getssulevel_parm {
531 u32 rsvd;
532};
533
534struct getssulevel_rsp {
535 u8 ss_ULevel[MAX_RATES_LENGTH];
536};
537
538struct setcountjudge_parm {
539 u8 count_judge[MAX_RATES_LENGTH];
540};
541
542struct getcountjudge_parm {
543 u32 rsvd;
544};
545
546struct getcountjudge_rsp {
547 u8 count_judge[MAX_RATES_LENGTH];
548};
549
550struct setratable_parm {
551 u8 ss_ForceUp[NumRates];
552 u8 ss_ULevel[NumRates];
553 u8 ss_DLevel[NumRates];
554 u8 count_judge[NumRates];
555};
556
557struct getratable_parm {
558 uint rsvd;
559};
560
561struct getratable_rsp {
562 u8 ss_ForceUp[NumRates];
563 u8 ss_ULevel[NumRates];
564 u8 ss_DLevel[NumRates];
565 u8 count_judge[NumRates];
566};
567
568/* to get TX,RX retry count */
569struct gettxretrycnt_parm{
570 unsigned int rsvd;
571};
572struct gettxretrycnt_rsp{
573 unsigned long tx_retrycnt;
574};
575
576struct getrxretrycnt_parm{
577 unsigned int rsvd;
578};
579struct getrxretrycnt_rsp{
580 unsigned long rx_retrycnt;
581};
582
583/* to get BCNOK,BCNERR count */
584struct getbcnokcnt_parm{
585 unsigned int rsvd;
586};
587struct getbcnokcnt_rsp{
588 unsigned long bcnokcnt;
589};
590
591struct getbcnerrcnt_parm{
592 unsigned int rsvd;
593};
594struct getbcnerrcnt_rsp{
595 unsigned long bcnerrcnt;
596};
597
598/* to get current TX power level */
599struct getcurtxpwrlevel_parm{
600 unsigned int rsvd;
601};
602
603struct getcurtxpwrlevel_rsp{
604 unsigned short tx_power;
605};
606
607struct setprobereqextraie_parm {
608 unsigned char e_id;
609 unsigned char ie_len;
610 unsigned char ie[0];
611};
612
613struct setassocreqextraie_parm {
614 unsigned char e_id;
615 unsigned char ie_len;
616 unsigned char ie[0];
617};
618
619struct setproberspextraie_parm {
620 unsigned char e_id;
621 unsigned char ie_len;
622 unsigned char ie[0];
623};
624
625struct setassocrspextraie_parm {
626 unsigned char e_id;
627 unsigned char ie_len;
628 unsigned char ie[0];
629};
630
631struct addBaReq_parm {
632 unsigned int tid;
633 u8 addr[ETH_ALEN];
634};
635
636/*H2C Handler index: 46 */
637struct set_ch_parm {
638 u8 ch;
639 u8 bw;
640 u8 ch_offset;
641};
642
643/*H2C Handler index: 59 */
644struct SetChannelPlan_param {
645 u8 channel_plan;
646};
647
648/*H2C Handler index: 60 */
649struct LedBlink_param {
650 struct led_8723a *pLed;
651};
652
653/*H2C Handler index: 61 */
654struct SetChannelSwitch_param {
655 u8 new_ch_no;
656};
657
658/*H2C Handler index: 62 */
659struct TDLSoption_param {
660 u8 addr[ETH_ALEN];
661 u8 option;
662};
663
664#define GEN_CMD_CODE(cmd) cmd ## _CMD_
665
666
667/*
668
669Result:
6700x00: success
6710x01: sucess, and check Response.
6720x02: cmd ignored due to duplicated sequcne number
6730x03: cmd dropped due to invalid cmd code
6740x04: reserved.
675
676*/
677
678#define H2C_RSP_OFFSET 512
679
680#define H2C_SUCCESS 0x00
681#define H2C_SUCCESS_RSP 0x01
682#define H2C_DUPLICATED 0x02
683#define H2C_DROPPED 0x03
684#define H2C_PARAMETERS_ERROR 0x04
685#define H2C_REJECTED 0x05
686#define H2C_CMD_OVERFLOW 0x06
687#define H2C_RESERVED 0x07
688
689u8 rtw_setassocsta_cmd(struct rtw_adapter *padapter, u8 *mac_addr);
690u8 rtw_setstandby_cmd(struct rtw_adapter *padapter, uint action);
691u8 rtw_sitesurvey_cmd23a(struct rtw_adapter *padapter, struct cfg80211_ssid *ssid, int ssid_num, struct rtw_ieee80211_channel *ch, int ch_num);
692u8 rtw_createbss_cmd23a(struct rtw_adapter *padapter);
693u8 rtw_createbss_cmd23a_ex(struct rtw_adapter *padapter, unsigned char *pbss, unsigned int sz);
694u8 rtw_setphy_cmd(struct rtw_adapter *padapter, u8 modem, u8 ch);
695u8 rtw_setstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 unicast_key);
696u8 rtw_clearstakey_cmd23a(struct rtw_adapter *padapter, u8 *psta, u8 entry, u8 enqueue);
697u8 rtw_joinbss_cmd23a(struct rtw_adapter *padapter, struct wlan_network* pnetwork);
698u8 rtw_disassoc_cmd23a(struct rtw_adapter *padapter, u32 deauth_timeout_ms, bool enqueue);
699u8 rtw_setopmode_cmd23a(struct rtw_adapter *padapter, enum ndis_802_11_net_infra networktype);
700u8 rtw_setdatarate_cmd(struct rtw_adapter *padapter, u8 *rateset);
701u8 rtw_setbasicrate_cmd(struct rtw_adapter *padapter, u8 *rateset);
702u8 rtw_setbbreg_cmd(struct rtw_adapter * padapter, u8 offset, u8 val);
703u8 rtw_setrfreg_cmd(struct rtw_adapter * padapter, u8 offset, u32 val);
704u8 rtw_getbbreg_cmd(struct rtw_adapter * padapter, u8 offset, u8 * pval);
705u8 rtw_getrfreg_cmd(struct rtw_adapter * padapter, u8 offset, u8 * pval);
706u8 rtw_setrfintfs_cmd(struct rtw_adapter *padapter, u8 mode);
707u8 rtw_setrttbl_cmd(struct rtw_adapter *padapter, struct setratable_parm *prate_table);
708u8 rtw_getrttbl_cmd(struct rtw_adapter *padapter, struct getratable_rsp *pval);
709
710u8 rtw_gettssi_cmd(struct rtw_adapter *padapter, u8 offset,u8 *pval);
711u8 rtw_setfwdig_cmd(struct rtw_adapter*padapter, u8 type);
712u8 rtw_setfwra_cmd(struct rtw_adapter*padapter, u8 type);
713
714u8 rtw_addbareq_cmd23a(struct rtw_adapter*padapter, u8 tid, u8 *addr);
715
716u8 rtw_dynamic_chk_wk_cmd23a(struct rtw_adapter *adapter);
717
718u8 rtw_lps_ctrl_wk_cmd23a(struct rtw_adapter*padapter, u8 lps_ctrl_type, u8 enqueue);
719
720u8 rtw_ps_cmd23a(struct rtw_adapter*padapter);
721
722#ifdef CONFIG_8723AU_AP_MODE
723u8 rtw_chk_hi_queue_cmd23a(struct rtw_adapter*padapter);
724#endif
725
726u8 rtw_set_ch_cmd23a(struct rtw_adapter*padapter, u8 ch, u8 bw, u8 ch_offset, u8 enqueue);
727u8 rtw_set_chplan_cmd(struct rtw_adapter*padapter, u8 chplan, u8 enqueue);
728u8 rtw_led_blink_cmd(struct rtw_adapter*padapter, struct led_8723a *pLed);
729u8 rtw_set_csa_cmd(struct rtw_adapter*padapter, u8 new_ch_no);
730u8 rtw_tdls_cmd(struct rtw_adapter*padapter, u8 *addr, u8 option);
731
732u8 rtw_c2h_wk_cmd23a(struct rtw_adapter *padapter, u8 *c2h_evt);
733
734u8 rtw_drvextra_cmd_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf);
735
736void rtw_survey_cmd_callback23a(struct rtw_adapter *padapter, struct cmd_obj *pcmd);
737void rtw_disassoc_cmd23a_callback(struct rtw_adapter *padapter, struct cmd_obj *pcmd);
738void rtw_joinbss_cmd23a_callback(struct rtw_adapter *padapter, struct cmd_obj *pcmd);
739void rtw_createbss_cmd23a_callback(struct rtw_adapter *padapter, struct cmd_obj *pcmd);
740void rtw_getbbrfreg_cmdrsp_callback23a(struct rtw_adapter *padapter, struct cmd_obj *pcmd);
741void rtw_readtssi_cmdrsp_callback(struct rtw_adapter* padapter, struct cmd_obj *pcmd);
742
743void rtw_setstaKey_cmdrsp_callback23a(struct rtw_adapter *padapter, struct cmd_obj *pcmd);
744void rtw_setassocsta_cmdrsp_callback23a(struct rtw_adapter *padapter, struct cmd_obj *pcmd);
745void rtw_getrttbl_cmdrsp_callback(struct rtw_adapter *padapter, struct cmd_obj *pcmd);
746
747struct _cmd_callback {
748 u32 cmd_code;
749 void (*callback)(struct rtw_adapter *padapter, struct cmd_obj *cmd);
750};
751
752enum rtw_h2c_cmd {
753 GEN_CMD_CODE(_Read_MACREG) , /*0*/
754 GEN_CMD_CODE(_Write_MACREG) ,
755 GEN_CMD_CODE(_Read_BBREG) ,
756 GEN_CMD_CODE(_Write_BBREG) ,
757 GEN_CMD_CODE(_Read_RFREG) ,
758 GEN_CMD_CODE(_Write_RFREG) , /*5*/
759 GEN_CMD_CODE(_Read_EEPROM) ,
760 GEN_CMD_CODE(_Write_EEPROM) ,
761 GEN_CMD_CODE(_Read_EFUSE) ,
762 GEN_CMD_CODE(_Write_EFUSE) ,
763
764 GEN_CMD_CODE(_Read_CAM) , /*10*/
765 GEN_CMD_CODE(_Write_CAM) ,
766 GEN_CMD_CODE(_setBCNITV),
767 GEN_CMD_CODE(_setMBIDCFG),
768 GEN_CMD_CODE(_JoinBss), /*14*/
769 GEN_CMD_CODE(_DisConnect) , /*15*/
770 GEN_CMD_CODE(_CreateBss) ,
771 GEN_CMD_CODE(_SetOpMode) ,
772 GEN_CMD_CODE(_SiteSurvey), /*18*/
773 GEN_CMD_CODE(_SetAuth) ,
774
775 GEN_CMD_CODE(_SetKey) , /*20*/
776 GEN_CMD_CODE(_SetStaKey) ,
777 GEN_CMD_CODE(_SetAssocSta) ,
778 GEN_CMD_CODE(_DelAssocSta) ,
779 GEN_CMD_CODE(_SetStaPwrState) ,
780 GEN_CMD_CODE(_SetBasicRate) , /*25*/
781 GEN_CMD_CODE(_GetBasicRate) ,
782 GEN_CMD_CODE(_SetDataRate) ,
783 GEN_CMD_CODE(_GetDataRate) ,
784 GEN_CMD_CODE(_SetPhyInfo) ,
785
786 GEN_CMD_CODE(_GetPhyInfo) , /*30*/
787 GEN_CMD_CODE(_SetPhy) ,
788 GEN_CMD_CODE(_GetPhy) ,
789 GEN_CMD_CODE(_readRssi) ,
790 GEN_CMD_CODE(_readGain) ,
791 GEN_CMD_CODE(_SetAtim) , /*35*/
792 GEN_CMD_CODE(_SetPwrMode) ,
793 GEN_CMD_CODE(_JoinbssRpt),
794 GEN_CMD_CODE(_SetRaTable) ,
795 GEN_CMD_CODE(_GetRaTable) ,
796
797 GEN_CMD_CODE(_GetCCXReport), /*40*/
798 GEN_CMD_CODE(_GetDTMReport),
799 GEN_CMD_CODE(_GetTXRateStatistics),
800 GEN_CMD_CODE(_SetUsbSuspend),
801 GEN_CMD_CODE(_SetH2cLbk),
802 GEN_CMD_CODE(_AddBAReq) , /*45*/
803 GEN_CMD_CODE(_SetChannel), /*46*/
804 GEN_CMD_CODE(_SetTxPower),
805 GEN_CMD_CODE(_SwitchAntenna),
806 GEN_CMD_CODE(_SetCrystalCap),
807 GEN_CMD_CODE(_SetSingleCarrierTx), /*50*/
808
809 GEN_CMD_CODE(_SetSingleToneTx),/*51*/
810 GEN_CMD_CODE(_SetCarrierSuppressionTx),
811 GEN_CMD_CODE(_SetContinuousTx),
812 GEN_CMD_CODE(_SwitchBandwidth), /*54*/
813 GEN_CMD_CODE(_TX_Beacon), /*55*/
814
815 GEN_CMD_CODE(_Set_MLME_EVT), /*56*/
816 GEN_CMD_CODE(_Set_Drv_Extra), /*57*/
817 GEN_CMD_CODE(_Set_H2C_MSG), /*58*/
818
819 GEN_CMD_CODE(_SetChannelPlan), /*59*/
820 GEN_CMD_CODE(_LedBlink), /*60*/
821
822 GEN_CMD_CODE(_SetChannelSwitch), /*61*/
823 GEN_CMD_CODE(_TDLS), /*62*/
824
825 MAX_H2CCMD
826};
827
828#define _GetBBReg_CMD_ _Read_BBREG_CMD_
829#define _SetBBReg_CMD_ _Write_BBREG_CMD_
830#define _GetRFReg_CMD_ _Read_RFREG_CMD_
831#define _SetRFReg_CMD_ _Write_RFREG_CMD_
832
833extern struct _cmd_callback rtw_cmd_callback[];
834
835#endif /* _CMD_H_ */
diff --git a/drivers/staging/rtl8723au/include/rtw_debug.h b/drivers/staging/rtl8723au/include/rtw_debug.h
new file mode 100644
index 000000000000..a69d6e215b8b
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_debug.h
@@ -0,0 +1,192 @@
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 *
15 ******************************************************************************/
16#ifndef __RTW_DEBUG_H__
17#define __RTW_DEBUG_H__
18
19#include <osdep_service.h>
20#include <drv_types.h>
21
22#define _drv_always_ 1
23#define _drv_emerg_ 2
24#define _drv_alert_ 3
25#define _drv_err_ 4
26#define _drv_warning_ 5
27#define _drv_notice_ 6
28#define _drv_info_ 7
29#define _drv_debug_ 8
30
31#define _module_rtl871x_xmit_c_ BIT(0)
32#define _module_xmit_osdep_c_ BIT(1)
33#define _module_rtl871x_recv_c_ BIT(2)
34#define _module_recv_osdep_c_ BIT(3)
35#define _module_rtl871x_mlme_c_ BIT(4)
36#define _module_mlme_osdep_c_ BIT(5)
37#define _module_rtl871x_sta_mgt_c_ BIT(6)
38#define _module_rtl871x_cmd_c_ BIT(7)
39#define _module_cmd_osdep_c_ BIT(8)
40#define _module_rtl871x_io_c_ BIT(9)
41#define _module_io_osdep_c_ BIT(10)
42#define _module_os_intfs_c_ BIT(11)
43#define _module_rtl871x_security_c_ BIT(12)
44#define _module_rtl871x_eeprom_c_ BIT(13)
45#define _module_hal_init_c_ BIT(14)
46#define _module_hci_hal_init_c_ BIT(15)
47#define _module_rtl871x_ioctl_c_ BIT(16)
48#define _module_rtl871x_ioctl_set_c_ BIT(17)
49#define _module_rtl871x_ioctl_query_c_ BIT(18)
50#define _module_rtl871x_pwrctrl_c_ BIT(19)
51#define _module_hci_intfs_c_ BIT(20)
52#define _module_hci_ops_c_ BIT(21)
53#define _module_osdep_service_c_ BIT(22)
54#define _module_mp_ BIT(23)
55#define _module_hci_ops_os_c_ BIT(24)
56#define _module_rtl871x_ioctl_os_c BIT(25)
57#define _module_rtl8712_cmd_c_ BIT(26)
58#define _module_rtl8192c_xmit_c_ BIT(28)
59#define _module_hal_xmit_c_ BIT(28) /* duplication intentional */
60#define _module_efuse_ BIT(29)
61#define _module_rtl8712_recv_c_ BIT(30)
62#define _module_rtl8712_led_c_ BIT(31)
63
64#undef _MODULE_DEFINE_
65
66#if defined _RTW_XMIT_C_
67 #define _MODULE_DEFINE_ _module_rtl871x_xmit_c_
68#elif defined _XMIT_OSDEP_C_
69 #define _MODULE_DEFINE_ _module_xmit_osdep_c_
70#elif defined _RTW_RECV_C_
71 #define _MODULE_DEFINE_ _module_rtl871x_recv_c_
72#elif defined _RECV_OSDEP_C_
73 #define _MODULE_DEFINE_ _module_recv_osdep_c_
74#elif defined _RTW_MLME_C_
75 #define _MODULE_DEFINE_ _module_rtl871x_mlme_c_
76#elif defined _MLME_OSDEP_C_
77 #define _MODULE_DEFINE_ _module_mlme_osdep_c_
78#elif defined _RTW_MLME_EXT_C_
79 #define _MODULE_DEFINE_ 1
80#elif defined _RTW_STA_MGT_C_
81 #define _MODULE_DEFINE_ _module_rtl871x_sta_mgt_c_
82#elif defined _RTW_CMD_C_
83 #define _MODULE_DEFINE_ _module_rtl871x_cmd_c_
84#elif defined _CMD_OSDEP_C_
85 #define _MODULE_DEFINE_ _module_cmd_osdep_c_
86#elif defined _RTW_IO_C_
87 #define _MODULE_DEFINE_ _module_rtl871x_io_c_
88#elif defined _IO_OSDEP_C_
89 #define _MODULE_DEFINE_ _module_io_osdep_c_
90#elif defined _OS_INTFS_C_
91 #define _MODULE_DEFINE_ _module_os_intfs_c_
92#elif defined _RTW_SECURITY_C_
93 #define _MODULE_DEFINE_ _module_rtl871x_security_c_
94#elif defined _RTW_EEPROM_C_
95 #define _MODULE_DEFINE_ _module_rtl871x_eeprom_c_
96#elif defined _HAL_INTF_C_
97 #define _MODULE_DEFINE_ _module_hal_init_c_
98#elif (defined _HCI_HAL_INIT_C_) || (defined _SDIO_HALINIT_C_)
99 #define _MODULE_DEFINE_ _module_hci_hal_init_c_
100#elif defined _RTL871X_IOCTL_C_
101 #define _MODULE_DEFINE_ _module_rtl871x_ioctl_c_
102#elif defined _RTL871X_IOCTL_SET_C_
103 #define _MODULE_DEFINE_ _module_rtl871x_ioctl_set_c_
104#elif defined _RTL871X_IOCTL_QUERY_C_
105 #define _MODULE_DEFINE_ _module_rtl871x_ioctl_query_c_
106#elif defined _RTL871X_PWRCTRL_C_
107 #define _MODULE_DEFINE_ _module_rtl871x_pwrctrl_c_
108#elif defined _RTW_PWRCTRL_C_
109 #define _MODULE_DEFINE_ 1
110#elif defined _HCI_INTF_C_
111 #define _MODULE_DEFINE_ _module_hci_intfs_c_
112#elif defined _HCI_OPS_C_
113 #define _MODULE_DEFINE_ _module_hci_ops_c_
114#elif defined _SDIO_OPS_C_
115 #define _MODULE_DEFINE_ 1
116#elif defined _OSDEP_HCI_INTF_C_
117 #define _MODULE_DEFINE_ _module_hci_intfs_c_
118#elif defined _OSDEP_SERVICE_C_
119 #define _MODULE_DEFINE_ _module_osdep_service_c_
120#elif defined _HCI_OPS_OS_C_
121 #define _MODULE_DEFINE_ _module_hci_ops_os_c_
122#elif defined _RTL871X_IOCTL_LINUX_C_
123 #define _MODULE_DEFINE_ _module_rtl871x_ioctl_os_c
124#elif defined _RTL8712_CMD_C_
125 #define _MODULE_DEFINE_ _module_rtl8712_cmd_c_
126#elif defined _RTL8192C_XMIT_C_
127 #define _MODULE_DEFINE_ 1
128#elif defined _RTL8723AS_XMIT_C_
129 #define _MODULE_DEFINE_ 1
130#elif defined _RTL8712_RECV_C_
131 #define _MODULE_DEFINE_ _module_rtl8712_recv_c_
132#elif defined _RTL8192CU_RECV_C_
133 #define _MODULE_DEFINE_ _module_rtl8712_recv_c_
134#elif defined _RTL871X_MLME_EXT_C_
135 #define _MODULE_DEFINE_ _module_mlme_osdep_c_
136#elif defined _RTW_MP_C_
137 #define _MODULE_DEFINE_ _module_mp_
138#elif defined _RTW_MP_IOCTL_C_
139 #define _MODULE_DEFINE_ _module_mp_
140#elif defined _RTW_EFUSE_C_
141 #define _MODULE_DEFINE_ _module_efuse_
142#endif
143
144#define DRIVER_PREFIX "RTL8723AU: "
145#define DEBUG_LEVEL (_drv_err_)
146#define DBG_8723A_LEVEL(_level, fmt, arg...) \
147 do { \
148 if (_level <= GlobalDebugLevel23A) \
149 pr_info(DRIVER_PREFIX"ERROR " fmt, ##arg);\
150 } while (0)
151
152#define DBG_8723A(...) \
153 do { \
154 if (_drv_err_ <= GlobalDebugLevel23A) \
155 pr_info(DRIVER_PREFIX __VA_ARGS__); \
156 } while (0)
157
158#define MSG_8723A(...) \
159 do { \
160 if (_drv_err_ <= GlobalDebugLevel23A) \
161 pr_info(DRIVER_PREFIX __VA_ARGS__); \
162 } while (0)
163
164extern u32 GlobalDebugLevel23A;
165
166
167#define RT_TRACE(_Comp, _Level, Fmt) \
168do { \
169 if (_Level <= GlobalDebugLevel23A) { \
170 pr_info("%s [0x%08x,%d]", DRIVER_PREFIX, \
171 (unsigned int)_Comp, _Level); \
172 pr_info Fmt; \
173 } \
174} while (0)
175
176#define RT_PRINT_DATA(_Comp, _Level, _TitleString, _HexData, \
177 _HexDataLen) \
178 if (_Level <= GlobalDebugLevel23A) { \
179 int __i; \
180 u8 *ptr = (u8 *)_HexData; \
181 pr_info("%s", DRIVER_PREFIX); \
182 pr_info(_TitleString); \
183 for (__i = 0; __i < (int)_HexDataLen; __i++) { \
184 printk("%02X%s", ptr[__i], \
185 (((__i + 1) % 4) == 0) ? " " : " "); \
186 if (((__i + 1) % 16) == 0) \
187 printk("\n"); \
188 } \
189 printk("\n"); \
190 }
191
192#endif /* __RTW_DEBUG_H__ */
diff --git a/drivers/staging/rtl8723au/include/rtw_eeprom.h b/drivers/staging/rtl8723au/include/rtw_eeprom.h
new file mode 100644
index 000000000000..d008f032181b
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_eeprom.h
@@ -0,0 +1,135 @@
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 ******************************************************************************/
15#ifndef __RTW_EEPROM_H__
16#define __RTW_EEPROM_H__
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21#define RTL8712_EEPROM_ID 0x8712
22/* define EEPROM_MAX_SIZE 256 */
23
24#define HWSET_MAX_SIZE_512 512
25#define EEPROM_MAX_SIZE HWSET_MAX_SIZE_512
26
27#define CLOCK_RATE 50 /* 100us */
28
29/* EEPROM opcodes */
30#define EEPROM_READ_OPCODE 06
31#define EEPROM_WRITE_OPCODE 05
32#define EEPROM_ERASE_OPCODE 07
33#define EEPROM_EWEN_OPCODE 19 /* Erase/write enable */
34#define EEPROM_EWDS_OPCODE 16 /* Erase/write disable */
35
36/* Country codes */
37#define USA 0x555320
38#define EUROPE 0x1 /* temp, should be provided later */
39#define JAPAN 0x2 /* temp, should be provided later */
40
41#define EEPROM_CID_DEFAULT 0x0
42#define EEPROM_CID_ALPHA 0x1
43#define EEPROM_CID_Senao 0x3
44#define EEPROM_CID_NetCore 0x5
45#define EEPROM_CID_CAMEO 0X8
46#define EEPROM_CID_SITECOM 0x9
47#define EEPROM_CID_COREGA 0xB
48#define EEPROM_CID_EDIMAX_BELKIN 0xC
49#define EEPROM_CID_SERCOMM_BELKIN 0xE
50#define EEPROM_CID_CAMEO1 0xF
51#define EEPROM_CID_WNC_COREGA 0x12
52#define EEPROM_CID_CLEVO 0x13
53#define EEPROM_CID_WHQL 0xFE /* added by chiyoko for dtm, 20090108 */
54
55/* */
56/* Customer ID, note that: */
57/* This variable is initiailzed through EEPROM or registry, */
58/* however, its definition may be different with that in EEPROM for */
59/* EEPROM size consideration. So, we have to perform proper translation between them. */
60/* Besides, CustomerID of registry has precedence of that of EEPROM. */
61/* defined below. 060703, by rcnjko. */
62/* */
63enum rt_customer_id
64{
65 RT_CID_DEFAULT = 0,
66 RT_CID_8187_ALPHA0 = 1,
67 RT_CID_8187_SERCOMM_PS = 2,
68 RT_CID_8187_HW_LED = 3,
69 RT_CID_8187_NETGEAR = 4,
70 RT_CID_WHQL = 5,
71 RT_CID_819x_CAMEO = 6,
72 RT_CID_819x_RUNTOP = 7,
73 RT_CID_819x_Senao = 8,
74 RT_CID_TOSHIBA = 9, /* Merge by Jacken, 2008/01/31. */
75 RT_CID_819x_Netcore = 10,
76 RT_CID_Nettronix = 11,
77 RT_CID_DLINK = 12,
78 RT_CID_PRONET = 13,
79 RT_CID_COREGA = 14,
80 RT_CID_CHINA_MOBILE = 15,
81 RT_CID_819x_ALPHA = 16,
82 RT_CID_819x_Sitecom = 17,
83 RT_CID_CCX = 18, /* It's set under CCX logo test and isn't demanded for CCX functions, but for test behavior like retry limit and tx report. By Bruce, 2009-02-17. */
84 RT_CID_819x_Lenovo = 19,
85 RT_CID_819x_QMI = 20,
86 RT_CID_819x_Edimax_Belkin = 21,
87 RT_CID_819x_Sercomm_Belkin = 22,
88 RT_CID_819x_CAMEO1 = 23,
89 RT_CID_819x_MSI = 24,
90 RT_CID_819x_Acer = 25,
91 RT_CID_819x_AzWave_ASUS = 26,
92 RT_CID_819x_AzWave = 27, /* For AzWave in PCIe, The ID is AzWave use and not only Asus */
93 RT_CID_819x_HP = 28,
94 RT_CID_819x_WNC_COREGA = 29,
95 RT_CID_819x_Arcadyan_Belkin = 30,
96 RT_CID_819x_SAMSUNG = 31,
97 RT_CID_819x_CLEVO = 32,
98 RT_CID_819x_DELL = 33,
99 RT_CID_819x_PRONETS = 34,
100 RT_CID_819x_Edimax_ASUS = 35,
101 RT_CID_819x_CAMEO_NETGEAR = 36,
102 RT_CID_PLANEX = 37,
103 RT_CID_CC_C = 38,
104 RT_CID_819x_Xavi = 39,
105 RT_CID_819x_FUNAI_TV = 40,
106 RT_CID_819x_ALPHA_WD=41,
107};
108
109struct eeprom_priv {
110 u8 bautoload_fail_flag;
111 u8 bloadfile_fail_flag;
112 u8 bloadmac_fail_flag;
113 /* u8 bempty; */
114 /* u8 sys_config; */
115 u8 mac_addr[6]; /* PermanentAddress */
116 /* u8 config0; */
117 u16 channel_plan;
118 /* u8 country_string[3]; */
119 /* u8 tx_power_b[15]; */
120 /* u8 tx_power_g[15]; */
121 /* u8 tx_power_a[201]; */
122
123 u8 EepromOrEfuse;
124
125 u8 efuse_eeprom_data[HWSET_MAX_SIZE_512]; /* 92C:256bytes, 88E:512bytes, we use union set (512bytes) */
126};
127
128void eeprom_write16(struct rtw_adapter *padapter, u16 reg, u16 data);
129u16 eeprom_read16(struct rtw_adapter *padapter, u16 reg);
130void read_eeprom_content(struct rtw_adapter *padapter);
131void eeprom_read_sz(struct rtw_adapter * padapter, u16 reg,u8* data, u32 sz);
132
133void read_eeprom_content_by_attrib(struct rtw_adapter *padapter);
134
135#endif /* __RTL871X_EEPROM_H__ */
diff --git a/drivers/staging/rtl8723au/include/rtw_efuse.h b/drivers/staging/rtl8723au/include/rtw_efuse.h
new file mode 100644
index 000000000000..a7755056163f
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_efuse.h
@@ -0,0 +1,109 @@
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 *
15 ******************************************************************************/
16#ifndef __RTW_EFUSE_H__
17#define __RTW_EFUSE_H__
18
19#include <osdep_service.h>
20
21#define EFUSE_ERROE_HANDLE 1
22
23#define PG_STATE_HEADER 0x01
24#define PG_STATE_WORD_0 0x02
25#define PG_STATE_WORD_1 0x04
26#define PG_STATE_WORD_2 0x08
27#define PG_STATE_WORD_3 0x10
28#define PG_STATE_DATA 0x20
29
30#define PG_SWBYTE_H 0x01
31#define PG_SWBYTE_L 0x02
32
33#define PGPKT_DATA_SIZE 8
34
35#define EFUSE_WIFI 0
36#define EFUSE_BT 1
37
38enum _EFUSE_DEF_TYPE {
39 TYPE_EFUSE_MAX_SECTION = 0,
40 TYPE_EFUSE_REAL_CONTENT_LEN = 1,
41 TYPE_AVAILABLE_EFUSE_BYTES_BANK = 2,
42 TYPE_AVAILABLE_EFUSE_BYTES_TOTAL = 3,
43 TYPE_EFUSE_MAP_LEN = 4,
44 TYPE_EFUSE_PROTECT_BYTES_BANK = 5,
45 TYPE_EFUSE_CONTENT_LEN_BANK = 6,
46};
47
48/* E-Fuse */
49#define EFUSE_MAP_SIZE 256
50
51#define EFUSE_MAX_SIZE 512
52/* end of E-Fuse */
53
54#define EFUSE_MAX_MAP_LEN 256
55#define EFUSE_MAX_HW_SIZE 512
56#define EFUSE_MAX_SECTION_BASE 16
57
58#define EXT_HEADER(header) ((header & 0x1F ) == 0x0F)
59#define ALL_WORDS_DISABLED(wde) ((wde & 0x0F) == 0x0F)
60#define GET_HDR_OFFSET_2_0(header) ( (header & 0xE0) >> 5)
61
62#define EFUSE_REPEAT_THRESHOLD_ 3
63
64/* */
65/* The following is for BT Efuse definition */
66/* */
67#define EFUSE_BT_MAX_MAP_LEN 1024
68#define EFUSE_MAX_BANK 4
69#define EFUSE_MAX_BT_BANK (EFUSE_MAX_BANK-1)
70/* */
71/*--------------------------Define Parameters-------------------------------*/
72#define EFUSE_MAX_WORD_UNIT 4
73
74/*------------------------------Define structure----------------------------*/
75struct pg_pkt_struct {
76 u8 offset;
77 u8 word_en;
78 u8 data[8];
79 u8 word_cnts;
80};
81
82/*------------------------Export global variable----------------------------*/
83
84u8 efuse_GetCurrentSize23a(struct rtw_adapter *padapter, u16 *size);
85u16 efuse_GetMaxSize23a(struct rtw_adapter *padapter);
86u8 rtw_efuse_access23a(struct rtw_adapter *padapter, u8 bRead, u16 start_addr, u16 cnts, u8 *data);
87u8 rtw_efuse_map_read23a(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data);
88u8 rtw_efuse_map_write(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data);
89u8 rtw_BT_efuse_map_read23a(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data);
90u8 rtw_BT_efuse_map_write(struct rtw_adapter *padapter, u16 addr, u16 cnts, u8 *data);
91
92u16 Efuse_GetCurrentSize23a(struct rtw_adapter *pAdapter, u8 efuseType);
93u8 Efuse_CalculateWordCnts23a(u8 word_en);
94void ReadEFuseByte23a(struct rtw_adapter *Adapter, u16 _offset, u8 *pbuf);
95void EFUSE_GetEfuseDefinition23a(struct rtw_adapter *pAdapter, u8 efuseType, u8 type, void *pOut);
96u8 efuse_OneByteRead23a(struct rtw_adapter *pAdapter, u16 addr, u8 *data);
97u8 efuse_OneByteWrite23a(struct rtw_adapter *pAdapter, u16 addr, u8 data);
98
99void Efuse_PowerSwitch23a(struct rtw_adapter *pAdapter,u8 bWrite,u8 PwrState);
100int Efuse_PgPacketRead23a(struct rtw_adapter *pAdapter, u8 offset, u8 *data);
101int Efuse_PgPacketWrite23a(struct rtw_adapter *pAdapter, u8 offset, u8 word_en, u8 *data);
102void efuse_WordEnableDataRead23a(u8 word_en, u8 *sourdata, u8 *targetdata);
103u8 Efuse_WordEnableDataWrite23a(struct rtw_adapter *pAdapter, u16 efuse_addr, u8 word_en, u8 *data);
104
105u8 EFUSE_Read1Byte23a(struct rtw_adapter *pAdapter, u16 Address);
106void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType);
107void EFUSE_ShadowRead23a(struct rtw_adapter *pAdapter, u8 Type, u16 Offset, u32 *Value);
108
109#endif
diff --git a/drivers/staging/rtl8723au/include/rtw_event.h b/drivers/staging/rtl8723au/include/rtw_event.h
new file mode 100644
index 000000000000..bb20640e6855
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_event.h
@@ -0,0 +1,114 @@
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 ******************************************************************************/
15#ifndef _RTW_EVENT_H_
16#define _RTW_EVENT_H_
17
18#include <osdep_service.h>
19
20#include <wlan_bssdef.h>
21
22/*
23Used to report a bss has been scanned
24
25*/
26struct survey_event {
27 struct wlan_bssid_ex bss;
28};
29
30/*
31Used to report that the requested site survey has been done.
32
33bss_cnt indicates the number of bss that has been reported.
34
35
36*/
37struct surveydone_event {
38 unsigned int bss_cnt;
39
40};
41
42/*
43Used to report the link result of joinning the given bss
44
45
46join_res:
47-1: authentication fail
48-2: association fail
49> 0: TID
50
51*/
52struct joinbss_event {
53 struct wlan_network network;
54};
55
56/*
57Used to report a given STA has joinned the created BSS.
58It is used in AP/Ad-HoC(M) mode.
59
60
61*/
62struct stassoc_event {
63 unsigned char macaddr[6];
64 unsigned char rsvd[2];
65 int cam_id;
66
67};
68
69struct stadel_event {
70 unsigned char macaddr[6];
71 unsigned char rsvd[2]; /* for reason */
72 int mac_id;
73};
74
75struct addba_event
76{
77 unsigned int tid;
78};
79
80#define GEN_EVT_CODE(event) event ## _EVT_
81
82struct fwevent {
83 u32 parmsize;
84 void (*event_callback)(struct rtw_adapter *dev, u8 *pbuf);
85};
86
87
88#define C2HEVENT_SZ 32
89
90struct event_node{
91 unsigned char *node;
92 unsigned char evt_code;
93 unsigned short evt_sz;
94 volatile int *caller_ff_tail;
95 int caller_ff_sz;
96};
97
98struct c2hevent_queue {
99 volatile int head;
100 volatile int tail;
101 struct event_node nodes[C2HEVENT_SZ];
102 unsigned char seq;
103};
104
105#define NETWORK_QUEUE_SZ 4
106
107struct network_queue {
108 volatile int head;
109 volatile int tail;
110 struct wlan_bssid_ex networks[NETWORK_QUEUE_SZ];
111};
112
113
114#endif /* _WLANEVENT_H_ */
diff --git a/drivers/staging/rtl8723au/include/rtw_ht.h b/drivers/staging/rtl8723au/include/rtw_ht.h
new file mode 100644
index 000000000000..7fe0aa46f707
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_ht.h
@@ -0,0 +1,43 @@
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 ******************************************************************************/
15#ifndef _RTW_HT_H_
16#define _RTW_HT_H_
17
18#include <osdep_service.h>
19#include "linux/ieee80211.h"
20#include "wifi.h"
21
22struct ht_priv
23{
24 u32 ht_option;
25 u32 ampdu_enable;/* for enable Tx A-MPDU */
26 /* u8 baddbareq_issued[16]; */
27 u32 tx_amsdu_enable;/* for enable Tx A-MSDU */
28 u32 tx_amdsu_maxlen; /* 1: 8k, 0:4k ; default:8k, for tx */
29 u32 rx_ampdu_maxlen; /* for rx reordering ctrl win_sz, updated when join_callback. */
30
31 u8 bwmode;/* */
32 u8 ch_offset;/* PRIME_CHNL_OFFSET */
33 u8 sgi;/* short GI */
34
35 /* for processing Tx A-MPDU */
36 u8 agg_enable_bitmap;
37 /* u8 ADDBA_retry_count; */
38 u8 candidate_tid_bitmap;
39
40 struct ieee80211_ht_cap ht_cap;
41};
42
43#endif /* _RTL871X_HT_H_ */
diff --git a/drivers/staging/rtl8723au/include/rtw_io.h b/drivers/staging/rtl8723au/include/rtw_io.h
new file mode 100644
index 000000000000..8d39d800267d
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_io.h
@@ -0,0 +1,416 @@
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 ******************************************************************************/
15
16#ifndef _RTW_IO_H_
17#define _RTW_IO_H_
18
19#include <osdep_service.h>
20#include <osdep_intf.h>
21
22#include <asm/byteorder.h>
23#include <linux/semaphore.h>
24#include <linux/list.h>
25/* include <linux/smp_lock.h> */
26#include <linux/spinlock.h>
27#include <asm/atomic.h>
28
29#include <linux/usb.h>
30#include <linux/usb/ch9.h>
31
32#define rtw_usb_buffer_alloc(dev, size, dma) usb_alloc_coherent((dev), (size), (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL), (dma))
33#define rtw_usb_buffer_free(dev, size, addr, dma) usb_free_coherent((dev), (size), (addr), (dma))
34
35#define NUM_IOREQ 8
36
37#define MAX_PROT_SZ (64-16)
38
39#define _IOREADY 0
40#define _IO_WAIT_COMPLETE 1
41#define _IO_WAIT_RSP 2
42
43/* IO COMMAND TYPE */
44#define _IOSZ_MASK_ (0x7F)
45#define _IO_WRITE_ BIT(7)
46#define _IO_FIXED_ BIT(8)
47#define _IO_BURST_ BIT(9)
48#define _IO_BYTE_ BIT(10)
49#define _IO_HW_ BIT(11)
50#define _IO_WORD_ BIT(12)
51#define _IO_SYNC_ BIT(13)
52#define _IO_CMDMASK_ (0x1F80)
53
54
55/*
56 For prompt mode accessing, caller shall free io_req
57 Otherwise, io_handler will free io_req
58*/
59
60
61
62/* IO STATUS TYPE */
63#define _IO_ERR_ BIT(2)
64#define _IO_SUCCESS_ BIT(1)
65#define _IO_DONE_ BIT(0)
66
67
68#define IO_RD32 (_IO_SYNC_ | _IO_WORD_)
69#define IO_RD16 (_IO_SYNC_ | _IO_HW_)
70#define IO_RD8 (_IO_SYNC_ | _IO_BYTE_)
71
72#define IO_RD32_ASYNC (_IO_WORD_)
73#define IO_RD16_ASYNC (_IO_HW_)
74#define IO_RD8_ASYNC (_IO_BYTE_)
75
76#define IO_WR32 (_IO_WRITE_ | _IO_SYNC_ | _IO_WORD_)
77#define IO_WR16 (_IO_WRITE_ | _IO_SYNC_ | _IO_HW_)
78#define IO_WR8 (_IO_WRITE_ | _IO_SYNC_ | _IO_BYTE_)
79
80#define IO_WR32_ASYNC (_IO_WRITE_ | _IO_WORD_)
81#define IO_WR16_ASYNC (_IO_WRITE_ | _IO_HW_)
82#define IO_WR8_ASYNC (_IO_WRITE_ | _IO_BYTE_)
83
84/*
85
86 Only Sync. burst accessing is provided.
87
88*/
89
90#define IO_WR_BURST(x) (_IO_WRITE_ | _IO_SYNC_ | _IO_BURST_ | ( (x) & _IOSZ_MASK_))
91#define IO_RD_BURST(x) (_IO_SYNC_ | _IO_BURST_ | ( (x) & _IOSZ_MASK_))
92
93
94
95/* below is for the intf_option bit defition... */
96
97#define _INTF_ASYNC_ BIT(0) /* support async io */
98
99struct intf_priv;
100struct intf_hdl;
101struct io_queue;
102
103struct _io_ops
104{
105 u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
106 u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
107 u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
108
109 int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
110 int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
111 int (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
112 int (*_writeN)(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata);
113
114 int (*_write8_async)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
115 int (*_write16_async)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
116 int (*_write32_async)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
117
118 void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
119 void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
120
121 void (*_sync_irp_protocol_rw)(struct io_queue *pio_q);
122
123 u32 (*_read_interrupt)(struct intf_hdl *pintfhdl, u32 addr);
124
125 u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, struct recv_buf *rbuf);
126 u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, struct xmit_buf *pmem);
127
128 u32 (*_write_scsi)(struct intf_hdl *pintfhdl,u32 cnt, u8 *pmem);
129
130 void (*_read_port_cancel)(struct intf_hdl *pintfhdl);
131 void (*_write_port_cancel)(struct intf_hdl *pintfhdl);
132
133};
134
135struct io_req {
136 struct list_head list;
137 u32 addr;
138 volatile u32 val;
139 u32 command;
140 u32 status;
141 u8 *pbuf;
142 struct semaphore sema;
143
144 void (*_async_io_callback)(struct rtw_adapter *padater, struct io_req *pio_req, u8 *cnxt);
145 u8 *cnxt;
146};
147
148struct intf_hdl {
149 struct rtw_adapter *padapter;
150 struct dvobj_priv *pintf_dev;/* pointer to &(padapter->dvobjpriv); */
151
152 struct _io_ops io_ops;
153
154};
155
156struct reg_protocol_rd {
157
158#ifdef __LITTLE_ENDIAN
159
160 /* DW1 */
161 u32 NumOfTrans:4;
162 u32 Reserved1:4;
163 u32 Reserved2:24;
164 /* DW2 */
165 u32 ByteCount:7;
166 u32 WriteEnable:1; /* 0:read, 1:write */
167 u32 FixOrContinuous:1; /* 0:continuous, 1: Fix */
168 u32 BurstMode:1;
169 u32 Byte1Access:1;
170 u32 Byte2Access:1;
171 u32 Byte4Access:1;
172 u32 Reserved3:3;
173 u32 Reserved4:16;
174 /* DW3 */
175 u32 BusAddress;
176 /* DW4 */
177 /* u32 Value; */
178#else
179
180
181/* DW1 */
182 u32 Reserved1 :4;
183 u32 NumOfTrans :4;
184
185 u32 Reserved2 :24;
186
187 /* DW2 */
188 u32 WriteEnable : 1;
189 u32 ByteCount :7;
190
191
192 u32 Reserved3 : 3;
193 u32 Byte4Access : 1;
194
195 u32 Byte2Access : 1;
196 u32 Byte1Access : 1;
197 u32 BurstMode :1 ;
198 u32 FixOrContinuous : 1;
199
200 u32 Reserved4 : 16;
201
202 /* DW3 */
203 u32 BusAddress;
204
205 /* DW4 */
206 /* u32 Value; */
207
208#endif
209
210};
211
212
213struct reg_protocol_wt {
214
215
216#ifdef __LITTLE_ENDIAN
217
218 /* DW1 */
219 u32 NumOfTrans:4;
220 u32 Reserved1:4;
221 u32 Reserved2:24;
222 /* DW2 */
223 u32 ByteCount:7;
224 u32 WriteEnable:1; /* 0:read, 1:write */
225 u32 FixOrContinuous:1; /* 0:continuous, 1: Fix */
226 u32 BurstMode:1;
227 u32 Byte1Access:1;
228 u32 Byte2Access:1;
229 u32 Byte4Access:1;
230 u32 Reserved3:3;
231 u32 Reserved4:16;
232 /* DW3 */
233 u32 BusAddress;
234 /* DW4 */
235 u32 Value;
236
237#else
238 /* DW1 */
239 u32 Reserved1 :4;
240 u32 NumOfTrans :4;
241
242 u32 Reserved2 :24;
243
244 /* DW2 */
245 u32 WriteEnable : 1;
246 u32 ByteCount :7;
247
248 u32 Reserved3 : 3;
249 u32 Byte4Access : 1;
250
251 u32 Byte2Access : 1;
252 u32 Byte1Access : 1;
253 u32 BurstMode :1 ;
254 u32 FixOrContinuous : 1;
255
256 u32 Reserved4 : 16;
257
258 /* DW3 */
259 u32 BusAddress;
260
261 /* DW4 */
262 u32 Value;
263
264#endif
265
266};
267
268
269
270/*
271Below is the data structure used by _io_handler
272
273*/
274
275struct io_queue {
276 spinlock_t lock;
277 struct list_head free_ioreqs;
278 struct list_head pending; /* The io_req list that will be served in the single protocol read/write. */
279 struct list_head processing;
280 u8 *free_ioreqs_buf; /* 4-byte aligned */
281 u8 *pallocated_free_ioreqs_buf;
282 struct intf_hdl intf;
283};
284
285struct io_priv{
286
287 struct rtw_adapter *padapter;
288
289 struct intf_hdl intf;
290
291};
292
293uint ioreq_flush(struct rtw_adapter *adapter, struct io_queue *ioqueue);
294void sync_ioreq_enqueue(struct io_req *preq,struct io_queue *ioqueue);
295uint sync_ioreq_flush(struct rtw_adapter *adapter, struct io_queue *ioqueue);
296
297uint free_ioreq(struct io_req *preq, struct io_queue *pio_queue);
298struct io_req *alloc_ioreq(struct io_queue *pio_q);
299
300uint register_intf_hdl(u8 *dev, struct intf_hdl *pintfhdl);
301void unregister_intf_hdl(struct intf_hdl *pintfhdl);
302
303void _rtw_attrib_read(struct rtw_adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
304void _rtw_attrib_write(struct rtw_adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
305
306u8 _rtw_read823a(struct rtw_adapter *adapter, u32 addr);
307u16 _rtw_read1623a(struct rtw_adapter *adapter, u32 addr);
308u32 _rtw_read3223a(struct rtw_adapter *adapter, u32 addr);
309void _rtw_read_mem23a(struct rtw_adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
310void _rtw_read_port23a(struct rtw_adapter *adapter, u32 addr, u32 cnt, struct recv_buf *rbuf);
311void _rtw_read_port23a_cancel(struct rtw_adapter *adapter);
312
313int _rtw_write823a(struct rtw_adapter *adapter, u32 addr, u8 val);
314int _rtw_write1623a(struct rtw_adapter *adapter, u32 addr, u16 val);
315int _rtw_write3223a(struct rtw_adapter *adapter, u32 addr, u32 val);
316int _rtw_writeN23a(struct rtw_adapter *adapter, u32 addr, u32 length, u8 *pdata);
317
318int _rtw_write823a_async23a(struct rtw_adapter *adapter, u32 addr, u8 val);
319int _rtw_write1623a_async(struct rtw_adapter *adapter, u32 addr, u16 val);
320int _rtw_write3223a_async23a(struct rtw_adapter *adapter, u32 addr, u32 val);
321
322void _rtw_write_mem23a(struct rtw_adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
323u32 _rtw_write_port23a(struct rtw_adapter *adapter, u32 addr, u32 cnt, struct xmit_buf *pmem);
324u32 _rtw_write_port23a_and_wait23a(struct rtw_adapter *adapter, u32 addr, u32 cnt, struct xmit_buf *pmem, int timeout_ms);
325void _rtw_write_port23a_cancel(struct rtw_adapter *adapter);
326
327#ifdef DBG_IO
328bool match_read_sniff_ranges(u16 addr, u16 len);
329bool match_write_sniff_ranges(u16 addr, u16 len);
330
331u8 dbg_rtw_read823a(struct rtw_adapter *adapter, u32 addr, const char *caller, const int line);
332u16 dbg_rtw_read1623a(struct rtw_adapter *adapter, u32 addr, const char *caller, const int line);
333u32 dbg_rtw_read3223a(struct rtw_adapter *adapter, u32 addr, const char *caller, const int line);
334
335int dbg_rtw_write823a(struct rtw_adapter *adapter, u32 addr, u8 val, const char *caller, const int line);
336int dbg_rtw_write1623a(struct rtw_adapter *adapter, u32 addr, u16 val, const char *caller, const int line);
337int dbg_rtw_write3223a(struct rtw_adapter *adapter, u32 addr, u32 val, const char *caller, const int line);
338int dbg_rtw_writeN23a(struct rtw_adapter *adapter, u32 addr ,u32 length , u8 *data, const char *caller, const int line);
339
340#define rtw_read8(adapter, addr) dbg_rtw_read823a((adapter), (addr), __FUNCTION__, __LINE__)
341#define rtw_read16(adapter, addr) dbg_rtw_read1623a((adapter), (addr), __FUNCTION__, __LINE__)
342#define rtw_read32(adapter, addr) dbg_rtw_read3223a((adapter), (addr), __FUNCTION__, __LINE__)
343#define rtw_read_mem(adapter, addr, cnt, mem) _rtw_read_mem23a((adapter), (addr), (cnt), (mem))
344#define rtw_read_port(adapter, addr, cnt, mem) _rtw_read_port23a((adapter), (addr), (cnt), (mem))
345#define rtw_read_port_cancel(adapter) _rtw_read_port23a_cancel((adapter))
346
347#define rtw_write8(adapter, addr, val) dbg_rtw_write823a((adapter), (addr), (val), __FUNCTION__, __LINE__)
348#define rtw_write16(adapter, addr, val) dbg_rtw_write1623a((adapter), (addr), (val), __FUNCTION__, __LINE__)
349#define rtw_write32(adapter, addr, val) dbg_rtw_write3223a((adapter), (addr), (val), __FUNCTION__, __LINE__)
350#define rtw_writeN(adapter, addr, length, data) dbg_rtw_writeN23a((adapter), (addr), (length), (data), __FUNCTION__, __LINE__)
351
352#define rtw_write8_async(adapter, addr, val) _rtw_write823a_async23a((adapter), (addr), (val))
353#define rtw_write16_async(adapter, addr, val) _rtw_write1623a_async((adapter), (addr), (val))
354#define rtw_write32_async(adapter, addr, val) _rtw_write3223a_async23a((adapter), (addr), (val))
355
356#define rtw_write_mem(adapter, addr, cnt, mem) _rtw_write_mem23a((adapter), addr, cnt, mem)
357#define rtw_write_port(adapter, addr, cnt, mem) _rtw_write_port23a(adapter, addr, cnt, mem)
358#define rtw_write_port_and_wait(adapter, addr, cnt, mem, timeout_ms) _rtw_write_port23a_and_wait23a((adapter), (addr), (cnt), (mem), (timeout_ms))
359#define rtw_write_port_cancel(adapter) _rtw_write_port23a_cancel(adapter)
360#else /* DBG_IO */
361#define rtw_read8(adapter, addr) _rtw_read823a((adapter), (addr))
362#define rtw_read16(adapter, addr) _rtw_read1623a((adapter), (addr))
363#define rtw_read32(adapter, addr) _rtw_read3223a((adapter), (addr))
364#define rtw_read_mem(adapter, addr, cnt, mem) _rtw_read_mem23a((adapter), (addr), (cnt), (mem))
365#define rtw_read_port(adapter, addr, cnt, mem) _rtw_read_port23a((adapter), (addr), (cnt), (mem))
366#define rtw_read_port_cancel(adapter) _rtw_read_port23a_cancel((adapter))
367
368#define rtw_write8(adapter, addr, val) _rtw_write823a((adapter), (addr), (val))
369#define rtw_write16(adapter, addr, val) _rtw_write1623a((adapter), (addr), (val))
370#define rtw_write32(adapter, addr, val) _rtw_write3223a((adapter), (addr), (val))
371#define rtw_writeN(adapter, addr, length, data) _rtw_writeN23a((adapter), (addr), (length), (data))
372
373#define rtw_write8_async(adapter, addr, val) _rtw_write823a_async23a((adapter), (addr), (val))
374#define rtw_write16_async(adapter, addr, val) _rtw_write1623a_async((adapter), (addr), (val))
375#define rtw_write32_async(adapter, addr, val) _rtw_write3223a_async23a((adapter), (addr), (val))
376
377#define rtw_write_mem(adapter, addr, cnt, mem) _rtw_write_mem23a((adapter), (addr), (cnt), (mem))
378#define rtw_write_port(adapter, addr, cnt, mem) _rtw_write_port23a((adapter), (addr), (cnt), (mem))
379#define rtw_write_port_and_wait(adapter, addr, cnt, mem, timeout_ms) _rtw_write_port23a_and_wait23a((adapter), (addr), (cnt), (mem), (timeout_ms))
380#define rtw_write_port_cancel(adapter) _rtw_write_port23a_cancel((adapter))
381#endif /* DBG_IO */
382
383void rtw_write_scsi(struct rtw_adapter *adapter, u32 cnt, u8 *pmem);
384
385/* ioreq */
386void ioreq_read8(struct rtw_adapter *adapter, u32 addr, u8 *pval);
387void ioreq_read16(struct rtw_adapter *adapter, u32 addr, u16 *pval);
388void ioreq_read32(struct rtw_adapter *adapter, u32 addr, u32 *pval);
389void ioreq_write8(struct rtw_adapter *adapter, u32 addr, u8 val);
390void ioreq_write16(struct rtw_adapter *adapter, u32 addr, u16 val);
391void ioreq_write32(struct rtw_adapter *adapter, u32 addr, u32 val);
392
393int rtw_init_io_priv23a(struct rtw_adapter *padapter, void (*set_intf_ops)(struct _io_ops *pops));
394
395uint alloc_io_queue(struct rtw_adapter *adapter);
396void free_io_queue(struct rtw_adapter *adapter);
397void async_bus_io(struct io_queue *pio_q);
398void bus_sync_io(struct io_queue *pio_q);
399u32 _ioreq2rwmem(struct io_queue *pio_q);
400void dev_power_down(struct rtw_adapter * Adapter, u8 bpwrup);
401
402#define PlatformEFIOWrite1Byte(_a,_b,_c) \
403 rtw_write8(_a,_b,_c)
404#define PlatformEFIOWrite2Byte(_a,_b,_c) \
405 rtw_write16(_a,_b,_c)
406#define PlatformEFIOWrite4Byte(_a,_b,_c) \
407 rtw_write32(_a,_b,_c)
408
409#define PlatformEFIORead1Byte(_a,_b) \
410 rtw_read8(_a,_b)
411#define PlatformEFIORead2Byte(_a,_b) \
412 rtw_read16(_a,_b)
413#define PlatformEFIORead4Byte(_a,_b) \
414 rtw_read32(_a,_b)
415
416#endif /* _RTL8711_IO_H_ */
diff --git a/drivers/staging/rtl8723au/include/rtw_ioctl.h b/drivers/staging/rtl8723au/include/rtw_ioctl.h
new file mode 100644
index 000000000000..629eec8a7023
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_ioctl.h
@@ -0,0 +1,26 @@
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 ******************************************************************************/
15#ifndef _RTW_IOCTL_H_
16#define _RTW_IOCTL_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21
22#if defined(CONFIG_WIRELESS_EXT)
23extern struct iw_handler_def rtw_handlers_def;
24#endif
25
26#endif /* #ifndef __INC_CEINFO_ */
diff --git a/drivers/staging/rtl8723au/include/rtw_ioctl_set.h b/drivers/staging/rtl8723au/include/rtw_ioctl_set.h
new file mode 100644
index 000000000000..18ad2a873350
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_ioctl_set.h
@@ -0,0 +1,39 @@
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 ******************************************************************************/
15#ifndef __RTW_IOCTL_SET_H_
16#define __RTW_IOCTL_SET_H_
17
18#include <drv_types.h>
19
20
21struct bssid_info {
22 unsigned char BSSID[6];
23 u8 PMKID[16];
24};
25
26u8 rtw_set_802_11_authentication_mode23a(struct rtw_adapter *pdapter,
27 enum ndis_802_11_auth_mode authmode);
28u8 rtw_set_802_11_add_wep23a(struct rtw_adapter * padapter,
29 struct ndis_802_11_wep *wep);
30u8 rtw_set_802_11_bssid23a_list_scan(struct rtw_adapter *padapter,
31 struct cfg80211_ssid *pssid, int ssid_max_num);
32u8 rtw_set_802_11_infrastructure_mode23a(struct rtw_adapter *padapter,
33 enum ndis_802_11_net_infra networktype);
34u8 rtw_set_802_11_ssid23a(struct rtw_adapter * padapter, struct cfg80211_ssid * ssid);
35
36u16 rtw_get_cur_max_rate23a(struct rtw_adapter *adapter);
37s32 FillH2CCmd(struct rtw_adapter *padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer);
38
39#endif
diff --git a/drivers/staging/rtl8723au/include/rtw_led.h b/drivers/staging/rtl8723au/include/rtw_led.h
new file mode 100644
index 000000000000..c071da587efd
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_led.h
@@ -0,0 +1,181 @@
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 ******************************************************************************/
15#ifndef __RTW_LED_H_
16#define __RTW_LED_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21#define MSECS(t) (HZ * ((t) / 1000) + (HZ * ((t) % 1000)) / 1000)
22
23#define LED_BLINK_NORMAL_INTERVAL 100
24#define LED_BLINK_SLOWLY_INTERVAL 200
25#define LED_BLINK_LONG_INTERVAL 400
26
27#define LED_BLINK_NO_LINK_INTERVAL_ALPHA 1000
28#define LED_BLINK_LINK_INTERVAL_ALPHA 500 /* 500 */
29#define LED_BLINK_SCAN_INTERVAL_ALPHA 180 /* 150 */
30#define LED_BLINK_FASTER_INTERVAL_ALPHA 50
31#define LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA 5000
32
33#define LED_BLINK_NORMAL_INTERVAL_NETTRONIX 100
34#define LED_BLINK_SLOWLY_INTERVAL_NETTRONIX 2000
35
36#define LED_BLINK_SLOWLY_INTERVAL_PORNET 1000
37#define LED_BLINK_NORMAL_INTERVAL_PORNET 100
38
39#define LED_BLINK_FAST_INTERVAL_BITLAND 30
40
41/* 060403, rcnjko: Customized for AzWave. */
42#define LED_CM2_BLINK_ON_INTERVAL 250
43#define LED_CM2_BLINK_OFF_INTERVAL 4750
44
45#define LED_CM8_BLINK_INTERVAL 500 /* for QMI */
46#define LED_CM8_BLINK_OFF_INTERVAL 3750 /* for QMI */
47
48/* 080124, lanhsin: Customized for RunTop */
49#define LED_RunTop_BLINK_INTERVAL 300
50
51/* 060421, rcnjko: Customized for Sercomm Printer Server case. */
52#define LED_CM3_BLINK_INTERVAL 1500
53
54enum led_ctl_mode {
55 LED_CTL_POWER_ON = 1,
56 LED_CTL_LINK = 2,
57 LED_CTL_NO_LINK = 3,
58 LED_CTL_TX = 4,
59 LED_CTL_RX = 5,
60 LED_CTL_SITE_SURVEY = 6,
61 LED_CTL_POWER_OFF = 7,
62 LED_CTL_START_TO_LINK = 8,
63 LED_CTL_START_WPS = 9,
64 LED_CTL_STOP_WPS = 10,
65 LED_CTL_START_WPS_BOTTON = 11, /* added for runtop */
66 LED_CTL_STOP_WPS_FAIL = 12, /* added for ALPHA */
67 LED_CTL_STOP_WPS_FAIL_OVERLAP = 13, /* added for BELKIN */
68 LED_CTL_CONNECTION_NO_TRANSFER = 14,
69};
70
71enum led_state_872x {
72 LED_UNKNOWN = 0,
73 RTW_LED_ON = 1,
74 RTW_LED_OFF = 2,
75 LED_BLINK_NORMAL = 3,
76 LED_BLINK_SLOWLY = 4,
77 LED_BLINK_POWER_ON = 5,
78 LED_BLINK_SCAN = 6, /* LED is blinking during scanning period, the # of times to blink is depend on time for scanning. */
79 LED_BLINK_NO_LINK = 7, /* LED is blinking during no link state. */
80 LED_BLINK_StartToBlink = 8,/* Customzied for Sercomm Printer Server case */
81 LED_BLINK_TXRX = 9,
82 LED_BLINK_WPS = 10, /* LED is blinkg during WPS communication */
83 LED_BLINK_WPS_STOP = 11, /* for ALPHA */
84 LED_BLINK_WPS_STOP_OVERLAP = 12, /* for BELKIN */
85 LED_BLINK_RUNTOP = 13, /* Customized for RunTop */
86 LED_BLINK_CAMEO = 14,
87 LED_BLINK_XAVI = 15,
88 LED_BLINK_ALWAYS_ON = 16,
89};
90
91enum led_pin_8723a {
92 LED_PIN_NULL = 0,
93 LED_PIN_LED0 = 1,
94 LED_PIN_LED1 = 2,
95 LED_PIN_LED2 = 3,
96 LED_PIN_GPIO0 = 4,
97};
98
99struct led_8723a {
100 struct rtw_adapter *padapter;
101
102 enum led_pin_8723a LedPin; /* Identify how to implement this SW led. */
103 enum led_state_872x CurrLedState; /* Current LED state. */
104 enum led_state_872x BlinkingLedState; /* Next state for blinking, either RTW_LED_ON or RTW_LED_OFF are. */
105
106 u8 bLedOn; /* true if LED is ON, false if LED is OFF. */
107
108 u8 bLedBlinkInProgress; /* true if it is blinking, false o.w.. */
109
110 u8 bLedWPSBlinkInProgress;
111
112 u32 BlinkTimes; /* Number of times to toggle led state for blinking. */
113
114 struct timer_list BlinkTimer; /* Timer object for led blinking. */
115
116 u8 bSWLedCtrl;
117
118 /* ALPHA, added by chiyoko, 20090106 */
119 u8 bLedNoLinkBlinkInProgress;
120 u8 bLedLinkBlinkInProgress;
121 u8 bLedStartToLinkBlinkInProgress;
122 u8 bLedScanBlinkInProgress;
123
124 struct work_struct BlinkWorkItem; /* Workitem used by BlinkTimer to manipulate H/W to blink LED. */
125};
126
127#define IS_LED_WPS_BLINKING(_LED_871x) (((struct led_8723a *)_LED_871x)->CurrLedState==LED_BLINK_WPS \
128 || ((struct led_8723a *)_LED_871x)->CurrLedState==LED_BLINK_WPS_STOP \
129 || ((struct led_8723a *)_LED_871x)->bLedWPSBlinkInProgress)
130
131#define IS_LED_BLINKING(_LED_871x) (((struct led_8723a *)_LED_871x)->bLedWPSBlinkInProgress \
132 ||((struct led_8723a *)_LED_871x)->bLedScanBlinkInProgress)
133
134/* */
135/* LED customization. */
136/* */
137
138enum led_strategy_8723a {
139 SW_LED_MODE0 = 0, /* SW control 1 LED via GPIO0. It is default option. */
140 SW_LED_MODE1= 1, /* 2 LEDs, through LED0 and LED1. For ALPHA. */
141 SW_LED_MODE2 = 2, /* SW control 1 LED via GPIO0, customized for AzWave 8187 minicard. */
142 SW_LED_MODE3 = 3, /* SW control 1 LED via GPIO0, customized for Sercomm Printer Server case. */
143 SW_LED_MODE4 = 4, /* for Edimax / Belkin */
144 SW_LED_MODE5 = 5, /* for Sercomm / Belkin */
145 SW_LED_MODE6 = 6, /* for 88CU minicard, porting from ce SW_LED_MODE7 */
146 HW_LED = 50, /* HW control 2 LEDs, LED0 and LED1 (there are 4 different control modes, see MAC.CONFIG1 for details.) */
147 LED_ST_NONE = 99,
148};
149
150void LedControl871x23a(struct rtw_adapter *padapter, enum led_ctl_mode LedAction);
151
152struct led_priv{
153 /* add for led controll */
154 struct led_8723a SwLed0;
155 struct led_8723a SwLed1;
156 enum led_strategy_8723a LedStrategy;
157 u8 bRegUseLed;
158 void (*LedControlHandler)(struct rtw_adapter *padapter, enum led_ctl_mode LedAction);
159 /* add for led controll */
160};
161
162#define rtw_led_control(adapter, LedAction)
163
164void BlinkWorkItemCallback23a(struct work_struct *work);
165
166void ResetLedStatus23a(struct led_8723a *pLed);
167
168void
169InitLed871x23a(
170 struct rtw_adapter *padapter,
171 struct led_8723a *pLed,
172 enum led_pin_8723a LedPin
173);
174
175void
176DeInitLed871x23a(struct led_8723a *pLed);
177
178/* hal... */
179void BlinkHandler23a(struct led_8723a *pLed);
180
181#endif /* __RTW_LED_H_ */
diff --git a/drivers/staging/rtl8723au/include/rtw_mlme.h b/drivers/staging/rtl8723au/include/rtw_mlme.h
new file mode 100644
index 000000000000..31f96f39b498
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_mlme.h
@@ -0,0 +1,624 @@
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 *
15 ******************************************************************************/
16#ifndef __RTW_MLME_H_
17#define __RTW_MLME_H_
18
19#include <osdep_service.h>
20#include <mlme_osdep.h>
21#include <drv_types.h>
22#include <wlan_bssdef.h>
23
24#define MAX_BSS_CNT 128
25#define MAX_JOIN_TIMEOUT 6500
26
27/* Increase the scanning timeout because of increasing the SURVEY_TO value. */
28
29#define SCANNING_TIMEOUT 8000
30
31#define SCAN_INTERVAL (30) /* unit:2sec, 30*2 = 60sec */
32
33#define SCANQUEUE_LIFETIME 20 /* unit:sec */
34
35#define WIFI_NULL_STATE 0x00000000
36
37#define WIFI_ASOC_STATE 0x00000001 /* Under Linked state.*/
38#define WIFI_REASOC_STATE 0x00000002
39#define WIFI_SLEEP_STATE 0x00000004
40#define WIFI_STATION_STATE 0x00000008
41
42#define WIFI_AP_STATE 0x00000010
43#define WIFI_ADHOC_STATE 0x00000020
44#define WIFI_ADHOC_MASTER_STATE 0x00000040
45#define WIFI_UNDER_LINKING 0x00000080
46
47#define WIFI_UNDER_WPS 0x00000100
48#define WIFI_STA_ALIVE_CHK_STATE 0x00000400
49/* to indicate the station is under site surveying */
50#define WIFI_SITE_MONITOR 0x00000800
51
52#define WIFI_MP_STATE 0x00010000
53#define WIFI_MP_CTX_BACKGROUND 0x00020000 /* in continous tx background */
54#define WIFI_MP_CTX_ST 0x00040000 /* in continous tx with single-tone */
55#define WIFI_MP_CTX_BACKGROUND_PENDING 0x00080000 /* pending in continous tx background due to out of skb */
56#define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continous tx */
57#define WIFI_MP_CTX_CCK_CS 0x00200000 /* in continous tx with carrier suppression */
58#define WIFI_MP_LPBK_STATE 0x00400000
59
60#define _FW_UNDER_LINKING WIFI_UNDER_LINKING
61#define _FW_LINKED WIFI_ASOC_STATE
62#define _FW_UNDER_SURVEY WIFI_SITE_MONITOR
63
64
65enum dot11AuthAlgrthmNum {
66 dot11AuthAlgrthm_Open = 0,
67 dot11AuthAlgrthm_Shared,
68 dot11AuthAlgrthm_8021X,
69 dot11AuthAlgrthm_Auto,
70 dot11AuthAlgrthm_MaxNum
71};
72
73/* Scan type including active and passive scan. */
74enum rt_scan_type {
75 SCAN_PASSIVE,
76 SCAN_ACTIVE,
77 SCAN_MIX,
78};
79
80enum {
81 GHZ24_50 = 0,
82 GHZ_50,
83 GHZ_24,
84};
85
86enum SCAN_RESULT_TYPE {
87 SCAN_RESULT_P2P_ONLY = 0, /* Will return all the P2P devices. */
88 SCAN_RESULT_ALL = 1, /* Will return all the scanned device, include AP. */
89 SCAN_RESULT_WFD_TYPE = 2 /* Will just return the correct WFD device. */
90 /* If this device is Miracast sink device, it will just return all the Miracast source devices. */
91};
92
93/*
94
95there are several "locks" in mlme_priv,
96since mlme_priv is a shared resource between many threads,
97like ISR/Call-Back functions, the OID handlers, and even timer functions.
98
99
100Each _queue has its own locks, already.
101Other items are protected by mlme_priv.lock.
102
103To avoid possible dead lock, any thread trying to modifiying mlme_priv
104SHALL not lock up more than one locks at a time!
105*/
106
107#define traffic_threshold 10
108#define traffic_scan_period 500
109
110struct sitesurvey_ctrl {
111 u64 last_tx_pkts;
112 uint last_rx_pkts;
113 int traffic_busy;
114 struct timer_list sitesurvey_ctrl_timer;
115};
116
117struct rt_link_detect {
118 u32 NumTxOkInPeriod;
119 u32 NumRxOkInPeriod;
120 u32 NumRxUnicastOkInPeriod;
121 bool bBusyTraffic;
122 bool bTxBusyTraffic;
123 bool bRxBusyTraffic;
124 bool bHigherBusyTraffic; /* For interrupt migration purpose. */
125 bool bHigherBusyRxTraffic; /* We may disable Tx interrupt according as Rx traffic. */
126 bool bHigherBusyTxTraffic; /* We may disable Tx interrupt according as Tx traffic. */
127};
128
129struct profile_info {
130 u8 ssidlen;
131 u8 ssid[IEEE80211_MAX_SSID_LEN];
132 u8 peermac[ETH_ALEN];
133};
134
135struct tx_invite_req_info {
136 u8 token;
137 u8 benable;
138 u8 go_ssid[IEEE80211_MAX_SSID_LEN];
139 u8 ssidlen;
140 u8 go_bssid[ETH_ALEN];
141 u8 peer_macaddr[ETH_ALEN];
142 u8 operating_ch; /* This information will be set by using the p2p_set op_ch = x */
143 u8 peer_ch; /* The listen channel for peer P2P device */
144
145};
146
147struct tx_invite_resp_info {
148 u8 token; /* Used to record the dialog token of p2p invitation request frame. */
149};
150
151#ifdef CONFIG_8723AU_P2P
152
153struct wifi_display_info {
154 u16 wfd_enable; /* Enable/Disable the WFD function. */
155 u16 rtsp_ctrlport; /* TCP port number at which the this WFD device listens for RTSP messages */
156 u16 peer_rtsp_ctrlport; /* TCP port number at which the peer WFD device listens for RTSP messages */
157 /* This filed should be filled when receiving the gropu negotiation request */
158
159 u8 peer_session_avail; /* WFD session is available or not for the peer wfd device. */
160 /* This variable will be set when sending the provisioning discovery request to peer WFD device. */
161 /* And this variable will be reset when it is read by using the iwpriv p2p_get wfd_sa command. */
162 u8 ip_address[4];
163 u8 peer_ip_address[4];
164 u8 wfd_pc; /* WFD preferred connection */
165 /* 0 -> Prefer to use the P2P for WFD connection on peer side. */
166 /* 1 -> Prefer to use the TDLS for WFD connection on peer side. */
167
168 u8 wfd_device_type;/* WFD Device Type */
169 /* 0 -> WFD Source Device */
170 /* 1 -> WFD Primary Sink Device */
171 enum SCAN_RESULT_TYPE scan_result_type; /* Used when P2P is enable. This parameter will impact the scan result. */
172};
173#endif /* CONFIG_8723AU_P2P */
174
175struct tx_provdisc_req_info {
176 u16 wps_config_method_request; /* Used when sending the provisioning request frame */
177 u16 peer_channel_num[2]; /* The channel number which the receiver stands. */
178 struct cfg80211_ssid ssid;
179 u8 peerDevAddr[ETH_ALEN]; /* Peer device address */
180 u8 peerIFAddr[ETH_ALEN]; /* Peer interface address */
181 u8 benable; /* This provision discovery request frame is trigger to send or not */
182};
183
184struct rx_provdisc_req_info { /* When peer device issue prov_disc_req first, we should store the following informations */
185 u8 peerDevAddr[ETH_ALEN]; /* Peer device address */
186 u8 strconfig_method_desc_of_prov_disc_req[4]; /* description for the config method located in the provisioning discovery request frame. */
187 /* The UI must know this information to know which config method the remote p2p device is requiring. */
188};
189
190struct tx_nego_req_info {
191 u16 peer_channel_num[2]; /* The channel number which the receiver stands. */
192 u8 peerDevAddr[ETH_ALEN];/* Peer device address */
193 u8 benable; /* This negoitation request frame is trigger to send or not */
194};
195
196struct group_id_info {
197 u8 go_device_addr[ETH_ALEN]; /*The GO's device address of P2P group */
198 u8 ssid[IEEE80211_MAX_SSID_LEN]; /* The SSID of this P2P group */
199};
200
201struct scan_limit_info {
202 u8 scan_op_ch_only; /* When this flag is set, the driver should just scan the operation channel */
203 u8 operation_ch[2]; /* Store the operation channel of invitation request frame */
204};
205
206struct cfg80211_wifidirect_info {
207 struct timer_list remain_on_ch_timer;
208 u8 restore_channel;
209 struct ieee80211_channel remain_on_ch_channel;
210 enum nl80211_channel_type remain_on_ch_type;
211 u64 remain_on_ch_cookie;
212 bool is_ro_ch;
213};
214
215struct wifidirect_info {
216 struct rtw_adapter *padapter;
217 struct timer_list find_phase_timer;
218 struct timer_list restore_p2p_state_timer;
219
220 /* Used to do the scanning. After confirming the peer is availalble, the driver transmits the P2P frame to peer. */
221 struct timer_list pre_tx_scan_timer;
222 struct timer_list reset_ch_sitesurvey;
223 struct timer_list reset_ch_sitesurvey2; /* Just for resetting the scan limit function by using p2p nego */
224 struct tx_provdisc_req_info tx_prov_disc_info;
225 struct rx_provdisc_req_info rx_prov_disc_info;
226 struct tx_invite_req_info invitereq_info;
227 struct profile_info profileinfo[P2P_MAX_PERSISTENT_GROUP_NUM]; /* Store the profile information of persistent group */
228 struct tx_invite_resp_info inviteresp_info;
229 struct tx_nego_req_info nego_req_info;
230 struct group_id_info groupid_info; /* Store the group id information when doing the group negotiation handshake. */
231 struct scan_limit_info rx_invitereq_info; /* Used for get the limit scan channel from the Invitation procedure */
232 struct scan_limit_info p2p_info; /* Used for get the limit scan channel from the P2P negotiation handshake */
233#ifdef CONFIG_8723AU_P2P
234 struct wifi_display_info *wfd_info;
235#endif
236 enum P2P_ROLE role;
237 enum P2P_STATE pre_p2p_state;
238 enum P2P_STATE p2p_state;
239 u8 device_addr[ETH_ALEN]; /* The device address should be the mac address of this device. */
240 u8 interface_addr[ETH_ALEN];
241 u8 social_chan[4];
242 u8 listen_channel;
243 u8 operating_channel;
244 u8 listen_dwell; /* This value should be between 1 and 3 */
245 u8 support_rate[8];
246 u8 p2p_wildcard_ssid[P2P_WILDCARD_SSID_LEN];
247 u8 intent; /* should only include the intent value. */
248 u8 p2p_peer_interface_addr[ETH_ALEN];
249 u8 p2p_peer_device_addr[ETH_ALEN];
250 u8 peer_intent; /* Included the intent value and tie breaker value. */
251 u8 device_name[WPS_MAX_DEVICE_NAME_LEN]; /* Device name for displaying on searching device screen */
252 u8 device_name_len;
253 u8 profileindex; /* Used to point to the index of profileinfo array */
254 u8 peer_operating_ch;
255 u8 find_phase_state_exchange_cnt;
256 u16 device_password_id_for_nego; /* The device password ID for group negotation */
257 u8 negotiation_dialog_token;
258 /* SSID information for group negotitation */
259 u8 nego_ssid[IEEE80211_MAX_SSID_LEN];
260 u8 nego_ssidlen;
261 u8 p2p_group_ssid[IEEE80211_MAX_SSID_LEN];
262 u8 p2p_group_ssid_len;
263 u8 persistent_supported; /* Flag to know the persistent function should be supported or not. */
264 /* In the Sigma test, the Sigma will provide this enable from the sta_set_p2p CAPI. */
265 /* 0: disable */
266 /* 1: enable */
267 u8 session_available; /* Flag to set the WFD session available to enable or disable "by Sigma" */
268 /* In the Sigma test, the Sigma will disable the session available by using the sta_preset CAPI. */
269 /* 0: disable */
270 /* 1: enable */
271
272 u8 wfd_tdls_enable; /* Flag to enable or disable the TDLS by WFD Sigma */
273 /* 0: disable */
274 /* 1: enable */
275 u8 wfd_tdls_weaksec; /* Flag to enable or disable the weak security function for TDLS by WFD Sigma */
276 /* 0: disable */
277 /* In this case, the driver can't issue the tdsl setup request frame. */
278 /* 1: enable */
279 /* In this case, the driver can issue the tdls setup request frame */
280 /* even the current security is weak security. */
281
282 enum P2P_WPSINFO ui_got_wps_info; /* This field will store the WPS value (PIN value or PBC) that UI had got from the user. */
283 u16 supported_wps_cm; /* This field describes the WPS config method which this driver supported. */
284 /* The value should be the combination of config method defined in page104 of WPS v2.0 spec. */
285 uint channel_list_attr_len; /* This field will contain the length of body of P2P Channel List attribute of group negotitation response frame. */
286 u8 channel_list_attr[100]; /* This field will contain the body of P2P Channel List attribute of group negotitation response frame. */
287 /* We will use the channel_cnt and channel_list fields when constructing the group negotitation confirm frame. */
288#ifdef CONFIG_8723AU_P2P
289 enum P2P_PS_MODE p2p_ps_mode; /* indicate p2p ps mode */
290 enum P2P_PS_STATE p2p_ps_state; /* indicate p2p ps state */
291 u8 noa_index; /* Identifies and instance of Notice of Absence timing. */
292 u8 ctwindow; /* Client traffic window. A period of time in TU after TBTT. */
293 u8 opp_ps; /* opportunistic power save. */
294 u8 noa_num; /* number of NoA descriptor in P2P IE. */
295 u8 noa_count[P2P_MAX_NOA_NUM]; /* Count for owner, Type of client. */
296 u32 noa_duration[P2P_MAX_NOA_NUM]; /* Max duration for owner, preferred or min acceptable duration for client. */
297 u32 noa_interval[P2P_MAX_NOA_NUM]; /* Length of interval for owner, preferred or max acceptable interval of client. */
298 u32 noa_start_time[P2P_MAX_NOA_NUM]; /* schedule expressed in terms of the lower 4 bytes of the TSF timer. */
299#endif /* CONFIG_8723AU_P2P */
300};
301
302struct tdls_ss_record { /* signal strength record */
303 u8 macaddr[ETH_ALEN];
304 u8 RxPWDBAll;
305 u8 is_tdls_sta; /* true: direct link sta, false: else */
306};
307
308struct tdls_info {
309 u8 ap_prohibited;
310 uint setup_state;
311 u8 sta_cnt;
312 /* 1:tdls sta == (NUM_STA-1), reach max direct link no; 0: else; */
313 u8 sta_maximum;
314 struct tdls_ss_record ss_record;
315 u8 macid_index; /* macid entry that is ready to write */
316 /* cam entry that is trying to clear, using it in direct link teardown*/
317 u8 clear_cam;
318 u8 ch_sensing;
319 u8 cur_channel;
320 u8 candidate_ch;
321 u8 collect_pkt_num[MAX_CHANNEL_NUM];
322 spinlock_t cmd_lock;
323 spinlock_t hdl_lock;
324 u8 watchdog_count;
325 u8 dev_discovered; /* WFD_TDLS: for sigma test */
326 u8 enable;
327#ifdef CONFIG_8723AU_P2P
328 struct wifi_display_info *wfd_info;
329#endif
330};
331
332struct mlme_priv {
333 spinlock_t lock;
334 int fw_state;
335 u8 bScanInProcess;
336 u8 to_join; /* flag */
337 u8 to_roaming; /* roaming trying times */
338
339 struct rtw_adapter *nic_hdl;
340
341 u8 not_indic_disco;
342 struct rtw_queue scanned_queue;
343
344 struct cfg80211_ssid assoc_ssid;
345 u8 assoc_bssid[6];
346
347 struct wlan_network cur_network;
348
349 /* uint wireless_mode; no used, remove it */
350
351 u32 scan_interval;
352
353 struct timer_list assoc_timer;
354
355 uint assoc_by_bssid;
356 uint assoc_by_rssi;
357
358 struct timer_list scan_to_timer;
359
360 struct timer_list set_scan_deny_timer;
361 atomic_t set_scan_deny; /* 0: allowed, 1: deny */
362
363 struct qos_priv qospriv;
364
365 /* Number of non-HT AP/stations */
366 int num_sta_no_ht;
367
368 int num_FortyMHzIntolerant;
369
370 struct ht_priv htpriv;
371
372 struct rt_link_detect LinkDetectInfo;
373 struct timer_list dynamic_chk_timer; /* dynamic/periodic check timer */
374
375 u8 key_mask; /* use for ips to set wep key after ips_leave23a */
376 u8 acm_mask; /* for wmm acm mask */
377 u8 ChannelPlan;
378 enum rt_scan_type scan_mode; /* active: 1, passive: 0 */
379
380 u8 *wps_probe_req_ie;
381 u32 wps_probe_req_ie_len;
382 u8 *assoc_req;
383 u32 assoc_req_len;
384 u32 assoc_rsp_len;
385 u8 *assoc_rsp;
386 u32 wps_assoc_resp_ie_len;
387 u8 *wps_assoc_resp_ie;
388 u8 *wps_probe_resp_ie;
389 u32 wps_probe_resp_ie_len;
390 u8 *wps_beacon_ie;
391 u32 wps_beacon_ie_len;
392 u32 p2p_go_probe_resp_ie_len; /* for GO */
393 u32 p2p_assoc_req_ie_len;
394 u8 *p2p_beacon_ie;
395 u8 *p2p_probe_req_ie;
396 u8 *p2p_probe_resp_ie;
397 u8 *p2p_go_probe_resp_ie; /* for GO */
398 u8 *p2p_assoc_req_ie;
399 u32 p2p_beacon_ie_len;
400 u32 p2p_probe_req_ie_len;
401 u32 p2p_probe_resp_ie_len;
402 u8 *wfd_assoc_req_ie;
403 u32 wfd_assoc_req_ie_len;
404
405#ifdef CONFIG_8723AU_AP_MODE
406 /* Number of associated Non-ERP stations (i.e., stations using 802.11b
407 * in 802.11g BSS) */
408 int num_sta_non_erp;
409
410 /* Number of associated stations that do not support Short Slot Time */
411 int num_sta_no_short_slot_time;
412
413 /* Number of associated stations that do not support Short Preamble */
414 int num_sta_no_short_preamble;
415
416 int olbc; /* Overlapping Legacy BSS Condition */
417
418 /* Number of HT associated stations that do not support greenfield */
419 int num_sta_ht_no_gf;
420
421 /* Number of associated non-HT stations */
422 /* int num_sta_no_ht; */
423
424 /* Number of HT associated stations 20 MHz */
425 int num_sta_ht_20mhz;
426
427 /* Overlapping BSS information */
428 int olbc_ht;
429
430 u16 ht_op_mode;
431
432 spinlock_t bcn_update_lock;
433 u8 update_bcn;
434
435#endif /* ifdef CONFIG_8723AU_AP_MODE */
436
437 u8 *wfd_beacon_ie;
438 u8 *wfd_probe_req_ie;
439 u8 *wfd_probe_resp_ie;
440 u8 *wfd_go_probe_resp_ie; /* for GO */
441
442 u32 wfd_beacon_ie_len;
443 u32 wfd_probe_req_ie_len;
444 u32 wfd_probe_resp_ie_len;
445 u32 wfd_go_probe_resp_ie_len; /* for GO */
446};
447
448#ifdef CONFIG_8723AU_AP_MODE
449
450struct hostapd_priv {
451 struct rtw_adapter *padapter;
452};
453
454int hostapd_mode_init(struct rtw_adapter *padapter);
455void hostapd_mode_unload(struct rtw_adapter *padapter);
456#endif
457
458void rtw_joinbss_event_prehandle23a(struct rtw_adapter *adapter, u8 *pbuf);
459void rtw_survey_event_cb23a(struct rtw_adapter *adapter, u8 *pbuf);
460void rtw_surveydone_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf);
461void rtw23a_joinbss_event_cb(struct rtw_adapter *adapter, u8 *pbuf);
462void rtw_stassoc_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf);
463void rtw_stadel_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf);
464void rtw_atimdone_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf);
465void rtw_cpwm_event_callback23a(struct rtw_adapter *adapter, u8 *pbuf);
466
467
468int event_thread(void *context);
469void rtw23a_join_to_handler(unsigned long);
470
471void rtw_free_network_queue23a(struct rtw_adapter *adapter, u8 isfreeall);
472int rtw_init_mlme_priv23a(struct rtw_adapter *adapter);
473
474void rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv);
475
476int rtw_select_and_join_from_scanned_queue23a(struct mlme_priv *pmlmepriv);
477int rtw_set_key23a(struct rtw_adapter *adapter,
478 struct security_priv *psecuritypriv, int keyid, u8 set_tx);
479int rtw_set_auth23a(struct rtw_adapter *adapter,
480 struct security_priv *psecuritypriv);
481
482static inline u8 *get_bssid(struct mlme_priv *pmlmepriv)
483{ /* if sta_mode:pmlmepriv->cur_network.network.MacAddress => bssid */
484 /* if adhoc_mode:pmlmepriv->cur_network.network.MacAddress => ibss mac address */
485 return pmlmepriv->cur_network.network.MacAddress;
486}
487
488static inline int check_fwstate(struct mlme_priv *pmlmepriv, int state)
489{
490 if (pmlmepriv->fw_state & state)
491 return true;
492
493 return false;
494}
495
496static inline int get_fwstate(struct mlme_priv *pmlmepriv)
497{
498 return pmlmepriv->fw_state;
499}
500
501/*
502 * No Limit on the calling context,
503 * therefore set it to be the critical section...
504 *
505 * ### NOTE:#### (!!!!)
506 * MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
507 */
508static inline void set_fwstate(struct mlme_priv *pmlmepriv, int state)
509{
510 pmlmepriv->fw_state |= state;
511 /* FOR HW integration */
512 if (_FW_UNDER_SURVEY == state)
513 pmlmepriv->bScanInProcess = true;
514}
515
516static inline void _clr_fwstate_(struct mlme_priv *pmlmepriv, int state)
517{
518 pmlmepriv->fw_state &= ~state;
519 /* FOR HW integration */
520 if (_FW_UNDER_SURVEY == state)
521 pmlmepriv->bScanInProcess = false;
522}
523
524/*
525 * No Limit on the calling context,
526 * therefore set it to be the critical section...
527 */
528static inline void clr_fwstate(struct mlme_priv *pmlmepriv, int state)
529{
530 spin_lock_bh(&pmlmepriv->lock);
531 if (check_fwstate(pmlmepriv, state) == true)
532 pmlmepriv->fw_state ^= state;
533 spin_unlock_bh(&pmlmepriv->lock);
534}
535
536static inline void clr_fwstate_ex(struct mlme_priv *pmlmepriv, int state)
537{
538 spin_lock_bh(&pmlmepriv->lock);
539 _clr_fwstate_(pmlmepriv, state);
540 spin_unlock_bh(&pmlmepriv->lock);
541}
542
543u16 rtw_get_capability23a(struct wlan_bssid_ex *bss);
544void rtw_update_scanned_network23a(struct rtw_adapter *adapter,
545 struct wlan_bssid_ex *target);
546void rtw_disconnect_hdl23a_under_linked(struct rtw_adapter *adapter,
547 struct sta_info *psta, u8 free_assoc);
548void rtw_generate_random_ibss23a(u8 *pibss);
549struct wlan_network *rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr);
550struct wlan_network *rtw_get_oldest_wlan_network23a(struct rtw_queue *scanned_queue);
551
552void rtw_free_assoc_resources23a(struct rtw_adapter *adapter,
553 int lock_scanned_queue);
554void rtw_indicate_disconnect23a(struct rtw_adapter *adapter);
555void rtw_indicate_connect23a(struct rtw_adapter *adapter);
556void rtw_indicate_scan_done23a(struct rtw_adapter *padapter, bool aborted);
557void rtw_scan_abort23a(struct rtw_adapter *adapter);
558
559int rtw_restruct_sec_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie,
560 uint in_len);
561int rtw_restruct_wmm_ie23a(struct rtw_adapter *adapter, u8 *in_ie, u8 *out_ie,
562 uint in_len, uint initial_out_len);
563void rtw_init_registrypriv_dev_network23a(struct rtw_adapter *adapter);
564
565void rtw_update_registrypriv_dev_network23a(struct rtw_adapter *adapter);
566
567void rtw_get_encrypt_decrypt_from_registrypriv23a(struct rtw_adapter *adapter);
568
569void rtw_scan_timeout_handler23a(unsigned long data);
570
571void rtw_dynamic_check_timer_handler(unsigned long data);
572bool rtw_is_scan_deny(struct rtw_adapter *adapter);
573void rtw_clear_scan_deny(struct rtw_adapter *adapter);
574void rtw_set_scan_deny_timer_hdl(unsigned long data);
575void rtw_set_scan_deny(struct rtw_adapter *adapter, u32 ms);
576
577int _rtw_init_mlme_priv23a(struct rtw_adapter *padapter);
578
579void rtw23a_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv);
580
581void _rtw_free_mlme_priv23a(struct mlme_priv *pmlmepriv);
582
583struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv);
584
585void _rtw_free_network23a(struct mlme_priv *pmlmepriv,
586 struct wlan_network *pnetwork, u8 isfreeall);
587void _rtw_free_network23a_nolock23a(struct mlme_priv *pmlmepriv,
588 struct wlan_network *pnetwork);
589
590struct wlan_network *_rtw_find_network23a(struct rtw_queue *scanned_queue, u8 *addr);
591
592void _rtw_free_network23a_queue23a(struct rtw_adapter *padapter, u8 isfreeall);
593
594int rtw_if_up23a(struct rtw_adapter *padapter);
595
596int rtw_linked_check(struct rtw_adapter *padapter);
597
598u8 *rtw_get_capability23a_from_ie(u8 *ie);
599u8 *rtw_get_timestampe_from_ie23a(u8 *ie);
600u8 *rtw_get_beacon_interval23a_from_ie(u8 *ie);
601
602
603void rtw_joinbss_reset23a(struct rtw_adapter *padapter);
604
605unsigned int rtw_restructure_ht_ie23a(struct rtw_adapter *padapter, u8 *in_ie,
606 u8 *out_ie, uint in_len, uint *pout_len);
607void rtw_update_ht_cap23a(struct rtw_adapter *padapter,
608 u8 *pie, uint ie_len);
609void rtw_issue_addbareq_cmd23a(struct rtw_adapter *padapter,
610 struct xmit_frame *pxmitframe);
611
612int rtw_is_same_ibss23a(struct rtw_adapter *adapter,
613 struct wlan_network *pnetwork);
614int is_same_network23a(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst);
615
616void _rtw23a_roaming(struct rtw_adapter *adapter,
617 struct wlan_network *tgt_network);
618void rtw23a_roaming(struct rtw_adapter *adapter,
619 struct wlan_network *tgt_network);
620void rtw_set_roaming(struct rtw_adapter *adapter, u8 to_roaming);
621u8 rtw_to_roaming(struct rtw_adapter *adapter);
622void rtw_stassoc_hw_rpt23a(struct rtw_adapter *adapter, struct sta_info *psta);
623
624#endif /* __RTL871X_MLME_H_ */
diff --git a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h
new file mode 100644
index 000000000000..0aaf0d5d8aea
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h
@@ -0,0 +1,780 @@
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 ******************************************************************************/
15#ifndef __RTW_MLME_EXT_H_
16#define __RTW_MLME_EXT_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20#include <wlan_bssdef.h>
21
22
23/* Commented by Albert 20101105 */
24/* Increase the SURVEY_TO value from 100 to 150 ( 100ms to 150ms ) */
25/* The Realtek 8188CE SoftAP will spend around 100ms to send the probe response after receiving the probe request. */
26/* So, this driver tried to extend the dwell time for each scanning channel. */
27/* This will increase the chance to receive the probe response from SoftAP. */
28
29#define SURVEY_TO (100)
30#define REAUTH_TO (300) /* 50) */
31#define REASSOC_TO (300) /* 50) */
32/* define DISCONNECT_TO (3000) */
33#define ADDBA_TO (2000)
34
35#define LINKED_TO (1) /* unit:2 sec, 1x2=2 sec */
36
37#define REAUTH_LIMIT (4)
38#define REASSOC_LIMIT (4)
39#define READDBA_LIMIT (2)
40
41#define ROAMING_LIMIT 8
42
43#define DYNAMIC_FUNC_DISABLE (0x0)
44
45/* ====== enum odm_ability ======== */
46/* BB ODM section BIT 0-15 */
47#define DYNAMIC_BB_DIG BIT(0)
48#define DYNAMIC_BB_RA_MASK BIT(1)
49#define DYNAMIC_BB_DYNAMIC_TXPWR BIT(2)
50#define DYNAMIC_BB_BB_FA_CNT BIT(3)
51
52#define DYNAMIC_BB_RSSI_MONITOR BIT(4)
53#define DYNAMIC_BB_CCK_PD BIT(5)
54#define DYNAMIC_BB_ANT_DIV BIT(6)
55#define DYNAMIC_BB_PWR_SAVE BIT(7)
56#define DYNAMIC_BB_PWR_TRAIN BIT(8)
57#define DYNAMIC_BB_RATE_ADAPTIVE BIT(9)
58#define DYNAMIC_BB_PATH_DIV BIT(10)
59#define DYNAMIC_BB_PSD BIT(11)
60
61/* MAC DM section BIT 16-23 */
62#define DYNAMIC_MAC_struct edca_turboURBO BIT(16)
63#define DYNAMIC_MAC_EARLY_MODE BIT(17)
64
65/* RF ODM section BIT 24-31 */
66#define DYNAMIC_RF_TX_PWR_TRACK BIT(24)
67#define DYNAMIC_RF_RX_GAIN_TRACK BIT(25)
68#define DYNAMIC_RF_CALIBRATION BIT(26)
69
70#define DYNAMIC_ALL_FUNC_ENABLE 0xFFFFFFF
71
72#define _HW_STATE_NOLINK_ 0x00
73#define _HW_STATE_ADHOC_ 0x01
74#define _HW_STATE_STATION_ 0x02
75#define _HW_STATE_AP_ 0x03
76
77
78#define _1M_RATE_ 0
79#define _2M_RATE_ 1
80#define _5M_RATE_ 2
81#define _11M_RATE_ 3
82#define _6M_RATE_ 4
83#define _9M_RATE_ 5
84#define _12M_RATE_ 6
85#define _18M_RATE_ 7
86#define _24M_RATE_ 8
87#define _36M_RATE_ 9
88#define _48M_RATE_ 10
89#define _54M_RATE_ 11
90
91
92extern unsigned char RTW_WPA_OUI23A[];
93extern unsigned char WMM_OUI23A[];
94extern unsigned char WPS_OUI23A[];
95extern unsigned char WFD_OUI23A[];
96extern unsigned char P2P_OUI23A[];
97
98extern unsigned char WMM_INFO_OUI23A[];
99extern unsigned char WMM_PARA_OUI23A[];
100
101
102/* */
103/* Channel Plan Type. */
104/* Note: */
105/* We just add new channel plan when the new channel plan is different from any of the following */
106/* channel plan. */
107/* If you just wnat to customize the acitions(scan period or join actions) about one of the channel plan, */
108/* customize them in struct rt_channel_info in the RT_CHANNEL_LIST. */
109/* */
110enum { /* _RT_CHANNEL_DOMAIN */
111 /* old channel plan mapping ===== */
112 RT_CHANNEL_DOMAIN_FCC = 0x00,
113 RT_CHANNEL_DOMAIN_IC = 0x01,
114 RT_CHANNEL_DOMAIN_ETSI = 0x02,
115 RT_CHANNEL_DOMAIN_SPAIN = 0x03,
116 RT_CHANNEL_DOMAIN_FRANCE = 0x04,
117 RT_CHANNEL_DOMAIN_MKK = 0x05,
118 RT_CHANNEL_DOMAIN_MKK1 = 0x06,
119 RT_CHANNEL_DOMAIN_ISRAEL = 0x07,
120 RT_CHANNEL_DOMAIN_TELEC = 0x08,
121 RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN = 0x09,
122 RT_CHANNEL_DOMAIN_WORLD_WIDE_13 = 0x0A,
123 RT_CHANNEL_DOMAIN_TAIWAN = 0x0B,
124 RT_CHANNEL_DOMAIN_CHINA = 0x0C,
125 RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO = 0x0D,
126 RT_CHANNEL_DOMAIN_KOREA = 0x0E,
127 RT_CHANNEL_DOMAIN_TURKEY = 0x0F,
128 RT_CHANNEL_DOMAIN_JAPAN = 0x10,
129 RT_CHANNEL_DOMAIN_FCC_NO_DFS = 0x11,
130 RT_CHANNEL_DOMAIN_JAPAN_NO_DFS = 0x12,
131 RT_CHANNEL_DOMAIN_WORLD_WIDE_5G = 0x13,
132 RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS = 0x14,
133
134 /* new channel plan mapping, (2GDOMAIN_5GDOMAIN) ===== */
135 RT_CHANNEL_DOMAIN_WORLD_NULL = 0x20,
136 RT_CHANNEL_DOMAIN_ETSI1_NULL = 0x21,
137 RT_CHANNEL_DOMAIN_FCC1_NULL = 0x22,
138 RT_CHANNEL_DOMAIN_MKK1_NULL = 0x23,
139 RT_CHANNEL_DOMAIN_ETSI2_NULL = 0x24,
140 RT_CHANNEL_DOMAIN_FCC1_FCC1 = 0x25,
141 RT_CHANNEL_DOMAIN_WORLD_ETSI1 = 0x26,
142 RT_CHANNEL_DOMAIN_MKK1_MKK1 = 0x27,
143 RT_CHANNEL_DOMAIN_WORLD_KCC1 = 0x28,
144 RT_CHANNEL_DOMAIN_WORLD_FCC2 = 0x29,
145 RT_CHANNEL_DOMAIN_WORLD_FCC3 = 0x30,
146 RT_CHANNEL_DOMAIN_WORLD_FCC4 = 0x31,
147 RT_CHANNEL_DOMAIN_WORLD_FCC5 = 0x32,
148 RT_CHANNEL_DOMAIN_WORLD_FCC6 = 0x33,
149 RT_CHANNEL_DOMAIN_FCC1_FCC7 = 0x34,
150 RT_CHANNEL_DOMAIN_WORLD_ETSI2 = 0x35,
151 RT_CHANNEL_DOMAIN_WORLD_ETSI3 = 0x36,
152 RT_CHANNEL_DOMAIN_MKK1_MKK2 = 0x37,
153 RT_CHANNEL_DOMAIN_MKK1_MKK3 = 0x38,
154 RT_CHANNEL_DOMAIN_FCC1_NCC1 = 0x39,
155 RT_CHANNEL_DOMAIN_FCC1_NCC2 = 0x40,
156 RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G = 0x41,
157 /* Add new channel plan above this line=============== */
158 RT_CHANNEL_DOMAIN_MAX,
159 RT_CHANNEL_DOMAIN_REALTEK_DEFINE = 0x7F,
160};
161
162enum { /* _RT_CHANNEL_DOMAIN_2G */
163 RT_CHANNEL_DOMAIN_2G_WORLD = 0x00, /* Worldwird 13 */
164 RT_CHANNEL_DOMAIN_2G_ETSI1 = 0x01, /* Europe */
165 RT_CHANNEL_DOMAIN_2G_FCC1 = 0x02, /* US */
166 RT_CHANNEL_DOMAIN_2G_MKK1 = 0x03, /* Japan */
167 RT_CHANNEL_DOMAIN_2G_ETSI2 = 0x04, /* France */
168 RT_CHANNEL_DOMAIN_2G_NULL = 0x05,
169 /* Add new channel plan above this line=============== */
170 RT_CHANNEL_DOMAIN_2G_MAX,
171};
172
173enum { /* _RT_CHANNEL_DOMAIN_5G */
174 RT_CHANNEL_DOMAIN_5G_NULL = 0x00,
175 RT_CHANNEL_DOMAIN_5G_ETSI1 = 0x01, /* Europe */
176 RT_CHANNEL_DOMAIN_5G_ETSI2 = 0x02, /* Australia, New Zealand */
177 RT_CHANNEL_DOMAIN_5G_ETSI3 = 0x03, /* Russia */
178 RT_CHANNEL_DOMAIN_5G_FCC1 = 0x04, /* US */
179 RT_CHANNEL_DOMAIN_5G_FCC2 = 0x05, /* FCC o/w DFS Channels */
180 RT_CHANNEL_DOMAIN_5G_FCC3 = 0x06, /* India, Mexico */
181 RT_CHANNEL_DOMAIN_5G_FCC4 = 0x07, /* Venezuela */
182 RT_CHANNEL_DOMAIN_5G_FCC5 = 0x08, /* China */
183 RT_CHANNEL_DOMAIN_5G_FCC6 = 0x09, /* Israel */
184 RT_CHANNEL_DOMAIN_5G_FCC7_IC1 = 0x0A, /* US, Canada */
185 RT_CHANNEL_DOMAIN_5G_KCC1 = 0x0B, /* Korea */
186 RT_CHANNEL_DOMAIN_5G_MKK1 = 0x0C, /* Japan */
187 RT_CHANNEL_DOMAIN_5G_MKK2 = 0x0D, /* Japan (W52, W53) */
188 RT_CHANNEL_DOMAIN_5G_MKK3 = 0x0E, /* Japan (W56) */
189 RT_CHANNEL_DOMAIN_5G_NCC1 = 0x0F, /* Taiwan */
190 RT_CHANNEL_DOMAIN_5G_NCC2 = 0x10, /* Taiwan o/w DFS */
191 /* Add new channel plan above this line=============== */
192 /* Driver Self Defined ===== */
193 RT_CHANNEL_DOMAIN_5G_FCC = 0x11,
194 RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS = 0x12,
195 RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS = 0x13,
196 RT_CHANNEL_DOMAIN_5G_MAX,
197};
198
199#define rtw_is_channel_plan_valid(chplan) (chplan<RT_CHANNEL_DOMAIN_MAX || chplan == RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
200
201struct rt_channel_plan {
202 unsigned char Channel[MAX_CHANNEL_NUM];
203 unsigned char Len;
204};
205
206struct rt_channel_plan_2g {
207 unsigned char Channel[MAX_CHANNEL_NUM_2G];
208 unsigned char Len;
209};
210
211struct rt_channel_plan_5g {
212 unsigned char Channel[MAX_CHANNEL_NUM_5G];
213 unsigned char Len;
214};
215
216struct rt_channel_plan_map {
217 unsigned char Index2G;
218 unsigned char Index5G;
219};
220
221enum Associated_AP {
222 atherosAP = 0,
223 broadcomAP = 1,
224 ciscoAP = 2,
225 marvellAP = 3,
226 ralinkAP = 4,
227 realtekAP = 5,
228 airgocapAP = 6,
229 unknownAP = 7,
230 maxAP,
231};
232
233enum { /* HT_IOT_PEER_E */
234 HT_IOT_PEER_UNKNOWN = 0,
235 HT_IOT_PEER_REALTEK = 1,
236 HT_IOT_PEER_REALTEK_92SE = 2,
237 HT_IOT_PEER_BROADCOM = 3,
238 HT_IOT_PEER_RALINK = 4,
239 HT_IOT_PEER_ATHEROS = 5,
240 HT_IOT_PEER_CISCO = 6,
241 HT_IOT_PEER_MERU = 7,
242 HT_IOT_PEER_MARVELL = 8,
243 HT_IOT_PEER_REALTEK_SOFTAP = 9,/* peer is RealTek SOFT_AP, by Bohn, 2009.12.17 */
244 HT_IOT_PEER_SELF_SOFTAP = 10, /* Self is SoftAP */
245 HT_IOT_PEER_AIRGO = 11,
246 HT_IOT_PEER_INTEL = 12,
247 HT_IOT_PEER_RTK_APCLIENT = 13,
248 HT_IOT_PEER_REALTEK_81XX = 14,
249 HT_IOT_PEER_REALTEK_WOW = 15,
250 HT_IOT_PEER_TENDA = 16,
251 HT_IOT_PEER_MAX = 17
252};
253
254enum SCAN_STATE {
255 SCAN_DISABLE = 0,
256 SCAN_START = 1,
257 SCAN_TXNULL = 2,
258 SCAN_PROCESS = 3,
259 SCAN_COMPLETE = 4,
260 SCAN_STATE_MAX,
261};
262
263struct mlme_handler {
264 char *str;
265 unsigned int (*func)(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
266};
267
268struct action_handler {
269 unsigned int num;
270 char* str;
271 unsigned int (*func)(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
272};
273
274struct ss_res
275{
276 int state;
277 int bss_cnt;
278 int channel_idx;
279 int scan_mode;
280 u8 ssid_num;
281 u8 ch_num;
282 struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT];
283 struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
284};
285
286/* define AP_MODE 0x0C */
287/* define STATION_MODE 0x08 */
288/* define AD_HOC_MODE 0x04 */
289/* define NO_LINK_MODE 0x00 */
290
291#define WIFI_FW_NULL_STATE _HW_STATE_NOLINK_
292#define WIFI_FW_STATION_STATE _HW_STATE_STATION_
293#define WIFI_FW_AP_STATE _HW_STATE_AP_
294#define WIFI_FW_ADHOC_STATE _HW_STATE_ADHOC_
295
296#define WIFI_FW_AUTH_NULL 0x00000100
297#define WIFI_FW_AUTH_STATE 0x00000200
298#define WIFI_FW_AUTH_SUCCESS 0x00000400
299
300#define WIFI_FW_ASSOC_STATE 0x00002000
301#define WIFI_FW_ASSOC_SUCCESS 0x00004000
302
303#define WIFI_FW_LINKING_STATE (WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE | WIFI_FW_AUTH_SUCCESS |WIFI_FW_ASSOC_STATE)
304
305struct FW_Sta_Info {
306 struct sta_info *psta;
307 u32 status;
308 u32 rx_pkt;
309 u32 retry;
310 unsigned char SupportedRates[NDIS_802_11_LENGTH_RATES_EX];
311};
312
313/*
314 * Usage:
315 * When one iface acted as AP mode and the other iface is STA mode and scanning,
316 * it should switch back to AP's operating channel periodically.
317 * Parameters info:
318 * When the driver scanned RTW_SCAN_NUM_OF_CH channels, it would switch back to AP's operating channel for
319 * RTW_STAY_AP_CH_MILLISECOND * SURVEY_TO milliseconds.
320 * Example:
321 * For chip supports 2.4G + 5GHz and AP mode is operating in channel 1,
322 * RTW_SCAN_NUM_OF_CH is 8, RTW_STAY_AP_CH_MILLISECOND is 3 and SURVEY_TO is 100.
323 * When it's STA mode gets set_scan command,
324 * it would
325 * 1. Doing the scan on channel 1.2.3.4.5.6.7.8
326 * 2. Back to channel 1 for 300 milliseconds
327 * 3. Go through doing site survey on channel 9.10.11.36.40.44.48.52
328 * 4. Back to channel 1 for 300 milliseconds
329 * 5. ... and so on, till survey done.
330 */
331
332struct mlme_ext_info
333{
334 u32 state;
335 u32 reauth_count;
336 u32 reassoc_count;
337 u32 link_count;
338 u32 auth_seq;
339 u32 auth_algo; /* 802.11 auth, could be open, shared, auto */
340 u32 authModeToggle;
341 u32 enc_algo;/* encrypt algorithm; */
342 u32 key_index; /* this is only valid for legendary wep, 0~3 for key id. */
343 u32 iv;
344 u8 chg_txt[128];
345 u16 aid;
346 u16 bcn_interval;
347 u16 capability;
348 u8 assoc_AP_vendor;
349 u8 slotTime;
350 u8 preamble_mode;
351 u8 WMM_enable;
352 u8 ERP_enable;
353 u8 ERP_IE;
354 u8 HT_enable;
355 u8 HT_caps_enable;
356 u8 HT_info_enable;
357 u8 HT_protection;
358 u8 turboMode_cts2self;
359 u8 turboMode_rtsen;
360 u8 SM_PS;
361 u8 agg_enable_bitmap;
362 u8 ADDBA_retry_count;
363 u8 candidate_tid_bitmap;
364 u8 dialogToken;
365 /* Accept ADDBA Request */
366 bool bAcceptAddbaReq;
367 u8 bwmode_updated;
368 u8 hidden_ssid_mode;
369
370 struct ADDBA_request ADDBA_req;
371 struct WMM_para_element WMM_param;
372 struct HT_caps_element HT_caps;
373 struct HT_info_element HT_info;
374 struct wlan_bssid_ex network;/* join network or bss_network, if in ap mode, it is the same to cur_network.network */
375 struct FW_Sta_Info FW_sta_info[NUM_STA];
376};
377
378/* The channel information about this channel including joining, scanning, and power constraints. */
379struct rt_channel_info {
380 u8 ChannelNum; /* The channel number. */
381 enum rt_scan_type ScanType; /* Scan type such as passive or active scan. */
382};
383
384int rtw_ch_set_search_ch23a(struct rt_channel_info *ch_set, const u32 ch);
385
386/* P2P_MAX_REG_CLASSES - Maximum number of regulatory classes */
387#define P2P_MAX_REG_CLASSES 10
388
389/* P2P_MAX_REG_CLASS_CHANNELS - Maximum number of channels per regulatory class */
390#define P2P_MAX_REG_CLASS_CHANNELS 20
391
392/* struct p2p_channels - List of supported channels */
393struct p2p_channels {
394 /* struct p2p_reg_class - Supported regulatory class */
395 struct p2p_reg_class {
396 /* reg_class - Regulatory class (IEEE 802.11-2007, Annex J) */
397 u8 reg_class;
398
399 /* channel - Supported channels */
400 u8 channel[P2P_MAX_REG_CLASS_CHANNELS];
401
402 /* channels - Number of channel entries in use */
403 size_t channels;
404 } reg_class[P2P_MAX_REG_CLASSES];
405
406 /* reg_classes - Number of reg_class entries in use */
407 size_t reg_classes;
408};
409
410struct p2p_oper_class_map {
411 enum hw_mode {IEEE80211G,IEEE80211A} mode;
412 u8 op_class;
413 u8 min_chan;
414 u8 max_chan;
415 u8 inc;
416 enum {
417 BW20, BW40PLUS, BW40MINUS
418 } bw;
419};
420
421struct mlme_ext_priv {
422 struct rtw_adapter *padapter;
423 u8 mlmeext_init;
424 atomic_t event_seq;
425 u16 mgnt_seq;
426
427 /* struct fw_priv fwpriv; */
428
429 unsigned char cur_channel;
430 unsigned char cur_bwmode;
431 unsigned char cur_ch_offset;/* PRIME_CHNL_OFFSET */
432 unsigned char cur_wireless_mode; /* NETWORK_TYPE */
433
434 unsigned char max_chan_nums;
435 struct rt_channel_info channel_set[MAX_CHANNEL_NUM];
436 struct p2p_channels channel_list;
437 unsigned char basicrate[NumRates];
438 unsigned char datarate[NumRates];
439
440 struct ss_res sitesurvey_res;
441 struct mlme_ext_info mlmext_info;/* for sta/adhoc mode, including current scanning/connecting/connected related info. */
442 /* for ap mode, network includes ap's cap_info */
443 struct timer_list survey_timer;
444 struct timer_list link_timer;
445 u16 chan_scan_time;
446
447 u8 scan_abort;
448 u8 tx_rate; /* TXRATE when USERATE is set. */
449
450 u32 retry; /* retry for issue probereq */
451
452 u64 TSFValue;
453
454 unsigned char bstart_bss;
455 u8 update_channel_plan_by_ap_done;
456 /* recv_decache check for Action_public frame */
457 u8 action_public_dialog_token;
458 u16 action_public_rxseq;
459 u8 active_keep_alive_check;
460};
461
462int init_mlme_ext_priv23a(struct rtw_adapter* padapter);
463int init_hw_mlme_ext23a(struct rtw_adapter *padapter);
464void free_mlme_ext_priv23a (struct mlme_ext_priv *pmlmeext);
465void init_mlme_ext_timer23a(struct rtw_adapter *padapter);
466void init_addba_retry_timer23a(struct sta_info *psta);
467struct xmit_frame *alloc_mgtxmitframe23a(struct xmit_priv *pxmitpriv);
468
469unsigned char networktype_to_raid23a(unsigned char network_type);
470u8 judge_network_type23a(struct rtw_adapter *padapter, unsigned char *rate,
471 int ratelen);
472void get_rate_set23a(struct rtw_adapter *padapter, unsigned char *pbssrate,
473 int *bssrate_len);
474void UpdateBrateTbl23a(struct rtw_adapter *padapter,u8 *mBratesOS);
475void Update23aTblForSoftAP(u8 *bssrateset, u32 bssratelen);
476
477void Save_DM_Func_Flag23a(struct rtw_adapter *padapter);
478void Restore_DM_Func_Flag23a(struct rtw_adapter *padapter);
479void Switch_DM_Func23a(struct rtw_adapter *padapter, unsigned long mode, u8 enable);
480
481void Set_MSR23a(struct rtw_adapter *padapter, u8 type);
482
483u8 rtw_get_oper_ch23a(struct rtw_adapter *adapter);
484void rtw_set_oper_ch23a(struct rtw_adapter *adapter, u8 ch);
485u8 rtw_get_oper_bw23a(struct rtw_adapter *adapter);
486void rtw_set_oper_bw23a(struct rtw_adapter *adapter, u8 bw);
487u8 rtw_get_oper_ch23aoffset(struct rtw_adapter *adapter);
488void rtw_set_oper_ch23aoffset23a(struct rtw_adapter *adapter, u8 offset);
489
490void set_channel_bwmode23a(struct rtw_adapter *padapter, unsigned char channel,
491 unsigned char channel_offset, unsigned short bwmode);
492void SelectChannel23a(struct rtw_adapter *padapter, unsigned char channel);
493void SetBWMode23a(struct rtw_adapter *padapter, unsigned short bwmode,
494 unsigned char channel_offset);
495
496unsigned int decide_wait_for_beacon_timeout23a(unsigned int bcn_interval);
497
498void write_cam23a(struct rtw_adapter *padapter, u8 entry, u16 ctrl,
499 u8 *mac, u8 *key);
500void clear_cam_entry23a(struct rtw_adapter *padapter, u8 entry);
501
502void invalidate_cam_all23a(struct rtw_adapter *padapter);
503void CAM_empty_entry23a(struct rtw_adapter *Adapter, u8 ucIndex);
504
505int allocate_fw_sta_entry23a(struct rtw_adapter *padapter);
506void flush_all_cam_entry23a(struct rtw_adapter *padapter);
507
508bool IsLegal5GChannel(struct rtw_adapter *Adapter, u8 channel);
509
510void site_survey23a(struct rtw_adapter *padapter);
511u8 collect_bss_info23a(struct rtw_adapter *padapter,
512 struct recv_frame *precv_frame,
513 struct wlan_bssid_ex *bssid);
514void update_network23a(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
515 struct rtw_adapter *padapter, bool update_ie);
516
517int get_bsstype23a(unsigned short capability);
518u8 *get_my_bssid23a(struct wlan_bssid_ex *pnetwork);
519u16 get_beacon_interval23a(struct wlan_bssid_ex *bss);
520
521int is_client_associated_to_ap23a(struct rtw_adapter *padapter);
522int is_client_associated_to_ibss23a(struct rtw_adapter *padapter);
523int is_IBSS_empty23a(struct rtw_adapter *padapter);
524
525unsigned char check_assoc_AP23a(u8 *pframe, uint len);
526
527int WMM_param_handler23a(struct rtw_adapter *padapter,
528 struct ndis_802_11_var_ies *pIE);
529#ifdef CONFIG_8723AU_P2P
530int WFD_info_handler(struct rtw_adapter *padapter,
531 struct ndis_802_11_var_ies *pIE);
532#endif
533void WMMOnAssocRsp23a(struct rtw_adapter *padapter);
534
535void HT_caps_handler23a(struct rtw_adapter *padapter,
536 struct ndis_802_11_var_ies *pIE);
537void HT_info_handler23a(struct rtw_adapter *padapter,
538 struct ndis_802_11_var_ies *pIE);
539void HTOnAssocRsp23a(struct rtw_adapter *padapter);
540
541void ERP_IE_handler23a(struct rtw_adapter *padapter,
542 struct ndis_802_11_var_ies *pIE);
543void VCS_update23a(struct rtw_adapter *padapter, struct sta_info *psta);
544
545void update_beacon23a_info(struct rtw_adapter *padapter, u8 *pframe, uint len,
546 struct sta_info *psta);
547int rtw_check_bcn_info23a(struct rtw_adapter *Adapter, u8 *pframe, u32 packet_len);
548void update_IOT_info23a(struct rtw_adapter *padapter);
549void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap);
550void update_wireless_mode23a(struct rtw_adapter * padapter);
551void update_tx_basic_rate23a(struct rtw_adapter *padapter, u8 modulation);
552void update_bmc_sta_support_rate23a(struct rtw_adapter *padapter, u32 mac_id);
553int update_sta_support_rate23a(struct rtw_adapter *padapter, u8* pvar_ie,
554 uint var_ie_len, int cam_idx);
555
556/* for sta/adhoc mode */
557void update_sta_info23a(struct rtw_adapter *padapter, struct sta_info *psta);
558unsigned int update_basic_rate23a(unsigned char *ptn, unsigned int ptn_sz);
559unsigned int update_supported_rate23a(unsigned char *ptn, unsigned int ptn_sz);
560unsigned int update_MSC_rate23a(struct HT_caps_element *pHT_caps);
561void Update_RA_Entry23a(struct rtw_adapter *padapter, struct sta_info *psta);
562void set_sta_rate23a(struct rtw_adapter *padapter, struct sta_info *psta);
563
564unsigned int receive_disconnect23a(struct rtw_adapter *padapter,
565 unsigned char *MacAddr, unsigned short reason);
566
567unsigned char get_highest_rate_idx23a(u32 mask);
568int support_short_GI23a(struct rtw_adapter *padapter,
569 struct HT_caps_element *pHT_caps);
570unsigned int is_ap_in_tkip23a(struct rtw_adapter *padapter);
571unsigned int is_ap_in_wep23a(struct rtw_adapter *padapter);
572unsigned int should_forbid_n_rate23a(struct rtw_adapter *padapter);
573
574void report_join_res23a(struct rtw_adapter *padapter, int res);
575void report_survey_event23a(struct rtw_adapter *padapter,
576 struct recv_frame *precv_frame);
577void report_surveydone_event23a(struct rtw_adapter *padapter);
578void report_del_sta_event23a(struct rtw_adapter *padapter,
579 unsigned char *MacAddr, unsigned short reason);
580void report_add_sta_event23a(struct rtw_adapter *padapter,
581 unsigned char *MacAddr, int cam_idx);
582
583void beacon_timing_control23a(struct rtw_adapter *padapter);
584u8 set_tx_beacon_cmd23a(struct rtw_adapter*padapter);
585unsigned int setup_beacon_frame(struct rtw_adapter *padapter,
586 unsigned char *beacon_frame);
587void update_mgnt_tx_rate23a(struct rtw_adapter *padapter, u8 rate);
588void update_mgntframe_attrib23a(struct rtw_adapter *padapter,
589 struct pkt_attrib *pattrib);
590void dump_mgntframe23a(struct rtw_adapter *padapter,
591 struct xmit_frame *pmgntframe);
592s32 dump_mgntframe23a_and_wait(struct rtw_adapter *padapter,
593 struct xmit_frame *pmgntframe, int timeout_ms);
594s32 dump_mgntframe23a_and_wait_ack23a(struct rtw_adapter *padapter,
595 struct xmit_frame *pmgntframe);
596
597#ifdef CONFIG_8723AU_P2P
598void issue_probersp23a_p2p23a(struct rtw_adapter *padapter, unsigned char *da);
599void issue_p2p_provision_request23a(struct rtw_adapter *padapter, u8 *pssid,
600 u8 ussidlen, u8* pdev_raddr);
601void issue_p2p_GO_request23a(struct rtw_adapter *padapter, u8* raddr);
602void issue23a_probereq_p2p(struct rtw_adapter *padapter, u8 *da);
603int issue23a_probereq_p2p_ex(struct rtw_adapter *adapter, u8 *da, int try_cnt,
604 int wait_ms);
605void issue_p2p_invitation_response23a(struct rtw_adapter *padapter, u8* raddr,
606 u8 dialogToken, u8 success);
607void issue_p2p_invitation_request23a(struct rtw_adapter *padapter, u8* raddr);
608#endif /* CONFIG_8723AU_P2P */
609void issue_beacon23a(struct rtw_adapter *padapter, int timeout_ms);
610void issue_probersp23a(struct rtw_adapter *padapter, unsigned char *da,
611 u8 is_valid_p2p_probereq);
612void issue_assocreq23a(struct rtw_adapter *padapter);
613void issue_asocrsp23a(struct rtw_adapter *padapter, unsigned short status,
614 struct sta_info *pstat, int pkt_type);
615void issue_auth23a(struct rtw_adapter *padapter, struct sta_info *psta,
616 unsigned short status);
617void issue_probereq23a(struct rtw_adapter *padapter, struct cfg80211_ssid *pssid,
618 u8 *da);
619s32 issue_probereq23a_ex23a(struct rtw_adapter *padapter, struct cfg80211_ssid *pssid,
620 u8 *da, int try_cnt, int wait_ms);
621int issue_nulldata23a(struct rtw_adapter *padapter, unsigned char *da,
622 unsigned int power_mode, int try_cnt, int wait_ms);
623int issue_qos_nulldata23a(struct rtw_adapter *padapter, unsigned char *da, u16 tid,
624 int try_cnt, int wait_ms);
625int issue_deauth23a(struct rtw_adapter *padapter, unsigned char *da,
626 unsigned short reason);
627int issue_deauth23a_ex23a(struct rtw_adapter *padapter, u8 *da, unsigned short reason,
628 int try_cnt, int wait_ms);
629void issue_action_spct_ch_switch23a(struct rtw_adapter *padapter, u8 *ra,
630 u8 new_ch, u8 ch_offset);
631void issue_action_BA23a(struct rtw_adapter *padapter, unsigned char *raddr,
632 unsigned char action, unsigned short status);
633unsigned int send_delba23a(struct rtw_adapter *padapter, u8 initiator, u8 *addr);
634unsigned int send_beacon23a(struct rtw_adapter *padapter);
635
636void start_clnt_assoc23a(struct rtw_adapter *padapter);
637void start_clnt_auth23a(struct rtw_adapter *padapter);
638void start_clnt_join23a(struct rtw_adapter *padapter);
639void start_create_ibss23a(struct rtw_adapter *padapter);
640
641unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
642unsigned int OnAssocRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
643unsigned int OnProbeReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
644unsigned int OnProbeRsp23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
645unsigned int DoReserved23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
646unsigned int OnBeacon23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
647unsigned int OnAtim23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
648unsigned int OnDisassoc23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
649unsigned int OnAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
650unsigned int OnAuth23aClient23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
651unsigned int OnDeAuth23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
652unsigned int OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
653
654unsigned int on_action_spct23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
655unsigned int OnAction23a_qos(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
656unsigned int OnAction23a_dls(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
657unsigned int OnAction23a_back23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
658unsigned int on_action_public23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
659unsigned int OnAction23a_ht(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
660unsigned int OnAction23a_wmm(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
661unsigned int OnAction23a_p2p(struct rtw_adapter *padapter, struct recv_frame *precv_frame);
662
663
664void mlmeext_joinbss_event_callback23a(struct rtw_adapter *padapter, int join_res);
665void mlmeext_sta_del_event_callback23a(struct rtw_adapter *padapter);
666void mlmeext_sta_add_event_callback23a(struct rtw_adapter *padapter, struct sta_info *psta);
667
668void linked_status_chk23a(struct rtw_adapter *padapter);
669
670#define set_survey_timer(mlmeext, ms) \
671 /*DBG_8723A("%s set_survey_timer(%p, %d)\n", __FUNCTION__, (mlmeext), (ms));*/ \
672 mod_timer(&mlmeext->survey_timer, jiffies + msecs_to_jiffies(ms));
673
674#define set_link_timer(mlmeext, ms) \
675 /*DBG_8723A("%s set_link_timer(%p, %d)\n", __FUNCTION__, (mlmeext), (ms));*/ \
676 mod_timer(&mlmeext->link_timer, jiffies + msecs_to_jiffies(ms));
677
678int cckrates_included23a(unsigned char *rate, int ratelen);
679int cckratesonly_included23a(unsigned char *rate, int ratelen);
680
681void process_addba_req23a(struct rtw_adapter *padapter, u8 *paddba_req, u8 *addr);
682
683void update_TSF23a(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len);
684void correct_TSF23a(struct rtw_adapter *padapter, struct mlme_ext_priv *pmlmeext);
685
686struct cmd_hdl {
687 uint parmsize;
688 u8 (*h2cfuns)(struct rtw_adapter *padapter, u8 *pbuf);
689};
690
691
692u8 read_macreg_hdl(struct rtw_adapter *padapter, u8 *pbuf);
693u8 write_macreg_hdl(struct rtw_adapter *padapter, u8 *pbuf);
694u8 read_bbreg_hdl(struct rtw_adapter *padapter, u8 *pbuf);
695u8 write_bbreg_hdl(struct rtw_adapter *padapter, u8 *pbuf);
696u8 read_rfreg_hdl(struct rtw_adapter *padapter, u8 *pbuf);
697u8 write_rfreg_hdl(struct rtw_adapter *padapter, u8 *pbuf);
698
699
700u8 NULL_hdl23a(struct rtw_adapter *padapter, u8 *pbuf);
701u8 join_cmd_hdl23a(struct rtw_adapter *padapter, u8 *pbuf);
702u8 disconnect_hdl23a(struct rtw_adapter *padapter, u8 *pbuf);
703u8 createbss_hdl23a(struct rtw_adapter *padapter, u8 *pbuf);
704u8 setopmode_hdl23a(struct rtw_adapter *padapter, u8 *pbuf);
705u8 sitesurvey_cmd_hdl23a(struct rtw_adapter *padapter, u8 *pbuf);
706u8 setauth_hdl23a(struct rtw_adapter *padapter, u8 *pbuf);
707u8 setkey_hdl23a(struct rtw_adapter *padapter, u8 *pbuf);
708u8 set_stakey_hdl23a(struct rtw_adapter *padapter, u8 *pbuf);
709u8 set_assocsta_hdl(struct rtw_adapter *padapter, u8 *pbuf);
710u8 del_assocsta_hdl(struct rtw_adapter *padapter, u8 *pbuf);
711u8 add_ba_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf);
712
713u8 mlme_evt_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf);
714u8 h2c_msg_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf);
715u8 tx_beacon_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf);
716u8 set_ch_hdl23a(struct rtw_adapter *padapter, u8 *pbuf);
717u8 set_chplan_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf);
718u8 led_blink_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf);
719u8 set_csa_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf); /* Kurt: Handling DFS channel switch announcement ie. */
720u8 tdls_hdl23a(struct rtw_adapter *padapter, unsigned char *pbuf);
721
722#define GEN_DRV_CMD_HANDLER(size, cmd) {size, &cmd ## _hdl23a},
723#define GEN_MLME_EXT_HANDLER(size, cmd) {size, cmd},
724
725struct C2HEvent_Header {
726#ifdef __LITTLE_ENDIAN
727
728 unsigned int len:16;
729 unsigned int ID:8;
730 unsigned int seq:8;
731
732#elif defined(__BIG_ENDIAN)
733
734 unsigned int seq:8;
735 unsigned int ID:8;
736 unsigned int len:16;
737
738#else
739
740# error "Must be LITTLE or BIG Endian"
741
742#endif
743
744 unsigned int rsvd;
745};
746
747void rtw_dummy_event_callback23a(struct rtw_adapter *adapter , u8 *pbuf);
748void rtw23a_fwdbg_event_callback(struct rtw_adapter *adapter , u8 *pbuf);
749
750enum rtw_c2h_event {
751 GEN_EVT_CODE(_Read_MACREG) = 0, /*0*/
752 GEN_EVT_CODE(_Read_BBREG),
753 GEN_EVT_CODE(_Read_RFREG),
754 GEN_EVT_CODE(_Read_EEPROM),
755 GEN_EVT_CODE(_Read_EFUSE),
756 GEN_EVT_CODE(_Read_CAM), /*5*/
757 GEN_EVT_CODE(_Get_BasicRate),
758 GEN_EVT_CODE(_Get_DataRate),
759 GEN_EVT_CODE(_Survey), /*8*/
760 GEN_EVT_CODE(_SurveyDone), /*9*/
761
762 GEN_EVT_CODE(_JoinBss) , /*10*/
763 GEN_EVT_CODE(_AddSTA),
764 GEN_EVT_CODE(_DelSTA),
765 GEN_EVT_CODE(_AtimDone) ,
766 GEN_EVT_CODE(_TX_Report),
767 GEN_EVT_CODE(_CCX_Report), /*15*/
768 GEN_EVT_CODE(_DTM_Report),
769 GEN_EVT_CODE(_TX_Rate_Statistics),
770 GEN_EVT_CODE(_C2HLBK),
771 GEN_EVT_CODE(_FWDBG),
772 GEN_EVT_CODE(_C2HFEEDBACK), /*20*/
773 GEN_EVT_CODE(_ADDBA),
774 GEN_EVT_CODE(_C2HBCN),
775 GEN_EVT_CODE(_ReportPwrState), /* filen: only for PCIE, USB */
776 GEN_EVT_CODE(_CloseRF), /* filen: only for PCIE, work around ASPM */
777 MAX_C2HEVT
778};
779
780#endif
diff --git a/drivers/staging/rtl8723au/include/rtw_p2p.h b/drivers/staging/rtl8723au/include/rtw_p2p.h
new file mode 100644
index 000000000000..93fdc658ff4d
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_p2p.h
@@ -0,0 +1,158 @@
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 ******************************************************************************/
15#ifndef __RTW_P2P_H_
16#define __RTW_P2P_H_
17
18#include <drv_types.h>
19
20u32 build_beacon_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf);
21u32 build_probe_resp_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf);
22u32 build_prov_disc_request_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf,
23 u8 *pssid, u8 ussidlen, u8 *pdev_raddr);
24u32 build_assoc_resp_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf,
25 u8 status_code);
26u32 build_deauth_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pbuf);
27#ifdef CONFIG_8723AU_P2P
28u32 build_probe_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
29u32 build_probe_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf,
30 u8 tunneled);
31u32 build_beacon_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
32u32 build_nego_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
33u32 build_nego_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
34u32 build_nego_confirm_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
35u32 build_invitation_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
36u32 build_invitation_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
37u32 build_assoc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
38u32 build_assoc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
39u32 build_provdisc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
40u32 build_provdisc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf);
41#endif /* CONFIG_8723AU_P2P */
42
43u32 process_probe_req_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pframe,
44 uint len);
45u32 process_assoc_req_p2p_ie23a(struct wifidirect_info *pwdinfo, u8 *pframe,
46 uint len, struct sta_info *psta);
47u32 process_p2p_devdisc_req23a(struct wifidirect_info *pwdinfo, u8 *pframe,
48 uint len);
49u32 process_p2p_devdisc_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe,
50 uint len);
51u8 process_p2p_provdisc_req23a(struct wifidirect_info *pwdinfo, u8 *pframe,
52 uint len);
53u8 process_p2p_provdisc_resp23a(struct wifidirect_info *pwdinfo, u8 *pframe);
54u8 process_p2p_group_negotation_req23a(struct wifidirect_info *pwdinfo,
55 u8 *pframe, uint len);
56u8 process_p2p_group_negotation_resp23a(struct wifidirect_info *pwdinfo,
57 u8 *pframe, uint len);
58u8 process_p2p_group_negotation_confirm23a(struct wifidirect_info *pwdinfo,
59 u8 *pframe, uint len);
60u8 process_p2p_presence_req23a(struct wifidirect_info *pwdinfo,
61 u8 *pframe, uint len);
62
63void p2p_protocol_wk_hdl23a(struct rtw_adapter *padapter, int cmdtype);
64
65#ifdef CONFIG_8723AU_P2P
66void process_p2p_ps_ie23a(struct rtw_adapter *padapter, u8 *IEs, u32 IELength);
67void p2p_ps_wk_hdl23a(struct rtw_adapter *padapter, u8 p2p_ps_state);
68u8 p2p_ps_wk_cmd23a(struct rtw_adapter *padapter, u8 p2p_ps_state, u8 enqueue);
69#endif /* CONFIG_8723AU_P2P */
70
71void rtw_init_cfg80211_wifidirect_info(struct rtw_adapter *padapter);
72int rtw_p2p_check_frames(struct rtw_adapter *padapter, const u8 *buf,
73 u32 len, u8 tx);
74void rtw_append_wfd_ie(struct rtw_adapter *padapter, u8 *buf, u32 *len);
75
76void reset_global_wifidirect_info23a(struct rtw_adapter *padapter);
77int rtw_init_wifi_display_info(struct rtw_adapter *padapter);
78void rtw_init_wifidirect_timers23a(struct rtw_adapter *padapter);
79void rtw_init_wifidirect_addrs23a(struct rtw_adapter *padapter, u8 *dev_addr,
80 u8 *iface_addr);
81void init_wifidirect_info23a(struct rtw_adapter *padapter, enum P2P_ROLE role);
82int rtw_p2p_enable23a(struct rtw_adapter *padapter, enum P2P_ROLE role);
83
84static inline void _rtw_p2p_set_state(struct wifidirect_info *wdinfo,
85 enum P2P_STATE state)
86{
87 if (wdinfo->p2p_state != state) {
88 /* wdinfo->pre_p2p_state = wdinfo->p2p_state; */
89 wdinfo->p2p_state = state;
90 }
91}
92
93static inline void _rtw_p2p_set_pre_state(struct wifidirect_info *wdinfo,
94 enum P2P_STATE state)
95{
96 if (wdinfo->pre_p2p_state != state)
97 wdinfo->pre_p2p_state = state;
98}
99
100static inline void _rtw_p2p_set_role(struct wifidirect_info *wdinfo,
101 enum P2P_ROLE role)
102{
103 if (wdinfo->role != role)
104 wdinfo->role = role;
105}
106
107static inline int _rtw_p2p_state(struct wifidirect_info *wdinfo)
108{
109 return wdinfo->p2p_state;
110}
111
112static inline int _rtw_p2p_pre_state(struct wifidirect_info *wdinfo)
113{
114 return wdinfo->pre_p2p_state;
115}
116
117static inline int _rtw_p2p_role(struct wifidirect_info *wdinfo)
118{
119 return wdinfo->role;
120}
121
122static inline bool _rtw_p2p_chk_state(struct wifidirect_info *wdinfo,
123 enum P2P_STATE state)
124{
125 return wdinfo->p2p_state == state;
126}
127
128static inline bool _rtw_p2p_chk_role(struct wifidirect_info *wdinfo,
129 enum P2P_ROLE role)
130{
131 return wdinfo->role == role;
132}
133
134#define rtw_p2p_set_state(wdinfo, state) _rtw_p2p_set_state(wdinfo, state)
135#define rtw_p2p_set_pre_state(wdinfo, state) \
136 _rtw_p2p_set_pre_state(wdinfo, state)
137#define rtw_p2p_set_role(wdinfo, role) _rtw_p2p_set_role(wdinfo, role)
138
139#define rtw_p2p_state(wdinfo) _rtw_p2p_state(wdinfo)
140#define rtw_p2p_pre_state(wdinfo) _rtw_p2p_pre_state(wdinfo)
141#define rtw_p2p_role(wdinfo) _rtw_p2p_role(wdinfo)
142#define rtw_p2p_chk_state(wdinfo, state) _rtw_p2p_chk_state(wdinfo, state)
143#define rtw_p2p_chk_role(wdinfo, role) _rtw_p2p_chk_role(wdinfo, role)
144
145#define rtw_p2p_findphase_ex_set(wdinfo, value) \
146 ((wdinfo)->find_phase_state_exchange_cnt = (value))
147
148/* is this find phase exchange for social channel scan? */
149#define rtw_p2p_findphase_ex_is_social(wdinfo) \
150 ((wdinfo)->find_phase_state_exchange_cnt >= \
151 P2P_FINDPHASE_EX_SOCIAL_FIRST)
152
153/* should we need find phase exchange anymore? */
154#define rtw_p2p_findphase_ex_is_needed(wdinfo) \
155 ((wdinfo)->find_phase_state_exchange_cnt < P2P_FINDPHASE_EX_MAX && \
156 (wdinfo)->find_phase_state_exchange_cnt != P2P_FINDPHASE_EX_NONE)
157
158#endif
diff --git a/drivers/staging/rtl8723au/include/rtw_pwrctrl.h b/drivers/staging/rtl8723au/include/rtw_pwrctrl.h
new file mode 100644
index 000000000000..e0da87d4d3d6
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_pwrctrl.h
@@ -0,0 +1,265 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#ifndef __RTW_PWRCTRL_H_
16#define __RTW_PWRCTRL_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21#define FW_PWR0 0
22#define FW_PWR1 1
23#define FW_PWR2 2
24#define FW_PWR3 3
25
26
27#define HW_PWR0 7
28#define HW_PWR1 6
29#define HW_PWR2 2
30#define HW_PWR3 0
31#define HW_PWR4 8
32
33#define FW_PWRMSK 0x7
34
35
36#define XMIT_ALIVE BIT(0)
37#define RECV_ALIVE BIT(1)
38#define CMD_ALIVE BIT(2)
39#define EVT_ALIVE BIT(3)
40
41enum Power_Mgnt {
42 PS_MODE_ACTIVE = 0,
43 PS_MODE_MIN,
44 PS_MODE_MAX,
45 PS_MODE_DTIM,
46 PS_MODE_VOIP,
47 PS_MODE_UAPSD_WMM,
48 PS_MODE_UAPSD,
49 PS_MODE_IBSS,
50 PS_MODE_WWLAN,
51 PM_Radio_Off,
52 PM_Card_Disable,
53 PS_MODE_NUM
54};
55
56
57/* BIT[2:0] = HW state
58 * BIT[3] = Protocol PS state, 0: active, 1: sleep state
59 * BIT[4] = sub-state
60 */
61
62#define PS_DPS BIT(0)
63#define PS_LCLK (PS_DPS)
64#define PS_RF_OFF BIT(1)
65#define PS_ALL_ON BIT(2)
66#define PS_ST_ACTIVE BIT(3)
67
68#define PS_ISR_ENABLE BIT(4)
69#define PS_IMR_ENABLE BIT(5)
70#define PS_ACK BIT(6)
71#define PS_TOGGLE BIT(7)
72
73#define PS_STATE_MASK (0x0F)
74#define PS_STATE_HW_MASK (0x07)
75#define PS_SEQ_MASK (0xc0)
76
77#define PS_STATE(x) (PS_STATE_MASK & (x))
78#define PS_STATE_HW(x) (PS_STATE_HW_MASK & (x))
79#define PS_SEQ(x) (PS_SEQ_MASK & (x))
80
81#define PS_STATE_S0 (PS_DPS)
82#define PS_STATE_S1 (PS_LCLK)
83#define PS_STATE_S2 (PS_RF_OFF)
84#define PS_STATE_S3 (PS_ALL_ON)
85#define PS_STATE_S4 ((PS_ST_ACTIVE) | (PS_ALL_ON))
86
87
88#define PS_IS_RF_ON(x) ((x) & (PS_ALL_ON))
89#define PS_IS_ACTIVE(x) ((x) & (PS_ST_ACTIVE))
90#define CLR_PS_STATE(x) ((x) = ((x) & (0xF0)))
91
92
93struct reportpwrstate_parm {
94 unsigned char mode;
95 unsigned char state; /* the CPWM value */
96 unsigned short rsvd;
97};
98
99#define LPS_DELAY_TIME (1*HZ) /* 1 sec */
100
101#define EXE_PWR_NONE 0x01
102#define EXE_PWR_IPS 0x02
103#define EXE_PWR_LPS 0x04
104
105/* RF state. */
106enum rt_rf_power_state {
107 rf_on, /* RF is on after RFSleep or RFOff */
108 rf_sleep, /* 802.11 Power Save mode */
109 rf_off, /* HW/SW Radio OFF or Inactive Power Save */
110 /* Add the new RF state above this line===== */
111 rf_max
112};
113
114/* RF Off Level for IPS or HW/SW radio off */
115#define RT_RF_OFF_LEVL_ASPM BIT(0) /* PCI ASPM */
116#define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /* PCI clock request */
117#define RT_RF_OFF_LEVL_PCI_D3 BIT(2) /* PCI D3 mode */
118/* NIC halt, re-init hw params */
119#define RT_RF_OFF_LEVL_HALT_NIC BIT(3)
120/* FW free, re-download the FW */
121#define RT_RF_OFF_LEVL_FREE_FW BIT(4)
122#define RT_RF_OFF_LEVL_FW_32K BIT(5) /* FW in 32k */
123/* Always enable ASPM and Clock Req in initialization. */
124#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT(6)
125/* When LPS is on, disable 2R if no packet is received or transmittd. */
126#define RT_RF_LPS_DISALBE_2R BIT(30)
127#define RT_RF_LPS_LEVEL_ASPM BIT(31) /* LPS with ASPM */
128
129#define RT_IN_PS_LEVEL(ppsc, _PS_FLAG) \
130 ((ppsc->cur_ps_level & _PS_FLAG) ? true : false)
131#define RT_CLEAR_PS_LEVEL(ppsc, _PS_FLAG) \
132 (ppsc->cur_ps_level &= (~(_PS_FLAG)))
133#define RT_SET_PS_LEVEL(ppsc, _PS_FLAG) \
134 (ppsc->cur_ps_level |= _PS_FLAG)
135
136
137enum {
138 PSBBREG_RF0 = 0,
139 PSBBREG_RF1,
140 PSBBREG_RF2,
141 PSBBREG_AFE0,
142 PSBBREG_TOTALCNT
143};
144
145enum { /* for ips_mode */
146 IPS_NONE = 0,
147 IPS_NORMAL,
148 IPS_LEVEL_2,
149};
150
151struct pwrctrl_priv {
152 struct semaphore lock;
153 volatile u8 rpwm; /* requested power state for fw */
154 volatile u8 cpwm; /* fw current power state. updated when 1.
155 * read from HCPWM 2. driver lowers power level
156 */
157 volatile u8 tog; /* toggling */
158 volatile u8 cpwm_tog; /* toggling */
159
160 u8 pwr_mode;
161 u8 smart_ps;
162 u8 bcn_ant_mode;
163
164 u32 alives;
165 struct work_struct cpwm_event;
166 u8 bpower_saving;
167
168 u8 b_hw_radio_off;
169 u8 reg_rfoff;
170 u8 reg_pdnmode; /* powerdown mode */
171 u32 rfoff_reason;
172
173 /* RF OFF Level */
174 u32 cur_ps_level;
175 u32 reg_rfps_level;
176
177 uint ips_enter23a_cnts;
178 uint ips_leave23a_cnts;
179
180 u8 ips_mode;
181 u8 ips_mode_req; /* used to accept the mode setting request */
182 uint bips_processing;
183 unsigned long ips_deny_time; /* deny IPS when system time is smaller */
184 u8 ps_processing; /* used to mark whether in rtw_ps_processor23a */
185
186 u8 bLeisurePs;
187 u8 LpsIdleCount;
188 u8 power_mgnt;
189 u8 bFwCurrentInPSMode;
190 unsigned long DelayLPSLastTimeStamp;
191 u8 btcoex_rfon;
192 s32 pnp_current_pwr_state;
193 u8 pnp_bstop_trx;
194
195 u8 bInternalAutoSuspend;
196 u8 bInSuspend;
197#ifdef CONFIG_8723AU_BT_COEXIST
198 u8 bAutoResume;
199 u8 autopm_cnt;
200#endif
201 u8 bSupportRemoteWakeup;
202 struct timer_list pwr_state_check_timer;
203 int pwr_state_check_interval;
204 u8 pwr_state_check_cnts;
205
206 int ps_flag;
207
208 enum rt_rf_power_state rf_pwrstate;/* cur power state */
209 enum rt_rf_power_state change_rfpwrstate;
210
211 u8 wepkeymask;
212 u8 bHWPowerdown;/* if support hw power down */
213 u8 bHWPwrPindetect;
214 u8 bkeepfwalive;
215 u8 brfoffbyhw;
216 unsigned long PS_BBRegBackup[PSBBREG_TOTALCNT];
217};
218
219#define rtw_get_ips_mode_req(pwrctrlpriv) \
220 ((pwrctrlpriv)->ips_mode_req)
221
222#define rtw_ips_mode_req(pwrctrlpriv, ips_mode) \
223 ((pwrctrlpriv)->ips_mode_req = (ips_mode))
224
225#define RTW_PWR_STATE_CHK_INTERVAL 2000
226
227#define _rtw_set_pwr_state_check_timer(pwrctrlpriv, ms) \
228 (mod_timer(&pwrctrlpriv->pwr_state_check_timer, jiffies + \
229 msecs_to_jiffies(ms)))
230
231#define rtw_set_pwr_state_check_timer(pwrctrlpriv) \
232 (_rtw_set_pwr_state_check_timer((pwrctrlpriv), \
233 (pwrctrlpriv)->pwr_state_check_interval))
234
235void rtw_init_pwrctrl_priv23a(struct rtw_adapter *adapter);
236void rtw_free_pwrctrl_priv(struct rtw_adapter *adapter);
237
238void rtw_set_ps_mode23a(struct rtw_adapter *padapter, u8 ps_mode,
239 u8 smart_ps, u8 bcn_ant_mode);
240void rtw_set_rpwm23a(struct rtw_adapter *padapter, u8 val8);
241void LeaveAllPowerSaveMode23a(struct rtw_adapter *adapter);
242void ips_enter23a(struct rtw_adapter *padapter);
243int ips_leave23a(struct rtw_adapter *padapter);
244
245void rtw_ps_processor23a(struct rtw_adapter *padapter);
246
247enum rt_rf_power_state RfOnOffDetect23a(struct rtw_adapter *adapter);
248
249s32 LPS_RF_ON_check23a(struct rtw_adapter *padapter, u32 delay_ms);
250void LPS_Enter23a(struct rtw_adapter *padapter);
251void LPS_Leave23a(struct rtw_adapter *padapter);
252
253u8 rtw_interface_ps_func23a(struct rtw_adapter *padapter,
254 enum hal_intf_ps_func efunc_id, u8 *val);
255void rtw_set_ips_deny23a(struct rtw_adapter *padapter, u32 ms);
256int _rtw_pwr_wakeup23a(struct rtw_adapter *padapter, u32 ips_deffer_ms,
257 const char *caller);
258#define rtw_pwr_wakeup(adapter) _rtw_pwr_wakeup23a(adapter, \
259 RTW_PWR_STATE_CHK_INTERVAL, __func__)
260#define rtw_pwr_wakeup_ex(adapter, ips_deffer_ms) \
261 _rtw_pwr_wakeup23a(adapter, ips_deffer_ms, __func__)
262int rtw_pm_set_ips23a(struct rtw_adapter *padapter, u8 mode);
263int rtw_pm_set_lps23a(struct rtw_adapter *padapter, u8 mode);
264
265#endif /* __RTL871X_PWRCTRL_H_ */
diff --git a/drivers/staging/rtl8723au/include/rtw_qos.h b/drivers/staging/rtl8723au/include/rtw_qos.h
new file mode 100644
index 000000000000..68fc5ba1844a
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_qos.h
@@ -0,0 +1,26 @@
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 ******************************************************************************/
15
16#ifndef _RTW_QOS_H_
17#define _RTW_QOS_H_
18
19#include <osdep_service.h>
20
21struct qos_priv {
22 /* bit mask option: u-apsd, s-apsd, ts, block ack... */
23 unsigned int qos_option;
24};
25
26#endif /* _RTL871X_QOS_H_ */
diff --git a/drivers/staging/rtl8723au/include/rtw_recv.h b/drivers/staging/rtl8723au/include/rtw_recv.h
new file mode 100644
index 000000000000..d1866a6e831f
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_recv.h
@@ -0,0 +1,318 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#ifndef _RTW_RECV_H_
16#define _RTW_RECV_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20#include <Hal8723APhyCfg.h>
21
22#define NR_RECVFRAME 256
23
24#define MAX_RXFRAME_CNT 512
25#define MAX_RX_NUMBLKS (32)
26#define RECVFRAME_HDR_ALIGN 128
27
28#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
29
30#define MAX_SUBFRAME_COUNT 64
31
32/* for Rx reordering buffer control */
33struct recv_reorder_ctrl {
34 struct rtw_adapter *padapter;
35 u8 enable;
36 u16 indicate_seq;/* wstart_b, init_value=0xffff */
37 u16 wend_b;
38 u8 wsize_b;
39 struct rtw_queue pending_recvframe_queue;
40 struct timer_list reordering_ctrl_timer;
41};
42
43struct stainfo_rxcache {
44 u16 tid_rxseq[16];
45/*
46 unsigned short tid0_rxseq;
47 unsigned short tid1_rxseq;
48 unsigned short tid2_rxseq;
49 unsigned short tid3_rxseq;
50 unsigned short tid4_rxseq;
51 unsigned short tid5_rxseq;
52 unsigned short tid6_rxseq;
53 unsigned short tid7_rxseq;
54 unsigned short tid8_rxseq;
55 unsigned short tid9_rxseq;
56 unsigned short tid10_rxseq;
57 unsigned short tid11_rxseq;
58 unsigned short tid12_rxseq;
59 unsigned short tid13_rxseq;
60 unsigned short tid14_rxseq;
61 unsigned short tid15_rxseq;
62*/
63};
64
65struct smooth_rssi_data {
66 u32 elements[100]; /* array to store values */
67 u32 index; /* index to current array to store */
68 u32 total_num; /* num of valid elements */
69 u32 total_val; /* sum of valid elements */
70};
71
72struct signal_stat {
73 u8 update_req; /* used to indicate */
74 u8 avg_val; /* avg of valid elements */
75 u32 total_num; /* num of valid elements */
76 u32 total_val; /* sum of valid elements */
77};
78
79struct phy_info {
80 u8 RxPWDBAll;
81 u8 SignalQuality; /* in 0-100 index. */
82 u8 RxMIMOSignalQuality[RF_PATH_MAX]; /* EVM */
83 u8 RxMIMOSignalStrength[RF_PATH_MAX];/* 0~100 */
84 s8 RxPower; /* in dBm Translate from PWdB */
85 /* Real power in dBm for this packet, no beautification and aggregation.
86 * Keep this raw info to be used for the other procedures.
87 */
88 s8 RecvSignalPower;
89 u8 BTRxRSSIPercentage;
90 u8 SignalStrength; /* in 0-100 index. */
91 u8 RxPwr[RF_PATH_MAX];/* per-path's pwdb */
92 u8 RxSNR[RF_PATH_MAX];/* per-path's SNR */
93};
94
95
96struct rx_pkt_attrib {
97 u16 pkt_len;
98 u8 physt;
99 u8 drvinfo_sz;
100 u8 shift_sz;
101 u8 hdrlen; /* the WLAN Header Len */
102 u8 to_fr_ds;
103 u8 amsdu;
104 u8 qos;
105 u8 priority;
106 u8 pw_save;
107 u8 mdata;
108 u16 seq_num;
109 u8 frag_num;
110 u8 mfrag;
111 u8 order;
112 u8 privacy; /* in frame_ctrl field */
113 u8 bdecrypted;
114 /* when 0 indicate no encrypt. when non-zero, indicate the algorith */
115 u8 encrypt;
116 u8 iv_len;
117 u8 icv_len;
118 u8 crc_err;
119 u8 icv_err;
120
121 u16 eth_type;
122
123 u8 dst[ETH_ALEN];
124 u8 src[ETH_ALEN];
125 u8 ta[ETH_ALEN];
126 u8 ra[ETH_ALEN];
127 u8 bssid[ETH_ALEN];
128
129 u8 ack_policy;
130
131 u8 tcpchk_valid; /* 0: invalid, 1: valid */
132 u8 ip_chkrpt; /* 0: incorrect, 1: correct */
133 u8 tcp_chkrpt; /* 0: incorrect, 1: correct */
134 u8 key_index;
135
136 u8 mcs_rate;
137 u8 rxht;
138 u8 sgi;
139 u8 pkt_rpt_type;
140 u32 MacIDValidEntry[2]; /* 64 bits present 64 entry. */
141 struct phy_info phy_info;
142};
143
144/* These definition is used for Rx packet reordering. */
145#define SN_LESS(a, b) (((a-b) & 0x800) != 0)
146#define SN_EQUAL(a, b) (a == b)
147#define REORDER_WAIT_TIME (50) /* (ms) */
148
149#define RECVBUFF_ALIGN_SZ 8
150
151#define RXDESC_SIZE 24
152#define RXDESC_OFFSET RXDESC_SIZE
153
154struct recv_stat {
155 unsigned int rxdw0;
156 unsigned int rxdw1;
157 unsigned int rxdw2;
158 unsigned int rxdw3;
159 unsigned int rxdw4;
160 unsigned int rxdw5;
161};
162
163/* accesser of recv_priv: rtw_recv_entry23a(dispatch / passive level); \
164 * recv_thread(passive) ; returnpkt(dispatch) ; halt(passive) ;
165 *
166 * using enter_critical section to protect
167 */
168struct recv_priv {
169 spinlock_t lock;
170
171 struct rtw_queue free_recv_queue;
172 struct rtw_queue recv_pending_queue;
173 struct rtw_queue uc_swdec_pending_queue;
174
175 void *pallocated_frame_buf;
176
177 uint free_recvframe_cnt;
178
179 struct rtw_adapter *adapter;
180
181 u32 bIsAnyNonBEPkts;
182 u64 rx_bytes;
183 u64 rx_pkts;
184 u64 rx_drop;
185 u64 last_rx_bytes;
186
187 uint rx_icv_err;
188 uint rx_largepacket_crcerr;
189 uint rx_smallpacket_crcerr;
190 uint rx_middlepacket_crcerr;
191
192 /* u8 *pallocated_urb_buf; */
193 struct semaphore allrxreturnevt;
194 uint ff_hwaddr;
195 u8 rx_pending_cnt;
196
197 struct urb *int_in_urb;
198
199 u8 *int_in_buf;
200
201 struct tasklet_struct irq_prepare_beacon_tasklet;
202 struct tasklet_struct recv_tasklet;
203 struct sk_buff_head free_recv_skb_queue;
204 struct sk_buff_head rx_skb_queue;
205 u8 *precv_buf;
206 struct rtw_queue free_recv_buf_queue;
207 u32 free_recv_buf_queue_cnt;
208
209 /* For display the phy informatiom */
210 u8 is_signal_dbg; /* for debug */
211 u8 signal_strength_dbg; /* for debug */
212 s8 rssi;
213 s8 rxpwdb;
214 u8 signal_strength;
215 u8 signal_qual;
216 u8 noise;
217 int RxSNRdB[2];
218 s8 RxRssi[2];
219 int FalseAlmCnt_all;
220
221 struct timer_list signal_stat_timer;
222 u32 signal_stat_sampling_interval;
223 /* u32 signal_stat_converging_constant; */
224 struct signal_stat signal_qual_data;
225 struct signal_stat signal_strength_data;
226};
227
228#define rtw_set_signal_stat_timer(recvpriv) \
229 mod_timer(&(recvpriv)->signal_stat_timer, jiffies + \
230 msecs_to_jiffies((recvpriv)->signal_stat_sampling_interval))
231
232struct sta_recv_priv {
233 spinlock_t lock;
234 int option;
235
236 /* struct rtw_queue blk_strms[MAX_RX_NUMBLKS]; */
237 struct rtw_queue defrag_q; /* keeping the fragment frame until defrag */
238
239 struct stainfo_rxcache rxcache;
240
241 /* uint sta_rx_bytes; */
242 /* uint sta_rx_pkts; */
243 /* uint sta_rx_fail; */
244
245};
246
247
248struct recv_buf {
249 struct list_head list;
250
251 struct rtw_adapter *adapter;
252
253 struct urb *purb;
254 struct sk_buff *pskb;
255};
256
257/* head ----->
258 *
259 * data ----->
260 *
261 * payload
262 *
263 * tail ----->
264 *
265 * end ----->
266 *
267 * len = (unsigned int )(tail - data);
268 *
269 */
270struct recv_frame {
271 struct list_head list;
272 struct sk_buff *pkt;
273
274 struct rtw_adapter *adapter;
275
276 struct rx_pkt_attrib attrib;
277
278 struct sta_info *psta;
279
280 /* for A-MPDU Rx reordering buffer control */
281 struct recv_reorder_ctrl *preorder_ctrl;
282};
283
284/* get a free recv_frame from pfree_recv_queue */
285struct recv_frame *rtw_alloc_recvframe23a(struct rtw_queue *pfree_recv_queue);
286int rtw_free_recvframe23a(struct recv_frame *precvframe, struct rtw_queue *pfree_recv_queue);
287
288int rtw_enqueue_recvframe23a(struct recv_frame *precvframe, struct rtw_queue *queue);
289
290void rtw_free_recvframe23a_queue(struct rtw_queue *pframequeue, struct rtw_queue *pfree_recv_queue);
291u32 rtw_free_uc_swdec_pending_queue23a(struct rtw_adapter *adapter);
292
293int rtw_enqueue_recvbuf23a_to_head(struct recv_buf *precvbuf, struct rtw_queue *queue);
294int rtw_enqueue_recvbuf23a(struct recv_buf *precvbuf, struct rtw_queue *queue);
295struct recv_buf *rtw_dequeue_recvbuf23a(struct rtw_queue *queue);
296
297void rtw_reordering_ctrl_timeout_handler23a(unsigned long pcontext);
298
299static inline s32 translate_percentage_to_dbm(u32 SignalStrengthIndex)
300{
301 s32 SignalPower; /* in dBm. */
302
303 /* Translate to dBm (x=0.5y-95). */
304 SignalPower = (s32)((SignalStrengthIndex + 1) >> 1);
305 SignalPower -= 95;
306
307 return SignalPower;
308}
309
310
311struct sta_info;
312
313void _rtw_init_sta_recv_priv23a(struct sta_recv_priv *psta_recvpriv);
314
315void mgt_dispatcher23a(struct rtw_adapter *padapter,
316 struct recv_frame *precv_frame);
317
318#endif
diff --git a/drivers/staging/rtl8723au/include/rtw_rf.h b/drivers/staging/rtl8723au/include/rtw_rf.h
new file mode 100644
index 000000000000..91a0a22a2709
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_rf.h
@@ -0,0 +1,113 @@
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 ******************************************************************************/
15#ifndef __RTW_RF_H_
16#define __RTW_RF_H_
17
18#include <rtw_cmd.h>
19
20#define OFDM_PHY 1
21#define MIXED_PHY 2
22#define CCK_PHY 3
23
24#define NumRates (13)
25
26/* slot time for 11g */
27#define SHORT_SLOT_TIME 9
28#define NON_SHORT_SLOT_TIME 20
29
30/* We now define the max channels in each channel plan. */
31#define MAX_CHANNEL_NUM_2G 14
32#define MAX_CHANNEL_NUM_5G 24
33#define MAX_CHANNEL_NUM 38/* 14+24 */
34
35/* define NUM_REGULATORYS 21 */
36#define NUM_REGULATORYS 1
37
38/* Country codes */
39#define USA 0x555320
40#define EUROPE 0x1 /* temp, should be provided later */
41#define JAPAN 0x2 /* temp, should be provided later */
42
43struct regulatory_class {
44 u32 starting_freq; /* MHz, */
45 u8 channel_set[MAX_CHANNEL_NUM];
46 u8 channel_cck_power[MAX_CHANNEL_NUM];/* dbm */
47 u8 channel_ofdm_power[MAX_CHANNEL_NUM];/* dbm */
48 u8 txpower_limit; /* dbm */
49 u8 channel_spacing; /* MHz */
50 u8 modem;
51};
52
53enum {
54 cESS = 0x0001,
55 cIBSS = 0x0002,
56 cPollable = 0x0004,
57 cPollReq = 0x0008,
58 cPrivacy = 0x0010,
59 cShortPreamble = 0x0020,
60 cPBCC = 0x0040,
61 cChannelAgility = 0x0080,
62 cSpectrumMgnt = 0x0100,
63 cQos = 0x0200, /* For HCCA, use with CF-Pollable and CF-PollReq */
64 cShortSlotTime = 0x0400,
65 cAPSD = 0x0800,
66 cRM = 0x1000, /* RRM (Radio Request Measurement) */
67 cDSSS_OFDM = 0x2000,
68 cDelayedBA = 0x4000,
69 cImmediateBA = 0x8000,
70};
71
72enum {
73 PREAMBLE_LONG = 1,
74 PREAMBLE_AUTO = 2,
75 PREAMBLE_SHORT = 3,
76};
77
78/* Bandwidth Offset */
79#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0
80#define HAL_PRIME_CHNL_OFFSET_LOWER 1
81#define HAL_PRIME_CHNL_OFFSET_UPPER 2
82
83/* Represent Channel Width in HT Capabilities */
84enum ht_channel_width {
85 HT_CHANNEL_WIDTH_20 = 0,
86 HT_CHANNEL_WIDTH_40 = 1,
87 HT_CHANNEL_WIDTH_80 = 2,
88 HT_CHANNEL_WIDTH_160 = 3,
89 HT_CHANNEL_WIDTH_10 = 4,
90};
91
92/* */
93/* Represent Extention Channel Offset in HT Capabilities */
94/* This is available only in 40Mhz mode. */
95/* */
96enum {
97 HT_EXTCHNL_OFFSET_NO_EXT = 0,
98 HT_EXTCHNL_OFFSET_UPPER = 1,
99 HT_EXTCHNL_OFFSET_NO_DEF = 2,
100 HT_EXTCHNL_OFFSET_LOWER = 3,
101};
102
103/* 2007/11/15 MH Define different RF type. */
104enum {
105 RF_1T2R = 0,
106 RF_2T4R = 1,
107 RF_2T2R = 2,
108 RF_1T1R = 3,
109 RF_2T2R_GREEN = 4,
110 RF_819X_MAX_TYPE = 5,
111};
112
113#endif /* _RTL8711_RF_H_ */
diff --git a/drivers/staging/rtl8723au/include/rtw_security.h b/drivers/staging/rtl8723au/include/rtw_security.h
new file mode 100644
index 000000000000..75bbb934a53c
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_security.h
@@ -0,0 +1,357 @@
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 ******************************************************************************/
15#ifndef __RTW_SECURITY_H_
16#define __RTW_SECURITY_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21
22#define _NO_PRIVACY_ 0x0
23#define _WEP40_ 0x1
24#define _TKIP_ 0x2
25#define _TKIP_WTMIC_ 0x3
26#define _AES_ 0x4
27#define _WEP104_ 0x5
28#define _WEP_WPA_MIXED_ 0x07 /* WEP + WPA */
29#define _SMS4_ 0x06
30
31#define is_wep_enc(alg) (((alg) == _WEP40_) || ((alg) == _WEP104_))
32
33#define _WPA_IE_ID_ 0xdd
34#define _WPA2_IE_ID_ 0x30
35
36#define SHA256_MAC_LEN 32
37#define AES_BLOCK_SIZE 16
38#define AES_PRIV_SIZE (4 * 44)
39
40enum ENCRYP_PROTOCOL {
41 ENCRYP_PROTOCOL_OPENSYS, /* open system */
42 ENCRYP_PROTOCOL_WEP, /* WEP */
43 ENCRYP_PROTOCOL_WPA, /* WPA */
44 ENCRYP_PROTOCOL_WPA2, /* WPA2 */
45 ENCRYP_PROTOCOL_MAX
46};
47
48#ifndef Ndis802_11AuthModeWPA2
49#define Ndis802_11AuthModeWPA2 (Ndis802_11AuthModeWPANone + 1)
50#endif
51
52#ifndef Ndis802_11AuthModeWPA2PSK
53#define Ndis802_11AuthModeWPA2PSK (Ndis802_11AuthModeWPANone + 2)
54#endif
55
56union pn48 {
57 u64 val;
58
59#ifdef __LITTLE_ENDIAN
60
61struct {
62 u8 TSC0;
63 u8 TSC1;
64 u8 TSC2;
65 u8 TSC3;
66 u8 TSC4;
67 u8 TSC5;
68 u8 TSC6;
69 u8 TSC7;
70} _byte_;
71
72#elif defined(__BIG_ENDIAN)
73
74struct {
75 u8 TSC7;
76 u8 TSC6;
77 u8 TSC5;
78 u8 TSC4;
79 u8 TSC3;
80 u8 TSC2;
81 u8 TSC1;
82 u8 TSC0;
83} _byte_;
84#else
85#error Need BIG or LITTLE endian
86
87#endif
88
89};
90
91union Keytype {
92 u8 skey[16];
93 u32 lkey[4];
94};
95
96
97struct rt_pmkid_list {
98 u8 bUsed;
99 u8 Bssid[6];
100 u8 PMKID[16];
101 u8 SsidBuf[33];
102 u8 *ssid_octet;
103 u16 ssid_length;
104};
105
106struct security_priv {
107 u32 dot11AuthAlgrthm; /* 802.11 auth, could be open, shared,
108 * 8021x and authswitch */
109 u32 dot11PrivacyAlgrthm; /* This specifies the privacy for
110 * shared auth. algorithm.
111 */
112 /* WEP */
113 u32 dot11PrivacyKeyIndex; /* this is only valid for legendary
114 * wep, 0~3 for key id. (tx key index)
115 */
116 union Keytype dot11DefKey[4]; /* this is only valid for def. key */
117 u32 dot11DefKeylen[4];
118
119 u32 dot118021XGrpPrivacy; /* specify the privacy algthm.
120 * used for Grp key
121 */
122 u32 dot118021XGrpKeyid; /* key id used for Grp Key
123 * (tx key index)
124 */
125 union Keytype dot118021XGrpKey[4];/* 802.1x Grp Key, inx0 and inx1 */
126 union Keytype dot118021XGrptxmickey[4];
127 union Keytype dot118021XGrprxmickey[4];
128 union pn48 dot11Grptxpn; /* PN48 used for Grp Key xmit.*/
129 union pn48 dot11Grprxpn; /* PN48 used for Grp Key recv.*/
130
131#ifdef CONFIG_8723AU_AP_MODE
132 /* extend security capabilities for AP_MODE */
133 unsigned int dot8021xalg;/* 0:disable, 1:psk, 2:802.1x */
134 unsigned int wpa_psk;/* 0:disable, bit(0): WPA, bit(1):WPA2 */
135 unsigned int wpa_group_cipher;
136 unsigned int wpa2_group_cipher;
137 unsigned int wpa_pairwise_cipher;
138 unsigned int wpa2_pairwise_cipher;
139#endif
140
141 u8 wps_ie[MAX_WPS_IE_LEN];/* added in assoc req */
142 int wps_ie_len;
143 u8 binstallGrpkey;
144 u8 busetkipkey;
145 u8 bcheck_grpkey;
146 u8 bgrpkey_handshake;
147 s32 hw_decrypted;
148 u32 ndisauthtype; /* enum ndis_802_11_auth_mode */
149 u32 ndisencryptstatus; /* NDIS_802_11_ENCRYPTION_STATUS */
150 struct wlan_bssid_ex sec_bss; /* for joinbss (h2c buffer) usage */
151 struct ndis_802_11_wep ndiswep;
152 u8 assoc_info[600];
153 u8 szofcapability[256]; /* for wpa2 usage */
154 u8 oidassociation[512]; /* for wpa/wpa2 usage */
155 u8 authenticator_ie[256]; /* store ap security information element */
156 u8 supplicant_ie[256]; /* store sta security information element */
157
158 /* for tkip countermeasure */
159 unsigned long last_mic_err_time;
160 u8 btkip_countermeasure;
161 u8 btkip_wait_report;
162 unsigned long btkip_countermeasure_time;
163
164 /* For WPA2 Pre-Authentication. */
165 struct rt_pmkid_list PMKIDList[NUM_PMKID_CACHE];
166 u8 PMKIDIndex;
167 u8 bWepDefaultKeyIdxSet;
168};
169
170struct sha256_state {
171 u64 length;
172 u32 state[8], curlen;
173 u8 buf[64];
174};
175
176#define GET_ENCRY_ALGO(psecuritypriv, psta, encry_algo, bmcst)\
177do {\
178 switch (psecuritypriv->dot11AuthAlgrthm) {\
179 case dot11AuthAlgrthm_Open:\
180 case dot11AuthAlgrthm_Shared:\
181 case dot11AuthAlgrthm_Auto:\
182 encry_algo = (u8)psecuritypriv->dot11PrivacyAlgrthm;\
183 break;\
184 case dot11AuthAlgrthm_8021X:\
185 if (bmcst)\
186 encry_algo = (u8)psecuritypriv->dot118021XGrpPrivacy;\
187 else\
188 encry_algo = (u8)psta->dot118021XPrivacy;\
189 break;\
190 } \
191} while (0)
192
193#define GET_TKIP_PN(iv, dot11txpn)\
194do {\
195 dot11txpn._byte_.TSC0 = iv[2];\
196 dot11txpn._byte_.TSC1 = iv[0];\
197 dot11txpn._byte_.TSC2 = iv[4];\
198 dot11txpn._byte_.TSC3 = iv[5];\
199 dot11txpn._byte_.TSC4 = iv[6];\
200 dot11txpn._byte_.TSC5 = iv[7];\
201} while (0)
202
203#define ROL32(A, n) (((A) << (n)) | (((A)>>(32-(n))) & ((1UL << (n)) - 1)))
204#define ROR32(A, n) ROL32((A), 32-(n))
205
206struct mic_data {
207 u32 K0, K1; /* Key */
208 u32 L, R; /* Current state */
209 u32 M; /* Message accumulator (single word) */
210 u32 nBytesInM; /* # bytes in M */
211};
212
213extern const u32 Te0[256];
214extern const u32 Te1[256];
215extern const u32 Te2[256];
216extern const u32 Te3[256];
217extern const u32 Te4[256];
218extern const u32 Td0[256];
219extern const u32 Td1[256];
220extern const u32 Td2[256];
221extern const u32 Td3[256];
222extern const u32 Td4[256];
223extern const u32 rcon[10];
224extern const u8 Td4s[256];
225extern const u8 rcons[10];
226
227#define RCON(i) (rcons[(i)] << 24)
228
229static inline u32 rotr(u32 val, int bits)
230{
231 return (val >> bits) | (val << (32 - bits));
232}
233
234#define TE0(i) Te0[((i) >> 24) & 0xff]
235#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8)
236#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16)
237#define TE3(i) rotr(Te0[(i) & 0xff], 24)
238#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000)
239#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000)
240#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00)
241#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff)
242#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000)
243#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000)
244#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00)
245#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff)
246#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff)
247
248#define TD0(i) Td0[((i) >> 24) & 0xff]
249#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8)
250#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16)
251#define TD3(i) rotr(Td0[(i) & 0xff], 24)
252#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24)
253#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16)
254#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8)
255#define TD44(i) (Td4s[(i) & 0xff])
256#define TD0_(i) Td0[(i) & 0xff]
257#define TD1_(i) rotr(Td0[(i) & 0xff], 8)
258#define TD2_(i) rotr(Td0[(i) & 0xff], 16)
259#define TD3_(i) rotr(Td0[(i) & 0xff], 24)
260
261#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \
262 ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
263
264#define PUTU32(ct, st) { \
265(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \
266(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
267
268#define WPA_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \
269 (((u32) (a)[2]) << 8) | ((u32) (a)[3]))
270
271#define WPA_PUT_LE16(a, val) \
272 do { \
273 (a)[1] = ((u16) (val)) >> 8; \
274 (a)[0] = ((u16) (val)) & 0xff; \
275 } while (0)
276
277#define WPA_PUT_BE32(a, val) \
278 do { \
279 (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff); \
280 (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff); \
281 (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff); \
282 (a)[3] = (u8) (((u32) (val)) & 0xff); \
283 } while (0)
284
285#define WPA_PUT_BE64(a, val) \
286 do { \
287 (a)[0] = (u8) (((u64) (val)) >> 56); \
288 (a)[1] = (u8) (((u64) (val)) >> 48); \
289 (a)[2] = (u8) (((u64) (val)) >> 40); \
290 (a)[3] = (u8) (((u64) (val)) >> 32); \
291 (a)[4] = (u8) (((u64) (val)) >> 24); \
292 (a)[5] = (u8) (((u64) (val)) >> 16); \
293 (a)[6] = (u8) (((u64) (val)) >> 8); \
294 (a)[7] = (u8) (((u64) (val)) & 0xff); \
295 } while (0)
296
297/* ===== start - public domain SHA256 implementation ===== */
298
299/* This is based on SHA256 implementation in LibTomCrypt that was released into
300 * public domain by Tom St Denis. */
301
302/* the K array */
303static const unsigned long K[64] = {
304 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
305 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
306 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
307 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
308 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
309 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
310 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
311 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
312 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
313 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
314 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
315 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
316 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
317};
318
319/* Various logical functions */
320#define RORc(x, y) \
321(((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \
322((unsigned long)(x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
323#define Ch(x, y, z) (z ^ (x & (y ^ z)))
324#define Maj(x, y, z) (((x | y) & z) | (x & y))
325#define S(x, n) RORc((x), (n))
326#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
327#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
328#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
329#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
330#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
331#ifndef MIN
332#define MIN(x, y) (((x) < (y)) ? (x) : (y))
333#endif
334
335void rtw_secmicsetkey23a(struct mic_data *pmicdata, u8 *key);
336void rtw_secmicappend23abyte23a(struct mic_data *pmicdata, u8 b);
337void rtw_secmicappend23a(struct mic_data *pmicdata, u8 *src, u32 nbBytes);
338void rtw_secgetmic23a(struct mic_data *pmicdata, u8 *dst);
339
340void rtw_seccalctkipmic23a(u8 *key, u8 *header, u8 *data, u32 data_len,
341 u8 *Miccode, u8 priorityi);
342
343u32 rtw_aes_encrypt23a(struct rtw_adapter *padapter,
344 struct xmit_frame *pxmitframe);
345u32 rtw_tkip_encrypt23a(struct rtw_adapter *padapter,
346 struct xmit_frame *pxmitframe);
347void rtw_wep_encrypt23a(struct rtw_adapter *padapter,
348 struct xmit_frame *pxmitframe);
349u32 rtw_aes_decrypt23a(struct rtw_adapter *padapter,
350 struct recv_frame *precvframe);
351u32 rtw_tkip_decrypt23a(struct rtw_adapter *padapter,
352 struct recv_frame *precvframe);
353void rtw_wep_decrypt23a(struct rtw_adapter *padapter, struct recv_frame *precvframe);
354
355void rtw_use_tkipkey_handler23a(void *FunctionContext);
356
357#endif /* __RTL871X_SECURITY_H_ */
diff --git a/drivers/staging/rtl8723au/include/rtw_sreset.h b/drivers/staging/rtl8723au/include/rtw_sreset.h
new file mode 100644
index 000000000000..4c523722dd14
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_sreset.h
@@ -0,0 +1,56 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#ifndef _RTW_SRESET_C_
16#define _RTW_SRESET_C_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21enum {
22 SRESET_TGP_NULL = 0,
23 SRESET_TGP_XMIT_STATUS = 1,
24 SRESET_TGP_LINK_STATUS = 2,
25};
26
27struct sreset_priv {
28 struct mutex silentreset_mutex;
29 u8 silent_reset_inprogress;
30 u8 Wifi_Error_Status;
31 unsigned long last_tx_time;
32 unsigned long last_tx_complete_time;
33
34 s32 dbg_trigger_point;
35};
36
37#include <rtl8723a_hal.h>
38
39#define WIFI_STATUS_SUCCESS 0
40#define USB_VEN_REQ_CMD_FAIL BIT0
41#define USB_READ_PORT_FAIL BIT1
42#define USB_WRITE_PORT_FAIL BIT2
43#define WIFI_MAC_TXDMA_ERROR BIT3
44#define WIFI_TX_HANG BIT4
45#define WIFI_RX_HANG BIT5
46#define WIFI_IF_NOT_EXIST BIT6
47
48void sreset_init_value23a(struct rtw_adapter *padapter);
49void sreset_reset_value23a(struct rtw_adapter *padapter);
50u8 sreset_get_wifi_status23a(struct rtw_adapter *padapter);
51void sreset_set_wifi_error_status23a(struct rtw_adapter *padapter, u32 status);
52void sreset_set_trigger_point(struct rtw_adapter *padapter, s32 tgp);
53bool sreset_inprogress(struct rtw_adapter *padapter);
54void sreset_reset(struct rtw_adapter *padapter);
55
56#endif
diff --git a/drivers/staging/rtl8723au/include/rtw_version.h b/drivers/staging/rtl8723au/include/rtw_version.h
new file mode 100644
index 000000000000..c947733a3e3e
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_version.h
@@ -0,0 +1 @@
#define DRIVERVERSION "v4.1.6_7336.20130426"
diff --git a/drivers/staging/rtl8723au/include/rtw_xmit.h b/drivers/staging/rtl8723au/include/rtw_xmit.h
new file mode 100644
index 000000000000..65a33a07c8ee
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/rtw_xmit.h
@@ -0,0 +1,407 @@
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 ******************************************************************************/
15#ifndef _RTW_XMIT_H_
16#define _RTW_XMIT_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21#define MAX_XMITBUF_SZ 2048
22#define NR_XMITBUFF 4
23
24#define XMITBUF_ALIGN_SZ 512
25
26/* xmit extension buff defination */
27#define MAX_XMIT_EXTBUF_SZ 1536
28#define NR_XMIT_EXTBUFF 32
29
30#define MAX_NUMBLKS 1
31
32#define XMIT_VO_QUEUE 0
33#define XMIT_VI_QUEUE 1
34#define XMIT_BE_QUEUE 2
35#define XMIT_BK_QUEUE 3
36
37#define VO_QUEUE_INX 0
38#define VI_QUEUE_INX 1
39#define BE_QUEUE_INX 2
40#define BK_QUEUE_INX 3
41#define BCN_QUEUE_INX 4
42#define MGT_QUEUE_INX 5
43#define HIGH_QUEUE_INX 6
44#define TXCMD_QUEUE_INX 7
45
46#define HW_QUEUE_ENTRY 8
47
48#define WEP_IV(pattrib_iv, dot11txpn, keyidx) \
49do { \
50 pattrib_iv[0] = dot11txpn._byte_.TSC0; \
51 pattrib_iv[1] = dot11txpn._byte_.TSC1; \
52 pattrib_iv[2] = dot11txpn._byte_.TSC2; \
53 pattrib_iv[3] = ((keyidx & 0x3) << 6); \
54 dot11txpn.val = (dot11txpn.val == 0xffffff) ? 0 : \
55 (dot11txpn.val+1); \
56} while (0)
57
58#define TKIP_IV(pattrib_iv, dot11txpn, keyidx) \
59do { \
60 pattrib_iv[0] = dot11txpn._byte_.TSC1; \
61 pattrib_iv[1] = (dot11txpn._byte_.TSC1 | 0x20) & 0x7f; \
62 pattrib_iv[2] = dot11txpn._byte_.TSC0; \
63 pattrib_iv[3] = BIT(5) | ((keyidx & 0x3)<<6); \
64 pattrib_iv[4] = dot11txpn._byte_.TSC2; \
65 pattrib_iv[5] = dot11txpn._byte_.TSC3; \
66 pattrib_iv[6] = dot11txpn._byte_.TSC4; \
67 pattrib_iv[7] = dot11txpn._byte_.TSC5; \
68 dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : \
69 (dot11txpn.val+1); \
70} while (0)
71
72#define AES_IV(pattrib_iv, dot11txpn, keyidx)\
73do { \
74 pattrib_iv[0] = dot11txpn._byte_.TSC0; \
75 pattrib_iv[1] = dot11txpn._byte_.TSC1; \
76 pattrib_iv[2] = 0; \
77 pattrib_iv[3] = BIT(5) | ((keyidx & 0x3) << 6); \
78 pattrib_iv[4] = dot11txpn._byte_.TSC2; \
79 pattrib_iv[5] = dot11txpn._byte_.TSC3; \
80 pattrib_iv[6] = dot11txpn._byte_.TSC4; \
81 pattrib_iv[7] = dot11txpn._byte_.TSC5; \
82 dot11txpn.val = dot11txpn.val == 0xffffffffffffULL ? 0 : \
83 (dot11txpn.val+1); \
84} while (0)
85
86#define HWXMIT_ENTRY 4
87
88#define TXDESC_SIZE 32
89
90#define PACKET_OFFSET_SZ 8
91#define TXDESC_OFFSET (TXDESC_SIZE + PACKET_OFFSET_SZ)
92
93struct tx_desc {
94 /* DWORD 0 */
95 unsigned int txdw0;
96 unsigned int txdw1;
97 unsigned int txdw2;
98 unsigned int txdw3;
99 unsigned int txdw4;
100 unsigned int txdw5;
101 unsigned int txdw6;
102 unsigned int txdw7;
103};
104
105union txdesc {
106 struct tx_desc txdesc;
107 unsigned int value[TXDESC_SIZE>>2];
108};
109
110struct hw_xmit {
111 struct rtw_queue *sta_queue;
112 int accnt;
113};
114
115/* reduce size */
116struct pkt_attrib {
117 u8 type;
118 u8 subtype;
119 u8 bswenc;
120 u8 dhcp_pkt;
121 u16 ether_type;
122 u16 seqnum;
123 u16 pkt_hdrlen; /* the original 802.3 pkt header len */
124 u16 hdrlen; /* the WLAN Header Len */
125 u32 pktlen; /* the original 802.3 pkt raw_data len */
126 u32 last_txcmdsz;
127 u8 nr_frags;
128 u8 encrypt; /* when 0 indicate no encrypt. */
129 u8 iv_len;
130 u8 icv_len;
131 u8 iv[18];
132 u8 icv[16];
133 u8 priority;
134 u8 ack_policy;
135 u8 mac_id;
136 u8 vcs_mode; /* virtual carrier sense method */
137 u8 dst[ETH_ALEN];
138 u8 src[ETH_ALEN];
139 u8 ta[ETH_ALEN];
140 u8 ra[ETH_ALEN];
141 u8 key_idx;
142 u8 qos_en;
143 u8 ht_en;
144 u8 raid;/* rate adpative id */
145 u8 bwmode;
146 u8 ch_offset;/* PRIME_CHNL_OFFSET */
147 u8 sgi;/* short GI */
148 u8 ampdu_en;/* tx ampdu enable */
149 u8 mdata;/* more data bit */
150 u8 pctrl;/* per packet txdesc control enable */
151 u8 triggered;/* for ap mode handling Power Saving sta */
152 u8 qsel;
153 u8 eosp;
154 u8 rate;
155 u8 retry_ctrl;
156 struct sta_info *psta;
157};
158
159#define WLANHDR_OFFSET 64
160
161#define NULL_FRAMETAG 0x0
162#define DATA_FRAMETAG 0x01
163#define L2_FRAMETAG 0x02
164#define MGNT_FRAMETAG 0x03
165#define AMSDU_FRAMETAG 0x04
166
167#define EII_FRAMETAG 0x05
168#define IEEE8023_FRAMETAG 0x06
169
170#define MP_FRAMETAG 0x07
171
172#define TXAGG_FRAMETAG 0x08
173
174struct submit_ctx {
175 u32 timeout_ms; /* <0: not synchronous, 0: wait forever,
176 * >0: up to ms waiting
177 */
178 int status; /* status for operation */
179 struct completion done;
180};
181
182enum {
183 RTW_SCTX_SUBMITTED = -1,
184 RTW_SCTX_DONE_SUCCESS = 0,
185 RTW_SCTX_DONE_UNKNOWN,
186 RTW_SCTX_DONE_TIMEOUT,
187 RTW_SCTX_DONE_BUF_ALLOC,
188 RTW_SCTX_DONE_BUF_FREE,
189 RTW_SCTX_DONE_WRITE_PORT_ERR,
190 RTW_SCTX_DONE_TX_DESC_NA,
191 RTW_SCTX_DONE_TX_DENY,
192 RTW_SCTX_DONE_CCX_PKT_FAIL,
193 RTW_SCTX_DONE_DRV_STOP,
194 RTW_SCTX_DONE_DEV_REMOVE,
195};
196
197void rtw_sctx_init23a(struct submit_ctx *sctx, int timeout_ms);
198int rtw_sctx_wait23a(struct submit_ctx *sctx);
199void rtw23a_sctx_done_err(struct submit_ctx **sctx, int status);
200void rtw_sctx_done23a(struct submit_ctx **sctx);
201
202struct xmit_buf {
203 struct list_head list, list2;
204 struct rtw_adapter *padapter;
205
206 u8 *pallocated_buf;
207 u8 *pbuf;
208 void *priv_data;
209
210 u16 ext_tag; /* 0: Normal xmitbuf, 1: extension xmitbuf. */
211 u16 flags;
212 u32 alloc_sz;
213 u32 len;
214 struct submit_ctx *sctx;
215 u32 ff_hwaddr;
216 struct urb *pxmit_urb[8];
217 u8 bpending[8];
218 int last[8];
219#if defined(DBG_XMIT_BUF) || defined(DBG_XMIT_BUF_EXT)
220 u8 no;
221#endif
222};
223
224struct xmit_frame {
225 struct list_head list;
226 struct pkt_attrib attrib;
227 struct sk_buff *pkt;
228 int frame_tag;
229 struct rtw_adapter *padapter;
230 u8 *buf_addr;
231 struct xmit_buf *pxmitbuf;
232
233 s8 pkt_offset;
234
235 u8 ack_report;
236
237 u8 ext_tag; /* 0:data, 1:mgmt */
238};
239
240struct tx_servq {
241 struct list_head tx_pending;
242 struct rtw_queue sta_pending;
243 int qcnt;
244};
245
246struct sta_xmit_priv {
247 spinlock_t lock;
248 int option;
249 int apsd_setting; /* When bit mask is on, the associated edca
250 * queue supports APSD.
251 */
252 struct tx_servq be_q; /* priority == 0,3 */
253 struct tx_servq bk_q; /* priority == 1,2 */
254 struct tx_servq vi_q; /* priority == 4,5 */
255 struct tx_servq vo_q; /* priority == 6,7 */
256 struct list_head legacy_dz;
257 struct list_head apsd;
258 u16 txseq_tid[16];
259};
260
261struct hw_txqueue {
262 volatile int head;
263 volatile int tail;
264 volatile int free_sz; /* in units of 64 bytes */
265 volatile int free_cmdsz;
266 volatile int txsz[8];
267 uint ff_hwaddr;
268 uint cmd_hwaddr;
269 int ac_tag;
270};
271
272struct agg_pkt_info {
273 u16 offset;
274 u16 pkt_len;
275};
276
277struct xmit_priv {
278 spinlock_t lock;
279
280 struct semaphore xmit_sema;
281 struct semaphore terminate_xmitthread_sema;
282
283 struct rtw_queue be_pending;
284 struct rtw_queue bk_pending;
285 struct rtw_queue vi_pending;
286 struct rtw_queue vo_pending;
287 struct rtw_queue bm_pending;
288
289 u8 *pallocated_frame_buf;
290 u8 *pxmit_frame_buf;
291 uint free_xmitframe_cnt;
292 struct rtw_queue free_xmit_queue;
293
294 u8 *xframe_ext_alloc_addr;
295 u8 *xframe_ext;
296 uint free_xframe_ext_cnt;
297 struct rtw_queue free_xframe_ext_queue;
298
299 uint frag_len;
300
301 struct rtw_adapter *adapter;
302
303 u8 vcs_setting;
304 u8 vcs;
305 u8 vcs_type;
306
307 u64 tx_bytes;
308 u64 tx_pkts;
309 u64 tx_drop;
310 u64 last_tx_bytes;
311 u64 last_tx_pkts;
312
313 struct hw_xmit *hwxmits;
314 u8 hwxmit_entry;
315
316 u8 wmm_para_seq[4];/* sequence for wmm ac parameter strength from
317 * large to small. it's value is 0->vo, 1->vi,
318 * 2->be, 3->bk.
319 */
320
321 struct semaphore tx_retevt;/* all tx return event; */
322 u8 txirp_cnt;/* */
323
324 struct tasklet_struct xmit_tasklet;
325 /* per AC pending irp */
326 int beq_cnt;
327 int bkq_cnt;
328 int viq_cnt;
329 int voq_cnt;
330
331 struct rtw_queue free_xmitbuf_queue;
332 struct list_head xmitbuf_list; /* track buffers for cleanup */
333 struct rtw_queue pending_xmitbuf_queue;
334 uint free_xmitbuf_cnt;
335
336 struct rtw_queue free_xmit_extbuf_queue;
337 struct list_head xmitextbuf_list; /* track buffers for cleanup */
338 uint free_xmit_extbuf_cnt;
339
340 u16 nqos_ssn;
341 int ack_tx;
342 struct mutex ack_tx_mutex;
343 struct submit_ctx ack_tx_ops;
344 spinlock_t lock_sctx;
345};
346
347struct xmit_buf *rtw_alloc_xmitbuf23a_ext(struct xmit_priv *pxmitpriv);
348s32 rtw_free_xmitbuf_ext23a(struct xmit_priv *pxmitpriv,
349 struct xmit_buf *pxmitbuf);
350
351struct xmit_buf *rtw_alloc_xmitbuf23a(struct xmit_priv *pxmitpriv);
352s32 rtw_free_xmitbuf23a(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf);
353
354void rtw_count_tx_stats23a(struct rtw_adapter *padapter,
355 struct xmit_frame *pxmitframe, int sz);
356void rtw_update_protection23a(struct rtw_adapter *padapter, u8 *ie, uint ie_len);
357s32 rtw_make_wlanhdr23a(struct rtw_adapter *padapter, u8 *hdr,
358 struct pkt_attrib *pattrib);
359s32 rtw_put_snap23a(u8 *data, u16 h_proto);
360struct xmit_frame *rtw_alloc_xmitframe23a(struct xmit_priv *pxmitpriv);
361struct xmit_frame *rtw_alloc_xmitframe23a_ext(struct xmit_priv *pxmitpriv);
362struct xmit_frame *rtw_alloc_xmitframe23a_once(struct xmit_priv *pxmitpriv);
363s32 rtw_free_xmitframe23a(struct xmit_priv *pxmitpriv,
364 struct xmit_frame *pxmitframe);
365void rtw_free_xmitframe_queue23a(struct xmit_priv *pxmitpriv, struct rtw_queue *pframequeue);
366struct tx_servq *rtw_get_sta_pending23a(struct rtw_adapter *padapter,
367 struct sta_info *psta, int up, u8 *ac);
368s32 rtw_xmitframe_enqueue23a(struct rtw_adapter *padapter,
369 struct xmit_frame *pxmitframe);
370struct xmit_frame *rtw_dequeue_xframe23a(struct xmit_priv *pxmitpriv,
371 struct hw_xmit *phwxmit_i, int entry);
372s32 rtw_xmit23a_classifier(struct rtw_adapter *padapter,
373 struct xmit_frame *pxmitframe);
374u32 rtw_calculate_wlan_pkt_size_by_attribue23a(struct pkt_attrib *pattrib);
375#define rtw_wlan_pkt_size(f) rtw_calculate_wlan_pkt_size_by_attribue23a(&f->attrib)
376s32 rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *pkt,
377 struct xmit_frame *pxmitframe);
378s32 _rtw_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag);
379void _rtw_init_sta_xmit_priv23a(struct sta_xmit_priv *psta_xmitpriv);
380
381s32 rtw_txframes_pending23a(struct rtw_adapter *padapter);
382s32 rtw_txframes_sta_ac_pending23a(struct rtw_adapter *padapter,
383 struct pkt_attrib *pattrib);
384void rtw_init_hwxmits23a(struct hw_xmit *phwxmit, int entry);
385s32 _rtw_init_xmit_priv23a(struct xmit_priv *pxmitpriv,
386 struct rtw_adapter *padapter);
387void _rtw_free_xmit_priv23a(struct xmit_priv *pxmitpriv);
388void rtw_alloc_hwxmits23a(struct rtw_adapter *padapter);
389void rtw_free_hwxmits23a(struct rtw_adapter *padapter);
390int rtw_xmit23a(struct rtw_adapter *padapter, struct sk_buff *pkt);
391#if defined(CONFIG_8723AU_AP_MODE)
392int xmitframe_enqueue_for_sleeping_sta23a(struct rtw_adapter *padapter,
393 struct xmit_frame *pxmitframe);
394void stop_sta_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta);
395void wakeup_sta_to_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta);
396void xmit_delivery_enabled_frames23a(struct rtw_adapter *padapter,
397 struct sta_info *psta);
398#endif
399u8 qos_acm23a(u8 acm_mask, u8 priority);
400u32 rtw_get_ff_hwaddr23a(struct xmit_frame *pxmitframe);
401int rtw_ack_tx_wait23a(struct xmit_priv *pxmitpriv, u32 timeout_ms);
402void rtw_ack_tx_done23a(struct xmit_priv *pxmitpriv, int status);
403
404/* include after declaring struct xmit_buf, in order to avoid warning */
405#include <xmit_osdep.h>
406
407#endif /* _RTL871X_XMIT_H_ */
diff --git a/drivers/staging/rtl8723au/include/sta_info.h b/drivers/staging/rtl8723au/include/sta_info.h
new file mode 100644
index 000000000000..ffbc9e3f2156
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/sta_info.h
@@ -0,0 +1,385 @@
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 ******************************************************************************/
15#ifndef __STA_INFO_H_
16#define __STA_INFO_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20#include <wifi.h>
21
22#define IBSS_START_MAC_ID 2
23#define NUM_STA 32
24#define NUM_ACL 16
25
26
27/* if mode ==0, then the sta is allowed once the addr is hit. */
28/* if mode ==1, then the sta is rejected once the addr is non-hit. */
29struct rtw_wlan_acl_node {
30 struct list_head list;
31 u8 addr[ETH_ALEN];
32 u8 valid;
33};
34
35/* mode=0, disable */
36/* mode=1, accept unless in deny list */
37/* mode=2, deny unless in accept list */
38struct wlan_acl_pool {
39 int mode;
40 int num;
41 struct rtw_wlan_acl_node aclnode[NUM_ACL];
42 struct rtw_queue acl_node_q;
43};
44
45struct rssi_sta {
46 s32 UndecoratedSmoothedPWDB;
47 s32 UndecoratedSmoothedCCK;
48 s32 UndecoratedSmoothedOFDM;
49 u64 PacketMap;
50 u8 ValidBit;
51};
52
53struct stainfo_stats {
54 u64 rx_mgnt_pkts;
55 u64 rx_beacon_pkts;
56 u64 rx_probereq_pkts;
57 u64 rx_probersp_pkts;
58 u64 rx_probersp_bm_pkts;
59 u64 rx_probersp_uo_pkts;
60 u64 rx_ctrl_pkts;
61 u64 rx_data_pkts;
62
63 u64 last_rx_mgnt_pkts;
64 u64 last_rx_beacon_pkts;
65 u64 last_rx_probereq_pkts;
66 u64 last_rx_probersp_pkts;
67 u64 last_rx_probersp_bm_pkts;
68 u64 last_rx_probersp_uo_pkts;
69 u64 last_rx_ctrl_pkts;
70 u64 last_rx_data_pkts;
71
72 u64 rx_bytes;
73 u64 rx_drops;
74
75 u64 tx_pkts;
76 u64 tx_bytes;
77 u64 tx_drops;
78
79};
80
81struct sta_info {
82 spinlock_t lock;
83 struct list_head list; /* free_sta_queue */
84 struct list_head hash_list; /* sta_hash */
85 struct rtw_adapter *padapter;
86
87 struct sta_xmit_priv sta_xmitpriv;
88 struct sta_recv_priv sta_recvpriv;
89
90 struct rtw_queue sleep_q;
91 unsigned int sleepq_len;
92
93 uint state;
94 uint aid;
95 uint mac_id;
96 uint qos_option;
97 u8 hwaddr[ETH_ALEN];
98
99 uint ieee8021x_blocked; /* 0: allowed, 1:blocked */
100 uint dot118021XPrivacy; /* aes, tkip... */
101 union Keytype dot11tkiptxmickey;
102 union Keytype dot11tkiprxmickey;
103 union Keytype dot118021x_UncstKey;
104 union pn48 dot11txpn; /* PN48 used for Unicast xmit. */
105 union pn48 dot11rxpn; /* PN48 used for Unicast recv. */
106
107
108 u8 bssrateset[16];
109 u32 bssratelen;
110 s32 rssi;
111 s32 signal_quality;
112
113 u8 cts2self;
114 u8 rtsen;
115
116 u8 raid;
117 u8 init_rate;
118 u32 ra_mask;
119 u8 wireless_mode; /* NETWORK_TYPE */
120 struct stainfo_stats sta_stats;
121
122 /* for A-MPDU TX, ADDBA timeout check */
123 struct timer_list addba_retry_timer;
124
125 /* for A-MPDU Rx reordering buffer control */
126 struct recv_reorder_ctrl recvreorder_ctrl[16];
127
128 /* for A-MPDU Tx */
129 /* unsigned char ampdu_txen_bitmap; */
130 u16 BA_starting_seqctrl[16];
131
132 struct ht_priv htpriv;
133
134 /* Notes: */
135 /* STA_Mode: */
136 /* curr_network(mlme_priv/security_priv/qos/ht) + sta_info: (STA & AP) CAP/INFO */
137 /* scan_q: AP CAP/INFO */
138
139 /* AP_Mode: */
140 /* curr_network(mlme_priv/security_priv/qos/ht) : AP CAP/INFO */
141 /* sta_info: (AP & STA) CAP/INFO */
142
143 struct list_head asoc_list;
144 struct list_head auth_list;
145
146 unsigned int expire_to;
147 unsigned int auth_seq;
148 unsigned int authalg;
149 unsigned char chg_txt[128];
150
151 u16 capability;
152 int flags;
153
154 int dot8021xalg;/* 0:disable, 1:psk, 2:802.1x */
155 int wpa_psk;/* 0:disable, bit(0): WPA, bit(1):WPA2 */
156 int wpa_group_cipher;
157 int wpa2_group_cipher;
158 int wpa_pairwise_cipher;
159 int wpa2_pairwise_cipher;
160
161 u8 bpairwise_key_installed;
162
163 u8 wpa_ie[32];
164
165 u8 nonerp_set;
166 u8 no_short_slot_time_set;
167 u8 no_short_preamble_set;
168 u8 no_ht_gf_set;
169 u8 no_ht_set;
170 u8 ht_20mhz_set;
171
172 unsigned int tx_ra_bitmap;
173 u8 qos_info;
174
175 u8 max_sp_len;
176 u8 uapsd_bk;/* BIT(0): Delivery enabled, BIT(1): Trigger enabled */
177 u8 uapsd_be;
178 u8 uapsd_vi;
179 u8 uapsd_vo;
180
181 u8 has_legacy_ac;
182 unsigned int sleepq_ac_len;
183
184 /* p2p priv data */
185 u8 is_p2p_device;
186 u8 p2p_status_code;
187
188 u8 keep_alive_trycnt;
189
190 /* p2p client info */
191 u8 dev_addr[ETH_ALEN];
192 u8 dev_cap;
193 u16 config_methods;
194 u8 primary_dev_type[8];
195 u8 num_of_secdev_type;
196 u8 secdev_types_list[32];/* 32/8 == 4; */
197 u16 dev_name_len;
198 u8 dev_name[32];
199 u8 *passoc_req;
200 u32 assoc_req_len;
201
202 /* for DM */
203 struct rssi_sta rssi_stat;
204
205 /* */
206 /* ================ODM Relative Info======================= */
207 /* Please be care, dont declare too much structure here. It will cost memory * STA support num. */
208 /* */
209 /* */
210 /* 2011/10/20 MH Add for ODM STA info. */
211 /* */
212 /* Driver Write */
213 u8 bValid; /* record the sta status link or not? */
214 u8 IOTPeer; /* Enum value. HT_IOT_PEER_E */
215 u8 rssi_level; /* for Refresh RA mask */
216 /* ODM Write */
217 /* 1 PHY_STATUS_INFO */
218 u8 RSSI_Path[4]; /* */
219 u8 RSSI_Ave;
220 u8 RXEVM[4];
221 u8 RXSNR[4];
222
223 /* ODM Write */
224 /* 1 TX_INFO (may changed by IC) */
225 /* ================ODM Relative Info======================= */
226 /* */
227
228 /* To store the sequence number of received management frame */
229 u16 RxMgmtFrameSeqNum;
230};
231
232#define sta_rx_pkts(sta) \
233 (sta->sta_stats.rx_mgnt_pkts \
234 + sta->sta_stats.rx_ctrl_pkts \
235 + sta->sta_stats.rx_data_pkts)
236
237#define sta_last_rx_pkts(sta) \
238 (sta->sta_stats.last_rx_mgnt_pkts \
239 + sta->sta_stats.last_rx_ctrl_pkts \
240 + sta->sta_stats.last_rx_data_pkts)
241
242#define sta_rx_data_pkts(sta) \
243 (sta->sta_stats.rx_data_pkts)
244
245#define sta_last_rx_data_pkts(sta) \
246 (sta->sta_stats.last_rx_data_pkts)
247
248#define sta_rx_mgnt_pkts(sta) \
249 (sta->sta_stats.rx_mgnt_pkts)
250
251#define sta_last_rx_mgnt_pkts(sta) \
252 (sta->sta_stats.last_rx_mgnt_pkts)
253
254#define sta_rx_beacon_pkts(sta) \
255 (sta->sta_stats.rx_beacon_pkts)
256
257#define sta_last_rx_beacon_pkts(sta) \
258 (sta->sta_stats.last_rx_beacon_pkts)
259
260#define sta_rx_probereq_pkts(sta) \
261 (sta->sta_stats.rx_probereq_pkts)
262
263#define sta_last_rx_probereq_pkts(sta) \
264 (sta->sta_stats.last_rx_probereq_pkts)
265
266#define sta_rx_probersp_pkts(sta) \
267 (sta->sta_stats.rx_probersp_pkts)
268
269#define sta_last_rx_probersp_pkts(sta) \
270 (sta->sta_stats.last_rx_probersp_pkts)
271
272#define sta_rx_probersp_bm_pkts(sta) \
273 (sta->sta_stats.rx_probersp_bm_pkts)
274
275#define sta_last_rx_probersp_bm_pkts(sta) \
276 (sta->sta_stats.last_rx_probersp_bm_pkts)
277
278#define sta_rx_probersp_uo_pkts(sta) \
279 (sta->sta_stats.rx_probersp_uo_pkts)
280
281#define sta_last_rx_probersp_uo_pkts(sta) \
282 (sta->sta_stats.last_rx_probersp_uo_pkts)
283
284#define sta_update_last_rx_pkts(sta) \
285 do { \
286 sta->sta_stats.last_rx_mgnt_pkts = sta->sta_stats.rx_mgnt_pkts; \
287 sta->sta_stats.last_rx_beacon_pkts = sta->sta_stats.rx_beacon_pkts; \
288 sta->sta_stats.last_rx_probereq_pkts = sta->sta_stats.rx_probereq_pkts; \
289 sta->sta_stats.last_rx_probersp_pkts = sta->sta_stats.rx_probersp_pkts; \
290 sta->sta_stats.last_rx_probersp_bm_pkts = sta->sta_stats.rx_probersp_bm_pkts; \
291 sta->sta_stats.last_rx_probersp_uo_pkts = sta->sta_stats.rx_probersp_uo_pkts; \
292 sta->sta_stats.last_rx_ctrl_pkts = sta->sta_stats.rx_ctrl_pkts; \
293 sta->sta_stats.last_rx_data_pkts = sta->sta_stats.rx_data_pkts; \
294 } while (0)
295
296#define STA_RX_PKTS_ARG(sta) \
297 sta->sta_stats.rx_mgnt_pkts \
298 , sta->sta_stats.rx_ctrl_pkts \
299 , sta->sta_stats.rx_data_pkts
300
301#define STA_LAST_RX_PKTS_ARG(sta) \
302 sta->sta_stats.last_rx_mgnt_pkts, \
303 sta->sta_stats.last_rx_ctrl_pkts, \
304 sta->sta_stats.last_rx_data_pkts
305
306#define STA_RX_PKTS_DIFF_ARG(sta) \
307 sta->sta_stats.rx_mgnt_pkts - sta->sta_stats.last_rx_mgnt_pkts, \
308 sta->sta_stats.rx_ctrl_pkts - sta->sta_stats.last_rx_ctrl_pkts, \
309 sta->sta_stats.rx_data_pkts - sta->sta_stats.last_rx_data_pkts
310
311#define STA_PKTS_FMT "(m:%llu, c:%llu, d:%llu)"
312
313struct sta_priv {
314 u8 *pallocated_stainfo_buf;
315 u8 *pstainfo_buf;
316 struct rtw_queue free_sta_queue;
317
318 spinlock_t sta_hash_lock;
319 struct list_head sta_hash[NUM_STA];
320 int asoc_sta_count;
321 struct rtw_queue sleep_q;
322 struct rtw_queue wakeup_q;
323
324 struct rtw_adapter *padapter;
325 struct list_head asoc_list;
326 struct list_head auth_list;
327 spinlock_t asoc_list_lock;
328 spinlock_t auth_list_lock;
329 u8 asoc_list_cnt;
330 u8 auth_list_cnt;
331
332 unsigned int auth_to; /* sec, time to expire in authenticating. */
333 unsigned int assoc_to; /* sec, time to expire before associating. */
334 unsigned int expire_to; /* sec , time to expire after associated. */
335
336 /* pointers to STA info; based on allocated AID or NULL if AID free
337 * AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1
338 * and so on
339 */
340 struct sta_info *sta_aid[NUM_STA];
341
342 u16 sta_dz_bitmap;/* only support 15 stations, staion aid bitmap
343 * for sleeping sta. */
344 u16 tim_bitmap;/* only support 15 stations,
345 * aid=0~15 mapping bit0~bit15 */
346
347 u16 max_num_sta;
348
349 struct wlan_acl_pool acl_list;
350};
351
352static inline u32 wifi_mac_hash(u8 *mac)
353{
354 u32 x;
355
356 x = mac[0];
357 x = (x << 2) ^ mac[1];
358 x = (x << 2) ^ mac[2];
359 x = (x << 2) ^ mac[3];
360 x = (x << 2) ^ mac[4];
361 x = (x << 2) ^ mac[5];
362
363 x ^= x >> 8;
364 x = x & (NUM_STA - 1);
365
366 return x;
367}
368
369u32 _rtw_init_sta_priv23a(struct sta_priv *pstapriv);
370u32 _rtw_free_sta_priv23a(struct sta_priv *pstapriv);
371
372#define stainfo_offset_valid(offset) (offset < NUM_STA && offset >= 0)
373int rtw_stainfo_offset23a(struct sta_priv *stapriv, struct sta_info *sta);
374struct sta_info *rtw_get_stainfo23a_by_offset23a(struct sta_priv *stapriv,
375 int offset);
376
377struct sta_info *rtw_alloc_stainfo23a(struct sta_priv *pstapriv, u8 *hwaddr);
378u32 rtw_free_stainfo23a(struct rtw_adapter *padapter, struct sta_info *psta);
379void rtw_free_all_stainfo23a(struct rtw_adapter *padapter);
380struct sta_info *rtw_get_stainfo23a(struct sta_priv *pstapriv, u8 *hwaddr);
381u32 rtw_init_bcmc_stainfo23a(struct rtw_adapter *padapter);
382struct sta_info *rtw_get_bcmc_stainfo23a(struct rtw_adapter *padapter);
383u8 rtw_access_ctrl23a(struct rtw_adapter *padapter, u8 *mac_addr);
384
385#endif /* _STA_INFO_H_ */
diff --git a/drivers/staging/rtl8723au/include/usb_hal.h b/drivers/staging/rtl8723au/include/usb_hal.h
new file mode 100644
index 000000000000..4edec3b539b7
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/usb_hal.h
@@ -0,0 +1,20 @@
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 ******************************************************************************/
15#ifndef __USB_HAL_H__
16#define __USB_HAL_H__
17
18int rtl8723au_set_hal_ops(struct rtw_adapter *padapter);
19
20#endif /* __USB_HAL_H__ */
diff --git a/drivers/staging/rtl8723au/include/usb_ops.h b/drivers/staging/rtl8723au/include/usb_ops.h
new file mode 100644
index 000000000000..55d1380f9036
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/usb_ops.h
@@ -0,0 +1,97 @@
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 ******************************************************************************/
15#ifndef __USB_OPS_H_
16#define __USB_OPS_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20#include <osdep_intf.h>
21#include <usb_ops_linux.h>
22
23#define REALTEK_USB_VENQT_READ 0xC0
24#define REALTEK_USB_VENQT_WRITE 0x40
25#define REALTEK_USB_VENQT_CMD_REQ 0x05
26#define REALTEK_USB_VENQT_CMD_IDX 0x00
27
28enum {
29 VENDOR_WRITE = 0x00,
30 VENDOR_READ = 0x01,
31};
32
33#define ALIGNMENT_UNIT 16
34#define MAX_VENDOR_REQ_CMD_SIZE 254 /* 8188cu SIE Support */
35#define MAX_USB_IO_CTL_SIZE (MAX_VENDOR_REQ_CMD_SIZE +ALIGNMENT_UNIT)
36
37#define rtw_usb_control_msg(dev, pipe, request, requesttype, value, \
38 index, data, size, timeout_ms) \
39 usb_control_msg((dev), (pipe), (request), (requesttype), \
40 (value), (index), (data), (size), (timeout_ms))
41#define rtw_usb_bulk_msg(usb_dev, pipe, data, len, actual_length, timeout_ms) \
42 usb_bulk_msg((usb_dev), (pipe), (data), (len), (actual_length), \
43 (timeout_ms))
44
45void rtl8723au_set_hw_type(struct rtw_adapter *padapter);
46#define hal_set_hw_type rtl8723au_set_hw_type
47
48void rtl8723au_set_intf_ops(struct _io_ops *pops);
49#define usb_set_intf_ops rtl8723au_set_intf_ops
50
51void rtl8723au_recv_tasklet(void *priv);
52
53void rtl8723au_xmit_tasklet(void *priv);
54
55/* Increase and check if the continual_urb_error of this @param dvobjprive is
56 * larger than MAX_CONTINUAL_URB_ERR. Return result
57 */
58static inline int rtw_inc_and_chk_continual_urb_error(struct dvobj_priv *dvobj)
59{
60 int ret = false;
61 int value;
62
63 value = atomic_inc_return(&dvobj->continual_urb_error);
64 if (value > MAX_CONTINUAL_URB_ERR) {
65 DBG_8723A("[dvobj:%p][ERROR] continual_urb_error:%d > %d\n",
66 dvobj, value, MAX_CONTINUAL_URB_ERR);
67 ret = true;
68 }
69 return ret;
70}
71
72/* Set the continual_urb_error of this @param dvobjprive to 0 */
73static inline void rtw_reset_continual_urb_error(struct dvobj_priv *dvobj)
74{
75 atomic_set(&dvobj->continual_urb_error, 0);
76}
77
78#define USB_HIGH_SPEED_BULK_SIZE 512
79#define USB_FULL_SPEED_BULK_SIZE 64
80
81static inline u8 rtw_usb_bulk_size_boundary(struct rtw_adapter *padapter,
82 int buf_len)
83{
84 u8 rst = true;
85 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
86
87 if (pdvobjpriv->ishighspeed)
88 rst = (0 == (buf_len) % USB_HIGH_SPEED_BULK_SIZE) ?
89 true : false;
90 else
91 rst = (0 == (buf_len) % USB_FULL_SPEED_BULK_SIZE) ?
92 true : false;
93 return rst;
94}
95
96
97#endif /* __USB_OPS_H_ */
diff --git a/drivers/staging/rtl8723au/include/usb_ops_linux.h b/drivers/staging/rtl8723au/include/usb_ops_linux.h
new file mode 100644
index 000000000000..8f5c59eace5a
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/usb_ops_linux.h
@@ -0,0 +1,46 @@
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 ******************************************************************************/
15#ifndef __USB_OPS_LINUX_H__
16#define __USB_OPS_LINUX_H__
17
18#define VENDOR_CMD_MAX_DATA_LEN 254
19
20#define RTW_USB_CONTROL_MSG_TIMEOUT_TEST 10/* ms */
21#define RTW_USB_CONTROL_MSG_TIMEOUT 500/* ms */
22
23#define MAX_USBCTRL_VENDORREQ_TIMES 10
24
25#define RTW_USB_BULKOUT_TIMEOUT 5000/* ms */
26
27#define _usbctrl_vendorreq_async_callback(urb, regs) \
28 _usbctrl_vendorreq_async_callback(urb)
29#define usb_write_mem23a_complete(purb, regs) usb_write_mem23a_complete(purb)
30#define usb_write_port23a_complete(purb, regs) usb_write_port23a_complete(purb)
31#define usb_read_port_complete(purb, regs) usb_read_port_complete(purb)
32#define usb_read_interrupt_complete(purb, regs) \
33 usb_read_interrupt_complete(purb)
34
35unsigned int ffaddr2pipehdl23a(struct dvobj_priv *pdvobj, u32 addr);
36
37void usb_read_mem23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem);
38void usb_write_mem23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem);
39
40void usb_read_port_cancel23a(struct intf_hdl *pintfhdl);
41
42u32 usb_write_port23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
43 struct xmit_buf *wmem);
44void usb_write_port23a_cancel(struct intf_hdl *pintfhdl);
45
46#endif
diff --git a/drivers/staging/rtl8723au/include/usb_osintf.h b/drivers/staging/rtl8723au/include/usb_osintf.h
new file mode 100644
index 000000000000..46087662834e
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/usb_osintf.h
@@ -0,0 +1,24 @@
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 ******************************************************************************/
15#ifndef __USB_OSINTF_H
16#define __USB_OSINTF_H
17
18#include <osdep_service.h>
19#include <drv_types.h>
20#include <usb_vendor_req.h>
21
22#define USBD_HALTED(_status) ((u32)(_status) >> 30 == 3)
23
24#endif
diff --git a/drivers/staging/rtl8723au/include/usb_vendor_req.h b/drivers/staging/rtl8723au/include/usb_vendor_req.h
new file mode 100644
index 000000000000..eb4508ef191e
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/usb_vendor_req.h
@@ -0,0 +1,31 @@
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 ******************************************************************************/
15#ifndef _USB_VENDOR_REQUEST_H_
16#define _USB_VENDOR_REQUEST_H_
17
18/* 4 Set/Get Register related wIndex/Data */
19#define RT_USB_RESET_MASK_OFF 0
20#define RT_USB_RESET_MASK_ON 1
21#define RT_USB_SLEEP_MASK_OFF 0
22#define RT_USB_SLEEP_MASK_ON 1
23#define RT_USB_LDO_ON 1
24#define RT_USB_LDO_OFF 0
25
26/* 4 Set/Get SYSCLK related wValue or Data */
27#define RT_USB_SYSCLK_32KHZ 0
28#define RT_USB_SYSCLK_40MHZ 1
29#define RT_USB_SYSCLK_60MHZ 2
30
31#endif
diff --git a/drivers/staging/rtl8723au/include/wifi.h b/drivers/staging/rtl8723au/include/wifi.h
new file mode 100644
index 000000000000..b5034c6ef1dc
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/wifi.h
@@ -0,0 +1,707 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#ifndef _WIFI_H_
16#define _WIFI_H_
17
18#define P80211CAPTURE_VERSION 0x80211001
19
20/* This value is tested by WiFi 11n Test Plan 5.2.3.
21 * This test verifies the WLAN NIC can update the NAV through sending
22 * the CTS with large duration.
23 */
24#define WiFiNavUpperUs 30000 /* 30 ms */
25
26enum WIFI_FRAME_TYPE {
27 WIFI_MGT_TYPE = (0),
28 WIFI_CTRL_TYPE = (BIT(2)),
29 WIFI_DATA_TYPE = (BIT(3)),
30 WIFI_QOS_DATA_TYPE = (BIT(7)|BIT(3)), /* QoS Data */
31};
32
33enum WIFI_FRAME_SUBTYPE {
34 /* below is for mgt frame */
35 WIFI_ASSOCREQ = (0 | WIFI_MGT_TYPE),
36 WIFI_ASSOCRSP = (BIT(4) | WIFI_MGT_TYPE),
37 WIFI_REASSOCREQ = (BIT(5) | WIFI_MGT_TYPE),
38 WIFI_REASSOCRSP = (BIT(5) | BIT(4) | WIFI_MGT_TYPE),
39 WIFI_PROBEREQ = (BIT(6) | WIFI_MGT_TYPE),
40 WIFI_PROBERSP = (BIT(6) | BIT(4) | WIFI_MGT_TYPE),
41 WIFI_BEACON = (BIT(7) | WIFI_MGT_TYPE),
42 WIFI_ATIM = (BIT(7) | BIT(4) | WIFI_MGT_TYPE),
43 WIFI_DISASSOC = (BIT(7) | BIT(5) | WIFI_MGT_TYPE),
44 WIFI_AUTH = (BIT(7) | BIT(5) | BIT(4) | WIFI_MGT_TYPE),
45 WIFI_DEAUTH = (BIT(7) | BIT(6) | WIFI_MGT_TYPE),
46 WIFI_ACTION = (BIT(7) | BIT(6) | BIT(4) | WIFI_MGT_TYPE),
47
48 /* below is for control frame */
49 WIFI_PSPOLL = (BIT(7) | BIT(5) | WIFI_CTRL_TYPE),
50 WIFI_RTS = (BIT(7) | BIT(5) | BIT(4) | WIFI_CTRL_TYPE),
51 WIFI_CTS = (BIT(7) | BIT(6) | WIFI_CTRL_TYPE),
52 WIFI_ACK = (BIT(7) | BIT(6) | BIT(4) | WIFI_CTRL_TYPE),
53 WIFI_CFEND = (BIT(7) | BIT(6) | BIT(5) | WIFI_CTRL_TYPE),
54 WIFI_CFEND_CFACK = (BIT(7) | BIT(6) | BIT(5) | BIT(4) | WIFI_CTRL_TYPE),
55
56 /* below is for data frame */
57 WIFI_DATA = (0 | WIFI_DATA_TYPE),
58 WIFI_DATA_CFACK = (BIT(4) | WIFI_DATA_TYPE),
59 WIFI_DATA_CFPOLL = (BIT(5) | WIFI_DATA_TYPE),
60 WIFI_DATA_CFACKPOLL = (BIT(5) | BIT(4) | WIFI_DATA_TYPE),
61 WIFI_DATA_NULL = (BIT(6) | WIFI_DATA_TYPE),
62 WIFI_CF_ACK = (BIT(6) | BIT(4) | WIFI_DATA_TYPE),
63 WIFI_CF_POLL = (BIT(6) | BIT(5) | WIFI_DATA_TYPE),
64 WIFI_CF_ACKPOLL = (BIT(6) | BIT(5) | BIT(4) | WIFI_DATA_TYPE),
65 WIFI_QOS_DATA_NULL = (BIT(6) | WIFI_QOS_DATA_TYPE),
66};
67
68
69enum WIFI_REG_DOMAIN {
70 DOMAIN_FCC = 1,
71 DOMAIN_IC = 2,
72 DOMAIN_ETSI = 3,
73 DOMAIN_SPAIN = 4,
74 DOMAIN_FRANCE = 5,
75 DOMAIN_MKK = 6,
76 DOMAIN_ISRAEL = 7,
77 DOMAIN_MKK1 = 8,
78 DOMAIN_MKK2 = 9,
79 DOMAIN_MKK3 = 10,
80 DOMAIN_MAX
81};
82
83
84#define SetToDs(pbuf) \
85 (*(unsigned short *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_TODS))
86
87#define SetFrDs(pbuf) \
88 (*(unsigned short *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_FROMDS))
89
90#define get_tofr_ds(pframe) ((ieee80211_has_tods(pframe) << 1) | \
91 ieee80211_has_fromds(pframe))
92
93#define SetMFrag(pbuf) \
94 (*(unsigned short *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS))
95
96#define ClearMFrag(pbuf) \
97 (*(unsigned short *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)))
98
99#define SetRetry(pbuf) \
100 (*(unsigned short *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_RETRY))
101
102#define SetPwrMgt(pbuf) \
103 (*(unsigned short *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_PM))
104
105#define SetMData(pbuf) \
106 (*(unsigned short *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_MOREDATA))
107
108#define SetPrivacy(pbuf) \
109 (*(unsigned short *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_PROTECTED))
110
111#define SetFrameType(pbuf, type) \
112 do { \
113 *(unsigned short *)(pbuf) &= __constant_cpu_to_le16(~(BIT(3) | BIT(2))); \
114 *(unsigned short *)(pbuf) |= __constant_cpu_to_le16(type); \
115 } while (0)
116
117#define SetFrameSubType(pbuf, type) \
118 do { \
119 *(unsigned short *)(pbuf) &= cpu_to_le16(~(BIT(7) | BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2))); \
120 *(unsigned short *)(pbuf) |= cpu_to_le16(type); \
121 } while (0)
122
123#define GetTupleCache(pbuf) (cpu_to_le16(*(unsigned short *)((unsigned long)(pbuf) + 22)))
124
125#define SetFragNum(pbuf, num) \
126 do { \
127 *(unsigned short *)((unsigned long)(pbuf) + 22) = \
128 ((*(unsigned short *)((unsigned long)(pbuf) + 22)) & le16_to_cpu(~(0x000f))) | \
129 cpu_to_le16(0x0f & (num)); \
130 } while (0)
131
132#define SetSeqNum(pbuf, num) \
133 do { \
134 *(unsigned short *)((unsigned long)(pbuf) + 22) = \
135 ((*(unsigned short *)((unsigned long)(pbuf) + 22)) & le16_to_cpu((unsigned short)0x000f)) | \
136 le16_to_cpu((unsigned short)(0xfff0 & (num << 4))); \
137 } while (0)
138
139#define SetDuration(pbuf, dur) \
140 (*(unsigned short *)((unsigned long)(pbuf) + 2) = \
141 cpu_to_le16(0xffff & (dur)))
142
143#define SetPriority(pbuf, tid) \
144 (*(unsigned short *)(pbuf) |= cpu_to_le16(tid & 0xf))
145
146#define SetEOSP(pbuf, eosp) \
147 (*(unsigned short *)(pbuf) |= cpu_to_le16((eosp & 1) << 4))
148
149#define SetAckpolicy(pbuf, ack) \
150 (*(unsigned short *)(pbuf) |= cpu_to_le16((ack & 3) << 5))
151
152#define SetAMsdu(pbuf, amsdu) \
153 (*(unsigned short *)(pbuf) |= cpu_to_le16((amsdu & 1) << 7))
154
155#define GetAid(pbuf) \
156 (cpu_to_le16(*(unsigned short *)((unsigned long)(pbuf) + 2)) & \
157 0x3fff)
158
159#define GetTid(pbuf) \
160 (cpu_to_le16(*(unsigned short *)((unsigned long)(pbuf) + \
161 (((ieee80211_has_tods(pbuf)<<1) | \
162 ieee80211_has_fromds(pbuf)) == 3 ? 30 : 24))) & 0x000f)
163
164static inline unsigned char *get_hdr_bssid(unsigned char *pframe)
165{
166 unsigned char *sa;
167 unsigned int to_fr_ds;
168 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) pframe;
169
170 to_fr_ds = (ieee80211_has_tods(hdr->frame_control) << 1) |
171 ieee80211_has_fromds(hdr->frame_control);
172
173 switch (to_fr_ds) {
174 case 0x00: /* ToDs=0, FromDs=0 */
175 sa = hdr->addr3;
176 break;
177 case 0x01: /* ToDs=0, FromDs=1 */
178 sa = hdr->addr2;
179 break;
180 case 0x02: /* ToDs=1, FromDs=0 */
181 sa = hdr->addr1;
182 break;
183 case 0x03: /* ToDs=1, FromDs=1 */
184 sa = hdr->addr1;
185 break;
186 default:
187 sa = NULL; /* */
188 break;
189 }
190 return sa;
191}
192
193/*-----------------------------------------------------------------------------
194 Below is for the security related definition
195------------------------------------------------------------------------------*/
196#define _RESERVED_FRAME_TYPE_ 0
197#define _SKB_FRAME_TYPE_ 2
198#define _PRE_ALLOCMEM_ 1
199#define _PRE_ALLOCHDR_ 3
200#define _PRE_ALLOCLLCHDR_ 4
201#define _PRE_ALLOCICVHDR_ 5
202#define _PRE_ALLOCMICHDR_ 6
203
204#define _SIFSTIME_ \
205 ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) ? 16 : 10)
206#define _ACKCTSLNG_ 14 /* 14 bytes long, including crclng */
207#define _CRCLNG_ 4
208
209#define _ASOCREQ_IE_OFFSET_ 4 /* excluding wlan_hdr */
210#define _ASOCRSP_IE_OFFSET_ 6
211#define _REASOCREQ_IE_OFFSET_ 10
212#define _REASOCRSP_IE_OFFSET_ 6
213#define _PROBEREQ_IE_OFFSET_ 0
214#define _PROBERSP_IE_OFFSET_ 12
215#define _AUTH_IE_OFFSET_ 6
216#define _DEAUTH_IE_OFFSET_ 0
217#define _BEACON_IE_OFFSET_ 12
218#define _PUBLIC_ACTION_IE_OFFSET_ 8
219
220#define _FIXED_IE_LENGTH_ _BEACON_IE_OFFSET_
221
222#define _SSID_IE_ 0
223#define _SUPPORTEDRATES_IE_ 1
224#define _DSSET_IE_ 3
225#define _TIM_IE_ 5
226#define _IBSS_PARA_IE_ 6
227#define _COUNTRY_IE_ 7
228#define _CHLGETXT_IE_ 16
229#define _SUPPORTED_CH_IE_ 36
230#define _CH_SWTICH_ANNOUNCE_ 37 /* Secondary Channel Offset */
231#define _RSN_IE_2_ 48
232#define _SSN_IE_1_ 221
233#define _ERPINFO_IE_ 42
234#define _EXT_SUPPORTEDRATES_IE_ 50
235
236#define _HT_CAPABILITY_IE_ 45
237#define _FTIE_ 55
238#define _TIMEOUT_ITVL_IE_ 56
239#define _SRC_IE_ 59
240#define _HT_EXTRA_INFO_IE_ 61
241#define _HT_ADD_INFO_IE_ 61 /* _HT_EXTRA_INFO_IE_ */
242
243
244#define EID_BSSCoexistence 72 /* 20/40 BSS Coexistence */
245#define EID_BSSIntolerantChlReport 73
246#define _RIC_Descriptor_IE_ 75
247
248#define _LINK_ID_IE_ 101
249#define _CH_SWITCH_TIMING_ 104
250#define _PTI_BUFFER_STATUS_ 106
251#define _EXT_CAP_IE_ 127
252#define _VENDOR_SPECIFIC_IE_ 221
253
254#define _RESERVED47_ 47
255
256/* ---------------------------------------------------------------------------
257 Below is the fixed elements...
258-----------------------------------------------------------------------------*/
259#define _AUTH_ALGM_NUM_ 2
260#define _AUTH_SEQ_NUM_ 2
261#define _BEACON_ITERVAL_ 2
262#define _CAPABILITY_ 2
263#define _CURRENT_APADDR_ 6
264#define _LISTEN_INTERVAL_ 2
265#define _ASOC_ID_ 2
266#define _STATUS_CODE_ 2
267#define _TIMESTAMP_ 8
268
269#define AUTH_ODD_TO 0
270#define AUTH_EVEN_TO 1
271
272#define WLAN_ETHCONV_ENCAP 1
273#define WLAN_ETHCONV_RFC1042 2
274#define WLAN_ETHCONV_8021h 3
275
276#define cap_ESS BIT(0)
277#define cap_IBSS BIT(1)
278#define cap_CFPollable BIT(2)
279#define cap_CFRequest BIT(3)
280#define cap_Privacy BIT(4)
281#define cap_ShortPremble BIT(5)
282#define cap_PBCC BIT(6)
283#define cap_ChAgility BIT(7)
284#define cap_SpecMgmt BIT(8)
285#define cap_QoS BIT(9)
286#define cap_ShortSlot BIT(10)
287
288/*-----------------------------------------------------------------------------
289 Below is the definition for 802.11i / 802.1x
290------------------------------------------------------------------------------*/
291#define _IEEE8021X_MGT_ 1 /* WPA */
292#define _IEEE8021X_PSK_ 2 /* WPA with pre-shared key */
293
294/*
295#define _NO_PRIVACY_ 0
296#define _WEP_40_PRIVACY_ 1
297#define _TKIP_PRIVACY_ 2
298#define _WRAP_PRIVACY_ 3
299#define _CCMP_PRIVACY_ 4
300#define _WEP_104_PRIVACY_ 5
301#define _WEP_WPA_MIXED_PRIVACY_ 6 WEP + WPA
302*/
303
304/*-----------------------------------------------------------------------------
305 Below is the definition for WMM
306------------------------------------------------------------------------------*/
307#define _WMM_IE_Length_ 7 /* for WMM STA */
308#define _WMM_Para_Element_Length_ 24
309
310
311/*-----------------------------------------------------------------------------
312 Below is the definition for 802.11n
313------------------------------------------------------------------------------*/
314
315#define SetOrderBit(pbuf) \
316 (*(unsigned short *)(pbuf) |= cpu_to_le16(_ORDER_))
317
318#define GetOrderBit(pbuf) \
319 (((*(unsigned short *)(pbuf)) & le16_to_cpu(_ORDER_)) != 0)
320
321
322/* struct rtw_ieee80211_ht_cap - HT additional information
323 *
324 * This structure refers to "HT information element" as
325 * described in 802.11n draft section 7.3.2.53
326 */
327struct ieee80211_ht_addt_info {
328 unsigned char control_chan;
329 unsigned char ht_param;
330 unsigned short operation_mode;
331 unsigned short stbc_param;
332 unsigned char basic_set[16];
333} __packed;
334
335struct HT_caps_element {
336 union {
337 struct {
338 unsigned short HT_caps_info;
339 unsigned char AMPDU_para;
340 unsigned char MCS_rate[16];
341 unsigned short HT_ext_caps;
342 unsigned int Beamforming_caps;
343 unsigned char ASEL_caps;
344 } HT_cap_element;
345 unsigned char HT_cap[26];
346 } u;
347} __packed;
348
349struct HT_info_element {
350 unsigned char primary_channel;
351 unsigned char infos[5];
352 unsigned char MCS_rate[16];
353} __packed;
354
355struct AC_param {
356 unsigned char ACI_AIFSN;
357 unsigned char CW;
358 unsigned short TXOP_limit;
359} __packed;
360
361struct WMM_para_element {
362 unsigned char QoS_info;
363 unsigned char reserved;
364 struct AC_param ac_param[4];
365} __packed;
366
367struct ADDBA_request {
368 unsigned char dialog_token;
369 unsigned short BA_para_set;
370 unsigned short BA_timeout_value;
371 unsigned short BA_starting_seqctrl;
372} __packed;
373
374
375#define OP_MODE_PURE 0
376#define OP_MODE_MAY_BE_LEGACY_STAS 1
377#define OP_MODE_20MHZ_HT_STA_ASSOCED 2
378#define OP_MODE_MIXED 3
379
380#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8) BIT(0) | BIT(1))
381#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8) BIT(0))
382#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8) BIT(0) | BIT(1))
383#define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH ((u8) BIT(2))
384#define HT_INFO_HT_PARAM_RIFS_MODE ((u8) BIT(3))
385#define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY ((u8) BIT(4))
386#define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY ((u8) BIT(5))
387
388#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \
389 ((u16) (0x0001 | 0x0002))
390#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0
391#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8) BIT(2))
392#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3))
393#define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT ((u8) BIT(4))
394
395#define HT_INFO_STBC_PARAM_DUAL_BEACON ((u16) BIT(6))
396#define HT_INFO_STBC_PARAM_DUAL_STBC_PROTECT ((u16) BIT(7))
397#define HT_INFO_STBC_PARAM_SECONDARY_BCN ((u16) BIT(8))
398#define HT_INFO_STBC_PARAM_LSIG_TXOP_PROTECT_ALLOWED ((u16) BIT(9))
399#define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16) BIT(10))
400#define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11))
401
402
403
404/* ===============WPS Section=============== */
405/* For WPSv1.0 */
406#define WPSOUI 0x0050f204
407/* WPS attribute ID */
408#define WPS_ATTR_VER1 0x104A
409#define WPS_ATTR_SIMPLE_CONF_STATE 0x1044
410#define WPS_ATTR_RESP_TYPE 0x103B
411#define WPS_ATTR_UUID_E 0x1047
412#define WPS_ATTR_MANUFACTURER 0x1021
413#define WPS_ATTR_MODEL_NAME 0x1023
414#define WPS_ATTR_MODEL_NUMBER 0x1024
415#define WPS_ATTR_SERIAL_NUMBER 0x1042
416#define WPS_ATTR_PRIMARY_DEV_TYPE 0x1054
417#define WPS_ATTR_SEC_DEV_TYPE_LIST 0x1055
418#define WPS_ATTR_DEVICE_NAME 0x1011
419#define WPS_ATTR_CONF_METHOD 0x1008
420#define WPS_ATTR_RF_BANDS 0x103C
421#define WPS_ATTR_DEVICE_PWID 0x1012
422#define WPS_ATTR_REQUEST_TYPE 0x103A
423#define WPS_ATTR_ASSOCIATION_STATE 0x1002
424#define WPS_ATTR_CONFIG_ERROR 0x1009
425#define WPS_ATTR_VENDOR_EXT 0x1049
426#define WPS_ATTR_SELECTED_REGISTRAR 0x1041
427
428/* Value of WPS attribute "WPS_ATTR_DEVICE_NAME */
429#define WPS_MAX_DEVICE_NAME_LEN 32
430
431/* Value of WPS Request Type Attribute */
432#define WPS_REQ_TYPE_ENROLLEE_INFO_ONLY 0x00
433#define WPS_REQ_TYPE_ENROLLEE_OPEN_8021X 0x01
434#define WPS_REQ_TYPE_REGISTRAR 0x02
435#define WPS_REQ_TYPE_WLAN_MANAGER_REGISTRAR 0x03
436
437/* Value of WPS Response Type Attribute */
438#define WPS_RESPONSE_TYPE_INFO_ONLY 0x00
439#define WPS_RESPONSE_TYPE_8021X 0x01
440#define WPS_RESPONSE_TYPE_REGISTRAR 0x02
441#define WPS_RESPONSE_TYPE_AP 0x03
442
443/* Value of WPS WiFi Simple Configuration State Attribute */
444#define WPS_WSC_STATE_NOT_CONFIG 0x01
445#define WPS_WSC_STATE_CONFIG 0x02
446
447/* Value of WPS Version Attribute */
448#define WPS_VERSION_1 0x10
449
450/* Value of WPS Configuration Method Attribute */
451#define WPS_CONFIG_METHOD_FLASH 0x0001
452#define WPS_CONFIG_METHOD_ETHERNET 0x0002
453#define WPS_CONFIG_METHOD_LABEL 0x0004
454#define WPS_CONFIG_METHOD_DISPLAY 0x0008
455#define WPS_CONFIG_METHOD_E_NFC 0x0010
456#define WPS_CONFIG_METHOD_I_NFC 0x0020
457#define WPS_CONFIG_METHOD_NFC 0x0040
458#define WPS_CONFIG_METHOD_PBC 0x0080
459#define WPS_CONFIG_METHOD_KEYPAD 0x0100
460#define WPS_CONFIG_METHOD_VPBC 0x0280
461#define WPS_CONFIG_METHOD_PPBC 0x0480
462#define WPS_CONFIG_METHOD_VDISPLAY 0x2008
463#define WPS_CONFIG_METHOD_PDISPLAY 0x4008
464
465/* Value of Category ID of WPS Primary Device Type Attribute */
466#define WPS_PDT_CID_DISPLAYS 0x0007
467#define WPS_PDT_CID_MULIT_MEDIA 0x0008
468#define WPS_PDT_CID_RTK_WIDI WPS_PDT_CID_MULIT_MEDIA
469
470/* Value of Sub Category ID of WPS Primary Device Type Attribute */
471#define WPS_PDT_SCID_MEDIA_SERVER 0x0005
472#define WPS_PDT_SCID_RTK_DMP WPS_PDT_SCID_MEDIA_SERVER
473
474/* Value of Device Password ID */
475#define WPS_DPID_PIN 0x0000
476#define WPS_DPID_USER_SPEC 0x0001
477#define WPS_DPID_MACHINE_SPEC 0x0002
478#define WPS_DPID_REKEY 0x0003
479#define WPS_DPID_PBC 0x0004
480#define WPS_DPID_REGISTRAR_SPEC 0x0005
481
482/* Value of WPS RF Bands Attribute */
483#define WPS_RF_BANDS_2_4_GHZ 0x01
484#define WPS_RF_BANDS_5_GHZ 0x02
485
486/* Value of WPS Association State Attribute */
487#define WPS_ASSOC_STATE_NOT_ASSOCIATED 0x00
488#define WPS_ASSOC_STATE_CONNECTION_SUCCESS 0x01
489#define WPS_ASSOC_STATE_CONFIGURATION_FAILURE 0x02
490#define WPS_ASSOC_STATE_ASSOCIATION_FAILURE 0x03
491#define WPS_ASSOC_STATE_IP_FAILURE 0x04
492
493/* =====================P2P Section===================== */
494/* For P2P */
495#define P2POUI 0x506F9A09
496
497/* P2P Attribute ID */
498#define P2P_ATTR_STATUS 0x00
499#define P2P_ATTR_MINOR_REASON_CODE 0x01
500#define P2P_ATTR_CAPABILITY 0x02
501#define P2P_ATTR_DEVICE_ID 0x03
502#define P2P_ATTR_GO_INTENT 0x04
503#define P2P_ATTR_CONF_TIMEOUT 0x05
504#define P2P_ATTR_LISTEN_CH 0x06
505#define P2P_ATTR_GROUP_BSSID 0x07
506#define P2P_ATTR_EX_LISTEN_TIMING 0x08
507#define P2P_ATTR_INTENTED_IF_ADDR 0x09
508#define P2P_ATTR_MANAGEABILITY 0x0A
509#define P2P_ATTR_CH_LIST 0x0B
510#define P2P_ATTR_NOA 0x0C
511#define P2P_ATTR_DEVICE_INFO 0x0D
512#define P2P_ATTR_GROUP_INFO 0x0E
513#define P2P_ATTR_GROUP_ID 0x0F
514#define P2P_ATTR_INTERFACE 0x10
515#define P2P_ATTR_OPERATING_CH 0x11
516#define P2P_ATTR_INVITATION_FLAGS 0x12
517
518/* Value of Status Attribute */
519#define P2P_STATUS_SUCCESS 0x00
520#define P2P_STATUS_FAIL_INFO_UNAVAILABLE 0x01
521#define P2P_STATUS_FAIL_INCOMPATIBLE_PARAM 0x02
522#define P2P_STATUS_FAIL_LIMIT_REACHED 0x03
523#define P2P_STATUS_FAIL_INVALID_PARAM 0x04
524#define P2P_STATUS_FAIL_REQUEST_UNABLE 0x05
525#define P2P_STATUS_FAIL_PREVOUS_PROTO_ERR 0x06
526#define P2P_STATUS_FAIL_NO_COMMON_CH 0x07
527#define P2P_STATUS_FAIL_UNKNOWN_P2PGROUP 0x08
528#define P2P_STATUS_FAIL_BOTH_GOINTENT_15 0x09
529#define P2P_STATUS_FAIL_INCOMPATIBLE_PROVSION 0x0A
530#define P2P_STATUS_FAIL_USER_REJECT 0x0B
531
532/* Value of Inviation Flags Attribute */
533#define P2P_INVITATION_FLAGS_PERSISTENT BIT(0)
534
535#define DMP_P2P_DEVCAP_SUPPORT (P2P_DEVCAP_SERVICE_DISCOVERY | \
536 P2P_DEVCAP_CLIENT_DISCOVERABILITY | \
537 P2P_DEVCAP_CONCURRENT_OPERATION | \
538 P2P_DEVCAP_INVITATION_PROC)
539
540#define DMP_P2P_GRPCAP_SUPPORT (P2P_GRPCAP_INTRABSS)
541
542/* Value of Device Capability Bitmap */
543#define P2P_DEVCAP_SERVICE_DISCOVERY BIT(0)
544#define P2P_DEVCAP_CLIENT_DISCOVERABILITY BIT(1)
545#define P2P_DEVCAP_CONCURRENT_OPERATION BIT(2)
546#define P2P_DEVCAP_INFRA_MANAGED BIT(3)
547#define P2P_DEVCAP_DEVICE_LIMIT BIT(4)
548#define P2P_DEVCAP_INVITATION_PROC BIT(5)
549
550/* Value of Group Capability Bitmap */
551#define P2P_GRPCAP_GO BIT(0)
552#define P2P_GRPCAP_PERSISTENT_GROUP BIT(1)
553#define P2P_GRPCAP_GROUP_LIMIT BIT(2)
554#define P2P_GRPCAP_INTRABSS BIT(3)
555#define P2P_GRPCAP_CROSS_CONN BIT(4)
556#define P2P_GRPCAP_PERSISTENT_RECONN BIT(5)
557#define P2P_GRPCAP_GROUP_FORMATION BIT(6)
558
559/* P2P Public Action Frame ( Management Frame ) */
560#define P2P_PUB_ACTION_ACTION 0x09
561
562/* P2P Public Action Frame Type */
563#define P2P_GO_NEGO_REQ 0
564#define P2P_GO_NEGO_RESP 1
565#define P2P_GO_NEGO_CONF 2
566#define P2P_INVIT_REQ 3
567#define P2P_INVIT_RESP 4
568#define P2P_DEVDISC_REQ 5
569#define P2P_DEVDISC_RESP 6
570#define P2P_PROVISION_DISC_REQ 7
571#define P2P_PROVISION_DISC_RESP 8
572
573/* P2P Action Frame Type */
574#define P2P_NOTICE_OF_ABSENCE 0
575#define P2P_PRESENCE_REQUEST 1
576#define P2P_PRESENCE_RESPONSE 2
577#define P2P_GO_DISC_REQUEST 3
578
579
580#define P2P_MAX_PERSISTENT_GROUP_NUM 10
581
582#define P2P_PROVISIONING_SCAN_CNT 3
583
584#define P2P_WILDCARD_SSID_LEN 7
585
586#define P2P_FINDPHASE_EX_NONE 0 /* default value, used when: (1)p2p disabed or (2)p2p enabled but only do 1 scan phase */
587#define P2P_FINDPHASE_EX_FULL 1 /* used when p2p enabled and want to do 1 scan phase and P2P_FINDPHASE_EX_MAX-1 find phase */
588#define P2P_FINDPHASE_EX_SOCIAL_FIRST (P2P_FINDPHASE_EX_FULL+1)
589#define P2P_FINDPHASE_EX_MAX 4
590#define P2P_FINDPHASE_EX_SOCIAL_LAST P2P_FINDPHASE_EX_MAX
591
592#define P2P_PROVISION_TIMEOUT 5000 /*5 sec timeout for sending the provision discovery request */
593#define P2P_CONCURRENT_PROVISION_TIMEOUT 3000 /*3 sec timeout for sending the provision discovery request under concurrent mode */
594#define P2P_GO_NEGO_TIMEOUT 5000 /*5 sec timeout for receiving the group negotation response */
595#define P2P_CONCURRENT_GO_NEGO_TIMEOUT 3000 /*3 sec timeout for sending the negotiation request under concurrent mode */
596#define P2P_TX_PRESCAN_TIMEOUT 100 /*100ms */
597#define P2P_INVITE_TIMEOUT 5000 /*5 sec timeout for sending the invitation request */
598#define P2P_CONCURRENT_INVITE_TIMEOUT 3000 /*3 sec timeout for sending the invitation request under concurrent mode */
599#define P2P_RESET_SCAN_CH 25000 /*25 sec t/o to reset the scan channel ( based on channel plan ) */
600#define P2P_MAX_INTENT 15
601
602#define P2P_MAX_NOA_NUM 2
603
604/* WPS Configuration Method */
605#define WPS_CM_NONE 0x0000
606#define WPS_CM_LABEL 0x0004
607#define WPS_CM_DISPLYA 0x0008
608#define WPS_CM_EXTERNAL_NFC_TOKEN 0x0010
609#define WPS_CM_INTEGRATED_NFC_TOKEN 0x0020
610#define WPS_CM_NFC_INTERFACE 0x0040
611#define WPS_CM_PUSH_BUTTON 0x0080
612#define WPS_CM_KEYPAD 0x0100
613#define WPS_CM_SW_PUHS_BUTTON 0x0280
614#define WPS_CM_HW_PUHS_BUTTON 0x0480
615#define WPS_CM_SW_DISPLAY_PIN 0x2008
616#define WPS_CM_LCD_DISPLAY_PIN 0x4008
617
618enum P2P_ROLE {
619 P2P_ROLE_DISABLE = 0,
620 P2P_ROLE_DEVICE = 1,
621 P2P_ROLE_CLIENT = 2,
622 P2P_ROLE_GO = 3
623};
624
625enum P2P_STATE {
626 P2P_STATE_NONE = 0, /*P2P disable */
627 P2P_STATE_IDLE = 1, /*P2P had enabled and do nothing */
628 P2P_STATE_LISTEN = 2, /*In pure listen state */
629 P2P_STATE_SCAN = 3, /*In scan phase */
630 P2P_STATE_FIND_PHASE_LISTEN = 4, /*In the listen state of find phase */
631 P2P_STATE_FIND_PHASE_SEARCH = 5, /*In the search state of find phase */
632 P2P_STATE_TX_PROVISION_DIS_REQ = 6, /*In P2P provisioning discovery */
633 P2P_STATE_RX_PROVISION_DIS_RSP = 7,
634 P2P_STATE_RX_PROVISION_DIS_REQ = 8,
635 P2P_STATE_GONEGO_ING = 9, /*Doing the group owner negoitation handshake */
636 P2P_STATE_GONEGO_OK = 10, /*finish the group negoitation handshake with success */
637 P2P_STATE_GONEGO_FAIL = 11, /*finish the group negoitation handshake with failure */
638 P2P_STATE_RECV_INVITE_REQ_MATCH = 12, /*receiving the P2P Inviation request and match with the profile. */
639 P2P_STATE_PROVISIONING_ING = 13, /*Doing the P2P WPS */
640 P2P_STATE_PROVISIONING_DONE = 14, /*Finish the P2P WPS */
641 P2P_STATE_TX_INVITE_REQ = 15, /*Transmit the P2P Invitation request */
642 P2P_STATE_RX_INVITE_RESP_OK = 16, /*Receiving the P2P Invitation response */
643 P2P_STATE_RECV_INVITE_REQ_DISMATCH = 17,/*receiving the P2P Inviation request and dismatch with the profile. */
644 P2P_STATE_RECV_INVITE_REQ_GO = 18, /*receiving the P2P Inviation request and this wifi is GO. */
645 P2P_STATE_RECV_INVITE_REQ_JOIN = 19, /*receiving the P2P Inviation request to join an existing P2P Group. */
646 P2P_STATE_RX_INVITE_RESP_FAIL = 20, /*receiving the P2P Inviation response with failure */
647 P2P_STATE_RX_INFOR_NOREADY = 21, /*receiving p2p negotiation response with information is not available */
648 P2P_STATE_TX_INFOR_NOREADY = 22, /*sending p2p negotiation response with information is not available */
649};
650
651enum P2P_WPSINFO {
652 P2P_NO_WPSINFO = 0,
653 P2P_GOT_WPSINFO_PEER_DISPLAY_PIN = 1,
654 P2P_GOT_WPSINFO_SELF_DISPLAY_PIN = 2,
655 P2P_GOT_WPSINFO_PBC = 3,
656};
657
658#define P2P_PRIVATE_IOCTL_SET_LEN 64
659
660enum P2P_PROTO_WK_ID {
661 P2P_FIND_PHASE_WK = 0,
662 P2P_RESTORE_STATE_WK = 1,
663 P2P_PRE_TX_PROVDISC_PROCESS_WK = 2,
664 P2P_PRE_TX_NEGOREQ_PROCESS_WK = 3,
665 P2P_PRE_TX_INVITEREQ_PROCESS_WK = 4,
666 P2P_AP_P2P_CH_SWITCH_PROCESS_WK = 5,
667 P2P_RO_CH_WK = 6,
668};
669
670#ifdef CONFIG_8723AU_P2P
671enum P2P_PS_STATE {
672 P2P_PS_DISABLE = 0,
673 P2P_PS_ENABLE = 1,
674 P2P_PS_SCAN = 2,
675 P2P_PS_SCAN_DONE = 3,
676 P2P_PS_ALLSTASLEEP = 4, /* for P2P GO */
677};
678
679enum P2P_PS_MODE {
680 P2P_PS_NONE = 0,
681 P2P_PS_CTWINDOW = 1,
682 P2P_PS_NOA = 2,
683 P2P_PS_MIX = 3, /* CTWindow and NoA */
684};
685#endif /* CONFIG_8723AU_P2P */
686
687/* =====================WFD Section===================== */
688/* For Wi-Fi Display */
689#define WFD_ATTR_DEVICE_INFO 0x00
690#define WFD_ATTR_ASSOC_BSSID 0x01
691#define WFD_ATTR_COUPLED_SINK_INFO 0x06
692#define WFD_ATTR_LOCAL_IP_ADDR 0x08
693#define WFD_ATTR_SESSION_INFO 0x09
694#define WFD_ATTR_ALTER_MAC 0x0a
695
696/* For WFD Device Information Attribute */
697#define WFD_DEVINFO_SOURCE 0x0000
698#define WFD_DEVINFO_PSINK 0x0001
699#define WFD_DEVINFO_SSINK 0x0002
700#define WFD_DEVINFO_DUAL 0x0003
701
702#define WFD_DEVINFO_SESSION_AVAIL 0x0010
703#define WFD_DEVINFO_WSD 0x0040
704#define WFD_DEVINFO_PC_TDLS 0x0080
705#define WFD_DEVINFO_HDCP_SUPPORT 0x0100
706
707#endif /* _WIFI_H_ */
diff --git a/drivers/staging/rtl8723au/include/wlan_bssdef.h b/drivers/staging/rtl8723au/include/wlan_bssdef.h
new file mode 100644
index 000000000000..92287ebe5b9b
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/wlan_bssdef.h
@@ -0,0 +1,215 @@
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 ******************************************************************************/
15#ifndef __WLAN_BSSDEF_H__
16#define __WLAN_BSSDEF_H__
17
18
19#define MAX_IE_SZ 768
20
21
22#define NDIS_802_11_LENGTH_RATES 8
23#define NDIS_802_11_LENGTH_RATES_EX 16
24
25enum ndis_802_11_net_type {
26 Ndis802_11FH,
27 Ndis802_11DS,
28 Ndis802_11OFDM5,
29 Ndis802_11OFDM24,
30 Ndis802_11NetworkTypeMax /* just an upper bound */
31};
32
33struct ndis_802_11_configuration_fh {
34 u32 Length; /* Length of structure */
35 u32 HopPattern; /* As defined by 802.11, MSB set */
36 u32 HopSet; /* to one if non-802.11 */
37 u32 DwellTime; /* units are Kusec */
38};
39
40
41/*
42 FW will only save the channel number in DSConfig.
43 ODI Handler will convert the channel number to freq. number.
44*/
45struct ndis_802_11_config {
46 u32 Length; /* Length of structure */
47 u32 BeaconPeriod; /* units are Kusec */
48 u32 ATIMWindow; /* units are Kusec */
49 u32 DSConfig; /* Frequency, units are kHz */
50 struct ndis_802_11_configuration_fh FHConfig;
51};
52
53enum ndis_802_11_net_infra {
54 Ndis802_11IBSS,
55 Ndis802_11Infrastructure,
56 Ndis802_11AutoUnknown,
57 Ndis802_11InfrastructureMax, /* Not a real value, defined as upper bound */
58 Ndis802_11APMode
59};
60
61struct ndis_802_11_fixed_ies {
62 u8 Timestamp[8];
63 u16 BeaconInterval;
64 u16 Capabilities;
65};
66
67struct ndis_802_11_var_ies {
68 u8 ElementID;
69 u8 Length;
70 u8 data[1];
71};
72
73/* Length is the 4 bytes multiples of the sum of
74 * sizeof(6 * sizeof(unsigned char)) + 2 + sizeof(struct ndis_802_11_ssid) +
75 * sizeof(u32) + sizeof(long) + sizeof(enum ndis_802_11_net_type) +
76 * sizeof(struct ndis_802_11_config) + sizeof(sizeof(unsigned char) *
77 * NDIS_802_11_LENGTH_RATES_EX) + IELength
78 *
79 * Except the IELength, all other fields are fixed length. Therefore,
80 * we can define a macro to present the partial sum.
81 */
82
83enum ndis_802_11_auth_mode {
84 Ndis802_11AuthModeOpen,
85 Ndis802_11AuthModeShared,
86 Ndis802_11AuthModeAutoSwitch,
87 Ndis802_11AuthModeWPA,
88 Ndis802_11AuthModeWPAPSK,
89 Ndis802_11AuthModeWPANone,
90 dis802_11AuthModeMax /* upper bound */
91};
92
93enum {
94 Ndis802_11WEPEnabled,
95 Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
96 Ndis802_11WEPDisabled,
97 Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
98 Ndis802_11WEPKeyAbsent,
99 Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
100 Ndis802_11WEPNotSupported,
101 Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
102 Ndis802_11Encryption2Enabled,
103 Ndis802_11Encryption2KeyAbsent,
104 Ndis802_11Encryption3Enabled,
105 Ndis802_11Encryption3KeyAbsent,
106};
107
108/* Key mapping keys require a BSSID */
109struct ndis_802_11_key {
110 u32 Length; /* Length of this structure */
111 u32 KeyIndex;
112 u32 KeyLength; /* length of key in bytes */
113 unsigned char BSSID[6];
114 unsigned long long KeyRSC;
115 u8 KeyMaterial[32]; /* variable length depending on above field */
116};
117
118struct ndis_802_11_wep {
119 u32 Length; /* Length of this structure */
120 u32 KeyIndex; /* 0 is the per-client key, 1-N are global */
121 u32 KeyLength; /* length of key in bytes */
122 u8 KeyMaterial[16];/* variable length depending on above field */
123};
124
125enum NDIS_802_11_STATUS_TYPE {
126 Ndis802_11StatusType_Authentication,
127 Ndis802_11StatusType_MediaStreamMode,
128 Ndis802_11StatusType_PMKID_CandidateList,
129 Ndis802_11StatusTypeMax /* not a real type, just an upper bound */
130};
131
132/* mask for authentication/integrity fields */
133#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f
134#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01
135#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02
136#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06
137#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E
138
139/* MIC check time, 60 seconds. */
140#define MIC_CHECK_TIME 60000000
141
142#ifndef Ndis802_11APMode
143#define Ndis802_11APMode (Ndis802_11InfrastructureMax+1)
144#endif
145
146struct wlan_phy_info {
147 u8 SignalStrength;/* in percentage) */
148 u8 SignalQuality;/* in percentage) */
149 u8 Optimum_antenna; /* for Antenna diversity */
150 u8 Reserved_0;
151};
152
153struct wlan_bcn_info {
154 /* these infor get from rtw_get_encrypt_info when
155 * * translate scan to UI */
156 u8 encryp_protocol;/* ENCRYP_PROTOCOL_E: OPEN/WEP/WPA/WPA2 */
157 int group_cipher; /* WPA/WPA2 group cipher */
158 int pairwise_cipher;/* WPA/WPA2/WEP pairwise cipher */
159 int is_8021x;
160
161 /* bwmode 20/40 and ch_offset UP/LOW */
162 unsigned short ht_cap_info;
163 unsigned char ht_info_infos_0;
164};
165
166struct wlan_bssid_ex {
167 u32 Length;
168 u8 MacAddress[ETH_ALEN];
169 u16 reserved;
170 struct cfg80211_ssid Ssid;
171 u32 Privacy;
172 long Rssi;/* in dBM, raw data , get from PHY) */
173 enum ndis_802_11_net_type NetworkTypeInUse;
174 struct ndis_802_11_config Configuration;
175 enum ndis_802_11_net_infra InfrastructureMode;
176 unsigned char SupportedRates[NDIS_802_11_LENGTH_RATES_EX];
177 struct wlan_phy_info PhyInfo;
178 u32 IELength;
179 u8 IEs[MAX_IE_SZ]; /* timestamp, beacon interval, and capability info*/
180} __packed;
181
182static inline uint get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
183{
184 return sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + bss->IELength;
185}
186
187struct wlan_network {
188 struct list_head list;
189 int network_type; /* refer to ieee80211.h for 11A/B/G */
190 /* set to fixed when not to be removed as site-surveying */
191 int fixed;
192 unsigned long last_scanned; /* timestamp for the network */
193 int aid; /* will only be valid when a BSS is joined. */
194 int join_res;
195 struct wlan_bssid_ex network; /* must be the last item */
196 struct wlan_bcn_info BcnInfo;
197};
198
199enum VRTL_CARRIER_SENSE {
200 DISABLE_VCS,
201 ENABLE_VCS,
202 AUTO_VCS
203};
204
205enum VCS_TYPE {
206 NONE_VCS,
207 RTS_CTS,
208 CTS_TO_SELF
209};
210
211/* john */
212#define NUM_PRE_AUTH_KEY 16
213#define NUM_PMKID_CACHE NUM_PRE_AUTH_KEY
214
215#endif /* ifndef WLAN_BSSDEF_H_ */
diff --git a/drivers/staging/rtl8723au/include/xmit_osdep.h b/drivers/staging/rtl8723au/include/xmit_osdep.h
new file mode 100644
index 000000000000..0eca53ece75d
--- /dev/null
+++ b/drivers/staging/rtl8723au/include/xmit_osdep.h
@@ -0,0 +1,57 @@
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 ******************************************************************************/
15#ifndef __XMIT_OSDEP_H_
16#define __XMIT_OSDEP_H_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20
21struct pkt_file {
22 struct sk_buff *pkt;
23 __kernel_size_t pkt_len; /* the remainder length of the open_file */
24 unsigned char *cur_buffer;
25 u8 *buf_start;
26 u8 *cur_addr;
27 __kernel_size_t buf_len;
28};
29
30
31#define NR_XMITFRAME 256
32
33struct xmit_priv;
34struct pkt_attrib;
35struct sta_xmit_priv;
36struct xmit_frame;
37struct xmit_buf;
38
39int rtw_xmit23a_entry23a(struct sk_buff *pkt, struct net_device *pnetdev);
40
41void rtw_os_xmit_schedule23a(struct rtw_adapter *padapter);
42
43int rtw_os_xmit_resource_alloc23a(struct rtw_adapter *padapter,
44 struct xmit_buf *pxmitbuf, u32 alloc_sz);
45void rtw_os_xmit_resource_free23a(struct rtw_adapter *padapter,
46 struct xmit_buf *pxmitbuf);
47uint rtw_remainder_len23a(struct pkt_file *pfile);
48void _rtw_open_pktfile23a(struct sk_buff *pkt, struct pkt_file *pfile);
49uint _rtw_pktfile_read23a(struct pkt_file *pfile, u8 *rmem, uint rlen);
50int rtw_endofpktfile23a(struct pkt_file *pfile);
51
52void rtw_os_pkt_complete23a(struct rtw_adapter *padapter, struct sk_buff *pkt);
53void rtw_os_xmit_complete23a(struct rtw_adapter *padapter,
54 struct xmit_frame *pxframe);
55int netdev_open23a(struct net_device *pnetdev);
56
57#endif /* __XMIT_OSDEP_H_ */
diff --git a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
new file mode 100644
index 000000000000..50840b9a11fa
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
@@ -0,0 +1,4532 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _IOCTL_CFG80211_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <rtw_ioctl_set.h>
20#include <xmit_osdep.h>
21
22#include "ioctl_cfg80211.h"
23#include <linux/version.h>
24
25#define RTW_MAX_MGMT_TX_CNT 8
26
27#define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 65535 /* ms */
28#define RTW_MAX_NUM_PMKIDS 4
29
30#define RTW_CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */
31
32static const u32 rtw_cipher_suites[] = {
33 WLAN_CIPHER_SUITE_WEP40,
34 WLAN_CIPHER_SUITE_WEP104,
35 WLAN_CIPHER_SUITE_TKIP,
36 WLAN_CIPHER_SUITE_CCMP,
37};
38
39#define RATETAB_ENT(_rate, _rateid, _flags) { \
40 .bitrate = (_rate), \
41 .hw_value = (_rateid), \
42 .flags = (_flags), \
43}
44
45#define CHAN2G(_channel, _freq, _flags) { \
46 .band = IEEE80211_BAND_2GHZ, \
47 .center_freq = (_freq), \
48 .hw_value = (_channel), \
49 .flags = (_flags), \
50 .max_antenna_gain = 0, \
51 .max_power = 30, \
52}
53
54#define CHAN5G(_channel, _flags) { \
55 .band = IEEE80211_BAND_5GHZ, \
56 .center_freq = 5000 + (5 * (_channel)), \
57 .hw_value = (_channel), \
58 .flags = (_flags), \
59 .max_antenna_gain = 0, \
60 .max_power = 30, \
61}
62
63static struct ieee80211_rate rtw_rates[] = {
64 RATETAB_ENT(10, 0x1, 0),
65 RATETAB_ENT(20, 0x2, 0),
66 RATETAB_ENT(55, 0x4, 0),
67 RATETAB_ENT(110, 0x8, 0),
68 RATETAB_ENT(60, 0x10, 0),
69 RATETAB_ENT(90, 0x20, 0),
70 RATETAB_ENT(120, 0x40, 0),
71 RATETAB_ENT(180, 0x80, 0),
72 RATETAB_ENT(240, 0x100, 0),
73 RATETAB_ENT(360, 0x200, 0),
74 RATETAB_ENT(480, 0x400, 0),
75 RATETAB_ENT(540, 0x800, 0),
76};
77
78#define rtw_a_rates (rtw_rates + 4)
79#define RTW_A_RATES_NUM 8
80#define rtw_g_rates (rtw_rates + 0)
81#define RTW_G_RATES_NUM 12
82
83#define RTW_2G_CHANNELS_NUM 14
84#define RTW_5G_CHANNELS_NUM 37
85
86static struct ieee80211_channel rtw_2ghz_channels[] = {
87 CHAN2G(1, 2412, 0),
88 CHAN2G(2, 2417, 0),
89 CHAN2G(3, 2422, 0),
90 CHAN2G(4, 2427, 0),
91 CHAN2G(5, 2432, 0),
92 CHAN2G(6, 2437, 0),
93 CHAN2G(7, 2442, 0),
94 CHAN2G(8, 2447, 0),
95 CHAN2G(9, 2452, 0),
96 CHAN2G(10, 2457, 0),
97 CHAN2G(11, 2462, 0),
98 CHAN2G(12, 2467, 0),
99 CHAN2G(13, 2472, 0),
100 CHAN2G(14, 2484, 0),
101};
102
103static struct ieee80211_channel rtw_5ghz_a_channels[] = {
104 CHAN5G(34, 0), CHAN5G(36, 0),
105 CHAN5G(38, 0), CHAN5G(40, 0),
106 CHAN5G(42, 0), CHAN5G(44, 0),
107 CHAN5G(46, 0), CHAN5G(48, 0),
108 CHAN5G(52, 0), CHAN5G(56, 0),
109 CHAN5G(60, 0), CHAN5G(64, 0),
110 CHAN5G(100, 0), CHAN5G(104, 0),
111 CHAN5G(108, 0), CHAN5G(112, 0),
112 CHAN5G(116, 0), CHAN5G(120, 0),
113 CHAN5G(124, 0), CHAN5G(128, 0),
114 CHAN5G(132, 0), CHAN5G(136, 0),
115 CHAN5G(140, 0), CHAN5G(149, 0),
116 CHAN5G(153, 0), CHAN5G(157, 0),
117 CHAN5G(161, 0), CHAN5G(165, 0),
118 CHAN5G(184, 0), CHAN5G(188, 0),
119 CHAN5G(192, 0), CHAN5G(196, 0),
120 CHAN5G(200, 0), CHAN5G(204, 0),
121 CHAN5G(208, 0), CHAN5G(212, 0),
122 CHAN5G(216, 0),
123};
124
125static void rtw_2g_channels_init(struct ieee80211_channel *channels)
126{
127 memcpy((void *)channels, (void *)rtw_2ghz_channels,
128 sizeof(struct ieee80211_channel) * RTW_2G_CHANNELS_NUM);
129}
130
131static void rtw_5g_channels_init(struct ieee80211_channel *channels)
132{
133 memcpy((void *)channels, (void *)rtw_5ghz_a_channels,
134 sizeof(struct ieee80211_channel) * RTW_5G_CHANNELS_NUM);
135}
136
137static void rtw_2g_rates_init(struct ieee80211_rate *rates)
138{
139 memcpy(rates, rtw_g_rates,
140 sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM);
141}
142
143static void rtw_5g_rates_init(struct ieee80211_rate *rates)
144{
145 memcpy(rates, rtw_a_rates,
146 sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM);
147}
148
149static struct ieee80211_supported_band *
150rtw_spt_band_alloc(enum ieee80211_band band)
151{
152 struct ieee80211_supported_band *spt_band = NULL;
153 int n_channels, n_bitrates;
154
155 if (band == IEEE80211_BAND_2GHZ) {
156 n_channels = RTW_2G_CHANNELS_NUM;
157 n_bitrates = RTW_G_RATES_NUM;
158 } else if (band == IEEE80211_BAND_5GHZ) {
159 n_channels = RTW_5G_CHANNELS_NUM;
160 n_bitrates = RTW_A_RATES_NUM;
161 } else {
162 goto exit;
163 }
164 spt_band = kzalloc(sizeof(struct ieee80211_supported_band) +
165 sizeof(struct ieee80211_channel) * n_channels +
166 sizeof(struct ieee80211_rate) * n_bitrates,
167 GFP_KERNEL);
168 if (!spt_band)
169 goto exit;
170
171 spt_band->channels =
172 (struct ieee80211_channel *)(((u8 *) spt_band) +
173 sizeof(struct
174 ieee80211_supported_band));
175 spt_band->bitrates =
176 (struct ieee80211_rate *)(((u8 *) spt_band->channels) +
177 sizeof(struct ieee80211_channel) *
178 n_channels);
179 spt_band->band = band;
180 spt_band->n_channels = n_channels;
181 spt_band->n_bitrates = n_bitrates;
182
183 if (band == IEEE80211_BAND_2GHZ) {
184 rtw_2g_channels_init(spt_band->channels);
185 rtw_2g_rates_init(spt_band->bitrates);
186 } else if (band == IEEE80211_BAND_5GHZ) {
187 rtw_5g_channels_init(spt_band->channels);
188 rtw_5g_rates_init(spt_band->bitrates);
189 }
190
191 /* spt_band.ht_cap */
192
193exit:
194 return spt_band;
195}
196
197static const struct ieee80211_txrx_stypes
198rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
199 [NL80211_IFTYPE_ADHOC] = {
200 .tx = 0xffff,
201 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
202 },
203 [NL80211_IFTYPE_STATION] = {
204 .tx = 0xffff,
205 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
206 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
207 },
208 [NL80211_IFTYPE_AP] = {
209 .tx = 0xffff,
210 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
211 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
212 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
213 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
214 BIT(IEEE80211_STYPE_AUTH >> 4) |
215 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
216 BIT(IEEE80211_STYPE_ACTION >> 4)
217 },
218 [NL80211_IFTYPE_AP_VLAN] = {
219 /* copy AP */
220 .tx = 0xffff,
221 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
222 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
223 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
224 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
225 BIT(IEEE80211_STYPE_AUTH >> 4) |
226 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
227 BIT(IEEE80211_STYPE_ACTION >> 4)
228 },
229 [NL80211_IFTYPE_P2P_CLIENT] = {
230 .tx = 0xffff,
231 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
232 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
233 },
234 [NL80211_IFTYPE_P2P_GO] = {
235 .tx = 0xffff,
236 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
237 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
238 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
239 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
240 BIT(IEEE80211_STYPE_AUTH >> 4) |
241 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
242 BIT(IEEE80211_STYPE_ACTION >> 4)
243 },
244};
245
246#define MAX_BSSINFO_LEN 1000
247static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter,
248 struct wlan_network *pnetwork)
249{
250 int ret = 0;
251 struct ieee80211_channel *notify_channel;
252 struct cfg80211_bss *bss;
253 /* struct ieee80211_supported_band *band; */
254 u16 channel;
255 u32 freq;
256 u64 notify_timestamp;
257 u16 notify_capability;
258 u16 notify_interval;
259 u8 *notify_ie;
260 size_t notify_ielen;
261 s32 notify_signal;
262 u8 buf[MAX_BSSINFO_LEN], *pbuf;
263 size_t len, bssinf_len = 0;
264 struct ieee80211_hdr *pwlanhdr;
265 unsigned short *fctrl;
266 u8 bc_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
267
268 struct wireless_dev *wdev = padapter->rtw_wdev;
269 struct wiphy *wiphy = wdev->wiphy;
270 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
271
272 /* DBG_8723A("%s\n", __func__); */
273
274 bssinf_len =
275 pnetwork->network.IELength + sizeof(struct ieee80211_hdr_3addr);
276 if (bssinf_len > MAX_BSSINFO_LEN) {
277 DBG_8723A("%s IE Length too long > %d byte\n", __func__,
278 MAX_BSSINFO_LEN);
279 goto exit;
280 }
281
282 channel = pnetwork->network.Configuration.DSConfig;
283 if (channel <= RTW_CH_MAX_2G_CHANNEL)
284 freq = ieee80211_channel_to_frequency(channel,
285 IEEE80211_BAND_2GHZ);
286 else
287 freq = ieee80211_channel_to_frequency(channel,
288 IEEE80211_BAND_5GHZ);
289
290 notify_channel = ieee80211_get_channel(wiphy, freq);
291
292 /* rtw_get_timestampe_from_ie23a() */
293 notify_timestamp = jiffies_to_msecs(jiffies) * 1000; /* uSec */
294
295 notify_interval =
296 le16_to_cpu(*(u16 *)
297 rtw_get_beacon_interval23a_from_ie(pnetwork->network.IEs));
298 notify_capability =
299 le16_to_cpu(*(u16 *)
300 rtw_get_capability23a_from_ie(pnetwork->network.IEs));
301
302 notify_ie = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
303 notify_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
304
305 /* We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM:
306 * signal strength in mBm (100*dBm)
307 */
308 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
309 is_same_network23a(&pmlmepriv->cur_network.network,
310 &pnetwork->network)) {
311 notify_signal = 100 * translate_percentage_to_dbm(padapter->recvpriv.signal_strength); /* dbm */
312 } else {
313 notify_signal = 100 * translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength); /* dbm */
314 }
315 pbuf = buf;
316
317 pwlanhdr = (struct ieee80211_hdr *)pbuf;
318 fctrl = &pwlanhdr->frame_control;
319 *(fctrl) = 0;
320
321 SetSeqNum(pwlanhdr, 0);
322
323 if (pnetwork->network.reserved == 1) { /* WIFI_BEACON */
324 memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
325 SetFrameSubType(pbuf, WIFI_BEACON);
326 } else {
327 memcpy(pwlanhdr->addr1, myid(&padapter->eeprompriv), ETH_ALEN);
328 SetFrameSubType(pbuf, WIFI_PROBERSP);
329 }
330
331 memcpy(pwlanhdr->addr2, pnetwork->network.MacAddress, ETH_ALEN);
332 memcpy(pwlanhdr->addr3, pnetwork->network.MacAddress, ETH_ALEN);
333
334 pbuf += sizeof(struct ieee80211_hdr_3addr);
335 len = sizeof(struct ieee80211_hdr_3addr);
336
337 memcpy(pbuf, pnetwork->network.IEs, pnetwork->network.IELength);
338 len += pnetwork->network.IELength;
339
340 bss = cfg80211_inform_bss_frame(wiphy, notify_channel,
341 (struct ieee80211_mgmt *)buf, len,
342 notify_signal, GFP_ATOMIC);
343
344 if (unlikely(!bss)) {
345 DBG_8723A("rtw_cfg80211_inform_bss error\n");
346 return -EINVAL;
347 }
348
349 cfg80211_put_bss(wiphy, bss);
350
351exit:
352 return ret;
353}
354
355void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter)
356{
357 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
358 struct wlan_network *cur_network = &pmlmepriv->cur_network;
359 struct wireless_dev *pwdev = padapter->rtw_wdev;
360#ifdef CONFIG_8723AU_P2P
361 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
362#endif
363
364 DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
365
366 if (pwdev->iftype != NL80211_IFTYPE_STATION &&
367 pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
368 return;
369
370 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
371 return;
372
373#ifdef CONFIG_8723AU_P2P
374 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
375 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
376 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
377 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
378 DBG_8723A("%s, role =%d, p2p_state =%d, pre_p2p_state =%d\n",
379 __func__, rtw_p2p_role(pwdinfo),
380 rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));
381 }
382#endif /* CONFIG_8723AU_P2P */
383
384 if (rtw_to_roaming(padapter) > 0) {
385 struct wiphy *wiphy = pwdev->wiphy;
386 struct ieee80211_channel *notify_channel;
387 u32 freq;
388 u16 channel = cur_network->network.Configuration.DSConfig;
389
390 if (channel <= RTW_CH_MAX_2G_CHANNEL)
391 freq =
392 ieee80211_channel_to_frequency(channel,
393 IEEE80211_BAND_2GHZ);
394 else
395 freq =
396 ieee80211_channel_to_frequency(channel,
397 IEEE80211_BAND_5GHZ);
398
399 notify_channel = ieee80211_get_channel(wiphy, freq);
400
401 DBG_8723A("%s call cfg80211_roamed\n", __func__);
402 cfg80211_roamed(padapter->pnetdev, notify_channel,
403 cur_network->network.MacAddress,
404 pmlmepriv->assoc_req +
405 sizeof(struct ieee80211_hdr_3addr) + 2,
406 pmlmepriv->assoc_req_len -
407 sizeof(struct ieee80211_hdr_3addr) - 2,
408 pmlmepriv->assoc_rsp +
409 sizeof(struct ieee80211_hdr_3addr) + 6,
410 pmlmepriv->assoc_rsp_len -
411 sizeof(struct ieee80211_hdr_3addr) - 6,
412 GFP_ATOMIC);
413 } else {
414 cfg80211_connect_result(padapter->pnetdev,
415 cur_network->network.MacAddress,
416 pmlmepriv->assoc_req +
417 sizeof(struct ieee80211_hdr_3addr) + 2,
418 pmlmepriv->assoc_req_len -
419 sizeof(struct ieee80211_hdr_3addr) - 2,
420 pmlmepriv->assoc_rsp +
421 sizeof(struct ieee80211_hdr_3addr) + 6,
422 pmlmepriv->assoc_rsp_len -
423 sizeof(struct ieee80211_hdr_3addr) - 6,
424 WLAN_STATUS_SUCCESS, GFP_ATOMIC);
425 }
426}
427
428void rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter)
429{
430 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
431 struct wireless_dev *pwdev = padapter->rtw_wdev;
432#ifdef CONFIG_8723AU_P2P
433 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
434#endif
435
436 DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
437
438 if (pwdev->iftype != NL80211_IFTYPE_STATION &&
439 pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
440 return;
441
442 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
443 return;
444
445#ifdef CONFIG_8723AU_P2P
446 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
447 del_timer_sync(&pwdinfo->find_phase_timer);
448 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
449 del_timer_sync(&pwdinfo->pre_tx_scan_timer);
450
451 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
452 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
453
454 DBG_8723A("%s, role =%d, p2p_state =%d, pre_p2p_state =%d\n",
455 __func__, rtw_p2p_role(pwdinfo),
456 rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));
457 }
458#endif /* CONFIG_8723AU_P2P */
459
460 if (!padapter->mlmepriv.not_indic_disco) {
461 if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING)) {
462 cfg80211_connect_result(padapter->pnetdev, NULL, NULL,
463 0, NULL, 0,
464 WLAN_STATUS_UNSPECIFIED_FAILURE,
465 GFP_ATOMIC);
466 } else {
467 cfg80211_disconnected(padapter->pnetdev, 0, NULL,
468 0, GFP_ATOMIC);
469 }
470 }
471}
472
473#ifdef CONFIG_8723AU_AP_MODE
474static u8 set_pairwise_key(struct rtw_adapter *padapter, struct sta_info *psta)
475{
476 struct cmd_obj *ph2c;
477 struct set_stakey_parm *psetstakey_para;
478 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
479 u8 res = _SUCCESS;
480
481 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
482 if (ph2c == NULL) {
483 res = _FAIL;
484 goto exit;
485 }
486
487 psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
488 if (psetstakey_para == NULL) {
489 kfree(ph2c);
490 res = _FAIL;
491 goto exit;
492 }
493
494 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
495
496 psetstakey_para->algorithm = (u8) psta->dot118021XPrivacy;
497
498 memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
499
500 memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
501
502 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
503
504exit:
505 return res;
506}
507
508static int set_group_key(struct rtw_adapter *padapter, u8 *key, u8 alg,
509 int keyid)
510{
511 u8 keylen;
512 struct cmd_obj *pcmd;
513 struct setkey_parm *psetkeyparm;
514 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
515 int res = _SUCCESS;
516
517 DBG_8723A("%s\n", __func__);
518
519 pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
520 if (!pcmd) {
521 res = _FAIL;
522 goto exit;
523 }
524 psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
525 if (!psetkeyparm) {
526 kfree(pcmd);
527 res = _FAIL;
528 goto exit;
529 }
530
531 psetkeyparm->keyid = (u8) keyid;
532 if (is_wep_enc(alg))
533 padapter->mlmepriv.key_mask |= CHKBIT(psetkeyparm->keyid);
534
535 psetkeyparm->algorithm = alg;
536
537 psetkeyparm->set_tx = 1;
538
539 switch (alg) {
540 case _WEP40_:
541 keylen = 5;
542 break;
543 case _WEP104_:
544 keylen = 13;
545 break;
546 case _TKIP_:
547 case _TKIP_WTMIC_:
548 case _AES_:
549 default:
550 keylen = 16;
551 }
552
553 memcpy(&psetkeyparm->key[0], key, keylen);
554
555 pcmd->cmdcode = _SetKey_CMD_;
556 pcmd->parmbuf = (u8 *) psetkeyparm;
557 pcmd->cmdsz = (sizeof(struct setkey_parm));
558 pcmd->rsp = NULL;
559 pcmd->rspsz = 0;
560
561 INIT_LIST_HEAD(&pcmd->list);
562
563 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
564
565exit:
566 return res;
567}
568
569static int set_wep_key(struct rtw_adapter *padapter, u8 *key, u8 keylen,
570 int keyid)
571{
572 u8 alg;
573
574 switch (keylen) {
575 case 5:
576 alg = _WEP40_;
577 break;
578 case 13:
579 alg = _WEP104_;
580 break;
581 default:
582 alg = _NO_PRIVACY_;
583 }
584
585 return set_group_key(padapter, key, alg, keyid);
586}
587
588static int rtw_cfg80211_ap_set_encryption(struct net_device *dev,
589 struct ieee_param *param,
590 u32 param_len)
591{
592 int ret = 0;
593 u32 wep_key_idx, wep_key_len;
594 struct sta_info *psta = NULL, *pbcmc_sta = NULL;
595 struct rtw_adapter *padapter = netdev_priv(dev);
596 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
597 struct security_priv *psecuritypriv = &padapter->securitypriv;
598 struct sta_priv *pstapriv = &padapter->stapriv;
599
600 DBG_8723A("%s\n", __func__);
601
602 param->u.crypt.err = 0;
603 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
604
605 /* sizeof(struct ieee_param) = 64 bytes; */
606 /* if (param_len != (u32) ((u8 *) param->u.crypt.key -
607 (u8 *) param) + param->u.crypt.key_len) */
608 if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len) {
609 ret = -EINVAL;
610 goto exit;
611 }
612
613 if (is_broadcast_ether_addr(param->sta_addr)) {
614 if (param->u.crypt.idx >= WEP_KEYS) {
615 ret = -EINVAL;
616 goto exit;
617 }
618 } else {
619 psta = rtw_get_stainfo23a(pstapriv, param->sta_addr);
620 if (!psta) {
621 /* ret = -EINVAL; */
622 DBG_8723A("rtw_set_encryption(), sta has already "
623 "been removed or never been added\n");
624 goto exit;
625 }
626 }
627
628 if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
629 /* todo:clear default encryption keys */
630
631 DBG_8723A("clear default encryption keys, keyid =%d\n",
632 param->u.crypt.idx);
633
634 goto exit;
635 }
636
637 if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
638 DBG_8723A("r871x_set_encryption, crypt.alg = WEP\n");
639
640 wep_key_idx = param->u.crypt.idx;
641 wep_key_len = param->u.crypt.key_len;
642
643 DBG_8723A("r871x_set_encryption, wep_key_idx =%d, len =%d\n",
644 wep_key_idx, wep_key_len);
645
646 if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
647 ret = -EINVAL;
648 goto exit;
649 }
650
651 if (wep_key_len > 0) {
652 wep_key_len = wep_key_len <= 5 ? 5 : 13;
653 }
654
655 if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
656 /* wep default key has not been set, so use
657 this key index as default key. */
658
659 psecuritypriv->ndisencryptstatus =
660 Ndis802_11Encryption1Enabled;
661 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
662 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
663
664 if (wep_key_len == 13) {
665 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
666 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
667 }
668
669 psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
670 }
671
672 memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0],
673 param->u.crypt.key, wep_key_len);
674
675 psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;
676
677 set_wep_key(padapter, param->u.crypt.key, wep_key_len,
678 wep_key_idx);
679
680 goto exit;
681
682 }
683
684 if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /* group key */
685 if (param->u.crypt.set_tx == 0) { /* group key */
686 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
687 DBG_8723A("%s, set group_key, WEP\n",
688 __func__);
689
690 memcpy(psecuritypriv->
691 dot118021XGrpKey[param->u.crypt.idx].
692 skey, param->u.crypt.key,
693 (param->u.crypt.key_len >
694 16 ? 16 : param->u.crypt.key_len));
695
696 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
697 if (param->u.crypt.key_len == 13) {
698 psecuritypriv->dot118021XGrpPrivacy =
699 _WEP104_;
700 }
701
702 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
703 DBG_8723A("%s, set group_key, TKIP\n",
704 __func__);
705
706 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
707
708 memcpy(psecuritypriv->
709 dot118021XGrpKey[param->u.crypt.idx].
710 skey, param->u.crypt.key,
711 (param->u.crypt.key_len >
712 16 ? 16 : param->u.crypt.key_len));
713
714 /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
715 /* set mic key */
716 memcpy(psecuritypriv->
717 dot118021XGrptxmickey[param->u.crypt.
718 idx].skey,
719 &param->u.crypt.key[16], 8);
720 memcpy(psecuritypriv->
721 dot118021XGrprxmickey[param->u.crypt.
722 idx].skey,
723 &param->u.crypt.key[24], 8);
724
725 psecuritypriv->busetkipkey = true;
726
727 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
728 DBG_8723A("%s, set group_key, CCMP\n",
729 __func__);
730
731 psecuritypriv->dot118021XGrpPrivacy = _AES_;
732
733 memcpy(psecuritypriv->
734 dot118021XGrpKey[param->u.crypt.idx].
735 skey, param->u.crypt.key,
736 (param->u.crypt.key_len >
737 16 ? 16 : param->u.crypt.key_len));
738 } else {
739 DBG_8723A("%s, set group_key, none\n",
740 __func__);
741
742 psecuritypriv->dot118021XGrpPrivacy =
743 _NO_PRIVACY_;
744 }
745
746 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
747
748 psecuritypriv->binstallGrpkey = true;
749
750 psecuritypriv->dot11PrivacyAlgrthm =
751 psecuritypriv->dot118021XGrpPrivacy;
752
753 set_group_key(padapter, param->u.crypt.key,
754 psecuritypriv->dot118021XGrpPrivacy,
755 param->u.crypt.idx);
756
757 pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
758 if (pbcmc_sta) {
759 pbcmc_sta->ieee8021x_blocked = false;
760 /* rx will use bmc_sta's dot118021XPrivacy */
761 pbcmc_sta->dot118021XPrivacy =
762 psecuritypriv->dot118021XGrpPrivacy;
763
764 }
765
766 }
767
768 goto exit;
769 }
770
771 if (psecuritypriv->dot11AuthAlgrthm ==
772 dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */
773 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
774 if (param->u.crypt.set_tx == 1) {
775 /* pairwise key */
776 memcpy(psta->dot118021x_UncstKey.skey,
777 param->u.crypt.key,
778 (param->u.crypt.key_len >
779 16 ? 16 : param->u.crypt.key_len));
780
781 if (!strcmp(param->u.crypt.alg, "WEP")) {
782 DBG_8723A("%s, set pairwise key, WEP\n",
783 __func__);
784
785 psta->dot118021XPrivacy = _WEP40_;
786 if (param->u.crypt.key_len == 13) {
787 psta->dot118021XPrivacy =
788 _WEP104_;
789 }
790 } else if (!strcmp(param->u.crypt.alg, "TKIP")) {
791 DBG_8723A("%s, set pairwise key, "
792 "TKIP\n", __func__);
793
794 psta->dot118021XPrivacy = _TKIP_;
795
796 /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
797 /* set mic key */
798 memcpy(psta->dot11tkiptxmickey.skey,
799 &param->u.crypt.key[16], 8);
800 memcpy(psta->dot11tkiprxmickey.skey,
801 &param->u.crypt.key[24], 8);
802
803 psecuritypriv->busetkipkey = true;
804
805 } else if (!strcmp(param->u.crypt.alg, "CCMP")) {
806
807 DBG_8723A("%s, set pairwise key, "
808 "CCMP\n", __func__);
809
810 psta->dot118021XPrivacy = _AES_;
811 } else {
812 DBG_8723A("%s, set pairwise key, "
813 "none\n", __func__);
814
815 psta->dot118021XPrivacy = _NO_PRIVACY_;
816 }
817
818 set_pairwise_key(padapter, psta);
819
820 psta->ieee8021x_blocked = false;
821
822 psta->bpairwise_key_installed = true;
823 } else { /* group key??? */
824 if (!strcmp(param->u.crypt.alg, "WEP")) {
825 memcpy(psecuritypriv->
826 dot118021XGrpKey[param->u.crypt.
827 idx].skey,
828 param->u.crypt.key,
829 (param->u.crypt.key_len >
830 16 ? 16 : param->u.crypt.
831 key_len));
832
833 psecuritypriv->dot118021XGrpPrivacy =
834 _WEP40_;
835 if (param->u.crypt.key_len == 13) {
836 psecuritypriv->
837 dot118021XGrpPrivacy =
838 _WEP104_;
839 }
840 } else if (!strcmp(param->u.crypt.alg, "TKIP")) {
841 psecuritypriv->dot118021XGrpPrivacy =
842 _TKIP_;
843
844 memcpy(psecuritypriv->
845 dot118021XGrpKey[param->u.crypt.
846 idx].skey,
847 param->u.crypt.key,
848 (param->u.crypt.key_len >
849 16 ? 16 : param->u.crypt.
850 key_len));
851
852 /* DEBUG_ERR("set key length :param->u"
853 ".crypt.key_len =%d\n",
854 param->u.crypt.key_len); */
855 /* set mic key */
856 memcpy(psecuritypriv->
857 dot118021XGrptxmickey[param->u.
858 crypt.idx].
859 skey, &param->u.crypt.key[16],
860 8);
861 memcpy(psecuritypriv->
862 dot118021XGrprxmickey[param->u.
863 crypt.idx].
864 skey, &param->u.crypt.key[24],
865 8);
866
867 psecuritypriv->busetkipkey = true;
868
869 } else if (!strcmp(param->u.crypt.alg, "CCMP")) {
870 psecuritypriv->dot118021XGrpPrivacy =
871 _AES_;
872
873 memcpy(psecuritypriv->
874 dot118021XGrpKey[param->u.crypt.
875 idx].skey,
876 param->u.crypt.key,
877 (param->u.crypt.key_len >
878 16 ? 16 : param->u.crypt.
879 key_len));
880 } else {
881 psecuritypriv->dot118021XGrpPrivacy =
882 _NO_PRIVACY_;
883 }
884
885 psecuritypriv->dot118021XGrpKeyid =
886 param->u.crypt.idx;
887
888 psecuritypriv->binstallGrpkey = true;
889
890 psecuritypriv->dot11PrivacyAlgrthm =
891 psecuritypriv->dot118021XGrpPrivacy;
892
893 set_group_key(padapter, param->u.crypt.key,
894 psecuritypriv->
895 dot118021XGrpPrivacy,
896 param->u.crypt.idx);
897
898 pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
899 if (pbcmc_sta) {
900 /* rx will use bmc_sta's
901 dot118021XPrivacy */
902 pbcmc_sta->ieee8021x_blocked = false;
903 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;
904 }
905 }
906 }
907 }
908
909exit:
910
911 return ret;
912
913}
914#endif
915
916static int rtw_cfg80211_set_encryption(struct net_device *dev,
917 struct ieee_param *param, u32 param_len)
918{
919 int ret = 0;
920 u32 wep_key_idx, wep_key_len;
921 struct rtw_adapter *padapter = netdev_priv(dev);
922 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
923 struct security_priv *psecuritypriv = &padapter->securitypriv;
924#ifdef CONFIG_8723AU_P2P
925 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
926#endif /* CONFIG_8723AU_P2P */
927
928
929
930 DBG_8723A("%s\n", __func__);
931
932 param->u.crypt.err = 0;
933 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
934
935 if (param_len <
936 (u32) ((u8 *) param->u.crypt.key - (u8 *) param) +
937 param->u.crypt.key_len) {
938 ret = -EINVAL;
939 goto exit;
940 }
941
942 if (is_broadcast_ether_addr(param->sta_addr)) {
943 if (param->u.crypt.idx >= WEP_KEYS) {
944 ret = -EINVAL;
945 goto exit;
946 }
947 } else {
948 ret = -EINVAL;
949 goto exit;
950 }
951
952 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
953 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
954 ("wpa_set_encryption, crypt.alg = WEP\n"));
955 DBG_8723A("wpa_set_encryption, crypt.alg = WEP\n");
956
957 wep_key_idx = param->u.crypt.idx;
958 wep_key_len = param->u.crypt.key_len;
959
960 if ((wep_key_idx > WEP_KEYS) || (wep_key_len <= 0)) {
961 ret = -EINVAL;
962 goto exit;
963 }
964
965 if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
966 /* wep default key has not been set, so use this
967 key index as default key. */
968
969 wep_key_len = wep_key_len <= 5 ? 5 : 13;
970
971 psecuritypriv->ndisencryptstatus =
972 Ndis802_11Encryption1Enabled;
973 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
974 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
975
976 if (wep_key_len == 13) {
977 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
978 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
979 }
980
981 psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
982 }
983
984 memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0],
985 param->u.crypt.key, wep_key_len);
986
987 psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;
988
989 rtw_set_key23a(padapter, psecuritypriv, wep_key_idx, 0);
990
991 goto exit;
992 }
993
994 if (padapter->securitypriv.dot11AuthAlgrthm ==
995 dot11AuthAlgrthm_8021X) { /* 802_1x */
996 struct sta_info *psta, *pbcmc_sta;
997 struct sta_priv *pstapriv = &padapter->stapriv;
998
999 if (check_fwstate(pmlmepriv,
1000 WIFI_STATION_STATE | WIFI_MP_STATE)) {
1001 /* sta mode */
1002 psta = rtw_get_stainfo23a(pstapriv, get_bssid(pmlmepriv));
1003 if (psta == NULL) {
1004 DBG_8723A("%s, : Obtain Sta_info fail\n",
1005 __func__);
1006 } else {
1007 /* Jeff: don't disable ieee8021x_blocked
1008 while clearing key */
1009 if (strcmp(param->u.crypt.alg, "none") != 0)
1010 psta->ieee8021x_blocked = false;
1011
1012 if ((padapter->securitypriv.ndisencryptstatus ==
1013 Ndis802_11Encryption2Enabled) ||
1014 (padapter->securitypriv.ndisencryptstatus ==
1015 Ndis802_11Encryption3Enabled)) {
1016 psta->dot118021XPrivacy =
1017 padapter->securitypriv.
1018 dot11PrivacyAlgrthm;
1019 }
1020
1021 if (param->u.crypt.set_tx == 1) {
1022 /* pairwise key */
1023 DBG_8723A("%s, : param->u.crypt.set_tx"
1024 " == 1\n", __func__);
1025
1026 memcpy(psta->dot118021x_UncstKey.skey,
1027 param->u.crypt.key,
1028 (param->u.crypt.key_len >
1029 16 ? 16 : param->u.crypt.
1030 key_len));
1031
1032 if (strcmp(param->u.crypt.alg,
1033 "TKIP") == 0) {
1034 memcpy(psta->dot11tkiptxmickey.
1035 skey,
1036 &param->u.crypt.key[16],
1037 8);
1038 memcpy(psta->dot11tkiprxmickey.
1039 skey,
1040 &param->u.crypt.key[24],
1041 8);
1042
1043 padapter->securitypriv.
1044 busetkipkey = false;
1045 }
1046 DBG_8723A(" ~~~~set sta key:unicastkey\n");
1047
1048 rtw_setstakey_cmd23a(padapter,
1049 (unsigned char *)psta,
1050 true);
1051 } else { /* group key */
1052 memcpy(padapter->securitypriv.
1053 dot118021XGrpKey[param->u.crypt.
1054 idx].skey,
1055 param->u.crypt.key,
1056 (param->u.crypt.key_len >
1057 16 ? 16 : param->u.crypt.
1058 key_len));
1059 memcpy(padapter->securitypriv.
1060 dot118021XGrptxmickey[param->u.
1061 crypt.idx].
1062 skey, &param->u.crypt.key[16],
1063 8);
1064 memcpy(padapter->securitypriv.
1065 dot118021XGrprxmickey[param->u.
1066 crypt.idx].
1067 skey, &param->u.crypt.key[24],
1068 8);
1069 padapter->securitypriv.binstallGrpkey =
1070 true;
1071 /* DEBUG_ERR((" param->u.crypt.key_len"
1072 "=%d\n", param->u.crypt.key_len)); */
1073 DBG_8723A
1074 (" ~~~~set sta key:groupkey\n");
1075
1076 padapter->securitypriv.
1077 dot118021XGrpKeyid =
1078 param->u.crypt.idx;
1079
1080 rtw_set_key23a(padapter,
1081 &padapter->securitypriv,
1082 param->u.crypt.idx, 1);
1083#ifdef CONFIG_8723AU_P2P
1084 if (rtw_p2p_chk_state
1085 (pwdinfo,
1086 P2P_STATE_PROVISIONING_ING)) {
1087 rtw_p2p_set_state(pwdinfo,
1088 P2P_STATE_PROVISIONING_DONE);
1089 }
1090#endif /* CONFIG_8723AU_P2P */
1091
1092 }
1093 }
1094
1095 pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
1096 if (pbcmc_sta) {
1097 /* Jeff: don't disable ieee8021x_blocked
1098 while clearing key */
1099 if (strcmp(param->u.crypt.alg, "none") != 0)
1100 pbcmc_sta->ieee8021x_blocked = false;
1101
1102 if ((padapter->securitypriv.ndisencryptstatus ==
1103 Ndis802_11Encryption2Enabled) ||
1104 (padapter->securitypriv.ndisencryptstatus ==
1105 Ndis802_11Encryption3Enabled)) {
1106 pbcmc_sta->dot118021XPrivacy =
1107 padapter->securitypriv.
1108 dot11PrivacyAlgrthm;
1109 }
1110 }
1111 } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { /* adhoc mode */
1112 }
1113 }
1114
1115exit:
1116
1117 DBG_8723A("%s, ret =%d\n", __func__, ret);
1118
1119
1120
1121 return ret;
1122}
1123
1124static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
1125 u8 key_index, bool pairwise,
1126 const u8 *mac_addr, struct key_params *params)
1127{
1128 char *alg_name;
1129 u32 param_len;
1130 struct ieee_param *param = NULL;
1131 int ret = 0;
1132 struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
1133 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1134 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1135
1136 DBG_8723A(FUNC_NDEV_FMT " adding key for %pM\n", FUNC_NDEV_ARG(ndev),
1137 mac_addr);
1138 DBG_8723A("cipher = 0x%x\n", params->cipher);
1139 DBG_8723A("key_len = 0x%x\n", params->key_len);
1140 DBG_8723A("seq_len = 0x%x\n", params->seq_len);
1141 DBG_8723A("key_index =%d\n", key_index);
1142 DBG_8723A("pairwise =%d\n", pairwise);
1143
1144 param_len = sizeof(struct ieee_param) + params->key_len;
1145 param = kzalloc(param_len, GFP_KERNEL);
1146 if (param == NULL)
1147 return -1;
1148
1149 param->cmd = IEEE_CMD_SET_ENCRYPTION;
1150 memset(param->sta_addr, 0xff, ETH_ALEN);
1151
1152 switch (params->cipher) {
1153 case IW_AUTH_CIPHER_NONE:
1154 /* todo: remove key */
1155 /* remove = 1; */
1156 alg_name = "none";
1157 break;
1158 case WLAN_CIPHER_SUITE_WEP40:
1159 case WLAN_CIPHER_SUITE_WEP104:
1160 alg_name = "WEP";
1161 break;
1162 case WLAN_CIPHER_SUITE_TKIP:
1163 alg_name = "TKIP";
1164 break;
1165 case WLAN_CIPHER_SUITE_CCMP:
1166 alg_name = "CCMP";
1167 break;
1168
1169 default:
1170 ret = -ENOTSUPP;
1171 goto addkey_end;
1172 }
1173
1174 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1175
1176 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
1177 param->u.crypt.set_tx = 0; /* for wpa/wpa2 group key */
1178 } else {
1179 param->u.crypt.set_tx = 1; /* for wpa/wpa2 pairwise key */
1180 }
1181
1182 /* param->u.crypt.idx = key_index - 1; */
1183 param->u.crypt.idx = key_index;
1184
1185 if (params->seq_len && params->seq) {
1186 memcpy(param->u.crypt.seq, params->seq, params->seq_len);
1187 }
1188
1189 if (params->key_len && params->key) {
1190 param->u.crypt.key_len = params->key_len;
1191 memcpy(param->u.crypt.key, params->key, params->key_len);
1192 }
1193
1194 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1195 ret = rtw_cfg80211_set_encryption(ndev, param, param_len);
1196 } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1197#ifdef CONFIG_8723AU_AP_MODE
1198 if (mac_addr)
1199 memcpy(param->sta_addr, (void *)mac_addr, ETH_ALEN);
1200
1201 ret = rtw_cfg80211_ap_set_encryption(ndev, param, param_len);
1202#endif
1203 } else {
1204 DBG_8723A("error! fw_state = 0x%x, iftype =%d\n",
1205 pmlmepriv->fw_state, rtw_wdev->iftype);
1206
1207 }
1208
1209addkey_end:
1210 kfree(param);
1211
1212 return ret;
1213}
1214
1215static int
1216cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev,
1217 u8 key_index, bool pairwise, const u8 *mac_addr,
1218 void *cookie,
1219 void (*callback) (void *cookie, struct key_params *))
1220{
1221 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
1222 return 0;
1223}
1224
1225static int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,
1226 u8 key_index, bool pairwise,
1227 const u8 *mac_addr)
1228{
1229 struct rtw_adapter *padapter = netdev_priv(ndev);
1230 struct security_priv *psecuritypriv = &padapter->securitypriv;
1231
1232 DBG_8723A(FUNC_NDEV_FMT " key_index =%d\n", FUNC_NDEV_ARG(ndev),
1233 key_index);
1234
1235 if (key_index == psecuritypriv->dot11PrivacyKeyIndex) {
1236 /* clear the flag of wep default key set. */
1237 psecuritypriv->bWepDefaultKeyIdxSet = 0;
1238 }
1239
1240 return 0;
1241}
1242
1243static int cfg80211_rtw_set_default_key(struct wiphy *wiphy,
1244 struct net_device *ndev, u8 key_index,
1245 bool unicast, bool multicast)
1246{
1247 struct rtw_adapter *padapter = netdev_priv(ndev);
1248 struct security_priv *psecuritypriv = &padapter->securitypriv;
1249
1250 DBG_8723A(FUNC_NDEV_FMT " key_index =%d"
1251 ", unicast =%d, multicast =%d.\n", FUNC_NDEV_ARG(ndev),
1252 key_index, unicast, multicast);
1253
1254 if ((key_index < WEP_KEYS) &&
1255 ((psecuritypriv->dot11PrivacyAlgrthm == _WEP40_) ||
1256 (psecuritypriv->dot11PrivacyAlgrthm == _WEP104_))) {
1257 /* set wep default key */
1258 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1259
1260 psecuritypriv->dot11PrivacyKeyIndex = key_index;
1261
1262 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
1263 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
1264 if (psecuritypriv->dot11DefKeylen[key_index] == 13) {
1265 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
1266 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
1267 }
1268
1269 /* set the flag to represent that wep default key
1270 has been set */
1271 psecuritypriv->bWepDefaultKeyIdxSet = 1;
1272 }
1273
1274 return 0;
1275}
1276
1277static int cfg80211_rtw_get_station(struct wiphy *wiphy,
1278 struct net_device *ndev,
1279 u8 *mac, struct station_info *sinfo)
1280{
1281 int ret = 0;
1282 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1283 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1284 struct sta_info *psta = NULL;
1285 struct sta_priv *pstapriv = &padapter->stapriv;
1286
1287 sinfo->filled = 0;
1288
1289 if (!mac) {
1290 DBG_8723A(FUNC_NDEV_FMT " mac ==%p\n", FUNC_NDEV_ARG(ndev), mac);
1291 ret = -ENOENT;
1292 goto exit;
1293 }
1294
1295 psta = rtw_get_stainfo23a(pstapriv, mac);
1296 if (psta == NULL) {
1297 DBG_8723A("%s, sta_info is null\n", __func__);
1298 ret = -ENOENT;
1299 goto exit;
1300 }
1301#ifdef CONFIG_DEBUG_CFG80211
1302 DBG_8723A(FUNC_NDEV_FMT " mac =" MAC_FMT "\n", FUNC_NDEV_ARG(ndev),
1303 MAC_ARG(mac));
1304#endif
1305
1306 /* for infra./P2PClient mode */
1307 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
1308 check_fwstate(pmlmepriv, _FW_LINKED)) {
1309 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1310
1311 if (memcmp(mac, cur_network->network.MacAddress, ETH_ALEN)) {
1312 DBG_8723A("%s, mismatch bssid =" MAC_FMT "\n", __func__,
1313 MAC_ARG(cur_network->network.MacAddress));
1314 ret = -ENOENT;
1315 goto exit;
1316 }
1317
1318 sinfo->filled |= STATION_INFO_SIGNAL;
1319 sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv.
1320 signal_strength);
1321
1322 sinfo->filled |= STATION_INFO_TX_BITRATE;
1323 sinfo->txrate.legacy = rtw_get_cur_max_rate23a(padapter);
1324
1325 sinfo->filled |= STATION_INFO_RX_PACKETS;
1326 sinfo->rx_packets = sta_rx_data_pkts(psta);
1327
1328 sinfo->filled |= STATION_INFO_TX_PACKETS;
1329 sinfo->tx_packets = psta->sta_stats.tx_pkts;
1330 }
1331
1332 /* for Ad-Hoc/AP mode */
1333 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
1334 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1335 check_fwstate(pmlmepriv, WIFI_AP_STATE)) &&
1336 check_fwstate(pmlmepriv, _FW_LINKED)
1337 ) {
1338 /* TODO: should acquire station info... */
1339 }
1340
1341exit:
1342 return ret;
1343}
1344
1345static int cfg80211_rtw_change_iface(struct wiphy *wiphy,
1346 struct net_device *ndev,
1347 enum nl80211_iftype type, u32 *flags,
1348 struct vif_params *params)
1349{
1350 enum nl80211_iftype old_type;
1351 enum ndis_802_11_net_infra networkType;
1352 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1353 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1354 struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
1355#ifdef CONFIG_8723AU_P2P
1356 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1357#endif
1358 int ret = 0;
1359 u8 change = false;
1360
1361 DBG_8723A(FUNC_NDEV_FMT " call netdev_open23a\n", FUNC_NDEV_ARG(ndev));
1362 if (netdev_open23a(ndev) != 0) {
1363 ret = -EPERM;
1364 goto exit;
1365 }
1366
1367 if (_FAIL == rtw_pwr_wakeup(padapter)) {
1368 ret = -EPERM;
1369 goto exit;
1370 }
1371
1372 old_type = rtw_wdev->iftype;
1373 DBG_8723A(FUNC_NDEV_FMT " old_iftype =%d, new_iftype =%d\n",
1374 FUNC_NDEV_ARG(ndev), old_type, type);
1375
1376 if (old_type != type) {
1377 change = true;
1378 pmlmeext->action_public_rxseq = 0xffff;
1379 pmlmeext->action_public_dialog_token = 0xff;
1380 }
1381
1382 switch (type) {
1383 case NL80211_IFTYPE_ADHOC:
1384 networkType = Ndis802_11IBSS;
1385 break;
1386 case NL80211_IFTYPE_P2P_CLIENT:
1387 case NL80211_IFTYPE_STATION:
1388 networkType = Ndis802_11Infrastructure;
1389#ifdef CONFIG_8723AU_P2P
1390 if (change && rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1391 del_timer_sync(&pwdinfo->find_phase_timer);
1392 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
1393 del_timer_sync(&pwdinfo->pre_tx_scan_timer);
1394
1395 /* it means remove GO and change mode from AP(GO)
1396 to station(P2P DEVICE) */
1397 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
1398 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
1399
1400 DBG_8723A("%s, role =%d, p2p_state =%d, pre_p2p_state ="
1401 "%d\n", __func__, rtw_p2p_role(pwdinfo),
1402 rtw_p2p_state(pwdinfo),
1403 rtw_p2p_pre_state(pwdinfo));
1404 }
1405#endif /* CONFIG_8723AU_P2P */
1406 break;
1407 case NL80211_IFTYPE_P2P_GO:
1408 case NL80211_IFTYPE_AP:
1409 networkType = Ndis802_11APMode;
1410#ifdef CONFIG_8723AU_P2P
1411 if (change && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
1412 /* it means P2P Group created, we will be GO
1413 and change mode from P2P DEVICE to AP(GO) */
1414 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
1415 }
1416#endif /* CONFIG_8723AU_P2P */
1417 break;
1418 default:
1419 return -EOPNOTSUPP;
1420 }
1421
1422 rtw_wdev->iftype = type;
1423
1424 if (rtw_set_802_11_infrastructure_mode23a(padapter, networkType) == false) {
1425 rtw_wdev->iftype = old_type;
1426 ret = -EPERM;
1427 goto exit;
1428 }
1429
1430 rtw_setopmode_cmd23a(padapter, networkType);
1431
1432exit:
1433 return ret;
1434}
1435
1436void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
1437 bool aborted)
1438{
1439 spin_lock_bh(&pwdev_priv->scan_req_lock);
1440 if (pwdev_priv->scan_request != NULL) {
1441#ifdef CONFIG_DEBUG_CFG80211
1442 DBG_8723A("%s with scan req\n", __func__);
1443#endif
1444 if (pwdev_priv->scan_request->wiphy !=
1445 pwdev_priv->rtw_wdev->wiphy)
1446 DBG_8723A("error wiphy compare\n");
1447 else
1448 cfg80211_scan_done(pwdev_priv->scan_request, aborted);
1449
1450 pwdev_priv->scan_request = NULL;
1451 } else {
1452#ifdef CONFIG_DEBUG_CFG80211
1453 DBG_8723A("%s without scan req\n", __func__);
1454#endif
1455 }
1456 spin_unlock_bh(&pwdev_priv->scan_req_lock);
1457}
1458
1459void rtw_cfg80211_surveydone_event_callback(struct rtw_adapter *padapter)
1460{
1461 struct list_head *plist, *phead, *ptmp;
1462 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1463 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1464 struct wlan_network *pnetwork;
1465
1466#ifdef CONFIG_DEBUG_CFG80211
1467 DBG_8723A("%s\n", __func__);
1468#endif
1469
1470 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1471
1472 phead = get_list_head(queue);
1473
1474 list_for_each_safe(plist, ptmp, phead) {
1475 pnetwork = container_of(plist, struct wlan_network, list);
1476
1477 /* report network only if the current channel set
1478 contains the channel to which this network belongs */
1479 if (rtw_ch_set_search_ch23a
1480 (padapter->mlmeextpriv.channel_set,
1481 pnetwork->network.Configuration.DSConfig) >= 0)
1482 rtw_cfg80211_inform_bss(padapter, pnetwork);
1483 }
1484
1485 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1486
1487 /* call this after other things have been done */
1488 rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev),
1489 false);
1490}
1491
1492static int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter,
1493 char *buf, int len)
1494{
1495 int ret = 0;
1496 uint wps_ielen = 0;
1497 u8 *wps_ie;
1498#ifdef CONFIG_8723AU_P2P
1499 u32 p2p_ielen = 0;
1500 u8 *p2p_ie;
1501 u32 wfd_ielen = 0;
1502#endif
1503 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1504
1505#ifdef CONFIG_DEBUG_CFG80211
1506 DBG_8723A("%s, ielen =%d\n", __func__, len);
1507#endif
1508
1509 if (len > 0) {
1510 wps_ie = rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen);
1511 if (wps_ie) {
1512#ifdef CONFIG_DEBUG_CFG80211
1513 DBG_8723A("probe_req_wps_ielen =%d\n", wps_ielen);
1514#endif
1515 if (pmlmepriv->wps_probe_req_ie) {
1516 pmlmepriv->wps_probe_req_ie_len = 0;
1517 kfree(pmlmepriv->wps_probe_req_ie);
1518 pmlmepriv->wps_probe_req_ie = NULL;
1519 }
1520
1521 pmlmepriv->wps_probe_req_ie =
1522 kmalloc(wps_ielen, GFP_KERNEL);
1523 if (pmlmepriv->wps_probe_req_ie == NULL) {
1524 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
1525 __func__, __LINE__);
1526 return -EINVAL;
1527 }
1528 memcpy(pmlmepriv->wps_probe_req_ie, wps_ie, wps_ielen);
1529 pmlmepriv->wps_probe_req_ie_len = wps_ielen;
1530 }
1531#ifdef CONFIG_8723AU_P2P
1532 p2p_ie = rtw_get_p2p_ie23a(buf, len, NULL, &p2p_ielen);
1533 if (p2p_ie) {
1534#ifdef CONFIG_DEBUG_CFG80211
1535 DBG_8723A("probe_req_p2p_ielen =%d\n", p2p_ielen);
1536#endif
1537
1538 if (pmlmepriv->p2p_probe_req_ie) {
1539 pmlmepriv->p2p_probe_req_ie_len = 0;
1540 kfree(pmlmepriv->p2p_probe_req_ie);
1541 pmlmepriv->p2p_probe_req_ie = NULL;
1542 }
1543
1544 pmlmepriv->p2p_probe_req_ie =
1545 kmalloc(p2p_ielen, GFP_KERNEL);
1546 if (pmlmepriv->p2p_probe_req_ie == NULL) {
1547 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
1548 __func__, __LINE__);
1549 return -EINVAL;
1550
1551 }
1552 memcpy(pmlmepriv->p2p_probe_req_ie, p2p_ie, p2p_ielen);
1553 pmlmepriv->p2p_probe_req_ie_len = p2p_ielen;
1554 }
1555#endif /* CONFIG_8723AU_P2P */
1556
1557 /* buf += p2p_ielen; */
1558 /* len -= p2p_ielen; */
1559
1560#ifdef CONFIG_8723AU_P2P
1561 if (rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen)) {
1562#ifdef CONFIG_DEBUG_CFG80211
1563 DBG_8723A("probe_req_wfd_ielen =%d\n", wfd_ielen);
1564#endif
1565
1566 if (pmlmepriv->wfd_probe_req_ie) {
1567 pmlmepriv->wfd_probe_req_ie_len = 0;
1568 kfree(pmlmepriv->wfd_probe_req_ie);
1569 pmlmepriv->wfd_probe_req_ie = NULL;
1570 }
1571
1572 pmlmepriv->wfd_probe_req_ie =
1573 kmalloc(wfd_ielen, GFP_KERNEL);
1574 if (pmlmepriv->wfd_probe_req_ie == NULL) {
1575 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
1576 __func__, __LINE__);
1577 return -EINVAL;
1578
1579 }
1580 rtw_get_wfd_ie(buf, len, pmlmepriv->wfd_probe_req_ie,
1581 &pmlmepriv->wfd_probe_req_ie_len);
1582 }
1583#endif /* CONFIG_8723AU_P2P */
1584
1585 }
1586
1587 return ret;
1588}
1589
1590static int cfg80211_rtw_scan(struct wiphy *wiphy,
1591 struct cfg80211_scan_request *request)
1592{
1593 int i;
1594 u8 _status = false;
1595 int ret = 0;
1596 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1597 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1598 struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1599 struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
1600 struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
1601 struct cfg80211_ssid *ssids = request->ssids;
1602#ifdef CONFIG_8723AU_P2P
1603 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1604 int social_channel = 0;
1605#endif /* CONFIG_8723AU_P2P */
1606 bool need_indicate_scan_done = false;
1607
1608#ifdef CONFIG_DEBUG_CFG80211
1609 DBG_8723A(FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(padapter));
1610#endif
1611
1612 spin_lock_bh(&pwdev_priv->scan_req_lock);
1613 pwdev_priv->scan_request = request;
1614 spin_unlock_bh(&pwdev_priv->scan_req_lock);
1615
1616 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1617
1618#ifdef CONFIG_DEBUG_CFG80211
1619 DBG_8723A("%s under WIFI_AP_STATE\n", __func__);
1620#endif
1621 /* need_indicate_scan_done = true; */
1622 /* goto check_need_indicate_scan_done; */
1623 }
1624
1625 if (rtw_pwr_wakeup(padapter) == _FAIL) {
1626 need_indicate_scan_done = true;
1627 goto check_need_indicate_scan_done;
1628 }
1629#ifdef CONFIG_8723AU_P2P
1630 if (!memcmp(ssids->ssid, "DIRECT-", 7) &&
1631 rtw_get_p2p_ie23a((u8 *) request->ie, request->ie_len, NULL, NULL)) {
1632 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
1633 rtw_p2p_enable23a(padapter, P2P_ROLE_DEVICE);
1634 wdev_to_priv(padapter->rtw_wdev)->p2p_enabled = true;
1635 } else {
1636 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
1637#ifdef CONFIG_DEBUG_CFG80211
1638 DBG_8723A("%s, role =%d, p2p_state =%d\n", __func__,
1639 rtw_p2p_role(pwdinfo),
1640 rtw_p2p_state(pwdinfo));
1641#endif
1642 }
1643 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
1644
1645 if (request->n_channels == 3 &&
1646 request->channels[0]->hw_value == 1 &&
1647 request->channels[1]->hw_value == 6 &&
1648 request->channels[2]->hw_value == 11)
1649 social_channel = 1;
1650 }
1651#endif /* CONFIG_8723AU_P2P */
1652
1653 if (request->ie && request->ie_len > 0) {
1654 rtw_cfg80211_set_probe_req_wpsp2pie(padapter,
1655 (u8 *) request->ie,
1656 request->ie_len);
1657 }
1658
1659 if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) {
1660 DBG_8723A("%s, bBusyTraffic == true\n", __func__);
1661 need_indicate_scan_done = true;
1662 goto check_need_indicate_scan_done;
1663 }
1664 if (rtw_is_scan_deny(padapter)) {
1665 DBG_8723A(FUNC_ADPT_FMT ": scan deny\n",
1666 FUNC_ADPT_ARG(padapter));
1667 need_indicate_scan_done = true;
1668 goto check_need_indicate_scan_done;
1669 }
1670
1671 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ==
1672 true) {
1673 DBG_8723A("%s, fwstate = 0x%x\n", __func__, pmlmepriv->fw_state);
1674 need_indicate_scan_done = true;
1675 goto check_need_indicate_scan_done;
1676 }
1677#ifdef CONFIG_8723AU_P2P
1678 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
1679 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
1680 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
1681 rtw_free_network_queue23a(padapter, true);
1682
1683 if (social_channel == 0)
1684 rtw_p2p_findphase_ex_set(pwdinfo,
1685 P2P_FINDPHASE_EX_NONE);
1686 else
1687 rtw_p2p_findphase_ex_set(pwdinfo,
1688 P2P_FINDPHASE_EX_SOCIAL_LAST);
1689 }
1690#endif /* CONFIG_8723AU_P2P */
1691
1692 memset(ssid, 0, sizeof(struct cfg80211_ssid) * RTW_SSID_SCAN_AMOUNT);
1693 /* parsing request ssids, n_ssids */
1694 for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {
1695#ifdef CONFIG_DEBUG_CFG80211
1696 DBG_8723A("ssid =%s, len =%d\n", ssids[i].ssid,
1697 ssids[i].ssid_len);
1698#endif
1699 memcpy(ssid[i].ssid, ssids[i].ssid, ssids[i].ssid_len);
1700 ssid[i].ssid_len = ssids[i].ssid_len;
1701 }
1702
1703 /* parsing channels, n_channels */
1704 memset(ch, 0,
1705 sizeof(struct rtw_ieee80211_channel) * RTW_CHANNEL_SCAN_AMOUNT);
1706
1707 if (request->n_channels == 1) {
1708 for (i = 0; i < request->n_channels &&
1709 i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
1710#ifdef CONFIG_DEBUG_CFG80211
1711 DBG_8723A(FUNC_ADPT_FMT CHAN_FMT "\n",
1712 FUNC_ADPT_ARG(padapter),
1713 CHAN_ARG(request->channels[i]));
1714#endif
1715 ch[i].hw_value = request->channels[i]->hw_value;
1716 ch[i].flags = request->channels[i]->flags;
1717 }
1718 }
1719
1720 spin_lock_bh(&pmlmepriv->lock);
1721 if (request->n_channels == 1) {
1722 memcpy(&ch[1], &ch[0], sizeof(struct rtw_ieee80211_channel));
1723 memcpy(&ch[2], &ch[0], sizeof(struct rtw_ieee80211_channel));
1724 _status = rtw_sitesurvey_cmd23a(padapter, ssid,
1725 RTW_SSID_SCAN_AMOUNT, ch, 3);
1726 } else {
1727 _status = rtw_sitesurvey_cmd23a(padapter, ssid,
1728 RTW_SSID_SCAN_AMOUNT, NULL, 0);
1729 }
1730 spin_unlock_bh(&pmlmepriv->lock);
1731
1732 if (_status == false)
1733 ret = -1;
1734
1735check_need_indicate_scan_done:
1736 if (need_indicate_scan_done)
1737 rtw_cfg80211_surveydone_event_callback(padapter);
1738 return ret;
1739}
1740
1741static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1742{
1743 DBG_8723A("%s\n", __func__);
1744 return 0;
1745}
1746
1747static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
1748 struct cfg80211_ibss_params *params)
1749{
1750 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
1751 return 0;
1752}
1753
1754static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1755{
1756 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
1757 return 0;
1758}
1759
1760static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv,
1761 u32 wpa_version)
1762{
1763 DBG_8723A("%s, wpa_version =%d\n", __func__, wpa_version);
1764
1765 if (!wpa_version) {
1766 psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
1767 return 0;
1768 }
1769
1770 if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) {
1771 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
1772 }
1773
1774/*
1775 if (wpa_version & NL80211_WPA_VERSION_2)
1776 {
1777 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;
1778 }
1779*/
1780
1781 return 0;
1782}
1783
1784static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,
1785 enum nl80211_auth_type sme_auth_type)
1786{
1787 DBG_8723A("%s, nl80211_auth_type =%d\n", __func__, sme_auth_type);
1788
1789 switch (sme_auth_type) {
1790 case NL80211_AUTHTYPE_AUTOMATIC:
1791 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1792
1793 break;
1794 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1795 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1796
1797 if (psecuritypriv->ndisauthtype > Ndis802_11AuthModeWPA)
1798 psecuritypriv->dot11AuthAlgrthm =
1799 dot11AuthAlgrthm_8021X;
1800 break;
1801 case NL80211_AUTHTYPE_SHARED_KEY:
1802 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1803
1804 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1805 break;
1806 default:
1807 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1808 /* return -ENOTSUPP; */
1809 }
1810
1811 return 0;
1812}
1813
1814static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv,
1815 u32 cipher, bool ucast)
1816{
1817 u32 ndisencryptstatus = Ndis802_11EncryptionDisabled;
1818
1819 u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm :
1820 &psecuritypriv->dot118021XGrpPrivacy;
1821
1822 DBG_8723A("%s, ucast =%d, cipher = 0x%x\n", __func__, ucast, cipher);
1823
1824 if (!cipher) {
1825 *profile_cipher = _NO_PRIVACY_;
1826 psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1827 return 0;
1828 }
1829
1830 switch (cipher) {
1831 case IW_AUTH_CIPHER_NONE:
1832 *profile_cipher = _NO_PRIVACY_;
1833 ndisencryptstatus = Ndis802_11EncryptionDisabled;
1834 break;
1835 case WLAN_CIPHER_SUITE_WEP40:
1836 *profile_cipher = _WEP40_;
1837 ndisencryptstatus = Ndis802_11Encryption1Enabled;
1838 break;
1839 case WLAN_CIPHER_SUITE_WEP104:
1840 *profile_cipher = _WEP104_;
1841 ndisencryptstatus = Ndis802_11Encryption1Enabled;
1842 break;
1843 case WLAN_CIPHER_SUITE_TKIP:
1844 *profile_cipher = _TKIP_;
1845 ndisencryptstatus = Ndis802_11Encryption2Enabled;
1846 break;
1847 case WLAN_CIPHER_SUITE_CCMP:
1848 *profile_cipher = _AES_;
1849 ndisencryptstatus = Ndis802_11Encryption3Enabled;
1850 break;
1851 default:
1852 DBG_8723A("Unsupported cipher: 0x%x\n", cipher);
1853 return -ENOTSUPP;
1854 }
1855
1856 if (ucast)
1857 psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1858
1859 return 0;
1860}
1861
1862static int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv,
1863 u32 key_mgt)
1864{
1865 DBG_8723A("%s, key_mgt = 0x%x\n", __func__, key_mgt);
1866
1867 if (key_mgt == WLAN_AKM_SUITE_8021X)
1868 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1869 else if (key_mgt == WLAN_AKM_SUITE_PSK)
1870 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1871 else
1872 DBG_8723A("Invalid key mgt: 0x%x\n", key_mgt);
1873
1874 return 0;
1875}
1876
1877static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie,
1878 size_t ielen)
1879{
1880 u8 *buf = NULL, *pos = NULL;
1881 int group_cipher = 0, pairwise_cipher = 0;
1882 int ret = 0;
1883 int wpa_ielen = 0;
1884 int wpa2_ielen = 0;
1885 u8 *pwpa, *pwpa2;
1886 u8 null_addr[] = { 0, 0, 0, 0, 0, 0 };
1887 int i;
1888
1889 if (!pie || !ielen) {
1890 /* Treat this as normal case, but need to clear
1891 WIFI_UNDER_WPS */
1892 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1893 goto exit;
1894 }
1895 if (ielen > MAX_WPA_IE_LEN + MAX_WPS_IE_LEN + MAX_P2P_IE_LEN) {
1896 ret = -EINVAL;
1897 goto exit;
1898 }
1899 buf = kzalloc(ielen, GFP_KERNEL);
1900 if (buf == NULL) {
1901 ret = -ENOMEM;
1902 goto exit;
1903 }
1904 memcpy(buf, pie, ielen);
1905
1906 /* dump */
1907 DBG_8723A("set wpa_ie(length:%zu):\n", ielen);
1908 for (i = 0; i < ielen; i = i + 8)
1909 DBG_8723A("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
1910 buf[i], buf[i + 1],
1911 buf[i + 2], buf[i + 3], buf[i + 4],
1912 buf[i + 5], buf[i + 6], buf[i + 7]);
1913 pos = buf;
1914 if (ielen < RSN_HEADER_LEN) {
1915 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
1916 ("Ie len too short %d\n", (int)ielen));
1917 ret = -1;
1918 goto exit;
1919 }
1920
1921 pwpa = rtw_get_wpa_ie23a(buf, &wpa_ielen, ielen);
1922 if (pwpa && wpa_ielen > 0) {
1923 if (rtw_parse_wpa_ie23a(pwpa, wpa_ielen + 2, &group_cipher,
1924 &pairwise_cipher, NULL) == _SUCCESS) {
1925 padapter->securitypriv.dot11AuthAlgrthm =
1926 dot11AuthAlgrthm_8021X;
1927 padapter->securitypriv.ndisauthtype =
1928 Ndis802_11AuthModeWPAPSK;
1929 memcpy(padapter->securitypriv.supplicant_ie, &pwpa[0],
1930 wpa_ielen + 2);
1931
1932 DBG_8723A("got wpa_ie, wpa_ielen:%u\n", wpa_ielen);
1933 }
1934 }
1935
1936 pwpa2 = rtw_get_wpa2_ie23a(buf, &wpa2_ielen, ielen);
1937 if (pwpa2 && wpa2_ielen > 0) {
1938 if (rtw_parse_wpa2_ie23a (pwpa2, wpa2_ielen + 2, &group_cipher,
1939 &pairwise_cipher, NULL) == _SUCCESS) {
1940 padapter->securitypriv.dot11AuthAlgrthm =
1941 dot11AuthAlgrthm_8021X;
1942 padapter->securitypriv.ndisauthtype =
1943 Ndis802_11AuthModeWPA2PSK;
1944 memcpy(padapter->securitypriv.supplicant_ie, &pwpa2[0],
1945 wpa2_ielen + 2);
1946
1947 DBG_8723A("got wpa2_ie, wpa2_ielen:%u\n", wpa2_ielen);
1948 }
1949 }
1950
1951 if (group_cipher == 0) {
1952 group_cipher = WPA_CIPHER_NONE;
1953 }
1954 if (pairwise_cipher == 0) {
1955 pairwise_cipher = WPA_CIPHER_NONE;
1956 }
1957
1958 switch (group_cipher) {
1959 case WPA_CIPHER_NONE:
1960 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1961 padapter->securitypriv.ndisencryptstatus =
1962 Ndis802_11EncryptionDisabled;
1963 break;
1964 case WPA_CIPHER_WEP40:
1965 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
1966 padapter->securitypriv.ndisencryptstatus =
1967 Ndis802_11Encryption1Enabled;
1968 break;
1969 case WPA_CIPHER_TKIP:
1970 padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
1971 padapter->securitypriv.ndisencryptstatus =
1972 Ndis802_11Encryption2Enabled;
1973 break;
1974 case WPA_CIPHER_CCMP:
1975 padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
1976 padapter->securitypriv.ndisencryptstatus =
1977 Ndis802_11Encryption3Enabled;
1978 break;
1979 case WPA_CIPHER_WEP104:
1980 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
1981 padapter->securitypriv.ndisencryptstatus =
1982 Ndis802_11Encryption1Enabled;
1983 break;
1984 }
1985
1986 switch (pairwise_cipher) {
1987 case WPA_CIPHER_NONE:
1988 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1989 padapter->securitypriv.ndisencryptstatus =
1990 Ndis802_11EncryptionDisabled;
1991 break;
1992 case WPA_CIPHER_WEP40:
1993 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1994 padapter->securitypriv.ndisencryptstatus =
1995 Ndis802_11Encryption1Enabled;
1996 break;
1997 case WPA_CIPHER_TKIP:
1998 padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
1999 padapter->securitypriv.ndisencryptstatus =
2000 Ndis802_11Encryption2Enabled;
2001 break;
2002 case WPA_CIPHER_CCMP:
2003 padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
2004 padapter->securitypriv.ndisencryptstatus =
2005 Ndis802_11Encryption3Enabled;
2006 break;
2007 case WPA_CIPHER_WEP104:
2008 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
2009 padapter->securitypriv.ndisencryptstatus =
2010 Ndis802_11Encryption1Enabled;
2011 break;
2012 }
2013
2014 { /* handle wps_ie */
2015 uint wps_ielen;
2016 u8 *wps_ie;
2017
2018 wps_ie = rtw_get_wps_ie23a(buf, ielen, NULL, &wps_ielen);
2019 if (wps_ie && wps_ielen > 0) {
2020 DBG_8723A("got wps_ie, wps_ielen:%u\n", wps_ielen);
2021 padapter->securitypriv.wps_ie_len =
2022 wps_ielen <
2023 MAX_WPS_IE_LEN ? wps_ielen : MAX_WPS_IE_LEN;
2024 memcpy(padapter->securitypriv.wps_ie, wps_ie,
2025 padapter->securitypriv.wps_ie_len);
2026 set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
2027 } else {
2028 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
2029 }
2030 }
2031
2032#ifdef CONFIG_8723AU_P2P
2033 { /* check p2p_ie for assoc req; */
2034 uint p2p_ielen = 0;
2035 u8 *p2p_ie;
2036 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2037
2038 p2p_ie = rtw_get_p2p_ie23a(buf, ielen, NULL, &p2p_ielen);
2039 if (p2p_ie) {
2040#ifdef CONFIG_DEBUG_CFG80211
2041 DBG_8723A("%s p2p_assoc_req_ielen =%d\n", __func__,
2042 p2p_ielen);
2043#endif
2044
2045 if (pmlmepriv->p2p_assoc_req_ie) {
2046 pmlmepriv->p2p_assoc_req_ie_len = 0;
2047 kfree(pmlmepriv->p2p_assoc_req_ie);
2048 pmlmepriv->p2p_assoc_req_ie = NULL;
2049 }
2050
2051 pmlmepriv->p2p_assoc_req_ie =
2052 kmalloc(p2p_ielen, GFP_KERNEL);
2053 if (pmlmepriv->p2p_assoc_req_ie == NULL) {
2054 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
2055 __func__, __LINE__);
2056 goto exit;
2057 }
2058 memcpy(pmlmepriv->p2p_assoc_req_ie, p2p_ie, p2p_ielen);
2059 pmlmepriv->p2p_assoc_req_ie_len = p2p_ielen;
2060 }
2061 }
2062#endif /* CONFIG_8723AU_P2P */
2063
2064#ifdef CONFIG_8723AU_P2P
2065 { /* check wfd_ie for assoc req; */
2066 uint wfd_ielen = 0;
2067 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2068
2069 if (rtw_get_wfd_ie(buf, ielen, NULL, &wfd_ielen)) {
2070#ifdef CONFIG_DEBUG_CFG80211
2071 DBG_8723A("%s wfd_assoc_req_ielen =%d\n", __func__,
2072 wfd_ielen);
2073#endif
2074
2075 if (pmlmepriv->wfd_assoc_req_ie) {
2076 pmlmepriv->wfd_assoc_req_ie_len = 0;
2077 kfree(pmlmepriv->wfd_assoc_req_ie);
2078 pmlmepriv->wfd_assoc_req_ie = NULL;
2079 }
2080
2081 pmlmepriv->wfd_assoc_req_ie =
2082 kmalloc(wfd_ielen, GFP_KERNEL);
2083 if (pmlmepriv->wfd_assoc_req_ie == NULL) {
2084 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
2085 __func__, __LINE__);
2086 goto exit;
2087 }
2088 rtw_get_wfd_ie(buf, ielen, pmlmepriv->wfd_assoc_req_ie,
2089 &pmlmepriv->wfd_assoc_req_ie_len);
2090 }
2091 }
2092#endif /* CONFIG_8723AU_P2P */
2093
2094 /* TKIP and AES disallow multicast packets until installing group key */
2095 if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_ ||
2096 padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_ ||
2097 padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
2098 /* WPS open need to enable multicast */
2099 /* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true)*/
2100 rtw_hal_set_hwreg23a(padapter, HW_VAR_OFF_RCR_AM, null_addr);
2101
2102 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
2103 ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->"
2104 "securitypriv.ndisencryptstatus =%d padapter->"
2105 "securitypriv.ndisauthtype =%d\n", pairwise_cipher,
2106 padapter->securitypriv.ndisencryptstatus,
2107 padapter->securitypriv.ndisauthtype));
2108
2109exit:
2110 kfree(buf);
2111 if (ret)
2112 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
2113 return ret;
2114}
2115
2116static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
2117 struct cfg80211_connect_params *sme)
2118{
2119 int ret = 0;
2120 struct list_head *phead, *plist, *ptmp;
2121 struct wlan_network *pnetwork = NULL;
2122 enum ndis_802_11_auth_mode authmode;
2123 struct cfg80211_ssid ndis_ssid;
2124 u8 *dst_ssid;
2125 u8 *src_ssid;
2126 u8 *dst_bssid;
2127 const u8 *src_bssid;
2128 /* u8 matched_by_bssid = false; */
2129 /* u8 matched_by_ssid = false; */
2130 u8 matched = false;
2131 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2132 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2133 struct security_priv *psecuritypriv = &padapter->securitypriv;
2134 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
2135
2136 DBG_8723A("=>" FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
2137 DBG_8723A("privacy =%d, key =%p, key_len =%d, key_idx =%d\n",
2138 sme->privacy, sme->key, sme->key_len, sme->key_idx);
2139
2140 if (wdev_to_priv(padapter->rtw_wdev)->block) {
2141 ret = -EBUSY;
2142 DBG_8723A("%s wdev_priv.block is set\n", __func__);
2143 goto exit;
2144 }
2145
2146 if (_FAIL == rtw_pwr_wakeup(padapter)) {
2147 ret = -EPERM;
2148 goto exit;
2149 }
2150
2151 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2152 ret = -EPERM;
2153 goto exit;
2154 }
2155
2156 if (!sme->ssid || !sme->ssid_len) {
2157 ret = -EINVAL;
2158 goto exit;
2159 }
2160
2161 if (sme->ssid_len > IW_ESSID_MAX_SIZE) {
2162 ret = -E2BIG;
2163 goto exit;
2164 }
2165
2166 memset(&ndis_ssid, 0, sizeof(struct cfg80211_ssid));
2167 ndis_ssid.ssid_len = sme->ssid_len;
2168 memcpy(ndis_ssid.ssid, sme->ssid, sme->ssid_len);
2169
2170 DBG_8723A("ssid =%s, len =%zu\n", ndis_ssid.ssid, sme->ssid_len);
2171
2172 if (sme->bssid)
2173 DBG_8723A("bssid =" MAC_FMT "\n", MAC_ARG(sme->bssid));
2174
2175 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
2176 ret = -EBUSY;
2177 DBG_8723A("%s, fw_state = 0x%x, goto exit\n", __func__,
2178 pmlmepriv->fw_state);
2179 goto exit;
2180 }
2181 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
2182 rtw_scan_abort23a(padapter);
2183 }
2184
2185 spin_lock_bh(&queue->lock);
2186
2187 phead = get_list_head(queue);
2188
2189 list_for_each_safe(plist, ptmp, phead) {
2190 pnetwork = container_of(plist, struct wlan_network, list);
2191
2192 dst_ssid = pnetwork->network.Ssid.ssid;
2193 dst_bssid = pnetwork->network.MacAddress;
2194
2195 if (sme->bssid) {
2196 if (memcmp(pnetwork->network.MacAddress,
2197 sme->bssid, ETH_ALEN))
2198 continue;
2199 }
2200
2201 if (sme->ssid && sme->ssid_len) {
2202 if (pnetwork->network.Ssid.ssid_len != sme->ssid_len ||
2203 memcmp(pnetwork->network.Ssid.ssid, sme->ssid,
2204 sme->ssid_len))
2205 continue;
2206 }
2207
2208 if (sme->bssid) {
2209 src_bssid = sme->bssid;
2210
2211 if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
2212 DBG_8723A("matched by bssid\n");
2213
2214 ndis_ssid.ssid_len =
2215 pnetwork->network.Ssid.ssid_len;
2216 memcpy(ndis_ssid.ssid,
2217 pnetwork->network.Ssid.ssid,
2218 pnetwork->network.Ssid.ssid_len);
2219
2220 matched = true;
2221 break;
2222 }
2223
2224 } else if (sme->ssid && sme->ssid_len) {
2225 src_ssid = ndis_ssid.ssid;
2226
2227 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.ssid_len)) &&
2228 (pnetwork->network.Ssid.ssid_len ==
2229 ndis_ssid.ssid_len)) {
2230 DBG_8723A("matched by ssid\n");
2231 matched = true;
2232 break;
2233 }
2234 }
2235 }
2236
2237 spin_unlock_bh(&queue->lock);
2238
2239 if (!matched || (pnetwork == NULL)) {
2240 ret = -ENOENT;
2241 DBG_8723A("connect, matched == false, goto exit\n");
2242 goto exit;
2243 }
2244
2245 if (rtw_set_802_11_infrastructure_mode23a
2246 (padapter, pnetwork->network.InfrastructureMode) == false) {
2247 ret = -EPERM;
2248 goto exit;
2249 }
2250
2251 psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
2252 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
2253 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
2254 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
2255 psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
2256
2257 ret =
2258 rtw_cfg80211_set_wpa_version(psecuritypriv,
2259 sme->crypto.wpa_versions);
2260 if (ret < 0)
2261 goto exit;
2262
2263 ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type);
2264
2265 if (ret < 0)
2266 goto exit;
2267
2268 DBG_8723A("%s, ie_len =%zu\n", __func__, sme->ie_len);
2269
2270 ret = rtw_cfg80211_set_wpa_ie(padapter, sme->ie, sme->ie_len);
2271 if (ret < 0)
2272 goto exit;
2273
2274 if (sme->crypto.n_ciphers_pairwise) {
2275 ret = rtw_cfg80211_set_cipher(psecuritypriv,
2276 sme->crypto.ciphers_pairwise[0],
2277 true);
2278 if (ret < 0)
2279 goto exit;
2280 }
2281
2282 /* For WEP Shared auth */
2283 if ((psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Shared ||
2284 psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Auto) &&
2285 sme->key) {
2286 u32 wep_key_idx, wep_key_len, wep_total_len;
2287 struct ndis_802_11_wep *pwep = NULL;
2288 DBG_8723A("%s(): Shared/Auto WEP\n", __func__);
2289
2290 wep_key_idx = sme->key_idx;
2291 wep_key_len = sme->key_len;
2292
2293 if (sme->key_idx > WEP_KEYS) {
2294 ret = -EINVAL;
2295 goto exit;
2296 }
2297
2298 if (wep_key_len > 0) {
2299 wep_key_len = wep_key_len <= 5 ? 5 : 13;
2300 wep_total_len =
2301 wep_key_len +
2302 offsetof(struct ndis_802_11_wep, KeyMaterial);
2303 pwep = (struct ndis_802_11_wep *)kmalloc(wep_total_len,
2304 GFP_KERNEL);
2305 if (pwep == NULL) {
2306 DBG_8723A(" wpa_set_encryption: pwep "
2307 "allocate fail !!!\n");
2308 ret = -ENOMEM;
2309 goto exit;
2310 }
2311
2312 memset(pwep, 0, wep_total_len);
2313
2314 pwep->KeyLength = wep_key_len;
2315 pwep->Length = wep_total_len;
2316
2317 if (wep_key_len == 13) {
2318 padapter->securitypriv.dot11PrivacyAlgrthm =
2319 _WEP104_;
2320 padapter->securitypriv.dot118021XGrpPrivacy =
2321 _WEP104_;
2322 }
2323 } else {
2324 ret = -EINVAL;
2325 goto exit;
2326 }
2327
2328 pwep->KeyIndex = wep_key_idx;
2329 pwep->KeyIndex |= 0x80000000;
2330
2331 memcpy(pwep->KeyMaterial, (void *)sme->key, pwep->KeyLength);
2332
2333 if (rtw_set_802_11_add_wep23a(padapter, pwep) == (u8) _FAIL) {
2334 ret = -EOPNOTSUPP;
2335 }
2336
2337 kfree(pwep);
2338
2339 if (ret < 0)
2340 goto exit;
2341 }
2342
2343 ret = rtw_cfg80211_set_cipher(psecuritypriv,
2344 sme->crypto.cipher_group, false);
2345 if (ret < 0)
2346 return ret;
2347
2348 if (sme->crypto.n_akm_suites) {
2349 ret = rtw_cfg80211_set_key_mgt(psecuritypriv,
2350 sme->crypto.akm_suites[0]);
2351 if (ret < 0)
2352 goto exit;
2353 }
2354
2355 authmode = psecuritypriv->ndisauthtype;
2356 rtw_set_802_11_authentication_mode23a(padapter, authmode);
2357
2358 /* rtw_set_802_11_encryption_mode(padapter,
2359 padapter->securitypriv.ndisencryptstatus); */
2360
2361 if (rtw_set_802_11_ssid23a(padapter, &ndis_ssid) == false) {
2362 ret = -1;
2363 goto exit;
2364 }
2365
2366 DBG_8723A("set ssid:dot11AuthAlgrthm =%d, dot11PrivacyAlgrthm =%d, "
2367 "dot118021XGrpPrivacy =%d\n", psecuritypriv->dot11AuthAlgrthm,
2368 psecuritypriv->dot11PrivacyAlgrthm,
2369 psecuritypriv->dot118021XGrpPrivacy);
2370
2371exit:
2372
2373 DBG_8723A("<=%s, ret %d\n", __func__, ret);
2374
2375 return ret;
2376}
2377
2378static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev,
2379 u16 reason_code)
2380{
2381 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2382
2383 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
2384
2385 rtw_set_roaming(padapter, 0);
2386
2387 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
2388 rtw_scan_abort23a(padapter);
2389 LeaveAllPowerSaveMode23a(padapter);
2390 rtw_disassoc_cmd23a(padapter, 500, false);
2391
2392 DBG_8723A("%s...call rtw_indicate_disconnect23a\n", __func__);
2393
2394 padapter->mlmepriv.not_indic_disco = true;
2395 rtw_indicate_disconnect23a(padapter);
2396 padapter->mlmepriv.not_indic_disco = false;
2397
2398 rtw_free_assoc_resources23a(padapter, 1);
2399 }
2400
2401 return 0;
2402}
2403
2404static int cfg80211_rtw_set_txpower(struct wiphy *wiphy,
2405 struct wireless_dev *wdev,
2406 enum nl80211_tx_power_setting type, int mbm)
2407{
2408 DBG_8723A("%s\n", __func__);
2409 return 0;
2410}
2411
2412static int cfg80211_rtw_get_txpower(struct wiphy *wiphy,
2413 struct wireless_dev *wdev, int *dbm)
2414{
2415 DBG_8723A("%s\n", __func__);
2416 *dbm = (12);
2417 return 0;
2418}
2419
2420inline bool rtw_cfg80211_pwr_mgmt(struct rtw_adapter *adapter)
2421{
2422 struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(adapter->rtw_wdev);
2423 return rtw_wdev_priv->power_mgmt;
2424}
2425
2426static int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy,
2427 struct net_device *ndev,
2428 bool enabled, int timeout)
2429{
2430 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2431 struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(padapter->rtw_wdev);
2432
2433 DBG_8723A(FUNC_NDEV_FMT " enabled:%u, timeout:%d\n",
2434 FUNC_NDEV_ARG(ndev), enabled, timeout);
2435
2436 rtw_wdev_priv->power_mgmt = enabled;
2437
2438 if (!enabled)
2439 LPS_Leave23a(padapter);
2440
2441 return 0;
2442}
2443
2444static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,
2445 struct net_device *netdev,
2446 struct cfg80211_pmksa *pmksa)
2447{
2448 u8 index, blInserted = false;
2449 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2450 struct security_priv *psecuritypriv = &padapter->securitypriv;
2451 u8 strZeroMacAddress[ETH_ALEN] = { 0x00 };
2452
2453 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(netdev));
2454
2455 if (!memcmp(pmksa->bssid, strZeroMacAddress, ETH_ALEN)) {
2456 return -EINVAL;
2457 }
2458
2459 blInserted = false;
2460
2461 /* overwrite PMKID */
2462 for (index = 0; index < NUM_PMKID_CACHE; index++) {
2463 if (!memcmp(psecuritypriv->PMKIDList[index].Bssid,
2464 pmksa->bssid, ETH_ALEN)) {
2465 /* BSSID is matched, the same AP => rewrite with
2466 new PMKID. */
2467 DBG_8723A(FUNC_NDEV_FMT
2468 " BSSID exists in the PMKList.\n",
2469 FUNC_NDEV_ARG(netdev));
2470
2471 memcpy(psecuritypriv->PMKIDList[index].PMKID,
2472 pmksa->pmkid, WLAN_PMKID_LEN);
2473 psecuritypriv->PMKIDList[index].bUsed = true;
2474 psecuritypriv->PMKIDIndex = index + 1;
2475 blInserted = true;
2476 break;
2477 }
2478 }
2479
2480 if (!blInserted) {
2481 /* Find a new entry */
2482 DBG_8723A(FUNC_NDEV_FMT
2483 " Use the new entry index = %d for this PMKID.\n",
2484 FUNC_NDEV_ARG(netdev), psecuritypriv->PMKIDIndex);
2485
2486 memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2487 Bssid, pmksa->bssid, ETH_ALEN);
2488 memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2489 PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2490
2491 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed =
2492 true;
2493 psecuritypriv->PMKIDIndex++;
2494 if (psecuritypriv->PMKIDIndex == 16) {
2495 psecuritypriv->PMKIDIndex = 0;
2496 }
2497 }
2498
2499 return 0;
2500}
2501
2502static int cfg80211_rtw_del_pmksa(struct wiphy *wiphy,
2503 struct net_device *netdev,
2504 struct cfg80211_pmksa *pmksa)
2505{
2506 u8 index, bMatched = false;
2507 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2508 struct security_priv *psecuritypriv = &padapter->securitypriv;
2509
2510 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(netdev));
2511
2512 for (index = 0; index < NUM_PMKID_CACHE; index++) {
2513 if (!memcmp(psecuritypriv->PMKIDList[index].Bssid,
2514 pmksa->bssid, ETH_ALEN)) {
2515 /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
2516 memset(psecuritypriv->PMKIDList[index].Bssid, 0x00,
2517 ETH_ALEN);
2518 memset(psecuritypriv->PMKIDList[index].PMKID, 0x00,
2519 WLAN_PMKID_LEN);
2520 psecuritypriv->PMKIDList[index].bUsed = false;
2521 bMatched = true;
2522 break;
2523 }
2524 }
2525
2526 if (false == bMatched) {
2527 DBG_8723A(FUNC_NDEV_FMT " do not have matched BSSID\n",
2528 FUNC_NDEV_ARG(netdev));
2529 return -EINVAL;
2530 }
2531
2532 return 0;
2533}
2534
2535static int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy,
2536 struct net_device *netdev)
2537{
2538 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2539 struct security_priv *psecuritypriv = &padapter->securitypriv;
2540
2541 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(netdev));
2542
2543 memset(&psecuritypriv->PMKIDList[0], 0x00,
2544 sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
2545 psecuritypriv->PMKIDIndex = 0;
2546
2547 return 0;
2548}
2549
2550#ifdef CONFIG_8723AU_AP_MODE
2551void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter,
2552 u8 *pmgmt_frame, uint frame_len)
2553{
2554 s32 freq;
2555 int channel;
2556 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2557 struct net_device *ndev = padapter->pnetdev;
2558
2559 DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2560
2561#if defined(RTW_USE_CFG80211_STA_EVENT)
2562 {
2563 struct station_info sinfo;
2564 u8 ie_offset;
2565 if (ieee80211_is_assoc_req(hdr->frame_control))
2566 ie_offset = _ASOCREQ_IE_OFFSET_;
2567 else /* WIFI_REASSOCREQ */
2568 ie_offset = _REASOCREQ_IE_OFFSET_;
2569
2570 sinfo.filled = 0;
2571 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
2572 sinfo.assoc_req_ies = pmgmt_frame + WLAN_HDR_A3_LEN + ie_offset;
2573 sinfo.assoc_req_ies_len =
2574 frame_len - WLAN_HDR_A3_LEN - ie_offset;
2575 cfg80211_new_sta(ndev, hdr->addr2, &sinfo, GFP_ATOMIC);
2576 }
2577#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2578 channel = pmlmeext->cur_channel;
2579 if (channel <= RTW_CH_MAX_2G_CHANNEL)
2580 freq = ieee80211_channel_to_frequency(channel,
2581 IEEE80211_BAND_2GHZ);
2582 else
2583 freq = ieee80211_channel_to_frequency(channel,
2584 IEEE80211_BAND_5GHZ);
2585
2586 rtw_cfg80211_rx_mgmt(padapter, freq, 0, pmgmt_frame, frame_len,
2587 GFP_ATOMIC);
2588#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2589}
2590
2591void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter,
2592 unsigned char *da,
2593 unsigned short reason)
2594{
2595 s32 freq;
2596 int channel;
2597 u8 *pmgmt_frame;
2598 uint frame_len;
2599 struct ieee80211_hdr *pwlanhdr;
2600 unsigned short *fctrl;
2601 u8 mgmt_buf[128] = { 0 };
2602 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2603 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2604 struct net_device *ndev = padapter->pnetdev;
2605
2606 DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2607
2608#if defined(RTW_USE_CFG80211_STA_EVENT)
2609 cfg80211_del_sta(ndev, da, GFP_ATOMIC);
2610#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2611 channel = pmlmeext->cur_channel;
2612 if (channel <= RTW_CH_MAX_2G_CHANNEL)
2613 freq = ieee80211_channel_to_frequency(channel,
2614 IEEE80211_BAND_2GHZ);
2615 else
2616 freq = ieee80211_channel_to_frequency(channel,
2617 IEEE80211_BAND_5GHZ);
2618
2619 pmgmt_frame = mgmt_buf;
2620 pwlanhdr = (struct ieee80211_hdr *)pmgmt_frame;
2621
2622 fctrl = &pwlanhdr->frame_control;
2623 *(fctrl) = 0;
2624
2625 memcpy(pwlanhdr->addr1, myid(&padapter->eeprompriv), ETH_ALEN);
2626 memcpy(pwlanhdr->addr2, da, ETH_ALEN);
2627 memcpy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
2628
2629 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2630 pmlmeext->mgnt_seq++;
2631 SetFrameSubType(pmgmt_frame, WIFI_DEAUTH);
2632
2633 pmgmt_frame += sizeof(struct ieee80211_hdr_3addr);
2634 frame_len = sizeof(struct ieee80211_hdr_3addr);
2635
2636 reason = cpu_to_le16(reason);
2637 pmgmt_frame = rtw_set_fixed_ie23a(pmgmt_frame,
2638 WLAN_REASON_PREV_AUTH_NOT_VALID,
2639 (unsigned char *)&reason, &frame_len);
2640
2641 rtw_cfg80211_rx_mgmt(padapter, freq, 0, mgmt_buf, frame_len,
2642 GFP_ATOMIC);
2643#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2644}
2645
2646static int rtw_cfg80211_monitor_if_open(struct net_device *ndev)
2647{
2648 int ret = 0;
2649
2650 DBG_8723A("%s\n", __func__);
2651
2652 return ret;
2653}
2654
2655static int rtw_cfg80211_monitor_if_close(struct net_device *ndev)
2656{
2657 int ret = 0;
2658
2659 DBG_8723A("%s\n", __func__);
2660
2661 return ret;
2662}
2663
2664static int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb,
2665 struct net_device *ndev)
2666{
2667 int ret = 0;
2668 int rtap_len;
2669 int qos_len = 0;
2670 int dot11_hdr_len = 24;
2671 int snap_len = 6;
2672 unsigned char *pdata;
2673 unsigned char src_mac_addr[6];
2674 unsigned char dst_mac_addr[6];
2675 struct ieee80211_hdr *dot11_hdr;
2676 struct ieee80211_radiotap_header *rtap_hdr;
2677 struct rtw_adapter *padapter = netdev_priv(ndev);
2678
2679 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
2680
2681 if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
2682 goto fail;
2683
2684 rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
2685 if (unlikely(rtap_hdr->it_version))
2686 goto fail;
2687
2688 rtap_len = ieee80211_get_radiotap_len(skb->data);
2689 if (unlikely(skb->len < rtap_len))
2690 goto fail;
2691
2692 if (rtap_len != 14) {
2693 DBG_8723A("radiotap len (should be 14): %d\n", rtap_len);
2694 goto fail;
2695 }
2696
2697 /* Skip the ratio tap header */
2698 skb_pull(skb, rtap_len);
2699
2700 dot11_hdr = (struct ieee80211_hdr *)skb->data;
2701 /* Check if the QoS bit is set */
2702 if (ieee80211_is_data(dot11_hdr->frame_control)) {
2703 /* Check if this ia a Wireless Distribution System (WDS) frame
2704 * which has 4 MAC addresses
2705 */
2706 if (ieee80211_is_data_qos(dot11_hdr->frame_control))
2707 qos_len = IEEE80211_QOS_CTL_LEN;
2708 if (ieee80211_has_a4(dot11_hdr->frame_control))
2709 dot11_hdr_len += 6;
2710
2711 memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
2712 memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
2713
2714 /*
2715 * Skip the 802.11 header, QoS (if any) and SNAP,
2716 * but leave spaces for two MAC addresses
2717 */
2718 skb_pull(skb, dot11_hdr_len + qos_len + snap_len -
2719 ETH_ALEN * 2);
2720 pdata = (unsigned char *)skb->data;
2721 memcpy(pdata, dst_mac_addr, ETH_ALEN);
2722 memcpy(pdata + ETH_ALEN, src_mac_addr, ETH_ALEN);
2723
2724 DBG_8723A("should be eapol packet\n");
2725
2726 /* Use the real net device to transmit the packet */
2727 ret = rtw_xmit23a_entry23a(skb, padapter->pnetdev);
2728
2729 return ret;
2730
2731 } else if (ieee80211_is_action(dot11_hdr->frame_control)) {
2732 /* only for action frames */
2733 struct xmit_frame *pmgntframe;
2734 struct pkt_attrib *pattrib;
2735 unsigned char *pframe;
2736 /* u8 category, action, OUI_Subtype, dialogToken = 0; */
2737 /* unsigned char *frame_body; */
2738 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2739 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2740 u32 len = skb->len;
2741 u8 category, action;
2742#ifdef CONFIG_8723AU_P2P
2743 int type = -1;
2744#endif
2745
2746 if (rtw_action_frame_parse23a(skb->data, len, &category,
2747 &action) == false) {
2748 DBG_8723A(FUNC_NDEV_FMT " frame_control:0x%x\n",
2749 FUNC_NDEV_ARG(ndev),
2750 le16_to_cpu(dot11_hdr->frame_control));
2751 goto fail;
2752 }
2753
2754 DBG_8723A("RTW_Tx:da =" MAC_FMT " via " FUNC_NDEV_FMT "\n",
2755 MAC_ARG(dot11_hdr->addr1), FUNC_NDEV_ARG(ndev));
2756#ifdef CONFIG_8723AU_P2P
2757 type = rtw_p2p_check_frames(padapter, skb->data, len, true);
2758 if (type >= 0)
2759 goto dump;
2760#endif
2761 if (category == WLAN_CATEGORY_PUBLIC)
2762 DBG_8723A("RTW_Tx:%s\n", action_public_str23a(action));
2763 else
2764 DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category,
2765 action);
2766#ifdef CONFIG_8723AU_P2P
2767dump:
2768#endif
2769 /* starting alloc mgmt frame to dump it */
2770 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2771 if (pmgntframe == NULL)
2772 goto fail;
2773
2774 /* update attribute */
2775 pattrib = &pmgntframe->attrib;
2776 update_mgntframe_attrib23a(padapter, pattrib);
2777 pattrib->retry_ctrl = false;
2778
2779 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2780
2781 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2782
2783 memcpy(pframe, skb->data, len);
2784#ifdef CONFIG_8723AU_P2P
2785 if (type >= 0) {
2786 struct wifi_display_info *pwfd_info;
2787
2788 pwfd_info = padapter->wdinfo.wfd_info;
2789
2790 if (pwfd_info->wfd_enable)
2791 rtw_append_wfd_ie(padapter, pframe, &len);
2792 }
2793#endif /* CONFIG_8723AU_P2P */
2794 pattrib->pktlen = len;
2795
2796 /* update seq number */
2797 pmlmeext->mgnt_seq = le16_to_cpu(dot11_hdr->seq_ctrl) >> 4;
2798 pattrib->seqnum = pmlmeext->mgnt_seq;
2799 pmlmeext->mgnt_seq++;
2800
2801 pattrib->last_txcmdsz = pattrib->pktlen;
2802
2803 dump_mgntframe23a(padapter, pmgntframe);
2804 }
2805
2806fail:
2807
2808 dev_kfree_skb(skb);
2809
2810 return 0;
2811}
2812
2813static int
2814rtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr)
2815{
2816 int ret = 0;
2817
2818 DBG_8723A("%s\n", __func__);
2819
2820 return ret;
2821}
2822
2823static const struct net_device_ops rtw_cfg80211_monitor_if_ops = {
2824 .ndo_open = rtw_cfg80211_monitor_if_open,
2825 .ndo_stop = rtw_cfg80211_monitor_if_close,
2826 .ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,
2827 .ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address,
2828};
2829
2830static int rtw_cfg80211_add_monitor_if(struct rtw_adapter *padapter, char *name,
2831 struct net_device **ndev)
2832{
2833 int ret = 0;
2834 struct net_device *mon_ndev = NULL;
2835 struct wireless_dev *mon_wdev = NULL;
2836 struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
2837
2838 if (!name) {
2839 DBG_8723A(FUNC_ADPT_FMT " without specific name\n",
2840 FUNC_ADPT_ARG(padapter));
2841 ret = -EINVAL;
2842 goto out;
2843 }
2844
2845 if (pwdev_priv->pmon_ndev) {
2846 DBG_8723A(FUNC_ADPT_FMT " monitor interface exist: " NDEV_FMT
2847 "\n", FUNC_ADPT_ARG(padapter),
2848 NDEV_ARG(pwdev_priv->pmon_ndev));
2849 ret = -EBUSY;
2850 goto out;
2851 }
2852
2853 mon_ndev = alloc_etherdev(sizeof(struct rtw_adapter));
2854 if (!mon_ndev) {
2855 DBG_8723A(FUNC_ADPT_FMT " allocate ndev fail\n",
2856 FUNC_ADPT_ARG(padapter));
2857 ret = -ENOMEM;
2858 goto out;
2859 }
2860
2861 mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP;
2862 strncpy(mon_ndev->name, name, IFNAMSIZ);
2863 mon_ndev->name[IFNAMSIZ - 1] = 0;
2864 mon_ndev->destructor = rtw_ndev_destructor;
2865
2866 mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;
2867
2868 /* wdev */
2869 mon_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
2870 if (!mon_wdev) {
2871 DBG_8723A(FUNC_ADPT_FMT " allocate mon_wdev fail\n",
2872 FUNC_ADPT_ARG(padapter));
2873 ret = -ENOMEM;
2874 goto out;
2875 }
2876
2877 mon_wdev->wiphy = padapter->rtw_wdev->wiphy;
2878 mon_wdev->netdev = mon_ndev;
2879 mon_wdev->iftype = NL80211_IFTYPE_MONITOR;
2880 mon_ndev->ieee80211_ptr = mon_wdev;
2881
2882 ret = register_netdevice(mon_ndev);
2883 if (ret) {
2884 goto out;
2885 }
2886
2887 *ndev = pwdev_priv->pmon_ndev = mon_ndev;
2888 memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ + 1);
2889
2890out:
2891 if (ret) {
2892 kfree(mon_wdev);
2893 mon_wdev = NULL;
2894 }
2895
2896 if (ret && mon_ndev) {
2897 free_netdev(mon_ndev);
2898 *ndev = mon_ndev = NULL;
2899 }
2900
2901 return ret;
2902}
2903
2904static struct wireless_dev *
2905cfg80211_rtw_add_virtual_intf(struct wiphy *wiphy, const char *name,
2906 enum nl80211_iftype type, u32 *flags,
2907 struct vif_params *params)
2908{
2909 int ret = 0;
2910 struct net_device *ndev = NULL;
2911 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2912
2913 DBG_8723A(FUNC_ADPT_FMT " wiphy:%s, name:%s, type:%d\n",
2914 FUNC_ADPT_ARG(padapter), wiphy_name(wiphy), name, type);
2915
2916 switch (type) {
2917 case NL80211_IFTYPE_ADHOC:
2918 case NL80211_IFTYPE_AP_VLAN:
2919 case NL80211_IFTYPE_WDS:
2920 case NL80211_IFTYPE_MESH_POINT:
2921 ret = -ENODEV;
2922 break;
2923 case NL80211_IFTYPE_MONITOR:
2924 ret =
2925 rtw_cfg80211_add_monitor_if(padapter, (char *)name, &ndev);
2926 break;
2927
2928 case NL80211_IFTYPE_P2P_CLIENT:
2929 case NL80211_IFTYPE_STATION:
2930 ret = -ENODEV;
2931 break;
2932
2933 case NL80211_IFTYPE_P2P_GO:
2934 case NL80211_IFTYPE_AP:
2935 ret = -ENODEV;
2936 break;
2937 default:
2938 ret = -ENODEV;
2939 DBG_8723A("Unsupported interface type\n");
2940 break;
2941 }
2942
2943 DBG_8723A(FUNC_ADPT_FMT " ndev:%p, ret:%d\n", FUNC_ADPT_ARG(padapter),
2944 ndev, ret);
2945
2946 return ndev ? ndev->ieee80211_ptr : ERR_PTR(ret);
2947}
2948
2949static int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy,
2950 struct wireless_dev *wdev)
2951{
2952 struct rtw_wdev_priv *pwdev_priv =
2953 (struct rtw_wdev_priv *)wiphy_priv(wiphy);
2954 struct net_device *ndev;
2955 ndev = wdev ? wdev->netdev : NULL;
2956
2957 if (!ndev)
2958 goto exit;
2959
2960 unregister_netdevice(ndev);
2961
2962 if (ndev == pwdev_priv->pmon_ndev) {
2963 pwdev_priv->pmon_ndev = NULL;
2964 pwdev_priv->ifname_mon[0] = '\0';
2965 DBG_8723A(FUNC_NDEV_FMT " remove monitor interface\n",
2966 FUNC_NDEV_ARG(ndev));
2967 }
2968
2969exit:
2970 return 0;
2971}
2972
2973static int rtw_add_beacon(struct rtw_adapter *adapter, const u8 *head,
2974 size_t head_len, const u8 *tail, size_t tail_len)
2975{
2976 int ret = 0;
2977 u8 *pbuf = NULL;
2978 uint len, wps_ielen = 0;
2979#ifdef CONFIG_8723AU_P2P
2980 uint p2p_ielen = 0;
2981 u8 got_p2p_ie = false;
2982#endif
2983 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2984 /* struct sta_priv *pstapriv = &padapter->stapriv; */
2985
2986 DBG_8723A("%s beacon_head_len =%zu, beacon_tail_len =%zu\n",
2987 __func__, head_len, tail_len);
2988
2989 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2990 return -EINVAL;
2991
2992 if (head_len < 24)
2993 return -EINVAL;
2994
2995 pbuf = kzalloc(head_len + tail_len, GFP_KERNEL);
2996 if (!pbuf)
2997 return -ENOMEM;
2998 /* 24 = beacon header len. */
2999 memcpy(pbuf, (void *)head + 24, head_len - 24);
3000 memcpy(pbuf + head_len - 24, (void *)tail, tail_len);
3001
3002 len = head_len + tail_len - 24;
3003
3004 /* check wps ie if inclued */
3005 if (rtw_get_wps_ie23a
3006 (pbuf + _FIXED_IE_LENGTH_, len - _FIXED_IE_LENGTH_, NULL,
3007 &wps_ielen))
3008 DBG_8723A("add bcn, wps_ielen =%d\n", wps_ielen);
3009
3010#ifdef CONFIG_8723AU_P2P
3011 /* check p2p ie if inclued */
3012 if (rtw_get_p2p_ie23a
3013 (pbuf + _FIXED_IE_LENGTH_, len - _FIXED_IE_LENGTH_, NULL,
3014 &p2p_ielen)) {
3015 DBG_8723A("got p2p_ie, len =%d\n", p2p_ielen);
3016 got_p2p_ie = true;
3017 }
3018#endif
3019
3020 /* pbss_network->IEs will not include p2p_ie, wfd ie */
3021 rtw_ies_remove_ie23a(pbuf, &len, _BEACON_IE_OFFSET_, _VENDOR_SPECIFIC_IE_,
3022 P2P_OUI23A, 4);
3023 rtw_ies_remove_ie23a(pbuf, &len, _BEACON_IE_OFFSET_, _VENDOR_SPECIFIC_IE_,
3024 WFD_OUI23A, 4);
3025
3026 if (rtw_check_beacon_data23a(adapter, pbuf, len) == _SUCCESS) {
3027#ifdef CONFIG_8723AU_P2P
3028 /* check p2p if enable */
3029 if (got_p2p_ie == true) {
3030 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
3031 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3032
3033 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
3034 DBG_8723A("Enable P2P function for the first "
3035 "time\n");
3036 rtw_p2p_enable23a(adapter, P2P_ROLE_GO);
3037 wdev_to_priv(adapter->rtw_wdev)->p2p_enabled =
3038 true;
3039 } else {
3040 del_timer_sync(&pwdinfo->find_phase_timer);
3041 del_timer_sync(&pwdinfo->
3042 restore_p2p_state_timer);
3043 del_timer_sync(&pwdinfo->pre_tx_scan_timer);
3044
3045 DBG_8723A("enter GO Mode, p2p_ielen =%d\n",
3046 p2p_ielen);
3047
3048 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3049 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3050 pwdinfo->intent = 15;
3051 }
3052
3053 pwdinfo->operating_channel = pmlmeext->cur_channel;
3054 }
3055#endif /* CONFIG_8723AU_P2P */
3056
3057 ret = 0;
3058
3059 } else {
3060 ret = -EINVAL;
3061 }
3062
3063 kfree(pbuf);
3064
3065 return ret;
3066}
3067
3068static int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,
3069 struct cfg80211_ap_settings *settings)
3070{
3071 int ret = 0;
3072 struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
3073
3074 DBG_8723A(FUNC_NDEV_FMT " hidden_ssid:%d, auth_type:%d\n",
3075 FUNC_NDEV_ARG(ndev), settings->hidden_ssid,
3076 settings->auth_type);
3077
3078 ret = rtw_add_beacon(adapter, settings->beacon.head,
3079 settings->beacon.head_len, settings->beacon.tail,
3080 settings->beacon.tail_len);
3081
3082 adapter->mlmeextpriv.mlmext_info.hidden_ssid_mode =
3083 settings->hidden_ssid;
3084
3085 if (settings->ssid && settings->ssid_len) {
3086 struct wlan_bssid_ex *pbss_network =
3087 &adapter->mlmepriv.cur_network.network;
3088 struct wlan_bssid_ex *pbss_network_ext =
3089 &adapter->mlmeextpriv.mlmext_info.network;
3090
3091 if (0)
3092 DBG_8723A(FUNC_ADPT_FMT
3093 " ssid:(%s,%d), from ie:(%s,%d)\n",
3094 FUNC_ADPT_ARG(adapter), settings->ssid,
3095 (int)settings->ssid_len,
3096 pbss_network->Ssid.ssid,
3097 pbss_network->Ssid.ssid_len);
3098
3099 memcpy(pbss_network->Ssid.ssid, (void *)settings->ssid,
3100 settings->ssid_len);
3101 pbss_network->Ssid.ssid_len = settings->ssid_len;
3102 memcpy(pbss_network_ext->Ssid.ssid, (void *)settings->ssid,
3103 settings->ssid_len);
3104 pbss_network_ext->Ssid.ssid_len = settings->ssid_len;
3105
3106 if (0)
3107 DBG_8723A(FUNC_ADPT_FMT
3108 " after ssid:(%s,%d), (%s,%d)\n",
3109 FUNC_ADPT_ARG(adapter),
3110 pbss_network->Ssid.ssid,
3111 pbss_network->Ssid.ssid_len,
3112 pbss_network_ext->Ssid.ssid,
3113 pbss_network_ext->Ssid.ssid_len);
3114 }
3115
3116 return ret;
3117}
3118
3119static int cfg80211_rtw_change_beacon(struct wiphy *wiphy,
3120 struct net_device *ndev,
3121 struct cfg80211_beacon_data *info)
3122{
3123 int ret = 0;
3124 struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
3125
3126 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3127
3128 ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail,
3129 info->tail_len);
3130
3131 return ret;
3132}
3133
3134static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
3135{
3136 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3137 return 0;
3138}
3139
3140static int cfg80211_rtw_add_station(struct wiphy *wiphy,
3141 struct net_device *ndev, u8 *mac,
3142 struct station_parameters *params)
3143{
3144 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3145
3146 return 0;
3147}
3148
3149static int cfg80211_rtw_del_station(struct wiphy *wiphy,
3150 struct net_device *ndev, u8 *mac)
3151{
3152 int ret = 0;
3153 struct list_head *phead, *plist, *ptmp;
3154 u8 updated = 0;
3155 struct sta_info *psta;
3156 struct rtw_adapter *padapter = netdev_priv(ndev);
3157 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3158 struct sta_priv *pstapriv = &padapter->stapriv;
3159
3160 DBG_8723A("+" FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3161
3162 if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true) {
3163 DBG_8723A("%s, fw_state != FW_LINKED|WIFI_AP_STATE\n",
3164 __func__);
3165 return -EINVAL;
3166 }
3167
3168 if (!mac) {
3169 DBG_8723A("flush all sta, and cam_entry\n");
3170
3171 flush_all_cam_entry23a(padapter); /* clear CAM */
3172
3173 ret = rtw_sta_flush23a(padapter);
3174
3175 return ret;
3176 }
3177
3178 DBG_8723A("free sta macaddr =" MAC_FMT "\n", MAC_ARG(mac));
3179
3180 if (is_broadcast_ether_addr(mac))
3181 return -EINVAL;
3182
3183 spin_lock_bh(&pstapriv->asoc_list_lock);
3184
3185 phead = &pstapriv->asoc_list;
3186
3187 /* check asoc_queue */
3188 list_for_each_safe(plist, ptmp, phead) {
3189 psta = container_of(plist, struct sta_info, asoc_list);
3190
3191 if (!memcmp(mac, psta->hwaddr, ETH_ALEN)) {
3192 if (psta->dot8021xalg == 1 &&
3193 psta->bpairwise_key_installed == false) {
3194 DBG_8723A("%s, sta's dot8021xalg = 1 and "
3195 "key_installed = false\n", __func__);
3196 } else {
3197 DBG_8723A("free psta =%p, aid =%d\n", psta,
3198 psta->aid);
3199
3200 list_del_init(&psta->asoc_list);
3201 pstapriv->asoc_list_cnt--;
3202
3203 /* spin_unlock_bh(&pstapriv->asoc_list_lock); */
3204 updated =
3205 ap_free_sta23a(padapter, psta, true,
3206 WLAN_REASON_DEAUTH_LEAVING);
3207 /* spin_lock_bh(&pstapriv->asoc_list_lock); */
3208
3209 psta = NULL;
3210
3211 break;
3212 }
3213 }
3214 }
3215
3216 spin_unlock_bh(&pstapriv->asoc_list_lock);
3217
3218 associated_clients_update23a(padapter, updated);
3219
3220 DBG_8723A("-" FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3221
3222 return ret;
3223}
3224
3225static int cfg80211_rtw_change_station(struct wiphy *wiphy,
3226 struct net_device *ndev, u8 *mac,
3227 struct station_parameters *params)
3228{
3229 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3230 return 0;
3231}
3232
3233static int cfg80211_rtw_dump_station(struct wiphy *wiphy,
3234 struct net_device *ndev, int idx, u8 *mac,
3235 struct station_info *sinfo)
3236{
3237 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3238
3239 /* TODO: dump scanned queue */
3240
3241 return -ENOENT;
3242}
3243
3244static int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev,
3245 struct bss_parameters *params)
3246{
3247 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3248 return 0;
3249}
3250#endif /* CONFIG_8723AU_AP_MODE */
3251
3252void rtw_cfg80211_rx_action_p2p(struct rtw_adapter *padapter, u8 *pmgmt_frame,
3253 uint frame_len)
3254{
3255#ifdef CONFIG_8723AU_P2P
3256 int type;
3257#endif
3258 s32 freq;
3259 int channel;
3260 u8 category, action;
3261
3262 channel = rtw_get_oper_ch23a(padapter);
3263
3264 DBG_8723A("RTW_Rx:cur_ch =%d\n", channel);
3265#ifdef CONFIG_8723AU_P2P
3266 type = rtw_p2p_check_frames(padapter, pmgmt_frame, frame_len, false);
3267 if (type >= 0)
3268 goto indicate;
3269#endif
3270 rtw_action_frame_parse23a(pmgmt_frame, frame_len, &category, &action);
3271 DBG_8723A("RTW_Rx:category(%u), action(%u)\n", category, action);
3272
3273#ifdef CONFIG_8723AU_P2P
3274indicate:
3275#endif
3276 if (channel <= RTW_CH_MAX_2G_CHANNEL)
3277 freq = ieee80211_channel_to_frequency(channel,
3278 IEEE80211_BAND_2GHZ);
3279 else
3280 freq = ieee80211_channel_to_frequency(channel,
3281 IEEE80211_BAND_5GHZ);
3282
3283 rtw_cfg80211_rx_mgmt(padapter, freq, 0, pmgmt_frame, frame_len,
3284 GFP_ATOMIC);
3285}
3286
3287void rtw_cfg80211_rx_p2p_action_public(struct rtw_adapter *padapter,
3288 u8 *pmgmt_frame, uint frame_len)
3289{
3290#ifdef CONFIG_8723AU_P2P
3291 int type;
3292#endif
3293 s32 freq;
3294 int channel;
3295 u8 category, action;
3296
3297 channel = rtw_get_oper_ch23a(padapter);
3298
3299 DBG_8723A("RTW_Rx:cur_ch =%d\n", channel);
3300#ifdef CONFIG_8723AU_P2P
3301 type = rtw_p2p_check_frames(padapter, pmgmt_frame, frame_len, false);
3302 if (type >= 0) {
3303 switch (type) {
3304 case P2P_GO_NEGO_CONF:
3305 case P2P_PROVISION_DISC_RESP:
3306 rtw_clear_scan_deny(padapter);
3307 }
3308 goto indicate;
3309 }
3310#endif
3311 rtw_action_frame_parse23a(pmgmt_frame, frame_len, &category, &action);
3312 DBG_8723A("RTW_Rx:category(%u), action(%u)\n", category, action);
3313
3314#ifdef CONFIG_8723AU_P2P
3315indicate:
3316#endif
3317 if (channel <= RTW_CH_MAX_2G_CHANNEL)
3318 freq = ieee80211_channel_to_frequency(channel,
3319 IEEE80211_BAND_2GHZ);
3320 else
3321 freq = ieee80211_channel_to_frequency(channel,
3322 IEEE80211_BAND_5GHZ);
3323
3324 rtw_cfg80211_rx_mgmt(padapter, freq, 0, pmgmt_frame, frame_len,
3325 GFP_ATOMIC);
3326}
3327
3328void rtw_cfg80211_rx_action(struct rtw_adapter *adapter, u8 *frame,
3329 uint frame_len, const char *msg)
3330{
3331 s32 freq;
3332 int channel;
3333 u8 category, action;
3334
3335 channel = rtw_get_oper_ch23a(adapter);
3336
3337 rtw_action_frame_parse23a(frame, frame_len, &category, &action);
3338
3339 DBG_8723A("RTW_Rx:cur_ch =%d\n", channel);
3340 if (msg)
3341 DBG_8723A("RTW_Rx:%s\n", msg);
3342 else
3343 DBG_8723A("RTW_Rx:category(%u), action(%u)\n", category,
3344 action);
3345
3346 if (channel <= RTW_CH_MAX_2G_CHANNEL)
3347 freq = ieee80211_channel_to_frequency(channel,
3348 IEEE80211_BAND_2GHZ);
3349 else
3350 freq = ieee80211_channel_to_frequency(channel,
3351 IEEE80211_BAND_5GHZ);
3352
3353 rtw_cfg80211_rx_mgmt(adapter, freq, 0, frame, frame_len, GFP_ATOMIC);
3354}
3355
3356#ifdef CONFIG_8723AU_P2P
3357void rtw_cfg80211_issue_p2p_provision_request23a(struct rtw_adapter *padapter,
3358 const u8 *buf, size_t len)
3359{
3360 u16 wps_devicepassword_id = 0x0000;
3361 uint wps_devicepassword_id_len = 0;
3362 u8 wpsie[255] = { 0x00 }, p2p_ie[255] = { 0x00 };
3363 uint p2p_ielen = 0;
3364 uint wpsielen = 0;
3365 u32 devinfo_contentlen = 0;
3366 u8 devinfo_content[64] = { 0x00 };
3367 u16 capability = 0;
3368 uint capability_len = 0;
3369
3370 unsigned char category = WLAN_CATEGORY_PUBLIC;
3371 u8 action = P2P_PUB_ACTION_ACTION;
3372 u8 dialogToken = 1;
3373 u32 p2poui = cpu_to_be32(P2POUI);
3374 u8 oui_subtype = P2P_PROVISION_DISC_REQ;
3375 u32 p2pielen = 0;
3376#ifdef CONFIG_8723AU_P2P
3377 u32 wfdielen = 0;
3378#endif /* CONFIG_8723AU_P2P */
3379
3380 struct xmit_frame *pmgntframe;
3381 struct pkt_attrib *pattrib;
3382 unsigned char *pframe;
3383 struct ieee80211_hdr *pwlanhdr, *hdr;
3384 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3385 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3386
3387 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3388 u8 *frame_body =
3389 (unsigned char *)(buf + sizeof(struct ieee80211_hdr_3addr));
3390 size_t frame_body_len = len - sizeof(struct ieee80211_hdr_3addr);
3391
3392 DBG_8723A("[%s] In\n", __func__);
3393
3394 hdr = (struct ieee80211_hdr *)buf;
3395 /* prepare for building provision_request frame */
3396 memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, hdr->addr1, ETH_ALEN);
3397 memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, hdr->addr1, ETH_ALEN);
3398
3399 pwdinfo->tx_prov_disc_info.wps_config_method_request =
3400 WPS_CM_PUSH_BUTTON;
3401
3402 rtw_get_wps_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
3403 frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, wpsie,
3404 &wpsielen);
3405 rtw_get_wps_attr_content23a(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID,
3406 (u8 *)&wps_devicepassword_id,
3407 &wps_devicepassword_id_len);
3408 wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
3409
3410 switch (wps_devicepassword_id) {
3411 case WPS_DPID_PIN:
3412 pwdinfo->tx_prov_disc_info.wps_config_method_request =
3413 WPS_CM_LABEL;
3414 break;
3415 case WPS_DPID_USER_SPEC:
3416 pwdinfo->tx_prov_disc_info.wps_config_method_request =
3417 WPS_CM_DISPLYA;
3418 break;
3419 case WPS_DPID_MACHINE_SPEC:
3420 break;
3421 case WPS_DPID_REKEY:
3422 break;
3423 case WPS_DPID_PBC:
3424 pwdinfo->tx_prov_disc_info.wps_config_method_request =
3425 WPS_CM_PUSH_BUTTON;
3426 break;
3427 case WPS_DPID_REGISTRAR_SPEC:
3428 pwdinfo->tx_prov_disc_info.wps_config_method_request =
3429 WPS_CM_KEYPAD;
3430 break;
3431 default:
3432 break;
3433 }
3434
3435 if (rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
3436 frame_body_len - _PUBLIC_ACTION_IE_OFFSET_,
3437 p2p_ie, &p2p_ielen)) {
3438 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen,
3439 P2P_ATTR_DEVICE_INFO, devinfo_content,
3440 &devinfo_contentlen);
3441 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY,
3442 (u8 *)&capability, &capability_len);
3443 }
3444
3445 /* start to build provision_request frame */
3446 memset(wpsie, 0, sizeof(wpsie));
3447 memset(p2p_ie, 0, sizeof(p2p_ie));
3448 p2p_ielen = 0;
3449
3450 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3451 if (pmgntframe == NULL)
3452 return;
3453 /* update attribute */
3454 pattrib = &pmgntframe->attrib;
3455 update_mgntframe_attrib23a(padapter, pattrib);
3456
3457 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3458
3459 pframe = (u8 *) (pmgntframe->buf_addr) + TXDESC_OFFSET;
3460 pwlanhdr = (struct ieee80211_hdr *)pframe;
3461
3462 pwlanhdr->frame_control = 0;
3463
3464 memcpy(pwlanhdr->addr1, pwdinfo->tx_prov_disc_info.peerDevAddr,
3465 ETH_ALEN);
3466 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
3467 memcpy(pwlanhdr->addr3, pwdinfo->tx_prov_disc_info.peerDevAddr,
3468 ETH_ALEN);
3469
3470 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3471 pmlmeext->mgnt_seq++;
3472 SetFrameSubType(pframe, WIFI_ACTION);
3473
3474 pframe += sizeof(struct ieee80211_hdr_3addr);
3475 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3476
3477 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
3478 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
3479 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
3480 &pattrib->pktlen);
3481 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
3482 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
3483
3484 /* build_prov_disc_request_p2p_ie23a */
3485 /* P2P OUI */
3486 p2pielen = 0;
3487 p2p_ie[p2pielen++] = 0x50;
3488 p2p_ie[p2pielen++] = 0x6F;
3489 p2p_ie[p2pielen++] = 0x9A;
3490 p2p_ie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
3491
3492 /* Commented by Albert 20110301 */
3493 /* According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */
3494 /* 1. P2P Capability */
3495 /* 2. Device Info */
3496 /* 3. Group ID ( When joining an operating P2P Group ) */
3497
3498 /* P2P Capability ATTR */
3499 /* Type: */
3500 p2p_ie[p2pielen++] = P2P_ATTR_CAPABILITY;
3501
3502 /* Length: */
3503 put_unaligned_le16(0x0002, p2p_ie + p2pielen);
3504 p2pielen += 2;
3505
3506 /* Value: */
3507 /* Device Capability Bitmap, 1 byte */
3508 /* Group Capability Bitmap, 1 byte */
3509 memcpy(p2p_ie + p2pielen, &capability, 2);
3510 p2pielen += 2;
3511
3512 /* Device Info ATTR */
3513 /* Type: */
3514 p2p_ie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
3515
3516 /* Length: */
3517 put_unaligned_le16(devinfo_contentlen, p2p_ie + p2pielen);
3518 p2pielen += 2;
3519
3520 /* Value: */
3521 memcpy(p2p_ie + p2pielen, devinfo_content, devinfo_contentlen);
3522 p2pielen += devinfo_contentlen;
3523
3524 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
3525 (unsigned char *)p2p_ie, &p2p_ielen);
3526 pattrib->pktlen += p2p_ielen;
3527
3528 wpsielen = 0;
3529 /* WPS OUI */
3530 *(u32 *)(wpsie) = cpu_to_be32(WPSOUI);
3531 wpsielen += 4;
3532
3533 /* WPS version */
3534 /* Type: */
3535 *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3536 wpsielen += 2;
3537
3538 /* Length: */
3539 *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3540 wpsielen += 2;
3541
3542 /* Value: */
3543 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
3544
3545 /* Config Method */
3546 /* Type: */
3547 *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3548 wpsielen += 2;
3549
3550 /* Length: */
3551 *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3552 wpsielen += 2;
3553
3554 /* Value: */
3555 *(u16 *)(wpsie + wpsielen) =
3556 cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);
3557 wpsielen += 2;
3558
3559 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
3560 (unsigned char *)wpsie, &pattrib->pktlen);
3561
3562#ifdef CONFIG_8723AU_P2P
3563 wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);
3564 pframe += wfdielen;
3565 pattrib->pktlen += wfdielen;
3566#endif /* CONFIG_8723AU_P2P */
3567
3568 pattrib->last_txcmdsz = pattrib->pktlen;
3569
3570 /* dump_mgntframe23a(padapter, pmgntframe); */
3571 if (dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe) != _SUCCESS)
3572 DBG_8723A("%s, ack to\n", __func__);
3573}
3574
3575static s32 cfg80211_rtw_remain_on_channel(struct wiphy *wiphy,
3576 struct wireless_dev *wdev,
3577 struct ieee80211_channel *channel,
3578 unsigned int duration, u64 *cookie)
3579{
3580 s32 err = 0;
3581 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
3582 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3583 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3584 struct cfg80211_wifidirect_info *pcfg80211_wdinfo =
3585 &padapter->cfg80211_wdinfo;
3586 u8 remain_ch =
3587 (u8) ieee80211_frequency_to_channel(channel->center_freq);
3588 u8 ready_on_channel = false;
3589
3590 DBG_8723A(FUNC_ADPT_FMT " ch:%u duration:%d\n", FUNC_ADPT_ARG(padapter),
3591 remain_ch, duration);
3592
3593 if (pcfg80211_wdinfo->is_ro_ch == true) {
3594 DBG_8723A("%s, cancel ro ch timer\n", __func__);
3595
3596 del_timer_sync(&padapter->cfg80211_wdinfo.remain_on_ch_timer);
3597
3598#ifdef CONFIG_8723AU_P2P
3599 p2p_protocol_wk_hdl23a(padapter, P2P_RO_CH_WK);
3600#endif
3601 }
3602
3603 pcfg80211_wdinfo->is_ro_ch = true;
3604
3605 if (_FAIL == rtw_pwr_wakeup(padapter)) {
3606 err = -EFAULT;
3607 goto exit;
3608 }
3609
3610 memcpy(&pcfg80211_wdinfo->remain_on_ch_channel, channel,
3611 sizeof(struct ieee80211_channel));
3612 pcfg80211_wdinfo->remain_on_ch_cookie = *cookie;
3613
3614 rtw_scan_abort23a(padapter);
3615 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
3616 rtw_p2p_enable23a(padapter, P2P_ROLE_DEVICE);
3617 wdev_to_priv(padapter->rtw_wdev)->p2p_enabled = true;
3618 } else {
3619 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3620#ifdef CONFIG_DEBUG_CFG80211
3621 DBG_8723A("%s, role =%d, p2p_state =%d\n", __func__,
3622 rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
3623#endif
3624 }
3625
3626 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
3627
3628 if (duration < 400)
3629 duration = duration * 3; /* extend from exper. */
3630
3631 pcfg80211_wdinfo->restore_channel = pmlmeext->cur_channel;
3632
3633 if (rtw_ch_set_search_ch23a(pmlmeext->channel_set, remain_ch) >= 0) {
3634 if (remain_ch != pmlmeext->cur_channel) {
3635 ready_on_channel = true;
3636 }
3637 } else {
3638 DBG_8723A("%s remain_ch:%u not in channel plan!!!!\n",
3639 __func__, remain_ch);
3640 }
3641
3642 /* call this after other things have been done */
3643 if (ready_on_channel == true) {
3644 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
3645 pmlmeext->cur_channel = remain_ch;
3646
3647 set_channel_bwmode23a(padapter, remain_ch,
3648 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
3649 HT_CHANNEL_WIDTH_20);
3650 }
3651 }
3652 DBG_8723A("%s, set ro ch timer, duration =%d\n", __func__, duration);
3653 mod_timer(&pcfg80211_wdinfo->remain_on_ch_timer,
3654 jiffies + msecs_to_jiffies(duration));
3655
3656 rtw_cfg80211_ready_on_channel(padapter, *cookie, channel, channel_type,
3657 duration, GFP_KERNEL);
3658
3659 pwdinfo->listen_channel = pmlmeext->cur_channel;
3660
3661exit:
3662 if (err)
3663 pcfg80211_wdinfo->is_ro_ch = false;
3664
3665 return err;
3666}
3667
3668static s32 cfg80211_rtw_cancel_remain_on_channel(struct wiphy *wiphy,
3669 struct wireless_dev *wdev,
3670 u64 cookie)
3671{
3672 s32 err = 0;
3673 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
3674 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3675 struct cfg80211_wifidirect_info *pcfg80211_wdinfo =
3676 &padapter->cfg80211_wdinfo;
3677
3678 DBG_8723A(FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(padapter));
3679
3680 if (pcfg80211_wdinfo->is_ro_ch == true) {
3681 DBG_8723A("%s, cancel ro ch timer\n", __func__);
3682 del_timer_sync(&padapter->cfg80211_wdinfo.remain_on_ch_timer);
3683#ifdef CONFIG_8723AU_P2P
3684 p2p_protocol_wk_hdl23a(padapter, P2P_RO_CH_WK);
3685#endif
3686 }
3687
3688 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3689#ifdef CONFIG_DEBUG_CFG80211
3690 DBG_8723A("%s, role =%d, p2p_state =%d\n", __func__,
3691 rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
3692#endif
3693 pcfg80211_wdinfo->is_ro_ch = false;
3694
3695 return err;
3696}
3697
3698#endif /* CONFIG_8723AU_P2P */
3699
3700static int _cfg80211_rtw_mgmt_tx(struct rtw_adapter *padapter, u8 tx_ch,
3701 const u8 *buf, size_t len)
3702{
3703 struct xmit_frame *pmgntframe;
3704 struct pkt_attrib *pattrib;
3705 unsigned char *pframe;
3706 int ret = _FAIL;
3707 bool ack = true;
3708 struct ieee80211_hdr *pwlanhdr;
3709 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3710 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3711 /* struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo; */
3712
3713 if (_FAIL == rtw_pwr_wakeup(padapter)) {
3714 ret = -EFAULT;
3715 goto exit;
3716 }
3717
3718 rtw_set_scan_deny(padapter, 1000);
3719
3720 rtw_scan_abort23a(padapter);
3721
3722 if (tx_ch != rtw_get_oper_ch23a(padapter)) {
3723 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
3724 pmlmeext->cur_channel = tx_ch;
3725 set_channel_bwmode23a(padapter, tx_ch,
3726 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
3727 HT_CHANNEL_WIDTH_20);
3728 }
3729
3730 /* starting alloc mgmt frame to dump it */
3731 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3732 if (pmgntframe == NULL) {
3733 /* ret = -ENOMEM; */
3734 ret = _FAIL;
3735 goto exit;
3736 }
3737
3738 /* update attribute */
3739 pattrib = &pmgntframe->attrib;
3740 update_mgntframe_attrib23a(padapter, pattrib);
3741 pattrib->retry_ctrl = false;
3742
3743 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3744
3745 pframe = (u8 *) (pmgntframe->buf_addr) + TXDESC_OFFSET;
3746
3747 memcpy(pframe, (void *)buf, len);
3748 pattrib->pktlen = len;
3749
3750 pwlanhdr = (struct ieee80211_hdr *)pframe;
3751 /* update seq number */
3752 pmlmeext->mgnt_seq = le16_to_cpu(pwlanhdr->seq_ctrl) >> 4;
3753 pattrib->seqnum = pmlmeext->mgnt_seq;
3754 pmlmeext->mgnt_seq++;
3755
3756#ifdef CONFIG_8723AU_P2P
3757 {
3758 struct wifi_display_info *pwfd_info;
3759
3760 pwfd_info = padapter->wdinfo.wfd_info;
3761
3762 if (true == pwfd_info->wfd_enable) {
3763 rtw_append_wfd_ie(padapter, pframe, &pattrib->pktlen);
3764 }
3765 }
3766#endif /* CONFIG_8723AU_P2P */
3767
3768 pattrib->last_txcmdsz = pattrib->pktlen;
3769
3770 if (dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe) != _SUCCESS) {
3771 ack = false;
3772 ret = _FAIL;
3773
3774#ifdef CONFIG_DEBUG_CFG80211
3775 DBG_8723A("%s, ack == _FAIL\n", __func__);
3776#endif
3777 } else {
3778#ifdef CONFIG_DEBUG_CFG80211
3779 DBG_8723A("%s, ack =%d, ok!\n", __func__, ack);
3780#endif
3781 ret = _SUCCESS;
3782 }
3783
3784exit:
3785
3786#ifdef CONFIG_DEBUG_CFG80211
3787 DBG_8723A("%s, ret =%d\n", __func__, ret);
3788#endif
3789
3790 return ret;
3791}
3792
3793static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
3794#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
3795 struct ieee80211_channel *chan,
3796 bool offchan,
3797 unsigned int wait,
3798 const u8 *buf, size_t len,
3799 bool no_cck, bool dont_wait_for_ack,
3800#else
3801 struct cfg80211_mgmt_tx_params *params,
3802#endif
3803 u64 *cookie)
3804{
3805 struct rtw_adapter *padapter =
3806 (struct rtw_adapter *)wiphy_to_adapter(wiphy);
3807 struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
3808 int ret = 0;
3809 int tx_ret;
3810 u32 dump_limit = RTW_MAX_MGMT_TX_CNT;
3811 u32 dump_cnt = 0;
3812 bool ack = true;
3813 u8 category, action;
3814 int type = (-1);
3815 unsigned long start = jiffies;
3816#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
3817 size_t len = params->len;
3818 struct ieee80211_channel *chan = params->chan;
3819 const u8 *buf = params->buf;
3820#endif
3821 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)buf;
3822 u8 tx_ch = (u8) ieee80211_frequency_to_channel(chan->center_freq);
3823
3824 /* cookie generation */
3825 *cookie = (unsigned long)buf;
3826
3827#ifdef CONFIG_DEBUG_CFG80211
3828 DBG_8723A(FUNC_ADPT_FMT " len =%zu, ch =%d"
3829 "\n", FUNC_ADPT_ARG(padapter), len, tx_ch);
3830#endif /* CONFIG_DEBUG_CFG80211 */
3831
3832 /* indicate ack before issue frame to avoid racing with rsp frame */
3833 rtw_cfg80211_mgmt_tx_status(padapter, *cookie, buf, len, ack,
3834 GFP_KERNEL);
3835
3836 if (rtw_action_frame_parse23a(buf, len, &category, &action) == false) {
3837 DBG_8723A(FUNC_ADPT_FMT " frame_control:0x%x\n",
3838 FUNC_ADPT_ARG(padapter),
3839 le16_to_cpu(hdr->frame_control));
3840 goto exit;
3841 }
3842
3843 DBG_8723A("RTW_Tx:tx_ch =%d, da =" MAC_FMT "\n", tx_ch,
3844 MAC_ARG(hdr->addr1));
3845#ifdef CONFIG_8723AU_P2P
3846 type = rtw_p2p_check_frames(padapter, buf, len, true);
3847 if (type >= 0)
3848 goto dump;
3849#endif
3850 if (category == WLAN_CATEGORY_PUBLIC)
3851 DBG_8723A("RTW_Tx:%s\n", action_public_str23a(action));
3852 else
3853 DBG_8723A("RTW_Tx:category(%u), action(%u)\n",
3854 category, action);
3855
3856#ifdef CONFIG_8723AU_P2P
3857dump:
3858#endif
3859 do {
3860 dump_cnt++;
3861 tx_ret = _cfg80211_rtw_mgmt_tx(padapter, tx_ch, buf, len);
3862 } while (dump_cnt < dump_limit && tx_ret != _SUCCESS);
3863
3864 if (tx_ret != _SUCCESS || dump_cnt > 1) {
3865 DBG_8723A(FUNC_ADPT_FMT " %s (%d/%d) in %d ms\n",
3866 FUNC_ADPT_ARG(padapter),
3867 tx_ret == _SUCCESS ? "OK" : "FAIL", dump_cnt,
3868 dump_limit, jiffies_to_msecs(jiffies - start));
3869 }
3870
3871 switch (type) {
3872 case P2P_GO_NEGO_CONF:
3873 rtw_clear_scan_deny(padapter);
3874 break;
3875 case P2P_INVIT_RESP:
3876 if (pwdev_priv->invit_info.flags & BIT(0)
3877 && pwdev_priv->invit_info.status == 0) {
3878 DBG_8723A(FUNC_ADPT_FMT " agree with invitation of "
3879 "persistent group\n",
3880 FUNC_ADPT_ARG(padapter));
3881 rtw_set_scan_deny(padapter, 5000);
3882 rtw_pwr_wakeup_ex(padapter, 5000);
3883 rtw_clear_scan_deny(padapter);
3884 }
3885 break;
3886 }
3887
3888exit:
3889 return ret;
3890}
3891
3892static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy,
3893 struct wireless_dev *wdev,
3894 u16 frame_type, bool reg)
3895{
3896
3897#ifdef CONFIG_DEBUG_CFG80211
3898 DBG_8723A(FUNC_ADPT_FMT " frame_type:%x, reg:%d\n",
3899 FUNC_ADPT_ARG(adapter), frame_type, reg);
3900#endif
3901
3902 if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
3903 return;
3904
3905 return;
3906}
3907
3908static int rtw_cfg80211_set_beacon_wpsp2pie(struct net_device *ndev, char *buf,
3909 int len)
3910{
3911 int ret = 0;
3912 uint wps_ielen = 0;
3913 u8 *wps_ie;
3914#ifdef CONFIG_8723AU_P2P
3915 u32 p2p_ielen = 0;
3916 u32 wfd_ielen = 0;
3917 u8 *p2p_ie;
3918#endif
3919#ifdef CONFIG_8723AU_AP_MODE
3920 u8 wps_oui[8] = { 0x0, 0x50, 0xf2, 0x04 };
3921#endif
3922 struct rtw_adapter *padapter = netdev_priv(ndev);
3923 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3924 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3925
3926 DBG_8723A(FUNC_NDEV_FMT " ielen =%d\n", FUNC_NDEV_ARG(ndev), len);
3927
3928 if (len > 0) {
3929 wps_ie = rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen);
3930 if (wps_ie) {
3931#ifdef CONFIG_DEBUG_CFG80211
3932 DBG_8723A("bcn_wps_ielen =%d\n", wps_ielen);
3933#endif
3934
3935 if (pmlmepriv->wps_beacon_ie) {
3936 pmlmepriv->wps_beacon_ie_len = 0;
3937 kfree(pmlmepriv->wps_beacon_ie);
3938 pmlmepriv->wps_beacon_ie = NULL;
3939 }
3940
3941 pmlmepriv->wps_beacon_ie =
3942 kmalloc(wps_ielen, GFP_KERNEL);
3943 if (pmlmepriv->wps_beacon_ie == NULL) {
3944 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
3945 __func__, __LINE__);
3946 return -EINVAL;
3947 }
3948 memcpy(pmlmepriv->wps_beacon_ie, wps_ie, wps_ielen);
3949 pmlmepriv->wps_beacon_ie_len = wps_ielen;
3950
3951#ifdef CONFIG_8723AU_AP_MODE
3952 update_beacon23a(padapter, _VENDOR_SPECIFIC_IE_, wps_oui,
3953 true);
3954#endif
3955 }
3956#ifdef CONFIG_8723AU_P2P
3957 p2p_ie = rtw_get_p2p_ie23a(buf, len, NULL, &p2p_ielen);
3958 if (p2p_ie) {
3959#ifdef CONFIG_DEBUG_CFG80211
3960 DBG_8723A("bcn_p2p_ielen =%d\n", p2p_ielen);
3961#endif
3962
3963 if (pmlmepriv->p2p_beacon_ie) {
3964 pmlmepriv->p2p_beacon_ie_len = 0;
3965 kfree(pmlmepriv->p2p_beacon_ie);
3966 pmlmepriv->p2p_beacon_ie = NULL;
3967 }
3968
3969 pmlmepriv->p2p_beacon_ie =
3970 kmalloc(p2p_ielen, GFP_KERNEL);
3971 if (pmlmepriv->p2p_beacon_ie == NULL) {
3972 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
3973 __func__, __LINE__);
3974 return -EINVAL;
3975 }
3976
3977 memcpy(pmlmepriv->p2p_beacon_ie, p2p_ie, p2p_ielen);
3978 pmlmepriv->p2p_beacon_ie_len = p2p_ielen;
3979 }
3980#endif /* CONFIG_8723AU_P2P */
3981
3982 /* buf += p2p_ielen; */
3983 /* len -= p2p_ielen; */
3984
3985#ifdef CONFIG_8723AU_P2P
3986 if (rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen)) {
3987#ifdef CONFIG_DEBUG_CFG80211
3988 DBG_8723A("bcn_wfd_ielen =%d\n", wfd_ielen);
3989#endif
3990
3991 if (pmlmepriv->wfd_beacon_ie) {
3992 pmlmepriv->wfd_beacon_ie_len = 0;
3993 kfree(pmlmepriv->wfd_beacon_ie);
3994 pmlmepriv->wfd_beacon_ie = NULL;
3995 }
3996
3997 pmlmepriv->wfd_beacon_ie =
3998 kmalloc(wfd_ielen, GFP_KERNEL);
3999 if (pmlmepriv->wfd_beacon_ie == NULL) {
4000 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
4001 __func__, __LINE__);
4002 return -EINVAL;
4003
4004 }
4005 rtw_get_wfd_ie(buf, len, pmlmepriv->wfd_beacon_ie,
4006 &pmlmepriv->wfd_beacon_ie_len);
4007 }
4008#endif /* CONFIG_8723AU_P2P */
4009
4010 pmlmeext->bstart_bss = true;
4011
4012 }
4013
4014 return ret;
4015}
4016
4017static int rtw_cfg80211_set_probe_resp_wpsp2pie(struct net_device *net,
4018 char *buf, int len)
4019{
4020 struct rtw_adapter *padapter = netdev_priv(net);
4021 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4022#ifdef CONFIG_8723AU_P2P
4023 u32 p2p_ielen = 0;
4024 u8 *p2p_ie;
4025 u32 wfd_ielen = 0;
4026#endif
4027 int ret = 0;
4028 uint wps_ielen = 0;
4029 u8 *wps_ie;
4030
4031 if (len > 0) {
4032 wps_ie = rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen);
4033 if (wps_ie) {
4034 uint attr_contentlen = 0;
4035 u16 uconfig_method, *puconfig_method = NULL;
4036
4037 if (pmlmepriv->wps_probe_resp_ie) {
4038 pmlmepriv->wps_probe_resp_ie_len = 0;
4039 kfree(pmlmepriv->wps_probe_resp_ie);
4040 pmlmepriv->wps_probe_resp_ie = NULL;
4041 }
4042
4043 pmlmepriv->wps_probe_resp_ie =
4044 kmalloc(wps_ielen, GFP_KERNEL);
4045 if (pmlmepriv->wps_probe_resp_ie == NULL) {
4046 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
4047 __func__, __LINE__);
4048 return -EINVAL;
4049
4050 }
4051
4052 /* add PUSH_BUTTON config_method by driver self in
4053 wpsie of probe_resp at GO Mode */
4054 puconfig_method = (u16 *)rtw_get_wps_attr_content23a(wps_ie, wps_ielen,
4055 WPS_ATTR_CONF_METHOD,
4056 NULL,
4057 &attr_contentlen);
4058 if (puconfig_method) {
4059 uconfig_method = WPS_CM_PUSH_BUTTON;
4060 uconfig_method = cpu_to_be16(uconfig_method);
4061
4062 *puconfig_method |= uconfig_method;
4063 }
4064
4065 memcpy(pmlmepriv->wps_probe_resp_ie, wps_ie, wps_ielen);
4066 pmlmepriv->wps_probe_resp_ie_len = wps_ielen;
4067
4068 }
4069
4070 /* buf += wps_ielen; */
4071 /* len -= wps_ielen; */
4072
4073#ifdef CONFIG_8723AU_P2P
4074 p2p_ie = rtw_get_p2p_ie23a(buf, len, NULL, &p2p_ielen);
4075 if (p2p_ie) {
4076 u8 is_GO = false;
4077 u32 attr_contentlen = 0;
4078 u16 cap_attr = 0;
4079
4080#ifdef CONFIG_DEBUG_CFG80211
4081 DBG_8723A("probe_resp_p2p_ielen =%d\n", p2p_ielen);
4082#endif
4083
4084 /* Check P2P Capability ATTR */
4085 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen,
4086 P2P_ATTR_CAPABILITY,
4087 (u8 *) &cap_attr,
4088 (uint *) &attr_contentlen)) {
4089 u8 grp_cap = 0;
4090 /* DBG_8723A( "[%s] Got P2P Capability Attr!!\n", __func__ ); */
4091 cap_attr = le16_to_cpu(cap_attr);
4092 grp_cap = (u8) ((cap_attr >> 8) & 0xff);
4093
4094 is_GO = (grp_cap & BIT(0)) ? true : false;
4095
4096 if (is_GO)
4097 DBG_8723A
4098 ("Got P2P Capability Attr, grp_cap"
4099 "= 0x%x, is_GO\n", grp_cap);
4100 }
4101
4102 if (is_GO == false) {
4103 if (pmlmepriv->p2p_probe_resp_ie) {
4104 pmlmepriv->p2p_probe_resp_ie_len = 0;
4105 kfree(pmlmepriv->p2p_probe_resp_ie);
4106 pmlmepriv->p2p_probe_resp_ie = NULL;
4107 }
4108
4109 pmlmepriv->p2p_probe_resp_ie =
4110 kmalloc(p2p_ielen, GFP_KERNEL);
4111 if (pmlmepriv->p2p_probe_resp_ie == NULL) {
4112 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
4113 __func__, __LINE__);
4114 return -EINVAL;
4115 }
4116 memcpy(pmlmepriv->p2p_probe_resp_ie, p2p_ie,
4117 p2p_ielen);
4118 pmlmepriv->p2p_probe_resp_ie_len = p2p_ielen;
4119 } else {
4120 if (pmlmepriv->p2p_go_probe_resp_ie) {
4121 pmlmepriv->p2p_go_probe_resp_ie_len = 0;
4122 kfree(pmlmepriv->p2p_go_probe_resp_ie);
4123 pmlmepriv->p2p_go_probe_resp_ie = NULL;
4124 }
4125
4126 pmlmepriv->p2p_go_probe_resp_ie =
4127 kmalloc(p2p_ielen, GFP_KERNEL);
4128 if (pmlmepriv->p2p_go_probe_resp_ie == NULL) {
4129 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
4130 __func__, __LINE__);
4131 return -EINVAL;
4132
4133 }
4134 memcpy(pmlmepriv->p2p_go_probe_resp_ie,
4135 p2p_ie, p2p_ielen);
4136 pmlmepriv->p2p_go_probe_resp_ie_len = p2p_ielen;
4137 }
4138 }
4139#endif /* CONFIG_8723AU_P2P */
4140
4141 /* buf += p2p_ielen; */
4142 /* len -= p2p_ielen; */
4143
4144#ifdef CONFIG_8723AU_P2P
4145 if (rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen)) {
4146#ifdef CONFIG_DEBUG_CFG80211
4147 DBG_8723A("probe_resp_wfd_ielen =%d\n", wfd_ielen);
4148#endif
4149
4150 if (pmlmepriv->wfd_probe_resp_ie) {
4151 pmlmepriv->wfd_probe_resp_ie_len = 0;
4152 kfree(pmlmepriv->wfd_probe_resp_ie);
4153 pmlmepriv->wfd_probe_resp_ie = NULL;
4154 }
4155
4156 pmlmepriv->wfd_probe_resp_ie =
4157 kmalloc(wfd_ielen, GFP_KERNEL);
4158 if (pmlmepriv->wfd_probe_resp_ie == NULL) {
4159 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
4160 __func__, __LINE__);
4161 return -EINVAL;
4162
4163 }
4164 rtw_get_wfd_ie(buf, len, pmlmepriv->wfd_probe_resp_ie,
4165 &pmlmepriv->wfd_probe_resp_ie_len);
4166 }
4167#endif /* CONFIG_8723AU_P2P */
4168 }
4169
4170 return ret;
4171}
4172
4173static int rtw_cfg80211_set_assoc_resp_wpsp2pie(struct net_device *net,
4174 char *buf, int len)
4175{
4176 int ret = 0;
4177 struct rtw_adapter *padapter = netdev_priv(net);
4178 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4179
4180 DBG_8723A("%s, ielen =%d\n", __func__, len);
4181
4182 if (len > 0) {
4183 if (pmlmepriv->wps_assoc_resp_ie) {
4184 pmlmepriv->wps_assoc_resp_ie_len = 0;
4185 kfree(pmlmepriv->wps_assoc_resp_ie);
4186 pmlmepriv->wps_assoc_resp_ie = NULL;
4187 }
4188
4189 pmlmepriv->wps_assoc_resp_ie = kmalloc(len, GFP_KERNEL);
4190 if (pmlmepriv->wps_assoc_resp_ie == NULL) {
4191 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
4192 __func__, __LINE__);
4193 return -EINVAL;
4194
4195 }
4196 memcpy(pmlmepriv->wps_assoc_resp_ie, buf, len);
4197 pmlmepriv->wps_assoc_resp_ie_len = len;
4198 }
4199
4200 return ret;
4201}
4202
4203int rtw_cfg80211_set_mgnt_wpsp2pie(struct net_device *net, char *buf, int len,
4204 int type)
4205{
4206 int ret = 0;
4207 uint wps_ielen = 0;
4208#ifdef CONFIG_8723AU_P2P
4209 u32 p2p_ielen = 0;
4210#endif
4211
4212#ifdef CONFIG_DEBUG_CFG80211
4213 DBG_8723A("%s, ielen =%d\n", __func__, len);
4214#endif
4215
4216 if ((rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen) && (wps_ielen > 0))
4217#ifdef CONFIG_8723AU_P2P
4218 || (rtw_get_p2p_ie23a(buf, len, NULL, &p2p_ielen) && (p2p_ielen > 0))
4219#endif
4220 ) {
4221 if (net) {
4222 switch (type) {
4223 case 0x1: /* BEACON */
4224 ret =
4225 rtw_cfg80211_set_beacon_wpsp2pie(net, buf,
4226 len);
4227 break;
4228 case 0x2: /* PROBE_RESP */
4229 ret =
4230 rtw_cfg80211_set_probe_resp_wpsp2pie(net,
4231 buf,
4232 len);
4233 break;
4234 case 0x4: /* ASSOC_RESP */
4235 ret =
4236 rtw_cfg80211_set_assoc_resp_wpsp2pie(net,
4237 buf,
4238 len);
4239 break;
4240 }
4241 }
4242 }
4243
4244 return ret;
4245
4246}
4247
4248static struct cfg80211_ops rtw_cfg80211_ops = {
4249 .change_virtual_intf = cfg80211_rtw_change_iface,
4250 .add_key = cfg80211_rtw_add_key,
4251 .get_key = cfg80211_rtw_get_key,
4252 .del_key = cfg80211_rtw_del_key,
4253 .set_default_key = cfg80211_rtw_set_default_key,
4254 .get_station = cfg80211_rtw_get_station,
4255 .scan = cfg80211_rtw_scan,
4256 .set_wiphy_params = cfg80211_rtw_set_wiphy_params,
4257 .connect = cfg80211_rtw_connect,
4258 .disconnect = cfg80211_rtw_disconnect,
4259 .join_ibss = cfg80211_rtw_join_ibss,
4260 .leave_ibss = cfg80211_rtw_leave_ibss,
4261 .set_tx_power = cfg80211_rtw_set_txpower,
4262 .get_tx_power = cfg80211_rtw_get_txpower,
4263 .set_power_mgmt = cfg80211_rtw_set_power_mgmt,
4264 .set_pmksa = cfg80211_rtw_set_pmksa,
4265 .del_pmksa = cfg80211_rtw_del_pmksa,
4266 .flush_pmksa = cfg80211_rtw_flush_pmksa,
4267
4268#ifdef CONFIG_8723AU_AP_MODE
4269 .add_virtual_intf = cfg80211_rtw_add_virtual_intf,
4270 .del_virtual_intf = cfg80211_rtw_del_virtual_intf,
4271
4272 .start_ap = cfg80211_rtw_start_ap,
4273 .change_beacon = cfg80211_rtw_change_beacon,
4274 .stop_ap = cfg80211_rtw_stop_ap,
4275
4276 .add_station = cfg80211_rtw_add_station,
4277 .del_station = cfg80211_rtw_del_station,
4278 .change_station = cfg80211_rtw_change_station,
4279 .dump_station = cfg80211_rtw_dump_station,
4280 .change_bss = cfg80211_rtw_change_bss,
4281#endif /* CONFIG_8723AU_AP_MODE */
4282
4283#ifdef CONFIG_8723AU_P2P
4284 .remain_on_channel = cfg80211_rtw_remain_on_channel,
4285 .cancel_remain_on_channel = cfg80211_rtw_cancel_remain_on_channel,
4286#endif
4287
4288 .mgmt_tx = cfg80211_rtw_mgmt_tx,
4289 .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,
4290};
4291
4292static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap,
4293 enum ieee80211_band band, u8 rf_type)
4294{
4295
4296#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */
4297#define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */
4298
4299 ht_cap->ht_supported = true;
4300
4301 ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
4302 IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 |
4303 IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU;
4304
4305 /*
4306 *Maximum length of AMPDU that the STA can receive.
4307 *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
4308 */
4309 ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
4310
4311 /*Minimum MPDU start spacing , */
4312 ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
4313
4314 ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
4315
4316 /*
4317 *hw->wiphy->bands[IEEE80211_BAND_2GHZ]
4318 *base on ant_num
4319 *rx_mask: RX mask
4320 *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7
4321 *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15
4322 *if rx_ant >= 3 rx_mask[2]= 0xff;
4323 *if BW_40 rx_mask[4]= 0x01;
4324 *highest supported RX rate
4325 */
4326 if (rf_type == RF_1T1R) {
4327 ht_cap->mcs.rx_mask[0] = 0xFF;
4328 ht_cap->mcs.rx_mask[1] = 0x00;
4329 ht_cap->mcs.rx_mask[4] = 0x01;
4330
4331 ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS7;
4332 } else if ((rf_type == RF_1T2R) || (rf_type == RF_2T2R)) {
4333 ht_cap->mcs.rx_mask[0] = 0xFF;
4334 ht_cap->mcs.rx_mask[1] = 0xFF;
4335 ht_cap->mcs.rx_mask[4] = 0x01;
4336
4337 ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS15;
4338 } else {
4339 DBG_8723A("%s, error rf_type =%d\n", __func__, rf_type);
4340 }
4341
4342}
4343
4344void rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter)
4345{
4346 u8 rf_type;
4347 struct ieee80211_supported_band *bands;
4348 struct wireless_dev *pwdev = padapter->rtw_wdev;
4349 struct wiphy *wiphy = pwdev->wiphy;
4350
4351 rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
4352
4353 DBG_8723A("%s:rf_type =%d\n", __func__, rf_type);
4354
4355 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
4356 {
4357 bands = wiphy->bands[IEEE80211_BAND_2GHZ];
4358 if (bands)
4359 rtw_cfg80211_init_ht_capab(&bands->ht_cap,
4360 IEEE80211_BAND_2GHZ,
4361 rf_type);
4362 }
4363
4364 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
4365 {
4366 bands = wiphy->bands[IEEE80211_BAND_5GHZ];
4367 if (bands)
4368 rtw_cfg80211_init_ht_capab(&bands->ht_cap,
4369 IEEE80211_BAND_5GHZ,
4370 rf_type);
4371 }
4372}
4373
4374static void rtw_cfg80211_preinit_wiphy(struct rtw_adapter *padapter,
4375 struct wiphy *wiphy)
4376{
4377 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
4378
4379 wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT;
4380 wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
4381 wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS;
4382
4383 wiphy->max_remain_on_channel_duration =
4384 RTW_MAX_REMAIN_ON_CHANNEL_DURATION;
4385
4386 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
4387 BIT(NL80211_IFTYPE_ADHOC) |
4388#ifdef CONFIG_8723AU_AP_MODE
4389 BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) |
4390#endif
4391#if defined(CONFIG_8723AU_P2P)
4392 BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) |
4393#endif
4394 0;
4395
4396#ifdef CONFIG_8723AU_AP_MODE
4397 wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes;
4398#endif /* CONFIG_8723AU_AP_MODE */
4399
4400 wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
4401
4402 /*
4403 wiphy->iface_combinations = &rtw_combinations;
4404 wiphy->n_iface_combinations = 1;
4405 */
4406
4407 wiphy->cipher_suites = rtw_cipher_suites;
4408 wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites);
4409
4410 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
4411 wiphy->bands[IEEE80211_BAND_2GHZ] =
4412 rtw_spt_band_alloc(IEEE80211_BAND_2GHZ);
4413 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
4414 wiphy->bands[IEEE80211_BAND_5GHZ] =
4415 rtw_spt_band_alloc(IEEE80211_BAND_5GHZ);
4416
4417 wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
4418 wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME;
4419
4420 if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
4421 wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
4422 else
4423 wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
4424}
4425
4426int rtw_wdev_alloc(struct rtw_adapter *padapter, struct device *dev)
4427{
4428 int ret = 0;
4429 struct wiphy *wiphy;
4430 struct wireless_dev *wdev;
4431 struct rtw_wdev_priv *pwdev_priv;
4432 struct net_device *pnetdev = padapter->pnetdev;
4433
4434 DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
4435
4436 /* wiphy */
4437 wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(struct rtw_wdev_priv));
4438 if (!wiphy) {
4439 DBG_8723A("Couldn't allocate wiphy device\n");
4440 ret = -ENOMEM;
4441 goto exit;
4442 }
4443 set_wiphy_dev(wiphy, dev);
4444 rtw_cfg80211_preinit_wiphy(padapter, wiphy);
4445
4446 ret = wiphy_register(wiphy);
4447 if (ret < 0) {
4448 DBG_8723A("Couldn't register wiphy device\n");
4449 goto free_wiphy;
4450 }
4451
4452 /* wdev */
4453 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
4454 if (!wdev) {
4455 DBG_8723A("Couldn't allocate wireless device\n");
4456 ret = -ENOMEM;
4457 goto unregister_wiphy;
4458 }
4459 wdev->wiphy = wiphy;
4460 wdev->netdev = pnetdev;
4461 /* wdev->iftype = NL80211_IFTYPE_STATION; */
4462 /* for rtw_setopmode_cmd23a() in cfg80211_rtw_change_iface() */
4463 wdev->iftype = NL80211_IFTYPE_MONITOR;
4464 padapter->rtw_wdev = wdev;
4465 pnetdev->ieee80211_ptr = wdev;
4466
4467 /* init pwdev_priv */
4468 pwdev_priv = wdev_to_priv(wdev);
4469 pwdev_priv->rtw_wdev = wdev;
4470 pwdev_priv->pmon_ndev = NULL;
4471 pwdev_priv->ifname_mon[0] = '\0';
4472 pwdev_priv->padapter = padapter;
4473 pwdev_priv->scan_request = NULL;
4474 spin_lock_init(&pwdev_priv->scan_req_lock);
4475
4476 pwdev_priv->p2p_enabled = false;
4477 pwdev_priv->provdisc_req_issued = false;
4478 rtw_wdev_invit_info_init(&pwdev_priv->invit_info);
4479
4480 if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
4481 pwdev_priv->power_mgmt = true;
4482 else
4483 pwdev_priv->power_mgmt = false;
4484
4485 return ret;
4486unregister_wiphy:
4487 wiphy_unregister(wiphy);
4488free_wiphy:
4489 wiphy_free(wiphy);
4490exit:
4491 return ret;
4492}
4493
4494void rtw_wdev_free(struct wireless_dev *wdev)
4495{
4496 struct rtw_wdev_priv *pwdev_priv;
4497
4498 DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
4499
4500 if (!wdev)
4501 return;
4502
4503 pwdev_priv = wdev_to_priv(wdev);
4504
4505 kfree(wdev->wiphy->bands[IEEE80211_BAND_2GHZ]);
4506 kfree(wdev->wiphy->bands[IEEE80211_BAND_5GHZ]);
4507
4508 wiphy_free(wdev->wiphy);
4509
4510 kfree(wdev);
4511}
4512
4513void rtw_wdev_unregister(struct wireless_dev *wdev)
4514{
4515 struct rtw_wdev_priv *pwdev_priv;
4516
4517 DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
4518
4519 if (!wdev)
4520 return;
4521
4522 pwdev_priv = wdev_to_priv(wdev);
4523
4524 rtw_cfg80211_indicate_scan_done(pwdev_priv, true);
4525
4526 if (pwdev_priv->pmon_ndev) {
4527 DBG_8723A("%s, unregister monitor interface\n", __func__);
4528 unregister_netdev(pwdev_priv->pmon_ndev);
4529 }
4530
4531 wiphy_unregister(wdev->wiphy);
4532}
diff --git a/drivers/staging/rtl8723au/os_dep/mlme_linux.c b/drivers/staging/rtl8723au/os_dep/mlme_linux.c
new file mode 100644
index 000000000000..b30d4d37556a
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/mlme_linux.c
@@ -0,0 +1,187 @@
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 ******************************************************************************/
15
16#define _MLME_OSDEP_C_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20#include <mlme_osdep.h>
21#include <rtw_ioctl_set.h>
22
23void rtw_os_indicate_connect23a(struct rtw_adapter *adapter)
24{
25 rtw_cfg80211_indicate_connect(adapter);
26
27 netif_carrier_on(adapter->pnetdev);
28
29 if (adapter->pid[2] != 0)
30 rtw_signal_process(adapter->pid[2], SIGALRM);
31}
32
33void rtw_os_indicate_scan_done23a(struct rtw_adapter *padapter, bool aborted)
34{
35 rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev),
36 aborted);
37}
38
39static struct rt_pmkid_list backupPMKIDList[NUM_PMKID_CACHE];
40
41void rtw_reset_securitypriv23a(struct rtw_adapter *adapter)
42{
43 u8 backupPMKIDIndex = 0;
44 u8 backupTKIPCountermeasure = 0x00;
45 unsigned long backupTKIPcountermeasure_time = 0;
46
47 if (adapter->securitypriv.dot11AuthAlgrthm ==
48 dot11AuthAlgrthm_8021X) { /* 802.1x */
49 /* We have to backup the PMK information for WiFi PMK
50 * Caching test item.
51 * Backup the btkip_countermeasure information.
52 * When the countermeasure is trigger, the driver have to
53 * disconnect with AP for 60 seconds.
54 */
55 memset(&backupPMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) *
56 NUM_PMKID_CACHE);
57
58 memcpy(&backupPMKIDList[0], &adapter->securitypriv.PMKIDList[0],
59 sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
60 backupPMKIDIndex = adapter->securitypriv.PMKIDIndex;
61 backupTKIPCountermeasure = adapter->securitypriv.btkip_countermeasure;
62 backupTKIPcountermeasure_time = adapter->securitypriv.btkip_countermeasure_time;
63
64 memset((unsigned char *)&adapter->securitypriv, 0,
65 sizeof (struct security_priv));
66 /* Restore the PMK information to securitypriv structure
67 * for the following connection.
68 */
69 memcpy(&adapter->securitypriv.PMKIDList[0], &backupPMKIDList[0],
70 sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
71 adapter->securitypriv.PMKIDIndex = backupPMKIDIndex;
72 adapter->securitypriv.btkip_countermeasure = backupTKIPCountermeasure;
73 adapter->securitypriv.btkip_countermeasure_time = backupTKIPcountermeasure_time;
74
75 adapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
76 adapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
77 } else { /* reset values in securitypriv */
78 struct security_priv *psec_priv = &adapter->securitypriv;
79
80 /* open system */
81 psec_priv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
82 psec_priv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
83 psec_priv->dot11PrivacyKeyIndex = 0;
84
85 psec_priv->dot118021XGrpPrivacy = _NO_PRIVACY_;
86 psec_priv->dot118021XGrpKeyid = 1;
87
88 psec_priv->ndisauthtype = Ndis802_11AuthModeOpen;
89 psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled;
90 }
91}
92
93void rtw_os_indicate_disconnect23a(struct rtw_adapter *adapter)
94{
95 /* Do it first for tx broadcast pkt after disconnection issue! */
96 netif_carrier_off(adapter->pnetdev);
97
98 rtw_cfg80211_indicate_disconnect(adapter);
99
100 rtw_reset_securitypriv23a(adapter);
101}
102
103void rtw_report_sec_ie23a(struct rtw_adapter *adapter, u8 authmode, u8 *sec_ie)
104{
105 uint len;
106 u8 *buff, *p, i;
107 union iwreq_data wrqu;
108
109 RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
110 ("+rtw_report_sec_ie23a, authmode =%d\n", authmode));
111
112 buff = NULL;
113 if (authmode == _WPA_IE_ID_) {
114 RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
115 ("rtw_report_sec_ie23a, authmode =%d\n", authmode));
116
117 buff = kzalloc(IW_CUSTOM_MAX, GFP_KERNEL);
118 if (!buff)
119 return;
120 p = buff;
121
122 p += sprintf(p, "ASSOCINFO(ReqIEs =");
123
124 len = sec_ie[1]+2;
125 len = (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX;
126
127 for (i = 0; i < len; i++)
128 p += sprintf(p, "%02x", sec_ie[i]);
129
130 p += sprintf(p, ")");
131
132 memset(&wrqu, 0, sizeof(wrqu));
133
134 wrqu.data.length = p-buff;
135
136 wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ?
137 wrqu.data.length : IW_CUSTOM_MAX;
138
139 kfree(buff);
140 }
141}
142
143#ifdef CONFIG_8723AU_AP_MODE
144void rtw_indicate_sta_assoc_event23a(struct rtw_adapter *padapter,
145 struct sta_info *psta)
146{
147 struct sta_priv *pstapriv = &padapter->stapriv;
148 union iwreq_data wrqu;
149
150 if (psta == NULL)
151 return;
152
153 if (psta->aid > NUM_STA)
154 return;
155
156 if (pstapriv->sta_aid[psta->aid - 1] != psta)
157 return;
158
159 wrqu.addr.sa_family = ARPHRD_ETHER;
160
161 memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
162
163 DBG_8723A("+rtw_indicate_sta_assoc_event23a\n");
164}
165
166void rtw_indicate_sta_disassoc_event23a(struct rtw_adapter *padapter,
167 struct sta_info *psta)
168{
169 struct sta_priv *pstapriv = &padapter->stapriv;
170 union iwreq_data wrqu;
171
172 if (psta == NULL)
173 return;
174
175 if (psta->aid > NUM_STA)
176 return;
177
178 if (pstapriv->sta_aid[psta->aid - 1] != psta)
179 return;
180
181 wrqu.addr.sa_family = ARPHRD_ETHER;
182
183 memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
184
185 DBG_8723A("+rtw_indicate_sta_disassoc_event23a\n");
186}
187#endif
diff --git a/drivers/staging/rtl8723au/os_dep/os_intfs.c b/drivers/staging/rtl8723au/os_dep/os_intfs.c
new file mode 100644
index 000000000000..57eca7a45672
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/os_intfs.c
@@ -0,0 +1,970 @@
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 ******************************************************************************/
15#define _OS_INTFS_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <xmit_osdep.h>
20#include <recv_osdep.h>
21#include <hal_intf.h>
22#include <rtw_version.h>
23#include <ethernet.h>
24
25#include <usb_osintf.h>
26#include <linux/version.h>
27
28MODULE_LICENSE("GPL");
29MODULE_DESCRIPTION("Realtek Wireless Lan Driver");
30MODULE_AUTHOR("Realtek Semiconductor Corp.");
31MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>");
32MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@redhat.com>");
33MODULE_VERSION(DRIVERVERSION);
34MODULE_FIRMWARE("rtlwifi/rtl8821aefw.bin");
35
36/* module param defaults */
37static int rtw_chip_version = 0x00;
38static int rtw_rfintfs = HWPI;
39static int rtw_debug = 1;
40
41static int rtw_channel = 1;/* ad-hoc support requirement */
42static int rtw_wireless_mode = WIRELESS_11BG_24N;
43static int rtw_vrtl_carrier_sense = AUTO_VCS;
44static int rtw_vcs_type = RTS_CTS;/* */
45static int rtw_rts_thresh = 2347;/* */
46static int rtw_frag_thresh = 2346;/* */
47static int rtw_preamble = PREAMBLE_LONG;/* long, short, auto */
48static int rtw_scan_mode = 1;/* active, passive */
49static int rtw_adhoc_tx_pwr = 1;
50static int rtw_soft_ap;
51static int rtw_power_mgnt = 1;
52static int rtw_ips_mode = IPS_NORMAL;
53
54static int rtw_smart_ps = 2;
55
56module_param(rtw_ips_mode, int, 0644);
57MODULE_PARM_DESC(rtw_ips_mode, "The default IPS mode");
58
59static int rtw_long_retry_lmt = 7;
60static int rtw_short_retry_lmt = 7;
61static int rtw_busy_thresh = 40;
62static int rtw_ack_policy = NORMAL_ACK;
63
64static int rtw_acm_method;/* 0:By SW 1:By HW. */
65
66static int rtw_wmm_enable = 1;/* default is set to enable the wmm. */
67static int rtw_uapsd_enable;
68
69int rtw_ht_enable23A = 1;
70/* 0 :diable, bit(0): enable 2.4g, bit(1): enable 5g */
71int rtw_cbw40_enable23A = 3;
72int rtw_ampdu_enable23A = 1;/* for enable tx_ampdu */
73/* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, default is set to enable
74 * 2.4GHZ for IOT issue with bufflao's AP at 5GHZ
75 */
76static int rtw_rx_stbc = 1;
77static int rtw_ampdu_amsdu;/* 0: disabled, 1:enabled, 2:auto */
78
79/* Use 2 path Tx to transmit MCS0~7 and legacy mode */
80static int rtw_lowrate_two_xmit = 1;
81
82/* int rf_config = RF_1T2R; 1T2R */
83static int rtw_rf_config = RF_819X_MAX_TYPE; /* auto */
84static int rtw_low_power;
85static int rtw_wifi_spec;
86static int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX;
87
88#ifdef CONFIG_8723AU_BT_COEXIST
89static int rtw_btcoex_enable = 1;
90static int rtw_bt_iso = 2;/* 0:Low, 1:High, 2:From Efuse */
91/* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter, 4.Busy, 5.OtherBusy */
92static int rtw_bt_sco = 3;
93/* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */
94static int rtw_bt_ampdu = 1 ;
95#endif
96
97/* 0:Reject AP's Add BA req, 1:Accept AP's Add BA req. */
98static int rtw_AcceptAddbaReq = true;
99
100static int rtw_antdiv_cfg = 2; /* 0:OFF , 1:ON, 2:decide by Efuse config */
101static int rtw_antdiv_type; /* 0:decide by efuse */
102
103static int rtw_enusbss;/* 0:disable, 1:enable */
104
105static int rtw_hwpdn_mode = 2;/* 0:disable, 1:enable, 2: by EFUSE config */
106
107static int rtw_hwpwrp_detect; /* HW power ping detect 0:disable , 1:enable */
108
109static int rtw_hw_wps_pbc = 1;
110
111static int rtw_80211d;
112
113static int rtw_regulatory_id = 0xff;/* Regulatory tab id, 0xff = follow efuse's setting */
114
115module_param(rtw_regulatory_id, int, 0644);
116
117static char *ifname = "wlan%d";
118module_param(ifname, charp, 0644);
119MODULE_PARM_DESC(ifname, "The default name to allocate for first interface");
120
121static char *if2name = "wlan%d";
122module_param(if2name, charp, 0644);
123MODULE_PARM_DESC(if2name, "The default name to allocate for second interface");
124
125module_param(rtw_channel_plan, int, 0644);
126module_param(rtw_chip_version, int, 0644);
127module_param(rtw_rfintfs, int, 0644);
128module_param(rtw_channel, int, 0644);
129module_param(rtw_wmm_enable, int, 0644);
130module_param(rtw_vrtl_carrier_sense, int, 0644);
131module_param(rtw_vcs_type, int, 0644);
132module_param(rtw_busy_thresh, int, 0644);
133module_param(rtw_ht_enable23A, int, 0644);
134module_param(rtw_cbw40_enable23A, int, 0644);
135module_param(rtw_ampdu_enable23A, int, 0644);
136module_param(rtw_rx_stbc, int, 0644);
137module_param(rtw_ampdu_amsdu, int, 0644);
138
139module_param(rtw_lowrate_two_xmit, int, 0644);
140
141module_param(rtw_rf_config, int, 0644);
142module_param(rtw_power_mgnt, int, 0644);
143module_param(rtw_smart_ps, int, 0644);
144module_param(rtw_low_power, int, 0644);
145module_param(rtw_wifi_spec, int, 0644);
146
147module_param(rtw_antdiv_cfg, int, 0644);
148
149module_param(rtw_enusbss, int, 0644);
150module_param(rtw_hwpdn_mode, int, 0644);
151module_param(rtw_hwpwrp_detect, int, 0644);
152
153module_param(rtw_hw_wps_pbc, int, 0644);
154
155static uint rtw_max_roaming_times = 2;
156module_param(rtw_max_roaming_times, uint, 0644);
157MODULE_PARM_DESC(rtw_max_roaming_times, "The max roaming times to try");
158
159module_param(rtw_80211d, int, 0644);
160MODULE_PARM_DESC(rtw_80211d, "Enable 802.11d mechanism");
161
162#ifdef CONFIG_8723AU_BT_COEXIST
163module_param(rtw_btcoex_enable, int, 0644);
164MODULE_PARM_DESC(rtw_btcoex_enable, "Enable BT co-existence mechanism");
165#endif
166
167static uint rtw_notch_filter;
168module_param(rtw_notch_filter, uint, 0644);
169MODULE_PARM_DESC(rtw_notch_filter, "0:Disable, 1:Enable, 2:Enable only for P2P");
170module_param_named(debug, rtw_debug, int, 0444);
171MODULE_PARM_DESC(debug, "Set debug level (1-9) (default 1)");
172
173static int netdev_close(struct net_device *pnetdev);
174
175static uint loadparam(struct rtw_adapter *padapter, struct net_device *pnetdev)
176{
177 struct registry_priv *registry_par = &padapter->registrypriv;
178 uint status = _SUCCESS;
179
180 GlobalDebugLevel23A = rtw_debug;
181 registry_par->chip_version = (u8)rtw_chip_version;
182 registry_par->rfintfs = (u8)rtw_rfintfs;
183 memcpy(registry_par->ssid.ssid, "ANY", 3);
184 registry_par->ssid.ssid_len = 3;
185 registry_par->channel = (u8)rtw_channel;
186 registry_par->wireless_mode = (u8)rtw_wireless_mode;
187 registry_par->vrtl_carrier_sense = (u8)rtw_vrtl_carrier_sense;
188 registry_par->vcs_type = (u8)rtw_vcs_type;
189 registry_par->rts_thresh = (u16)rtw_rts_thresh;
190 registry_par->frag_thresh = (u16)rtw_frag_thresh;
191 registry_par->preamble = (u8)rtw_preamble;
192 registry_par->scan_mode = (u8)rtw_scan_mode;
193 registry_par->adhoc_tx_pwr = (u8)rtw_adhoc_tx_pwr;
194 registry_par->soft_ap = (u8)rtw_soft_ap;
195 registry_par->smart_ps = (u8)rtw_smart_ps;
196 registry_par->power_mgnt = (u8)rtw_power_mgnt;
197 registry_par->ips_mode = (u8)rtw_ips_mode;
198 registry_par->long_retry_lmt = (u8)rtw_long_retry_lmt;
199 registry_par->short_retry_lmt = (u8)rtw_short_retry_lmt;
200 registry_par->busy_thresh = (u16)rtw_busy_thresh;
201 registry_par->ack_policy = (u8)rtw_ack_policy;
202 registry_par->acm_method = (u8)rtw_acm_method;
203 /* UAPSD */
204 registry_par->wmm_enable = (u8)rtw_wmm_enable;
205 registry_par->uapsd_enable = (u8)rtw_uapsd_enable;
206 registry_par->ht_enable = (u8)rtw_ht_enable23A;
207 registry_par->cbw40_enable = (u8)rtw_cbw40_enable23A;
208 registry_par->ampdu_enable = (u8)rtw_ampdu_enable23A;
209 registry_par->rx_stbc = (u8)rtw_rx_stbc;
210 registry_par->ampdu_amsdu = (u8)rtw_ampdu_amsdu;
211 registry_par->lowrate_two_xmit = (u8)rtw_lowrate_two_xmit;
212 registry_par->rf_config = (u8)rtw_rf_config;
213 registry_par->low_power = (u8)rtw_low_power;
214 registry_par->wifi_spec = (u8)rtw_wifi_spec;
215 registry_par->channel_plan = (u8)rtw_channel_plan;
216#ifdef CONFIG_8723AU_BT_COEXIST
217 registry_par->btcoex = (u8)rtw_btcoex_enable;
218 registry_par->bt_iso = (u8)rtw_bt_iso;
219 registry_par->bt_sco = (u8)rtw_bt_sco;
220 registry_par->bt_ampdu = (u8)rtw_bt_ampdu;
221#endif
222 registry_par->bAcceptAddbaReq = (u8)rtw_AcceptAddbaReq;
223 registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg;
224 registry_par->antdiv_type = (u8)rtw_antdiv_type;
225
226 /* 0:disable, 1:enable, 2:by EFUSE config */
227 registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode;
228 /* 0:disable, 1:enable */
229 registry_par->hwpwrp_detect = (u8)rtw_hwpwrp_detect;
230 registry_par->hw_wps_pbc = (u8)rtw_hw_wps_pbc;
231 registry_par->max_roaming_times = (u8)rtw_max_roaming_times;
232 registry_par->enable80211d = (u8)rtw_80211d;
233 snprintf(registry_par->ifname, 16, "%s", ifname);
234 snprintf(registry_par->if2name, 16, "%s", if2name);
235 registry_par->notch_filter = (u8)rtw_notch_filter;
236 registry_par->regulatory_tid = (u8)rtw_regulatory_id;
237 return status;
238}
239
240static int rtw_net_set_mac_address(struct net_device *pnetdev, void *p)
241{
242 struct rtw_adapter *padapter = netdev_priv(pnetdev);
243 struct sockaddr *addr = p;
244
245 if (!padapter->bup)
246 ether_addr_copy(padapter->eeprompriv.mac_addr, addr->sa_data);
247 return 0;
248}
249
250static struct net_device_stats *rtw_net_get_stats(struct net_device *pnetdev)
251{
252 struct rtw_adapter *padapter = netdev_priv(pnetdev);
253 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
254 struct recv_priv *precvpriv = &padapter->recvpriv;
255
256 padapter->stats.tx_packets = pxmitpriv->tx_pkts;
257 padapter->stats.rx_packets = precvpriv->rx_pkts;
258 padapter->stats.tx_dropped = pxmitpriv->tx_drop;
259 padapter->stats.rx_dropped = precvpriv->rx_drop;
260 padapter->stats.tx_bytes = pxmitpriv->tx_bytes;
261 padapter->stats.rx_bytes = precvpriv->rx_bytes;
262
263 return &padapter->stats;
264}
265
266/*
267 * AC to queue mapping
268 *
269 * AC_VO -> queue 0
270 * AC_VI -> queue 1
271 * AC_BE -> queue 2
272 * AC_BK -> queue 3
273 */
274static const u16 rtw_1d_to_queue[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
275
276/* Given a data frame determine the 802.1p/1d tag to use. */
277static unsigned int rtw_classify8021d(struct sk_buff *skb)
278{
279 unsigned int dscp;
280
281 /* skb->priority values from 256->263 are magic values to
282 * directly indicate a specific 802.1d priority. This is used
283 * to allow 802.1d priority to be passed directly in from VLAN
284 * tags, etc.
285 */
286 if (skb->priority >= 256 && skb->priority <= 263)
287 return skb->priority - 256;
288 switch (skb->protocol) {
289 case htons(ETH_P_IP):
290 dscp = ip_hdr(skb)->tos & 0xfc;
291 break;
292 default:
293 return 0;
294 }
295 return dscp >> 5;
296}
297
298static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb,
299 void *accel_priv,
300 select_queue_fallback_t fallback)
301{
302 struct rtw_adapter *padapter = netdev_priv(dev);
303 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
304
305 skb->priority = rtw_classify8021d(skb);
306
307 if (pmlmepriv->acm_mask != 0)
308 skb->priority = qos_acm23a(pmlmepriv->acm_mask, skb->priority);
309 return rtw_1d_to_queue[skb->priority];
310}
311
312u16 rtw_recv_select_queue23a(struct sk_buff *skb)
313{
314 struct iphdr *piphdr;
315 unsigned int dscp;
316 u16 eth_type;
317 u32 priority;
318 u8 *pdata = skb->data;
319
320 memcpy(&eth_type, pdata + (ETH_ALEN << 1), 2);
321 switch (eth_type) {
322 case htons(ETH_P_IP):
323 piphdr = (struct iphdr *)(pdata + ETH_HLEN);
324 dscp = piphdr->tos & 0xfc;
325 priority = dscp >> 5;
326 break;
327 default:
328 priority = 0;
329 }
330 return rtw_1d_to_queue[priority];
331}
332
333static const struct net_device_ops rtw_netdev_ops = {
334 .ndo_open = netdev_open23a,
335 .ndo_stop = netdev_close,
336 .ndo_start_xmit = rtw_xmit23a_entry23a,
337 .ndo_select_queue = rtw_select_queue,
338 .ndo_set_mac_address = rtw_net_set_mac_address,
339 .ndo_get_stats = rtw_net_get_stats,
340};
341
342int rtw_init_netdev23a_name23a(struct net_device *pnetdev, const char *ifname)
343{
344 if (dev_alloc_name(pnetdev, ifname) < 0) {
345 RT_TRACE(_module_os_intfs_c_, _drv_err_,
346 ("dev_alloc_name, fail!\n"));
347 }
348 netif_carrier_off(pnetdev);
349 return 0;
350}
351
352static const struct device_type wlan_type = {
353 .name = "wlan",
354};
355
356struct net_device *rtw_init_netdev23a(struct rtw_adapter *old_padapter)
357{
358 struct rtw_adapter *padapter;
359 struct net_device *pnetdev;
360
361 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+init_net_dev\n"));
362
363 pnetdev = alloc_etherdev_mq(sizeof(struct rtw_adapter), 4);
364 if (!pnetdev)
365 return NULL;
366
367 pnetdev->dev.type = &wlan_type;
368 padapter = netdev_priv(pnetdev);
369 padapter->pnetdev = pnetdev;
370
371 DBG_8723A("register rtw_netdev_ops to netdev_ops\n");
372 pnetdev->netdev_ops = &rtw_netdev_ops;
373
374 pnetdev->watchdog_timeo = HZ*3; /* 3 second timeout */
375
376 /* step 2. */
377 loadparam(padapter, pnetdev);
378 return pnetdev;
379}
380
381u32 rtw_start_drv_threads23a(struct rtw_adapter *padapter)
382{
383 u32 _status = _SUCCESS;
384
385 RT_TRACE(_module_os_intfs_c_, _drv_info_,
386 ("+rtw_start_drv_threads23a\n"));
387 padapter->cmdThread = kthread_run(rtw_cmd_thread23a, padapter,
388 "RTW_CMD_THREAD");
389 if (IS_ERR(padapter->cmdThread)) {
390 _status = _FAIL;
391 } else {
392 /* wait for cmd_thread to run */
393 down(&padapter->cmdpriv.terminate_cmdthread_sema);
394 }
395 rtw_hal_start_thread23a(padapter);
396 return _status;
397}
398
399void rtw_stop_drv_threads23a(struct rtw_adapter *padapter)
400{
401 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_stop_drv_threads23a\n"));
402
403 /* Below is to termindate rtw_cmd_thread23a & event_thread... */
404 up(&padapter->cmdpriv.cmd_queue_sema);
405 if (padapter->cmdThread)
406 down(&padapter->cmdpriv.terminate_cmdthread_sema);
407 rtw_hal_stop_thread23a(padapter);
408}
409
410static u8 rtw_init_default_value(struct rtw_adapter *padapter)
411{
412 struct registry_priv *pregistrypriv = &padapter->registrypriv;
413 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
414 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
415 struct security_priv *psecuritypriv = &padapter->securitypriv;
416 u8 ret = _SUCCESS;
417
418 /* xmit_priv */
419 pxmitpriv->vcs_setting = pregistrypriv->vrtl_carrier_sense;
420 pxmitpriv->vcs = pregistrypriv->vcs_type;
421 pxmitpriv->vcs_type = pregistrypriv->vcs_type;
422 /* pxmitpriv->rts_thresh = pregistrypriv->rts_thresh; */
423 pxmitpriv->frag_len = pregistrypriv->frag_thresh;
424
425 /* mlme_priv */
426 pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
427 pmlmepriv->scan_mode = SCAN_ACTIVE;
428
429 /* ht_priv */
430 pmlmepriv->htpriv.ampdu_enable = false;/* set to disabled */
431
432 /* security_priv */
433 psecuritypriv->binstallGrpkey = _FAIL;
434
435 /* open system */
436 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
437 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
438
439 psecuritypriv->dot11PrivacyKeyIndex = 0;
440
441 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
442 psecuritypriv->dot118021XGrpKeyid = 1;
443
444 psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
445 psecuritypriv->ndisencryptstatus = Ndis802_11WEPDisabled;
446
447 /* registry_priv */
448 rtw_init_registrypriv_dev_network23a(padapter);
449 rtw_update_registrypriv_dev_network23a(padapter);
450
451 /* hal_priv */
452 rtw_hal_def_value_init23a(padapter);
453
454 /* misc. */
455 padapter->bReadPortCancel = false;
456 padapter->bWritePortCancel = false;
457 padapter->bRxRSSIDisplay = 0;
458 padapter->bNotifyChannelChange = 0;
459#ifdef CONFIG_8723AU_P2P
460 padapter->bShowGetP2PState = 1;
461#endif
462 return ret;
463}
464
465u8 rtw_reset_drv_sw23a(struct rtw_adapter *padapter)
466{
467 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
468 struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
469 u8 ret8 = _SUCCESS;
470
471 /* hal_priv */
472 rtw_hal_def_value_init23a(padapter);
473 padapter->bReadPortCancel = false;
474 padapter->bWritePortCancel = false;
475 padapter->bRxRSSIDisplay = 0;
476 pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
477
478 padapter->xmitpriv.tx_pkts = 0;
479 padapter->recvpriv.rx_pkts = 0;
480
481 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
482
483 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING);
484
485 rtw_hal_sreset_reset23a_value23a(padapter);
486 pwrctrlpriv->pwr_state_check_cnts = 0;
487
488 /* mlmeextpriv */
489 padapter->mlmeextpriv.sitesurvey_res.state = SCAN_DISABLE;
490
491 rtw_set_signal_stat_timer(&padapter->recvpriv);
492 return ret8;
493}
494
495u8 rtw_init_drv_sw23a(struct rtw_adapter *padapter)
496{
497 u8 ret8 = _SUCCESS;
498
499 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_init_drv_sw23a\n"));
500
501 if ((rtw_init_cmd_priv23a(&padapter->cmdpriv)) == _FAIL) {
502 RT_TRACE(_module_os_intfs_c_, _drv_err_,
503 ("\n Can't init cmd_priv\n"));
504 ret8 = _FAIL;
505 goto exit;
506 }
507
508 padapter->cmdpriv.padapter = padapter;
509
510 if (rtw_init_evt_priv23a(&padapter->evtpriv) == _FAIL) {
511 RT_TRACE(_module_os_intfs_c_, _drv_err_,
512 ("\n Can't init evt_priv\n"));
513 ret8 = _FAIL;
514 goto exit;
515 }
516
517 if (rtw_init_mlme_priv23a(padapter) == _FAIL) {
518 RT_TRACE(_module_os_intfs_c_, _drv_err_,
519 ("\n Can't init mlme_priv\n"));
520 ret8 = _FAIL;
521 goto exit;
522 }
523
524#ifdef CONFIG_8723AU_P2P
525 rtw_init_wifidirect_timers23a(padapter);
526 init_wifidirect_info23a(padapter, P2P_ROLE_DISABLE);
527 reset_global_wifidirect_info23a(padapter);
528 rtw_init_cfg80211_wifidirect_info(padapter);
529#ifdef CONFIG_8723AU_P2P
530 if (rtw_init_wifi_display_info(padapter) == _FAIL)
531 RT_TRACE(_module_os_intfs_c_, _drv_err_,
532 ("\n Can't init init_wifi_display_info\n"));
533#endif
534#endif /* CONFIG_8723AU_P2P */
535
536 if (init_mlme_ext_priv23a(padapter) == _FAIL) {
537 RT_TRACE(_module_os_intfs_c_, _drv_err_,
538 ("\n Can't init mlme_ext_priv\n"));
539 ret8 = _FAIL;
540 goto exit;
541 }
542
543 if (_rtw_init_xmit_priv23a(&padapter->xmitpriv, padapter) == _FAIL) {
544 DBG_8723A("Can't _rtw_init_xmit_priv23a\n");
545 ret8 = _FAIL;
546 goto exit;
547 }
548
549 if (_rtw_init_recv_priv23a(&padapter->recvpriv, padapter) == _FAIL) {
550 DBG_8723A("Can't _rtw_init_recv_priv23a\n");
551 ret8 = _FAIL;
552 goto exit;
553 }
554
555 if (_rtw_init_sta_priv23a(&padapter->stapriv) == _FAIL) {
556 DBG_8723A("Can't _rtw_init_sta_priv23a\n");
557 ret8 = _FAIL;
558 goto exit;
559 }
560
561 padapter->stapriv.padapter = padapter;
562 padapter->setband = GHZ24_50;
563 rtw_init_bcmc_stainfo23a(padapter);
564
565 rtw_init_pwrctrl_priv23a(padapter);
566
567 ret8 = rtw_init_default_value(padapter);
568
569 rtw_hal_dm_init23a(padapter);
570 rtw_hal_sw_led_init23a(padapter);
571
572 rtw_hal_sreset_init23a(padapter);
573
574exit:
575
576 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-rtw_init_drv_sw23a\n"));
577 return ret8;
578}
579
580void rtw_cancel_all_timer23a(struct rtw_adapter *padapter)
581{
582 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_cancel_all_timer23a\n"));
583
584 del_timer_sync(&padapter->mlmepriv.assoc_timer);
585 RT_TRACE(_module_os_intfs_c_, _drv_info_,
586 ("rtw_cancel_all_timer23a:cancel association timer complete!\n"));
587
588 del_timer_sync(&padapter->mlmepriv.scan_to_timer);
589 RT_TRACE(_module_os_intfs_c_, _drv_info_,
590 ("rtw_cancel_all_timer23a:cancel scan_to_timer!\n"));
591
592 del_timer_sync(&padapter->mlmepriv.dynamic_chk_timer);
593 RT_TRACE(_module_os_intfs_c_, _drv_info_,
594 ("rtw_cancel_all_timer23a:cancel dynamic_chk_timer!\n"));
595
596 /* cancel sw led timer */
597 rtw_hal_sw_led_deinit23a(padapter);
598 RT_TRACE(_module_os_intfs_c_, _drv_info_,
599 ("rtw_cancel_all_timer23a:cancel DeInitSwLeds!\n"));
600
601 del_timer_sync(&padapter->pwrctrlpriv.pwr_state_check_timer);
602
603#ifdef CONFIG_8723AU_P2P
604 del_timer_sync(&padapter->cfg80211_wdinfo.remain_on_ch_timer);
605#endif /* CONFIG_8723AU_P2P */
606
607 del_timer_sync(&padapter->mlmepriv.set_scan_deny_timer);
608 rtw_clear_scan_deny(padapter);
609 RT_TRACE(_module_os_intfs_c_, _drv_info_,
610 ("rtw_cancel_all_timer23a:cancel set_scan_deny_timer!\n"));
611
612 del_timer_sync(&padapter->recvpriv.signal_stat_timer);
613 /* cancel dm timer */
614 rtw_hal_dm_deinit23a(padapter);
615}
616
617u8 rtw_free_drv_sw23a(struct rtw_adapter *padapter)
618{
619#ifdef CONFIG_8723AU_P2P
620 struct wifidirect_info *pwdinfo;
621#endif
622
623 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("==>rtw_free_drv_sw23a"));
624
625 /* we can call rtw_p2p_enable23a here, but:
626 * 1. rtw_p2p_enable23a may have IO operation
627 * 2. rtw_p2p_enable23a is bundled with wext interface
628 */
629#ifdef CONFIG_8723AU_P2P
630 pwdinfo = &padapter->wdinfo;
631 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
632 del_timer_sync(&pwdinfo->find_phase_timer);
633 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
634 del_timer_sync(&pwdinfo->pre_tx_scan_timer);
635 rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
636 }
637#endif
638
639 free_mlme_ext_priv23a(&padapter->mlmeextpriv);
640
641 rtw_free_cmd_priv23a(&padapter->cmdpriv);
642
643 rtw_free_evt_priv23a(&padapter->evtpriv);
644
645 rtw_free_mlme_priv23a(&padapter->mlmepriv);
646
647 _rtw_free_xmit_priv23a(&padapter->xmitpriv);
648
649 _rtw_free_sta_priv23a(&padapter->stapriv);/* will free bcmc_stainfo here */
650
651 _rtw_free_recv_priv23a(&padapter->recvpriv);
652
653 rtw_free_pwrctrl_priv(padapter);
654
655 rtw_hal_free_data23a(padapter);
656
657 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("<== rtw_free_drv_sw23a\n"));
658
659 /* free the old_pnetdev */
660 if (padapter->rereg_nd_name_priv.old_pnetdev) {
661 free_netdev(padapter->rereg_nd_name_priv.old_pnetdev);
662 padapter->rereg_nd_name_priv.old_pnetdev = NULL;
663 }
664
665 /* clear pbuddy_adapter to avoid access wrong pointer. */
666 if (padapter->pbuddy_adapter != NULL)
667 padapter->pbuddy_adapter->pbuddy_adapter = NULL;
668 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-rtw_free_drv_sw23a\n"));
669 return _SUCCESS;
670}
671
672static int _rtw_drv_register_netdev(struct rtw_adapter *padapter, char *name)
673{
674 struct net_device *pnetdev = padapter->pnetdev;
675 int ret = _SUCCESS;
676
677 /* alloc netdev name */
678 rtw_init_netdev23a_name23a(pnetdev, name);
679
680 ether_addr_copy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr);
681
682 /* Tell the network stack we exist */
683 if (register_netdev(pnetdev)) {
684 DBG_8723A(FUNC_NDEV_FMT "Failed!\n", FUNC_NDEV_ARG(pnetdev));
685 ret = _FAIL;
686 goto error_register_netdev;
687 }
688 DBG_8723A("%s, MAC Address (if%d) = " MAC_FMT "\n", __func__,
689 (padapter->iface_id + 1), MAC_ARG(pnetdev->dev_addr));
690 return ret;
691
692error_register_netdev:
693
694 if (padapter->iface_id > IFACE_ID0) {
695 rtw_free_drv_sw23a(padapter);
696
697 free_netdev(pnetdev);
698 }
699 return ret;
700}
701
702int rtw_drv_register_netdev(struct rtw_adapter *if1)
703{
704 struct dvobj_priv *dvobj = if1->dvobj;
705 int i, status = _SUCCESS;
706
707 if (dvobj->iface_nums < IFACE_ID_MAX) {
708 for (i = 0; i < dvobj->iface_nums; i++) {
709 struct rtw_adapter *padapter = dvobj->padapters[i];
710
711 if (padapter) {
712 char *name;
713
714 if (padapter->iface_id == IFACE_ID0)
715 name = if1->registrypriv.ifname;
716 else if (padapter->iface_id == IFACE_ID1)
717 name = if1->registrypriv.if2name;
718 else
719 name = "wlan%d";
720 status = _rtw_drv_register_netdev(padapter,
721 name);
722 if (status != _SUCCESS)
723 break;
724 }
725 }
726 }
727 return status;
728}
729
730int netdev_open23a(struct net_device *pnetdev)
731{
732 struct rtw_adapter *padapter = netdev_priv(pnetdev);
733 struct pwrctrl_priv *pwrctrlpriv;
734 int ret = 0;
735 uint status;
736
737 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+871x_drv - dev_open\n"));
738 DBG_8723A("+871x_drv - drv_open, bup =%d\n", padapter->bup);
739
740 mutex_lock(&adapter_to_dvobj(padapter)->hw_init_mutex);
741
742 pwrctrlpriv = &padapter->pwrctrlpriv;
743 if (pwrctrlpriv->ps_flag) {
744 padapter->net_closed = false;
745 goto netdev_open23a_normal_process;
746 }
747
748 if (!padapter->bup) {
749 padapter->bDriverStopped = false;
750 padapter->bSurpriseRemoved = false;
751 padapter->bCardDisableWOHSM = false;
752
753 status = rtw_hal_init23a(padapter);
754 if (status == _FAIL) {
755 RT_TRACE(_module_os_intfs_c_, _drv_err_,
756 ("rtl871x_hal_init(): Can't init h/w!\n"));
757 goto netdev_open23a_error;
758 }
759
760 DBG_8723A("MAC Address = "MAC_FMT"\n",
761 MAC_ARG(pnetdev->dev_addr));
762
763 status = rtw_start_drv_threads23a(padapter);
764 if (status == _FAIL) {
765 DBG_8723A("Initialize driver software resource Failed!\n");
766 goto netdev_open23a_error;
767 }
768
769 if (init_hw_mlme_ext23a(padapter) == _FAIL) {
770 DBG_8723A("can't init mlme_ext_priv\n");
771 goto netdev_open23a_error;
772 }
773
774 if (padapter->intf_start)
775 padapter->intf_start(padapter);
776
777 rtw_cfg80211_init_wiphy(padapter);
778
779 rtw_led_control(padapter, LED_CTL_NO_LINK);
780
781 padapter->bup = true;
782 }
783 padapter->net_closed = false;
784
785 mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
786 jiffies + msecs_to_jiffies(2000));
787
788 padapter->pwrctrlpriv.bips_processing = false;
789 rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
790
791 /* netif_carrier_on(pnetdev);call this func when
792 rtw23a_joinbss_event_cb return success */
793 if (!rtw_netif_queue_stopped(pnetdev))
794 netif_tx_start_all_queues(pnetdev);
795 else
796 netif_tx_wake_all_queues(pnetdev);
797
798netdev_open23a_normal_process:
799 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-871x_drv - dev_open\n"));
800 DBG_8723A("-871x_drv - drv_open, bup =%d\n", padapter->bup);
801exit:
802 mutex_unlock(&adapter_to_dvobj(padapter)->hw_init_mutex);
803 return ret;
804
805netdev_open23a_error:
806 padapter->bup = false;
807
808 netif_carrier_off(pnetdev);
809 netif_tx_stop_all_queues(pnetdev);
810
811 RT_TRACE(_module_os_intfs_c_, _drv_err_,
812 ("-871x_drv - dev_open, fail!\n"));
813 DBG_8723A("-871x_drv - drv_open fail, bup =%d\n", padapter->bup);
814
815 ret = -1;
816 goto exit;
817}
818
819static int ips_netdrv_open(struct rtw_adapter *padapter)
820{
821 int status = _SUCCESS;
822
823 padapter->net_closed = false;
824 DBG_8723A("===> %s.........\n", __func__);
825
826 padapter->bDriverStopped = false;
827 padapter->bSurpriseRemoved = false;
828 padapter->bCardDisableWOHSM = false;
829
830 status = rtw_hal_init23a(padapter);
831 if (status == _FAIL) {
832 RT_TRACE(_module_os_intfs_c_, _drv_err_,
833 ("ips_netdrv_open(): Can't init h/w!\n"));
834 goto netdev_open23a_error;
835 }
836
837 if (padapter->intf_start)
838 padapter->intf_start(padapter);
839
840 rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
841 mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
842 jiffies + msecs_to_jiffies(5000));
843
844 return _SUCCESS;
845
846netdev_open23a_error:
847 /* padapter->bup = false; */
848 DBG_8723A("-ips_netdrv_open - drv_open failure, bup =%d\n",
849 padapter->bup);
850
851 return _FAIL;
852}
853
854int rtw_ips_pwr_up23a(struct rtw_adapter *padapter)
855{
856 int result;
857 unsigned long start_time = jiffies;
858
859 DBG_8723A("===> rtw_ips_pwr_up23a..............\n");
860 rtw_reset_drv_sw23a(padapter);
861
862 result = ips_netdrv_open(padapter);
863
864 rtw_led_control(padapter, LED_CTL_NO_LINK);
865
866 DBG_8723A("<=== rtw_ips_pwr_up23a.............. in %dms\n",
867 jiffies_to_msecs(jiffies - start_time));
868 return result;
869}
870
871void rtw_ips_pwr_down23a(struct rtw_adapter *padapter)
872{
873 unsigned long start_time = jiffies;
874
875 DBG_8723A("===> rtw_ips_pwr_down23a...................\n");
876
877 padapter->bCardDisableWOHSM = true;
878 padapter->net_closed = true;
879
880 rtw_led_control(padapter, LED_CTL_POWER_OFF);
881
882 rtw_ips_dev_unload23a(padapter);
883 padapter->bCardDisableWOHSM = false;
884 DBG_8723A("<=== rtw_ips_pwr_down23a..................... in %dms\n",
885 jiffies_to_msecs(jiffies - start_time));
886}
887
888void rtw_ips_dev_unload23a(struct rtw_adapter *padapter)
889{
890 rtw_hal_set_hwreg23a(padapter, HW_VAR_FIFO_CLEARN_UP, NULL);
891
892 if (padapter->intf_stop)
893 padapter->intf_stop(padapter);
894
895 /* s5. */
896 if (!padapter->bSurpriseRemoved)
897 rtw_hal_deinit23a(padapter);
898}
899
900int pm_netdev_open23a(struct net_device *pnetdev, u8 bnormal)
901{
902 int status;
903
904 if (bnormal)
905 status = netdev_open23a(pnetdev);
906 else
907 status = (_SUCCESS == ips_netdrv_open(netdev_priv(pnetdev))) ?
908 (0) : (-1);
909
910 return status;
911}
912
913static int netdev_close(struct net_device *pnetdev)
914{
915 struct rtw_adapter *padapter = netdev_priv(pnetdev);
916
917 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+871x_drv - drv_close\n"));
918
919 if (padapter->pwrctrlpriv.bInternalAutoSuspend) {
920 if (padapter->pwrctrlpriv.rf_pwrstate == rf_off)
921 padapter->pwrctrlpriv.ps_flag = true;
922 }
923 padapter->net_closed = true;
924
925 if (padapter->pwrctrlpriv.rf_pwrstate == rf_on) {
926 DBG_8723A("(2)871x_drv - drv_close, bup =%d, hw_init_completed =%d\n",
927 padapter->bup,
928 padapter->hw_init_completed);
929
930 /* s1. */
931 if (pnetdev) {
932 if (!rtw_netif_queue_stopped(pnetdev))
933 netif_tx_stop_all_queues(pnetdev);
934 }
935
936 /* s2. */
937 LeaveAllPowerSaveMode23a(padapter);
938 rtw_disassoc_cmd23a(padapter, 500, false);
939 /* s2-2. indicate disconnect to os */
940 rtw_indicate_disconnect23a(padapter);
941 /* s2-3. */
942 rtw_free_assoc_resources23a(padapter, 1);
943 /* s2-4. */
944 rtw_free_network_queue23a(padapter, true);
945 /* Close LED */
946 rtw_led_control(padapter, LED_CTL_POWER_OFF);
947 }
948
949#ifdef CONFIG_8723AU_P2P
950 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled)
951 wdev_to_priv(padapter->rtw_wdev)->p2p_enabled = false;
952 rtw_p2p_enable23a(padapter, P2P_ROLE_DISABLE);
953#endif /* CONFIG_8723AU_P2P */
954
955 rtw_scan_abort23a(padapter);
956 /* set this at the end */
957 padapter->rtw_wdev->iftype = NL80211_IFTYPE_MONITOR;
958
959 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-871x_drv - drv_close\n"));
960 DBG_8723A("-871x_drv - drv_close, bup =%d\n", padapter->bup);
961
962 return 0;
963}
964
965void rtw_ndev_destructor(struct net_device *ndev)
966{
967 DBG_8723A(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
968 kfree(ndev->ieee80211_ptr);
969 free_netdev(ndev);
970}
diff --git a/drivers/staging/rtl8723au/os_dep/osdep_service.c b/drivers/staging/rtl8723au/os_dep/osdep_service.c
new file mode 100644
index 000000000000..97fc27dce19c
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/osdep_service.c
@@ -0,0 +1,175 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15
16
17#define _OSDEP_SERVICE_C_
18
19#include <osdep_service.h>
20#include <drv_types.h>
21#include <recv_osdep.h>
22#include <linux/vmalloc.h>
23
24#define RT_TAG ('1178')
25
26/*
27* Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE23a
28* @return: one of RTW_STATUS_CODE23a
29*/
30inline int RTW_STATUS_CODE23a(int error_code)
31{
32 if (error_code >= 0)
33 return _SUCCESS;
34 return _FAIL;
35}
36
37inline u8 *_rtw_vmalloc(u32 sz)
38{
39 u8 *pbuf;
40 pbuf = vmalloc(sz);
41
42 return pbuf;
43}
44
45inline u8 *_rtw_zvmalloc(u32 sz)
46{
47 u8 *pbuf;
48 pbuf = _rtw_vmalloc(sz);
49 if (pbuf != NULL)
50 memset(pbuf, 0, sz);
51
52 return pbuf;
53}
54
55inline void _rtw_vmfree(u8 *pbuf, u32 sz)
56{
57 vfree(pbuf);
58}
59
60void _rtw_init_queue23a(struct rtw_queue *pqueue)
61{
62 INIT_LIST_HEAD(&pqueue->queue);
63 spin_lock_init(&pqueue->lock);
64}
65
66u32 _rtw_queue_empty23a(struct rtw_queue *pqueue)
67{
68 if (list_empty(&pqueue->queue))
69 return true;
70 else
71 return false;
72}
73
74u64 rtw_modular6423a(u64 x, u64 y)
75{
76 return do_div(x, y);
77}
78
79u64 rtw_division6423a(u64 x, u64 y)
80{
81 do_div(x, y);
82 return x;
83}
84
85/* rtw_cbuf_full23a - test if cbuf is full
86 * @cbuf: pointer of struct rtw_cbuf
87 *
88 * Returns: true if cbuf is full
89 */
90inline bool rtw_cbuf_full23a(struct rtw_cbuf *cbuf)
91{
92 return (cbuf->write == cbuf->read-1) ? true : false;
93}
94
95/* rtw_cbuf_empty23a - test if cbuf is empty
96 * @cbuf: pointer of struct rtw_cbuf
97 *
98 * Returns: true if cbuf is empty
99 */
100inline bool rtw_cbuf_empty23a(struct rtw_cbuf *cbuf)
101{
102 return (cbuf->write == cbuf->read) ? true : false;
103}
104
105/**
106 * rtw_cbuf_push23a - push a pointer into cbuf
107 * @cbuf: pointer of struct rtw_cbuf
108 * @buf: pointer to push in
109 *
110 * Lock free operation, be careful of the use scheme
111 * Returns: true push success
112 */
113bool rtw_cbuf_push23a(struct rtw_cbuf *cbuf, void *buf)
114{
115 if (rtw_cbuf_full23a(cbuf))
116 return _FAIL;
117
118 if (0)
119 DBG_8723A("%s on %u\n", __func__, cbuf->write);
120 cbuf->bufs[cbuf->write] = buf;
121 cbuf->write = (cbuf->write+1)%cbuf->size;
122
123 return _SUCCESS;
124}
125
126/**
127 * rtw_cbuf_pop23a - pop a pointer from cbuf
128 * @cbuf: pointer of struct rtw_cbuf
129 *
130 * Lock free operation, be careful of the use scheme
131 * Returns: pointer popped out
132 */
133void *rtw_cbuf_pop23a(struct rtw_cbuf *cbuf)
134{
135 void *buf;
136 if (rtw_cbuf_empty23a(cbuf))
137 return NULL;
138
139 if (0)
140 DBG_8723A("%s on %u\n", __func__, cbuf->read);
141 buf = cbuf->bufs[cbuf->read];
142 cbuf->read = (cbuf->read+1)%cbuf->size;
143
144 return buf;
145}
146
147/**
148 * rtw_cbuf_alloc23a - allocte a rtw_cbuf with given size and do initialization
149 * @size: size of pointer
150 *
151 * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
152 */
153struct rtw_cbuf *rtw_cbuf_alloc23a(u32 size)
154{
155 struct rtw_cbuf *cbuf;
156
157 cbuf = kmalloc(sizeof(*cbuf) + sizeof(void *)*size, GFP_KERNEL);
158
159 if (cbuf) {
160 cbuf->write = 0;
161 cbuf->read = 0;
162 cbuf->size = size;
163 }
164
165 return cbuf;
166}
167
168/**
169 * rtw_cbuf_free - free the given rtw_cbuf
170 * @cbuf: pointer of struct rtw_cbuf to free
171 */
172void rtw_cbuf_free(struct rtw_cbuf *cbuf)
173{
174 kfree(cbuf);
175}
diff --git a/drivers/staging/rtl8723au/os_dep/recv_linux.c b/drivers/staging/rtl8723au/os_dep/recv_linux.c
new file mode 100644
index 000000000000..84402a589f25
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/recv_linux.c
@@ -0,0 +1,225 @@
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 ******************************************************************************/
15#define _RECV_OSDEP_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19
20#include <wifi.h>
21#include <recv_osdep.h>
22
23#include <osdep_intf.h>
24#include <ethernet.h>
25
26#include <usb_ops.h>
27
28/* alloc os related resource in struct recv_frame */
29int rtw_os_recv_resource_alloc23a(struct rtw_adapter *padapter,
30 struct recv_frame *precvframe)
31{
32 int res = _SUCCESS;
33
34 precvframe->pkt = NULL;
35
36 return res;
37}
38
39/* alloc os related resource in struct recv_buf */
40int rtw_os_recvbuf_resource_alloc23a(struct rtw_adapter *padapter,
41 struct recv_buf *precvbuf)
42{
43 int res = _SUCCESS;
44
45 precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
46 if (precvbuf->purb == NULL)
47 res = _FAIL;
48
49 precvbuf->pskb = NULL;
50
51 return res;
52}
53
54/* free os related resource in struct recv_buf */
55int rtw_os_recvbuf_resource_free23a(struct rtw_adapter *padapter,
56 struct recv_buf *precvbuf)
57{
58 int ret = _SUCCESS;
59
60 usb_free_urb(precvbuf->purb);
61
62 if (precvbuf->pskb)
63 dev_kfree_skb_any(precvbuf->pskb);
64
65 return ret;
66}
67
68void rtw_handle_tkip_mic_err23a(struct rtw_adapter *padapter, u8 bgroup)
69{
70 enum nl80211_key_type key_type = 0;
71 union iwreq_data wrqu;
72 struct iw_michaelmicfailure ev;
73 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
74 struct security_priv *psecuritypriv = &padapter->securitypriv;
75 unsigned long cur_time;
76
77 if (psecuritypriv->last_mic_err_time == 0) {
78 psecuritypriv->last_mic_err_time = jiffies;
79 } else {
80 cur_time = jiffies;
81
82 if (cur_time - psecuritypriv->last_mic_err_time < 60*HZ) {
83 psecuritypriv->btkip_countermeasure = true;
84 psecuritypriv->last_mic_err_time = 0;
85 psecuritypriv->btkip_countermeasure_time = cur_time;
86 } else {
87 psecuritypriv->last_mic_err_time = jiffies;
88 }
89 }
90
91 if (bgroup)
92 key_type |= NL80211_KEYTYPE_GROUP;
93 else
94 key_type |= NL80211_KEYTYPE_PAIRWISE;
95
96 cfg80211_michael_mic_failure(padapter->pnetdev,
97 (u8 *)&pmlmepriv->assoc_bssid[0],
98 key_type, -1, NULL, GFP_ATOMIC);
99
100 memset(&ev, 0x00, sizeof(ev));
101 if (bgroup)
102 ev.flags |= IW_MICFAILURE_GROUP;
103 else
104 ev.flags |= IW_MICFAILURE_PAIRWISE;
105
106 ev.src_addr.sa_family = ARPHRD_ETHER;
107 ether_addr_copy(ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[0]);
108
109 memset(&wrqu, 0x00, sizeof(wrqu));
110 wrqu.data.length = sizeof(ev);
111}
112
113void rtw_hostapd_mlme_rx23a(struct rtw_adapter *padapter,
114 struct recv_frame *precv_frame)
115{
116}
117
118int rtw_recv_indicatepkt23a(struct rtw_adapter *padapter,
119 struct recv_frame *precv_frame)
120{
121 struct recv_priv *precvpriv;
122 struct rtw_queue *pfree_recv_queue;
123 struct sk_buff *skb;
124 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
125
126 precvpriv = &(padapter->recvpriv);
127 pfree_recv_queue = &(precvpriv->free_recv_queue);
128
129 skb = precv_frame->pkt;
130 if (!skb) {
131 RT_TRACE(_module_recv_osdep_c_, _drv_err_,
132 ("rtw_recv_indicatepkt23a():skb == NULL!!!!\n"));
133 goto _recv_indicatepkt_drop;
134 }
135
136 RT_TRACE(_module_recv_osdep_c_, _drv_info_,
137 ("rtw_recv_indicatepkt23a():skb != NULL !!!\n"));
138 RT_TRACE(_module_recv_osdep_c_, _drv_info_,
139 ("rtw_recv_indicatepkt23a():precv_frame->hdr.rx_data =%p\n",
140 precv_frame->pkt->data));
141 RT_TRACE(_module_recv_osdep_c_, _drv_info_,
142 ("\n skb->head =%p skb->data =%p skb->tail =%p skb->end =%p skb->len =%d\n",
143 skb->head, skb->data,
144 skb_tail_pointer(skb), skb_end_pointer(skb), skb->len));
145
146 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
147 struct sk_buff *pskb2 = NULL;
148 struct sta_info *psta = NULL;
149 struct sta_priv *pstapriv = &padapter->stapriv;
150 struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
151 int bmcast = is_multicast_ether_addr(pattrib->dst);
152
153 /* DBG_8723A("bmcast =%d\n", bmcast); */
154
155 if (!ether_addr_equal(pattrib->dst,
156 myid(&padapter->eeprompriv))) {
157 /* DBG_8723A("not ap psta =%p, addr =%pM\n", psta, pattrib->dst); */
158 if (bmcast) {
159 psta = rtw_get_bcmc_stainfo23a(padapter);
160 pskb2 = skb_clone(skb, GFP_ATOMIC);
161 } else {
162 psta = rtw_get_stainfo23a(pstapriv, pattrib->dst);
163 }
164
165 if (psta) {
166 struct net_device *pnetdev = padapter->pnetdev;
167
168 /* DBG_8723A("directly forwarding to the rtw_xmit23a_entry23a\n"); */
169
170 /* skb->ip_summed = CHECKSUM_NONE; */
171 skb->dev = pnetdev;
172 skb_set_queue_mapping(skb, rtw_recv_select_queue23a(skb));
173
174 rtw_xmit23a_entry23a(skb, pnetdev);
175
176 if (bmcast)
177 skb = pskb2;
178 else
179 goto _recv_indicatepkt_end;
180 }
181 } else { /* to APself */
182 /* DBG_8723A("to APSelf\n"); */
183 }
184 }
185
186 skb->ip_summed = CHECKSUM_NONE;
187 skb->dev = padapter->pnetdev;
188 skb->protocol = eth_type_trans(skb, padapter->pnetdev);
189
190 netif_rx(skb);
191
192_recv_indicatepkt_end:
193
194 precv_frame->pkt = NULL; /* pointers to NULL before rtw_free_recvframe23a() */
195
196 rtw_free_recvframe23a(precv_frame, pfree_recv_queue);
197
198 RT_TRACE(_module_recv_osdep_c_, _drv_info_,
199 ("\n rtw_recv_indicatepkt23a :after netif_rx!!!!\n"));
200 return _SUCCESS;
201
202_recv_indicatepkt_drop:
203
204 rtw_free_recvframe23a(precv_frame, pfree_recv_queue);
205 return _FAIL;
206}
207
208void rtw_os_read_port23a(struct rtw_adapter *padapter, struct recv_buf *precvbuf)
209{
210 struct recv_priv *precvpriv = &padapter->recvpriv;
211
212 /* free skb in recv_buf */
213 dev_kfree_skb_any(precvbuf->pskb);
214
215 precvbuf->pskb = NULL;
216
217 rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, precvbuf);
218}
219
220void rtw_init_recv_timer23a(struct recv_reorder_ctrl *preorder_ctrl)
221{
222 setup_timer(&preorder_ctrl->reordering_ctrl_timer,
223 rtw_reordering_ctrl_timeout_handler23a,
224 (unsigned long)preorder_ctrl);
225}
diff --git a/drivers/staging/rtl8723au/os_dep/usb_intf.c b/drivers/staging/rtl8723au/os_dep/usb_intf.c
new file mode 100644
index 000000000000..612806e0de2e
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/usb_intf.c
@@ -0,0 +1,833 @@
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 ******************************************************************************/
15#define _HCI_INTF_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <recv_osdep.h>
20#include <xmit_osdep.h>
21#include <hal_intf.h>
22#include <rtw_version.h>
23#include <osdep_intf.h>
24#include <usb_vendor_req.h>
25#include <usb_ops.h>
26#include <usb_osintf.h>
27#include <usb_hal.h>
28
29static int rtw_suspend(struct usb_interface *intf, pm_message_t message);
30static int rtw_resume(struct usb_interface *intf);
31static int rtw_drv_init(struct usb_interface *pusb_intf,
32 const struct usb_device_id *pdid);
33static void rtw_disconnect(struct usb_interface *pusb_intf);
34
35#define USB_VENDER_ID_REALTEK 0x0BDA
36
37#define RTL8723A_USB_IDS \
38 {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x8724, \
39 0xff, 0xff, 0xff)}, /* 8723AU 1*1 */ \
40 {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x1724, \
41 0xff, 0xff, 0xff)}, /* 8723AU 1*1 */ \
42 {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x0724, \
43 0xff, 0xff, 0xff)}, /* 8723AU 1*1 */
44
45static struct usb_device_id rtl8723a_usb_id_tbl[] = {
46 RTL8723A_USB_IDS
47 {} /* Terminating entry */
48};
49
50MODULE_DEVICE_TABLE(usb, rtl8723a_usb_id_tbl);
51
52static struct usb_driver rtl8723a_usb_drv = {
53 .name = (char *)"rtl8723au",
54 .probe = rtw_drv_init,
55 .disconnect = rtw_disconnect,
56 .id_table = rtl8723a_usb_id_tbl,
57 .suspend = rtw_suspend,
58 .resume = rtw_resume,
59 .reset_resume = rtw_resume,
60};
61
62static struct usb_driver *usb_drv = &rtl8723a_usb_drv;
63
64static inline int RT_usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
65{
66 return (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN;
67}
68
69static inline int RT_usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
70{
71 return (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT;
72}
73
74static inline int RT_usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
75{
76 return (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT;
77}
78
79static inline int RT_usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
80{
81 return (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK;
82}
83
84static inline int RT_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
85{
86 return RT_usb_endpoint_xfer_bulk(epd) && RT_usb_endpoint_dir_in(epd);
87}
88
89static inline int RT_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
90{
91 return RT_usb_endpoint_xfer_bulk(epd) && RT_usb_endpoint_dir_out(epd);
92}
93
94static inline int RT_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
95{
96 return RT_usb_endpoint_xfer_int(epd) && RT_usb_endpoint_dir_in(epd);
97}
98
99static inline int RT_usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
100{
101 return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
102}
103
104static u8 rtw_init_intf_priv(struct dvobj_priv *dvobj)
105{
106 u8 rst = _SUCCESS;
107
108 mutex_init(&dvobj->usb_vendor_req_mutex);
109 dvobj->usb_alloc_vendor_req_buf = kzalloc(MAX_USB_IO_CTL_SIZE,
110 GFP_KERNEL);
111 if (dvobj->usb_alloc_vendor_req_buf == NULL) {
112 DBG_8723A("alloc usb_vendor_req_buf failed... /n");
113 rst = _FAIL;
114 goto exit;
115 }
116 dvobj->usb_vendor_req_buf =
117 PTR_ALIGN(dvobj->usb_alloc_vendor_req_buf, ALIGNMENT_UNIT);
118exit:
119 return rst;
120}
121
122static u8 rtw_deinit_intf_priv(struct dvobj_priv *dvobj)
123{
124 u8 rst = _SUCCESS;
125
126 kfree(dvobj->usb_alloc_vendor_req_buf);
127
128 mutex_destroy(&dvobj->usb_vendor_req_mutex);
129
130 return rst;
131}
132
133static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
134{
135 struct dvobj_priv *pdvobjpriv;
136 struct usb_device_descriptor *pdev_desc;
137 struct usb_host_config *phost_conf;
138 struct usb_config_descriptor *pconf_desc;
139 struct usb_host_interface *phost_iface;
140 struct usb_interface_descriptor *piface_desc;
141 struct usb_host_endpoint *phost_endp;
142 struct usb_endpoint_descriptor *pendp_desc;
143 struct usb_device *pusbd;
144 int i;
145 int status = _FAIL;
146
147 pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL);
148 if (!pdvobjpriv)
149 goto exit;
150
151 mutex_init(&pdvobjpriv->hw_init_mutex);
152 mutex_init(&pdvobjpriv->h2c_fwcmd_mutex);
153 mutex_init(&pdvobjpriv->setch_mutex);
154 mutex_init(&pdvobjpriv->setbw_mutex);
155
156 pdvobjpriv->pusbintf = usb_intf;
157 pusbd = interface_to_usbdev(usb_intf);
158 pdvobjpriv->pusbdev = pusbd;
159 usb_set_intfdata(usb_intf, pdvobjpriv);
160
161 pdvobjpriv->RtNumInPipes = 0;
162 pdvobjpriv->RtNumOutPipes = 0;
163
164 pdev_desc = &pusbd->descriptor;
165
166 phost_conf = pusbd->actconfig;
167 pconf_desc = &phost_conf->desc;
168
169 phost_iface = &usb_intf->altsetting[0];
170 piface_desc = &phost_iface->desc;
171
172 pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces;
173 pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber;
174 pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
175
176 for (i = 0; i < pdvobjpriv->nr_endpoint; i++) {
177 phost_endp = phost_iface->endpoint + i;
178 if (phost_endp) {
179 pendp_desc = &phost_endp->desc;
180
181 DBG_8723A("\nusb_endpoint_descriptor(%d):\n", i);
182 DBG_8723A("bLength =%x\n", pendp_desc->bLength);
183 DBG_8723A("bDescriptorType =%x\n",
184 pendp_desc->bDescriptorType);
185 DBG_8723A("bEndpointAddress =%x\n",
186 pendp_desc->bEndpointAddress);
187 DBG_8723A("wMaxPacketSize =%d\n",
188 le16_to_cpu(pendp_desc->wMaxPacketSize));
189 DBG_8723A("bInterval =%x\n", pendp_desc->bInterval);
190
191 if (RT_usb_endpoint_is_bulk_in(pendp_desc)) {
192 DBG_8723A("RT_usb_endpoint_is_bulk_in = %x\n",
193 RT_usb_endpoint_num(pendp_desc));
194 pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] =
195 RT_usb_endpoint_num(pendp_desc);
196 pdvobjpriv->RtNumInPipes++;
197 } else if (RT_usb_endpoint_is_int_in(pendp_desc)) {
198 DBG_8723A("RT_usb_endpoint_is_int_in = %x, Interval = %x\n",
199 RT_usb_endpoint_num(pendp_desc),
200 pendp_desc->bInterval);
201 pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] =
202 RT_usb_endpoint_num(pendp_desc);
203 pdvobjpriv->RtNumInPipes++;
204 } else if (RT_usb_endpoint_is_bulk_out(pendp_desc)) {
205 DBG_8723A("RT_usb_endpoint_is_bulk_out = %x\n",
206 RT_usb_endpoint_num(pendp_desc));
207 pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] =
208 RT_usb_endpoint_num(pendp_desc);
209 pdvobjpriv->RtNumOutPipes++;
210 }
211 pdvobjpriv->ep_num[i] = RT_usb_endpoint_num(pendp_desc);
212 }
213 }
214 DBG_8723A("nr_endpoint =%d, in_num =%d, out_num =%d\n\n",
215 pdvobjpriv->nr_endpoint, pdvobjpriv->RtNumInPipes,
216 pdvobjpriv->RtNumOutPipes);
217
218 if (pusbd->speed == USB_SPEED_HIGH) {
219 pdvobjpriv->ishighspeed = true;
220 DBG_8723A("USB_SPEED_HIGH\n");
221 } else {
222 pdvobjpriv->ishighspeed = false;
223 DBG_8723A("NON USB_SPEED_HIGH\n");
224 }
225
226 if (rtw_init_intf_priv(pdvobjpriv) == _FAIL) {
227 RT_TRACE(_module_os_intfs_c_, _drv_err_,
228 ("\n Can't INIT rtw_init_intf_priv\n"));
229 goto free_dvobj;
230 }
231 /* 3 misc */
232 sema_init(&(pdvobjpriv->usb_suspend_sema), 0);
233 rtw_reset_continual_urb_error(pdvobjpriv);
234 usb_get_dev(pusbd);
235 status = _SUCCESS;
236free_dvobj:
237 if (status != _SUCCESS && pdvobjpriv) {
238 usb_set_intfdata(usb_intf, NULL);
239 mutex_destroy(&pdvobjpriv->hw_init_mutex);
240 mutex_destroy(&pdvobjpriv->h2c_fwcmd_mutex);
241 mutex_destroy(&pdvobjpriv->setch_mutex);
242 mutex_destroy(&pdvobjpriv->setbw_mutex);
243 kfree(pdvobjpriv);
244 pdvobjpriv = NULL;
245 }
246exit:
247 return pdvobjpriv;
248}
249
250static void usb_dvobj_deinit(struct usb_interface *usb_intf)
251{
252 struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf);
253
254 usb_set_intfdata(usb_intf, NULL);
255 if (dvobj) {
256 /* Modify condition for 92DU DMDP 2010.11.18, by Thomas */
257 if ((dvobj->NumInterfaces != 2 && dvobj->NumInterfaces != 3) ||
258 (dvobj->InterfaceNumber == 1)) {
259 if (interface_to_usbdev(usb_intf)->state !=
260 USB_STATE_NOTATTACHED) {
261 /* If we didn't unplug usb dongle and
262 * remove/insert module, driver fails on
263 * sitesurvey for the first time when
264 * device is up .
265 * Reset usb port for sitesurvey fail issue.
266 */
267 DBG_8723A("usb attached..., try to reset usb device\n");
268 usb_reset_device(interface_to_usbdev(usb_intf));
269 }
270 }
271 rtw_deinit_intf_priv(dvobj);
272 mutex_destroy(&dvobj->hw_init_mutex);
273 mutex_destroy(&dvobj->h2c_fwcmd_mutex);
274 mutex_destroy(&dvobj->setch_mutex);
275 mutex_destroy(&dvobj->setbw_mutex);
276 kfree(dvobj);
277 }
278 usb_put_dev(interface_to_usbdev(usb_intf));
279}
280
281static void decide_chip_type_by_usb_device_id(struct rtw_adapter *padapter,
282 const struct usb_device_id *pdid)
283{
284 padapter->chip_type = NULL_CHIP_TYPE;
285 hal_set_hw_type(padapter);
286}
287
288static void usb_intf_start(struct rtw_adapter *padapter)
289{
290 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_start\n"));
291 rtw_hal_inirp_init23a(padapter);
292 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-usb_intf_start\n"));
293}
294
295static void usb_intf_stop(struct rtw_adapter *padapter)
296{
297 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_stop\n"));
298
299 /* disable_hw_interrupt */
300 if (!padapter->bSurpriseRemoved) {
301 /* device still exists, so driver can do i/o operation
302 * TODO:
303 */
304 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
305 ("SurpriseRemoved == false\n"));
306 }
307
308 /* cancel in irp */
309 rtw_hal_inirp_deinit23a(padapter);
310
311 /* cancel out irp */
312 rtw_write_port_cancel(padapter);
313
314 /* todo:cancel other irps */
315 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-usb_intf_stop\n"));
316}
317
318static void rtw_dev_unload(struct rtw_adapter *padapter)
319{
320 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_dev_unload\n"));
321
322 if (padapter->bup) {
323 DBG_8723A("===> rtw_dev_unload\n");
324
325 padapter->bDriverStopped = true;
326 if (padapter->xmitpriv.ack_tx)
327 rtw_ack_tx_done23a(&padapter->xmitpriv,
328 RTW_SCTX_DONE_DRV_STOP);
329
330 /* s3. */
331 if (padapter->intf_stop)
332 padapter->intf_stop(padapter);
333
334 /* s4. */
335 if (!padapter->pwrctrlpriv.bInternalAutoSuspend)
336 rtw_stop_drv_threads23a(padapter);
337
338 /* s5. */
339 if (!padapter->bSurpriseRemoved) {
340 rtw_hal_deinit23a(padapter);
341 padapter->bSurpriseRemoved = true;
342 }
343 padapter->bup = false;
344 } else {
345 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
346 ("r871x_dev_unload():padapter->bup == false\n"));
347 }
348 DBG_8723A("<=== rtw_dev_unload\n");
349 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n"));
350}
351
352int rtw_hw_suspend23a(struct rtw_adapter *padapter)
353{
354 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
355 struct net_device *pnetdev = padapter->pnetdev;
356
357 if ((!padapter->bup) || (padapter->bDriverStopped) ||
358 (padapter->bSurpriseRemoved)) {
359 DBG_8723A("padapter->bup =%d bDriverStopped =%d bSurpriseRemoved = %d\n",
360 padapter->bup, padapter->bDriverStopped,
361 padapter->bSurpriseRemoved);
362 goto error_exit;
363 }
364
365 if (padapter) { /* system suspend */
366 LeaveAllPowerSaveMode23a(padapter);
367
368 DBG_8723A("==> rtw_hw_suspend23a\n");
369 down(&pwrpriv->lock);
370 pwrpriv->bips_processing = true;
371 /* padapter->net_closed = true; */
372 /* s1. */
373 if (pnetdev) {
374 netif_carrier_off(pnetdev);
375 netif_tx_stop_all_queues(pnetdev);
376 }
377
378 /* s2. */
379 rtw_disassoc_cmd23a(padapter, 500, false);
380
381 /* s2-2. indicate disconnect to os */
382 /* rtw_indicate_disconnect23a(padapter); */
383 {
384 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
385
386 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
387 _clr_fwstate_(pmlmepriv, _FW_LINKED);
388
389 rtw_led_control(padapter, LED_CTL_NO_LINK);
390
391 rtw_os_indicate_disconnect23a(padapter);
392
393 /* donnot enqueue cmd */
394 rtw_lps_ctrl_wk_cmd23a(padapter,
395 LPS_CTRL_DISCONNECT, 0);
396 }
397 }
398 /* s2-3. */
399 rtw_free_assoc_resources23a(padapter, 1);
400
401 /* s2-4. */
402 rtw_free_network_queue23a(padapter, true);
403 rtw_ips_dev_unload23a(padapter);
404 pwrpriv->rf_pwrstate = rf_off;
405 pwrpriv->bips_processing = false;
406 up(&pwrpriv->lock);
407 } else {
408 goto error_exit;
409 }
410 return 0;
411error_exit:
412 DBG_8723A("%s, failed\n", __func__);
413 return -1;
414}
415
416int rtw_hw_resume23a(struct rtw_adapter *padapter)
417{
418 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
419 struct net_device *pnetdev = padapter->pnetdev;
420
421 if (padapter) { /* system resume */
422 DBG_8723A("==> rtw_hw_resume23a\n");
423 down(&pwrpriv->lock);
424 pwrpriv->bips_processing = true;
425 rtw_reset_drv_sw23a(padapter);
426
427 if (pm_netdev_open23a(pnetdev, false)) {
428 up(&pwrpriv->lock);
429 goto error_exit;
430 }
431
432 netif_device_attach(pnetdev);
433 netif_carrier_on(pnetdev);
434
435 if (!rtw_netif_queue_stopped(pnetdev))
436 netif_tx_start_all_queues(pnetdev);
437 else
438 netif_tx_wake_all_queues(pnetdev);
439
440 pwrpriv->bkeepfwalive = false;
441 pwrpriv->brfoffbyhw = false;
442
443 pwrpriv->rf_pwrstate = rf_on;
444 pwrpriv->bips_processing = false;
445
446 up(&pwrpriv->lock);
447 } else {
448 goto error_exit;
449 }
450 return 0;
451error_exit:
452 DBG_8723A("%s, Open net dev failed\n", __func__);
453 return -1;
454}
455
456static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
457{
458 struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
459 struct rtw_adapter *padapter = dvobj->if1;
460 struct net_device *pnetdev = padapter->pnetdev;
461 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
462 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
463 int ret = 0;
464 unsigned long start_time = jiffies;
465
466 DBG_8723A("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
467
468 if ((!padapter->bup) || (padapter->bDriverStopped) ||
469 (padapter->bSurpriseRemoved)) {
470 DBG_8723A("padapter->bup =%d bDriverStopped =%d bSurpriseRemoved = %d\n",
471 padapter->bup, padapter->bDriverStopped,
472 padapter->bSurpriseRemoved);
473 goto exit;
474 }
475 pwrpriv->bInSuspend = true;
476 rtw_cancel_all_timer23a(padapter);
477 LeaveAllPowerSaveMode23a(padapter);
478
479 down(&pwrpriv->lock);
480 /* padapter->net_closed = true; */
481 /* s1. */
482 if (pnetdev) {
483 netif_carrier_off(pnetdev);
484 netif_tx_stop_all_queues(pnetdev);
485 }
486
487 /* s2. */
488 rtw_disassoc_cmd23a(padapter, 0, false);
489
490 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
491 check_fwstate(pmlmepriv, _FW_LINKED)) {
492 DBG_8723A("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n",
493 __func__, __LINE__,
494 pmlmepriv->cur_network.network.Ssid.ssid,
495 pmlmepriv->cur_network.network.MacAddress,
496 pmlmepriv->cur_network.network.Ssid.ssid_len,
497 pmlmepriv->assoc_ssid.ssid_len);
498
499 rtw_set_roaming(padapter, 1);
500 }
501 /* s2-2. indicate disconnect to os */
502 rtw_indicate_disconnect23a(padapter);
503 /* s2-3. */
504 rtw_free_assoc_resources23a(padapter, 1);
505 /* s2-4. */
506 rtw_free_network_queue23a(padapter, true);
507
508 rtw_dev_unload(padapter);
509 up(&pwrpriv->lock);
510
511 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
512 rtw_indicate_scan_done23a(padapter, 1);
513
514 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
515 rtw_indicate_disconnect23a(padapter);
516
517exit:
518 DBG_8723A("<=== %s return %d.............. in %dms\n", __func__,
519 ret, jiffies_to_msecs(jiffies - start_time));
520
521 return ret;
522}
523
524static int rtw_resume(struct usb_interface *pusb_intf)
525{
526 struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
527 struct rtw_adapter *padapter = dvobj->if1;
528 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
529 int ret = 0;
530
531 if (pwrpriv->bInternalAutoSuspend)
532 ret = rtw_resume_process23a(padapter);
533 else
534 ret = rtw_resume_process23a(padapter);
535
536 return ret;
537}
538
539int rtw_resume_process23a(struct rtw_adapter *padapter)
540{
541 struct net_device *pnetdev;
542 struct pwrctrl_priv *pwrpriv = NULL;
543 int ret = -1;
544 unsigned long start_time = jiffies;
545
546 DBG_8723A("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
547
548 if (!padapter)
549 goto exit;
550 pnetdev = padapter->pnetdev;
551 pwrpriv = &padapter->pwrctrlpriv;
552
553 down(&pwrpriv->lock);
554 rtw_reset_drv_sw23a(padapter);
555 pwrpriv->bkeepfwalive = false;
556
557 DBG_8723A("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive);
558 if (pm_netdev_open23a(pnetdev, true) != 0)
559 goto exit;
560
561 netif_device_attach(pnetdev);
562 netif_carrier_on(pnetdev);
563
564 up(&pwrpriv->lock);
565
566 if (padapter->pid[1] != 0) {
567 DBG_8723A("pid[1]:%d\n", padapter->pid[1]);
568 rtw_signal_process(padapter->pid[1], SIGUSR2);
569 }
570
571 rtw23a_roaming(padapter, NULL);
572
573 ret = 0;
574exit:
575 if (pwrpriv)
576 pwrpriv->bInSuspend = false;
577 DBG_8723A("<=== %s return %d.............. in %dms\n", __func__,
578 ret, jiffies_to_msecs(jiffies - start_time));
579
580 return ret;
581}
582
583/*
584 * drv_init() - a device potentially for us
585 *
586 * notes: drv_init() is called when the bus driver has located a card
587 * for us to support.
588 * We accept the new device by returning 0.
589 */
590static struct rtw_adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
591 struct usb_interface *pusb_intf,
592 const struct usb_device_id *pdid)
593{
594 struct rtw_adapter *padapter = NULL;
595 struct net_device *pnetdev = NULL;
596 int status = _FAIL;
597
598 pnetdev = rtw_init_netdev23a(padapter);
599 if (!pnetdev)
600 goto handle_dualmac;
601 padapter = netdev_priv(pnetdev);
602
603 padapter->dvobj = dvobj;
604 padapter->bDriverStopped = true;
605 dvobj->if1 = padapter;
606 dvobj->padapters[dvobj->iface_nums++] = padapter;
607 padapter->iface_id = IFACE_ID0;
608
609 /* step 1-1., decide the chip_type via vid/pid */
610 decide_chip_type_by_usb_device_id(padapter, pdid);
611
612 if (rtw_handle_dualmac23a(padapter, 1) != _SUCCESS)
613 goto free_adapter;
614
615 SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
616
617 if (rtw_wdev_alloc(padapter, dvobj_to_dev(dvobj)))
618 goto handle_dualmac;
619
620 /* step 2. hook HalFunc, allocate HalData */
621 if (rtl8723au_set_hal_ops(padapter))
622 return NULL;
623
624 padapter->intf_start = &usb_intf_start;
625 padapter->intf_stop = &usb_intf_stop;
626
627 /* step init_io_priv */
628 rtw_init_io_priv23a(padapter, usb_set_intf_ops);
629
630 /* step read_chip_version */
631 rtw_hal_read_chip_version23a(padapter);
632
633 /* step usb endpoint mapping */
634 rtw_hal_chip_configure23a(padapter);
635
636 /* step read efuse/eeprom data and get mac_addr */
637 rtw_hal_read_chip_info23a(padapter);
638
639 /* step 5. */
640 if (rtw_init_drv_sw23a(padapter) == _FAIL) {
641 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
642 ("Initialize driver software resource Failed!\n"));
643 goto free_hal_data;
644 }
645
646#ifdef CONFIG_PM
647 if (padapter->pwrctrlpriv.bSupportRemoteWakeup) {
648 dvobj->pusbdev->do_remote_wakeup = 1;
649 pusb_intf->needs_remote_wakeup = 1;
650 device_init_wakeup(&pusb_intf->dev, 1);
651 DBG_8723A("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n");
652 DBG_8723A("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n",
653 device_may_wakeup(&pusb_intf->dev));
654 }
655#endif
656 /* 2012-07-11 Move here to prevent the 8723AS-VAU BT
657 * auto suspend influence
658 */
659 if (usb_autopm_get_interface(pusb_intf) < 0)
660 DBG_8723A("can't get autopm:\n");
661#ifdef CONFIG_8723AU_BT_COEXIST
662 padapter->pwrctrlpriv.autopm_cnt = 1;
663#endif
664
665 /* set mac addr */
666 rtw_macaddr_cfg23a(padapter->eeprompriv.mac_addr);
667#ifdef CONFIG_8723AU_P2P
668 rtw_init_wifidirect_addrs23a(padapter, padapter->eeprompriv.mac_addr,
669 padapter->eeprompriv.mac_addr);
670#endif
671
672 DBG_8723A("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n",
673 padapter->bDriverStopped, padapter->bSurpriseRemoved,
674 padapter->bup, padapter->hw_init_completed
675 );
676 status = _SUCCESS;
677
678free_hal_data:
679 if (status != _SUCCESS)
680 kfree(padapter->HalData);
681 if (status != _SUCCESS) {
682 rtw_wdev_unregister(padapter->rtw_wdev);
683 rtw_wdev_free(padapter->rtw_wdev);
684 }
685handle_dualmac:
686 if (status != _SUCCESS)
687 rtw_handle_dualmac23a(padapter, 0);
688free_adapter:
689 if (status != _SUCCESS) {
690 if (pnetdev)
691 free_netdev(pnetdev);
692 padapter = NULL;
693 }
694 return padapter;
695}
696
697static void rtw_usb_if1_deinit(struct rtw_adapter *if1)
698{
699 struct net_device *pnetdev = if1->pnetdev;
700 struct mlme_priv *pmlmepriv = &if1->mlmepriv;
701
702 if (check_fwstate(pmlmepriv, _FW_LINKED))
703 rtw_disassoc_cmd23a(if1, 0, false);
704
705#ifdef CONFIG_8723AU_AP_MODE
706 free_mlme_ap_info23a(if1);
707#endif
708
709 if (pnetdev)
710 unregister_netdev(pnetdev); /* will call netdev_close() */
711
712 rtw_cancel_all_timer23a(if1);
713
714 rtw_dev_unload(if1);
715
716 DBG_8723A("+r871xu_dev_remove, hw_init_completed =%d\n",
717 if1->hw_init_completed);
718
719 rtw_handle_dualmac23a(if1, 0);
720
721 if (if1->rtw_wdev) {
722 rtw_wdev_unregister(if1->rtw_wdev);
723 rtw_wdev_free(if1->rtw_wdev);
724 }
725
726#ifdef CONFIG_8723AU_BT_COEXIST
727 if (1 == if1->pwrctrlpriv.autopm_cnt) {
728 usb_autopm_put_interface(adapter_to_dvobj(if1)->pusbintf);
729 if1->pwrctrlpriv.autopm_cnt--;
730 }
731#endif
732
733 rtw_free_drv_sw23a(if1);
734
735 if (pnetdev)
736 free_netdev(pnetdev);
737}
738
739static int rtw_drv_init(struct usb_interface *pusb_intf,
740 const struct usb_device_id *pdid)
741{
742 struct rtw_adapter *if1 = NULL;
743 struct dvobj_priv *dvobj;
744 int status = _FAIL;
745
746 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_init\n"));
747
748 /* Initialize dvobj_priv */
749 dvobj = usb_dvobj_init(pusb_intf);
750 if (!dvobj) {
751 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
752 ("initialize device object priv Failed!\n"));
753 goto exit;
754 }
755
756 if1 = rtw_usb_if1_init(dvobj, pusb_intf, pdid);
757 if (!if1) {
758 DBG_8723A("rtw_init_primary_adapter Failed!\n");
759 goto free_dvobj;
760 }
761
762 /* dev_alloc_name && register_netdev */
763 status = rtw_drv_register_netdev(if1);
764 if (status != _SUCCESS)
765 goto free_if1;
766 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
767 ("-871x_drv - drv_init, success!\n"));
768
769 status = _SUCCESS;
770
771free_if1:
772 if (status != _SUCCESS && if1)
773 rtw_usb_if1_deinit(if1);
774free_dvobj:
775 if (status != _SUCCESS)
776 usb_dvobj_deinit(pusb_intf);
777exit:
778 return status == _SUCCESS ? 0 : -ENODEV;
779}
780
781/* dev_remove() - our device is being removed */
782static void rtw_disconnect(struct usb_interface *pusb_intf)
783{
784 struct dvobj_priv *dvobj;
785 struct rtw_adapter *padapter;
786 struct net_device *pnetdev;
787 struct mlme_priv *pmlmepriv;
788
789 dvobj = usb_get_intfdata(pusb_intf);
790 if (!dvobj)
791 return;
792
793 padapter = dvobj->if1;
794 pnetdev = padapter->pnetdev;
795 pmlmepriv = &padapter->mlmepriv;
796
797 usb_set_intfdata(pusb_intf, NULL);
798
799 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n"));
800
801 rtw_pm_set_ips23a(padapter, IPS_NONE);
802 rtw_pm_set_lps23a(padapter, PS_MODE_ACTIVE);
803
804 LeaveAllPowerSaveMode23a(padapter);
805
806 rtw_usb_if1_deinit(padapter);
807
808 usb_dvobj_deinit(pusb_intf);
809
810 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-dev_remove()\n"));
811 DBG_8723A("-r871xu_dev_remove, done\n");
812
813 return;
814}
815
816static int __init rtw_drv_entry(void)
817{
818 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_entry\n"));
819 return usb_register(usb_drv);
820}
821
822static void __exit rtw_drv_halt(void)
823{
824 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_halt\n"));
825 DBG_8723A("+rtw_drv_halt\n");
826
827 usb_deregister(usb_drv);
828
829 DBG_8723A("-rtw_drv_halt\n");
830}
831
832module_init(rtw_drv_entry);
833module_exit(rtw_drv_halt);
diff --git a/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c b/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c
new file mode 100644
index 000000000000..c49160e477d8
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c
@@ -0,0 +1,283 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _USB_OPS_LINUX_C_
16
17#include <drv_types.h>
18#include <usb_ops_linux.h>
19#include <rtw_sreset.h>
20
21unsigned int ffaddr2pipehdl23a(struct dvobj_priv *pdvobj, u32 addr)
22{
23 struct usb_device *pusbd = pdvobj->pusbdev;
24 unsigned int pipe = 0, ep_num = 0;
25
26 if (addr == RECV_BULK_IN_ADDR) {
27 pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]);
28 } else if (addr == RECV_INT_IN_ADDR) {
29 pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[1]);
30 } else if (addr < HW_QUEUE_ENTRY) {
31 ep_num = pdvobj->Queue2Pipe[addr];
32 pipe = usb_sndbulkpipe(pusbd, ep_num);
33 }
34 return pipe;
35}
36
37struct zero_bulkout_context {
38 void *pbuf;
39 void *purb;
40 void *pirp;
41 void *padapter;
42};
43
44void usb_read_mem23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
45{
46}
47
48void usb_write_mem23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
49{
50}
51
52void usb_read_port_cancel23a(struct intf_hdl *pintfhdl)
53{
54 struct recv_buf *precvbuf;
55 struct rtw_adapter *padapter = pintfhdl->padapter;
56 int i;
57
58 precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
59
60 DBG_8723A("%s\n", __func__);
61
62 padapter->bReadPortCancel = true;
63
64 for (i = 0; i < NR_RECVBUFF ; i++) {
65 if (precvbuf->purb)
66 usb_kill_urb(precvbuf->purb);
67 precvbuf++;
68 }
69 usb_kill_urb(padapter->recvpriv.int_in_urb);
70}
71
72static void usb_write_port23a_complete(struct urb *purb, struct pt_regs *regs)
73{
74 struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
75 struct rtw_adapter *padapter = pxmitbuf->padapter;
76 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
77 struct hal_data_8723a *phaldata;
78 unsigned long irqL;
79
80 switch (pxmitbuf->flags) {
81 case VO_QUEUE_INX:
82 pxmitpriv->voq_cnt--;
83 break;
84 case VI_QUEUE_INX:
85 pxmitpriv->viq_cnt--;
86 break;
87 case BE_QUEUE_INX:
88 pxmitpriv->beq_cnt--;
89 break;
90 case BK_QUEUE_INX:
91 pxmitpriv->bkq_cnt--;
92 break;
93 case HIGH_QUEUE_INX:
94#ifdef CONFIG_8723AU_AP_MODE
95 rtw_chk_hi_queue_cmd23a(padapter);
96#endif
97 break;
98 default:
99 break;
100 }
101
102 if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
103 padapter->bWritePortCancel) {
104 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
105 ("usb_write_port23a_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)",
106 padapter->bDriverStopped, padapter->bSurpriseRemoved));
107 DBG_8723A("%s(): TX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bWritePortCancel(%d) pxmitbuf->ext_tag(%x)\n",
108 __func__, padapter->bDriverStopped,
109 padapter->bSurpriseRemoved, padapter->bReadPortCancel,
110 pxmitbuf->ext_tag);
111
112 goto check_completion;
113 }
114
115 if (purb->status) {
116 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
117 ("usb_write_port23a_complete : purb->status(%d) != 0\n",
118 purb->status));
119 DBG_8723A("###=> urb_write_port_complete status(%d)\n",
120 purb->status);
121 if ((purb->status == -EPIPE) || (purb->status == -EPROTO)) {
122 sreset_set_wifi_error_status23a(padapter,
123 USB_WRITE_PORT_FAIL);
124 } else if (purb->status == -EINPROGRESS) {
125 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
126 ("usb_write_port23a_complete: EINPROGESS\n"));
127 goto check_completion;
128 } else if (purb->status == -ENOENT) {
129 DBG_8723A("%s: -ENOENT\n", __func__);
130 goto check_completion;
131 } else if (purb->status == -ECONNRESET) {
132 DBG_8723A("%s: -ECONNRESET\n", __func__);
133 goto check_completion;
134 } else if (purb->status == -ESHUTDOWN) {
135 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
136 ("usb_write_port23a_complete: ESHUTDOWN\n"));
137 padapter->bDriverStopped = true;
138 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
139 ("usb_write_port23a_complete:bDriverStopped = true\n"));
140 goto check_completion;
141 } else {
142 padapter->bSurpriseRemoved = true;
143 DBG_8723A("bSurpriseRemoved = true\n");
144 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
145 ("usb_write_port23a_complete:bSurpriseRemoved = true\n"));
146 goto check_completion;
147 }
148 }
149 phaldata = GET_HAL_DATA(padapter);
150 phaldata->srestpriv.last_tx_complete_time = jiffies;
151
152check_completion:
153 spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
154 rtw23a_sctx_done_err(&pxmitbuf->sctx,
155 purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR :
156 RTW_SCTX_DONE_SUCCESS);
157 spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
158
159 rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
160
161 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
162}
163
164u32 usb_write_port23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
165 struct xmit_buf *pxmitbuf)
166{
167 struct urb *purb = NULL;
168 struct rtw_adapter *padapter = (struct rtw_adapter *)pintfhdl->padapter;
169 struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
170 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
171 struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
172 struct usb_device *pusbd = pdvobj->pusbdev;
173 unsigned long irqL;
174 unsigned int pipe;
175 int status;
176 u32 ret = _FAIL;
177
178 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("+usb_write_port23a\n"));
179
180 if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||
181 (padapter->pwrctrlpriv.pnp_bstop_trx)) {
182 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
183 ("usb_write_port23a:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
184 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
185 goto exit;
186 }
187
188 spin_lock_irqsave(&pxmitpriv->lock, irqL);
189
190 switch (addr) {
191 case VO_QUEUE_INX:
192 pxmitpriv->voq_cnt++;
193 pxmitbuf->flags = VO_QUEUE_INX;
194 break;
195 case VI_QUEUE_INX:
196 pxmitpriv->viq_cnt++;
197 pxmitbuf->flags = VI_QUEUE_INX;
198 break;
199 case BE_QUEUE_INX:
200 pxmitpriv->beq_cnt++;
201 pxmitbuf->flags = BE_QUEUE_INX;
202 break;
203 case BK_QUEUE_INX:
204 pxmitpriv->bkq_cnt++;
205 pxmitbuf->flags = BK_QUEUE_INX;
206 break;
207 case HIGH_QUEUE_INX:
208 pxmitbuf->flags = HIGH_QUEUE_INX;
209 break;
210 default:
211 pxmitbuf->flags = MGT_QUEUE_INX;
212 break;
213 }
214
215 spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
216
217 purb = pxmitbuf->pxmit_urb[0];
218
219 /* translate DMA FIFO addr to pipehandle */
220 pipe = ffaddr2pipehdl23a(pdvobj, addr);
221
222 usb_fill_bulk_urb(purb, pusbd, pipe,
223 pxmitframe->buf_addr, /* pxmitbuf->pbuf */
224 cnt, usb_write_port23a_complete,
225 pxmitbuf);/* context is pxmitbuf */
226
227 status = usb_submit_urb(purb, GFP_ATOMIC);
228 if (!status) {
229 struct hal_data_8723a *phaldata = GET_HAL_DATA(padapter);
230 phaldata->srestpriv.last_tx_time = jiffies;
231 } else {
232 rtw23a_sctx_done_err(&pxmitbuf->sctx,
233 RTW_SCTX_DONE_WRITE_PORT_ERR);
234 DBG_8723A("usb_write_port23a, status =%d\n", status);
235 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
236 ("usb_write_port23a(): usb_submit_urb, status =%x\n",
237 status));
238
239 switch (status) {
240 case -ENODEV:
241 padapter->bDriverStopped = true;
242 break;
243 default:
244 break;
245 }
246 goto exit;
247 }
248 ret = _SUCCESS;
249 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("-usb_write_port23a\n"));
250
251exit:
252 if (ret != _SUCCESS)
253 rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
254
255 return ret;
256}
257
258void usb_write_port23a_cancel(struct intf_hdl *pintfhdl)
259{
260 struct rtw_adapter *padapter = pintfhdl->padapter;
261 struct xmit_buf *pxmitbuf;
262 struct list_head *plist;
263 int j;
264
265 DBG_8723A("%s\n", __func__);
266
267 padapter->bWritePortCancel = true;
268
269 list_for_each(plist, &padapter->xmitpriv.xmitbuf_list) {
270 pxmitbuf = container_of(plist, struct xmit_buf, list2);
271 for (j = 0; j < 8; j++) {
272 if (pxmitbuf->pxmit_urb[j])
273 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
274 }
275 }
276 list_for_each(plist, &padapter->xmitpriv.xmitextbuf_list) {
277 pxmitbuf = container_of(plist, struct xmit_buf, list2);
278 for (j = 0; j < 8; j++) {
279 if (pxmitbuf->pxmit_urb[j])
280 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
281 }
282 }
283}
diff --git a/drivers/staging/rtl8723au/os_dep/xmit_linux.c b/drivers/staging/rtl8723au/os_dep/xmit_linux.c
new file mode 100644
index 000000000000..e1c6fc746233
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/xmit_linux.c
@@ -0,0 +1,195 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 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 ******************************************************************************/
15#define _XMIT_OSDEP_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19
20#include <linux/if_ether.h>
21#include <linux/ip.h>
22#include <wifi.h>
23#include <mlme_osdep.h>
24#include <xmit_osdep.h>
25#include <osdep_intf.h>
26
27uint rtw_remainder_len23a(struct pkt_file *pfile)
28{
29 return pfile->buf_len - ((unsigned long)(pfile->cur_addr) -
30 (unsigned long)(pfile->buf_start));
31}
32
33void _rtw_open_pktfile23a(struct sk_buff *pktptr, struct pkt_file *pfile)
34{
35 pfile->pkt = pktptr;
36 pfile->buf_start = pktptr->data;
37 pfile->cur_addr = pktptr->data;
38 pfile->buf_len = pktptr->len;
39 pfile->pkt_len = pktptr->len;
40
41 pfile->cur_buffer = pfile->buf_start;
42}
43
44uint _rtw_pktfile_read23a(struct pkt_file *pfile, u8 *rmem, uint rlen)
45{
46 uint len = 0;
47
48 len = rtw_remainder_len23a(pfile);
49 len = (rlen > len) ? len : rlen;
50
51 if (rmem)
52 skb_copy_bits(pfile->pkt, pfile->buf_len-pfile->pkt_len,
53 rmem, len);
54
55 pfile->cur_addr += len;
56 pfile->pkt_len -= len;
57
58 return len;
59}
60
61int rtw_endofpktfile23a(struct pkt_file *pfile)
62{
63 if (pfile->pkt_len == 0)
64 return true;
65 return false;
66}
67
68int rtw_os_xmit_resource_alloc23a(struct rtw_adapter *padapter,
69 struct xmit_buf *pxmitbuf, u32 alloc_sz)
70{
71 int i;
72
73 pxmitbuf->pallocated_buf = kzalloc(alloc_sz, GFP_KERNEL);
74 if (pxmitbuf->pallocated_buf == NULL)
75 return _FAIL;
76
77 pxmitbuf->pbuf = PTR_ALIGN(pxmitbuf->pallocated_buf, XMITBUF_ALIGN_SZ);
78
79 for (i = 0; i < 8; i++) {
80 pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
81 if (pxmitbuf->pxmit_urb[i] == NULL) {
82 DBG_8723A("pxmitbuf->pxmit_urb[i]==NULL");
83 return _FAIL;
84 }
85 }
86 return _SUCCESS;
87}
88
89void rtw_os_xmit_resource_free23a(struct rtw_adapter *padapter,
90 struct xmit_buf *pxmitbuf)
91{
92 int i;
93
94 for (i = 0; i < 8; i++)
95 usb_free_urb(pxmitbuf->pxmit_urb[i]);
96 kfree(pxmitbuf->pallocated_buf);
97}
98
99#define WMM_XMIT_THRESHOLD (NR_XMITFRAME*2/5)
100
101void rtw_os_pkt_complete23a(struct rtw_adapter *padapter, struct sk_buff *pkt)
102{
103 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
104 u16 queue;
105
106 queue = skb_get_queue_mapping(pkt);
107 if (padapter->registrypriv.wifi_spec) {
108 if (__netif_subqueue_stopped(padapter->pnetdev, queue) &&
109 (pxmitpriv->hwxmits[queue].accnt < WMM_XMIT_THRESHOLD))
110 netif_wake_subqueue(padapter->pnetdev, queue);
111 } else {
112 if (__netif_subqueue_stopped(padapter->pnetdev, queue))
113 netif_wake_subqueue(padapter->pnetdev, queue);
114 }
115 dev_kfree_skb_any(pkt);
116}
117
118void rtw_os_xmit_complete23a(struct rtw_adapter *padapter,
119 struct xmit_frame *pxframe)
120{
121 if (pxframe->pkt)
122 rtw_os_pkt_complete23a(padapter, pxframe->pkt);
123
124 pxframe->pkt = NULL;
125}
126
127void rtw_os_xmit_schedule23a(struct rtw_adapter *padapter)
128{
129 struct xmit_priv *pxmitpriv;
130
131 if (!padapter)
132 return;
133 pxmitpriv = &padapter->xmitpriv;
134
135 spin_lock_bh(&pxmitpriv->lock);
136
137 if (rtw_txframes_pending23a(padapter))
138 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
139 spin_unlock_bh(&pxmitpriv->lock);
140}
141
142static void rtw_check_xmit_resource(struct rtw_adapter *padapter,
143 struct sk_buff *pkt)
144{
145 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
146 u16 queue;
147
148 queue = skb_get_queue_mapping(pkt);
149 if (padapter->registrypriv.wifi_spec) {
150 /* No free space for Tx, tx_worker is too slow */
151 if (pxmitpriv->hwxmits[queue].accnt > WMM_XMIT_THRESHOLD)
152 netif_stop_subqueue(padapter->pnetdev, queue);
153 } else {
154 if (pxmitpriv->free_xmitframe_cnt <= 4) {
155 if (!netif_tx_queue_stopped(netdev_get_tx_queue(padapter->pnetdev, queue)))
156 netif_stop_subqueue(padapter->pnetdev, queue);
157 }
158 }
159}
160
161int rtw_xmit23a_entry23a(struct sk_buff *skb, struct net_device *pnetdev)
162{
163 struct rtw_adapter *padapter = netdev_priv(pnetdev);
164 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
165 int res = 0;
166
167 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("+xmit_enry\n"));
168
169 if (!rtw_if_up23a(padapter)) {
170 RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
171 ("rtw_xmit23a_entry23a: rtw_if_up23a fail\n"));
172 goto drop_packet;
173 }
174
175 rtw_check_xmit_resource(padapter, skb);
176
177 res = rtw_xmit23a(padapter, skb);
178 if (res < 0)
179 goto drop_packet;
180
181 pxmitpriv->tx_pkts++;
182 RT_TRACE(_module_xmit_osdep_c_, _drv_info_,
183 ("rtw_xmit23a_entry23a: tx_pkts=%d\n",
184 (u32)pxmitpriv->tx_pkts));
185 goto exit;
186
187drop_packet:
188 pxmitpriv->tx_drop++;
189 dev_kfree_skb_any(skb);
190 RT_TRACE(_module_xmit_osdep_c_, _drv_notice_,
191 ("rtw_xmit23a_entry23a: drop, tx_drop=%d\n",
192 (u32)pxmitpriv->tx_drop));
193exit:
194 return 0;
195}
diff --git a/drivers/staging/unisys/Kconfig b/drivers/staging/unisys/Kconfig
index ac080c9dcf46..6bae2afbaa15 100644
--- a/drivers/staging/unisys/Kconfig
+++ b/drivers/staging/unisys/Kconfig
@@ -3,7 +3,7 @@
3# 3#
4menuconfig UNISYSSPAR 4menuconfig UNISYSSPAR
5 bool "Unisys SPAR driver support" 5 bool "Unisys SPAR driver support"
6 depends on X86_64 6 depends on X86_64 && BROKEN
7 ---help--- 7 ---help---
8 Support for the Unisys SPAR drivers 8 Support for the Unisys SPAR drivers
9 9
diff --git a/drivers/staging/unisys/visorchipset/filexfer.c b/drivers/staging/unisys/visorchipset/filexfer.c
index 431cff844a43..f950d6e85b5f 100644
--- a/drivers/staging/unisys/visorchipset/filexfer.c
+++ b/drivers/staging/unisys/visorchipset/filexfer.c
@@ -83,7 +83,7 @@ struct any_request {
83 * coarsest possible alignment boundary that could be required 83 * coarsest possible alignment boundary that could be required
84 * for any user data structure. 84 * for any user data structure.
85 */ 85 */
86 u8 caller_context_data[1] __aligned(sizeof(ulong2); 86 u8 caller_context_data[1] __aligned(sizeof(ulong2));
87}; 87};
88 88
89/* 89/*
diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c
index 8252ca14695d..257c6e59b460 100644
--- a/drivers/staging/unisys/visorchipset/visorchipset_main.c
+++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c
@@ -2414,6 +2414,9 @@ proc_read_installer(struct file *file, char __user *buf,
2414 char *vbuf; 2414 char *vbuf;
2415 loff_t pos = *offset; 2415 loff_t pos = *offset;
2416 2416
2417 if (!ControlVm_channel)
2418 return -ENODEV;
2419
2417 if (pos < 0) 2420 if (pos < 0)
2418 return -EINVAL; 2421 return -EINVAL;
2419 2422
@@ -2463,6 +2466,9 @@ proc_write_installer(struct file *file,
2463 U16 remainingSteps; 2466 U16 remainingSteps;
2464 U32 error, textId; 2467 U32 error, textId;
2465 2468
2469 if (!ControlVm_channel)
2470 return -ENODEV;
2471
2466 /* Check to make sure there is no buffer overflow */ 2472 /* Check to make sure there is no buffer overflow */
2467 if (count > (sizeof(buf) - 1)) 2473 if (count > (sizeof(buf) - 1))
2468 return -EINVAL; 2474 return -EINVAL;
@@ -2524,6 +2530,9 @@ proc_read_toolaction(struct file *file, char __user *buf,
2524 char *vbuf; 2530 char *vbuf;
2525 loff_t pos = *offset; 2531 loff_t pos = *offset;
2526 2532
2533 if (!ControlVm_channel)
2534 return -ENODEV;
2535
2527 if (pos < 0) 2536 if (pos < 0)
2528 return -EINVAL; 2537 return -EINVAL;
2529 2538
@@ -2562,6 +2571,9 @@ proc_write_toolaction(struct file *file,
2562 char buf[3]; 2571 char buf[3];
2563 U8 toolAction; 2572 U8 toolAction;
2564 2573
2574 if (!ControlVm_channel)
2575 return -ENODEV;
2576
2565 /* Check to make sure there is no buffer overflow */ 2577 /* Check to make sure there is no buffer overflow */
2566 if (count > (sizeof(buf) - 1)) 2578 if (count > (sizeof(buf) - 1))
2567 return -EINVAL; 2579 return -EINVAL;
@@ -2601,6 +2613,9 @@ proc_read_bootToTool(struct file *file, char __user *buf,
2601 char *vbuf; 2613 char *vbuf;
2602 loff_t pos = *offset; 2614 loff_t pos = *offset;
2603 2615
2616 if (!ControlVm_channel)
2617 return -ENODEV;
2618
2604 if (pos < 0) 2619 if (pos < 0)
2605 return -EINVAL; 2620 return -EINVAL;
2606 2621
@@ -2639,6 +2654,9 @@ proc_write_bootToTool(struct file *file,
2639 int inputVal; 2654 int inputVal;
2640 ULTRA_EFI_SPAR_INDICATION efiSparIndication; 2655 ULTRA_EFI_SPAR_INDICATION efiSparIndication;
2641 2656
2657 if (!ControlVm_channel)
2658 return -ENODEV;
2659
2642 /* Check to make sure there is no buffer overflow */ 2660 /* Check to make sure there is no buffer overflow */
2643 if (count > (sizeof(buf) - 1)) 2661 if (count > (sizeof(buf) - 1))
2644 return -EINVAL; 2662 return -EINVAL;